commit 8f5315e9367698cb857dd601433aff8e17a9dd91 Author: liqi Date: Thu Sep 19 11:32:39 2024 +0800 初始化仓库 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..954d0e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,55 @@ +# yii console command +#/yii +/admin/runtime/ +/member/runtime/ +/service/runtime/ +/console/runtime/ +/platform/runtime/ + +# phpstorm project files +/.idea +/.vscode +# netbeans project files +nbproject + +# zend studio for eclipse project files +.buildpath +.project +.settings + +# windows thumbnail cache +Thumbs.db + +# composer vendor dir + + +# composer itself is not needed +composer.phar + +# Mac DS_Store Files +.DS_Store + +# phpunit itself is not needed +phpunit.phar +# local phpunit config +/phpunit.xml + +composer.lock +.env +.env.dev +.env.example +.htaccess +nginx.htaccess + +web/.htaccess +web/nginx.htaccess +web/admin +web/service/uploads + +common/config/codeception-local.php +common/config/main-local.php +common/config/params-local.php + +yii_test +yii_test.bat +/vendor/ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..ee872b9 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,29 @@ +Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Yii Software LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +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..46d8021 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +### 3 分钟了解如何进入开发 + +欢迎使用云效 Codeup,通过阅读以下内容,你可以快速熟悉 Codeup ,并立即开始今天的工作。 + +### 提交**文件** + +首先,你需要了解在 Codeup 中如何提交代码文件,跟着文档「[__提交第一行代码__](https://help.aliyun.com/document_detail/153708.html)」一起操作试试看吧。 + +### 开启代码检测 + +开发过程中,为了更好的管理你的代码资产,Codeup 内置了「[__代码检测服务__](https://help.aliyun.com/document_detail/434321.html),可设置提交或合并请求的变更自动触发扫描,并及时提供结果反馈。 +![](https://img.alicdn.com/tfs/TB1nRDatoz1gK0jSZLeXXb9kVXa-1122-380.png "") +![](https://img.alicdn.com/tfs/TB1PrPatXY7gK0jSZKzXXaikpXa-1122-709.png "") +### 发起代码评审 + +功能开发完毕后,通常你需要发起「[__代码合并和评审__](https://help.aliyun.com/document_detail/153872.html)」,Codeup 支持多人协作的代码评审服务,你可以通过「[__保护分支__](https://help.aliyun.com/document_detail/153873.html)」策略及「[__合并请求设置__](https://help.aliyun.com/document_detail/153874.html)」对合并过程进行流程化管控,同时提供 WebIDE 在线代码评审及冲突解决能力,让你的评审过程更加流畅。 + +![](https://img.alicdn.com/tfs/TB1XHrctkP2gK0jSZPxXXacQpXa-1432-887.png "") + +![](https://img.alicdn.com/tfs/TB1V3fctoY1gK0jSZFMXXaWcVXa-1432-600.png "") + +### 查看代码贡献 +代码库提供了图形化报表帮助企业查看团队的代码提交和代码行贡献情况,此外还支持查看提交评审率、千行代码评论数等指标以衡量成员的代码评审活动参与度。 + +### 成员协作 + +是时候邀请成员一起编写卓越的代码工程了,请点击右上角「成员」邀请你的小伙伴开始协作吧! + +### 更多 + +Git 使用教学、高级功能指引等更多说明,参见[__Codeup帮助文档__](https://help.aliyun.com/document_detail/153784.html)。 \ No newline at end of file diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..e702309 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,88 @@ +require 'yaml' +require 'fileutils' + +required_plugins_installed = nil +required_plugins = %w( vagrant-hostmanager vagrant-vbguest ) +required_plugins.each do |plugin| + unless Vagrant.has_plugin? plugin + system "vagrant plugin install #{plugin}" + required_plugins_installed = true + end +end + +# IF plugin[s] was just installed - restart required +if required_plugins_installed + # Get CLI command[s] and call again + system 'vagrant' + ARGV.to_s.gsub(/\[\"|\", \"|\"\]/, ' ') + exit +end + +domains = { + app: 'y2aa-app.test', + admin: 'y2aa-admin.test' +} + +config = { + local: './vagrant/config/vagrant-local.yml', + example: './vagrant/config/vagrant-local.example.yml' +} + +# copy config from example if local config not exists +FileUtils.cp config[:example], config[:local] unless File.exist?(config[:local]) +# read config +options = YAML.load_file config[:local] + +# check github token +if options['github_token'].nil? || options['github_token'].to_s.length != 40 + puts "You must place REAL GitHub token into configuration:\n/yii2-app-advanced/vagrant/config/vagrant-local.yml" + exit +end + +# vagrant configurate +Vagrant.configure(2) do |config| + # select the box + config.vm.box = 'bento/ubuntu-18.04' + + # should we ask about box updates? + config.vm.box_check_update = options['box_check_update'] + + config.vm.provider 'virtualbox' do |vb| + # machine cpus count + vb.cpus = options['cpus'] + # machine memory size + vb.memory = options['memory'] + # machine name (for VirtualBox UI) + vb.name = options['machine_name'] + end + + # machine name (for vagrant console) + config.vm.define options['machine_name'] + + # machine name (for guest machine console) + config.vm.hostname = options['machine_name'] + + # network settings + config.vm.network 'private_network', ip: options['ip'] + + # sync: folder 'yii2-app-advanced' (host machine) -> folder '/app' (guest machine) + config.vm.synced_folder './', '/app', owner: 'vagrant', group: 'vagrant' + + # disable folder '/vagrant' (guest machine) + config.vm.synced_folder '.', '/vagrant', disabled: true + + # hosts settings (host machine) + config.vm.provision :hostmanager + config.hostmanager.enabled = true + config.hostmanager.manage_host = true + config.hostmanager.ignore_private_ip = false + config.hostmanager.include_offline = true + config.hostmanager.aliases = domains.values + + # provisioners + config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone'], options['ip']] + config.vm.provision 'shell', path: './vagrant/provision/once-as-vagrant.sh', args: [options['github_token']], privileged: false + config.vm.provision 'shell', path: './vagrant/provision/always-as-root.sh', run: 'always' + + # post-install message (vagrant console) + config.vm.post_up_message = "Frontend URL: http://#{domains[:frontend]}\nBackend URL: http://#{domains[:backend]}" +end diff --git a/admin/Dockerfile b/admin/Dockerfile new file mode 100644 index 0000000..2aa3842 --- /dev/null +++ b/admin/Dockerfile @@ -0,0 +1,4 @@ +FROM yiisoftware/yii2-php:8.1-apache + +# Change document root for Apache +RUN sed -i -e 's|/app/web|/app/admin/web|g' /etc/apache2/sites-available/000-default.conf diff --git a/admin/behaviors/PageFilterBehavior.php b/admin/behaviors/PageFilterBehavior.php new file mode 100644 index 0000000..135d637 --- /dev/null +++ b/admin/behaviors/PageFilterBehavior.php @@ -0,0 +1,69 @@ + 'filter', + ]; + } + + /** + * @param ActionEvent $event + * @return mixed + */ + public function filter($event){ + $event->isValid = true; // 继续执行action + //echo 'Access Denied'; + $rule = $event->action->getUniqueId(); + + if($result = $this->allowdCheck($rule)){ + return $result; + }; + if(!Yii::$app->request->isAjax + && Yii::$app->request->getHeaders()->get('Accept')!=='application/json' + && !Yii::$app->request->getHeaders()->has('x-dux-sfc') + ){ + + $event->isValid = false; // 终止执行action + Yii::$app->response->format = Response::FORMAT_HTML; + Yii::$app->response->content = $event->action->controller->renderContent(''); + Yii::$app->end(); + return false; + } + + + return true; + } + + public function allowdCheck($rule){ + foreach ($this->allowActions as $allow) { + //dump($rule); dump(rtrim($allow,'*')); echo '
'; + if (substr($allow, -1) == '*') { + if (strpos($rule, rtrim($allow,'*')) === 0) { + return true; + } + } else { + if ($rule == $allow) { + return true; + } + } + } + } + +} diff --git a/admin/behaviors/RbacBehavior.php b/admin/behaviors/RbacBehavior.php new file mode 100644 index 0000000..bf5d0aa --- /dev/null +++ b/admin/behaviors/RbacBehavior.php @@ -0,0 +1,113 @@ + [ + * 'class' => 'backend\behaviors\RbacBehavior', + * 'allowActions' => ['site/login', 'site/error'] + * ] + * ~~~ + * + */ +class RbacBehavior extends \yii\base\Behavior +{ + + /** + * @var array 无需权限检查的action + */ + public $allowActions = []; + + /** + * --------------------------------------- + * 功能说明 + * @return array + * --------------------------------------- + */ + public function events() + { + return [ + Controller::EVENT_BEFORE_ACTION => 'rbacAction', + ]; + } + + /** + * --------------------------------------- + * 控制器执行前的rbac处理 + * @param $event \yii\base\ActionEvent 为什么是ActionEvent而不是Event, + * 因为yii/base/Controller第269行,事件参数是$event = new ActionEvent($action) + * + * 注意:ActionEvent::$isValid参数true/false分别表示继续执行或终止执行action, + * 所以验证成功后要$event->isValid = true,参考代码yii/base/Controller第152、270行 + * @return boolean + * --------------------------------------- + */ + public function rbacAction($event){ + $event->isValid = true; // 继续执行action + $action = $event->action; + $rule = $action->getUniqueId(); + + if($result = $this->commonCheck($rule)){ + return $result; + }; + //echo 'Access Denied'; + $event->isValid = false; // 终止执行action + $this->denyAccess(); + } + + /** + * Denies the access of the user. HTTP 403 您没有执行此操作的权限 + * The default implementation will redirect the user to the login page if he is a guest; + * if the user is already logged, a 403 HTTP exception will be thrown. + * @throws ForbiddenHttpException if the user is already logged in. + */ + protected function denyAccess() + { + if (\Yii::$app->user->getIsGuest()) { + \Yii::$app->user->loginRequired(); + } else { + Yii::$app->user->logout(); + throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.')); + } + } + + public function commonCheck($rule) + { + foreach ($this->allowActions as $allow) { + //dump($rule); dump(rtrim($allow,'*')); echo '
'; + if (substr($allow, -1) == '*') { + if (strpos($rule, rtrim($allow,'*')) === 0) { + return true; + } + } else { + if ($rule == $allow) { + return true; + } + } + } + if($rule == 'index/index'){ + if(!\Yii::$app->user->getIsGuest()){ + return true; + } + }else{ + /* 权限检查 */ + if ( Menu::checkRule($rule) ){ + return true; + } + } + return false; + } + + +} diff --git a/admin/codeception.yml b/admin/codeception.yml new file mode 100644 index 0000000..ec406fb --- /dev/null +++ b/admin/codeception.yml @@ -0,0 +1,15 @@ +namespace: admin\tests +actor_suffix: Tester +paths: + tests: tests + output: tests/_output + data: tests/_data + support: tests/_support +bootstrap: _bootstrap.php +settings: + colors: true + memory_limit: 1024M +modules: + config: + Yii2: + configFile: 'config/codeception-local.php' diff --git a/admin/components/BaseAdminController.php b/admin/components/BaseAdminController.php new file mode 100644 index 0000000..5e0bad6 --- /dev/null +++ b/admin/components/BaseAdminController.php @@ -0,0 +1,380 @@ + 2020/5/21 + * --------------------------------------- + */ + public function init() + { + parent::init(); + // 多语言,需要在http header中设置 app-language:zh-CN + //Yii::$app->language = Yii::$app->request->getHeaders()->get('app-language'); //'en-US'; + Yii::$app->params['web'] = Config::lists(); + } + + + /** + * --------------------------------------- + * 行为 + * + * @return array + * + * @author hlf 2020/5/21 + * --------------------------------------- + */ + final public function behaviors() + { + $behaviors = parent::behaviors(); + $newBehaviors = []; + $newBehaviors['corsFilter'] = [ + 'class' => Cors::class, + ]; +// $newBehaviors['pageFilter'] = [ +// 'class' => PageFilterBehavior::class,//如果不是接口请求直接返回布局页面 +// 'allowActions'=>[ +// 'debug/*','gii/*' +// ] +// ]; + foreach ($behaviors as $k => $v) { + $newBehaviors[$k] = $v; + } + //unset($behaviors['authenticator']); //删掉,保持先cors,后authenticator + // 设置认证方式,接口才认证 + $newBehaviors['authenticator'] = [ + 'class' => HttpBearerAuth::class, + 'optional' => $this->optional, + ]; + + return $newBehaviors; + } + + public function beforeAction($action) + { + $ret = parent::beforeAction($action); // TODO: Change the autogenerated stub + //不同角色权限 + if (!Yii::$app->user->isGuest) { + /** @var Admin $admin */ + $admin = Yii::$app->user->identity; + $this->mallId = $this->supplierId = 0; + switch ($admin->role) { + //角色1为官方管理,2为市场专员,3为客服,4为供应商管理,5为业务员,6为门店管理 + case 1: + //官方管理 + $this->mallId = FakeId::decodeId($this->get("mallId", 0)); + $this->supplierId = FakeId::decodeId($this->get("supplierId", 0)); + break; + case 2: + case 3: + //@todo 根据绑定关系 + $this->mallId = 0; + $this->supplierId = 0; + break; + case 4: + $this->mallId = 0; + $this->supplierId = $admin->supplier_id; + break; + case 5: + $this->mallId = 0; + $this->supplierId = $admin->supplier_id; + break; + case 6: + $this->supplierId = 0; + $this->mallId = $admin->mall_id; + break; + } + Yii::$app->mallId = $this->mallId; + Yii::$app->supplierId = $this->supplierId; + + } + return $ret; + } + + + public function create($query, $post) + { + $pagination = []; + $defaultPageSize = 10; + if (isset($post['page'])) { + $pagination['page'] = (int)$post['page']; + } + if (isset($post['limit'])) { + $defaultPageSize = (int)$post['limit']; + } + return new ActiveDataProvider([ + 'query' => $query, + 'pagination' => [ + 'defaultPageSize' => $defaultPageSize, + 'params' => $pagination + ] + ]); + } + + /** + * 当前登陆用户ID + * @return int|string + */ + public function getCurrentUserId() + { + return Yii::$app->user->identity->getId(); + } + + /** + * 取post参数 + * @param $name + * @param $defaultValue + * @return array|mixed + */ + public function post($name = null, $defaultValue = null) + { + return Yii::$app->request->post($name, $defaultValue); + } + + /** + * 取get参数 + * @param $name + * @param $defaultValue + * @return array|mixed + */ + public function get($name = null, $defaultValue = null) + { + return Yii::$app->request->get($name, $defaultValue); + } + + /** + * 参数验证 + * @param $data + * @param $rules + * @return DynamicModel|\stdClass + * @throws + */ + public function requestValidate($data, $rules) + { + foreach ($rules as $rule) { + if (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type + foreach ((array)$rule[0] as $r) { + if (!isset($data[$r])) { + $data[$r] = null; + } + } + } + } + $validate = DynamicModel::validateData($data, $rules); + if ($validate->hasErrors()) { + throw new InvalidArgumentException(current($validate->getFirstErrors())); + } + return $validate; + } + + public function serializeData($data) + { + if (Yii::$app->response->format == Response::FORMAT_RAW) { + return $data; + } + if ($data instanceof Model && $data->hasErrors()) { + throw new InvalidArgumentException('参数错误。' . implode('', $data->getFirstErrors())); +// $data = $this->serializeModelErrors($data); + } elseif ($data instanceof Arrayable) { + $data = $this->serializeModel($data); + } elseif ($data instanceof DataProviderInterface) { + $data = $this->serializeDataProvider($data); + } elseif ($data === null) { + $data = []; + } + return array_merge($this->extend_result, $data); + } + + protected function serializeDataProvider($dataProvider) + { + if (!empty($this->field)) { + $models = ArrayHelper::toArray($dataProvider->getModels(), $this->field); + } else { + $models = array_values($dataProvider->getModels()); + $models = $this->serializeModels($models); + } + $pagination = $dataProvider->getPagination(); + $result = [ + $this->listkey => $models, + ]; + if ($pagination !== false) { + return array_merge($result, $this->serializePagination($pagination)); + } + + return $result; + } + + /** + * Serializes a model object. + * @param Arrayable $model + * @return array the array representation of the model + */ + protected function serializeModel($model) + { + return $model->toArray(); + } + + protected function serializeModels(array $models) + { + foreach ($models as $i => $model) { + if ($model instanceof Arrayable) { + $models[$i] = $model->toArray(); + } elseif (is_array($model)) { + $models[$i] = ArrayHelper::toArray($model); + } + } + + return $models; + } + + protected function serializePagination($pagination) + { + return [ + //$this->pagekey => [ + 'total' => $pagination->totalCount, + 'totalPage' => $pagination->getPageCount(), + 'pageSize' => $pagination->getPageSize(), + //], + ]; + } + + final public function afterAction($action, $result) + { + $result = parent::afterAction($action, $result); + return $this->serializeData($result); + } + + public function createUrl($params) + { + return Yii::$app->urlManager->createUrl($params); + } + + + /** + * 前端事件 + * @param array $model + * @param $type + * @param $name + * @return false|void + */ + public function callbackEvent($models, $key, $type) + { + + $event = new Event(get_called_class()); + if (!empty($models)) { + foreach ($models as $model) { + $event->add($type, $model[$key], $model); + } + } else { + //没有的话默认刷新事件 + $event->add($type, $key, []); + } + $this->extend_result['__event'] = $event->render()['__event']; + } + + + public function render($view, $params = []) + { + Yii::$app->response->format = Response::FORMAT_RAW; + $this->layout = false;//去掉布局 + return parent::render($view, $params); // TODO: Change the autogenerated stub + } + + public function getErrorMsg($model = null) + { + if (!$model) { + $model = $this; + } + $msg = isset($model->errors) ? current($model->errors)[0] : '数据异常!'; + return $msg; + + } + + public function actionCheckAuth() + { + $user_id = Yii::$app->user->identity; + + $path = 'Admin/' . Yii::$app->requestedRoute; + $path = explode('/', $path); + foreach ($path as $value) { + $v = ucfirst($value); + $arr[] = $v; + } + $new_path = implode('/', $arr); + + $AuthRule = AuthRule::find()->where(['path' => $new_path])->one(); + if (!$AuthRule) throw new Exception('权限不存在!!!'); + + if ($AuthRule->status == 0) { + throw new Exception('该权限已被禁用'); + } + + $AuthRole = AuthRole::find()->where(['rule_id' => $AuthRule->id, 'role_id' => $user_id->role])->one(); + if (!$AuthRole) { + throw new Exception('您没有:' . $AuthRule->title . '的权限'); + } + if ($AuthRole->status == 0) { + throw new Exception('您的'.$AuthRule->title.'权限已被禁用'); + } + return $AuthRule; + } +} diff --git a/admin/components/HigherOrderTapProxy.php b/admin/components/HigherOrderTapProxy.php new file mode 100644 index 0000000..88eb303 --- /dev/null +++ b/admin/components/HigherOrderTapProxy.php @@ -0,0 +1,37 @@ +target = $target; + } + + /** + * Dynamically pass method calls to the target. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + $this->target->{$method}(...$parameters); + + return $this->target; + } +} diff --git a/admin/components/ModelAgent.php b/admin/components/ModelAgent.php new file mode 100644 index 0000000..8aa391a --- /dev/null +++ b/admin/components/ModelAgent.php @@ -0,0 +1,20 @@ +model = $model; + } + + public function __call($method, $arguments) + { + $this->model = $this->model->$method(...$arguments); + return $this; + } +} diff --git a/admin/components/Tree.php b/admin/components/Tree.php new file mode 100644 index 0000000..bca91b4 --- /dev/null +++ b/admin/components/Tree.php @@ -0,0 +1,121 @@ + $value){ + if(isset($child[$value['id']])){ + $children = $child[$value['id']]; + }else{ + $children = []; + } + $parent[$key]['children'] = $children; + } + return $parent; + } + + /** + * 数组转树形 + * @param array $list + * @param string $id + * @param string $pid + * @param string $son + * @return array + */ + public static function arr2tree(array $list, string $id = 'id', string $pid = 'pid', string $son = 'sub'): array + { + [$tree, $map] = [[], []]; + foreach ($list as $item) { + $map[$item[$id]] = $item; + } + + foreach ($list as $item) { + if (isset($item[$pid], $map[$item[$pid]])) { + $map[$item[$pid]][$son][] = &$map[$item[$id]]; + } else { + $tree[] = &$map[$item[$id]]; + } + } + unset($map); + return $tree; + } + + /** + * 数组转表格树 + * @param array $list 数据列表 + * @param string $id ID Key + * @param string $pid 父ID Key + * @param string $name 名称 Key + * @param string $path + * @param string $ppath + * @return array + */ + public static function arr2table(array $list, string $id = 'id', string $pid = 'pid', string $name = '', string $path = 'path', string $ppath = ''): array + { + $tree = []; + foreach (self::arr2tree($list, $id, $pid) as $attr) { + $attr[$path] = "{$ppath}-{$attr[$id]}"; + $attr['sub'] = $attr['sub'] ?? []; + $attr['spt'] = substr_count($ppath, '-'); + $attr['spl'] = str_repeat(" ├ ", $attr['spt']); + $attr['spl_' . $name] = $attr['spl'] . $attr[$name]; + $sub = $attr['sub']; + unset($attr['sub']); + $tree[] = $attr; + if (!empty($sub)) { + $tree = array_merge($tree, self::arr2table($sub, $id, $pid, $name, $path, $attr[$path])); + } + } + return $tree; + } + + /** + * 数组转路径 + * @param array $data + * @param int $parentId + * @param string $id + * @param string $pid + * @param array $categories + * @return array + */ + public static function arr2path(array $data, int $parentId, string $id = 'id', string $pid = 'pid', array &$categories = []): array + { + if ($data && is_array($data)) { + foreach ($data as $item) { + if ($item[$id] == $parentId) { + $categories[] = $item; + self::arr2path($data, $item[$pid], $id, $pid, $categories); + } + } + } + return $categories; + } + + /** + * 获取子id + * @param $data + * @param string $id + * @return array + */ + public static function allIds($data, string $id = 'id'): array + { + $arr = []; + array_walk_recursive($data, static function ($v, $k) use (&$arr, $id) { + if ($k == $id) + $arr[] = $v; + }); + return $arr; + } +} diff --git a/admin/components/UI/Components/ApexData.php b/admin/components/UI/Components/ApexData.php new file mode 100644 index 0000000..a9bd0bd --- /dev/null +++ b/admin/components/UI/Components/ApexData.php @@ -0,0 +1,83 @@ +type = $type; + $this->config = $config; + } + + /** + * @param $startdate + * @param $enddate + * @return array + */ + private function getDateFromRange($startdate, $enddate): array + { + $stimestamp = strtotime($startdate); + $etimestamp = strtotime($enddate); + // 计算日期段内有多少天 + $days = ($etimestamp - $stimestamp) / 86400 + 1; + // 保存每天日期 + $date = array(); + for ($i = 0; $i < $days; $i++) { + $date[] = date('Y-m-d', $stimestamp + (86400 * $i)); + } + return $date; + } + + public function data($data): array + { + $series = []; + $labels = []; + + $group = []; + $names = []; + foreach ($data as $vo) { + if ($this->type === 'day') { + $vo['label'] = date('Y-m-d', strtotime($vo['label'])); + } + $group[$vo['name']][$vo['label']] += $vo['value']; + $labels[] = $vo['label']; + $names[] = $vo['name']; + } + $labels = array_unique($labels); + + if ($this->type === 'day') { + $labels = $this->getDateFromRange($this->config['start'] ?? $labels[0], $this->config['stop'] ?? end($labels)); + } + + $date = array(); + foreach ($labels as $key => $vo) { + $date[] = strtotime($vo); + } + array_multisort($date, SORT_ASC, $labels); + + $names = array_unique($names); + $tmpArr = []; + foreach ($names as $name) { + foreach ($labels as $label) { + $tmpArr[$name][] = $group[$name][$label] ?: 0; + } + } + foreach ($tmpArr as $name => $vo) { + $series[] = [ + 'name' => $name, + 'data' => $vo + ]; + } + return [$labels, $series]; + } +} diff --git a/admin/components/UI/Components/Chart.php b/admin/components/UI/Components/Chart.php new file mode 100644 index 0000000..172e8fa --- /dev/null +++ b/admin/components/UI/Components/Chart.php @@ -0,0 +1,458 @@ + false, + 'x' => 'right', + 'y' => 'top' + ]; + + private array $date = [ + 'start' => '', + 'stop' => '', + 'interval' => '1 days', + 'format' => 'Y-m-d' + ]; + + private array $series = []; + private array $labels = []; + private array $data = []; + private array $title = []; + private array $subtitle = []; + + + /** + * @param int|string $width + * @return $this + */ + public function width($width): self + { + $this->width = $width; + return $this; + } + + /** + * @param int $height + * @return $this + */ + public function height(int $height): self + { + $this->height = $height; + return $this; + } + + /** + * @param string $title + * @param string $align + * @return $this + */ + public function title(string $title, string $align = 'left'): self + { + $this->title = [ + 'title' => $title, + 'align' => $align + ]; + return $this; + } + + /** + * @param string $title + * @param string $align + * @return $this + */ + public function subtitle(string $title, string $align = 'left'): self + { + $this->subtitle = [ + 'title' => $title, + 'align' => $align + ]; + return $this; + } + + /** + * @param false $zoom + * @return $this + */ + public function zoom(bool $zoom = false): self + { + $this->zoom = $zoom; + return $this; + } + + /** + * @param false $toolbar + * @return $this + */ + public function toolbar(bool $toolbar = false): self + { + $this->toolbar = $toolbar; + return $this; + } + + /** + * @param $status + * @param string $x + * @param string $y + * @return $this + */ + public function legend($status, string $x = "right", string $y = 'top'): self + { + $this->legend = [ + 'status' => $status, + 'x' => $x, + 'y' => $y + ]; + return $this; + } + + /** + * 时间轴 + * @param bool $status + * @return $this + */ + public function datetime(bool $status = true): self + { + $this->datatime = $status; + return $this; + + } + + /** + * @param string $start + * @param string $stop + * @param string $interval + * @param string $format + * @return $this + */ + public function date(string $start, string $stop, string $interval = '1 days', string $format = 'Y-m-d'): self + { + $this->date = [ + 'start' => $start, + 'stop' => $stop, + 'interval' => $interval, + 'format' => $format + ]; + return $this; + } + + /** + * @param string $name + * @param array $data + * @param string $format + * @return $this + */ + public function data(string $name, array $data = [], string $format = 'Ymd'): self + { + $this->data[] = [ + 'name' => $name, + 'data' => $data, + 'format' => $format + ]; + return $this; + } + + + /** + * 线型图 + * @return $this + */ + public function line(): self + { + $this->type = 'line'; + + $this->option = function () { + return [ + 'dataLabels' => [ + 'enabled' => false, + ], + 'fill' => [ + 'opacity' => 1, + ], + 'stroke' => [ + 'curve' => "straight", + ], + 'xaxis' => [ + 'type' => $this->datatime ? 'datetime' : 'category', + 'categories' => $this->labels + ], + ]; + }; + return $this; + } + + /** + * 区域图 + * @return $this + */ + public function area(): self + { + $this->type = 'area'; + + $this->option = function () { + return [ + 'dataLabels' => [ + 'enabled' => false, + ], + 'fill' => [ + 'opacity' => .2, + 'type' => 'solid' + ], + 'xaxis' => [ + 'type' => $this->datatime ? 'datetime' : 'category', + 'categories' => $this->labels + ], + ]; + }; + return $this; + } + + /** + * 柱状图 + * @return $this + */ + public function column(): self + { + $this->type = 'bar'; + + $this->option = function () { + return [ + 'plotOptions' => [ + 'bar' => [ + 'columnWidth' => '50%', + ] + ], + 'dataLabels' => [ + 'enabled' => false, + ], + 'fill' => [ + 'opacity' => 1, + ], + 'xaxis' => [ + 'type' => $this->datatime ? 'datetime' : 'category', + 'categories' => $this->labels + ], + ]; + }; + return $this; + } + + public function get_uuid($len = 0): string + { + $int = ''; + while (strlen($int) != $len) { + $int .= mt_rand(0, 9); + } + return date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8) . $int; + } + + /** + * @param bool $html + * @return array|string + */ + public function render(bool $html = false) + { + $this->renderData(); + + $option = call_user_func($this->option); + + + $option['chart'] = [ + 'id' => 'vuechart-' . $this->get_uuid(10), + ]; + + $option['grid'] = [ + 'strokeDashArray' => 4, + ]; + + if ($this->title) { + $option['title'] = [ + 'text' => $this->title['title'], + 'align' => $this->title['align'], + 'style' => [ + 'fontSize' => '16px', + 'fontWeight' => 'normal', + ] + ]; + } + if ($this->subtitle) { + $option['subtitle'] = [ + 'text' => $this->title['title'], + 'align' => $this->title['align'], + 'style' => [ + 'fontSize' => '14px', + 'fontWeight' => 'normal', + ] + ]; + } + + if ($this->toolbar) { + $option['chart']['toolbar'] = [ + 'show' => true, + 'autoSelected' => true + ]; + } else { + $option['chart']['toolbar'] = [ + 'show' => false + ]; + } + + if ($this->zoom) { + $option['chart']['zoom'] = [ + 'enabled' => true, + 'type' => 'x', + 'autoScaleYaxis' => false + ]; + } else { + $option['chart']['zoom'] = [ + 'enabled' => false + ]; + } + + if ($this->legend['status']) { + $option['legend'] = [ + 'show' => true, + 'position' => $this->legend['y'], + 'horizontalAlign' => $this->legend['x'], + 'floating' => true, + 'offsetY' => 0, + 'offsetX' => -5 + ]; + } else { + $option['legend'] = [ + 'show' => false + ]; + } + + if ($html) { + return $this->renderHtml($option); + } else { + return $this->renderNode($option); + } + + } + + /** + * @param array$option + * @return string + */ + private function renderHtml(array $option): string + { + $option = json_encode($option); + $series = json_encode($this->series); + return << + HTML; + } + + /** + * @param array $option + * @return array + */ + private function renderNode(array $option): array + { + return [ + 'nodeName' => 'apexchart', + 'ref' => 'chart', + 'width' => $this->width, + 'height' => $this->height, + 'type' => $this->type, + 'options' => $option, + 'series' => $this->series + ]; + } + + /** + * @return void + */ + private function renderData(): void + { + $labels = $this->getDateFromRange($this->date['start'] ?: date($this->data['format'], strtotime('-7 day')), $this->date['stop'] ?: date($this->data['format']), $this->date['interval'], $this->date['format']); + $this->labels = $labels; + + foreach ($this->data as $data) { + $group = []; + foreach ($data['data'] as $vo) { + $vo['label'] = date_format(date_create_from_format($data['format'], $vo['label']), $this->date['format']); + $group[$vo['label']] += $vo['value']; + } + $tmpArr = []; + foreach ($labels as $label) { + $tmpArr[] = $group[$label] ?: 0; + } + $this->series[] = [ + 'name' => $data['name'], + 'data' => $tmpArr + ]; + } + + } + + /** + * @param string $startdate + * @param string $enddate + * @param string $interval + * @param string $format + * @return array + */ + private function getDateFromRange(string $startdate, string $enddate, $interval = '1 days', $format = 'Y-m-d'): array + { + $period = CarbonPeriod::create($startdate, $interval, $enddate)->toArray(); + $data = []; + foreach ($period as $date) { + $data[] = $date->format($format); + } + return $data; + } + + /** + * @param $method + * @param $arguments + * @return $this + */ + public function __call($method, $arguments) + { + $this->type = $method; + $this->option = function () use ($arguments) { + $option = [ + 'dataLabels' => [ + 'enabled' => false, + ], + ]; + + if ($arguments && $arguments[0] instanceof \Closure) { + call_user_func($arguments[0], $option, $this); + } + }; + return $this; + } +} diff --git a/admin/components/UI/Components/Component.php b/admin/components/UI/Components/Component.php new file mode 100644 index 0000000..9bc069a --- /dev/null +++ b/admin/components/UI/Components/Component.php @@ -0,0 +1,14 @@ +title = $title; + $this->content = $content; + } + + /** + * @return mixed + */ + public function render() + { + return view('vendor.duxphp.duxravel-app.src.core.UI.View.Components.loading'); + } +} diff --git a/admin/components/UI/Components/NoData.php b/admin/components/UI/Components/NoData.php new file mode 100644 index 0000000..1533e4d --- /dev/null +++ b/admin/components/UI/Components/NoData.php @@ -0,0 +1,32 @@ +title = $title; + $this->content = $content; + $this->reload = $reload; + } + + /** + * @return mixed + */ + public function render() + { + return view('vendor.duxphp.duxravel-app.src.core.UI.View.Components.nodata'); + } +} diff --git a/admin/components/UI/Components/Trend.php b/admin/components/UI/Components/Trend.php new file mode 100644 index 0000000..9a405e4 --- /dev/null +++ b/admin/components/UI/Components/Trend.php @@ -0,0 +1,31 @@ +type = $type; + } + + /** + * @return mixed + */ + public function render() + { + return view('vendor.duxphp.duxravel-app.src.core.UI.View.Components.trend'); + } +} diff --git a/admin/components/UI/Components/VueComponent.php b/admin/components/UI/Components/VueComponent.php new file mode 100644 index 0000000..332bb25 --- /dev/null +++ b/admin/components/UI/Components/VueComponent.php @@ -0,0 +1,15 @@ + $v) { + $el->{$k} = $v; + } + return $el; + } + public function toArray(){ + return $this->_attrs; + } + + public function offsetGet($offset) + { + return $this->_attrs[$offset]; + // TODO: Implement offsetGet() method. + } + + public function offsetSet($offset, $value) + { + $this->_attrs[$offset] = $value; + return true; + // TODO: Implement offsetSet() method. + } + public function offsetUnset($offset) + { + unset($this->_attrs[$offset]); + return true; + // TODO: Implement offsetUnset() method. + } + + public function offsetExists($offset) + { + return isset($this->_attrs[$offset]); + // TODO: Implement offsetExists() method. + } +} diff --git a/admin/components/UI/Event.php b/admin/components/UI/Event.php new file mode 100644 index 0000000..37543e2 --- /dev/null +++ b/admin/components/UI/Event.php @@ -0,0 +1,64 @@ +name = md5($name); + } + + /** + * 增加动作 + * @param $type + * @param string $key + * @param array $data + * @param array $attr + * @return $this + */ + public function add($type, string $key = '', array $data = [], array $attr = []): self + { + $this->data[] = array_filter(array_merge([ + 'type' => $type, + 'key' => $key, + 'data' => $data + ], $attr)); + return $this; + } + + /** + * 渲染数据 + * @param false $inner + * @return array + */ + public function render(bool $inner = false): array + { + if ($inner) { + return [ + 'name' => $this->name, + 'data' => $this->data + ]; + } + + return [ + '__event' => [ + 'name' => $this->name, + 'data' => $this->data + ] + ]; + } + +} diff --git a/admin/components/UI/Form.php b/admin/components/UI/Form.php new file mode 100644 index 0000000..c0af0d3 --- /dev/null +++ b/admin/components/UI/Form.php @@ -0,0 +1,986 @@ +[],'right'=>[]]; + protected bool $dialog = false; + protected bool $vertical = true; + protected array $map = []; + public Collection $element; + + /** + * Form constructor. + * @param $data + * @param bool $model + */ + public function __construct($data = null, bool $model = true) + { + if (!$model) { + // 虚拟数据 + $this->info = $data; + } else { + // 数据模型 + if ($data instanceof ActiveRecord) { + $this->model = $data; + $this->modelElo = $data; + $this->info = $data->getAttributes(); + } else { + $this->info = $data; + } + } + $this->element = Collection::make(); + + if (\Yii::$app->request->getHeaders()->has('x-dialog')) { + $this->dialog = true; + } + } + + /** + * 设置条件主键 + * @param $key + * @param $value + */ + public function setKey($key, $value): void + { + if ($key && $value) { + $this->keys[$key] = $value; + } + if (!$this->model) { + return; + } + $this->setInfo(); + } + + /** + * 获取当前数据 + * @return array|ActiveRecord + */ + public function info() + { + return $this->info; + } + + /** + * 模型对象 + * @return ActiveRecord + */ + public function model(): ActiveRecord + { + return $this->model; + } + + /** + * 模型对象 + * @return ActiveRecord + */ + public function modelElo(): ?ActiveRecord + { + return $this->modelElo; + } + + /** + * 获取元素集合 + * @param null $class + */ + public function getElement($class = null, $num = 0): Collection + { + if ($class) { + $i = 0; + foreach ($this->element as $vo) { + if ($vo instanceof $class) { + if ($i === $num) { + return $vo; + } + $i++; + } + } + } + return $this->element; + } + + /** + * 表单标题 + * @param string $title + * @param bool $back + * @return $this + */ + public function title(string $title, bool $back = true): self + { + $this->title = $title; + $this->back = $back; + return $this; + } + + /** + * 附加脚本 + * @param string $content + * @param string $return + * @return $this + */ + public function script(string $content = '', string $return = ''): self + { + $this->script[] = $content; + $this->scriptReturn[] = $return; + return $this; + } + + /** + * 附加属性 + * @param $name + * @param $value + * @return $this + */ + public function attr($name, $value): Form + { + $this->attr[] = $name . '="' . $value . '"'; + return $this; + } + + /** + * 多行组件 + * @return Form\Row + */ + public function row(): Form\Row + { + $data = new Form\Row(); + $data->dialog($this->dialog); + $data->vertical($this->vertical); + $this->element->push($data); + return $data; + } + + /** + * 切换组件 + * @return Form\Tab + */ + public function tab(): Form\Tab + { + $data = new Form\Tab(); + $data->dialog($this->dialog); + $data->vertical($this->vertical); + $this->element->push($data); + return $data; + } + + /** + * 卡片组件 + * @param $callback + * @return Form\Card + */ + public function card($callback): Form\Card + { + $data = new Form\Card($callback); + $data->dialog($this->dialog); + $data->vertical($this->vertical); + $this->element->push($data); + return $data; + } + + /** + * Html内容 + * @param $name + * @param $callback + * @return Form\Html + */ + public function html($name, $callback): Form\Html + { + $data = new Form\Html($name, $callback); + $data->dialog($this->dialog); + $data->vertical($this->vertical); + $this->element->push($data); + return $data; + } + + /** + * 布局组件 + * @param $callback + * @return Form\Layout + */ + public function layout($callback): Form\Layout + { + $data = new Form\Layout($callback); + $data->dialog($this->dialog); + $this->element->push($data); + return $data; + } + + // 边栏元素 + public function side($callback, string $direction = 'left'): self + { + $this->sideNode[] = [ + 'callback' => $callback, + 'direction' => $direction + ]; + return $this; + } + + /** + * 设置字段映射 + * @param array $map + * @return $this + */ + public function map(array $map): self + { + $this->map = array_merge($this->map, $map); + return $this; + } + + /** + * 获取表单数据 + */ + public function renderData($info) + { + $collection = Collection::make(); + $this->element->map(function ($item) use ($collection, $info) { + $data = $item->getData($info); + foreach ($data as $key => $vo) { + $collection->put($key, $vo); + } + }); + if ($this->map) { + foreach ($this->map as $k => $v) { + $key = is_int($k) ? str_replace(['.', '->'], '_', $v) : $k; + $vo = is_callable($v) ? call_user_func($v, $info) : Tools::parsingArrData($info,$v); + $collection->put($key, $vo); + } + } + return $collection->toArray(); + } + + /** + * @return array + */ + public function renderForm(): array + { + return $this->element->map(function ($vo, $key) { + $sort = $vo->getSort(); + $sort = $sort ?? $key; + + $groupRule = $vo->getGroup(); + $group = []; + foreach ($groupRule as $rule) { + if (is_array($rule['value'])) { + $value = json_encode($rule['value']); + $group[] = "{$value}.indexOf(data.{$rule['name']}) !== -1"; + }else { + $group[] = "data.{$rule['name']} == '{$rule['value']}'"; + } + + } + $group = $group ? implode(' || ', $group) : null; + + if ($vo instanceof Form\Composite) { + $node = [ + 'nodeName' => 'div', + 'child' => $vo->getRender(), + 'sort' => $sort, + ]; + if ($group) { + $node['vIf'] = $group; + } + + return array_merge($node, $vo->getLayoutAttr()); + } + + $helpNode = []; + $prompt = $vo->getPrompt(); + $help = $vo->getHelp(); + if ($prompt) { + $helpNode = [ + 'nodeName' => 'a-tooltip', + 'class' => 'ml-3', + 'position' => 'top', + 'content' => $vo->getPrompt(), + 'child' => [ + 'nodeName' => 'span', + 'child' => [ + 'nodeName' => 'icon-question-circle' + ] + ], + ]; + } + if ($help) { + $helpNode = [ + 'nodeName' => 'div', + 'class' => 'text-gray-300 pt-2 pb-2 ml-3', + 'child' => $help + ]; + } + + $helpLine = $vo->getHelpLine(); + $must = $vo->getMust(); + + $item = [ + 'nodeName' => 'a-form-item', + 'label' => $vo->getName(), + 'field' => $vo->getField(), + 'vIf' => $group, + 'sort' => $sort, + 'child' => [ + $vo->getRender(), + $helpLine ? [ + 'vSlot:help' => '', + 'nodeName' => 'div', + 'child' => $helpLine + ] : [], + $helpNode ? [ + 'nodeName' => 'div', + 'class' => 'ml-2', + 'child' => $helpNode + ] : [] + ] + ]; + + if ($must) { + $item['rules'] = [ + [ + 'required' => true, + 'message' => '请填写' . $vo->getName() + ] + ]; + } + return $item; + })->filter()->sortBy('sort')->values()->toArray(); + } + + /** + * @return mixed|void|null + * @throws \Exception + */ + public function setInfo() + { + if ($this->info) { + return $this->info; + } + if ($this->keys) { + $model = $this->model(); + foreach ($this->keys as $key => $value) { + $model->where($key, $value); + } + $info = $model->find()->one(); + if (empty($info)) { + throw new \Exception('内容不存在'); + } + } else { + $info = []; + } + $this->info = $info; + } + + /** + * 提交类型 + * @param string $name + * @return $this + */ + public function method(string $name = 'post'): self + { + $this->method = $name; + return $this; + } + + /** + * 指定模板变量 + * @param string $name + * @param null $value + * @return $this + */ + public function assign(string $name, $value = null): self + { + $this->assign[$name] = $value; + return $this; + } + + /** + * 是否弹窗 + * @param bool $status + * @return $this + */ + public function dialog(bool $status): self + { + $this->dialog = $status; + $this->vertical = true; + return $this; + } + + /** + * 纵向表单 + * @param bool $status + * @return $this + */ + public function vertical(bool $status): self + { + $this->vertical = $status; + return $this; + } + + /** + * 获取弹窗状态 + * @return bool + */ + public function getDialog(): bool + { + return $this->dialog; + } + + /** + * 保存链接 + * @param $uri + * @return $this + */ + public function action($uri): self + { + $this->action = $uri; + return $this; + } + + /** + * 渲染表单(数组) + * @return array + */ + public function renderArray() + { + $params = \Yii::$app->request->getQueryParams(); + $action = route($this->action, $params); + + // 提交地址 + //if ($this->action) { + // $action = $this->action; + //} else { + // $params = \Yii::$app->request->getQueryParams(); + // if ($this->modelElo) { + // $key = $this->modelElo->getKeyName(); + // $id = $this->info->$key; + // $params['id'] = $id; + // } + // $action = route($this->action, $params); + //} + + $node = new Node($action, $this->method, $this->title); + $node->dialog($this->dialog); + $node->vertical($this->vertical); + $node->back($this->back); + + // 表单元素· + $node->element($this->renderForm()); + + + // 表单数据 + $node->data($this->renderData($this->info)); + + // 边栏元素 + foreach ($this->sideNode as $vo) { + $node->side($vo['callback'], $vo['direction']); + } + + // 处理附加js + foreach ($this->script as $key => $value) { + $node->script($value, $this->scriptReturn[$key]); + } + + return $node->render(); + } + public function renderFormWithoutNode(){ + $params = \Yii::$app->request->getQueryParams(); + $action = route($this->action, $params); + + // 提交地址 + //if ($this->action) { + // $action = $this->action; + //} else { + // $params = \Yii::$app->request->getQueryParams(); + // if ($this->modelElo) { + // $key = $this->modelElo->getKeyName(); + // $id = $this->info->$key; + // $params['id'] = $id; + // } + // $action = route($this->action, $params); + //} + + // 处理附加js + $script = []; + foreach ($this->script as $key => $value) { + if ($value instanceof \Closure) { + $script[] = $value(); + } else { + $script[] = $value; + } + } + return [ + 'nodeName' => 'app-form', + 'url' => $action, + 'method' => $this->method, + 'value' => $this->renderData($this->info), + 'layout' => $this->vertical ? 'vertical' : 'horizontal', + 'back' => $this->back, + 'child' => [ + 'nodeName' => 'div', + 'class' => 'flex', + 'vSlot' => '{value: data, submitStatus: loading}', + 'child' => $this->dialog ? $this->renderDialog() : $this->renderPage() + ] + ]; + } + + /** + * 获取提交数据 + * @param $time + * @return Collection + */ + public function getInput($time): Collection + { + // 获取提交数据 + $data = \Yii::$app->request->post(); + + // 提交数据处理 + if ($this->flow['submit']) { + foreach ($this->flow['submit'] as $item) { + $data = $item($data, $time); + } + } + // 过滤数据 + $collection = Collection::make(); + $this->element->map(function ($item) use ($collection, $time) { + $inputs = $item->getInput($time); + + foreach ($inputs as $key => $vo) { + $collection->put($key, $vo); + } + }); + + //验证数据 + $rules = []; + $msgs = []; + $collection->map(function ($item) use (&$rules, &$msgs) { + if ($item['verify']['rule']) { + $rules = $rules + $item['verify']['rule']; + } + if ($item['verify']['msg']) { + $msgs = $msgs + $item['verify']['msg']; + } + }); + $validator = \Validator::make($data, $rules, $msgs); + + if ($this->flow['validator']) { + foreach ($this->flow['validator'] as $vo) { + $vo($validator); + } + } + $validator->validate(); + + // 格式化数据 + return $collection->map(function ($item) { + $value = $item['value']; + if ($item['format']) { + foreach ($item['format'] as $vo) { + $value = call_user_func($vo, $item['value']); + } + } + return ['value' => $value, 'has' => $item['has'], 'pivot' => $item['pivot']]; + }); + } + + /** + * 流程时间 + * @var array + */ + protected array $prepared = []; + + /** + * 主键值 + * @var null + */ + public $modelId = null; + + /** + * 保存数据 + * @return null $modelId + */ + public function save() + { + // 获取主键数据 + $id = 0; + if ($this->modelElo) { + $id = $this->keys[$this->modelElo->getPrimaryKey()]; + } + + // 保存类型 + $type = $id ? 'edit' : 'add'; + + // 获取提交数据 + $data = $this->getInput($type); + + // 提取提交数据 + $formatData = []; + foreach ($data as $key => $vo) { + $formatData[$key] = $vo['value']; + } + $formatData = collect($formatData); + + // 非模型返回集合 + if (!$this->modelElo) { + return $formatData; + } + + // 获取模型对象 + if ($type === 'add') { + $model = $this->modelElo; + } else { + $model = $this->modelElo->find($id); + } + + // 保存数据库 + \Yii::$app->db->transation(function () use ($model, $data, $type, $formatData) { + // 保存前置回调 + if ($this->flow['front']) { + foreach ($this->flow['front'] as $item) { + $ret = $item($formatData, $type, $model); + if ($ret instanceof ActiveRecord) { + $model = $ret; + } + } + } + + // 树形处理 已废弃 先设置 scoped 数据 再设置上级数据 + /*if ($model->parent_id) { + if (method_exists($model, 'appendToNode')) { + $model = $model->appendToNode($this->modelElo->find($formatData['parent_id'])); + } + }*/ + + $data->map(function ($item, $key) use ($model) { + $has = $item['has']; + // 查询关联对象 + if (method_exists($model, $has) && !is_null($item['value'])) { + $relation = $model->$has(); + // 多对多 + if ($relation instanceof \Illuminate\Database\Eloquent\Relations\BelongsToMany) { + $this->prepared[] = static function ($model) use ($item) { + $sync = is_array($item['value']) ? $item['value'] : [$item['value']]; + $syncFormat = []; + if ($item['pivot']) { + foreach ($sync as $vo) { + $syncFormat[$vo] = $item['pivot']; + } + $sync = $syncFormat; + } + $model->{$item['has']}()->sync($sync); + }; + } + } else if ($model::getTableSchema()->getColumn($key)) { + // 过滤无用字段 + $model->$key = $item['value']; + } + }); + + // 保存前置回调 + if ($this->flow['before']) { + foreach ($this->flow['before'] as $item) { + $ret = $item($formatData, $type, $model); + if ($ret instanceof ActiveRecord) { + $model = $ret; + } + } + } + + $model->save(); + + // 同步关联数据 + foreach ($this->prepared as $callback) { + $callback($model); + } + // 保存后置回调 + if ($this->flow['after']) { + foreach ($this->flow['after'] as $item) { + $item($formatData, $type, $model); + } + } + }); + $this->modelId = $model->getKey(); + return $this->modelId; + } + + /** + * 处理数据之前提交 + * @param $callback + * @return $this + */ + public function front($callback): Form + { + $this->flow['front'][] = $callback; + return $this; + } + + /** + * 验证表单扩展 + * @param $callback + * @return $this + */ + public function validator($callback): Form + { + $this->flow['validator'][] = $callback; + return $this; + } + + /** + * 提交之前回调 + * @param $callback + * @return $this + */ + public function submit($callback): Form + { + $this->flow['submit'][] = $callback; + return $this; + } + + /** + * 保存之前回调 + * @param $callback + * @return $this + */ + public function before($callback): Form + { + $this->flow['before'][] = $callback; + return $this; + } + + /** + * 保存后回调 + * @param $callback + * @return $this + */ + public function after($callback): Form + { + $this->flow['after'][] = $callback; + return $this; + } + + /** + * 扩展元素 + * @param $method + * @param $className + */ + public function extend($method, $className): void + { + $this->extend[$method] = $className; + } + + + /** + * 前端事件 + * @param $table + * @param $name + * @param $type + * @return array|false + */ + public function callbackEvent($table, $name, $type, $data = null) + { + if (!$this->modelId) { + return false; + } + $rowsData = $data ?: $this->modelElo->where($this->modelElo->getPrimaryKey(), $this->modelId)->get(); + $list = $table->renderRowData($rowsData, false); + + $parentKey = null; + if ($table->getTree()) { + $parentKey = $this->modelElo->find($this->modelId)->parent_id; + } + + $event = new Event($name); + foreach ($list as $item) { + $event->add($type, $this->modelId, $item, $parentKey !== false ? ['parentKey' => $parentKey] : []); + } + return $event->render(); + + } + + /** + * 回调类库 + * @param $method + * @param $arguments + * @return mixed + * @throws \Exception + */ + public function __call($method, $arguments) + { + $class = 'backend\\components\\UI\\Form\\' . ucfirst($method); + if (!class_exists($class)) { + if (!$this->extend[$method]) { + throw new \Exception('There is no form method "' . $method . '"'); + } + $class = $this->extend[$method]; + } + $object = new $class(...$arguments); + $object->dialog($this->dialog); + $this->element->push($object); + return $object; + } + private function renderPage(): array + { + return [ + $this->side['left'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none flex h-screen flex-col', + 'child' => $this->side['left'] + ] : [], + + [ + 'nodeName' => 'div', + 'class' => 'flex flex-col lg:h-screen flex-grow w-10', + 'child' => [ + [ + 'nodeName' => 'div', + 'child' => $this->renderForm() + ], + [ + 'nodeName' => 'div', + 'class' => 'flex items-center justify-end gap-2 flex-row ', + 'child' => [ + $this->back ? [ + 'nodeName' => 'route', + 'type' => 'back', + 'child' => [ + 'type' => "outline", + 'nodeName' => 'a-button', + 'child' => '返回', + ] + ] : [], + [ + 'nodeName' => 'a-button', + 'html-type' => 'submit', + 'vBind:loading' => "loading", + 'type' => 'primary', + 'child' => $this->back ? '提交' : '保存', + ], + ] + ], + + ], + ], + $this->side['right']? [ + 'nodeName' => 'div', + 'class' => 'flex-none flex h-screen flex-col', + 'child' => $this->side['right'] + ] : [], + ]; + } + + /** + * 渲染弹窗 + * @return array + */ + private function renderDialog(): array + { + + return [ + 'nodeName' => 'app-dialog', + 'title' => $this->title ?: '信息详情', + 'class' => 'flex-grow', + 'child' => [ + [ + 'nodeName' => 'div', + 'vSlot:default' => '', + 'class' => 'flex', + 'child' => [ + $this->side['left'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none', + 'child' => $this->side['left'] + ] : [], + [ + 'nodeName' => 'div', + 'class' => 'flex-grow p-5 pb-0', + 'child' => $this->renderForm() + ], + $this->side['right'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none', + 'child' => $this->side['right'] + ] : [] + ] + ], + [ + 'nodeName' => 'div', + 'vSlot:footer' => '', + 'class' => 'arco-modal-footer', + 'child' => [ + [ + 'nodeName' => 'route', + 'type' => 'back', + 'child' => [ + 'nodeName' => 'a-button', + 'child' => '取消' + ] + ], + [ + 'nodeName' => 'a-button', + 'type' => 'primary', + 'html-type' => 'submit', + 'vBind:loading' => "loading", + 'child' => '提交' + ], + ] + ] + ] + + ]; + + } + +} diff --git a/admin/components/UI/Form/Area.php b/admin/components/UI/Form/Area.php new file mode 100644 index 0000000..11acc55 --- /dev/null +++ b/admin/components/UI/Form/Area.php @@ -0,0 +1,101 @@ + 'province', + 'city' => 'city', + 'region' => 'region', + 'street' => 'street', + ]; + + /** + * @param string $name + * @param array $map + * @param string $has + */ + public function __construct(string $name, array $map = [], string $has = '') + { + if ($map) { + $this->map = $map; + } + $this->name = $name; + $this->field = end($this->map); + $this->has = $has; + $this->attr['placeholder'] = null; + } + + /** + * @return $this + */ + public function multi(): self + { + $this->multi = true; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'app-cascader', + 'nParams' => [ + 'cascade' => true, + 'show-path' => true, + 'filterable' => false, + 'clearable' => true, + 'leaf-only' => true, + 'multiple' => $this->multi, + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + ], + 'dataUrl' => route('service.area', ['level' => count($this->map)]), + ]; + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + return $data; + } + + /** + * @param $data + * @return array + */ + public function appendInput($data): array + { + $info = \backend\components\Model\Area::where(['code' => $data])->first(); + + $code = $info->parent_code; + if ($info->level > 3) { + $region = \backend\components\Model\Area::where(['code' => $code])->first(); + $code = $region['parent_code']; + } + if ($info->level > 2) { + $city = \backend\components\Model\Area::where(['code' => $code])->first(); + $code = $city['parent_code']; + } + if ($info->level > 1) { + $province = \backend\components\Model\Area::where(['code' => $code])->first(); + } + $data = []; + if ($region) { + $data[$this->map['region']] = $region->code; + } + if ($city) { + $data[$this->map['city']] = $city->code; + } + if ($province) { + $data[$this->map['province']] = $province->code; + } + return $data; + } + +} diff --git a/admin/components/UI/Form/Card.php b/admin/components/UI/Form/Card.php new file mode 100644 index 0000000..7105829 --- /dev/null +++ b/admin/components/UI/Form/Card.php @@ -0,0 +1,48 @@ +callback = $callback; + $form = new Form(); + $form->dialog($this->dialog); + $form->vertical($this->vertical); + $callback($form); + $this->column[] = [ + 'object' => $form, + ]; + } + + /** + * @return array + */ + public function render(): array + { + $inner = []; + foreach ($this->column as $vo) { + $inner = $vo['object']->renderForm(); + } + + if (!$this->dialog) { + $this->class('mb-4 bg-white dark:bg-blackgray-4 rounded shadow p-7 pb-2'); + } + + return [ + 'nodeName' => 'div', + 'class' => implode(' ', $this->class), + 'child' => $inner + ]; + } + +} diff --git a/admin/components/UI/Form/Cascader.php b/admin/components/UI/Form/Cascader.php new file mode 100644 index 0000000..ff0da57 --- /dev/null +++ b/admin/components/UI/Form/Cascader.php @@ -0,0 +1,200 @@ +name = $name; + $this->field = $field; + $this->data = $data; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * 添加选项 + * @param $name + * @param $id + * @param $pid + * @return $this + */ + public function add($name, $id, $pid): self + { + $this->data[] = [ + 'name' => $name, + 'id' => $id, + 'pid' => $pid + ]; + return $this; + } + + + /** + * @param $url + * @return $this + */ + public function url($url): self + { + $this->url = $url; + return $this; + } + + /** + * @param string $route + * @param array $params + * @return $this + */ + public function route(string $route, array $params = []): self + { + $this->route = $route; + $this->url = app_route($route, $params); + return $this; + } + + /** + * @return $this + */ + public function multi(): self + { + $this->multi = true; + return $this; + } + + /** + * leaf choice + * @param bool $leaf + * @return $this + */ + public function leaf(bool $leaf): self + { + $this->leaf = $leaf; + return $this; + } + + /** + * tree data + * @param bool $bool + * @return $this + */ + public function tree(bool $bool = true): self + { + $this->treeData = $bool; + return $this; + } + + /** + * 标签显示最大条数 + * @param int $num + * @return $this + */ + public function maxTagCount(int $num){ + return $this->nParams('maxTagCount',$num); + } + + /** + * 附加参数 + * @param $key + * @param $value + * @return $this + */ + public function nParams($key,$value){ + $this->params[$key] = $value; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + + $data = []; + if ($this->data instanceof \Closure) { + $data = call_user_func($this->data, $this); + } + if (is_array($this->data)) { + $data = $this->data; + } + + if (!$this->treeData) { + $options = []; + foreach ($data as $vo) { + $options[] = [ + 'id' => $vo['id'], + 'pid' => $vo['parent_id'], + 'value' => $vo['id'], + 'label' => $vo['name'], + ]; + } + + $options = \backend\components\Tree::arr2tree($options, 'id', 'pid', 'children'); + } else { + $options = $data; + } + + + $data = [ + 'nodeName' => 'app-cascader', + 'nParams' => array_merge($this->params, [ + 'check-strictly' => !$this->leaf, + 'multiple' => $this->multi, + 'options' => $options, + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + ]) + ]; + + if ($this->route) { + $data['vBind:dataUrl'] = $this->url; + } else { + $data['dataUrl'] = $this->url; + } + + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + + return $data; + } + + /** + * @param $value + * @return array|mixed + */ + public function dataValue($value) + { + return $this->multi ? array_values(array_filter((array)$this->getValueArray($value))) : $this->getValue($value); + } + + /** + * @param $data + * @return string + */ + public function dataInput($data): ?string + { + return is_array($data) ? implode(',', $data) : $data; + } + + +} diff --git a/admin/components/UI/Form/Checkbox.php b/admin/components/UI/Form/Checkbox.php new file mode 100644 index 0000000..043eb0b --- /dev/null +++ b/admin/components/UI/Form/Checkbox.php @@ -0,0 +1,96 @@ +name = $name; + $this->field = $field; + $this->data = $data; + $this->has = $has; + } + + /** + * add data + * @param $name + * @param $value + * @return $this + */ + public function add($name, $value): self + { + $this->data[] = [ + 'name' => $name, + 'value' => $value + ]; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = []; + if ($this->data instanceof \Closure) { + $data = call_user_func($this->data); + } + if (is_array($this->data)) { + $data = $this->data; + } + + $child = []; + foreach ($data as $key => $vo) { + $child[] = [ + 'nodeName' => 'a-checkbox', + 'value' => $key, + 'child' => $vo, + ]; + } + + $data = [ + 'nodeName' => 'a-checkbox-group', + 'child' => $child + ]; + + if ($this->model) { + $data['vModel:model-value'] = $this->getModelField(); + } + + return $data; + } + + /** + * @param $value + * @return array + */ + public function dataValue($value): array + { + return array_values(array_filter((array)$this->getValueArray($value))); + } + + /** + * @param $data + * @return string + */ + public function dataInput($data): ?string + { + return is_array($data) ? implode(',', $data) : $data; + } + +} diff --git a/admin/components/UI/Form/Choice.php b/admin/components/UI/Form/Choice.php new file mode 100644 index 0000000..8a48e84 --- /dev/null +++ b/admin/components/UI/Form/Choice.php @@ -0,0 +1,184 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * @param string $url + * @param string $key + * @param callable $column + * @param array $types + * @return $this + */ + public function ajax(string $url, string $key, callable $column, array $types = []): self + { + $this->ajax = [ + 'url' => $url, + 'key' => $key, + 'column' => $column, + 'type' => $types + ]; + return $this; + } + + /** + * text column + * @param string $name + * @param string $field + * @return $this + */ + public function text(string $name, string $field): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'text' + ]; + return $this; + } + + /** + * image column + * @param string $name + * @param string $field + * @return $this + */ + public function image(string $name, string $field): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'image' + ]; + return $this; + } + + /** + * show column + * @param string $name + * @param string $field + * @return $this + */ + public function show(string $name, string $field): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'show' + ]; + return $this; + } + + /** + * hidden column + * @param string $name + * @param string $field + * @return $this + */ + public function hidden(string $name, string $field): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'hidden' + ]; + return $this; + } + + /** + * option status + * @param bool $status + * @return $this + */ + public function option(bool $status = true): self + { + $this->option = $status; + return $this; + } + + /** + * maximum number + * @param int $num + * @return $this + */ + public function num(int $num = 0): self + { + $this->number = $num; + return $this; + } + + /** + * @return array + * @throws ErrorException + */ + public function render(): array + { + $url = route('service.image.placeholder', ['w' => 64, 'h' => 64, 't' => $this->attr['placeholder'] ?: '图片']); + + $ajaxColumn = $this->ajax['column'] ?: []; + if (is_callable($ajaxColumn)) { + $ajaxColumn = $ajaxColumn(new ChoiceColumn()); + if (!$ajaxColumn instanceof ChoiceColumn) { + app_error('Choice component configuration error'); + } + $ajaxColumn = $ajaxColumn->getData(); + } + + return [ + 'nodeName' => 'app-choice', + 'vModel:value' => $this->getModelField(), + 'column' => $this->column, + 'ajaxColumn' => $ajaxColumn, + 'ajaxType' => $this->ajax['type'], + 'key' => $this->ajax['key'], + 'url' => $this->ajax['url'], + 'number' => $this->number, + 'option' => $this->option, + ]; + + } + + /** + * @param $value + * @return array|null + */ + public function dataValue($value): ?array + { + $value = $this->getValue($value); + if ($value instanceof \Illuminate\Database\Eloquent\Collection && $value->count()) { + $values = $value->toArray(); + } else if (is_array($value)) { + $values = $value; + } else { + $values = []; + } + return $values; + } + +} diff --git a/admin/components/UI/Form/ChoiceColumn.php b/admin/components/UI/Form/ChoiceColumn.php new file mode 100644 index 0000000..79f2d61 --- /dev/null +++ b/admin/components/UI/Form/ChoiceColumn.php @@ -0,0 +1,55 @@ +column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'text' + ]; + return $this; + } + + /** + * @param string $name + * @param string $field + * @return $this + */ + public function image(string $name, string $field): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'image' + ]; + return $this; + } + + + /** + * @return array + */ + public function getData(): array + { + return $this->column; + } + +} diff --git a/admin/components/UI/Form/Color.php b/admin/components/UI/Form/Color.php new file mode 100644 index 0000000..8d4e799 --- /dev/null +++ b/admin/components/UI/Form/Color.php @@ -0,0 +1,72 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * @return $this + */ + public function picker(): self + { + $this->picker = true; + return $this; + } + + /** + * @param array $data + * @return $this + */ + public function color(array $data): self + { + $this->color = $data; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + if ($this->picker) { + // 暂无组件 + $data = [ + + ]; + }else { + $data = [ + 'nodeName' => 'app-color', + 'colors' => $this->color, + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + ]; + } + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + + return $data; + } + +} diff --git a/admin/components/UI/Form/Component.php b/admin/components/UI/Form/Component.php new file mode 100644 index 0000000..18df416 --- /dev/null +++ b/admin/components/UI/Form/Component.php @@ -0,0 +1,12 @@ +column[$key][$item] : $this->column[$key]) : $this->column; + } + + /** + * 获取值 + * @param string $time + * @return array + */ + public function getInput(string $time = 'add'): array + { + $data = []; + foreach ($this->column as $vo) { + $vo['object']->getElement()->map(function ($item) use (&$data, $time) { + foreach ($item->getInput($time) as $k => $v) { + $data[$k] = $v; + } + }); + } + return $data; + } + + /** + * @param $info + * @return array + */ + public function getData($info): array + { + $data = []; + foreach ($this->column as $vo) { + $vo['object']->getElement()->map(function ($item) use (&$data, $info) { + foreach ($item->getData($info) as $k => $v) { + $data[$k] = $v; + } + }); + } + return $data; + } +} diff --git a/admin/components/UI/Form/Data.php b/admin/components/UI/Form/Data.php new file mode 100644 index 0000000..5d3571d --- /dev/null +++ b/admin/components/UI/Form/Data.php @@ -0,0 +1,213 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * 文本列 + * @param string $name + * @param string $field + * @param null $width + * @return $this + */ + public function text(string $name, string $field, $width = null): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'text', + 'width' => $width, + ]; + return $this; + } + + /** + * 图片列 + * @param string $name + * @param string $field + * @param null $width + * @return $this + */ + public function image(string $name, string $field, $width = null): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'image', + 'width' => $width, + ]; + return $this; + } + + /** + * 展示列 + * @param string $name + * @param string $field + * @param null $width + * @return $this + */ + public function show(string $name, string $field, $width = null): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'show', + 'width' => $width, + ]; + return $this; + } + + /** + * 隐藏列 + * @param string $name + * @param string $field + * @return $this + */ + public function hidden(string $name, string $field): self + { + $this->column[] = [ + 'name' => $name, + 'key' => $field, + 'type' => 'hidden' + ]; + return $this; + } + + /** + * 操作状态 + * @param bool $status + * @return $this + */ + public function option(bool $status = true): self + { + $this->option = $status; + return $this; + } + + /** + * 最大数量 + * @param int $num + * @return $this + */ + public function max(int $num = 0): self + { + $this->numberMax = $num; + return $this; + } + + /** + * 最小数量 + * @param int $num + * @return $this + */ + public function min(int $num = 0): self + { + $this->numberMin = $num; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $url = route('service.image.placeholder', ['w' => 64, 'h' => 64, 't' => $this->attr['placeholder'] ?: '图片']); + + $inner = []; + $default = []; + foreach ($this->column as $column) { + $default[$column['key']] = ''; + $field = "value['{$column['key']}']"; + if ($column['type'] === 'text') { + $inner[] = [ + 'nodeName' => 'div', + 'class' => 'flex-grow', + 'child' => [ + 'nodeName' => 'a-input', + 'placeholder' => '请输入' . $column['name'], + 'vModel:model-value' => $field + ] + ]; + } + if ($column['type'] === 'image') { + $inner[] = [ + 'nodeName' => 'div', + 'class' => 'flex-none', + 'child' => [ + 'nodeName' => 'app-file', + 'image' => 'true', + 'mini' => true, + 'size' => 8, + 'vModel:value' => $field + ] + ]; + } + if ($column['type'] === 'show') { + $inner[] = [ + 'nodeName' => 'div', + 'class' => 'flex-grow', + 'child' => "{{ $field || '-'}}" + ]; + } + } + + $create = json_encode($default); + $data = [ + 'nodeName' => 'app-dynamic-data', + 'vModel:value' => $this->getModelField(), + 'vBind:on-create' => "() => { return $create }", + 'child' => [ + 'vSlot' => '{ index, value }', + 'nodeName' => 'div', + 'class' => 'flex flex-grow gap-4 items-center', + 'child' => $inner + ] + ]; + + if ($this->numberMax) { + $data['max'] = $this->numberMax; + } + + if ($this->numberMin) { + $data['min'] = $this->numberMin; + } + + return $data; + } + + /** + * @param $data + * @return array|null + */ + public function dataValue($data): ?array + { + $data = $this->getValue($data); + return $data ?: []; + } + +} diff --git a/admin/components/UI/Form/Date.php b/admin/components/UI/Form/Date.php new file mode 100644 index 0000000..dec567b --- /dev/null +++ b/admin/components/UI/Form/Date.php @@ -0,0 +1,87 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * @param string $type + * @return $this + */ + public function type(string $type): self + { + if (!in_array($type, $this->types)) { + throw new \RuntimeException('There is no type "' . $type . '"'); + } + $this->type = $type; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-date-picker', + 'allowClear' => true, + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + 'vModel:modelValue' => $this->getModelField() + ]; + if ($this->type) { + $data['nodeName'] = 'a-' . $this->type . '-picker'; + } + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + /** + * @param $data + * @return string|null + */ + public function dataInput($data): ?string + { + return $data ? date('Y-m-d', strtotime($data)) : null; + } + + /** + * @param $data + * @return string|null + */ + public function dataValue($data): ?string + { + $data = $this->getValue($data); + return $data ?: null; + } + +} diff --git a/admin/components/UI/Form/Daterange.php b/admin/components/UI/Form/Daterange.php new file mode 100644 index 0000000..c51149f --- /dev/null +++ b/admin/components/UI/Form/Daterange.php @@ -0,0 +1,106 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * 设置结束字段 + * @param $field + * @return $this + */ + public function stopField($field): self + { + $this->stopField = $field; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-range-picker', + 'allowClear' => true, + 'vModel:modelValue' => $this->getModelField() + ]; + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + /** + * @param $value + * @return array + */ + public function appendInput($value): array + { + if (!$this->stopField) { + return []; + } + $data = []; + $data[$this->stopField] = is_array($value) && $value[1] ? date('Y-m-d H:i:s', strtotime($value[1])) : null; + return $data; + } + + /** + * @param $value + * @return string|null + */ + public function dataInput($value): ?string + { + if ($this->stopField) { + return is_array($value) && $value[0] ? date('Y-m-d H:i:s',strtotime($value[0])) : null; + } + return is_array($value) ? date('Y-m-d H:i:s', strtotime($value[0])) . ',' . date('Y-m-d H:i:s', strtotime($value[1])) : null; + } + + /** + * @param $value + * @param $info + * @return array|null + */ + public function dataValue($value, $info): ?array + { + $value = $this->getValue($value); + $data = []; + if ($this->stopField) { + $data[] = $value ?: null; + $stopValue = Tools::parsingArrData($info, $this->stopField); + $data[] = $stopValue ?: null; + return $data; + } + if ($value) { + $data = explode(',', $value); + } + return $data ? [$data[0], $data[1]] : null; + } + + +} diff --git a/admin/components/UI/Form/Datetime.php b/admin/components/UI/Form/Datetime.php new file mode 100644 index 0000000..b4edbe3 --- /dev/null +++ b/admin/components/UI/Form/Datetime.php @@ -0,0 +1,79 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * 日期格式 + * @param string $format + * @return $this + */ + public function string(string $format): self + { + $this->string = $format; + return $this; + } + + /** + * 渲染组件 + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-date-picker', + 'vModel:value' => $this->getModelField(), + 'showTime' => true, + 'allowClear' => true, + 'format' => $this->string, + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + 'vModel:modelValue' => $this->getModelField() + ]; + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + /** + * @param $data + * @return string|null + */ + public function dataInput($data): ?string + { + return $data ? date('Y-m-d H:i:s', strtotime($data)) : null; + } + + /** + * @param $data + * @return string|null + */ + public function dataValue($data): ?string + { + $data = $this->getValue($data); + return $data ?: null; + } + +} diff --git a/admin/components/UI/Form/Editor.php b/admin/components/UI/Form/Editor.php new file mode 100644 index 0000000..555dfe0 --- /dev/null +++ b/admin/components/UI/Form/Editor.php @@ -0,0 +1,38 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'app-editor' + ]; + + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + return $data; + } + +} diff --git a/admin/components/UI/Form/Element.php b/admin/components/UI/Form/Element.php new file mode 100644 index 0000000..492dc8c --- /dev/null +++ b/admin/components/UI/Form/Element.php @@ -0,0 +1,536 @@ +dialog = $bool; + return $this; + } + + /** + * 设置方向 + * @param $bool + * @return $this + */ + public function vertical($bool): self + { + $this->vertical = $bool; + return $this; + } + + /** + * 设置数据模型 + */ + public function modelElo($class) + { + $this->modelElo = $class; + return $this; + } + + /** + * 设置数据前缀 + */ + public function model($model) + { + $this->model = $model; + return $this; + } + + /** + * 获取模型字段 + * @return string + */ + public function getModelField() + { + return $this->model . $this->field; + } + + /** + * 获取标签状态 + * @return bool + */ + public function getLabel(): bool + { + return $this->label; + } + + + /** + * 获取字段名 + * @return string + */ + public function getField(): string + { + return $this->field; + } + + /** + * 获取关联模型 + * @return string + */ + public function getHas(): string + { + return $this->has; + } + + /** + * 获取名称 + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * 获取值 + * @param $value + * @return mixed + */ + public function getValue($value = null) + { + return ($this->value ?? $value) ?? $this->default; + } + + /** + * 获取数组值 + * @param $value + * @param bool $json + * @return array|null + */ + public function getValueArray($value, bool $json = false): ?array + { + if ($value instanceof \Illuminate\Database\Eloquent\Collection) { + if ($value->count()) { + $values = $value->pluck($value->first()->getKeyName())->toArray(); + } else { + $values = $json ? [] : null; + } + } else if (is_array($value)) { + $values = $value; + } else if ($value !== null) { + $values = $json ? json_decode($value, true) : explode(',', $value); + } else { + $values = $json ? [] : null; + } + return $values; + } + + /** + * 获取回调数据组 + * @param $data + * @param $value + * @return array + */ + public function getCallbackArray($data, $value): array + { + if ($data instanceof \Closure) { + return call_user_func($data, [$value]); + } + if (is_array($data)) { + return $data; + } + return []; + } + + /** + * 设置选项值 + * @param $value + * @return $this + */ + public function value($value): self + { + $this->value = $value; + return $this; + } + + /** + * 设置默认值 + * @param $value + * @return $this + */ + public function default($value): self + { + $this->default = $value; + return $this; + } + + /** + * 设置帮助信息 + * @param string|array $value + * @param bool $line + * @return $this + */ + public function help($value, bool $line = false): self + { + if ($line) { + $this->helpLine = $value; + } else { + $this->help = $value; + } + return $this; + } + + /** + * 属性数据 + * @param string $name + * @param string|array $value + * @return $this + */ + public function attr(string $name, $value): self + { + $this->attr[$name] = $value; + return $this; + } + + /** + * 布局树形 + * @param string $name + * @param $value + * @return $this + */ + public function layoutAttr(string $name, $value): self + { + $this->layoutAttr[$name] = $value; + return $this; + } + + /** + * 属性数组 + * @param $attr + * @return $this + */ + public function attrArray($attr): self + { + $this->attr = $attr; + return $this; + } + + /** + * class样式 + * @param string $name + * @return $this + */ + public function class(string $name): self + { + $this->class[] = $name; + return $this; + } + + /** + * 字符串替换标签(数字字符串处理使用) + * @param $replace + * @return $this + */ + public function replace($replace): self + { + $this->replace = $replace; + return $this; + } + + /** + * 设置提示 + * @param $name + * @return $this + */ + public function placeholder($name): self + { + if ($name) { + $this->attr['placeholder'] = $name; + } + return $this; + } + + /** + * 元素分组 + * @param $name + * @param $value + * @return $this + */ + public function group($name, $value): self + { + $this->group[] = [ + 'name' => $name, + 'value' => $value + ]; + return $this; + } + + /** + * 必填样式 + * @return $this + */ + public function must(): self + { + $this->must = true; + $this->verify['all'][$this->field][] = 'required'; + $this->verifyMsg['all'][$this->field . '.' . 'required'] = '请输入' . $this->name; + return $this; + } + + /** + * 帮助信息 + * @param $content + * @return $this + */ + public function prompt($content): self + { + $this->prompt = $content; + return $this; + } + + /** + * 排序 + * @param $num + * @return $this + */ + public function sort($num): self + { + $this->sort = $num; + return $this; + } + + /** + * 获取分组 + * @return array + */ + public function getGroup(): array + { + return $this->group; + } + + /** + * 获取必须 + * @return bool + */ + public function getMust(): bool + { + return $this->must; + } + + /** + * 获取提醒 + * @return string + */ + public function getPrompt(): string + { + return $this->prompt; + } + + /** + * 获取帮助行 + * @return string|array + */ + public function getHelpLine() + { + return $this->helpLine; + } + + + /** + * 获取层属性 + * @return array + */ + public function getLayoutAttr() + { + return $this->layoutAttr; + } + + /** + * 同步附加数据 + * @param $data + * @return $this + */ + public function pivot($data) + { + $this->pivot = $data; + return $this; + } + + /** + * 设置字段验证 + * @param $rule + * @param array $msg + * @param string $time + * @return $this + */ + public function verify($rule, array $msg = [], string $time = 'all'): self + { + $this->verify[$time][$this->field] = $rule; + foreach ($msg as $key => $vo) { + $this->verifyMsg[$time][$this->field . '.' . $key] = $vo; + } + return $this; + } + + /** + * 获取验证规则 + * @param string $time + * @return array + */ + public function getVerify(string $time = 'add'): array + { + return [ + 'rule' => (array)$this->verify['all'] + (array)$this->verify[$time], + 'msg' => (array)$this->verifyMsg['all'] + (array)$this->verifyMsg[$time] + ]; + } + + /** + * 设置表单格式化 + * @param string|callable $rule + * @param string $time + * @return $this + */ + public function format($rule, string $time = 'all'): self + { + $this->format[$time][] = $rule; + return $this; + } + + /** + * 获取表单格式化 + * @param string $time + * @return array + */ + public function getFormat(string $time = 'add'): array + { + return (array)$this->format['all'] + (array)$this->format[$time]; + } + + + /** + * 获取提交数据 + * @param string $time + * @return mixed + */ + public function getInput(string $time = 'add'): array + { + $data = \Yii::$app->request->get($this->field); + $inputs = []; + if (method_exists($this, 'appendInput') && !$this->has) { + $appendData = $this->appendInput($data); + foreach ($appendData as $key => $vo) { + $inputs[$key] = ['value' => $vo]; + } + } + + if (method_exists($this, 'dataInput') && !$this->has) { + $data = $this->dataInput($data); + } + $inputs[$this->field] = ['value' => $data, 'has' => $this->has, 'format' => $this->getFormat($time), 'verify' => $this->getVerify($time), 'pivot' => $this->pivot]; + + return $inputs; + } + + /** + * 获取帮助信息 + * @return string|array + */ + public function getHelp() + { + return $this->help; + } + + /** + * 获取顺序 + * @return null + */ + public function getSort(): ?int + { + return $this->sort; + } + + /** + * 复合组件 + * @return bool + */ + public function getComponent(): bool + { + return $this->component; + } + + /** + * 获取渲染组件 + * @return array + */ + public function getRender(): array + { + if ($this->class) { + $this->attr['class'] = implode(' ', $this->class); + } + return array_merge($this->render(), $this->attr); + } + + + /** + * 获取数据值 + * @param $info + * @return array + */ + public function getData($info): array + { + $field = $this->getHas() ?: $this->getField(); + $value = Tools::parsingArrData($info, $field); + $data = []; + if (method_exists($this, 'appendValue')) { + $appendValue = $this->appendValue($info); + foreach ($appendValue as $key => $vo) { + $data[$key] = $vo; + } + } + if (method_exists($this, 'dataValue')) { + $value = $this->dataValue($value, $info); + } else { + $value = $this->getValue($value); + } + $data[$this->getField()] = $value; + + return $data; + } + + +} diff --git a/admin/components/UI/Form/Email.php b/admin/components/UI/Form/Email.php new file mode 100644 index 0000000..3523c19 --- /dev/null +++ b/admin/components/UI/Form/Email.php @@ -0,0 +1,36 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->object = new Text($this->name, $this->field, $this->has); + $this->object->afterIcon('email'); + } + + /** + * @return array + */ + public function render(): array + { + return $this->object->getRender(); + } + +} diff --git a/admin/components/UI/Form/File.php b/admin/components/UI/Form/File.php new file mode 100644 index 0000000..e8faf8c --- /dev/null +++ b/admin/components/UI/Form/File.php @@ -0,0 +1,84 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * 上传方式 + * @param string $type + * @return $this + */ + public function type(string $type = 'upload'): self + { + $this->type = $type; + return $this; + } + + /** + * 上传地址 + * @param string $url + * @return $this + */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * 文件地址 + * @param string $url + * @return $this + */ + public function fileUrl(string $url): self + { + $this->fileUrl = $url; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'app-file', + ]; + if ($this->url) { + $data['upload'] = $this->url; + } + if ($this->fileUrl) { + $data['fileUrl'] = $this->fileUrl; + } + if ($this->type) { + $data['type'] = $this->type; + } + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + return $data; + } + +} diff --git a/admin/components/UI/Form/Files.php b/admin/components/UI/Form/Files.php new file mode 100644 index 0000000..025e309 --- /dev/null +++ b/admin/components/UI/Form/Files.php @@ -0,0 +1,85 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * 上传方式 + * @param string $type + * @return $this + */ + public function type(string $type = 'manage'): self + { + $this->type = $type; + return $this; + } + + /** + * 上传地址 + * @param string $url + * @return $this + */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * 文件地址 + * @param string $url + * @return $this + */ + public function fileUrl(string $url): self + { + $this->fileUrl = $url; + return $this; + } + + /** + * @return string[] + */ + public function render(): array + { + $data = [ + 'nodeName' => 'app-files', + ]; + if ($this->type) { + $data['type'] = $this->type; + } + if ($this->url) { + $data['upload'] = $this->url; + } + if ($this->fileUrl) { + $data['fileUrl'] = $this->fileUrl; + } + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + + return $data; + } + +} diff --git a/admin/components/UI/Form/Html.php b/admin/components/UI/Form/Html.php new file mode 100644 index 0000000..3309c53 --- /dev/null +++ b/admin/components/UI/Form/Html.php @@ -0,0 +1,40 @@ +name = $name; + $this->callback = $callback; + } + + /** + * @return array + */ + public function render(): array + { + $callback = is_callable($this->callback) ? call_user_func($this->callback) : $this->callback; + + if (is_array($callback)) { + return $callback; + } + return [ + 'nodeName' => 'rich-text', + 'nodes' => $callback + ]; + + } + +} diff --git a/admin/components/UI/Form/Image.php b/admin/components/UI/Form/Image.php new file mode 100644 index 0000000..579dc46 --- /dev/null +++ b/admin/components/UI/Form/Image.php @@ -0,0 +1,124 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * 缩图 + * @param int $width + * @param int $height + * @param string $type + * @return $this + */ + public function thumb(int $width, int $height, string $type = 'scale'): self + { + $this->thumb = [ + 'width' => $width, + 'height' => $height, + 'thumb' => $type + ]; + return $this; + } + + /** + * 水印 + * @param string $position + * @param int $alpha + * @return $this + */ + public function water(string $position = 'center', int $alpha = 80): self + { + $this->water = [ + 'alpha' => $alpha, + 'water' => $position + ]; + return $this; + } + + /** + * @param string $type + * @return $this + */ + public function type(string $type = 'manage'): self + { + $this->type = $type; + return $this; + } + + /** + * 上传地址 + * @param string $url + * @return $this + */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * 文件地址 + * @param string $url + * @return $this + */ + public function fileUrl(string $url): self + { + $this->fileUrl = $url; + return $this; + } + + + /** + * 渲染组件 + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'app-file', + 'format' => 'image', + 'image' => true, + 'size' => 125 + ]; + if ($this->url) { + $data['upload'] = $this->url; + } + if ($this->fileUrl) { + $data['fileUrl'] = $this->fileUrl; + } + if ($this->type) { + $data['type'] = $this->type; + } + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + return $data; + } + +} diff --git a/admin/components/UI/Form/Images.php b/admin/components/UI/Form/Images.php new file mode 100644 index 0000000..7cb3405 --- /dev/null +++ b/admin/components/UI/Form/Images.php @@ -0,0 +1,79 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + public function type($type = 'manage') + { + $this->type = $type; + return $this; + } + + /** + * 上传地址 + * @param string $url + * @return $this + */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * 文件地址 + * @param string $url + * @return $this + */ + public function fileUrl(string $url): self + { + $this->fileUrl = $url; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'app-images', + ]; + if ($this->type) { + $data['type'] = $this->type; + } + if ($this->url) { + $data['upload'] = $this->url; + } + if ($this->fileUrl) { + $data['fileUrl'] = $this->fileUrl; + } + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + + return $data; + } + +} diff --git a/admin/components/UI/Form/Ip.php b/admin/components/UI/Form/Ip.php new file mode 100644 index 0000000..1341e2b --- /dev/null +++ b/admin/components/UI/Form/Ip.php @@ -0,0 +1,35 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->object = new Text($this->name, $this->field, $this->has); + $this->object->afterIcon('desktop'); + } + + /** + * @return array + */ + public function render(): array + { + return $this->object->getRender(); + } + +} diff --git a/admin/components/UI/Form/Layout.php b/admin/components/UI/Form/Layout.php new file mode 100644 index 0000000..c669140 --- /dev/null +++ b/admin/components/UI/Form/Layout.php @@ -0,0 +1,35 @@ +callback = $callback; + } + + /** + * @return array + */ + public function render(): array + { + $callback = is_callable($this->callback) ? call_user_func($this->callback) : $this->callback; + return [ + 'nodeName' => 'div', + 'class' => 'mb-4', + 'child' => $callback + ]; + + } + +} diff --git a/admin/components/UI/Form/Location.php b/admin/components/UI/Form/Location.php new file mode 100644 index 0000000..90a429a --- /dev/null +++ b/admin/components/UI/Form/Location.php @@ -0,0 +1,96 @@ + 'province', + 'city' => 'city', + 'district' => 'district', + 'street' => 'street', + 'streetNumber' => 'streetNumber', + 'address' => 'address', + 'lat' => 'lat', + 'lng' => 'lng' + ]; + /** + * @param string $name + * @param string $field + * @param string $has + */ + public function __construct(string $name, string $field, string $has = '') + { + $this->name = $name; + $this->field = $field; + $this->has = $has; + } + + + /** + * @return array + */ + public function render(): array + { + + $child = []; + + return [ + 'nodeName' => 'app-map', + 'vModel:value' => $this->getModelField(), + 'child' => $child, + 'placeholder' => '请输入' . $this->name, + ]; + } + /** + * @param $data + * @return array + */ + public function appendInput($data): array + { + $ret = []; + if ($data->province) { + $ret[$this->map['province']] = $data->province; + } + if ($data->city) { + $ret[$this->map['city']] = $data->city; + } + if ($data->district) { + $ret[$this->map['district']] = $data->district; + } + if ($data->street) { + $ret[$this->map['street']] = $data->street; + } + if ($data->streetNumber) { + $ret[$this->map['streetNumber']] = $data->streetNumber; + } + if ($data->address) { + $ret[$this->map['address']] = $data->address; + } + if ($data->lat) { + $ret[$this->map['lat']] = $data->lat; + } + if ($data->lng) { + $ret[$this->map['lng']] = $data->lng; + } + return $ret; + } + /** + * @param $data + * @return string|null + */ + public function dataValue($data): ?array + { + $data = $this->getValue($data); + if( empty($data) ){ + return []; + }else{ + return json_decode($data,true); + } + + } +} diff --git a/admin/components/UI/Form/Node.php b/admin/components/UI/Form/Node.php new file mode 100644 index 0000000..f05af5d --- /dev/null +++ b/admin/components/UI/Form/Node.php @@ -0,0 +1,264 @@ +[],'right'=>[]]; + private array $script = []; + private array $scriptReturn = []; + + /** + * Node constructor. + * @param string $action + * @param string $method + * @param string|null $title + */ + public function __construct(string $action, string $method, ?string $title = '') + { + $this->url = $action; + $this->method = $method; + $this->title = $title; + } + + /** + * @param bool $bool + */ + public function back(bool $bool): void + { + $this->back = $bool; + } + + /** + * @param Closure|string $content + * @param string $return + * @return $this + */ + public function script($content, string $return): self + { + if ($content instanceof \Closure) { + $this->script[] = $content(); + } else { + $this->script[] = $content; + } + $this->scriptReturn[] = $return; + return $this; + } + + /** + * @param bool $bool + * @return $this + */ + public function dialog(bool $bool): self + { + $this->dialog = $bool; + $this->vertical = true; + return $this; + } + + /** + * @param bool $bool + * @return $this + */ + public function vertical(bool $bool): self + { + $this->vertical = $bool; + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function element(array $node): self + { + $this->element = $node; + return $this; + } + + /** + * @param Closure|array $node + * @param string $type + * @return $this + */ + public function side($node, string $type = 'left'): self + { + $this->side[$type] = is_callable($node) ? $node() : $node; + return $this; + } + + /** + * @param $data + * @return $this + */ + public function data($data): self + { + $this->data = $data; + return $this; + } + + /** + * 渲染页面 + * @return array[] + */ + private function renderPage(): array + { + return [ + $this->side['left'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none flex h-screen flex-col', + 'child' => $this->side['left'] + ] : [], + [ + 'nodeName' => 'app-layout', + 'class' => 'flex-grow w-10', + 'title' => $this->title ?: '信息详情', + 'form' => true, + 'back' => $this->back, + 'vBind:formLoading' => 'loading', + 'child' => [ + [ + 'nodeName' => 'div', + 'class' => 'p-4', + 'child' => [ + [ + 'nodeName' => 'div', + 'child' => $this->element + ], + [ + 'nodeName' => 'div', + 'class' => 'flex items-center justify-end gap-2 flex-row ', + 'child' => [ + $this->back ? [ + 'nodeName' => 'route', + 'type' => 'back', + 'child' => [ + 'type' => "outline", + 'nodeName' => 'a-button', + 'child' => '返回', + ] + ] : [], + [ + 'nodeName' => 'a-button', + 'html-type' => 'submit', + 'vBind:loading' => "loading", + 'type' => 'primary', + 'child' => $this->back ? '提交' : '保存', + ], + ] + ], + + ], + ], + ], + ], + $this->side['right']? [ + 'nodeName' => 'div', + 'class' => 'flex-none flex h-screen flex-col', + 'child' => $this->side['right'] + ] : [], + ]; + } + + /** + * 渲染弹窗 + * @return array + */ + private function renderDialog(): array + { + + return [ + 'nodeName' => 'app-dialog', + 'title' => $this->title ?: '信息详情', + 'class' => 'flex-grow', + 'child' => [ + [ + 'nodeName' => 'div', + 'vSlot:default' => '', + 'class' => 'flex', + 'child' => [ + $this->side['left'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none', + 'child' => $this->side['left'] + ] : [], + [ + 'nodeName' => 'div', + 'class' => 'flex-grow p-5 pb-0', + 'child' => $this->element + ], + $this->side['right'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none', + 'child' => $this->side['right'] + ] : [] + ] + ], + [ + 'nodeName' => 'div', + 'vSlot:footer' => '', + 'class' => 'arco-modal-footer', + 'child' => [ + [ + 'nodeName' => 'route', + 'type' => 'back', + 'child' => [ + 'nodeName' => 'a-button', + 'child' => '取消' + ] + ], + [ + 'nodeName' => 'a-button', + 'type' => 'primary', + 'html-type' => 'submit', + 'vBind:loading' => "loading", + 'child' => '提交' + ], + ] + ] + ] + + ]; + + } + + /** + * 渲染布局 + * @return array + */ + public function render(): array + { + return [ + 'node' => [ + 'nodeName' => 'app-form', + 'url' => $this->url, + 'method' => $this->method, + 'value' => $this->data, + 'layout' => $this->vertical ? 'vertical' : 'horizontal', + 'back' => $this->back, + 'child' => [ + 'nodeName' => 'div', + 'class' => 'flex', + 'vSlot' => '{value: data, submitStatus: loading}', + 'child' => $this->dialog ? $this->renderDialog() : $this->renderPage() + ] + ], + 'setupScript' => implode("\n", $this->script) . "\n" . ' return {' . implode(",", $this->scriptReturn) . '}' + + ]; + } + +} diff --git a/admin/components/UI/Form/Number.php b/admin/components/UI/Form/Number.php new file mode 100644 index 0000000..b2ee7a9 --- /dev/null +++ b/admin/components/UI/Form/Number.php @@ -0,0 +1,101 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * 最大值 + * @param int|float $default + * @return $this + */ + public function max($default = 0): self + { + $this->max = $default; + return $this; + } + + /** + * 最小值 + * @param int|float $default + * @return $this + */ + public function min($default = 0): self + { + $this->min = $default; + return $this; + } + + /** + * 步进数值 + * @param int|float $default + * @param int|null $precision + * @return $this + */ + public function step($default = 1, ?int $precision = null): self + { + $this->step = $default; + $this->precision = $precision; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-input-number', + 'placeholder' => $this->attr['placeholder'] ?: '请输入' . $this->name, + 'vModel:modelValue' => $this->getModelField(), + 'step' => $this->step, + 'min' => $this->min, + 'mode' => 'button' + ]; + if ($this->max) { + $data['max'] = $this->max; + } + if ($this->precision) { + $data['precision'] = $this->precision; + } + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + return $data; + } + +} diff --git a/admin/components/UI/Form/Password.php b/admin/components/UI/Form/Password.php new file mode 100644 index 0000000..ae723f5 --- /dev/null +++ b/admin/components/UI/Form/Password.php @@ -0,0 +1,48 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-input-password', + 'vModel:modelValue' => $this->getModelField(), + 'placeholder' => $this->attr['placeholder'] ?: '请输入' . $this->name, + 'allowClear' => true + ]; + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + +} diff --git a/admin/components/UI/Form/Radio.php b/admin/components/UI/Form/Radio.php new file mode 100644 index 0000000..3e61409 --- /dev/null +++ b/admin/components/UI/Form/Radio.php @@ -0,0 +1,108 @@ +name = $name; + $this->field = $field; + $this->data = $data; + $this->has = $has; + } + + /** + * 添加选项 + * @param $name + * @param $value + * @return $this + */ + public function add($name, $value): self + { + $this->data[$name] = $value; + return $this; + } + + /** + * 切换组件 + * @param $group + * @return $this + */ + public function switch($group): self + { + $this->switch = $group; + return $this; + } + + /** + * 类型选择 + * @param array $data + * @return $this + */ + public function box(array $data): self + { + $this->box = $data; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + + $data = []; + if ($this->data instanceof \Closure) { + $data = call_user_func($this->data); + } + if (is_array($this->data)) { + $data = $this->data; + } + $this->data = $data; + + + $child = []; + foreach ($data as $key => $vo) { + $child[] = [ + 'nodeName' => 'a-radio', + 'child' => $vo, + 'value' => $key, + ]; + } + + $data = [ + 'nodeName' => 'a-radio-group', + 'name' => $this->field, + 'vModel:modelValue' => $this->getModelField(), + 'child' => $child + ]; + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + public function dataValue($value) + { + return $this->getValue($value) ?? array_key_first((array)$this->data); + } + +} diff --git a/admin/components/UI/Form/Row.php b/admin/components/UI/Form/Row.php new file mode 100644 index 0000000..506ade4 --- /dev/null +++ b/admin/components/UI/Form/Row.php @@ -0,0 +1,54 @@ +column[] = [ + 'width' => $width, + 'object' => $form, + ]; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $inner = []; + foreach ($this->column as $vo) { + $width = $vo['width'] ? "lg:row-span-{$vo['width']}" : ''; + $form = $vo['object']->renderForm(); + $inner[] = [ + 'nodeName' => 'div', + 'class' => $width, + 'child' => $form + ]; + } + + return [ + 'nodeName' => 'div', + 'class' => 'grid lg:grid-flow-col gap-4', + 'child' => $inner + ]; + } + +} diff --git a/admin/components/UI/Form/Select.php b/admin/components/UI/Form/Select.php new file mode 100644 index 0000000..fdbebc3 --- /dev/null +++ b/admin/components/UI/Form/Select.php @@ -0,0 +1,198 @@ +name = $name; + $this->field = $field; + $this->data = $data; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * 添加选项 + * @param $name + * @param $value + * @return $this + */ + public function add($name, $value): self + { + $this->data[$value] = $name; + return $this; + } + + /** + * 默认提示 + * @param bool $tip + * @return $this + */ + public function tip(bool $tip = true): self + { + $this->tip = $tip; + return $this; + } + + /** + * 搜索 + * @param bool $search + * @return $this + */ + public function search(bool $search = true): self + { + $this->search = $search; + return $this; + } + + /** + * 搜索地址 + * @param string $url + * @return $this + */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * 路由地址 + * @param string $route + * @param array $params + * @return $this + */ + public function route(string $route, array $params = []): self + { + $this->route = $route; + $this->url = app_route($route, $params); + return $this; + } + + /** + * 多选 + * @param int $count + * @return $this + */ + public function multi(int $count = 0): self + { + $this->multi = true; + $this->tagCount = $count; + return $this; + } + + /** + * 选项渲染 + * @param array $data JS Node + * @return $this + */ + public function optionRender(array $data): self + { + $this->optionRender = $data; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = []; + if ($this->data instanceof \Closure) { + $data = call_user_func($this->data); + } + if (is_array($this->data)) { + $data = $this->data; + } + $options = []; + if(isset($data[0]['label'])){ + $options=$data; + }else{ + foreach ($data as $key => $vo) { + $options[] = [ + 'label' => $vo, + 'value' => $key + ]; + } + } + + $object = [ + + 'nodeName' => 'app-select', + 'nParams' => [ + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + 'options' => $options + ], + ]; + + if ($this->model) { + $object['vModel:value'] = $this->getModelField(); + } + $object['nParams']['allowClear'] = true; + if ($this->multi) { + $object['nParams']['multiple'] = true; + } + if ($this->url) { + $object['nParams']['allowSearch'] = true; + $object['nParams']['filterOption'] = false; + if ($this->route) { + $object['vBind:dataUrl'] = $this->url; + } else { + $object['dataUrl'] = $this->url; + } + } + if ($this->search) { + $object['nParams']['allowSearch'] = true; + } + if ($this->tagCount) { + $object['nParams']['maxTagCount'] = $this->tagCount; + } + if ($this->optionRender) { + $object['vRender:optionRender:item'] = $this->optionRender; + } + + return $object; + } + + /** + * @param $value + * @return array|mixed + */ + public function dataValue($value) + { + return $this->multi ? array_values(array_filter((array)$this->getValueArray($value))) : $this->getValue($value); + } + + /** + * @param $data + * @return string + */ + public function dataInput($data): ?string + { + return is_array($data) ? implode(',', $data) : $data; + } + +} diff --git a/admin/components/UI/Form/Tab.php b/admin/components/UI/Form/Tab.php new file mode 100644 index 0000000..a834e1f --- /dev/null +++ b/admin/components/UI/Form/Tab.php @@ -0,0 +1,99 @@ +dialog($this->dialog); + $form->vertical($this->vertical); + $callback($form); + $this->column[] = [ + 'name' => $name, + 'title' => $title, + 'desc' => $desc, + 'order' => $order ?? (count($this->column) + 1), + 'object' => $form, + + ]; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + + $nodes = []; + + $column = collect($this->column)->sortBy('order')->toArray(); + + foreach ($column as $key => $vo) { + + $child = []; + if ($vo['title']) { + $child[] = [ + 'nodeName' => 'div', + 'class' => 'py-4 flex flex-col gap-2', + 'child' => [ + [ + 'nodeName' => 'div', + 'class' => 'text-xl', + 'child' => $vo['title'], + ], + [ + 'nodeName' => 'div', + 'class' => 'text-gray-500', + 'child' => $vo['desc'], + ] + ] + ]; + } + $child[] = [ + 'nodeName' => 'div', + 'class' => 'pt-2', + 'child' => $vo['object']->renderForm() + ]; + + $nodes[] = [ + 'nodeName' => 'a-tab-pane', + 'title' => $vo['name'], + 'key' => $key, + 'class' => !$this->dialog ? ' border-t border-gray-200 dark:border-blackgray-1 px-3 pt-4 pb-0' : '', + 'child' => [ + 'nodeName' => 'div', + 'class' => '', + 'child' => $child + ] + ]; + } + + return [ + 'nodeName' => 'a-tabs', + 'class' => !$this->dialog ? 'mb-4 bg-white dark:bg-blackgray-4 rounded shadow p-4 pb-1' : '', + 'type' => 'rounded', + 'child' => $nodes + ]; + + } + +} diff --git a/admin/components/UI/Form/Tags.php b/admin/components/UI/Form/Tags.php new file mode 100644 index 0000000..8574738 --- /dev/null +++ b/admin/components/UI/Form/Tags.php @@ -0,0 +1,78 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * @param $num + * @return $this + */ + public function limit($num): self + { + $this->limit = $num; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-input-tag', + 'vModel:modelValue' => $this->getModelField(), + 'placeholder' => $this->attr['placeholder'] ?: '请输入' . $this->name, + 'allowClear' => true + ]; + if ($this->limit) { + $data['maxTagCount'] = $this->limit; + } + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + /** + * @param $value + * @return array + */ + public function dataValue($value): array + { + return array_values(array_filter((array)$this->getValueArray($value))); + } + + /** + * @param $data + * @return string + */ + public function dataInput($data): ?string + { + return is_array($data) ? implode(',', $data) : $data; + } + +} diff --git a/admin/components/UI/Form/Tel.php b/admin/components/UI/Form/Tel.php new file mode 100644 index 0000000..8e22dd4 --- /dev/null +++ b/admin/components/UI/Form/Tel.php @@ -0,0 +1,48 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->object = new Text($this->name, $this->field, $this->has); + $this->object->afterIcon('phone'); + } + + /** + * 设置掩码 + * @param $value + * @return $this + */ + public function mask($value): self + { + $this->mask = (string) $value; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $this->object->attrArray($this->attr); + return $this->object->getRender(); + } + +} diff --git a/admin/components/UI/Form/Text.php b/admin/components/UI/Form/Text.php new file mode 100644 index 0000000..3c5edb4 --- /dev/null +++ b/admin/components/UI/Form/Text.php @@ -0,0 +1,121 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * 文本类型 + * @param $name + * @return $this + */ + public function type($name): self + { + $this->type = $name; + return $this; + } + + /** + * 前置图标 + * @param $content + * @return $this + */ + public function beforeIcon($content): self + { + $this->before = (new Icon($content))->attr('vSlot:prepend', '')->getRender(); + return $this; + } + + /** + * 后置图标 + * @param $content + * @return $this + */ + public function afterIcon($content): self + { + $this->after = (new Icon($content))->attr('vSlot:append', '')->getRender(); + return $this; + } + + /** + * 前置文本 + * @param $content + * @return $this + */ + public function beforeText($content): self + { + $this->before = [ + 'vSlot:prepend' => '', + 'nodeName' => 'span', + 'child' => $content + ]; + return $this; + } + + /** + * 后置文本 + * @param $content + * @return $this + */ + public function afterText($content): self + { + $this->after = [ + 'vSlot:append' => '', + 'nodeName' => 'span', + 'child' => $content + ]; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + + $child = []; + if ($this->before || $this->after) { + $child = [ + $this->before, + $this->after + ]; + } + + $data = [ + 'nodeName' => 'a-input', + 'vModel:modelValue' => $this->getModelField(), + 'child' => $child, + 'placeholder' => '请输入' . $this->name + ]; + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + +} diff --git a/admin/components/UI/Form/Textarea.php b/admin/components/UI/Form/Textarea.php new file mode 100644 index 0000000..2c3f29b --- /dev/null +++ b/admin/components/UI/Form/Textarea.php @@ -0,0 +1,62 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * @param $num + * @return $this + */ + public function limit($num): self + { + $this->limit = $num; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-textarea', + 'vModel:modelValue' => $this->getModelField(), + 'placeholder' => $this->attr['placeholder'] ?: '请输入' . $this->name, + 'allowClear' => true, + 'showWordLimit' => true + ]; + if ($this->limit) { + $data['maxLength'] = $this->limit; + } + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + +} diff --git a/admin/components/UI/Form/Time.php b/admin/components/UI/Form/Time.php new file mode 100644 index 0000000..867ea71 --- /dev/null +++ b/admin/components/UI/Form/Time.php @@ -0,0 +1,53 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->attr['placeholder'] = null; + } + + /** + * 时间格式 + * @param string $format + * @return $this + */ + public function string(string $format): self + { + $this->string = $format; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + return [ + 'nodeName' => 'a-time-picker', + 'allowClear' => true, + 'format' => $this->string, + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + 'vModel:model-value' => $this->getModelField() + ]; + } + +} diff --git a/admin/components/UI/Form/Toggle.php b/admin/components/UI/Form/Toggle.php new file mode 100644 index 0000000..b779ac1 --- /dev/null +++ b/admin/components/UI/Form/Toggle.php @@ -0,0 +1,67 @@ +name = $name; + $this->field = $field; + $this->has = $has; + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => 'a-switch', + 'vModel:modelValue' => $this->getModelField(), + 'checkedValue' => $this->checkedValue, + 'uncheckedValue' => $this->uncheckedValue + ]; + + if($this->replace != ''){ + $data['vStringReplace'] = $this->replace; + } + + return $data; + } + + /** + * 开关数据 + * @param string|number|boolean $checkedValue + * @param string|number|boolean $uncheckedValue + * @return $this + */ + public function data($checkedValue,$uncheckedValue){ + $this->checkedValue = $checkedValue; + $this->uncheckedValue = $uncheckedValue; + return $this; + } + + /** + * @param $data + * @return int + */ + public function dataInput($data): int + { + return $data ? 1 : 0; + } + +} diff --git a/admin/components/UI/Form/Tree.php b/admin/components/UI/Form/Tree.php new file mode 100644 index 0000000..804cb65 --- /dev/null +++ b/admin/components/UI/Form/Tree.php @@ -0,0 +1,96 @@ +name = $name; + $this->field = $field; + $this->data = $data; + $this->has = $has; + } + + /** + * @return array + */ + public function render(): array + { + $data = $this->data; + if ($this->data instanceof \Closure) { + $data = call_user_func($this->data); + } + if ($data instanceof \Illuminate\Database\Eloquent\Collection) { + $data = $data->toArray(); + } + + $data = $this->loop($data); + $data = [ + 'nodeName' => 'div', + 'class' => 'bg-gray-100 dark:bg-blackgray-2 p-2 rounded w-full h-56 overflow-y-auto app-scrollbar', + 'child' => [ + 'nodeName' => 'a-tree', + 'blockNode' => true, + 'checkable' => true, + 'showLine' => true, + 'vModel:checked-keys' => $this->getModelField(), + 'data' => $data, + ] + ]; + return $data; + } + + /** + * @param $value + * @return array|null + */ + public function dataValue($value): ?array + { + return $this->getValueArray($value); + } + + /** + * @param $data + * @return string + */ + public function dataInput($data): ?string + { + return is_array($data) ? implode(',', $data) : ''; + } + + /** + * @param $data + * @return array + */ + protected function loop($data): array + { + $newData = []; + foreach ($data as $item) { + $tmpData = [ + 'title' => $item['name'], + 'key' => $item['id'], + ]; + if ($item['children']) { + $tmpData['children'] = $this->loop($item['children']); + } + $newData[] = $tmpData; + } + return $newData; + } + +} diff --git a/admin/components/UI/Form/TreeSelect.php b/admin/components/UI/Form/TreeSelect.php new file mode 100644 index 0000000..48b2846 --- /dev/null +++ b/admin/components/UI/Form/TreeSelect.php @@ -0,0 +1,183 @@ +name = $name; + $this->field = $field; + $this->data = $data; + $this->has = $has; + $this->attr['placeholder'] = null; + + } + + /** + * 添加选项 + * @param $name + * @param $id + * @param $pid + * @return $this + */ + public function add($name, $id, $pid): self + { + $this->data[] = [ + 'name' => $name, + 'id' => $id, + 'pid' => $pid + ]; + return $this; + } + + + /** + * 设置动态地址 + * @param string $url + * @return $this + */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * @param string $route + * @param array $params + * @return $this + */ + public function route(string $route, array $params = []): self + { + $this->route = $route; + $this->url = app_route($route, $params); + return $this; + } + + /** + * 多选组件 + * @return $this + */ + public function multi(): self + { + $this->multi = true; + return $this; + } + + /** + * 树形模式 + * @param bool $bool + * @return $this + */ + public function tree(bool $bool = true): self + { + $this->treeData = $bool; + return $this; + } + + + /** + * 回填方式 + * @param string $model + * @return $this + */ + public function strategy(string $model): self + { + $this->strategy = $model; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + + $data = []; + if ($this->data instanceof \Closure) { + $data = call_user_func($this->data, $this); + } + if (is_array($this->data)) { + $data = $this->data; + } + + if (!$this->treeData) { + $options = []; + foreach ($data as $vo) { + $options[] = [ + 'id' => $vo['id'], + 'pid' => $vo['pid'], + 'value' => $vo['id'], + 'label' => $vo['name'], + ]; + } + $options = \backend\components\Util\Tree::arr2tree($options, 'id', 'pid', 'children'); + + } else { + $options = $data; + } + + $data = [ + 'nodeName' => 'app-tree-select', + 'nParams' => [ + 'multiple' => $this->multi, + 'treeCheckable' => $this->multi, + 'treeCheckedStrategy' => $this->strategy, + 'data' => $options, + 'placeholder' => $this->attr['placeholder'] ?: '请选择' . $this->name, + + ] + ]; + + if ($this->route) { + $data['vBind:dataUrl'] = $this->url; + } else { + $data['dataUrl'] = $this->url; + } + + if ($this->model) { + $data['vModel:value'] = $this->getModelField(); + } + + return $data; + } + + /** + * @param $value + * @return array|mixed + */ + public function dataValue($value) + { + return $this->multi ? array_values(array_filter((array)$this->getValueArray($value))) : $this->getValue($value); + } + + /** + * @param $data + * @return string + */ + public function dataInput($data): ?string + { + return is_array($data) ? implode(',', $data) : $data; + } + +} diff --git a/admin/components/UI/Form/Url.php b/admin/components/UI/Form/Url.php new file mode 100644 index 0000000..18bbeb9 --- /dev/null +++ b/admin/components/UI/Form/Url.php @@ -0,0 +1,37 @@ +name = $name; + $this->field = $field; + $this->has = $has; + $this->object = new Text($this->name, $this->field, $this->has); + $this->object->beforeText('http(s)'); + } + + /** + * @return array + */ + public function render(): array + { + $this->object->attrArray($this->attr); + return $this->object->getRender(); + } + +} diff --git a/admin/components/UI/Layout.php b/admin/components/UI/Layout.php new file mode 100644 index 0000000..ff264ed --- /dev/null +++ b/admin/components/UI/Layout.php @@ -0,0 +1,49 @@ +title = $title; + } + public $child = []; + function setup(string $script) + { + // TODO: Implement setup() method. + } + public function addChild($node){ + + $this->child[] = $node; + } + + function render() + { + return ['node'=>[ + "nodeName" => "div", + "class" => "flex h-screen", + "vSlot" => "{value: data}", + "child" => [ + [ + 'nodeName' => $this->name, + 'class' => $this->class, + 'title' => $this->title, + 'child' => [ + [ + 'nodeName' => 'div', + 'class' => 'p-4', + 'child' => $this->child + ] + ] + ] + ], + 'setupScript'=>"\n return {}" + ]]; + // TODO: Implement render() method. + } +} diff --git a/admin/components/UI/Node.php b/admin/components/UI/Node.php new file mode 100644 index 0000000..827c0cd --- /dev/null +++ b/admin/components/UI/Node.php @@ -0,0 +1,38 @@ +nodes as $vo) { + $data[] = $vo->render(); + } + return $data; + } + + /** + * @param $method + * @param $arguments + * @return NodeEl + */ + public function __call($method, $arguments) + { + $nodeEl = new NodeEl($method, $arguments[0]); + $this->nodes[] = $nodeEl; + return $nodeEl; + } +} diff --git a/admin/components/UI/Node/NodeEl.php b/admin/components/UI/Node/NodeEl.php new file mode 100644 index 0000000..c8374cd --- /dev/null +++ b/admin/components/UI/Node/NodeEl.php @@ -0,0 +1,56 @@ +name = $name; + if ($callback instanceof \Closure) { + $node = new Node(); + $callback($node); + $this->callback = $node; + }else { + $this->callback = $callback; + } + } + + /** + * @return array + */ + public function render(): array + { + $data = [ + 'nodeName' => $this->name, + ]; + if ($this->callback instanceof Node) { + $data['child'] = $this->callback->render(); + } else if ($this->callback) { + $data['child'] = $this->callback; + } + return array_merge($data, $this->attr); + } + + + public function __call($method, $arguments) + { + $this->attr[$method] = $arguments[0]; + return $this; + } +} diff --git a/admin/components/UI/Table.php b/admin/components/UI/Table.php new file mode 100644 index 0000000..5e83881 --- /dev/null +++ b/admin/components/UI/Table.php @@ -0,0 +1,847 @@ +model = $data; + $this->query = $data::find(); + $this->fields = $data::getTableSchema()->getColumnNames(); + } else { + $this->data = $data; + } + $this->columns = Collection::make(); + $this->filters = Collection::make(); + $this->filtersType = Collection::make(); + + if (\Yii::$app->request->getHeaders()->has('x-dialog')) { + $this->dialog = true; + } + } + + public function filterLayout($filterLayout): self + { + $this->filterLayout = $filterLayout; + return $this; + } + + /** + * 设置列 + * @param string $name + * @param string $label + * @param null $callback + * @return Column + */ + public function column(string $label = '', string $name = '', $callback = null): Column + { + ////关联模型 + //if ($this->model && Str::contains($name, '.')) { + // return $this->joinColumn($label, $name, $callback); + //} + + //数组对象 + //if (Str::contains($name, '->')) { + // $name = str_replace('->', '.', $name); + return $this->addColumn($label, $name, $callback); + //} + + ////是否关联模型 + //if ($this->model && $this->hasRelationColumn($label)) { + // $this->model->has($label); + // return $this->addColumn($name, $label, $callback)->setRelation($label); + //} + return $this->addColumn($label, $name, $callback); + } + public function addColumns($fields){ + $labels = $this->model->attributeLabels(); + foreach ($fields as $field){ + $this->column($labels[$field],$field); + } + return true; + } + + /** + * 展开行 + * @param string $title + * @param array $node + * @param int $width + * @return $this + */ + public function expand(string $title = '', array $node = [], int $width = 100): self + { + $this->expand = [ + 'title' => $title, + 'width' => $width, + 'vRender:expandedRowRender:rowData' => $node + ]; + return $this; + } + + /** + * 添加列参数 + * @param $name + * @param $label + * @param $callback + * @return Column + */ + protected function addColumn($name, $label, $callback): Column + { + $column = new Column($name, $label, $callback); + $column->setLayout($this); + return tap($column, function ($value) { + $this->columns->push($value); + }); + } + + /** + * 判断关联模型 + * @param $relation + * @return bool + */ + protected function hasRelationColumn($relation): bool + { + if (!method_exists($this->model, $relation)) { + return false; + } + if (!$this->model->{$relation}() instanceof \Illuminate\Database\Eloquent\Relations\Relation) { + return false; + } + return true; + } + + /** + * 关联模型 + * @param $name + * @param $label + * @param $callback + * @return Column + */ + protected function joinColumn($name, $label, $callback): Column + { + [$relation, $field] = explode('.', $label, 2); + $this->query->with($relation); + return $this->addColumn($name, str_replace('->', '.', $field), $callback)->setRelation($relation); + } + + /** + * 获取列集合 + * @return Collection + */ + protected function getColumns(): Collection + { + return $this->columns; + } + + /** + * 设置行数据 + * @param \Closure $callback + * @return $this + */ + public function row(\Closure $callback): self + { + $this->rows[] = $callback; + return $this; + } + + /** + * 设置字段映射 + * @param array $map + * @return $this + */ + public function map(array $map): self + { + $this->map = array_merge($this->map, $map); + return $this; + } + + /** + * 筛选参数 + * @param $key + * @param $value + * @return $this + */ + public function filterParams($key, $value): self + { + $this->filterParams[$key] = $value; + return $this; + } + + /** + * 自定义头 + * @param string|callable|object $callback + * @return $this + */ + public function header($callback): self + { + $this->headerNode[] = $callback; + return $this; + } + + /** + * 自定义底部 + * @param string|callable|object $callback + * @return $this + */ + public function footer($callback): self + { + $this->footerNode[] = $callback; + return $this; + } + + /** + * 自定义侧边 + * @param $callback + * @param string $direction + * @param bool $resize + * @param string $width + * @return $this + */ + public function side($callback, string $direction = 'left', bool $resize = false, string $width = '100px'): self + { + $this->sideNode[] = [ + 'callback' => $callback, + 'direction' => $direction, + 'resize' => $resize, + 'width' => $width + ]; + return $this; + } + + /** + * 自定义page内容 + * @param $callback + * @param string $direction + * @return $this + */ + public function page($callback, string $direction = 'left'): self + { + $this->pageNode[] = [ + 'callback' => $callback, + 'direction' => $direction + ]; + return $this; + } + + /** + * 设置样式class + * @param string $class + * @return $this + */ + public function class(string $class): self + { + $this->class[] = $class; + return $this; + } + + /** + * 设置绑定方式 + * @param $urlBind true 使用url绑定控件 + * @return $this + */ + public function urlBind($urlBind): self + { + $this->urlBind = $urlBind; + return $this; + } + + /** + * 设置请求事件绑定名称 + * @param string|null $eventName + * @return $this + */ + public function eventName(?string $eventName): self + { + $this->eventName = $eventName; + return $this; + } + + /** + * 设置筛选条件 + * @param string $name + * @param string $field + * @param bool $where + * @param null $default + * @return Filter + */ + public function filter(string $name, string $field, $where = true, $default = null): Filter + { + $filter = new \backend\components\UI\Table\Filter($name, $field, $where, $default); + $filter->setLayout($this); + return tap($filter, function ($value) { + $this->filters->push($value); + }); + } + + + /** + * 筛选类型 + * @param string $name + * @param callable|null $where + * @return FilterType + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + */ + public function filterType(string $name, callable $where = null): FilterType + { + if (!isset($this->filterParams['type'])) { + $this->filterParams('type', \Yii::$app->request->get('type', 0)); + } + $filterType = new \backend\components\UI\Table\FilterType($name, $where, $this->filterParams['type']); + $filterType->setLayout($this); + return tap($filterType, function ($value) { + $this->filtersType->push($value); + }); + } + + /** + * 设置动作 + * @return Action + */ + public function action(): Action + { + if (!$this->action) { + $this->action = new Action(); + } + return $this->action; + } + + /** + * 批量操作 + * @return Batch + */ + public function batch(): Batch + { + if (!$this->batch) { + $this->batch = new Batch(); + } + return $this->batch; + } + + /** + * 树形表格 + * @return $this + */ + public function tree(): self + { + $this->tree = true; + return $this; + } + + /** + * 树形状态 + * @return bool + */ + public function getTree(): bool + { + return $this->tree; + } + + /** + * 表格标题 + * @param string $title + * @return $this + */ + public function title(string $title): self + { + $this->title = $title; + return $this; + } + + /** + * 分页数量 + * @param int $num + * @return $this + */ + public function limit(int $num): self + { + $this->limit = $num; + return $this; + } + + /** + * 模型对象 + */ + public function model(): ActiveQuery + { + return $this->query; + } + + /** + * 模型对象 + * @return ActiveRecord + */ + public function modelElo(): ?ActiveRecord + { + return $this->model; + } + + /** + * 设置附加属性 + * @param $name + * @param $value + * @return $this + */ + public function attr($name, $value): self + { + $this->attr[$name] = $value; + return $this; + } + + /** + * 窗口滚动参数 + * @param $x + * @param $y + * @return $this + */ + public function scroll($x,$y){ + return $this->attr('scroll',['x' => $x,'y' => $y]); + } + + /** + * 设置表格主键 + * @param $key + * @return $this + */ + public function key($key): self + { + $this->key = $key; + return $this; + } + + /** + * 弹窗 + * @param bool $status + * @return $this + */ + public function dialog(bool $status = true): self + { + $this->dialog = $status; + return $this; + } + + public function isDialog(){ + return $this->dialog; + } + + /** + * url数据 + * @param string $url + * @return $this + */ + public function url(string $url = ''): self + { + $this->url = $url; + return $this; + } + + /** + * 获取Url + * @return string + */ + public function getUrl(): string + { + return $this->url; + } + + /** + * @param string $content + * @param string $return + * @return $this + */ + public function script(string $content = '', string $return = ''): self + { + $this->script[] = $content; + $this->scriptReturn[] = $return; + return $this; + } + + /** + * @param $data + * @return $this + */ + public function scriptData($data): self + { + $this->scriptData = array_merge($this->scriptData, $data); + return $this; + } + + /** + * 数据导出 + * @param callable $callback + */ + public function export(callable $callback): void + { + // 设置筛选信息 + $this->filters->map(function ($filter) { + return $filter->render(); + }); + // 设置筛选类型 + $this->filtersType->map(function ($filter, $key) { + return $filter->render($key); + }); + // 查询导出数据 + $data = $this->query->all(); + // 执行渲染输出 + $export = new \backend\components\UI\Table\Export(); + $callback($export); + $export->render($data); + } + + /** + * 数据回调 + * @param callable $callback + * @return $this + */ + public function dataCallback(callable $callback): self + { + $this->dataCallback = $callback; + return $this; + } + + /** + * 渲染列node + * @return array + */ + public function renderColumn(): array + { + return $this->getColumns()->map(function ($column, $key) { + $render = $column->getRender(); + if (!empty($render)) { + $render['sort'] = $render['sort'] ?? $key; + return $render; + } + })->filter()->sortBy('sort')->values()->toArray(); + } + + /** + * 渲染组件 + * @return Node + */ + private function renderNode() + { + // 扩展节点 + $headerNode = []; + foreach ($this->headerNode as $vo) { + $headerNode[] = is_callable($vo) ? $vo() : $vo; + } + $footerNode = []; + foreach ($this->footerNode as $vo) { + $footerNode[] = is_callable($vo) ? $vo() : $vo; + } + // 动作节点 + $actionNode = $this->action ? $this->action()->render() : []; + // 批处理节点 + $batchNode = $this->batch ? $this->batch()->render() : []; + // 类型筛选 + $typeNode = $this->filtersType->map(function ($filter, $key) { + return $filter->render($key); + })->toArray(); + // 筛选数据 + $filters = $this->filters->map(function ($filter) { + return $filter->render(); + })->toArray(); + $filterNode = []; + $quickNode = []; + foreach ($filters as $vo) { + if (isset($vo['quick']) && $vo['quick']) { + $quickNode[] = $vo['render']; + } else { + $filterNode[] = $vo['render']; + } + } + // 表格列节点 + $columnNode = $this->getColumns()->map(function ($column, $key) { + $render = $column->getRender(); + if (!empty($render)) { + $render['sort'] = $render['sort'] ?? $key; + return $render; + } + })->filter()->sortBy('sort')->values()->toArray(); + $keyName = $this->key ?: ($this->model ? $this->model->getPrimaryKey() : null); + $node = new Node($this->url ?: \Yii::$app->urlManager->createUrl(\Yii::$app->request->getPathInfo() . '/ajax'), $keyName, $this->title); + $node->urlBind($this->urlBind); + $node->class(implode(' ', $this->class)); + $node->params($this->attr); + $node->data($this->filterParams); + $node->columns($columnNode); + $node->expand($this->expand); + $node->eventName($this->eventName); + + foreach ($this->script as $key => $value) { + $node->script($value, $this->scriptReturn[$key]); + } + if ($this->scriptData) { + $node->scriptData($this->scriptData); + } + + $node->type($typeNode); + $node->quickFilter($quickNode); + $node->filter($filterNode); + $node->filterLayout($this->filterLayout); + foreach ($this->sideNode as $vo) { + $node->side($vo['callback'], $vo['direction'], $vo['resize'], $vo['width']); + } + foreach ($this->pageNode as $vo) { + $node->page($vo['callback'], $vo['direction']); + } + + $node->header($headerNode); + $node->footer($footerNode); + + if ($actionNode) { + $node->action($actionNode); + } + if ($batchNode) { + $node->bath($batchNode); + } + + return $node; + } + + /** + * 渲染表格(数组) + * @return array + */ + public function renderArray() + { + $node = $this->renderNode(); + return $node->render(); + } + + /** + * 只渲染table + * @return array + */ + public function renderTableCore() + { + $node = $this->renderNode(); + return $node->renderTableCore(); + } + + /** + * 数据渲染 + * @return array + */ + public function renderAjax() + { + // 筛选数据 + $this->filters->map(function ($filter) { + $filter->execute($this->query); + }); + $this->filtersType->map(function ($filter, $key) { + $filter->execute($this->query, $key); + }); + + // 列筛选数据 + if ($this->columns) { + $this->columns->map(function ($column) { + if (method_exists($column, 'execute')) { + $column->execute($this->query); + } + }); + } + + //主键 + $key = $this->key ?: ($this->model ? $this->model->getPrimaryKey() : ''); + + $limit = \Yii::$app->request->get('limit', $this->limit); + + // 查询列表 + if ($this->query) { + $data = $this->query; + if ($this->tree) { + $data = $data->paginate(99999)->eloquent(); + $data->setCollection($data->getCollection()->toTree()); + } else { + $data = $data->paginate($limit)->eloquent(); + } + } else { + $data = $this->paginateCollection($this->data, $limit); + if ($this->tree) { + $data->setCollection(collect(Tree::arr2table($data->getCollection()->toArray(), $key, 'parent_id'))); + } + } + if ($this->dataCallback) { + $dataCallback = call_user_func($this->dataCallback, $data->getCollection()); + $data->setCollection($dataCallback); + } + + $totalPage = $data->lastPage(); + $page = $data->currentPage(); + $total = $data->total(); + + + $columns = []; + if ($this->columns) { + $columns = $this->columns->map(function ($column) { + return $column; + })->filter(); + } + + + // 设置行数据回调 + $this->map[] = $key; + + // 排序自动设置key + if ($this->tree) { + $this->map['key'] = $key; + } + + $resetData = $this->formatData($data, $columns,$this->tree); + + return app_success('ok', [ + 'data' => $resetData, + 'total' => $total, + 'pageSize' => $limit, + 'totalPage' => $totalPage, + ]); + } + + /** + * 渲染行数据 + * @param Collection $data + * @param bool $tree + * @return array + */ + public function renderRowData(Collection $data, bool $tree = true): array + { + if ($this->dataCallback) { + $data = call_user_func($this->dataCallback, $data); + } + $key = $this->key ?: ($this->model ? $this->model->getPrimaryKey() : ''); + $columns = []; + if ($this->columns) { + $columns = $this->columns->map(function ($column) { + return $column; + })->filter(); + } + // 设置行数据回调 + $this->map[] = $key; + + // 排序自动设置key + if ($this->tree) { + $this->map['key'] = $key; + } + return $this->formatData($data, $columns, $tree); + + } + + /** + * @param $data + * @param $columns + * @param bool $tree + * @return array + */ + private function formatData($data, $columns, bool $tree = true): array + { + $resetData = []; + foreach ($data as $vo) { + $rowData = []; + if ($this->rows) { + foreach ($this->rows as $row) { + if ($call = call_user_func($row, $vo)) { + $rowData = $call; + } + } + } + foreach ($columns as $column) { + if ($colData = $column->getData($vo)) { + foreach ($colData as $k => $v) { + $rowData[$k] = $v; + } + } + } + if ($this->map) { + foreach ($this->map as $k => $v) { + $rowData[is_int($k) ? str_replace(['.', '->'], '_', $v) : $k] = is_callable($v) ? call_user_func($v, $vo) : Tools::parsingArrData($vo, $v); + } + } + if ($vo['children'] && $tree) { + $rowData['children'] = $this->formatData($vo['children'], $columns, $tree); + } + $resetData[] = $rowData; + } + return $resetData; + } + + /** + * 集合分页 + * @param $collection + * @param $perPage + * @param string $pageName + * @param null $fragment + */ + protected function paginateCollection($collection, $perPage, $pageName = 'page', $fragment = null): ActiveDataProvider + { + parse_str(\Yii::$app->request->getQueryString(), $query); + unset($query[$pageName]); + return new ActiveDataProvider([ + 'query' => $query, + 'pagination' => [ + 'pageSize' => 20, + ], + ] + ); + } +} diff --git a/admin/components/UI/Table/Action.php b/admin/components/UI/Table/Action.php new file mode 100644 index 0000000..8c87e8b --- /dev/null +++ b/admin/components/UI/Table/Action.php @@ -0,0 +1,65 @@ +button($type); + $this->button[] = $link; + return $link; + } + + /** + * 菜单按钮 + * @param string $name + * @param string $type + * @return Menu + */ + public function menu(string $name, string $type = 'default'): Menu + { + $menu = new Menu($name, $type); + $this->menu[] = $menu; + return $menu; + } + + /** + * 渲染组件 + * @return array + */ + public function render(): array + { + $node = []; + foreach ($this->menu as $menu) { + $node[] = $menu->getRender(); + } + foreach ($this->button as $class) { + $node[] = $class->getRender(); + } + return $node; + } + +} diff --git a/admin/components/UI/Table/Batch.php b/admin/components/UI/Table/Batch.php new file mode 100644 index 0000000..1f271e7 --- /dev/null +++ b/admin/components/UI/Table/Batch.php @@ -0,0 +1,87 @@ +nodes[] = [ + 'nodeName' => 'a-button', + 'type' => 'secondary', + 'status' => $btnType, + 'child' => $name, + 'vOn:click' => "footer.checkAction('$url', '确定执行$name\操作?')" + ]; + return $this; + } + + /** + * @param string $name + * @param string $route + * @param array $params + * @return $this + */ + public function select(string $name, string $route = '', array $params = []): self + { + $url = route($route, $params); + $this->select[] = [ + 'nodeName' => 'a-doption', + 'child' => $name, + 'vOn:click' => "footer.checkAction('$url' '确定执行$name\操作?')" + ]; + return $this; + } + + /** + * 渲染组件 + * @return array + */ + public function render(): array + { + if ($this->select) { + $this->nodes[] = [ + 'nodeName' => 'a-dropdown', + 'child' => [ + [ + 'nodeName' => 'a-button', + 'type' => 'secondary', + 'child' => '批量操作', + ], + [ + 'vSlot:content' => '', + 'nodeName' => 'div', + 'child' => $this->select + ] + ], + ]; + } + + return $this->nodes; + } + +} diff --git a/admin/components/UI/Table/Column.php b/admin/components/UI/Table/Column.php new file mode 100644 index 0000000..75e7aab --- /dev/null +++ b/admin/components/UI/Table/Column.php @@ -0,0 +1,467 @@ +name = $name; + $this->label = $label; + $this->callback = $callback; + } + + /** + * 设置父级对象 + * @param Table $layout + */ + public function setLayout(Table $layout): void + { + $this->layout = $layout; + } + + /** + * 关联数据 + * @param $relation + * @return $this + */ + public function setRelation($relation): self + { + $this->relation = $relation; + return $this; + } + + /** + * 宽度 + * @param $width + * @return $this + */ + public function width($width): self + { + $this->width = $width; + return $this; + } + + /** + * 自定义节点数据 + * @param $node + * @return $this + */ + public function node($node): self + { + $this->node = $node; + return $this; + } + + /** + * 对齐 + * @param string $align + * @return $this + * @throws Exception + */ + public function align(string $align): self + { + $this->align = $align; + return $this; + } + + /** + * 固定列 + * @param string $fixed + * @return $this + */ + public function fixed(string $fixed = 'right'): self + { + $this->fixed = $fixed; + return $this; + } + + /** + * 设置样式类 + * @param string $class + * @return $this + */ + public function class(string $class): self + { + $this->class[] = $class; + return $this; + } + + /** + * 设置附加属性 + * @param string $name + * @param $value + * @return $this + */ + public function attr(string $name, $value): self + { + $this->attr[$name] = $value; + return $this; + } + + /** + * 设置颜色 + * @param string $name + * @return $this + */ + public function color(string $name): self + { + $this->class[] = 'text-' . $name; + return $this; + } + + /** + * 字符串替换标签(数字字符串处理使用) + * @param $replace + * @return $this + */ + public function replace($replace): self + { + $this->replace = $replace; + return $this; + } + + /** + * 添加链接 + * @param string $name + * @param string $route + * @param array $params + * @param bool $absolute + * @return Link + */ + public function link(string $name, string $route, array $params = [], bool $absolute = false): Link + { + if (!$this->element) { + $this->element = new Table\Column\Link(); + $this->element->fields($this->layout->fields); + } + return $this->element->add($name, $route, $params, $absolute); + } + + /** + * 添加菜单 + * @param string $name + * @param string $route + * @param array $params + * @return Link + */ + public function menu(string $name, string $route, array $params = []): Link + { + if (!$this->element) { + $this->element = new Table\Column\Menu(); + } + return $this->element->add($name, $route, $params); + } + + /** + * 副标题 + * @param string $label + * @param callable|null $callback + * @return $this + */ + public function desc(string $label, callable $callback = null): self + { + if (!$this->element && !$this->element instanceof Table\Column\RichText) { + $this->element = new Table\Column\RichText(); + $this->element->setRelation($this->relation); + } + $this->element->desc($label, $callback); + return $this; + } + + /** + * 图片显示 + * @param string $label + * @param callable|null $callback + * @param int $width + * @param int $height + * @param string $placeholder + * @return $this + */ + public function image(string $label, callable $callback = null, int $width = 10, int $height = 10, string $placeholder = ''): self + { + if (!$this->element && !$this->element instanceof Table\Column\RichText) { + $this->element = new Table\Column\RichText(); + } + $this->element->image($label, $width, $height, $placeholder, $callback); + return $this; + } + + /** + * 格式化时间 + * @param $format + * @return $this + */ + public function date($format): self + { + $this->function[] = [ + 'fun' => 'date', + 'params' => $format + ]; + return $this; + } + + /** + * 显示隐藏 + * @param callable $callback + * @return $this + */ + public function show(callable $callback): self + { + $this->show = $callback; + return $this; + } + + /** + * 列排序 + * @param int $num + * @return $this + */ + public function sort(int $num): self + { + $this->sort = $num; + return $this; + } + + /** + * 排序条件 + */ + public function sorter($sorter = true): self + { + $this->sorter = $sorter; + return $this; + } + + /** + * 列合并 + * @param int $num + * @return $this + */ + public function colspan(int $num): self + { + $this->colspan = $num; + return $this; + } + + // 分组表格 + public function children(string $name = '', string $label = '', $callback = null): self + { + $this->children[] = new Column($name, $label, $callback); + return $this; + } + + /** + * 获取字段名 + * @return string + */ + public function getLabel(): string + { + return Tools::converLabel2($this->label, $this->relation); + } + + /** + * 获取列配置 + */ + public function getRender(): array + { + $render = $this->node; + if ($this->node instanceof \Closure) { + $render = call_user_func($this->node); + } + if ($this->element) { + $render = $this->element->render($this->getLabel()); + } + + $node = [ + 'title' => $this->name, + 'dataIndex' => $this->label, + 'width' => $this->width, + 'className' => implode(' ', $this->class), + 'colSpan' => $this->colspan, + 'sort' => $this->sort, + 'align' => $this->align, + ]; + + if ($this->fixed) { + $node['fixed'] = $this->fixed; + } + + if($this->replace){ + $node['replace'] = $this->replace; + } + + if ($this->children) { + $children = []; + foreach ($this->children as $item) { + $children[] = $item->getRender(); + } + $node['children'] = $children; + } + + if ($this->sorter) { + $node['vBind:sortable'] = 'colSortable'; + } + + if ($render) { + $node['render:rowData, rowIndex'] = $render; + } + return array_merge($node, $this->attr); + } + + /** + * 行数据 + * @param $rowData + * @return array + */ + public function getData($rowData): array + { + if ($this->relation) { + // 解析关联数组 + $parsingData = Tools::parsingObjData($rowData, $this->relation, $this->label); + } else { + // 解析普通数组 + $parsingData = Tools::parsingArrData($rowData, $this->label); + } + + // 回调处理 + if ($this->callback instanceof \Closure) { + $callback = call_user_func($this->callback, $parsingData, $rowData); + if ($callback) { + $parsingData = $callback; + } + } else { + $parsingData = $this->callback ?: $parsingData; + } + + // 函数处理 + if ($this->function) { + foreach ($this->function as $vo) { + if (function_exists($vo['fun'])) { + $parsingData = call_user_func($vo['fun'], $vo['params'], $parsingData); + } + } + } + + if ($this->label) { + $data = [ + $this->getLabel() => $parsingData + ]; + } else { + $data = []; + } + + // 元素数据 + if ($this->element && method_exists($this->element, 'getData')) { + $data = array_merge($data, $this->element->getData($rowData, $this->getLabel(), $parsingData)); + } + + if ($this->children) { + foreach ($this->children as $item) { + $data = array_merge($data, $item->getData($rowData)); + } + } + + return $data; + } + + /** + * 列条件 + * @param $query + * @return false|void + */ + public function execute($query) + { + $sort = \Yii::$app->request->get('_sort'); + $value = $sort && $sort[$this->label] ? $sort[$this->label] : null; + if (!$this->sorter || $value === null) { + return false; + } + if ($this->sorter instanceof \Closure) { + call_user_func($this->sorter, $query, $value); + } else if ($this->sorter !== false) { + $query->orderBy(is_string($this->sorter) ? $this->sorter : $this->label, $value === 'desc' ? 'desc' : 'asc'); + } + } + + /** + * 执行元素处理 + * @param callable $callback + * @return $this + */ + public function element(callable $callback){ + $callback($this->element); + return $this; + } + + /** + * @param $method + * @param $arguments + * @return $this + * @throws Exception + */ + public function __call($method, $arguments) + { + $class = 'backend\\components\\UI\\Table\\Column\\' . ucfirst($method); + if (!class_exists($class)) { + if (!$this->extend[$method]) { + throw new \Exception('There is no form method "' . $method . '"'); + } else { + $class = $this->extend[$method]; + } + } + $object = new $class(...$arguments); + if (method_exists($object, 'fields')) { + $object->fields($this->layout->fields); + } + $this->element = $object; + return $this; + } + +} diff --git a/admin/components/UI/Table/Column/Chart.php b/admin/components/UI/Table/Column/Chart.php new file mode 100644 index 0000000..947fdc4 --- /dev/null +++ b/admin/components/UI/Table/Column/Chart.php @@ -0,0 +1,74 @@ +day = $day; + $this->has = $has; + $this->key = $key; + $this->name = $name; + $this->type = $type; + } + + /** + * @param $value + * @param $data + * @return string + */ + public function render($value, $data): string + { + $chartData = $data->{$this->has}; + $tmpData = []; + $chartData->each(function ($item) use (&$tmpData) { + $tmpData[$item->date] += $item[$this->key]; + }); + $tmpChart = []; + foreach ($tmpData as $key => $vo) { + $tmpChart[] = [ + "value" => $vo, + "label" => $key, + "name" => $this->name + ]; + } + $viewId = 'chart-chart-' . Str::random(5); + + $chart = (new \backend\components\Util\ApexCharts)->{$this->type}($tmpChart)->type('day', [ + 'start' => date('Y-m-d', strtotime('-' . $this->day . ' day')), + ])->render($viewId, function ($config) { + Arr::set($config, 'chart.height', 35); + Arr::set($config, 'chart.sparkline.enabled', true); + Arr::set($config, 'chart.animations.enabled', false); + Arr::set($config, 'tooltip.enabled', false); + return $config; + }); + + return "
$chart"; + + } + +} diff --git a/admin/components/UI/Table/Column/Component.php b/admin/components/UI/Table/Column/Component.php new file mode 100644 index 0000000..a9097c0 --- /dev/null +++ b/admin/components/UI/Table/Column/Component.php @@ -0,0 +1,13 @@ + 'div', + 'child' => [ + [ + 'nodeName' => 'span', + 'class' => 'mr-2', + 'vIf' => "rowData.record['$name']", + 'child' => "{{rowData.record['$label']}}", + ], + [ + 'nodeName' => 'a-button', + 'shape' => 'round', + 'size' => 'mini', + 'type' => 'outline', + 'vBind:status' => "rowData.record['$name'] ? 'warning' : ''", + 'class' => 'mr-2', + 'vOn:click' => "rowData.record['$name'] = !rowData.record['$name']", + 'child' => "{{rowData.record['$name'] ? '隐藏' : '显示'}}", + ], + ] + ]; + } + +} diff --git a/admin/components/UI/Table/Column/Images.php b/admin/components/UI/Table/Column/Images.php new file mode 100644 index 0000000..5d8067f --- /dev/null +++ b/admin/components/UI/Table/Column/Images.php @@ -0,0 +1,49 @@ +size = $size; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + $node = [ + 'nodeName' => 'div', + 'vFor' => "item in rowData.record['$label']", + 'class' => "flex-none bg-cover w-{$this->size} h-{$this->size}", + 'vBind:style' => "{'background-image': 'url(' + item + ')'}" + ]; + + return [ + 'nodeName' => 'div', + 'class' => 'flex gap-2', + 'child' => $node + ]; + } + + public function getData($rowData, $field, $value): array + { + return [$field => !is_array($value) ? json_decode($value, true) : $value]; + + } + +} diff --git a/admin/components/UI/Table/Column/Input.php b/admin/components/UI/Table/Column/Input.php new file mode 100644 index 0000000..1e3f6f1 --- /dev/null +++ b/admin/components/UI/Table/Column/Input.php @@ -0,0 +1,55 @@ +field = $field; + $this->params = $params; + $this->route = $route; + } + + /** + * @param array $fields + * @return $this + */ + public function fields(array $fields = []): Input + { + $this->fields = $fields; + return $this; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + $url = app_route($this->route, $this->params, false, 'rowData.record', $this->fields); + return [ + 'nodeName' => 'n-input', + 'class' => 'shadow-sm', + 'vModel:value' => "rowData.record['$label']", + 'vOn:blur' => "editValue($url, {'field': '$this->field', '$this->field': rowData.record['$label']})", + ]; + } + +} diff --git a/admin/components/UI/Table/Column/Link.php b/admin/components/UI/Table/Column/Link.php new file mode 100644 index 0000000..53310d2 --- /dev/null +++ b/admin/components/UI/Table/Column/Link.php @@ -0,0 +1,80 @@ +fields = $fields; + return $this; + } + + /** + * 添加条目 + * @param string $name + * @param string $route + * @param array $params + * @param bool $absolute + * @return \backend\components\UI\Widget\Link + */ + public function add(string $name, string $route, array $params = [], bool $absolute = false): \backend\components\UI\Widget\Link + { + $link = new \backend\components\UI\Widget\Link($name, $route, $params, $absolute); + $link->fields($this->fields); + $link = $link->model('rowData.record'); + $this->link[] = $link; + return $link; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + $link = []; + foreach ($this->link as $class) { + $type = $class->getType(); + $data = $class->render(); + + if (($type === 'ajax' || $type === 'dialog') && (!isset($data['vBind:before']) || !isset($data['before']))) { + $data['vBind:before'] = "() => rowData.record.__loading = true"; + } + + if (($type === 'ajax' || $type === 'dialog') && (!isset($data['vBind:after']) || !isset($data['after']))) { + $data['vBind:after'] = "() => rowData.record.__loading = false"; + } + + $link[] = [ + 'nodeName' => 'span', + 'child' => $data + ]; + } + + $link = array_filter($link); + return [ + 'nodeName' => 'a-spin', + 'vBind:loading' => 'rowData.record.__loading', + 'child' => [ + 'nodeName' => 'div', + 'class' => 'inline-flex gap-2', + 'child' => $link + ] + ]; + } + +} diff --git a/admin/components/UI/Table/Column/Menu.php b/admin/components/UI/Table/Column/Menu.php new file mode 100644 index 0000000..672254c --- /dev/null +++ b/admin/components/UI/Table/Column/Menu.php @@ -0,0 +1,105 @@ +model('rowData'); + $this->link[] = $link; + $this->routes[$label] = [ + 'route' => $route, + 'params' => $params + ]; + return $link; + } + + /** + * 获取数据 + * @param $rowData + * @return array + */ + public function getData($rowData): array + { + $urls = []; + foreach ($this->routes as $key => $vo) { + $params = []; + foreach ($vo['params'] as $k => $v) { + $params[$k] = Tools::parsingArrData($rowData, $v, true); + } + $urls[$key] = route($vo['route'], $params, false); + } + return $urls; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + $options = []; + foreach ($this->link as $key => $class) { + $data = $class->render(); + + $route = [ + 'nodeName' => 'route', + 'type' => $data['type'], + 'title' => $data['title'], + 'href' => $class->getRoute(), + ]; + + $options[] = [ + 'label' => $data['name'], + 'key' => $key, + 'route' =>$route, + ]; + } + $options = array_filter($options); + + return [ + 'nodeName' => 'n-dropdown', + 'width' => '80', + 'placement' => 'right-start', + 'overlap' => true, + 'trigger' => 'click', + 'options' => $options, + 'render-label:option' => [ + 'nodeName' => 'route', + 'class' => 'block', + 'vBind:href' => 'rowData.record[option.route.href]', + 'vBind:title' => 'option.route.title', + 'vBind:type' => 'option.route.type', + 'child' => '{{option.label}}' + ], + 'child' => [ + 'nodeName' => 'n-icon', + 'class' => 'cursor-pointer', + 'size' => 16, + 'child' => [ + 'nodeName' => 'dots-vertical-icon' + ] + ], + ]; + } + +} diff --git a/admin/components/UI/Table/Column/Progress.php b/admin/components/UI/Table/Column/Progress.php new file mode 100644 index 0000000..9ab6559 --- /dev/null +++ b/admin/components/UI/Table/Column/Progress.php @@ -0,0 +1,31 @@ +color = $color; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + return (new \backend\components\UI\Widget\Progress("rowData.record['$label']"))->color($this->color)->render(); + } + +} diff --git a/admin/components/UI/Table/Column/RichText.php b/admin/components/UI/Table/Column/RichText.php new file mode 100644 index 0000000..a1586db --- /dev/null +++ b/admin/components/UI/Table/Column/RichText.php @@ -0,0 +1,153 @@ +relation = $relation; + return $this; + } + + /** + * @param string $label + * @param callable|null $callback + * @return $this + */ + public function desc(string $label, ?callable $callback = null): self + { + $this->desc[] = ['label' => $label, 'callback' => $callback]; + return $this; + } + + /** + * @param string $label + * @param int $width + * @param int $height + * @param string $placeholder + * @param callable|null $callback + * @return $this + */ + public function image(string $label, int $width = 10, int $height = 10, string $placeholder = '', ?callable $callback = null): self + { + $this->image[] = [ + 'label' => $label, + 'width' => $width, + 'height' => $height, + 'placeholder' => $placeholder, + 'callback' => $callback + ]; + return $this; + } + + /** + * @param $rowData + * @return array + */ + public function getData($rowData): array + { + $data = []; + foreach ($this->image as $vo) { + if ($this->relation) { + // 解析关联数组 + $url = Tools::parsingObjData($rowData, $this->relation, $vo['label']); + } else { + // 解析普通数组 + $url = Tools::parsingArrData($rowData, $vo['label'], true); + } + + if ($vo['callback'] instanceof \Closure) { + $url = call_user_func($vo['callback'], $url, $rowData); + } + if (filter_var($url, FILTER_VALIDATE_URL) === false) { + $url = route('service.image.placeholder', ['w' => 100, 'h' => 100, 't' => $vo['placeholder'] ?: '暂无']); + } + $data[Tools::converLabel($vo['label'], $this->relation)] = $url; + } + foreach ($this->desc as $key => $vo) { + + if ($this->relation) { + // 解析关联数组 + $var = Tools::parsingObjData($rowData, $this->relation, $vo['label']); + } else { + // 解析普通数组 + $var = Tools::parsingArrData($rowData, $vo['label']); + } + if ($vo['callback'] instanceof \Closure) { + $var = call_user_func($vo['callback'], $var, $rowData); + } + $data[Tools::converLabel($vo['label'], $this->relation)] = $var; + } + return $data; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + + $imageNode = []; + if ($this->image) { + foreach ($this->image as $vo) { + $itemLabel = Tools::converLabel2($vo['label']); + $imageNode[] = [ + 'nodeName' => 'div', + 'class' => "flex-none bg-cover w-{$vo['width']} h-{$vo['height']}", + 'vBind:style' => "{'background-image': 'url(' + rowData.record['$itemLabel'] + ')'}" + ]; + } + } + + $descNode = []; + if ($this->desc) { + foreach ($this->desc as $vo) { + $itemLabel = Tools::converLabel2($vo['label']); + $descNode[] = [ + 'nodeName' => 'div', + 'class' => "text-gray-500 overflow-ellipsis max-w-md", + 'child' => "{{rowData.record['$itemLabel']}}" + ]; + } + } + + return [ + 'nodeName' => 'div', + 'class' => 'flex items-center gap-2', + 'child' => [ + ...$imageNode, + [ + 'nodeName' => 'div', + 'class' => 'flex-grow', + 'child' => [ + [//注释是因为图片显示会把url也显示 + 'nodeName' => 'div', + 'class' => 'overflow-ellipsis max-w-md', + 'child' => "{{rowData.record['$label']}}" + ], + ...$descNode + ] + + ] + ] + ]; + + } + +} diff --git a/admin/components/UI/Table/Column/Status.php b/admin/components/UI/Table/Column/Status.php new file mode 100644 index 0000000..63bd1d0 --- /dev/null +++ b/admin/components/UI/Table/Column/Status.php @@ -0,0 +1,58 @@ +map = $map; + $this->color = $color; + $this->type = $type; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + $statusArr = []; + foreach ($this->map as $key => $vo) { + $statusArr[$key]['name'] = $vo; + $statusArr[$key]['color'] = $this->color[$key] ?? 'blue'; + } + + $node = []; + foreach ($statusArr as $key => $vo) { + if ($this->type === 'badge') { + $item = (new Badge($vo['name']))->color($vo['color'])->render(); + $item['vIf'] = "rowData.record['{$label}'] == " . (is_numeric($key) ? $key : "'$key'"); + } else { + $item = [ + 'nodeName' => 'div', + 'class' => 'text-' . $vo['color'] . '-900', + 'child' => $vo['name'] + ]; + } + $node[] = $item; + } + return $node; + } + +} diff --git a/admin/components/UI/Table/Column/Tags.php b/admin/components/UI/Table/Column/Tags.php new file mode 100644 index 0000000..4a2edc0 --- /dev/null +++ b/admin/components/UI/Table/Column/Tags.php @@ -0,0 +1,61 @@ +map = $map; + $this->color = $color; + } + + /** + * @param $label + * @return array + */ + public function render($label): array + { + $tagsArr = []; + foreach ($this->map as $key => $vo) { + $tagsArr[$key]['name'] = $vo; + } + foreach ($this->color as $key => $vo) { + $tagsArr[$key]['color'] = $vo; + } + + $node = []; + foreach ($tagsArr as $key => $vo) { + $item = (new Badge($vo['name']))->color($vo['color'])->render(); + $item['vIf'] = "~rowData.record['{$label}'].indexOf(". (is_numeric($key) ? $key : "'$key'") .")"; + $node[] = $item; + } + + return [ + 'nodeName' => 'div', + 'class' => 'flex gap-2', + 'child' => $node + ]; + } + + public function getData($rowData, $field, $value): array + { + return [$field => !is_array($value) ? explode(',', $value) : $value]; + + } + +} diff --git a/admin/components/UI/Table/Column/Toggle.php b/admin/components/UI/Table/Column/Toggle.php new file mode 100644 index 0000000..f5a8d15 --- /dev/null +++ b/admin/components/UI/Table/Column/Toggle.php @@ -0,0 +1,71 @@ +field = $field; + $this->params = $params; + $this->route = $route; + } + + /** + * 设置列字段 + * @param array $fields + * @return $this + */ + public function fields(Array $fields = []): self + { + $this->fields = $fields; + return $this; + } + + /** + * 开关数据 + * @param string|number|boolean $checkedValue + * @param string|number|boolean $uncheckedValue + * @return $this + */ + public function data($checkedValue,$uncheckedValue){ + $this->checkedValue = $checkedValue; + $this->uncheckedValue = $uncheckedValue; + return $this; + } + + /** + * @param $label + * @return string[] + */ + public function render($label): array + { + $url = app_route($this->route, $this->params, false, 'rowData.record', $this->fields); + return [ + 'nodeName' => 'a-switch', + 'vModel:model-value' => "rowData.record['$label']", + 'vOn:change' => "rowData.record['$label'] = \$event, editValue($url, {'field': '$this->field', '$this->field': rowData.record['$label']})", + 'checkedValue' => $this->checkedValue, + 'uncheckedValue' => $this->uncheckedValue + ]; + } + +} diff --git a/admin/components/UI/Table/Export.php b/admin/components/UI/Table/Export.php new file mode 100644 index 0000000..f54d963 --- /dev/null +++ b/admin/components/UI/Table/Export.php @@ -0,0 +1,87 @@ +title = $name; + return $this; + } + + /** + * 副标题 + * @param $name + * @return $this + */ + public function subtitle($name): self + { + $this->subtitle = $name; + return $this; + } + + /** + * 列设置 + * @param string $name + * @param string|Closure $value + * @param int $width + * @return $this + */ + public function column(string $name, $value, int $width = 10): self + { + $this->column[] = [ + 'name' => $name, + 'value' => $value, + 'width' => $width + ]; + return $this; + } + + /** + * 输出表单 + * @param $data + */ + public function render($data): void + { + $header = []; + $cellData = []; + foreach ($data as $vo) { + $tmp = []; + foreach ($this->column as $column) { + if (is_string($column['value'])) { + $tmp[] = Tools::parsingArrData($vo, $column['value']); + } else { + $tmp[] = call_user_func($column['value'], $vo); + } + } + $cellData[] = $tmp; + } + foreach ($this->column as $vo) { + $header[] = [ + 'name' => $vo['name'], + 'width' => $vo['width'] + ]; + } + Excel::export($this->title, $this->subtitle, $header, $cellData); + } + +} diff --git a/admin/components/UI/Table/Filter.php b/admin/components/UI/Table/Filter.php new file mode 100644 index 0000000..8f98425 --- /dev/null +++ b/admin/components/UI/Table/Filter.php @@ -0,0 +1,291 @@ +name = $name; + $this->field = $field; + $this->where = $where; + $this->default = $default; + $this->value = \Yii::$app->request->get($field, $this->default); + } + + /** + * 设置父级对象 + * @param Table $layout + */ + public function setLayout(Table $layout): void + { + $this->layout = $layout; + $this->model = $layout->model(); + } + + /** + * 级联选择 + * @param callable|array $data + * @param callable|null $callback + * @return $this + */ + public function cascader($data = [], callable $callback = NULL): self + { + $this->data = $data; + $this->type = 'cascader'; + $this->callback = $callback; + return $this; + } + + /** + * 下拉框 + * @param callable|array $data + * @param callable|null $callback + * @return $this + */ + public function select($data = [], callable $callback = NULL): self + { + $this->data = $data; + $this->type = 'select'; + $this->callback = $callback; + return $this; + } + + /** + * 文本库 + * @param string $placeholder + * @param callable|null $callback + * @return $this + */ + public function text(string $placeholder = '', callable $callback = NULL): self + { + $this->placeholder = $placeholder; + $this->type = 'text'; + $this->callback = $callback; + return $this; + } + + /** + * 日期 + * @param string $placeholder + * @param callable|null $callback + * @return $this + */ + public function date(string $placeholder = '', callable $callback = NULL): self + { + $this->placeholder = $placeholder; + $this->type = 'date'; + $this->callback = $callback; + return $this; + } + + /** + * 日期时间 + * @param string $placeholder + * @param callable|null $callback + * @return $this + */ + public function datetime(string $placeholder = '', callable $callback = NULL): self + { + $this->placeholder = $placeholder; + $this->type = 'datetime'; + $this->callback = $callback; + return $this; + } + + /** + * 日期范围 + * @param string $placeholder + * @param callable|null $callback + * @return $this + */ + public function daterange(string $placeholder = '', callable $callback = NULL): self + { + $this->placeholder = $placeholder; + $this->type = 'daterange'; + $this->callback = $callback; + return $this; + } + + /** + * 快捷筛选 + * @return $this + */ + public function quick(): self + { + $this->quick = true; + return $this; + } + + + /** + * 筛选条件 + * @param $type + * @return $this + */ + public function condition($type): self + { + $this->condition = $type; + return $this; + } + + + /** + * 执行筛选 + * @param $query + * @return false + */ + public function execute($query): bool + { + if ($this->value === null) { + return false; + } + if (is_array($this->value) && empty($this->value)) { + return false; + } + if ($this->where instanceof \Closure) { + call_user_func($this->where, $query, $this->value, $this->data); + } elseif ($this->where !== false) { + + $field = is_string($this->where) ? $this->where : $this->field; + $condition = '='; + $value = $this->value; + + if ($this->condition === 'like') { + $condition = 'like'; + $value = '%' . $value . '%'; + } + + $query->where($field, $condition, $value); + } + return true; + } + + /** + * 渲染组件 + * @return array + */ + public function render(): array + { + if (!$this->type) { + $this->layout->filterParams($this->field, $this->value); + return []; + } + switch ($this->type) { + case 'select': + $object = new Select($this->name, $this->field, $this->data); + $object->tip(true); + break; + case 'cascader': + $object = new Cascader($this->name, $this->field, $this->data); + break; + case 'date': + $object = new Date($this->name, $this->field); + break; + case 'datetime': + $object = new Datetime($this->name, $this->field); + break; + case 'daterange': + $object = new Daterange($this->name, $this->field); + break; + case 'text': + default: + $object = new Text($this->name, $this->field); + } + + $object->model('data.filter.'); + + + $this->layout->filterParams($this->field, $this->value); + + if ($this->callback instanceof \Closure) { + call_user_func($this->callback, $object); + } + + $data = [ + 'status' => $this->value !== null, + 'quick' => $this->quick, + 'where' => $this->where, + 'value' => $this->value, + 'field' => $this->field, + 'data' => $this->data, + 'name' => $this->name + ]; + + if($this->layout->filterLayout=='rows'){ + $data['render'] = [ + 'nodeName'=>'a-col', + "span"=>"6", + 'child'=>[ + 'nodeName'=>'a-form-item', + 'field'=>$this->field, + 'label'=>$this->name, + 'child' => $object->placeholder($this->placeholder)->getRender() + ] + ]; + return $data; + + } + if ($this->quick) { + $data['render'] = [ + 'nodeName' => 'div', + 'class' => 'lg:w-40', + 'child' => $object->placeholder($this->placeholder)->getRender() + ]; + } else { + $data['render'] = [ + 'nodeName' => 'div', + 'class' => 'my-2', + 'child' => [ + [ + 'nodeName' => 'div', + 'child' => $this->name, + ], + [ + 'nodeName' => 'div', + 'class' => 'mt-2', + 'child' => $object->placeholder($this->placeholder)->getRender() + ] + ], + ]; + } + + return $data; + } +} diff --git a/admin/components/UI/Table/FilterType.php b/admin/components/UI/Table/FilterType.php new file mode 100644 index 0000000..89863df --- /dev/null +++ b/admin/components/UI/Table/FilterType.php @@ -0,0 +1,88 @@ +name = $name; + $this->where = $where; + $this->value = $value; + } + + public function setLayout(Table $layout): void + { + $this->layout = $layout; + $this->model = $layout->model(); + } + + public function num($num = 0): self + { + $this->num = $num; + return $this; + } + + public function icon($content): self + { + $this->icon = $content; + return $this; + } + + public function execute($query, $key): void + { + if ($this->where instanceof \Closure && $this->value == $key) { + call_user_func($this->where, $this->model); + } + } + + /** + * @param $key + * @return array + */ + public function render($key): array + { + return [ + 'nodeName' => 'a-radio', + 'value' => $key, + 'child' => [ + $this->icon ? [ + 'nodeName' => $this->icon + ]: [], + [ + 'nodeName' => 'span', + 'child' => ' ' . $this->name + ] + ] + ]; + + } +} diff --git a/admin/components/UI/Table/Node.php b/admin/components/UI/Table/Node.php new file mode 100644 index 0000000..0a892b2 --- /dev/null +++ b/admin/components/UI/Table/Node.php @@ -0,0 +1,591 @@ +[],'filter'=>[]]; + private array $columns = []; + private array $expand = []; + private array $filter = []; + private array $quickFilter = []; + private array $action = []; + private array $bath = []; + private array $page = ['left'=>[],'right'=>[]]; + private array $type = []; + private array $side = ['left'=>[],'right'=>[]]; + private array $sideSize = ['left'=>'','right'=>'']; + private array $header = []; + private array $footer = []; + private array $script = []; + private array $scriptReturn = []; + private array $scriptData = []; + private ?string $eventName = null; + private $filterLayout =null; + + /** + * Node constructor. + * @param string $url + * @param string $key + * @param string|null $title + */ + public function __construct(string $url, string $key, ?string $title = '') + { + $this->url = $url; + $this->key = $key; + $this->title = $title; + } + + /** + * @param $urlBind + * @return $this + */ + public function urlBind($urlBind): self + { + $this->urlBind = $urlBind; + return $this; + } + + /** + * @param $class + * @return $this + */ + public function class($class): self + { + $this->class .= ' ' . $class; + return $this; + } + + /** + * @param $params + * @return $this + */ + public function params($params): self + { + $this->params = $params; + return $this; + } + + /** + * 附加参数 + * @param $key + * @param $value + * @return $this + */ + public function nParams($key,$value){ + $this->params[$key] = $value; + return $this; + } + + /** + * @param array $filter + * @return $this + */ + public function data(array $filter): self + { + $this->data['filter'] = $filter; + return $this; + } + + /** + * @param $content + * @param $return + * @return $this + */ + public function script($content, $return): self + { + if ($content instanceof \Closure) { + $this->script[] = $content(); + } else { + $this->script[] = $content; + } + $this->scriptReturn[] = $return; + return $this; + } + + /** + * @param $data + * @return $this + */ + public function scriptData($data): self + { + $this->scriptData = array_merge($this->scriptData, $data); + return $this; + } + + /** + * @param $config + * @return $this + */ + public function tree($config): self + { + $this->tree = $config; + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function columns(array $node): self + { + $this->columns = $node; + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function expand(array $node): self + { + $this->expand = $node; + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function type(array $node): self + { + $this->type = $node; + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function filter(array $node): self + { + $this->filter = array_values(array_filter($node)); + return $this; + } + + public function filterLayout($l):self{ + $this->filterLayout =$l; + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function quickFilter(array $node): self + { + if ($node) { + $this->quickFilter = $node; + } + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function action(array $node): self + { + $this->action = $node; + return $this; + } + + /** + * @param array $node + * @return $this + */ + public function bath(array $node): self + { + $this->bath = $node; + return $this; + } + + /** + * @param string|null $eventName + * @return $this + */ + public function eventName(?string $eventName): self + { + $this->eventName = $eventName; + return $this; + } + + /** + * @param $node + * @param string $type + * @param false $resize + * @param string $width + * @return $this + */ + public function side($node, string $type = 'left', bool $resize = false, string $width = '100px'): self + { + $this->side[$type] = is_callable($node) ? $node() : $node; + if ($resize) { + $this->sideSize[$type] = $width; + } + return $this; + } + + /** + * @param $node + * @param string $type + * @return $this + */ + public function page($node, string $type = 'left'): self + { + $this->page[$type] = is_callable($node) ? $node() : $node; + return $this; + } + + /** + * @param $node + * @return $this + */ + public function header($node): self + { + $this->header = $node; + return $this; + } + + /** + * @param $node + * @return $this + */ + public function footer($node): self + { + $this->footer = $node; + return $this; + } + + /** + * @return array[] + */ + private function headNode(): array + { + if($this->filterLayout=='rows'){ + $ret[] = [ + 'nodeName'=>'a-row', + 'child'=>[ + [ + 'nodeName'=>'a-col', + 'child'=>[ + 'nodeName' => 'a-form', + "label-align"=>"left", + "vBind:label-col-props"=>"{'span':'8'}", + "vBind:wrapper-col-props"=>"{'span':'16'}", + 'child'=>[ + [ + 'nodeName'=>'a-row', + "vBind:gutter"=>"16", + 'child' => $this->filter + ], + ] + ] + ], + ] + ]; + if(!empty($this->action)){ + if(!empty($this->filter)){ + $ret[] = [ + 'nodeName'=>'a-divider', + 'style'=>'margin-top: 0', + ]; + } + $ret[] = [ + 'nodeName'=>'a-row', + "style"=>"margin-bottom: 16px", + 'child'=>[ + 'nodeName' => 'a-col', + 'vBind:span'=>'16', + 'child'=>[ + 'nodeName' => 'a-space', + 'child'=>$this->action + ] + ] + ]; + } + return $ret; + } + if ($this->filter) { + $this->quickFilter[] = [ + 'nodeName' => 'a-trigger', + 'position' => 'br', + 'trigger' => 'click', + 'child' => [ + [ + 'nodeName' => 'a-button', + 'type' => 'secondary', + 'child' => [ + '筛选', + [ + 'vSlot:icon' => '', + 'nodeName' => 'icon-filter', + ] + ] + ], + [ + 'vSlot:content' => '', + 'nodeName' => 'div', + 'class' => 'flex flex-col rounded shadow bg-white dark:bg-blackgray-1 dark:text-gray-400 p-2 w-56', + 'child' => $this->filter + ] + ] + ]; + } + $header=[]; + $ret = []; + if ($this->type) { + $header = [ + 'nodeName' => 'a-radio-group', + 'name' => 'type', + 'type' => 'button', + 'vModel:modelValue' => 'data.filter.type', + 'child' => $this->type + ]; + $ret[] = [ + 'nodeName' => 'div', + 'class' => 'flex-grow lg:w-10 flex justify-center lg:justify-start', + 'child' => $header + ]; + } + $ret[] = [ + 'nodeName' => 'div', + 'class' => 'flex-none flex gap-2', + 'child' => array_filter(array_merge($this->quickFilter, $this->action)) + ]; + return $ret; + } + + /** + * @return array + */ + public function tableNode(): array + { + // 指定行key + $this->params['row-key'] = $this->key; + + // 设置扩展行 + if ($this->expand) { + $this->params['vChild:expandable'] = $this->expand; + } + + // 分组表头线 + $children = false; + foreach ($this->columns as $col) { + if (isset($col['children']) && $col['children']) { + $children = true; + break; + } + } + if ($children) { + $this->params['bordered'] = [ + 'headerCell' => true + ]; + } + + return [ + 'nodeName' => 'app-table', + 'requestEventName' => $this->eventName, + 'class' => $this->class, + 'url' => $this->url, + 'urlBind' => $this->urlBind, + 'n-params' => $this->params, + 'columns' => $this->columns, + 'vBind:filter' => 'data.filter', + 'select' => (bool)$this->bath, + 'table-layout-fixed' => true, + 'child' => [ + 'vSlot:footer' => 'footer', + 'nodeName' => 'div', + 'class' => 'flex gap-2', + 'child' => $this->bath + ] + ]; + } + + + /** + * @return array + */ + public function render(): array + { + + /*$this->script[] = <<scriptReturn[] = 'dataRef';*/ + + $value = [ + 'filter' => $this->data['filter'] ?: [], + 'show' => $this->data['show'] ?: [] + ]; + $value = array_merge($this->scriptData, $value); + return [ + 'node' => [ + 'nodeName' => 'app-form', + 'value' => $value, + 'child' => [ + 'nodeName' => 'div', + 'class' => 'flex h-screen', + 'vSlot' => '{value: data}', + 'child' => [ + $this->side['left'] ? [ + 'nodeName' => isset($this->sideSize['left']) ? 'a-resize-box' : 'div', + 'style' => $this->sideSize['left'] ? 'width:' . $this->sideSize['left'] : '', + 'directions' => ['right'], + 'class' => 'border-r border-gray-200 dark:border-gray-700 flex-none bg-white dark:bg-blackgray-4 h-screen', + 'child' => $this->side['left'] + ] : [], + + [ + 'nodeName' => 'app-layout', + 'class' => 'flex-grow w-10', + 'title' => $this->title ?: '列表数据', + 'child' => [ + [ + 'vSlot' => '', + 'nodeName' => 'div', + 'class' => 'flex flex-row items-start gap-4 p-4', + 'child' => [ + $this->page['left'] ?: [], + [ + 'nodeName' => 'div', + 'class' => 'flex-grow lg:w-10 p-4 bg-white dark:bg-blackgray-4 rounded shadow', + 'child' => [ + $this->header ? [ + 'nodeName' => 'div', + 'class' => 'pb-4', + 'child' => $this->header + ] : [], + [ + 'nodeName' => 'div', + 'class' => 'flex-none flex-row gap-2 items-center pb-4', + 'child' => $this->headNode() + + ], + $this->tableNode(), + $this->footer ? [ + 'nodeName' => 'div', + 'class' => 'pb-4', + 'child' => $this->footer + ] : [], + ], + ], + $this->page['right'] ?: [], + ] + ] + ] + ], + + + $this->side['right'] ? [ + 'nodeName' => $this->sideSize['right'] ? 'a-resize-box' : 'div', + 'style' => $this->sideSize['right'] ? 'width:' . $this->sideSize['left'] : '', + 'directions' => ['left'], + 'class' => 'border-l border-gray-200 dark:border-gray-700 flex-none bg-white dark:bg-blackgray-4 h-screen', + 'child' => $this->side['right'] + ] : [], + ] + ], + ], + 'setupScript' => implode("\n", $this->script) . "\n" . ' return {' . implode(",", $this->scriptReturn) . '}' + ]; + } + + /** + * 渲染table核心 + * @return array[] + */ + public function renderTableCore(): array + { + $value = [ + 'filter' => $this->data['filter'] ?: [], + 'show' => $this->data['show'] ?: [] + ]; + $value = array_merge($this->scriptData, $value); + return [ + 'node' => [ + 'nodeName' => 'app-form', + 'value' => $value, + 'child' => [ + 'nodeName' => 'app-dialog', + 'vSlot' => '{value: data}', + 'title' => $this->title ?: '信息详情', + 'class' => 'flex-grow', + 'child' => [ + [ + 'nodeName' => 'div', + 'class' => 'flex', + 'vSlot' => '{value: data}', + 'child' => [ + $this->side['left'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none', + 'child' => $this->side['left'] + ] : [], + [ + 'nodeName' => 'div', + 'class' => 'flex-grow lg:w-10 p-4 bg-white dark:bg-blackgray-4 rounded shadow', + 'child' => [ + $this->header ? [ + 'nodeName' => 'div', + 'class' => 'pb-4', + 'child' => $this->header + ] : [], + [ + 'nodeName' => 'div', + 'class' => 'flex-none flex flex-row gap-2 items-center pb-4', + 'child' => $this->headNode() + + ], + $this->tableNode(), + $this->footer ? [ + 'nodeName' => 'div', + 'class' => 'pb-4', + 'child' => $this->footer + ] : [], + ], + ], + $this->side['right'] ? [ + 'nodeName' => 'div', + 'class' => 'flex-none', + 'child' => $this->side['right'] + ] : [] + ] + ], + [ + 'nodeName' => 'div', + 'vSlot:footer' => '', + 'class' => 'arco-modal-footer', + 'child' => [ + [ + 'nodeName' => 'route', + 'type' => 'back', + 'child' => [ + 'nodeName' => 'a-button', + 'child' => '关闭' + ] + ] + ] + ] + ] + ] + ] + ]; + } + +} diff --git a/admin/components/UI/Table/Tree.php b/admin/components/UI/Table/Tree.php new file mode 100644 index 0000000..282f2f6 --- /dev/null +++ b/admin/components/UI/Table/Tree.php @@ -0,0 +1,99 @@ +label = $label; + $this->node = $node; + + } + + /** + * @param $node + * @return $this + */ + public function prefix($node): self + { + $this->prefix = $node; + return $this; + } + + /** + * @param $node + * @return $this + */ + public function suffix($node): self + { + $this->suffix = $node; + return $this; + } + + /** + * 添加链接 + * @param string $name + * @param string $route + * @param array $params + * @return Link + */ + public function link(string $name, string $route, array $params = []): Link + { + if (!$this->link) { + $this->link = new Column\Link(); + } + return $this->link->add($name, $route, $params); + } + + + /** + * 渲染组件 + * @return array + */ + public function render(): array + { + $suffix = $this->suffix; + if ($this->link) { + $suffix = $this->link->render(''); + } + return [ + 'node' => $this->node ?: ['nodeName' => 'div', 'child' => "{{rowData.record['$this->label']}}"], + 'prefix' => $this->prefix, + 'suffix' => $suffix + ]; + } + + /** + * 组件行数据 + * @param $rowData + * @return array + */ + public function getData($rowData): array + { + $data = []; + // 元素数据 + if ($this->link) { + $data = array_merge($data, $this->link->getData($rowData)); + } + return $data; + } + +} diff --git a/admin/components/UI/Tabs.php b/admin/components/UI/Tabs.php new file mode 100644 index 0000000..8e26fa8 --- /dev/null +++ b/admin/components/UI/Tabs.php @@ -0,0 +1,73 @@ +nodes[] = ['title'=>$title,'name'=>$title,'key'=>$key,'order'=>0,'desc'=>$desc,'child'=>$child?[$child]:[]]; + } + public function render(): array + { + + $panelNodes = []; + + $nodes = collect($this->nodes)->sortBy('order')->toArray(); + foreach ($nodes as $key => $node) { + $child = []; + if ($node['title']) { + $child[] = [ + 'nodeName' => 'div', + 'class' => 'pt-2', + 'child' => $node['child'] + ]; + } + + //$child[] = [ + // 'nodeName' => 'div', + // 'class' => 'pt-2', + // 'child' => $node['object']->render() + //]; + $panelNodes[] = [ + 'nodeName' => 'a-tab-pane', + 'title' => $node['name'], + 'key' => $key, + 'class' => !$this->dialog ? ' border-t border-gray-200 dark:border-blackgray-1 px-3 pt-4 pb-0' : '', + 'child' => [ + 'nodeName' => 'div', + 'class' => '', + 'child' => $child + ] + ]; + } + + return [ + 'nodeName' => 'a-tabs', + 'lazy-load'=>$this->lazyLoad, + 'class' => !$this->dialog ? 'mb-4 bg-white dark:bg-blackgray-4 rounded shadow p-4 pb-1' : '', + 'type' => 'rounded', + 'child' => $panelNodes + ]; + + } +} diff --git a/admin/components/UI/Tools.php b/admin/components/UI/Tools.php new file mode 100644 index 0000000..f1bf06d --- /dev/null +++ b/admin/components/UI/Tools.php @@ -0,0 +1,72 @@ +$relation; + if ($field) { + if ($relationData instanceof \Illuminate\Support\Collection) { + $tmp = []; + foreach ($relationData as $vo) { + $tmp[] = self::parsingArrData($vo, $field); + } + $data = implode(',', $tmp); + } else { + $data = self::parsingArrData($relationData, $field); + } + } else { + $data = ''; + } + return $data; + } + + /** + * 解析数组数据 + * @param $data + * @param string|null $field + * @param bool $source + * @return string|string[]|null + */ + public static function parsingArrData($data, string $field = null, bool $source = false) + { + //$field = str_replace('->', '.', $field); + if (!$source) { + return $field ? Arr::get($data, $field) : ''; + } + return Arr::has($data, $field) ? Arr::get($data, $field) : $field; + } + + + /** + * 标签转换 + * @param $label + * @param null $relation + * @return string + */ + public static function converLabel($label, $relation = null): string + { + return str_replace(['.', '->'], "_", $relation ? $relation . '_' . $label : $label); + } + public static function converLabel2($label): string + { + return str_replace(['.', '->'], "']['",$label); + } +} diff --git a/admin/components/UI/View/Components/loading.blade.php b/admin/components/UI/View/Components/loading.blade.php new file mode 100644 index 0000000..f041e67 --- /dev/null +++ b/admin/components/UI/View/Components/loading.blade.php @@ -0,0 +1,11 @@ +
+
+
+ Loading... +
+

{{$title}}

+

+ {{$content}} +

+
+
diff --git a/admin/components/UI/View/Components/nodata.blade.php b/admin/components/UI/View/Components/nodata.blade.php new file mode 100644 index 0000000..b345bd2 --- /dev/null +++ b/admin/components/UI/View/Components/nodata.blade.php @@ -0,0 +1,39 @@ +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+

{{$title}}

+

+ {{$content}} +

+ @if($reload) + + @endif +
+
diff --git a/admin/components/UI/View/Components/trend.blade.php b/admin/components/UI/View/Components/trend.blade.php new file mode 100644 index 0000000..90dfca5 --- /dev/null +++ b/admin/components/UI/View/Components/trend.blade.php @@ -0,0 +1,22 @@ +@if($type == 2) + +@elseif($type == 1) + +@else + +@endif diff --git a/admin/components/UI/View/base.blade.php b/admin/components/UI/View/base.blade.php new file mode 100644 index 0000000..e77fee5 --- /dev/null +++ b/admin/components/UI/View/base.blade.php @@ -0,0 +1 @@ +@include($layout) diff --git a/admin/components/UI/View/dialog.blade.php b/admin/components/UI/View/dialog.blade.php new file mode 100644 index 0000000..e77fee5 --- /dev/null +++ b/admin/components/UI/View/dialog.blade.php @@ -0,0 +1 @@ +@include($layout) diff --git a/admin/components/UI/Widget.php b/admin/components/UI/Widget.php new file mode 100644 index 0000000..d7ffe5d --- /dev/null +++ b/admin/components/UI/Widget.php @@ -0,0 +1,39 @@ +next()->getRender(); + } +} diff --git a/admin/components/UI/Widget/Alert.php b/admin/components/UI/Widget/Alert.php new file mode 100644 index 0000000..d2d6a06 --- /dev/null +++ b/admin/components/UI/Widget/Alert.php @@ -0,0 +1,51 @@ +title = $title; + $this->content = $content; + $this->callback = $callback; + } + + /** + * 文本类型 + * @param $name + * @return $this + */ + public function type($name): self + { + $this->type = $name; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + return [ + 'nodeName' => 'a-alert', + 'title' => $this->title, + 'type' => $this->type, + 'child' => $this->content + ]; + } +} diff --git a/admin/components/UI/Widget/Append/Element.php b/admin/components/UI/Widget/Append/Element.php new file mode 100644 index 0000000..2e9ffe8 --- /dev/null +++ b/admin/components/UI/Widget/Append/Element.php @@ -0,0 +1,12 @@ +content = $content; + $this->callback = $callback; + } + + /** + * 颜色 + * @param $value + * @return $this + */ + public function color($value): self + { + $this->type = $value; + return $this; + } + + /** + * 大小 + * @param string $size + * @return $this + */ + public function size(string $size = ''): self + { + $this->size = $size; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + return [ + 'nodeName' => 'a-tag', + 'color' => $this->type, + 'size' => $this->size, + 'child' => $this->content + ]; + } + +} diff --git a/admin/components/UI/Widget/Form.php b/admin/components/UI/Widget/Form.php new file mode 100644 index 0000000..58e2319 --- /dev/null +++ b/admin/components/UI/Widget/Form.php @@ -0,0 +1,38 @@ +callback = $callback; + $this->form = new \backend\components\UI\Form($data, false); + } + + /** + * @return string + */ + public function render(): string + { + return $this->form->render(); + } + + /** + * @param $method + * @param $arguments + * @return mixed + */ + public function __call($method, $arguments) + { + return $this->form->$method(...$arguments); + } + +} diff --git a/admin/components/UI/Widget/Icon.php b/admin/components/UI/Widget/Icon.php new file mode 100644 index 0000000..c11f81e --- /dev/null +++ b/admin/components/UI/Widget/Icon.php @@ -0,0 +1,64 @@ +content = $content; + $this->callback = $callback; + } + + /** + * 设置大小 + * @param int $size + * @return $this + */ + public function size(int $size): self + { + $this->size = $size; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $icon = $this->content; + if (strpos($icon, ' 'n-icon', + 'size' => $this->size, + 'child' => [ + 'nodeName' => 'rich-text', + 'class' => implode(' ', $this->class), + 'nodes' => $icon + ] + ]; + } + + return [ + 'nodeName' => 'icon-' . $icon, + 'class' => implode(' ', $this->class), + ]; + } + +} diff --git a/admin/components/UI/Widget/Images.php b/admin/components/UI/Widget/Images.php new file mode 100644 index 0000000..90bcc78 --- /dev/null +++ b/admin/components/UI/Widget/Images.php @@ -0,0 +1,63 @@ +list = $list; + $this->callback = $callback; + } + + /** + * 图像大小 + * @param int $size + * @return $this + */ + public function size(int $size): self + { + $this->size = $size; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $list = []; + foreach ($this->list as $vo) { + $list[] = [ + 'nodeName' => 'a-image', + 'src' => $vo, + 'width' => $this->size, + 'height' => $this->size, + ]; + } + + return [ + 'nodeName' => 'a-image-preview-group', + 'infinite' => true, + 'child' => [ + 'nodeName' => 'a-space', + 'child' => $list + ] + ]; + + } + +} diff --git a/admin/components/UI/Widget/Item.php b/admin/components/UI/Widget/Item.php new file mode 100644 index 0000000..2eb05cf --- /dev/null +++ b/admin/components/UI/Widget/Item.php @@ -0,0 +1,26 @@ +params = $params; + } + + public function __call($method, $arguments) + { + $this->{$method}[] = $arguments; + return $this; + } + +} diff --git a/admin/components/UI/Widget/Link.php b/admin/components/UI/Widget/Link.php new file mode 100644 index 0000000..bebcc33 --- /dev/null +++ b/admin/components/UI/Widget/Link.php @@ -0,0 +1,303 @@ +name = $name; + $this->route = $route; + $this->params = $params ?: []; + $this->absolute = $absolute; + } + + /** + * @param $params + * @return $this + */ + public function fields($params): self + { + $this->fields = $params; + return $this; + } + + /** + * 链接类型 + * @param string $name + * @param array $config + * @return $this + */ + public function type(string $name = 'default', array $config = []): self + { + $this->type = $name; + $this->typeConfig = $config; + return $this; + } + + /** + * 获取类型 + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * 获取类型配置 + * @return array + */ + public function getTypeConfig(): array + { + return $this->typeConfig; + } + + /** + * 数据模型 + * @param string $model + * @return $this + */ + public function model(string $model): self + { + $this->model = $model; + return $this; + } + + /** + * 图标 + * @param $icon + * @return $this + */ + public function icon($icon): self + { + $this->icon = $icon; + return $this; + } + + /** + * 按钮属性 + * @param string $type + * @param string $status + * @param bool $block + * @return $this + */ + public function button(string $type = 'primary', string $status = 'medium', bool $block = false): self + { + $this->button = $type; + $this->status = $status; + $this->block = $block; + return $this; + } + + /** + * 获取路由 + * @return string + */ + public function getRoute(): string + { + return $this->route; + } + + /** + * 显示隐藏 + * @param callable $callback + * @return $this + */ + public function show(callable $callback): self + { + $this->show = $callback; + return $this; + } + + + /** + * 自定义权限 + * @param string $name + * @return $this + */ + public function can(string $name): self + { + if (strpos($name, '.') !== false) { + $this->auth = $name; + } else { + $this->auth = $this->route . '|' . $name; + } + return $this; + } + + /** + * 获取url + * @return false|string + */ + public function getUrl() + { + if (!$this->isAuth()) { + return false; + } + + if ($this->show && !call_user_func($this->show)) { + return false; + } + + return app_route($this->route, $this->params, $this->absolute, $this->model, $this->fields); + } + + /** + * @return array + */ + public function render(): array + { + $url = $this->getUrl(); + + if (!$url) { + return []; + } + + $object = [ + 'nodeName' => 'route', + ]; + + switch ($this->type) { + case 'default': + $object['vBind:href'] = $url; + break; + case 'blank': + $object['nodeName'] = 'a'; + $object['vBind:href'] = $url; + $object['target'] = '_blank'; + $object['child'] = $this->name; + break; + case 'dialog': + $object['vBind:href'] = $url; + $object['type'] = 'dialog'; + $object['title'] = $this->name; + break; + case 'drawer': + $object['vBind:href'] = $url; + $object['type'] = 'dialog'; + $object['mode'] = 'drawer'; + $object['title'] = $this->name; + break; + case 'ajax': + $object['vBind:href'] = $url; + $object['type'] = 'ajax'; + $object['title'] = '确认进行' . $this->name . '操作?'; + break; + } + $object = array_merge($object, $this->typeConfig); + + if ($this->button) { + $link = [ + 'nodeName' => 'a-button', + 'class' => implode(' ', $this->class), + 'type' => $this->button, + 'status' => $this->status, + 'child' => [ + $this->name + ] + ]; + if ($this->icon) { + $link['child'][] = (new Icon($this->icon))->attr('vSlot:icon', '')->getRender(); + } + if ($this->block) { + $link['long'] = true; + } + } else { + $link = [ + 'nodeName' => 'span', + 'class' => 'arco-link arco-link-status-normal ' . implode(' ', $this->class), + 'child' => [ + $this->name + ] + ]; + if ($this->icon) { + $link['child'][] = (new Icon($this->icon))->class('mr-2')->getRender(); + } + } + + $object['child'] = $link; + + return array_merge($object, $this->attr); + + } + + private function isAuth(): bool + { + return true; + //// 路由不存在 + //if (!\Route::has($this->route)) { + // return false; + //} + //// 验证是否公共类 + //$public = \Route::getRoutes()->getByName($this->route)->getAction('public'); + //if ($public) { + // return true; + //} + //// 验证是否当前守护器 + //$app = Str::before($this->route, '.'); + //if ($app <> Permission::getGuerd()) { + // return true; + //} + // + //// 设置通用页面权限 + //if (Str::afterLast($this->route, '.') === 'page') { + // if ($this->params['id']) { + // $this->can('edit'); + // } else { + // $this->can('add'); + // } + //} + // + //// 验证自定义权限 + //if ($this->auth) { + // if (!auth($app)->user()->can($this->auth)) { + // return false; + // } + // return true; + //} + // + //// 验证通用权限 + //if (auth($app)->user()->can($this->route)) { + // return true; + //} + //return false; + } + +} diff --git a/admin/components/UI/Widget/Lists.php b/admin/components/UI/Widget/Lists.php new file mode 100644 index 0000000..65d82a9 --- /dev/null +++ b/admin/components/UI/Widget/Lists.php @@ -0,0 +1,51 @@ +data = $data; + $this->callback = $callback; + } + + + /** + * @return array + */ + public function render(): array + { + + $inner = []; + $i = 0; + foreach ($this->data as $item) { + $inner[] = [ + 'nodeName' => 'a-list-item', + 'child' => $item + ]; + } + + return $inner ? [ + 'nodeName' => 'a-list', + 'child' => $inner + ] : [ + 'nodeName' => 'a-empty', + ]; + } + +} diff --git a/admin/components/UI/Widget/Menu.php b/admin/components/UI/Widget/Menu.php new file mode 100644 index 0000000..1b76887 --- /dev/null +++ b/admin/components/UI/Widget/Menu.php @@ -0,0 +1,75 @@ +name = $name; + $this->type = $type; + $this->callback = $callback; + } + + /** + * @param string $name + * @param string $route + * @param array $params + * + * @return Link + */ + public function link(string $name, string $route = '', array $params = []): Link + { + $link = new Link($name, $route, $params); + $this->link[] = $link; + return $link; + } + + /** + * @return array + */ + public function render(): array + { + $list = []; + foreach ($this->link as $class) { + $list[] = [ + 'nodeName' => 'a-doption', + 'child' => $class->render(), + ]; + } + return [ + 'nodeName' => 'a-dropdown', + 'child' => [ + [ + 'nodeName' => 'a-button', + 'type' => $this->type, + 'child' => $this->name + ], + [ + 'nodeName' => 'div', + 'vSlot:content' => '', + 'child' => $list + ] + ] + ]; + + } + +} diff --git a/admin/components/UI/Widget/Progress.php b/admin/components/UI/Widget/Progress.php new file mode 100644 index 0000000..30d4789 --- /dev/null +++ b/admin/components/UI/Widget/Progress.php @@ -0,0 +1,71 @@ +value = $value; + $this->callback = $callback; + } + + /** + * @param string $color + * @return $this + */ + public function color(string $color): self + { + $this->color = $color; + return $this; + } + + /** + * @param string $size + * @return $this + */ + public function size($size = 'medium'): self + { + $this->size = (bool)$size; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $node = [ + 'nodeName' => 'a-progress', + 'size' => $this->size, + 'status' => $this->color, + ]; + if (is_numeric($this->value)) { + $node['percent'] = $this->value; + }else { + $node['vBind:percent'] = $this->value; + } + return $node; + + } + +} diff --git a/admin/components/UI/Widget/Row.php b/admin/components/UI/Widget/Row.php new file mode 100644 index 0000000..693992a --- /dev/null +++ b/admin/components/UI/Widget/Row.php @@ -0,0 +1,63 @@ +callback = $callback; + } + + /** + * 设置列 + * @param callable $callback + * @param int $width + * @return $this + */ + public function column(callable $callback, int $width = 0): self + { + $this->column[] = [ + 'width' => $width, + 'callback' => $callback, + ]; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + + $nodes = []; + foreach ($this->column as $vo) { + $nodes[] = [ + 'nodeName' => 'div', + 'class' => $vo['width'] ? "row-span-{$vo['width']}" : '', + 'child' => call_user_func($vo['callback']) + ]; + } + return [ + 'nodeName' => 'div', + 'class' => 'grid grid-flow-col gap-x-4', + 'child' => $nodes + ]; + + + } + +} diff --git a/admin/components/UI/Widget/StatsCard.php b/admin/components/UI/Widget/StatsCard.php new file mode 100644 index 0000000..ca58795 --- /dev/null +++ b/admin/components/UI/Widget/StatsCard.php @@ -0,0 +1,68 @@ +callback = $callback; + $this->column = $column; + } + + /** + * @param $name + * @param $num + * + * @return $this + */ + public function item($name, $num): self + { + $this->items[] = [ + 'name' => $name, + 'num' => $num, + ]; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $childs = []; + foreach ($this->items as $vo) { + $childs[] = [ + 'nodeName' => 'div', + 'child' => [ + 'nodeName' => 'a-statistic', + 'title' => $vo['name'], + 'value' => $vo['num'], + ] + ]; + } + + return [ + 'nodeName' => 'div', + 'class' => 'grid gap-4 grid-cols-' . $this->column, + 'child' => $childs + ]; + + } + +} diff --git a/admin/components/UI/Widget/Table.php b/admin/components/UI/Widget/Table.php new file mode 100644 index 0000000..811a557 --- /dev/null +++ b/admin/components/UI/Widget/Table.php @@ -0,0 +1,44 @@ +callback = $callback; + $this->table = new \backend\components\UI\Table($data); + } + + /** + * @return string + */ + public function render(): string + { + return $this->table->render(); + } + + /** + * @param $method + * @param $arguments + * @return mixed + */ + public function __call($method, $arguments) + { + return $this->table->$method(...$arguments); + } + +} diff --git a/admin/components/UI/Widget/TreeList.php b/admin/components/UI/Widget/TreeList.php new file mode 100644 index 0000000..d41a6cc --- /dev/null +++ b/admin/components/UI/Widget/TreeList.php @@ -0,0 +1,165 @@ +key = $default; + $this->field = $field; + $this->event = $event; + } + + /** + * @param bool $bool + * @param array $keyword + * @return $this + */ + public function search(bool $bool = true, array $keyword = []): self + { + $this->search = $bool; + $this->keyword = $keyword; + return $this; + } + + /** + * @param array $data + * @return $this + */ + public function menu(array $data = []): self + { + $this->menu = $data; + return $this; + } + + /** + * @param string|null $url + * @return $this + */ + public function url(string $url = null): self + { + $this->url = $url; + return $this; + } + + /** + * @param string|null $url + * @return $this + */ + public function sortUrl(string $url = null): self + { + $this->sortUrl = $url; + return $this; + } + + /** + * @param string $filter + * @return $this + */ + public function filter(string $filter): self + { + $this->filter = $filter; + return $this; + } + + public function fieldNames(array $map): self + { + $this->fieldNames = $map; + return $this; + } + + /** + * @param $node + * @return $this + */ + public function label($node): TreeList + { + $this->labelNode = $node; + return $this; + } + + /** + * @return array + */ + public function render(): array + { + $urlPaths = parse_url(substr($this->url, 0, strrpos($this->url, "/"))); + $tree = [ + 'nodeName' => 'widget-tree', + 'url' => $this->url, + 'sortUrl' => $this->sortUrl, + 'search' => $this->search, + 'keywords' => $this->keyword, + 'requestEventName' => md5($this->event), + 'vBind:filter' => $this->filter ?: '', + 'refreshUrls' => [trim($urlPaths['path'], '/')], + 'iconColor' => ['blue', 'cyan', 'green', 'orange', 'red', 'purple'], + 'vModel:value' => "data.filter['{$this->field}']", + ]; + + if ($this->fieldNames) { + $tree['fieldNames'] = $this->fieldNames; + } + + if ($this->labelNode) { + $tree['child'] = [ + 'nodeName' => 'span', + 'vSlot:label' => 'item', + 'child' => $this->labelNode + ]; + } + + $menu = []; + if ($this->menu) { + foreach ($this->menu as $key => $vo) { + $url = $vo['url']; + $event = $vo['event']; + $tmp = [ + 'text' => $vo['name'], + ]; + $tmp['key'] = $key; + if ($event) { + $tmp['event'] = $event; + } else { + switch ($vo['type']) { + case 'dialog': + $tmp['event'] = $url ? "window.router.dialog($url)" : "window.dialog.alert({content: '未定义链接数据'})"; + break; + case 'ajax': + $tmp['event'] = $url ? "window.router.ajax($url, {_method: 'POST', _title: '确认进行{$vo['name']}操作?'})" : "window.dialog.alert({content: '未定义链接数据'})"; + break; + default: + $tmp['event'] = $url ? "window.router.push($url)" : "window.dialog.alert({content: '未定义链接数据'})"; + } + } + $menu[] = $tmp; + } + $tree['contextMenus'] = $menu; + } + + return $tree; + } +} diff --git a/admin/components/UI/Widget/Widget.php b/admin/components/UI/Widget/Widget.php new file mode 100644 index 0000000..077e915 --- /dev/null +++ b/admin/components/UI/Widget/Widget.php @@ -0,0 +1,110 @@ +attr[$name] = $value; + return $this; + } + + /** + * class样式 + * @param string $name + * @return $this + */ + public function class(string $name): self + { + $this->class[] = $name; + return $this; + } + + /** + * 设置样式 + * @param string $name + * @param string $value + * @return $this + */ + public function style(string $name, string $value): self + { + $this->style[$name] = $value; + return $this; + } + + /** + * 设置变量 + * @param $name + * @param $value + * @return $this + */ + public function setValue($name, $value): self + { + $this->$name = $value; + return $this; + } + + /** + * 获取变量 + * @param $name + * @return mixed + */ + public function getValue($name) + { + return $this->$name; + } + + /** + * 合并数组 + * @param array $array + * @param string $str + * @return string + */ + public function mergeArray(array $array, string $str = ''): string + { + return implode($str, $array); + } + + /** + * 回调设置 + * @return $this + */ + public function next(): Widget + { + if (!$this->callback) { + return $this; + } + $this->callbackData = call_user_func($this->callback, $this); + return $this; + } + + /** + * @return array + */ + public function getRender(): array + { + return array_merge($this->render(), $this->attr); + } + + +} diff --git a/admin/components/UI/yii/Arr.php b/admin/components/UI/yii/Arr.php new file mode 100644 index 0000000..054273f --- /dev/null +++ b/admin/components/UI/yii/Arr.php @@ -0,0 +1,113 @@ + $key) { + if (count($keys) === 1) { + break; + } + + unset($keys[$i]); + + // If the key doesn't exist at this depth, we will just create an empty array + // to hold the next value, allowing us to create the arrays to hold final + // values at the correct depth. Then we'll keep digging into the array. + if (! isset($array[$key]) || ! is_array($array[$key])) { + $array[$key] = []; + } + + $array = &$array[$key]; + } + + $array[array_shift($keys)] = $value; + + return $array; + } + + public static function has($array, $keys) + { + $keys = (array) $keys; + + if (! $array || $keys === []) { + return false; + } + + foreach ($keys as $key) { + $subKeyArray = $array; + + if (static::exists($array, $key)) { + continue; + } + + foreach (explode('.', $key) as $segment) { + if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) { + $subKeyArray = $subKeyArray[$segment]; + } else { + return false; + } + } + } + + return true; + } + public static function get($array, $key, $default = null) + { + if (! static::accessible($array)) { + return value($default); + } + + if (is_null($key)) { + return $array; + } + + if (static::exists($array, $key)) { + return $array[$key]; + } + + if (strpos($key, '.') === false) { + return $array[$key] ?? value($default); + } + + foreach (explode('.', $key) as $segment) { + if (static::accessible($array) && static::exists($array, $segment)) { + $array = $array[$segment]; + } else { + return value($default); + } + } + + return $array; + } + public static function accessible($value) + { + return is_array($value) || $value instanceof \ArrayAccess; + } + public static function exists($array, $key) + { + if ($array instanceof Enumerable) { + return $array->has($key); + } + + if ($array instanceof \ArrayAccess) { + return $array->offsetExists($key); + } + + return array_key_exists($key, $array); + } +} diff --git a/admin/components/UI/yii/Str.php b/admin/components/UI/yii/Str.php new file mode 100644 index 0000000..20b6f7b --- /dev/null +++ b/admin/components/UI/yii/Str.php @@ -0,0 +1,80 @@ + [ + [ + 'app'=>'store', + 'name'=>'我的', + 'title'=>null, + "icon"=>"icon-tags", + "url"=>'/admin/supplier/agent-store', + 'route'=>'', + 'topic'=>'我的', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'门店', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'我的门店', + 'title'=>null, + 'url'=>'/admin/supplier/agent-store', + 'target'=>null + ], + [ + 'name'=>'我的店员', + 'title'=>null, + 'url'=>'/admin/supplier/agent-clerk', + 'target'=>null + ], + ] + ], + [ + 'name'=>'订单', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'订单列表', + 'title'=>null, + 'url'=>'/admin/supplier/agent-order', + 'target'=>null + ] + ] + ] + ] + ], +]]; \ No newline at end of file diff --git a/admin/config/bootstrap.php b/admin/config/bootstrap.php new file mode 100644 index 0000000..ce73d66 --- /dev/null +++ b/admin/config/bootstrap.php @@ -0,0 +1,118 @@ + $v) { + preg_match('/(?:\{)(.*)(?:\})/i', $v, $match); + if (isset($match[1])) { + $paramsFix[$k] = $match[1]; + $data[$k] = 'Ss' . $k . 'sS'; + } else { + if (in_array($v, $field)) { + $paramsModel[$k] = $v; + $data[$k] = 'Ss' . $k . 'sS'; + } else { + $data[$k] = $v; + } + } + } + + $url = route($route, $data, $absolute); + + // 解析js变量 + foreach ($paramsFix as $k => $v) { + $url = str_replace('Ss' . $k . 'sS', '${' . $v . ' || \'\'}', $url); + } + foreach ($paramsModel as $k => $v) { + $url = str_replace('Ss' . $k . 'sS', '${' . ($model ? $model . '.' : '') . $v . '|| \'\'}', $url); + } + $url = "`$url`"; + + return $url; + } +} + +if (!function_exists("app_filesize")) { + /** + * 文件大小转换 + * @param $num + * @return string + */ + function app_filesize($num) + { + $p = 0; + $format = 'bytes'; + if ($num > 0 && $num < 1024) { + $p = 0; + return number_format($num) . ' ' . $format; + } + if ($num >= 1024 && $num < pow(1024, 2)) { + $p = 1; + $format = 'KB'; + } + if ($num >= pow(1024, 2) && $num < pow(1024, 3)) { + $p = 2; + $format = 'MB'; + } + if ($num >= pow(1024, 3) && $num < pow(1024, 4)) { + $p = 3; + $format = 'GB'; + } + if ($num >= pow(1024, 4) && $num < pow(1024, 5)) { + $p = 3; + $format = 'TB'; + } + $num /= pow(1024, $p); + return number_format($num, 3) . ' ' . $format; + } +} + +if(!function_exists('route')){ + function route($route,$data,$absolute=true){ + //if(isset($data['id'])){ + // $route .='/'.$data['id']; + // unset($data['id']); + //} + //$data[0] = $route; + //return Yii::$app->urlManager->createUrl($data); + $http_build_query = http_build_query($data); + return $route.($http_build_query?'?'.$http_build_query:""); + } +} +if (!function_exists('url_class')) { + function url_class($url): array + { + return [ + 'class' => Yii::$app->controller->getUniqueId(), + 'action' => Yii::$app->controller->action->getUniqueId() + ]; + } +} diff --git a/admin/config/codeception-local.php b/admin/config/codeception-local.php new file mode 100644 index 0000000..2d875dd --- /dev/null +++ b/admin/config/codeception-local.php @@ -0,0 +1,11 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => 'PNBvDHRrIvzkhTPsX9HUCeCbXk8gX1HN', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => \yii\debug\Module::class, + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => \yii\gii\Module::class, + ]; +} + +return $config; diff --git a/admin/config/main.php b/admin/config/main.php new file mode 100644 index 0000000..b9f1586 --- /dev/null +++ b/admin/config/main.php @@ -0,0 +1,151 @@ + 'app-backend', + 'name'=>'萧康医院', + 'basePath' => dirname(__DIR__), + /* 控制器默认命名空间 */ + 'controllerNamespace' => 'admin\controllers', + /** + * 比较重要的属性,系统启动阶段(一般new application()最后)加载的组件或模块。 + * 如果该组件或模块实现BootstrapInterface接口,那么就会执行bootstrap()方法,yii/base/application类315行左右。 + * 应用案例:yii-debug扩展,或者设想我有个需求:在数据库中配置某些组件和模块的开启或关闭。这样可以不将这些组件或模块 + * 配置在config.php中,而写在数据库中,通过bootstrap()方法将这些组件模块动态加载到系统中。 + * 参考:http://www.yiichina.com/doc/guide/2.0/structure-applications#bootstrap + */ + 'bootstrap' => ['log'], + /** + * 模块 + */ + 'modules' => [ + 'v1' => [ + 'class' => 'admin\modules\v1\Module', + ], + 'doc'=>[ + 'class' => 'cfd\doc\Module', +// 'modelDescriptions'=>require __DIR__ . '/model_description.php', + 'modelsMap'=>[ + '\common\models\\', + '\common\modelsgii\\', + ] + ], + ], + /* 默认路由 */ + 'defaultRoute' => 'index', + /* 默认布局文件 优先级 控制器>配置文件>系统默认 */ + 'layout' => 'main', + /** + * 组件 + */ + 'components' => [ + // 身份认证类 默认yii\web\user + 'user' => [ + 'class' => 'yii\web\User', + 'identityClass' => 'admin\models\Admin', + 'enableSession' => false, //关闭session + 'enableAutoLogin' => true, + 'loginUrl' => null, //默认登录url + 'on afterLogin' => function ($event) { + $user = $event->identity; + $user->last_login_ip = ip2long(\Yii::$app->request->userIP); + $user->last_login_time = time(); + $user->save(); + } + ], + // 修改默认的request组件 + 'request' => [ + 'parsers' => [ + 'application/json' =>\yii\web\JsonParser::class + ] + ], + + // 数据库RBAC权限控制 + 'authManager' => [ + 'class' => 'common\core\rbac\DbManager', + ], + // 日志 + // 'log' => [ + // 'traceLevel' => YII_DEBUG ? 3 : 0, + // 'targets' => [ + // [ + // 'class' => 'yii\log\FileTarget', + // 'levels' => ['error', 'warning'],//info会记录一些删除的信息,放开一下 + // ], + // ], + // ], + // 错误处理器 + /*'errorHandler' => [ + 'errorAction' => 'public/404', + ],*/ + + // 链接管理 + 'urlManager' => [ + 'class' => 'common\core\UrlManager', + 'enablePrettyUrl' => 'BACKEND_PRETTY_URL', //开启url规则 + 'showScriptName' => false, //是否显示链接中的index.php + //'suffix' => '.html', //后缀 + 'rules' => [ + // + ], + ], + // 响应组件 + 'response' => [ + 'class' => 'yii\web\Response', + 'format' => \yii\web\Response::FORMAT_JSON, + 'formatters' => [ + \yii\web\Response::FORMAT_JSON => [ + 'class' => 'admin\foundation\JsonResponseFormatter', + 'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode + 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, + ], + ], + ], + /** + * 这里要注意了,由于我使用的是模板自带的jQuery和bootstrap,所以这里就先清空系统的jQuery和bootstrap + * 基本上所有的插件都是使用了yii\web\JqueryAsset, + * 为了模板全局的js/css放在其他插件的前面,这里我设置了yii\web\JqueryAsset依赖backend\assets\AppAsset + */ + //'assetManager' => [ + // 'bundles' => [ + // 'yii\web\JqueryAsset' => [ + // 'sourcePath' => null, + // 'js' => [], + // 'depends' => [ + // 'backend\assets\AppAsset' + // ] + // ], + // 'yii\bootstrap\BootstrapAsset' => [ + // 'css' => [] + // ], + // ], + // + //], + ], + /** + * 该属性允许你用一个数组定义多个 别名 代替 Yii::setAlias() + */ + 'aliases' => [ + '@bower' => '@vendor/bower-asset' + ], + /** + * 通过配置文件附加行为,全局 + */ + //'as rbac' => [ + // 'class' => 'admin\behaviors\RbacBehavior', + // 'allowActions' => [ + // 'login/login', 'v1/admin/login','v1/admin/my-menu', 'login/logout', 'public*', 'debug/*', 'gii/*', 'order/settle-result' // 不需要权限检测 + // ] + //], + + 'params' => $params, +]; diff --git a/admin/config/menu.php b/admin/config/menu.php new file mode 100644 index 0000000..68e47b4 --- /dev/null +++ b/admin/config/menu.php @@ -0,0 +1,221 @@ + [ + [ + 'app'=>'dashboard', + 'name'=>'控制台', + 'title'=>null, + "icon"=>"icon-dashboard", + "url"=>'/admin/dashboard/index', + 'route'=>'', + 'topic'=>'控制台', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'控制台', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'概况', + 'title'=>null, + 'url'=>'/admin/dashboard/index', + 'target'=>null + ] + ] + ] + ] + ], + [ + 'app'=>'store', + 'name'=>'门店', + 'title'=>null, + "icon"=>"icon-tags", + "url"=>'/admin/store/mall', + 'route'=>'', + 'topic'=>'门店', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'门店', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'门店管理', + 'title'=>null, + 'url'=>'/admin/store/mall', + 'target'=>null + ], + ] + ] + ] + ], + [ + 'app'=>'supplier', + 'name'=>'供应商', + 'title'=>null, + "icon"=>"icon-interaction", + "url"=>'/admin/supplier/supplier', + 'route'=>'', + 'topic'=>'供应商', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'供应商', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'供应商列表', + 'title'=>null, + 'url'=>'/admin/supplier/supplier', + 'target'=>null + ], + [ + 'name'=>'业务员列表', + 'title'=>null, + 'url'=>'/admin/supplier/agent', + 'hidden'=>true, + 'target'=>null + ], + ] + ] + ] + ], + [ + 'app'=>'order', + 'name'=>'订单', + 'title'=>null, + "icon"=>"icon-apps", + "url"=>'/admin/order/admin-order/index', + 'route'=>'', + 'topic'=>'订单', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'订单', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'订单列表', + 'title'=>null, + 'url'=>'/admin/order/admin-order/index', + 'target'=>null + ] + ] + ] + ] + ], + [ + 'app'=>'goods', + 'name'=>'商品', + 'title'=>null, + "icon"=>"icon-common", + "url"=>'/admin/goods/drug', + 'route'=>'', + 'topic'=>'商品', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'商品', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'基础商品库', + 'title'=>null, + 'url'=>'/admin/goods/drug', + 'target'=>null + ], + [ + 'name'=>'基础分类', + 'title'=>null, + 'url'=>'/admin/goods/drug-category', + 'target'=>null + ], + ] + ] + ] + ], + [ + 'app'=>'user', + 'name'=>'用户', + 'title'=>null, + "icon"=>"icon-user", + "url"=>'/admin/user/user', + 'route'=>'', + 'topic'=>'商品', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'普通用户', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'用户列表', + 'title'=>null, + 'url'=>'/admin/user/user', + 'target'=>null + ] + ] + ], + [ + 'name'=>'店员', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'店员列表', + 'title'=>null, + 'url'=>'/admin/user/clerk', + 'target'=>null + ], + [ + 'name'=>'兑换记录', + 'title'=>null, + 'url'=>'/admin/user/clerk-exchange', + 'target'=>null + ], + [ + 'name'=>'兑换物品', + 'title'=>null, + 'url'=>'/admin/user/clerk-exchange-goods', + 'target'=>null + ] + ] + ] + ] + ], + [ + 'app'=>'system', + 'name'=>'设置', + 'title'=>null, + "icon"=>"icon-settings", + "url"=>'/admin/system/index', + 'route'=>'', + 'topic'=>'设置', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'系统设置', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'基础配置', + 'title'=>null, + 'url'=>'/admin/system/index', + 'target'=>null + ], + [ + 'name'=>'配置项管理', + 'title'=>null, + 'url'=>'/admin/system/config', + 'target'=>null + ], + ] + ] + ] + ], +]]; \ No newline at end of file diff --git a/admin/config/params-local.php b/admin/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/admin/config/params-local.php @@ -0,0 +1,4 @@ + 'admin@example.com', + + /* 超级管理员的UID */ + 'admin' => 2, + /* 后台系统配置 类型 和 分组 */ + 'config_type' => [ + 0 => '数字', + 1 => '字符', + 2 => '文本', + 3 => '数组', + 4 => '单选', + 5 => '富文本', + 6 => '多选', + ], +]; diff --git a/admin/config/store_menu.php b/admin/config/store_menu.php new file mode 100644 index 0000000..ac90704 --- /dev/null +++ b/admin/config/store_menu.php @@ -0,0 +1,213 @@ + [ + [ + 'app'=>'dashboard', + 'name'=>'控制台', + 'title'=>null, + "icon"=>"icon-dashboard", + "url"=>'/admin/dashboard/index', + 'route'=>'', + 'topic'=>'控制台', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'控制台', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'概况', + 'title'=>null, + 'url'=>'/admin/dashboard/index', + 'target'=>null + ] + ] + ] + ] + ], + [ + 'app'=>'store', + 'name'=>'店铺', + 'title'=>null, + "icon"=>"icon-dashboard", + "url"=>'/admin/store/banner/index', + 'route'=>'', + 'topic'=>'店铺', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'轮播图', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'轮播图', + 'title'=>null, + 'url'=>'/admin/store/banner/index', + 'target'=>null + ], +// [ +// 'name'=>'下载中心', +// 'title'=>null, +// 'url'=>'/admin/store/file/index', +// 'target'=>null +// ] + ] + ] + ] + ], + [ + 'app'=>'order', + 'name'=>'订单', + 'title'=>null, + "icon"=>"icon-apps", + "url"=>'/admin/order/order/index', + 'route'=>'', + 'topic'=>'订单', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'订单', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'订单列表', + 'title'=>null, + 'url'=>'/admin/order/order/index', + 'target'=>null + ], + [ + 'name'=>'售后', + 'title'=>null, + 'url'=>'/admin/order/aftersell/index', + 'target'=>null + ], + ] + ] + ] + ], + [ + 'app'=>'goods', + 'name'=>'商品', + 'title'=>null, + "icon"=>"icon-common", + "url"=>'/admin/goods/goods', + 'route'=>'', + 'topic'=>'商品', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'商品', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'商品列表', + 'title'=>null, + 'url'=>'/admin/goods/goods', + 'target'=>null + ], + [ + 'name'=>'商品分类列表', + 'title'=>null, + 'url'=>'/admin/goods/goods-cats', + 'target'=>null + ], + ] + ] + ] + ], + [ + 'app'=>'marketing', + 'name'=>'营销', + 'title'=>null, + "icon"=>"icon-fire", + "url"=>'/admin/marketing/coupon', + 'route'=>'', + 'topic'=>'营销', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'满减', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'满减活动列表', + 'title'=>null, + 'url'=>'/admin/marketing/reduce/index', + 'target'=>null + ], + ] + ], + [ + 'name'=>'优惠券', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'优惠券管理', + 'title'=>null, + 'url'=>'/admin/marketing/coupon', + 'target'=>null + ], + //[ + // 'name'=>'自动发放', + // 'title'=>null, + // 'url'=>'/admin/marketing/coupon-send', + // 'target'=>null + //], + //[ + // 'name'=>'使用记录', + // 'title'=>null, + // 'url'=>'/admin/marketing/coupon-use', + // 'target'=>null + //], + //[ + // 'name'=>'发放统计', + // 'title'=>null, + // 'url'=>'/admin/marketing/coupon-analysis', + // 'target'=>null + //], + ] + ] + ] + ], + [ + 'app'=>'system', + 'name'=>'设置', + 'title'=>null, + "icon"=>"icon-settings", + "url"=>'/admin/system/delivery/postage-rule', + 'route'=>'', + 'topic'=>'设置', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'物流设置', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'运费规则', + 'title'=>null, + 'url'=>'/admin/system/delivery/postage-rule', + 'target'=>null + ], + [ + 'name'=>'包邮规则', + 'title'=>null, + 'url'=>'/admin/system/free-rule', + 'target'=>null + ], + [ + 'name'=>'退货地址', + 'title'=>null, + 'url'=>'/admin/system/refund-address', + 'target'=>null + ], + ] + ] + ] + ], +]]; \ No newline at end of file diff --git a/admin/config/supplier_menu.php b/admin/config/supplier_menu.php new file mode 100644 index 0000000..f80432e --- /dev/null +++ b/admin/config/supplier_menu.php @@ -0,0 +1,52 @@ + [ + [ + 'app'=>'order', + 'name'=>'商品', + 'title'=>null, + "icon"=>"icon-common", + "url"=>'/admin/supplier/supplier-drug/index', + 'route'=>'', + 'topic'=>'订单', + 'hidden'=>false, + 'target'=>null, + "menu"=>[ + [ + 'name'=>'商品', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'供应商品', + 'title'=>null, + 'url'=>'/admin/supplier/supplier-drug/index', + 'target'=>null + ], + ] + ], + [ + 'name'=>'业务员', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'业务员', + 'title'=>null, + 'url'=>'/admin/supplier/supplier-agent/index', + 'target'=>null + ], + ] + ], + [ + 'name'=>'订单', + 'title'=>null, + 'menu'=>[ + [ + 'name'=>'订单列表', + 'title'=>null, + 'url'=>'/admin/supplier/supplier-order/index', + 'target'=>null + ], + ] + ], + ] + ], +]]; \ No newline at end of file diff --git a/admin/config/test-local.php b/admin/config/test-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/admin/config/test-local.php @@ -0,0 +1,4 @@ + 'app-admin-tests', + 'components' => [ + 'assetManager' => [ + 'basePath' => __DIR__ . '/../web/assets', + ], + 'urlManager' => [ + 'showScriptName' => true, + ], + 'request' => [ + 'cookieValidationKey' => 'test', + ], + ], +]; diff --git a/admin/controllers/AdminController.php b/admin/controllers/AdminController.php new file mode 100644 index 0000000..d6ed8a6 --- /dev/null +++ b/admin/controllers/AdminController.php @@ -0,0 +1,393 @@ + + */ +class AdminController extends BaseAdminController +{ + public $modelClass = Admin::class; + public $roles; + public $login_role; + + /** + * --------------------------------------- + * 构造方法 + * --------------------------------------- + */ + public function init() + { + parent::init(); + } + // + //public function beforeAction($action) + //{ + // $user_id = Yii::$app->user->identity->getId(); + // $login_role = Yii::$app->authManager->getRolesByUser($user_id); + // $this->login_role = array_keys($login_role)[0]; + // + // if(Yii::$app->params['admin'] == Yii::$app->user->id){ + // $roles = Yii::$app->authManager->getRoles(); + // }else{ + // $roles = Yii::$app->authManager->getChildRoles($this->login_role); + // unset($roles[$this->login_role]); + // } + // $this->roles = $roles; + // + // $uid = Yii::$app->request->get('uid'); + // if($uid){ + // $assign = Yii::$app->authManager->getAssignments($uid); + // $role = array_keys($assign)[0]; + // //管理员只能管理下级管理员,不能管理同级和上级管理员 + // if(!in_array($role,array_keys($roles))){ + // throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.')); + // } + // } + // return parent::beforeAction($action); // TODO: Change the autogenerated stub + //} + + + /** + * --------------------------------------- + * 后台用户列表 + * @doc-param int type 1内部账号2客户账号 + * @doc-param string search 搜索 / optional + * @doc-return @List{is_sub-int-是否子账号0否1是} + * --------------------------------------- + */ + public function actionIndex() + { + /* 添加当前位置到cookie供后续操作调用 */ +// $this->setForward(); + $admin = Yii::$app->user->identity; + $get = Yii::$app->request->get(); + $this->requestValidate($get,[ + ['type','required','message'=>'类型不能为空'] + ]); + $query = Admin::find(); + switch ($get['type']){ + case 1: + $query->andWhere(['<>','role',UserRoleEnum::STORE_ADMIN]); + break; + case 2: + $query->andWhere(['role'=>UserRoleEnum::STORE_ADMIN]); + break; + default: + throw new \yii\db\Exception('参数错误'); + } + + if (UserRoleEnum::STORE_ADMIN == $admin->role) { + $query->andWhere(['role' => UserRoleEnum::STORE_ADMIN, 'store_id' => $admin->store_id]); + } + if (!empty($get['search'])){ + $query->andWhere([ + 'or', + ['mobile'=>$get['search']], + ['like','username',$get['search']] + ]); + } + + $this->field = [ + Admin::class => [ + 'uid', 'username', 'password', 'mobile', 'store_id', 'store' => 'store.name', 'role_id' => 'role', 'role' => 'roles.name', 'is_sub','code','province_id','city_id', + 'province'=>'province.name', + 'city'=>'city.name', + 'status' + ] + ]; + return $this->create($query, $get); + } + + /** + * --------------------------------------- + * 添加 + * --------------------------------------- + */ + public function actionAdd() + { + + $model = new Admin(); + + if (Yii::$app->request->isPost) { + /* 表单验证 */ + $data = Yii::$app->request->post('Admin'); + $data['reg_time'] = time(); + $data['reg_ip'] = ip2long(Yii::$app->request->getUserIP()); + $data['last_login_time'] = 0; + $data['last_login_ip'] = ip2long('127.0.0.1'); + $data['update_time'] = 0; + /* 表单数据加载和验证,具体验证规则在模型rule中配置 */ + /* 密码单独验证,否则setPassword后密码肯定符合rule */ + if (empty($data['password']) || strlen($data['password']) < 6) { + $this->error('密码为空或小于6字符'); + } + $model->setAttributes($data); + $model->generateAuthKey(); + $model->setPassword($data['password']); + if (!isset($data['role']) || !$data['role']) { + $this->error('未选择任何角色'); + } + /* 保存用户数据到数据库 */ + if ($model->save()) { + + /* 先删除 用户组-用户 记录 */ + Yii::$app->authManager->revokeAll($model->uid); + /* 再添加记录 */ + $role = Yii::$app->authManager->getRole($data['role']); + Yii::$app->authManager->assign($role, $model->uid); + + $this->success('操作成功', $this->getForward()); + } else { + $this->error('操作错误:' . array_values($model->getFirstErrors())[0]); + } + } + + //获取下属角色 + $roles = array_map(function ($n) { + return $n->name; + }, $this->roles); + + $model->role = reset($roles); + $model->status = 1; + + return $this->render('add', [ + 'model' => $model, + 'roles' => $roles + ]); + } + + /** + * --------------------------------------- + * 编辑 + * --------------------------------------- + */ + public function actionEdit($uid) + { + $model = Admin::findOne($uid); + + if (Yii::$app->request->isPost) { + /* 表单验证 */ + $data = Yii::$app->request->post('Admin'); + $data['update_time'] = time(); + /* 如果设置密码则重置密码,否则不修改密码 */ + if (!empty($data['password'])) { + $model->generateAuthKey(); + $model->setPassword($data['password']); + } + unset($data['password']); + if (!isset($data['role']) || !$data['role']) { + $this->error('未选择任何角色'); + } + + $model->setAttributes($data); + /* 保存用户数据到数据库 */ + if ($model->save()) { + + /* 先删除 用户组-用户 记录 */ + Yii::$app->authManager->revokeAll($model->uid); + /* 再添加记录 */ + $role = Yii::$app->authManager->getRole($data['role']); + Yii::$app->authManager->assign($role, $model->uid); + + $this->success('操作成功', $this->getForward()); + } else { + $this->error('操作错误'); + } + } + + $roles = array_map(function ($n) { + return $n->name; + }, $this->roles); + + $assign = Yii::$app->authManager->getAssignments($model->uid); + $model->role = array_keys($assign)[0]; + $model->password = ''; + return $this->render('edit', [ + 'model' => $model, + 'roles' => $roles + ]); + } + + /** + * --------------------------------------- + * 删除 + * --------------------------------------- + */ + public function actionDelete() + { + $ids = Yii::$app->request->param('uid', 0); + $ids = implode(',', array_unique((array)$ids)); + + if (empty($ids)) { + $this->error('请选择要操作的数据!'); + } + + /* 不能删除超级管理员 */ + if (in_array(Yii::$app->params['admin'], explode(',', $ids))) { + $this->error('不能删除超级管理员!'); + } + + $_where = 'uid in(' . $ids . ')'; + if (Admin::deleteAll($_where)) { + foreach (explode(',', $ids) as $uid) { + Yii::$app->authManager->revokeAll($uid); + } + + $this->success('删除成功', $this->getForward()); + } else { + $this->error('删除失败!'); + } + } + + /** + * 个人信息 + */ + public function actionPersonal() + { + $user_id = Yii::$app->user->identity->getId(); + $model = Admin::findOne($user_id); + + if (Yii::$app->request->isPost) { + /* 表单验证 */ + $data = Yii::$app->request->post('Admin'); + $data['update_time'] = time(); + /* 如果设置密码则重置密码,否则不修改密码 */ + if (!empty($data['password'])) { + $model->generateAuthKey(); + $model->setPassword($data['password']); + } + unset($data['password']); + $model->setAttributes($data); + /* 保存用户数据到数据库 */ + if ($model->save()) { + $this->success('操作成功', $this->getForward()); + } else { + $this->error('操作错误'); + } + } + + $model->password = ''; + return $this->render('personal', [ + 'model' => $model + ]); + } + + /** + * 个人信息 + */ + public function actionEditPass() + { + $user_id = Yii::$app->user->identity->getId(); + $model = Admin::findOne($user_id); + + /* 表单验证 */ + $data = Yii::$app->request->post(); + $data['update_time'] = time(); + /* 如果设置密码则重置密码,否则不修改密码 */ + if (isset($data['password']) && !empty($data['password'])) { + if (strlen($data['password']) < 6) { + throw new Exception('密码小于6字符'); + } + $model->generateAuthKey(); + $model->setPassword($data['password']); + } + unset($data['password']); + $model->setAttributes($data); + /* 保存用户数据到数据库 */ + $model->saveOrFail(); + } + + private function createMenuNode($name, $icon, $url) + { + return ['app' => 'index', 'name' => $name, 'title' => null, 'icon' => $icon, 'url' => $url, 'route' => '', 'topic' => '', 'hidden' => false, 'target' => null]; + } + + public function actionMyMenu() + { + $role = Yii::$app->user->identity->role; +//角色1为官方管理,2为市场专员,3为客服,4为供应商管理,5为业务员,6为门店管理 + if ($role == 1) { + return ['list' => Yii::$app->params['menu']]; + } else if ($role == 6) { + return ['list' => Yii::$app->params['store_menu']]; + } else if ($role == 5) { + return ['list' => Yii::$app->params['agent_menu']]; + } else if ($role == 4) { + return ['list' => Yii::$app->params['supplier_menu']]; + } + } + + public function actionMenu() + { + if (Yii::$app->user->identity->is_sub === 1) { + $userMenus = SubAccountMenu::findAll(['admin_id' => Yii::$app->user->identity->uid]); + } else { + $role = Yii::$app->user->identity->role; + $userMenus = RoleMenu::findAll(['role_id' => $role]); + } + + $keys = ArrayHelper::getColumn($userMenus, 'menuUrl'); + $menus = Menu::find()->where(['in', 'menuUrl', $keys])->orderBy(['sort' => SORT_ASC])->asArray()->all(); + return ArrayHelper::itemsMerge($menus, 0, 'menuUrl', 'parentPath', 'children'); + + ////当前用户menu + //return ['list'=> Yii::$app->params['menu']]; + + } + + /** + * --------------------------------------- + * 用户授权 + * --------------------------------------- + */ +// public function actionAuth($uid) +// { +// $auth = Yii::$app->authManager; +// /* 获取用户信息 */ +// $model = Admin::findOne($uid); +// +// if (Yii::$app->request->isPost) { +// $data = Yii::$app->request->post(); +// /* 用户权限组 */ +// $item_name = $data['param']; +// +// /* 先删除 用户组-用户 记录 */ +// $auth->revokeAll($uid); +// /* 再添加记录 */ +// $role = $auth->getRole($item_name); +// $auth->assign($role, $uid); +// +// $this->success('授权成功!', $this->getForward()); +// +// var_dump($data['param']); +// exit; +// } +// +// /* 获取所有权限组 */ +// $roles = $auth->getRoles(); +// /* 获取该用户的权限 */ +// $group = array_keys($auth->getAssignments($uid)); +// //var_dump($group);exit; +// +// return $this->render('auth', [ +// 'model' => $model, +// 'roles' => $roles, +// 'group' => $group +// ]); +// } + +} diff --git a/admin/controllers/AttachmentController.php b/admin/controllers/AttachmentController.php new file mode 100644 index 0000000..d8316c1 --- /dev/null +++ b/admin/controllers/AttachmentController.php @@ -0,0 +1,27 @@ + $uploadService->index($name)]; + } +} \ No newline at end of file diff --git a/admin/controllers/AuthController.php b/admin/controllers/AuthController.php new file mode 100644 index 0000000..4d9295c --- /dev/null +++ b/admin/controllers/AuthController.php @@ -0,0 +1,453 @@ +authManager = \Yii::$app->authManager; + } + + public function beforeAction($action) + { + parent::beforeAction($action); // TODO: Change the autogenerated stub + //验证权限 + if ($this->actionCheckAuth()) { + return true; + } + throw new ForbiddenHttpException(\Yii::t('yii', 'You are not allowed to perform this action.')); + } + + + /** + * @doc-name 权限列表 + * @doc-param int role_id 角色id + * @doc-return mixed @List{AuthRule{id,pid,component-string-组件地址,title-string-权限名称,path-string-权限对应路由,redirect-string-跳转路由,icon-string-菜单图标,api_url-int-接口地址,status-int-权限状态1启用 0禁用} 规则列表 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionRuleList() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['role_id','required'] + ]); + + if ($get['role_id']==UserRoleEnum::SUPER_ADMIN ){ + $data=['217','218','219']; + $AuthRule = AuthRule::find()->where(['hidden' => 0])->andWhere(['not in','id',$data])->asArray()->all(); + }elseif($get['role_id']==UserRoleEnum::STORE_ADMIN){ + $data=['219']; + $AuthRule = AuthRule::find()->where(['hidden' => 0])->andWhere(['not in','id',$data])->asArray()->all(); + }else{ + $AuthRule = AuthRule::find()->where(['hidden' => 0])->asArray()->all(); + } + + return ArrayHelper::list_to_tree($AuthRule, 'id', 'pid', 'children'); + } + + /** + * @doc-name 添加权限 + * @doc-param int pid 父级id / optional + * @doc-param string title 权限名称 + * @doc-param string path 权限对应路由 + * @doc-param string component 组件地址 / optional + * @doc-param string redirect 跳转路由 / optional + * @doc-param string icon 菜单图标 / optional + * @doc-param string api_url 接口地址 / optional + * @doc-param int status 权限状态 1启用 0 禁用 / optional + */ + public function actionAddRule() + { + if (\Yii::$app->request->isPost) { + $data = \Yii::$app->request->post(); + + $this->requestValidate($data, [ + [['pid', 'title', 'path', 'status'], 'required'], + ]); + $path = 'Admin/' . $data['path']; + $path = explode('/', $path); + foreach ($path as $value) { + $v = ucfirst($value); + $arr[] = $v; + } + $new_path = implode('/', $arr); + + $AuthRule = AuthRule::find()->where(['path' => $new_path])->one(); + if ($AuthRule) throw new Exception('权限已存在'); + $data['path'] = $new_path; + + $model = new AuthRule(); + $model->setAttributes($data); + if (!$model->saveOrFail()) { + throw new Exception('添加失败' . array_values($model->getFirstErrors())[0]); + } else { + return ['添加成功']; + } + } + throw new Exception('请求方式错误'); + } + + /** + * @doc-name 编辑权限 + * @doc-param int id id + * @doc-param int pid 父级id / optional + * @doc-param string title 权限名称 + * @doc-param string path 权限对应路由 + * @doc-param string component 组件地址 / optional + * @doc-param string redirect 跳转路由 / optional + * @doc-param string icon 菜单图标 / optional + * @doc-param string api_url 接口地址 / optional + * @doc-param int status 权限状态 1启用 0 禁用 / optional + */ + public function actionEditRule() + { + if (\Yii::$app->request->isPost) { + $data = \Yii::$app->request->post(); + $this->requestValidate($data, [ + ['id', 'required'], + ]); + + $AuthRule = AuthRule::find()->where(['id' => $data['id']])->one(); + if (!$AuthRule) throw new Exception('需要编辑的规则不存在'); + + $AuthRule->pid = $data['pid'] ?? $AuthRule->pid; + $AuthRule->title = $data['title'] ?? $AuthRule->title; + $AuthRule->path = $data['path'] ?? $AuthRule->path; + $AuthRule->component = $data['component'] ?? $AuthRule->component; + $AuthRule->redirect = $data['redirect'] ?? $AuthRule->redirect; + $AuthRule->icon = $data['icon'] ?? $AuthRule->icon; + $AuthRule->api_url = $data['api_url'] ?? $AuthRule->api_url; + $AuthRule->status = $data['status'] ?? $AuthRule->status; + if (!$AuthRule->saveOrFail()) { + throw new Exception('编辑失败'); + } + return ['编辑成功']; + } + throw new Exception('请求方式错误'); + } + + /** + * @doc-name 删除权限 + * @doc-param int id id + */ + public function actionDelRule() + { + $data = \Yii::$app->request->get(); + $this->requestValidate($data, [ + ['id', 'required'], + ]); + + $id = AuthRule::find()->where(['id' => $data['id']])->one(); + if (!$id) throw new Exception('所删除的权限不存在'); + $t = \Yii::$app->db->beginTransaction(); + try { + //删除权限 + $id->delete(); + + //删除角色的权限 + AuthRole::deleteAll(['rule_id' => $id]); + + $t->commit(); + return ['删除成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 角色列表 + */ + public function actionRoleList() + { + + $data = \Yii::$app->request->get(); + $query = Role::find()->where(['>','id',9]); + + $this->field = [ + Role::class => [ + 'id', 'name', 'role_code', 'description', + 'authRole' => function ($a) { + return AuthRole::find()->where(['role_id' => $a->id])->all(); + } + ] + ]; + + return $this->create($query, $data); + } + + /** + * @doc-name 添加角色 + * @doc-param string name 名字 + * @doc-param string role_code + * @doc-param string description 描述 + */ + public function actionAddRole() + { + $data = \Yii::$app->request->post(); + $this->requestValidate($data, [ + ['name', 'required'], + ]); + + $role = Role::find()->where(['name' => $data['name']])->one(); + if ($role) throw new Exception('角色已经存在'); + $t = \Yii::$app->db->beginTransaction(); + try { + $model = new Role(); + $model->name = $data['name']; + $model->role_code = $data['role_code'] ?? ''; + $model->description = $data['description'] ?? ''; + $model->save(); + + $path = 'Admin/Menu/List'; + $AuthRule = AuthRule::find()->where(['path' => $path])->one(); + if (!$AuthRule) throw new Exception('菜单列表不存在'); + //添加菜单列表权限 + $AuthRole = AuthRole::find()->where(['role_id' => $model->id, 'rule_id' => $AuthRule->id])->one(); + if (!$AuthRole) { + $AuthRole = new AuthRole(); + $AuthRole->role_id = $model->id; + $AuthRole->rule_id = $AuthRule->id; + $AuthRole->saveOrFail(); + } + + $t->commit(); + return ['添加成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 编辑角色 + * @doc-param int id id + * @doc-param string name 名字 + * @doc-param string role_code + * @doc-param string description 描述 + */ + public function actionEditRole() + { + if (\Yii::$app->request->isPost) { + $data = \Yii::$app->request->post(); + $this->requestValidate($data, [ + ['id', 'required'], + ]); + + $edit_role = Role::find()->where(['id' => $data['id']])->one(); + if (!$edit_role) throw new Exception('角色不存在'); + if (!empty($data['name'])) { + $role = Role::find()->where(['name' => $data['name']])->andWhere(['!=', 'id', $data['id']])->one(); + if ($role) { + throw new Exception('角色已存在'); + } + } + + $edit_role->name = $data['name'] ?? $edit_role->name; + $edit_role->role_code = $data['role_code'] ?? $edit_role->role_code; + $edit_role->description = $data['description'] ?? $edit_role->description; + if (!$edit_role->save()) { + throw new Exception('编辑失败'); + } + return ['编辑成功']; + } + throw new Exception('请求方式错误'); + } + + /** + * @doc-name 删除角色 + * @doc-param int id id + */ + public function actionDelRole() + { + $data = \Yii::$app->request->get(); + $this->requestValidate($data, [ + ['id', 'required'], + ]); + + $role = Role::find()->where(['id' => $data['id']])->one(); + if (!$role) throw new Exception('所删除的角色不存在'); + $t = \Yii::$app->db->beginTransaction(); + try { + //删除权限 + $role->delete(); + + //删除角色的权限 + AuthRole::deleteAll(['role_id' => $role->id]); + $t->commit(); + return ['删除成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @@doc-name 给角色添加权限 + * @doc-param int role_id role_id + * @doc-param int rule_id 权限id 1,2,3 + * @doc-param int status 状态1启用 0禁用 + */ + public function actionRoleAddRule() + { + $data = \Yii::$app->request->post(); + $this->requestValidate($data, [ + [['role_id', 'rule_id', 'status'], 'required'], + ]); + + $rule_id = explode(',', $data['rule_id']); + $t = \Yii::$app->db->beginTransaction(); + try { + foreach ($rule_id as $value) { + $AuthRole = AuthRole::find()->where(['rule_id' => $value, 'role_id' => $data['role_id']])->one(); + if (!$AuthRole) { + $AuthRole = new AuthRole(); + $AuthRole->role_id = $data['role_id']; + $AuthRole->rule_id = $value; + $AuthRole->status = $data['status']; + $AuthRole->saveOrFail(); + } + } + + $t->commit(); + return ['添加成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @@doc-name 给角色修改权限 + * @doc-param int role_id role_id + * @doc-param int rule_id 权限id 1,2,3,4,5 + * @doc-param int status 状态1启用 0禁用 + */ + public function actionRoleEditRule() + { + $data = \Yii::$app->request->post(); + $this->requestValidate($data, [ + [['role_id', 'rule_id', 'status'], 'required'], + ]); + $rule_id = explode(',', $data['rule_id']); + $t = \Yii::$app->db->beginTransaction(); + try { + foreach ($rule_id as $value) { + $AuthRole = AuthRole::find()->where(['rule_id' => $value, 'role_id' => $data['role_id']])->one(); + if (!$AuthRole) { + $AuthRole = new AuthRole(); + $AuthRole->role_id = $data['role_id']; + $AuthRole->rule_id = $value; + $AuthRole->status = $data['status']; + $AuthRole->saveOrFail(); + } + } + + $all_rule_id = AuthRole::find()->select(['rule_id'])->where(['role_id' => $data['role_id']])->column(); + $arr = array_diff($all_rule_id, $rule_id); +// if ($data['role_id']!=UserRoleEnum::SUPER_ADMIN){ + foreach ($arr as $val) { + $AuthRole = AuthRole::find()->where(['role_id' => $data['role_id'], 'rule_id' => $val])->one(); + if ($AuthRole) { + $AuthRole->delete(); + } + } +// } + + $t->commit(); + return ['修改成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @@doc-name 给角色删除权限 + * @doc-param int id id + */ + public function actionRoleDelRule() + { + $data = \Yii::$app->request->get(); + $this->requestValidate($data, [ + ['id', 'required'], + ]); + $AuthRole = AuthRole::find()->where(['id' => $data['id']])->one(); + if (!$AuthRole) throw new Exception('该权限不存在'); + $AuthRole->delete(); + return ['删除成功']; + } + + /** + * @doc-name 查看角色权限 + * @doc-param int role_id 角色ID + * @doc-return mixed @List{id,role_id,rule_id,rule-string-权限} 查看角色权限列表 + */ + public function actionQueryRoleRule() + { + $data = \Yii::$app->request->get(); + $this->requestValidate($data, [ + ['role_id', 'required'], + ]); + + $query = AuthRole::find()->where(['role_id' => $data['role_id']]); + $this->field = [ + AuthRole::class => [ + 'id', 'role_id', 'rule_id', 'rule' => 'authRule.title' + ] + ]; + return $this->create($query, $data); + } + + + /** + * @doc-name 账号修改角色 + * @doc-param string mobile 手机号 + * @doc-param int role 角色 + */ + public function actionAccountEditRole() + { + + $data = \Yii::$app->request->get(); + $this->requestValidate($data, [ + [['mobile', 'role'], 'required'], + ]); + + $Admin = Admin::find()->where(['mobile' => $data['mobile']])->one(); + if (!$Admin) { + throw new Exception('账号不存在'); + } + + $role = Role::find()->where(['id' => $data['role']])->one(); + if (!$role) throw new Exception('角色不存在'); + + $Admin->role = $data['role']; + $Admin->saveOrFail(); + return []; + } + +} \ No newline at end of file diff --git a/admin/controllers/DoctorController.php b/admin/controllers/DoctorController.php new file mode 100644 index 0000000..12db9ed --- /dev/null +++ b/admin/controllers/DoctorController.php @@ -0,0 +1,66 @@ +request->post(); + $HospitalDocForm = new HospitalDocForm(); + $HospitalDocForm->attributes = $post; + + return $HospitalDocForm->grade(); + } + + /** + * 获取互医信息 + */ + public function actionHospitalDocInfo() + { + $post = \Yii::$app->request->post(); + $HospitalDocForm = new HospitalDocForm(); + $HospitalDocForm->attributes = $post; + + return $HospitalDocForm->DocInfo(); + } + + /** + * 同步患者 + */ + public function actionSyncPatient() + { + $post = \Yii::$app->request->post(); + $HospitalDocForm = new HospitalDocForm(); + $HospitalDocForm->attributes = $post; + + return $HospitalDocForm->SyncPatient(); + } + + /** + * @doc-name 医生审核 + * @doc-param int status 是否同意0否1是 + * @doc-param int doctor_id 医生id + */ + public function actionDoctorExamine() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['status','required'] + ]); + $HospitalDocForm = new HospitalDocForm(); + $HospitalDocForm->attributes = $post; + return $HospitalDocForm->ExamineDoc(); + } +} \ No newline at end of file diff --git a/admin/controllers/IndexController.php b/admin/controllers/IndexController.php new file mode 100644 index 0000000..884447a --- /dev/null +++ b/admin/controllers/IndexController.php @@ -0,0 +1,20 @@ + + */ +class IndexController extends BaseAdminController +{ + public $defaultAction = 'login-page'; + public function actionLoginPage() + { + return $this->render('login-page'); + } + +} diff --git a/admin/controllers/LoginController.php b/admin/controllers/LoginController.php new file mode 100644 index 0000000..78291a5 --- /dev/null +++ b/admin/controllers/LoginController.php @@ -0,0 +1,149 @@ +attributes=Yii::$app->request->post(); + + if (Yii::$app->request->isPost) { + /** @var $adminAccessToken AdminAccessToken */ + if ($model->load(Yii::$app->request->post(), '') && $adminAccessToken = $model->login()) { + $admin = Admin::find()->where(['uid' => $adminAccessToken->admin_id])->one(); + $admin = ArrayHelper::toArray($admin, [ + Admin::class => ['uid', 'username', 'role', 'mobile', 'store_id','code','city_id','province_id'], + ]); + $title = '萧康管理后台'; + switch ($admin['role']) { + case UserRoleEnum::SUPER_ADMIN: + $title = '萧康管理后台'; + break; + case UserRoleEnum::STORE_ADMIN: + $name = Store::find()->select(['name'])->where(['id' => $admin['store_id']])->one(); + $title = $name->name . '管理后台'; + break; + case UserRoleEnum::PROVINCE_DAI : + case UserRoleEnum::CITY_DAI: + case UserRoleEnum::SUPPLY: + $title = $admin['username'].'的管理后台'; + break; + default: + $title = $admin['username'].'的管理后台'; + } + $admin['title'] = $title; + + return [ + 'userInfo' => $admin, + 'token' => $adminAccessToken->access_token + ]; + } else { + throw new Exception("登陆失败,帐号或者密码错误"); + } + } + } + + public function actionLogout() + { + Yii::$app->user->logout(); + return []; + } + + /** + * @doc-name 后台注册 + * @doc-param string mobile 手机号 + * @doc-param string password 密码 + * @doc-param string username 用户名 + * @doc-param int role 角色id + * @doc-param int store_id 门店id / optional + * @doc-param int province_id 省份 / optional + * @doc-param int city_id 城市 / optional + */ + public function actionRegister() + { + $post = Yii::$app->request->post(); + + $model = new RegisterForm(); + $model->attributes = $post; + return $model->register(); + } + + /** + * @doc-name 重置密码或忘记密码 + * @doc-param string mobile 手机号 + * @doc-param string password 密码 + */ + public function actionResetPassword() + { + $post = Yii::$app->request->post(); + $this->requestValidate($post, [ + [['mobile', 'password'], 'required'] + ]); + $LoginForm = new LoginForm(); + $LoginForm->attributes = $post; + return $LoginForm->ResetPassword(); + } + + /** + * @doc-name 所有角色 + * @doc-return mixed @List{id,name-string-名字,role_code-string-role_code,description-string-描述} 医生列表 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionAllRole() + { + $post = Yii::$app->request->get(); + $query = Role::find(); + + $this->field = [ + Role::class => [ + 'id', 'name', 'role_code', 'description' + ] + ]; + return $this->create($query, $post); + } + + + /** + * @doc-name 编辑管理员信息 + * @doc-param string bank_user_name 开户人姓名 / optional + * @doc-param string bank_card 银行卡号 / optional + * @doc-param string bank_name 开户行 / optional + * @doc-param int bank_account_type 银行账户类型 1:对公,2:对私,5:存折 / optional + * @doc-param string bank_no 银行联行号bank_account_type=1或5或非62开头的对私银行账户时必选 / optional + */ + public function actionEditSuperInfo() + { + $post = Yii::$app->request->post(); + + $admin = \Yii::$app->user->identity; + if ($admin->role!=UserRoleEnum::SUPER_ADMIN){ + throw new \yii\db\Exception('您不是超管,不能编辑信息'); + } + $model = new RegisterForm(); + $model->attributes = $post; + return $model->EditSuper(); + } + + +} diff --git a/admin/controllers/MenuController.php b/admin/controllers/MenuController.php new file mode 100644 index 0000000..be296a1 --- /dev/null +++ b/admin/controllers/MenuController.php @@ -0,0 +1,72 @@ + + */ +class MenuController extends AuthController +{ + public $modelClass = Menu::class; + + /** + * @doc-name 菜单列表 + */ + public function actionList() + { + $user=\Yii::$app->user->identity; + + $rule_id=AuthRole::find()->select(['rule_id'])->where(['role_id'=>$user->role])->column(); + + $AuthRule_path=AuthRule::find()->select(['path'])->where(['in','id',$rule_id])->andWhere(['type'=>1])->column(); + + $menu2s = Menu::find()->where(['in','menuUrl',$AuthRule_path])->andWhere(['hidden'=>0])->orderBy(['sort'=>SORT_ASC])->asArray()->all(); + + return ArrayHelper::itemsMerge($menu2s,0,'menuUrl','parentPath','children'); + } + public function actionSave(){ + $menuUrl = $this->post('menuUrl'); + $model = Menu::findOne($menuUrl); + if(!$model){ + $model = new Menu(); + } + $model->load($this->post()); + if( $model->load($this->post(),'') && $model->save()){ + return $model->getAttributes(); + }else{ + throw new Exception("参数不对"); + } + } + + public function actionDel(){ + $menuUrl = $this->post('menuUrl'); + $model = Menu::findOne($menuUrl); + if (!$model) throw new \yii\db\Exception('菜单不存在'); + if($model->delete()){ + Menu::updateAll(['parentPath'=>''],['parentPath'=>$menuUrl]); + } + return ['删除成功']; + } + + /** + * @doc-name 编辑菜单 + */ + public function actionEdit() + { + $data= $this->post(); + $menuUrl = $this->post('menuUrl'); + $model = Menu::findOne($menuUrl); + + if (!$model) throw new \yii\db\Exception('菜单不存在'); + $model->attributes=$data; + $model->saveOrFail(); + return ['编辑成功']; + } +} diff --git a/admin/controllers/MobileController.php b/admin/controllers/MobileController.php new file mode 100644 index 0000000..4068790 --- /dev/null +++ b/admin/controllers/MobileController.php @@ -0,0 +1,53 @@ +response; + // $response->statusCode = 200; + // $response->data = ['message' => 'hello world']; + return ['data' => $rs, 'error' => '0']; + } + + public function init() + { + parent::init(); + + $handler = new ApiErrorHandler(); + \Yii::$app->set('errorHandler', $handler); + $handler->register(); + } + + + + public function formatDataBeforeSend($event){ + $response = $event->sender; + //自已定义失败的返回 + if ($response->data !== null && $response->isSuccessful==false) { + $response->data = [ + 'code' => 500, + 'status' => "FAIL" , + 'message' => "系统繁忙,请稍后再试", + ]; + $response->statusCode = 200; + } + } + + public function behaviors() + { + $behaviors = parent::behaviors(); + unset($behaviors['contentNegotiator']['formats']['application/xml']);//去除xml格式就按剩下的json显示 + return $behaviors; + } +} diff --git a/admin/controllers/PublicController.php b/admin/controllers/PublicController.php new file mode 100644 index 0000000..e1128ad --- /dev/null +++ b/admin/controllers/PublicController.php @@ -0,0 +1,80 @@ + + */ +class PublicController extends \common\core\Controller +{ + + /** @var bool */ + public $layout = false; + + /** @var bool */ + public $enableCsrfValidation = false; + + /** + * --------------------------------------- + * @inheritdoc + * --------------------------------------- + */ + public function actions() + { + return ArrayHelper::merge(parent::actions(), [ + /* 省市区联动 */ + 'region' => [ + 'class' => DepDropAction::className(), + 'enableCsrfValidation' => false, + 'outputCallback' => function ($id, $params) { + $region = Region::find()->where(['parent_code' => $id])->orderBy('code ASC')->asArray()->all(); + $_out = [];//var_dump($region); + foreach ($region as $value) { + $_tmp['id'] = $value['code']; + $_tmp['name'] = $value['fullname']; + $_out[] = $_tmp; + } + return $_out; + }, + 'selectedCallback' => function ($id, $params) { + return Yii::$app->getRequest()->get('sid'); + } + ], + /* ueditor文件上传 */ + 'ueditor' => [ + 'class' => 'common\actions\UEditorAction', + 'config' => Yii::$app->params['ueditorConfig'], + ], + /* 单图、多图上传 */ + 'uploadimage' => [ + 'class' => 'common\widgets\images\UploadAction', + ], + /* migration备份数据 */ + 'backup' => [ + 'class' => 'e282486518\migration\WebAction', + 'returnFormat' => 'json', + 'migrationPath' => '@console/migrations' + ] + ]); + } + + /** + * --------------------------------------- + * 通用的404错误处理 + * @return string + * --------------------------------------- + */ + public function action404() + { + + //渲染模板 + return $this->render('404'); + } + +} diff --git a/admin/controllers/StoreController.php b/admin/controllers/StoreController.php new file mode 100644 index 0000000..0b18299 --- /dev/null +++ b/admin/controllers/StoreController.php @@ -0,0 +1,61 @@ +response->format = \yii\web\Response::FORMAT_RAW; + $store = Store::find()->where([ + 'id' => $store_id + ])->one(); + if (!$store){ + throw new Exception('门店不存在'); + } +// if (!$store->qr_code) { +// $response = WechatService::getInstance()->app->app_code->getUnlimit($scene, [ +// 'page' => 'pages/home/home', +// 'check_path' => false, +// ]); +// +// if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) { +// $path = 'uploads/STORE_QR_CODE/' . date('Ymd'); +// $filename = $response->save('uploads/STORE_QR_CODE/' . date('Ymd'), 'STORE_QR_CODE_' . $store_id); +// +// $realpath = FuncHelper::getRealFilepath('service', $path . '/' . $filename); +// +// $uploadService = new UploadService(); +// $url = $uploadService->saveFile($realpath); +// +// $store->setAttributes(['qr_code' => $url]); +// $store->save(); +// } +// } + if (!$store->qr_code) { + $weappService = new WeappService(); + $url= $weappService->getQrcode($scene); + $store->qr_code=$url; + $store->saveOrFail(); + } + return $store->qr_code; + } + + +} \ No newline at end of file diff --git a/admin/controllers/UserController.php b/admin/controllers/UserController.php new file mode 100644 index 0000000..02553b0 --- /dev/null +++ b/admin/controllers/UserController.php @@ -0,0 +1,184 @@ +request->get(); + $query = User::find()->where([ + 'is_delete' => 0 + ]); + if (!empty($get['name'])) {//搜索姓名 + $query->andWhere(['like', 'nickname', $get['name']]); + } + if (!empty($get['major_number'])) {//手机号 + $query->andWhere(['mobile' => $get['major_number']]); + } + if (!empty($get['gender'])) {//性别 + $query->andWhere(['gender' => $get['gender']]); + } + if (!empty($get['idcard'])) {//身份证 + $query->andWhere(['idcard' => $get['idcard']]); + } + + $this->field = [ + User::class => [ + 'id', 'nickname', 'mobile', 'gender', 'idcard', 'created_at' => function ($model) { + return date('Y-m-d H:i:s', $model->created_at); + }, + 'age' => function ($model) { + return $model->idcard ? FuncHelper::getAgeFromIdNo($model->idcard) : ''; + }, + 'UserPatientHealthInquiry' => function ($m) { + $UserPatient = UserPatient::find()->select('id')->where([ + 'user_id' => $m->id, + 'relation' => 0 + ])->column(); + return UserPatientHealthInquiry::find()->where([ + 'user_patient_id' => $UserPatient, + 'is_delete' => 0 + ])->one(); + }, + 'UserInquiry' => function ($i) { + return Order::find()->where([ + 'user_id' => $i->id, + ])->with(['inquiry'])->asArray()->all(); + }, + 'Prescription' => function ($p) { + return Prescription::find()->where([ + 'user_id' => $p->id, + 'is_deleted' => 0 + ])->all(); + }, + 'register'=>function($r){ + return Register::find()->where([ + 'user_id'=>$r->id + ])->all(); + } + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 用户端用户详情 + * @doc-param int id ID + * @doc-return mixed @User{id,nickname-string-昵称,mobile-string-电话,created_at-string-首次访问时间,gender-int-性别,值为1时是男性,值为2时是女性,值为0时是未知性别,idcard-string-身份证,age-int-年龄} 用户信息 + * @doc-return mixed @UserPatientHealthInquiry{liver_function-int-肝功能状态0正常1异常,liver_index-string-肝功能异常指标,renal_function-int-肾功能状态0正常1异常,renal_index-string-肾功能异常指标,person_status-int-既往史0无1有,person_history-string-既往史,allergic_status-int-过敏史0无1有,allergic_status-string-过敏史,,allergic_status-int-家族遗传史0无1有,allergic_status-string-家族遗传史} 基本健康信息 + * @doc-return mixed @UserInquiry{id-int-订单id,user_id-int-用户id,order_no-string-订单号,total_pay_price-float-支付金额,is_pay-int-知否支付0否1是,@Inquiry{images-string-检查报告或患者照片,is_visit-string-是否就诊0否1是,visit_desc-string-就诊描述,patient_data-string-就诊人基础信息,liver_function-int-肝功能0正常1异常,renal_function-string-肾功能0正常1异常,person_status-int-个人病史0无1有,person_history-string-个人病史,allergic_status-int-过敏史0无1有,allergic_history-int-过敏史0无1有,family_status-int-家庭病史0无1有,family_history-string-家庭病史}} 问诊记录 + * @doc-return mixed @Prescription{id-int-id,platform_prescription_no-string-平台处方单号,prescription_no-string-处方单号,order_id-int-订单id,status-int-状态0待审核1已通过2未通过3待使用4已使用5未使用6已失效7已初审,content-string-处方快照,prescription_type-int-1中药处方2西药处方3颗粒药处方,category-int-类别 1自费2医保,doctor_order-string-医嘱,clinical_diagnose-string-临床诊断,,医生签名-string-医生签名,type-int-类型1普通方2常用方,order_type-int-订单类型1处方2医技,total_pay_price-float-支付金额} 处方记录 + */ + public function actionInfo() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + $User = User::find()->where([ + 'id' => $get['id'], + 'is_delete' => 0 + ])->with(['userPatient' => function ($u) { + $u->where(['relation' => 0]); + }])->asArray()->one(); + $UserPatientId = $User['userPatient'][0]['id']; + + if (!$User) throw new Exception('用户不存在'); + $UserPatientHealthInquiry = UserPatientHealthInquiry::find()->where([ + 'user_patient_id' => $UserPatientId, + 'is_delete' => 0 + ])->one(); + $UserInquiry = Order::find()->where([ + 'user_id' => $get['id'], + ])->with(['inquiry'])->asArray()->all(); + + $Prescription = Prescription::find()->where([ + 'user_id' => $get['id'], + 'is_deleted' => 0 + ])->all(); + $register=Register::find()->where([ + 'user_id'=>$get['id'], + ])->all(); + return [ + 'User' => $User, + 'UserPatientHealthInquiry' => $UserPatientHealthInquiry, + 'UserInquiry' => $UserInquiry, + 'Prescription' => $Prescription, + 'register' => $register, + ]; + } + + public function actionPatientList(){ + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + $user = User::find()->where([ + 'id' => $get['id'], + 'is_delete' => 0 + ])->asArray()->one(); + if (!$user) throw new Exception('用户不存在'); + $userPatient = UserPatient::find()->select('id,name')->where(['user_id' => $get['id'],'is_delete' => 0])->orderBy('is_default desc,created_at asc')->all(); + return $userPatient; + } + + public function actionPatientInfo(){ + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['patient_id', 'required'] + ]); + $userPatient = UserPatient::find()->where(['id' => $get['patient_id'],'is_delete' => 0])->one(); + if(!$userPatient){ + throw new Exception('就诊人不存在'); + } + $UserPatientHealthInquiry = UserPatientHealthInquiry::find()->where([ + 'user_patient_id' => $get['patient_id'], + 'is_delete' => 0 + ])->one(); + return [ + 'info' => $userPatient, + 'healthInquiry' => $UserPatientHealthInquiry + ]; + } + + public function actionPatientPrescriptionList(){ + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['patient_id', 'required'] + ]); + $userPatient = UserPatient::find()->where(['id' => $get['patient_id'],'is_delete' => 0])->one(); + if(!$userPatient){ + throw new Exception('就诊人不存在'); + } + $prescriptionList = Prescription::find()->select(['id','su_id','clinical_diagnose','prescription_no','created_at'])->where(['up_id' => $get['patient_id'],'is_deleted' => 0,'cancel_status' => 0])->orderBy('created_at desc')->asArray()->all(); + foreach($prescriptionList as &$v){ + $v['created_at'] = date('Y年m月d日 H:i',$v['created_at']); + $v['doctor_name'] = DoctorInfo::find()->where(['su_id' => $v['su_id']])->select('name')->scalar(); + } + return $prescriptionList; + } +} \ No newline at end of file diff --git a/admin/controllers/base/ArticleController.php b/admin/controllers/base/ArticleController.php new file mode 100644 index 0000000..2d23dfc --- /dev/null +++ b/admin/controllers/base/ArticleController.php @@ -0,0 +1,144 @@ +request->post(); + $this->requestValidate($post,[ + [['name','pid','level'],'required'], + ]); + if (empty($post['id'])){ + $Categories= Categories::find()->where(['name'=>$post['name'],'is_deleted'=>0])->one(); + if (!$Categories){ + $Categories= new Categories(); + $Categories->name=$post['name']; + $Categories->pid=$post['pid']; + $Categories->level=$post['level']; + $Categories->save(); + } + return ['已添加']; + }else{ + $Categories= Categories::find()->where(['id'=>$post['id'],'is_deleted'=>0])->one(); + if (!$Categories){ + throw new Exception('分类不存在'); + + } + $Categories->name=$post['name']??$Categories->name; + $Categories->pid=$post['pid']??$Categories->pid;; + $Categories->level=$post['level']??$Categories->level;; + if (! $Categories->saveOrFail()){ + throw new Exception('编辑失败'); + }; + return ['编辑成功']; + } + + } + /** + * @doc-name 删除分类 + * @doc-param int id ID + */ + public function actionDelCategories() + { + $get=\Yii::$app->request->get(); + $this->requestValidate($get,[ + ['id','required'], + ]); + $Categories= Categories::find()->where(['id'=>$get['id']])->one(); + if (!$Categories){ + throw new Exception('分类不存在'); + } + $Categories->is_deleted=1; + if (!$Categories->saveOrFail()){ + throw new Exception('删除失败'); + }; + return ['删除成功']; + } + /** + * @doc-name 文章分类列表 + * @doc-return mixed @List{id,name-string-分类,pid-int-父级id,level-int-级别} 文章分类列表 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionCategoriesList() + { + $get=\Yii::$app->request->get(); + $query= Categories::find()->where(['is_deleted'=>0])->orderBy(['id'=>SORT_DESC]); + + $this->field=[ + Categories::class=>[ + 'id','name','pid','level' + ] + ]; + return $this->create($query,$get); + + + } + /** + * @doc-name 文章列表 + * @doc-return mixed @List{id,su_id-int-医生id 0为后台发布,cover-string-封面,title-string-文章标题,intro-string-简介,content-string-内容,video_url-string-视频链接,read_num-int-阅读量,collection-string-货收藏),is_draft-int-是否是草稿0否1是} 文章列表 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionArticleList() + { + $get=\Yii::$app->request->get(); + $query= DoctorArticle::find()->where(['is_delete'=>0])->orderBy(['id'=>SORT_DESC]); + + $this->field=[ + DoctorArticle::class=>[ + 'id','cid','su_id','cover','title','intro','content','video_url','read_num','collection','is_draft','categories'=>'categories.name','type' + ] + ]; + return $this->create($query,$get); + } + /** + * @doc-name 新增或修改文章 + * @doc-param int id 传id则修改 / optional + * @doc-param int type 文章类型1图文类型2图片 / optional + * @doc-param int cid 分类id / optional + * @doc-param int su_id 发部人 / optional + * @doc-param string cover 封面 + * @doc-param string title 标题 + * @doc-param string intro 简介 / optional + * @doc-param string content 内容 + * @doc-param string video_url 视频链接 / optional + * @doc-param int is_draft 是否是草稿0否1是 / optional + */ + public function actionSaveArticle() + { + $post = \Yii::$app->request->post(); + $ArticleForm= new ArticleForm(); + $ArticleForm->attributes = $post; + return $ArticleForm->save(); + } + /** + * @doc-name 删除文章 + * @doc-param int id id + */ + public function actionDelArticle() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['id','required'], + ]); + $ArticleForm= new ArticleForm(); + $ArticleForm->attributes = $get; + return $ArticleForm->del(); + } +} \ No newline at end of file diff --git a/admin/controllers/base/DepartController.php b/admin/controllers/base/DepartController.php new file mode 100644 index 0000000..4e25bfa --- /dev/null +++ b/admin/controllers/base/DepartController.php @@ -0,0 +1,216 @@ +request->get(); + $query = Department::find(); + if (!empty($get['name'])) { + $query->andWhere([ + 'like', 'name', $get['name'] + ]); + } + + $this->field = [ + Department::class => [ + 'id', 'name', 'pid', 'level', + 'child_depart' => 'child' + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 科室列表 + * @doc-param int name 科室名字 / optional + * @doc-return mixed @List{id,name-string-名字,pid-int-父级id,level-int-等级} 科室信息 + */ + public function actionList() + { + $get = \Yii::$app->request->get(); + $query = Department::find(); + if (!empty($get['name'])) { + $query->andWhere([ + 'like', 'name', $get['name'] + ]); + } + + return $query->select(['id', 'name', 'level'])->all(); + } + + /** + * @doc-name 新增科室 + * @doc-param string name 科室 + * @doc-param int level 科室级别 + * @doc-param int pid 父级id / optional + * @doc-param string is_recommend 是否推荐 / optional + * @doc-param int feature 是否是重点特色专科0不是1是 / optional + */ + public function actionSaveDept() + { + $post = \Yii::$app->request->post(); + $DepartForm = new DepartForm(); + $DepartForm->attributes = $post; + return $DepartForm->SaveDepart(); + } + + /** + * @doc-name 门店列表 + * @doc-param int name 名字 / optional + * @doc-param string region 省 / optional + * @doc-param string city 市 / optional + * @doc-param int limit 每页条数 / optional + * @doc-return mixed @List{id,name-string-名字,drugstore_id-int-仓库id,drugstore-string-仓库,plate_id-int-平台id,position-string-位置,pic-string-图片,contact-string-联系人,mobile-string-联系电话,qr_code-string-门店二维码,start_time-string-开始营业时间,end_time-string-结束营业时间,see_rate-int-是否查看毛利率0否1是} 门店信息 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionStoreList() + { + $get = \Yii::$app->request->get(); + $query = Store::find()->alias('s'); + $name = \Yii::$app->request->get('name'); + $region = \Yii::$app->request->get('region'); + $city = \Yii::$app->request->get('city'); + $admin = \Yii::$app->user->identity; + + if ($admin->role==UserRoleEnum::STORE_ADMIN){ + $query->andWhere(['s.id'=>$admin->store_id])->orderBy(['s.id'=>SORT_DESC]); + }elseif ($admin->role==UserRoleEnum::PROVINCE_DAI){ + $query->andWhere(['s.province_id'=>$admin->province_id])->orderBy(['s.id'=>SORT_DESC]); + }elseif ($admin->role==UserRoleEnum::CITY_DAI){ + $query->andWhere(['s.city_id'=>$admin->city_id])->orderBy(['s.id'=>SORT_DESC]); + }elseif ($admin->role==UserRoleEnum::SUPPLY){ + $query->andWhere(['s.code'=>$admin->code])->orderBy(['s.id'=>SORT_DESC]); + }else{ + $query->orderBy(['s.id'=>SORT_DESC]); + } + if (!empty($name) ) { + $query->andWhere([ + 'or', + ['like', 's.name', $name], + ['like', 's.shouzimu', $name], + ]); + } + if ( !empty($region)) { + $query->joinWith(['province'=>function($p)use($region){ + $p->alias('p'); + $p->where(['like','p.name',$region]); + }]); + } + if ( !empty($city)) { + $query->joinWith(['city'=>function($p)use($city){ + $p->alias('c'); + $p->where(['like','c.name',$city]); + }]); + } + $this->field = [ + Store::class => [ + 'id', 'plate_id', 'name', 'position', 'offical_seal', 'pic', 'contact', 'mobile', 'qr_code', + 'start_time', 'end_time', + 'drugstore_id', 'see_rate', + 'drugstore' => 'drugStore.name', + 'code','uid','supply'=>'admin.username', + 'province'=>'province.name', + 'city'=>'city.name', + 'province_id', + 'city_id','erp_id' + ] + ]; + return $this->create($query, $get); + } + + + /** + * @doc-name 新增或编辑门店 + * @doc-desc 传id则修改 + * @doc-param int id 门店id / optional + * @doc-param int plate_id 平台ID + * @doc-param int erp_id erp_id / optional + * @doc-param int drugstore_id 仓库ID + * @doc-param string name 名字 + * @doc-param string contact 联系人 + * @doc-param string position 位置 + * @doc-param string mobile 电话 + * @doc-param int province_id 省 + * @doc-param int city_id 市 + * @doc-param string code 推广码 + * @doc-param string offical_seal 公章 + * @doc-param string start_time 开始营业时间 + * @doc-param string end_time 结束营业时间 + * @doc-param string pic 图片 / optional + * @doc-param string bank_user_name 开户人姓名 / optional + * @doc-param string bank_card 银行卡号 / optional + * @doc-param string bank_name 开户行 / optional + * @doc-param int bank_account_type 银行账户类型 1:对公,2:对私,5:存折 / optional + * @doc-param string bank_no 银行联行号bank_account_type=1或5或非62开头的对私银行账户时必选 / optional + */ + public function actionSaveStore() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['code','required','message'=>'推广码不能为空'], + ['plate_id','required','message'=>'平台ID不能为空'], + ['drugstore_id','required','message'=>'仓库ID不能为空'], + ['name','required','message'=>'名字不能为空'], + ['contact','required','message'=>'联系人不能为空'], + ['position','required','message'=>'联系人不能为空'], + ['mobile','required','message'=>'电话不能为空'], +// ['offical_seal','required','message'=>'公章不能为空'], + ['start_time','required','message'=>'开始营业时间不能为空'], + ['end_time','required','message'=>'结束营业时间不能为空'], + ['province_id','required','message'=>'省份不能为空'], + ['city_id','required','message'=>'城市不能为空'], + ]); + + $post['store_name'] = $post['name']; + $post['shouzimu']=ArrayHelper::shouzimu($post['name']); + + $DepartForm = new DepartForm(); + $DepartForm->attributes = $post; + return $DepartForm->SaveStore(); + } + + /** + * @doc-name 平台列表 + * @doc-param int name 名字 / optional + * @doc-return mixed @List{id,name-string-平台名称,token-string-平台密钥(后期使用),url-string-通讯地址,callbackurl-string-位置,status-int-1使用0不使用} 平台信息 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionPlatformList() + { + $get = \Yii::$app->request->get(); + $query = Platform::find(); + + if (!empty($get['name'])) { + $query->andWhere([ + 'like', 'name', $get['name'] + ]); + } + + $this->field = [ + Platform::class => [ + 'id', 'name', 'token', 'callbackurl', 'url', 'status' + ] + ]; + return $this->create($query, $get); + } +} \ No newline at end of file diff --git a/admin/controllers/base/DiagnoseController.php b/admin/controllers/base/DiagnoseController.php new file mode 100644 index 0000000..b5e0c25 --- /dev/null +++ b/admin/controllers/base/DiagnoseController.php @@ -0,0 +1,117 @@ +request->get(); + $query = Disease::find()->where(['is_delete' => 0]); + + if (!empty($get['name'])){ + $query->andWhere([ + 'like', 'name',$get['name'] + ]); + } + if (!empty($get['major_number'])){ + $query->andWhere([ + 'major_number'=>$get['major_number'] + ]); + } + if (!empty($get['ref_number'])){ + $query->andWhere([ + 'ref_number'=>$get['ref_number'] + ]); + } + + $this->field = [ + Disease::class => [ + 'id', 'diagnose_code','name', 'major_number', 'ref_number' + ] + ]; + + return $this->create($query, $get); + } + + /** + * @doc-name 新增或编辑诊断症状 + * @doc-desc 传ID则编辑 + * @doc-param int ID 症状id / optional + * @doc-param string name 名字 + * @doc-param string diagnose_code 疾病诊断代码 / optional + * @doc-param string major_number 主编号 / optional + * @doc-param string ref_number 次编号 / optional + */ + public function actionSave() + { + $post = \Yii::$app->request->post(); + $DiagnoseForm = new DiagnoseForm(); + $DiagnoseForm->attributes = $post; + return $DiagnoseForm->save(); + } + + /** + * @doc-name 删除诊断症状 + * @doc-param int id 诊断症状ID + */ + public function actionDel() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $DiagnoseForm = new DiagnoseForm(); + $DiagnoseForm->attributes = $post; + return $DiagnoseForm->del(); + } + + /** + * @doc-name 导入诊断症状 + * @doc-param file file 文件 + */ + public function actionImport() + { + $request = \Yii::$app->request; + if ($request->isPost) { + //设置最大执行时间 + ini_set("max_execution_time", "360"); + $file = UploadedFile::getInstanceByName('file'); + if ($file->size > 5 * 1024 * 1024) { + throw new Exception('excel文件不能超过5M!'); + } + + //文件名 + $filename = date('His') . md5($file->getBaseName()) . mt_rand(1000, 9999) . '.' . $file->getExtension(); + //保存文件 + $file->saveAs($filename); + + $data = Excel::import($filename, [ + 'setFirstRecordAsKeys' => true, + 'getOnlySheet' => 'Sheet1', + ]); + + $DiagnoseForm = new DiagnoseForm(); + return $DiagnoseForm->export($data); + } else { + throw new Exception('请求方式错误'); + } + } +} \ No newline at end of file diff --git a/admin/controllers/base/DivideAccountController.php b/admin/controllers/base/DivideAccountController.php new file mode 100644 index 0000000..6bd6aad --- /dev/null +++ b/admin/controllers/base/DivideAccountController.php @@ -0,0 +1,916 @@ +request->post(); + $this->requestValidate($post, [ + [['apply_cash', 'bank_user_name', 'bank_card', 'bank_name', 'bank_account_type', 'user_type'], 'required'] + ]); + if ($post['apply_cash']<3){ + throw new \yii\db\Exception('申请提现金额最少不能小于3元'); + } + $user = \Yii::$app->user->identity; + + if ($user->role != UserRoleEnum::STORE_ADMIN) { + throw new Exception('您还不是诊所管理员,没有权限申请打款'); + } + if ($post['user_type'] != 1) throw new Exception('用户类型错误'); + + if ($post['bank_account_type'] == 1 || $post['bank_account_type'] == 5) { + if (empty($post['bank_no'])) { + throw new Exception('bank_no不能为空'); + } + } else { + if (substr($post['bank_card'], 0, 2) != '62') { + if (empty($post['bank_no'])) { + throw new Exception('bank_no不能为空'); + } + } + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $order_no = 'DK' . time() . rand(111111, 999999); + $Account = CashAccount::find()->where([ + 'user_id' => $user->store_id, + 'user_type' => 1 + ])->one(); + if (!$Account) throw new Exception('账号不存在'); + + if (bcsub($Account->able_cash ,$Account->frozen_cash,2) < $post['apply_cash']) { + throw new Exception('sorry,您的账户没有那么多提现金额'); + } + + $CashAccount = CashAccount::find()->where([ + 'user_id' => $user->store_id, + 'user_type' => 1 + ])->one(); + + $Platform= CashAccount::find()->where([ + 'user_id' => 0, + 'user_type' => 2 + ])->one(); +// $CashAccount->able_cash = bcsub($CashAccount->able_cash, $post['apply_cash'], 2); + $CashAccount->frozen_cash = bcadd($post['apply_cash'], $CashAccount->frozen_cash, 2); + $CashAccount->last_apply_time = date('Y-m-d H:i:s', time()); + $CashAccount->saveOrFail(); + + $qianliuwu=bcdiv(0.65,100,4); + $shouxufei=bcadd(bcmul($post['apply_cash'],$qianliuwu,2),2,3); + +// $Platform->updateAllCounters(['able_cash'=>1]); +// $Platform->updateAllCounters(['total_cash'=>1]); + + $CashApply = new CashApply(); + $CashApply->user_id = $user->store_id;//诊所id + $CashApply->user_type = 1;//用户类型1诊所2总部 + $CashApply->order_no = $order_no;//申请提现金额 + $CashApply->apply_cash = $post['apply_cash'];//申请提现金额 + $CashApply->charge_cash =$shouxufei;//手续费 + $CashApply->true_cash = bcsub($CashApply->apply_cash, $shouxufei, 2);//实际到账金额 + $CashApply->apply_time = date('Y-m-d H:i:s', time()); + $CashApply->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '诊所申请打款'; + $log->mold = 3;//财务操作 + $log->content = '诊所管理员ID:' . $user->uid . '申请打款:' . $post['apply_cash'] . '元,订单号为:' . $order_no . ',开户人姓名为:' . $post['bank_user_name'] . ',银行卡号:' . $post['bank_card'] . ',开户行名称:' . $post['bank_name'] . ',银行账户类型:' . $post['bank_account_type'] . ',账户的冻结金额由原来的:' . $Account->frozen_cash . '元变为:' . $CashAccount->frozen_cash . '元'; + $log->save(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + $t->commit(); + return ['申请成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 平台申请提现操作 + * @doc-param string apply_cash 申请提现金额 + * @doc-param string bank_user_name 开户人姓名 + * @doc-param string bank_card 银行卡号 + * @doc-param string bank_name 开户行名称 + * @doc-param int bank_account_type 银行账户类型 1:对公,2:对私,5:存折 + * @doc-param string bank_no 银行联行号bank_account_type=1或5或非62开头的对私银行账户时必选 / optional + * @doc-param int user_type 用户类型1诊所2总部 + */ + public function actionPlatformApply() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['apply_cash', 'bank_user_name', 'bank_card', 'bank_name', 'bank_account_type', 'user_type'], 'required'] + ]); + if ($post['apply_cash']<3){ + throw new \yii\db\Exception('申请提现金额最少不能小于3元'); + } + $user = \Yii::$app->user->identity; + + if ($user->role != UserRoleEnum::SUPER_ADMIN) throw new \yii\base\Exception('您还不是超级管理员,没有权限申请打款'); + if ($post['user_type'] != 2) throw new \yii\db\Exception('用户类型错误'); + + if ($post['bank_account_type'] == 1 || $post['bank_account_type'] == 5) { + if (empty($post['bank_no'])) { + throw new \yii\base\Exception('bank_no不能为空'); + } + } else { + if (substr($post['bank_card'], 0, 2) != '62') { + if (empty($post['bank_no'])) { + throw new Exception('bank_no不能为空'); + } + } + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $order_no = 'DK' . time() . rand(111111, 999999); + $Account = CashAccount::find()->where([ + 'user_type' => 2, + 'user_id' => 0, + ])->one(); + if (!$Account) throw new Exception('账号不存在'); + if (bcsub($Account->able_cash,$Account->frozen_cash,2) < $post['apply_cash']) + throw new Exception('sorry,您的账户没有那么多提现金额'); + + $CashAccount = CashAccount::find()->where([ + 'user_type' => 2,//平台 + 'user_id' => 0, + ])->one(); +// $CashAccount->able_cash = bcsub($CashAccount->able_cash, $post['apply_cash'], 2); + $CashAccount->frozen_cash = bcadd($post['apply_cash'], $CashAccount->frozen_cash, 2); + $CashAccount->last_apply_time = date('Y-m-d H:i:s', time()); + $CashAccount->saveOrFail(); + + + $qianliuwu=bcdiv(0.65,100,4); + $shouxufei=bcadd(bcmul($post['apply_cash'],$qianliuwu,2),2,3); + + $CashApply = new CashApply(); + $CashApply->user_type = 2; + $CashApply->user_id = 0;//用户ID + $CashApply->order_no = $order_no; + $CashApply->apply_cash = $post['apply_cash'];//申请提现金额 + $CashApply->charge_cash = $shouxufei;//手续费 + $CashApply->true_cash = bcsub($CashApply->apply_cash, $shouxufei, 2);//实际到账金额 + $CashApply->apply_time = date('Y-m-d H:i:s', time()); + $CashApply->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '平台申请打款'; + $log->content = '平台ID:' . $user->uid . '申请打款:' . $post['apply_cash'] . '元,订单号为::' . $order_no . ',开户人姓名为:' . $post['bank_user_name'] . ',银行卡号:' . $post['bank_card'] . ',开户行名称:' . $post['bank_name'] . ',银行账户类型:' . $post['bank_account_type'] . ',账户冻结金额由原来的:' . $Account->frozen_cash . '元变为:' . $CashAccount->frozen_cash . '元'; + $log->mold = 3;//财务操作 + $log->save(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + $t->commit(); + return ['申请成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 分账申请打款审核(超级管理员)--通过 + * @doc-param int id 申请id + * @doc-param int user_type 类型1诊所2总部 + * @doc-param string check_result 审核结果 + */ + public function actionApplyAgree() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['id', 'check_result', 'user_type'], 'required'], + ]); + $user = \Yii::$app->user->identity; + if ($user->role != UserRoleEnum::SUPER_ADMIN) throw new Exception('你不是超级管理员,没有分账申请打款审核权限'); + + $CashApply = CashApply::find()->where([ + 'id' => $post['id'], + 'user_type' => $post['user_type'], + 'check_status' => 1 + ])->one(); + if (!$CashApply) throw new Exception('申请不存在'); + + if ($post['user_type'] == 1) {//诊所 + $Account = CashAccount::find()->where([ + 'user_id' => $CashApply->user_id, + 'user_type' => $CashApply->user_type + ])->one(); + $config=Store::find()->where(['id'=>$CashApply->user_id])->one(); + } else {//平台 + $Account = CashAccount::find()->where([ + 'user_id' => 0, + 'user_type' => $CashApply->user_type + ])->one(); + $config=Admin::find()->where(['role'=>UserRoleEnum::SUPER_ADMIN])->one(); + } + + if (!$Account) throw new Exception('诊所或平台的账号不存在'); + + $CashAccount = CashAccount::find()->where([ + 'user_type' => $CashApply->user_type, + 'user_id' => $CashApply->user_id + ])->one(); + + if (empty($config['bank_user_name']) || empty($config['bank_card']) || empty($config['bank_name']) || empty($config['bank_account_type'])){ + $CashAccount->frozen_cash = bcsub($CashAccount->frozen_cash, $CashApply->apply_cash, 2);//申请提现冻结的金额 + $CashAccount->saveOrFail(); + + $CashApply->check_id = $user->uid; + $CashApply->check_status = 4;//提现失败 + $CashApply->check_result = '银行卡相关配置不完善'; + $CashApply->check_time = date('Y-m-d H:i:s', time()); + $CashApply->dakuan_status = -1;//失败 + $CashApply->dakuan_time = date('Y-m-d H:i:s', time()); + $CashApply->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '分账申请打款审核'; + $log->content = '超级管理员:' . $user->uid . '打款操作,订单号:' . $CashApply->order_no . ',打款金额:' . bcadd($CashApply->true_cash,2,2) . '元,开户人姓名:' . $config->bank_user_name . ',银行卡号:' . $config->bank_card . ',银行名称:' . $config->bank_name . ',银行账户类型:' . $config->bank_account_type . ',打款失败,原因:银行卡相关配置不完善' ; + $log->mold = 3;//财务操作 + $log->saveOrFail(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + throw new \yii\db\Exception('银行卡相关配置不能为空'); + } + + + $param=[ + 'order_no'=>$CashApply->order_no, + 'apply_cash'=>bcadd($CashApply->true_cash,1,2), + 'bank_name'=>$config->bank_name, + 'bank_account_type'=>$config->bank_account_type, + 'bank_no'=>$config->bank_no, + 'bank_user_name' => $config->bank_user_name, + 'bank_card' => $config->bank_card, + ]; + //打款 + $res = EplPayService::getInstance()->withDraw($param); + //打款失败 + if ($res['returnCode'] != 0000) { + try { + $transaction=\Yii::$app->db->beginTransaction(); + + $CashAccount->frozen_cash = bcsub($CashAccount->frozen_cash, $CashApply->apply_cash, 2);//申请提现冻结的金额 + $CashAccount->saveOrFail(); + + $CashApply->check_id = $user->uid; + $CashApply->check_status = 4;//提现失败 + $CashApply->check_result = $res['returnMsg']; + $CashApply->check_time = date('Y-m-d H:i:s', time()); + $CashApply->dakuan_status = -1;//失败 + $CashApply->dakuan_time = date('Y-m-d H:i:s', time()); + $CashApply->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '分账申请打款审核'; + $log->content = '打款失败:超级管理员:' . $user->uid . '打款操作,订单号:' . $CashApply->order_no . ',打款金额:' . bcadd($CashApply->true_cash,2,2) . '元,开户人姓名:' . $config->bank_user_name . ',银行卡号:' . $config->bank_card . ',银行名称:' . $config->bank_name . ',银行账户类型:' . $config->bank_account_type . ',打款失败,原因:' . $res['returnMsg']; + $log->mold = 3;//财务操作 + $log->saveOrFail(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + $transaction->commit(); + return $res; + }catch (\Exception $e){ + $transaction->rollBack(); + throw new \yii\db\Exception($e->getMessage()); + } + }else{ + $t = \Yii::$app->db->beginTransaction(); + try { + //打款成功 + $CashAccount->able_cash = bcsub($CashAccount->able_cash, $CashApply->apply_cash, 2);//账户余额 + $CashAccount->frozen_cash = bcsub($CashAccount->frozen_cash, $CashApply->apply_cash, 2);//申请提现冻结的金额 + $CashAccount->withdrawn_cash = bcadd($CashAccount->withdrawn_cash, $CashApply->true_cash, 2);//已提现金额 + $CashAccount->charge_cash = bcadd($CashAccount->charge_cash, $CashApply->charge_cash, 2);//手续费 + $CashAccount->saveOrFail(); + + $CashApply->check_id = $user->uid; + $CashApply->check_status = 2;//成功 + $CashApply->check_result = $post['check_result']; + $CashApply->check_time = date('Y-m-d H:i:s', time()); + $CashApply->check_time = date('Y-m-d H:i:s', time()); + $CashApply->dakuan_status = 1;//成功 + $CashApply->dakuan_time = date('Y-m-d H:i:s', time()); + $CashApply->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '分账申请打款审核'; + $log->content = $user->uid . '通过了ID为:' . $post['id'] . '的打款申请,打款结果:成功'; + $log->mold = 3;//财务操作 + $log->save(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + $t->commit(); + return ['审核成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + } + + /** + * @doc-name 分账申请打款审核(超级管理员)--拒绝 + * @doc-param int id 申请id + * @doc-param int user_type 类型1诊所2总部 + * @doc-param string check_result 审核结果 + */ + public function actionApplyRefuse() + { + + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['id', 'check_result', 'user_type'], 'required'], + ]); + $user = \Yii::$app->user->identity; + if ($user->role != UserRoleEnum::SUPER_ADMIN) throw new Exception('你不是超级管理员,没有分账申请打款审核权限'); + + $CashApply = CashApply::find()->where([ + 'id' => $post['id'], + 'user_type' => $post['user_type'], + 'check_status' => 1, + ])->one(); + if (!$CashApply) throw new Exception('申请不存在'); + + $Account = CashAccount::find()->where([ + 'user_id' => $CashApply->user_id, + 'user_type' => $CashApply->user_type + ])->one(); + if (!$Account) throw new Exception('平台或技术方的账号不存在'); + + + $t = \Yii::$app->db->beginTransaction(); + try { + $CashApply->check_id = $user->uid; + $CashApply->check_status = 3;//拒绝 + $CashApply->check_result = $post['check_result']; + $CashApply->check_time = date('Y-m-d H:i:s', time()); + $CashApply->saveOrFail(); + + $CashAccount = CashAccount::find()->where([ + 'user_type' => $CashApply->user_type + ])->one(); + $CashAccount->frozen_cash = bcsub($CashAccount->frozen_cash, $CashApply->apply_cash, 2); + $CashAccount->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '分账申请打款审核'; + $log->content = '管理员:' . $user->uid . '拒绝了ID为:' . $post['id'] . '的打款申请,可提现账户ID为:' . $Account->id . '的账户的冻结的金额由' . $Account->frozen_cash . '变为' . $CashAccount->frozen_cash; + $log->mold = 3;//财务操作 + $log->save(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + $t->commit(); + return ['成功拒绝']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 分账打款 + * @doc-param int apply_id 提现申请ID + * @doc-param string order_no 订单号 + * @doc-param string order_no 订单号 + * @doc-param string bank_user_name 开户人姓名 + * @doc-param string bank_card 银行卡号 + * @doc-param string bank_name 银行名称 + * @doc-param string bank_account_type 1对公2对私5存 + */ + public function actionPayment() + { + $post = \Yii::$app->request->post(); + $user = \Yii::$app->user->identity; + + if ($user->role != UserRoleEnum::SUPER_ADMIN) throw new \yii\db\Exception('您不是超级管理员,没权限打款'); + + $this->requestValidate($post, [ + [['apply_id', 'order_no', 'bank_user_name', 'bank_card', 'bank_name', 'bank_account_type'], 'required'] + ]); + $CashApply = CashApply::find()->where(['id' => $post['apply_id']])->one(); + if (!$CashApply) throw new Exception('提现申请不存在'); + + if ($CashApply->check_status != 2) {//不是已通过状态 + throw new Exception('提现申请不是已通过状态,您还不能打款'); + } + + $CashAccount = CashAccount::find()->where([ + 'user_type' => $CashApply->user_type, + 'user_id' => $CashApply->user_id + ])->one(); + if (!$CashAccount) throw new Exception('账户不存在'); + + $post['apply_cash'] = $CashApply->apply_cash; + + $t = \Yii::$app->db->beginTransaction(); + try { + //打款 + $res = EplPayService::getInstance()->withDraw($post); + //打款失败 + if ($res['returnCode'] != 0000) { + $CashAccount->frozen_cash = bcsub($CashAccount->frozen_cash, $CashApply->apply_cash, 2);//申请提现冻结的金额 + // $CashAccount->able_cash=bcadd($CashAccount->able_cash,$CashApply->apply_cash,2);//可提现金额 + $CashAccount->saveOrFail(); + + + $CashApply->dakuan_status = -1; + $CashApply->dakuan_time = date('Y-m-d H:i:s', time()); + $CashApply->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '超级管理员'; + $log->content = '打款失败:超级管理员:' . $user->uid . '打款操作,订单号:' . $post['order_no'] . ',打款金额:' . $post['apply_cash'] . '元,开户人姓名:' . $post['bank_user_name'] . ',银行卡号:' . $post['bank_card'] . ',银行名称:' . $post['bank_name'] . ',银行账户类型:' . $post['bank_account_type'] . '打款失败:失败原因' . $res; + $log->mold = 3;//财务操作 + $log->saveOrFail(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + return $res; + } + + //打款成功 + $CashAccount->able_cash = bcsub($CashAccount->able_cash, $CashApply->apply_cash, 2);//账户余额 + $CashAccount->frozen_cash = bcsub($CashAccount->frozen_cash, $CashApply->apply_cash, 2);//申请提现冻结的金额 + $CashAccount->withdrawn_cash = bcadd($CashAccount->withdrawn_cash, $CashApply->apply_cash, 2);//已提现金额 + $CashAccount->charge_cash = bcadd($CashAccount->charge_cash, $CashApply->charge_cash, 2);//手续费 + $CashAccount->saveOrFail(); + + $CashApply->dakuan_status = 1; + $CashApply->dakuan_time = date('Y-m-d H:i:s', time()); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '超级管理员'; + $log->content = '打款成功:超级管理员:' . $user->uid . '打款操作:订单号:' . $post['order_no'] . ',打款金额:' . $post['apply_cash'] . '元,开户人姓名:' . $post['bank_user_name'] . ',银行卡号:' . $post['bank_card'] . ',银行名称:' . $post['bank_name'] . ',银行账户类型:' . $post['bank_account_type']; + $log->mold = 3;//财务操作 + $log->saveOrFail(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + + } + + /** + * @doc-name 分账资金流水 + * @doc-param string type 1增2减 / optional + * @doc-param string content 内容 / optional + * @doc-return mixed @List{id,order_id-int-订单id,user_id-int-业务员id或仓库id其他为0,user_type-int-用户类型 1诊所 2平台,type-int-1增2减,amount-float-金额,content-string-内容,created_at-string-流水时间} 快递公司 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionDivideFundWater() + { + + $get = \Yii::$app->request->get(); + $user = \Yii::$app->user->identity; + $query = LedgerLog::find()->orderBy(['id' => SORT_DESC]); + + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query->andWhere(['user_type' => 1]); + } + if ($user->role == UserRoleEnum::SUPER_ADMIN) { + $query->andWhere(['user_type' => [1, 2]]); + } + + if (!empty($get['type'])) { + $query->andWhere(['type' => $get['type']]); + } + + if (!empty($get['content'])) { + $query->andWhere(['like', 'content', $get['content']]); + } + + $this->field = [ + LedgerLog::class => [ + 'id', 'order_id', 'user_id', 'username' => function ($m) { + return Admin::find()->select(['username'])->where(['uid' => $m->user_id])->column(); + }, 'user_type', 'type', 'amount', 'content', + 'created_at' => function ($m) { + return date('Y-m-d H:i:s', $m->created_at); + } + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 首页数据 + * @doc-return mixed @List{id,user_id-int-用户ID,total_cash-float-累计收益,able_cash-int-账户余额,frozen_cash-int-申请提现冻结的金额,withdrawn_cash-int-已提现金额,wait_cash-float-待结算收益,charge_cash-float-手续费,user_type-int-用户类型 1诊所 2平台,last_apply_time-string-最近提现申请时间,account-string-账户} 首页数据 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionHomeData() + { + $get = \Yii::$app->request->get(); + $QUERY = CashAccount::find(); + $this->field = [ + CashAccount::class => [ + 'id', 'user_id', 'total_cash', 'able_cash', 'frozen_cash', 'withdrawn_cash', 'wait_cash', 'charge_cash', + 'account' => function ($m) { + if ($m->user_id == 0) { + return Admin::find()->where(['role' => UserRoleEnum::SUPER_ADMIN])->one(); + } else { + return Store::find()->where(['id' => $m->user_id])->one(); + } + }, + 'user_type', + 'last_apply_time' + ] + ]; + return $this->create($QUERY, $get); + } + + + /** + * @doc-name 平台的提现账户 + * @doc-return string user_id 用户 + * @doc-return string total_cash 累计收益 + * @doc-return string able_cash 账户余额 + * @doc-return string frozen_cash 申请提现冻结的金额 + * @doc-return string withdrawn_cash 待结算收益 + * @doc-return string wait_cash 已提现金额 + * @doc-return string charge_cash 手续费 + * @doc-return string user_type 用户类型 1诊所 2平台 + * @doc-return string last_apply_time 最近提现申请时间 + */ + public function actionPlatformAccount() + { + $get = \Yii::$app->request->get(); + $user = \Yii::$app->user->identity; + + $CashAccount = CashAccount::find()->where(['user_id' => 0, 'user_type' => 2])->one(); + if (!$CashAccount) throw new \yii\db\Exception('账户不存在'); + $price=Ledger::find()->where(['status'=>0,'user_type'=>2,'user_id'=>0])->sum('money'); + $CashAccount->total_cash=bcadd(bcadd($CashAccount->able_cash,$CashAccount->withdrawn_cash,2),$CashAccount->charge_cash,2); + + $CashAccount->wait_cash=$price; + $CashAccount->saveOrFail(); + + return $CashAccount; + } + + /** + * @doc-name 诊所提现账户 + * @doc-param int store_id 诊所ID + * @doc-return string user_id 用户 + * @doc-return string total_cash 累计收益 + * @doc-return string able_cash 账户余额 + * @doc-return string frozen_cash 申请提现冻结的金额 + * @doc-return string withdrawn_cash 待结算收益 + * @doc-return string wait_cash 已提现金额 + * @doc-return string charge_cash 手续费 + * @doc-return string user_type 用户类型 1诊所2平台 + * @doc-return string last_apply_time 最近提现申请时间 + */ + public function actionStoreAccount() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['store_id', 'required'], + ]); + $store = Store::find()->where(['id' => $get['store_id']])->one(); + if (!$store) throw new \yii\db\Exception('诊所不存在'); + + $CashAccount = CashAccount::find()->where(['user_id' => $get['store_id'], 'user_type' => 1])->one(); + if (!$CashAccount) throw new \yii\db\Exception('账户不存在'); + + $price=Ledger::find()->where(['status'=>0,'user_type'=>1,'user_id'=>$CashAccount->user_id])->sum('money'); + $CashAccount->total_cash=bcadd(bcadd($CashAccount->able_cash,$CashAccount->withdrawn_cash,2),$CashAccount->charge_cash,2); + + $CashAccount->wait_cash=$price??0; + $CashAccount->saveOrFail(); + + return $CashAccount; + } + + /** + * @doc-name 分账--审核管理列表 + * @doc-param int status 1待审核2审核通过3审核拒绝 + * @doc-return mixed @List{id,user_id-int-用户ID,user_type-int-用户类型1诊所2总部,order_no-int-订单,apply_cash-float-申请提现金额,true_cash-float-实际到账金额,charge_cash-string-手续费,check_id-string-关联admin表 审核人ID,check_status-string-审核状态0待审核1审核中2已通过3已拒绝,check_result-string-审核结果/拒绝原因,check_time-string-审核时间,apply_time-string-申请时间,dakuan_status-string-打款状态-1失败0未知1成功,dakuan_time-string-打款时间,payee-string-收款人} 审核管理列表 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionCheckManage() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['status', 'required'] + ]); + + $query = CashApply::find()->orderBy(['id' => SORT_DESC]); + switch ($get['status']) { + case 1: + $query->andWhere(['check_status' => [0, 1]]); + break; + case 2: + $query->andWhere(['check_status' => 2]); + break; + case 3: + $query->andWhere(['check_status' => 3]); + break; + default: + throw new \yii\db\Exception('参数错误'); + } + if(!empty($get['start_time']) && !empty($get['end_time'])){ + $start_time=strtotime($get['start_time'].' '.'00:00:00'); + $end_time=strtotime($get['end_time'].' '.'23:59:59'); + $query->andWhere(['between','created_at',$start_time,$end_time]); + } + + + if(!empty($get['name'])){ + if($get['name'] == '平台'){ + $query->andWhere(['user_id' => 0]); + }else{ + $store = Store::find()->where(['name'=>$get['name']])->asArray()->one(); + if($store){ + $query->andWhere(['user_id' => intval($store['id'])]); + }else{ + $query->andWhere(['user_id' => -1]); + } + } + } + + $this->field = [ + CashApply::class => [ + 'id', 'user_id', 'user_type', 'order_no', 'apply_cash', 'true_cash', 'charge_cash', 'check_id', 'check_status', 'check_result', 'check_time', 'apply_time', 'dakuan_status', 'dakuan_time', 'payee' => function ($m) { + if ($m->user_id == 0) { + return Admin::find()->where(['role' => UserRoleEnum::SUPER_ADMIN])->one(); + } else { + return Store::find()->where(['id' => $m->user_id])->one(); + } + } + ] + ]; + return $this->create($query, $get); + } + + + /** + * @doc-name 导出提现审核 + */ + public function actionExportWithDraw() + { + \Yii::$app->response->format = Response::FORMAT_RAW; + $params = \Yii::$app->request->get(); + $parameter['header'] = ['订单号', '平台/诊所', '收款人', '申请提现金额', '审核状态', '时间']; + $parameter['data'] = CashApply::inventory($params,\Yii::$app->user->identity->store_id); + ExportService::ExportByCors($parameter); + } + + /** + * @doc-name 分账--财务数据 + * @doc-param float total_cash 累计收益 + * @doc-param float able_cash 账户余额 + * @doc-param float withdrawn_cash 已体现 + * @doc-param float charge_cash 手续费 + * @doc-param float wait_cash 待结算 + */ + public function actionFenzhangFinance() + { + //总收入 + $total_price=CashAccount::find()->sum('total_cash'); + //账户余额 + $account_price=CashAccount::find()->sum('able_cash'); + $withdrawn_cash=CashAccount::find()->sum('withdrawn_cash'); + $charge_cash=CashAccount::find()->sum('charge_cash'); +// $wait_cash=CashAccount::find()->sum('wait_cash'); + + $wait_cash=Ledger::find()->where(['status'=>0])->sum('money'); + return [ + 'total_cash'=>$total_price, + 'able_cash'=>$account_price, + 'withdrawn_cash'=>$withdrawn_cash, + 'charge_cash'=>$charge_cash, + 'wait_cash'=>$wait_cash??0, + ]; + } + + /** + * @doc-name 分账--财务数据的明细 + */ + public function actionFenzhangFinanceDetail() + { + $CashApply=CashApply::find()->orderBy(['id'=>SORT_DESC])->all(); + $Ledger=Ledger::find()->orderBy(['id'=>SORT_DESC])->with(['productOrder'])->asArray()->all(); + + return [ + 'CashApply'=>$CashApply, + 'Ledger'=>$Ledger, + ]; + } + /** + * @doc-name 平台/诊所提现管理 + * @doc-return mixed @List{id,user_id-int-用户ID,user_type-int-用户类型1诊所2总部,order_no-int-订单,apply_cash-float-申请提现金额,true_cash-float-实际到账金额,charge_cash-string-手续费,check_id-string-关联admin表 审核人ID,check_status-string-审核状态0待审核1审核中2已通过3已拒绝,check_result-string-审核结果/拒绝原因,check_time-string-审核时间,apply_time-string-申请时间,dakuan_status-string-打款状态-1失败0未知1成功,dakuan_time-string-打款时间,payee-string-收款人} 平台/诊所提现管理 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionWithdrawnManage() + { + $get = \Yii::$app->request->get(); + $user = \Yii::$app->user->identity; + $order_no=$get['order_no']; + $query = CashApply::find()->alias('c')->orderBy(['id' => SORT_DESC]); + + if (!empty($order_no)){ + $query->andWhere(['c.order_no'=>$order_no]); + } + if (!empty($get['start_time']) && !empty($get['end_time'])){ + $query->andWhere(['between','c.apply_time',$get['start_time'],$get['end_time']]); + } + if ($user->role==UserRoleEnum::SUPER_ADMIN){//平台 + $query->andWhere(['c.user_id'=>0,'c.user_type'=>2]); + }else{ + $query->andWhere(['c.user_id'=>$user->store_id,'c.user_type'=>1]); + } + $this->field = [ + CashApply::class => [ + 'id', 'user_id', 'user_type', 'order_no', 'apply_cash', 'true_cash', 'charge_cash', 'check_id', 'check_status', 'check_result', 'check_time', 'apply_time', 'dakuan_status', 'dakuan_time', 'payee' => function ($m) { + if ($m->user_id == 0) { + return Admin::find()->where(['role' => UserRoleEnum::SUPER_ADMIN])->one(); + } else { + return Store::find()->where(['id' => $m->user_id])->one(); + } + }, + 'type' => function ($c) {//结算类别 + return '提现记录'; + }, + 'status' => function ($ca) { + if ($ca->check_status == 1 ) { + return '审核中'; + } elseif($ca->check_status == 2) { + return '审核通过,提现成功'; + }elseif($ca->check_status == 3) { + return '申请已拒绝,手续费未扣'; + }elseif($ca->check_status == 4 ) { + return '审核通过,提现失败'; + }else{ + return '未知'; + } + }, + 'tixian_person'=>function($m){ + if ($m->user_type==1)return '诊所'; + if ($m->user_type==2)return '平台'; + }, + ], + ]; + return $this->create($query, $get); + } + + + /** + * @doc-name 平台/诊所结算列表 + * @doc-param string order_no 产品订单号 + * @doc-param string register_no 挂号订单号 + * @doc-param string start_time 开始时间 + * @doc-param string end_time 结束时间 + * @doc-return mixed @List{id,user_id-int-用户ID,user_type-int-用户类型1诊所2总部,order_no-int-订单,order_id-int-订单id,su_id-int-医生id,drugstore_id-int-仓库id,drug_id-string-药品id,status-string-结算状态 0待结算 1已结算 2已取消,money-string-分佣金额,time-string-时间} 平台/诊所是否结算管理 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionJiesuanList() + { + $get = \Yii::$app->request->get(); + $user = \Yii::$app->user->identity; + $order_no=$get['order_no']; + $register_no=$get['register_no']; + $start_time=strtotime($get['start_time']); + $end_time=strtotime($get['end_time']); + + $query = Ledger::find()->alias('l')->where(['l.status'=>[0,1]])->orderBy(['l.id' => SORT_DESC]); + + if (!empty($order_no)){ + $query->joinWith(['productOrder'=>function($p)use($order_no){ + $p->where(['order_no'=>$order_no]); + }]); + } + if (!empty($register_no)){ + $query->joinWith(['register'=>function($p)use($register_no){ + $p->where(['order_no'=>$register_no]); + }]); + } + if (!empty($start_time) && !empty($end_time)){ + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + $query->andWhere(['between','l.created_at',$start_time,$end_time]); + } + + if ($user->role==UserRoleEnum::SUPER_ADMIN){//平台 + $query->andWhere(['l.user_id'=>0,'l.user_type'=>2])->groupBy('l.order_id,l.order_type'); + }else{ + $query->andWhere(['l.user_id'=>$user->store_id,'l.user_type'=>1])->groupBy('l.order_id,l.order_type'); + } + $this->field = [ + Ledger::class => [ + 'id', 'user_id','order_id', 'user_type','su_id', 'drugstore_id', 'drug_id', 'status', 'money'=> function ($m) { + return $this->actionTotal($m->order_id,$m->user_type,$m->order_type); + }, + 'order_no'=> function ($order) { + if ($order->order_type == 1) { + return ProductOrder::find()->select(['order_no'])->where(['id' => $order->order_id])->column(); + } + if ($order->order_type == 2) { + return Register::find()->select(['order_no'])->where(['id' => $order->order_id])->column(); + } + }, + 'type'=>function($l){ + if ($l->order_type==1){ + return '产品订单'; + }else{ + return '挂号订单'; + } + }, + 'fee_type'=>function($f){ + if ($f->fee_type==1){ + return '药品费用'; + }elseif($f->fee_type==2){ + return '挂号费用'; + }elseif($f->fee_type==3){ + return '快递费用'; + }elseif($f->fee_type==4){ + return '代煎费用'; + }else{ + return '其他'; + } + }, + 'price_from'=>'productOrder.user.nickname', + 'time'=>function($le){ + return date('Y-m-d H:i:s',$le->created_at); + } + ], + ]; + return $this->create($query, $get); + } + + + public function actionTotal($order_id='',$user_type=1,$order_type='') + { + + $money = Ledger::find()->alias('l')->where(['l.order_id' => $order_id, 'l.status' => [0, 1]])->andWhere(['l.user_type'=>$user_type,'l.order_type'=>$order_type])->sum('money'); + return $money ?? 0; + } + +} \ No newline at end of file diff --git a/admin/controllers/base/FinanceController.php b/admin/controllers/base/FinanceController.php new file mode 100644 index 0000000..4747f40 --- /dev/null +++ b/admin/controllers/base/FinanceController.php @@ -0,0 +1,439 @@ +request->get(); + $user = \Yii::$app->user->identity; + + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query = ProductOrderRefund::find()->alias('po')->where([ + 'po.is_deleted' => 0 + ])->orderBy(['po.id' => SORT_DESC]); +// $query->joinWith(['order' => function ($model) use ($user) { +// $model->andWhere(['drugstore_id' => $user->drugstore]); +// }]); + } + if ($user->role == UserRoleEnum::SUPER_ADMIN) { + $query = ProductOrderRefund::find()->alias('po')->where([ + 'is_deleted' => 0 + ])->orderBy(['po.id' => SORT_DESC]); + } + + if (!empty($get['refund_no'])) { + $query->andWhere(['refund_no' => $get['refund_no']]); + } + $this->field = [ + ProductOrderRefund::class => [ + 'id', 'order_id', 'user_id', 'reason', 'remark', 'refund_images', 'refund_type', 'refund_no', 'refund_price', 'is_refund', 'refund_time', + 'status', 'created_at' => function ($m) { + return date('Y-m-d H:i:s', $m->created_at); + } + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 同意退款操作 + * @doc-param int id 退款申请记录ID + */ + public function actionRefundAgree() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id', 'required'], + ]); + $user = \Yii::$app->user->identity; + + $t = \Yii::$app->db->beginTransaction(); + try { + $ProductOrderRefund = ProductOrderRefund::find()->where([ + 'id' => $post['id'], + 'is_deleted' => 0, + ])->with(['order'])->one(); + + if (!$ProductOrderRefund) { + throw new Exception('退款申请记录不存在'); + } + + $ProductOrder = ProductOrder::find()->where(['id' => $ProductOrderRefund->order_id])->one(); + if (!$ProductOrder) throw new Exception('产品订单不存在'); + + + $ProductOrder->refund_status = 3;//已退款 + $ProductOrder->saveOrFail(); + + $ProductOrderRefund->is_refund = 1; + $ProductOrderRefund->status = 1; + $ProductOrderRefund->refund_time = date('Y-m-d H:i:s', time()); + $ProductOrderRefund->saveOrFail(); + + $form = new ProductRefundForm(); + $form->refundMoney($ProductOrderRefund); + + $t->commit(); + return ['success']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 拒绝退款操作 + * @doc-param int id 退款申请记录ID + * @doc-param string check_result 拒绝原因 + */ + public function actionRefundRefuse() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['id_id', 'check_result'], 'required'], + ]); + $id = $post['id_id']; + $user = \Yii::$app->user->identity; + + if ($user->role == UserRoleEnum::SUPER_ADMIN) {//超管 + $ProductOrderRefund = ProductOrderRefund::find()->where([ + 'id' => $id, + 'is_deleted' => 0, + ])->with(['order'])->one(); + + } + if ($user->role == UserRoleEnum::STORE_ADMIN) {//门店管理员 + $ProductOrderRefund = ProductOrderRefund::find()->alias('po')->where([ + 'po.id' => $id, + 'po.is_deleted' => 0, + ])->with(['order'])->one(); + } + + + if (!$ProductOrderRefund) throw new Exception('退款申请记录不存在'); + + $t = \Yii::$app->db->beginTransaction(); + try { + $ProductOrder = ProductOrder::find()->where(['id' => $ProductOrderRefund->order_id])->one(); + + if (!$ProductOrder) throw new Exception('产品订单不存在'); + if ($ProductOrder->is_send == 1) { + $ProductOrder->status = 6;//确认收货 + } else { + $ProductOrder->status = 1;//待发货 + } + $ProductOrder->refund_status = 4;//拒绝退款 + $ProductOrder->saveOrFail(); + + $ProductOrderRefund->is_refund = 0; + $ProductOrderRefund->status = 3;//拒绝退款 + $ProductOrderRefund->check_result = $post['check_result'];//审核结果 + $ProductOrderRefund->refund_time = date('Y-m-d H:i:s', time()); + $ProductOrderRefund->saveOrFail(); + + //拒绝退款通知 + $systemNotice = new SystemNotice(); + $systemNotice->store_id = $ProductOrder->store_id; + $systemNotice->content = '工作人员已拒绝退款,原因:' . $post['check_result']; + $systemNotice->base_type = 7; + $systemNotice->scene_type = 1; + $systemNotice->user_id = $ProductOrderRefund->user_id; + $systemNotice->notice_at = date('Y-m-d h:i:s', time()); + $systemNotice->saveOrFail(); + + + $t->commit(); + return ['success']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + + /** + * @doc-name 资金流水记录 + * @doc-param string start_time 时间 / optional + * @doc-param string end_time 时间 / optional + * @doc-param string doctor 医生 / optional + * @doc-param string store 诊所 / optional + * @doc-param string order_no 订单号 / optional + * @doc-param string refund_no 退款单号 / optional + * @doc-return @List{id,order_id-int-订单id,order_type-int-订单类型1产品订单2问诊订单,user_id-int-用户ID,type-string-类型enter入账refund出账,price-float-金额,order_no-string-订单号,refund_no-string-退款单号,created_at-string-收入或支出时间,pay_type-int-支付类型1为微信} 资金流水记录 + */ + public function actionFundWater() + { + $get = \Yii::$app->request->get(); + $user = \Yii::$app->user->identity; + + $start_time=strtotime($get['start_time']); + $end_time=strtotime($get['end_time']); + + $doctor = $get['doctor']; + $store = $get['store']; + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query = FundWater::find()->where([ + 'f.store_id' => $user->store_id + ])->alias('f')->orderBy(['id' => SORT_DESC]); + } + if ($user->role == UserRoleEnum::SUPER_ADMIN) { + $query = FundWater::find()->alias('f')->orderBy(['id' => SORT_DESC]); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time==$end_time){//筛选当天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + $query->andWhere(['between', 'f.created_at', $start_time,$end_time]); + } + + if (!empty($doctor)) { + $query->joinWith(['doctor' => function ($d) use ($doctor) { + $d->alias('d'); + $d->andWhere(['like', 'd.name', $doctor]); + }]); + } + if (!empty($store)) { + $query->joinWith(['store' => function ($s) use ($store) { + $s->alias('s'); + $s->andWhere(['like', 's.name', $store]); + }]); + } + + if (!empty($get['order_no'])) { + $query->andWhere(['f.order_no' => $get['order_no']]); + } + if (!empty($get['refund_no'])) { + $query->andWhere(['f.refund_no' => $get['refund_no']]); + } + $this->field = [ + FundWater::class => [ + 'id', 'order_id', 'order_type', 'user_id', 'type', 'price', 'order_no', 'refund_no', 'pay_type', 'store_id', + 'created_at' => function ($m) { + return date('Y-m-d H:i:s', $m->created_at); + }, + 'store' => 'store.name', 'service_user_id', 'doctor' => 'doctor.name', + 'user' => 'user.nickname' + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 导出资金流水 + */ + public function actionExportFundWater() + { + \Yii::$app->response->format = Response::FORMAT_RAW; + $params = \Yii::$app->request->post(); + $parameter['header'] = ['订单类型', '医生', '用户', '价格', '诊所', '时间']; + $parameter['data'] = FundWater::inventory($params,\Yii::$app->user->identity->store_id); + ExportService::ExportByCors($parameter); + } + + /** + * @doc-name 财务数据--结算记录(包括平台和门诊的) + * @doc-param string order_no 产品订单号 + * @doc-param string register_no 挂号订单号 + * @doc-param string start_time 开始时间 + * @doc-param string end_time 结束时间 + * @doc-param string order_no 订单 + * @doc-return mixed @List{id,user_id-int-用户ID,user_type-int-用户类型1诊所2总部,order_no-int-订单,order_id-int-订单id,su_id-int-医生id,drugstore_id-int-仓库id,drug_id-string-药品id,status-string-结算状态 0待结算 1已结算 2已取消,money-string-分佣金额,time-string-时间} 平台/诊所是否结算管理 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionJiesuanList() + { + $get = \Yii::$app->request->get(); + $order_no = $get['order_no']; + $register_no = $get['register_no']; + $start_time=strtotime($get['start_time'].' '.'00:00:00'); + $end_time=strtotime($get['end_time'].' '.'23:59:59'); + + $query = Ledger::find()->alias('l')->where(['l.status' => [0, 1]])->orderBy(['id' => SORT_DESC])->groupBy('l.order_id,l.order_type'); + if (!empty($order_no)) { + + $query->joinWith(['productOrder' => function ($p) use ($order_no) { + $p->where(['order_no' => $order_no]); + }]); + } + + if (!empty($register_no)){ + $query->joinWith(['register'=>function($p)use($register_no){ + $p->where(['order_no'=>$register_no]); + }]); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time==$end_time){//筛选当天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + $query->andWhere(['between', 'l.created_at', $start_time, $end_time]); + } + + $this->field = [ + Ledger::class => [ + 'id', 'user_id', 'user_type', 'su_id', 'drugstore_id', 'drug_id', 'status', 'money' => function ($m) { + return $this->actionTotal($m->order_id); + }, + 'order_id', + 'order_no' => function ($order) { + if ($order->order_type == 1) { + return ProductOrder::find()->select(['order_no'])->where(['id' => $order->order_id])->column(); + } + if ($order->order_type == 2) { + return Register::find()->select(['order_no'])->where(['id' => $order->order_id])->column(); + } + }, + 'type' => function ($l) { + if ($l->order_type == 1) { + return '产品订单'; + } else { + return '挂号订单'; + } + }, + 'fee_type' => function ($f) { + if ($f->fee_type == 1) { + return '药品费用'; + } elseif ($f->fee_type == 2) { + return '挂号费用'; + } elseif ($f->fee_type == 3) { + return '快递费用'; + } elseif ($f->fee_type == 4) { + return '代煎费用'; + } else { + return '其他'; + } + }, + 'price_from' => 'productOrder.user.nickname', + 'time' => function ($le) { + return date('Y-m-d H:i:s', $le->created_at); + } + ], + ]; + return $this->create($query, $get); + } + + public function actionTotal($order_id) + { + $money = Ledger::find()->alias('l')->where(['l.order_id' => $order_id, 'l.status' => [0, 1]])->sum('money'); + return $money ?? 0; + } + + /** + * @doc-name 财务数据--提现记录 + * @doc-param string order_no 订单号 + * @doc-param string start_time 开始时间 + * @doc-param string end_time 结束时间 + * @doc-return mixed @List{id,user_id-int-用户ID,user_type-int-用户类型1诊所2总部,order_no-int-订单,apply_cash-float-申请提现金额,true_cash-float-实际到账金额,charge_cash-string-手续费,check_id-string-关联admin表 审核人ID,check_status-string-审核状态0待审核1审核中2已通过3已拒绝,check_result-string-审核结果/拒绝原因,check_time-string-审核时间,apply_time-string-申请时间,dakuan_status-string-打款状态-1失败0未知1成功,dakuan_time-string-打款时间,payee-string-收款人} 平台/诊所提现管理 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionWithdrawnManage() + { + $get = \Yii::$app->request->get(); + $order_no = $get['order_no']; + $start_time=strtotime($get['start_time'].' '.'00:00:00'); + $end_time=strtotime($get['end_time'].' '.'23:59:59'); + + $query = CashApply::find()->alias('c')->orderBy(['id' => SORT_DESC]); + if (!empty($order_no)) { + $query->where(['c.order_no' => $order_no]); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time==$end_time){//筛选当天 + $time=FuncHelper::getDayBE($get['start_time']); + $start_time=$get['start_time']; + $end_time=date('Y-m-d H:i:s',$time); + }else{ + $start_time=$get['start_time']; + $end_time=$get['end_time']; + } + + $query->andWhere(['between', 'c.apply_time',$start_time,$end_time]); + } + + + $this->field = [ + CashApply::class => [ + 'id', 'user_id', 'user_type', 'order_no', 'apply_cash', 'true_cash', 'charge_cash', 'check_id', 'check_status', 'check_result', 'check_time', 'apply_time', 'dakuan_status', 'dakuan_time', 'payee' => function ($m) { + if ($m->user_id == 0) { + return Admin::find()->where(['role' => UserRoleEnum::SUPER_ADMIN])->one(); + } else { + return Store::find()->where(['id' => $m->user_id])->one(); + } + }, + 'type' => function ($c) {//结算类别 + return '提现记录'; + }, + 'status' => function ($ca) { + if ($ca->check_status == 1) { + return '审核中'; + } elseif ($ca->check_status == 2) { + return '审核通过,提现成功'; + } elseif ($ca->check_status == 3) { + return '申请已拒绝,手续费未扣'; + } elseif ($ca->check_status == 4) { + return '审核通过,提现失败'; + } else { + return '未知'; + } + }, + 'tixian_person' => function ($m) { + if ($m->user_type == 1) return '诊所'; + if ($m->user_type == 2) return '平台'; + }, + ], + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 导出提现、结算记录 + */ + public function actionExportSettlement() + { + \Yii::$app->response->format = Response::FORMAT_RAW; + $params = \Yii::$app->request->get(); + if($params['type'] == 1){ + $parameter['header'] = ['单号','提现方', '提现金额', '到账金额','手续费', '状态', '时间']; + $parameter['data'] = CashApply::inventory1($params); + }else{ + $parameter['header'] = ['单号','订单类型', '用户', '金额', '状态', '时间']; + $parameter['data'] = Ledger::inventory($params,\Yii::$app->user->identity->store_id); + } + + ExportService::ExportByCors($parameter); + } + +} \ No newline at end of file diff --git a/admin/controllers/base/NavController.php b/admin/controllers/base/NavController.php new file mode 100644 index 0000000..dae043d --- /dev/null +++ b/admin/controllers/base/NavController.php @@ -0,0 +1,174 @@ + 0, 'value' => '轮播图'], + ]; + } + + /** + * @doc-name 轮播图列表 + * @doc-param int is_home 是否首页0否1是 / optional + * @doc-param int type 类型1活动2专题 / optional + * @doc-return mixed @nav{id,pic,external_link-string-外部链接,is_home-int-是否首页0否1是,home_time-string-首页时间,type-int-类型1活动2专题} 轮播图 + */ + public function actionList() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['store_id', 'required'] + ]); + $admin = \Yii::$app->user->identity; + + $query = Nav::find()->where([ + 'store_id' => $get['store_id'], + 'is_delete' => 0, + ])->orderBy(['id' => SORT_DESC]); + + + if (!empty($get['is_home'])) { + $query->andWhere([ + 'is_home' => $get['is_home'] + ]); + } + if (!empty($get['type'])) { + $query->andWhere([ + 'type' => $get['type'] + ]); + } + $this->field = [ + Nav::class => [ + 'id', 'pic', 'external_link', 'is_home', 'home_time', 'type', 'sort', 'store_id','link_type' + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 新增轮播图 + * @doc-param int store_id 门店ID / optional + * @doc-param int sort 排序 / optional + * @doc-param string pic 轮播图 + * @doc-param int link_type 1内部2外部 / optional + * @doc-param string external_link 外部链接 / optional + * @doc-param int is_home 是否首页0否1是 / optional + * @doc-param int type 类型1轮播图 / optional + */ + public function actionSaveNav() + { + $post = \Yii::$app->request->post(); + + $NavForm = new NavForm(); + $NavForm->attributes = $post; + return $NavForm->save(); + } + + /** + * @doc-name 修改轮播图 + * @doc-param int id 轮播图id + * @doc-param string store_id 门店ID + * @doc-param string sort 排序 + * @doc-param string pic 轮播图 + * @doc-param string external_link + * @doc-param int is_home 是否首页0否1是 + * @doc-param int type 类型1活动2专题 + */ + public function actionEditNav() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id', 'required'] + ]); + + $NavForm = new NavForm(); + $NavForm->attributes = $post; + return $NavForm->update(); + } + + /** + * @doc-name 删除轮播图 + * @doc-param int id 轮播图id + */ + public function actionDel() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + + $NavForm = new NavForm(); + $NavForm->attributes = $get; + return $NavForm->del(); + } + + /** + * @doc-name 轮播图详情 + * @doc-param int id 轮播图id + * @doc-return mixed @nav{*} 轮播图 + */ + public function actionInfo() + { + $get =\Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + $nav = Nav::find()->where([ + 'id' => $get['id'], + 'is_delete' => 0 + ])->one(); + if (!$nav) throw new Exception('轮播图不存在'); + + return $nav; + + } + + /** + * @doc-name 是否推送的首页 + * @doc-param int id 轮播图id + * @doc-param int status 状态0否1是 + */ + public function actionIsHome() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['id', 'status'], 'required'] + ]); + $nav = Nav::find()->where([ + 'id' => $post['id'], + 'is_delete' => 0 + ])->one(); + if (!$nav) throw new Exception('轮播图不存在'); + + switch ($post['status']) { + case 0: + $nav->is_home = 0; + $nav->home_time = date('Y-m-d H:i:s', time()); + $nav->saveOrFail(); + return ['已取消']; + break; + case 1: + $nav->is_home = 1; + $nav->home_time = date('Y-m-d H:i:s', time()); + $nav->saveOrFail(); + return ['已推送']; + break; + default: + throw new Exception('参数错误'); + } + } +} \ No newline at end of file diff --git a/admin/controllers/base/NoticeController.php b/admin/controllers/base/NoticeController.php new file mode 100644 index 0000000..2c3435a --- /dev/null +++ b/admin/controllers/base/NoticeController.php @@ -0,0 +1,51 @@ +request->get(); + $query = SystemNotice::find()->where(['base_type'=>99]); + $this->field = [ + SystemNotice::class => [ + 'id', 'scene_type', 'content','base_type' + ] + ]; + return $this->create($query,$get); + + } + + /** + * @doc-name 发送公告 + * @doc-param string content 发送公告 + * @doc-param int type 3全部4所有医生5所有用户 发送公告 + */ + public function actionAddNotice() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + [['type', 'content'], 'required'] + ]); + + $SystemNotice = new SystemNotice(); + $SystemNotice->content = $get['content']; + $SystemNotice->scene_type = $get['type']; + $SystemNotice->base_type = 99; + + + $SystemNotice->saveOrFail(); + } +} \ No newline at end of file diff --git a/admin/controllers/base/OrderController.php b/admin/controllers/base/OrderController.php new file mode 100644 index 0000000..9211dff --- /dev/null +++ b/admin/controllers/base/OrderController.php @@ -0,0 +1,511 @@ +request->get(); + $good_name = $get['good_name']; + $store = $get['store']; + $doctor = $get['doctor']; + $type=$get['type']; + $admin = \Yii::$app->user->identity; + + $start_time=strtotime($get['start_time'].' '.'00:00:00'); + $end_time=strtotime($get['end_time'].' '.'23:59:59'); + + if ($admin->role == UserRoleEnum::STORE_ADMIN) {//门店 + $query = ProductOrder::find()->alias('pd')->where(['pd.store_id' => $admin->store_id])->orderBy(['pd.id' => SORT_DESC]); + } elseif ($admin->role == UserRoleEnum::PROVINCE_DAI){//省代 + $store_id = Store::find()->select(['id'])->where(['province_id' => $admin->province_id])->column(); + $query = ProductOrder::find()->alias('pd')->where(['in','pd.store_id',$store_id])->orderBy(['pd.id' => SORT_DESC]); + } elseif ($admin->role == UserRoleEnum::CITY_DAI){//市代 + $store_id = Store::find()->select(['id'])->where(['city_id' => $admin->city_id])->column(); + $query = ProductOrder::find()->alias('pd')->where(['in','pd.store_id',$store_id])->orderBy(['pd.id' => SORT_DESC]); + } elseif ($admin->role == UserRoleEnum::SUPPLY){//业务员 + $store_id = Store::find()->select(['id'])->where(['code' => $admin->code])->column(); + $query = ProductOrder::find()->alias('pd')->where(['in','pd.store_id',$store_id])->orderBy(['pd.id' => SORT_DESC]); + }else {//总后台 + $query = ProductOrder::find()->alias('pd')->orderBy(['pd.id' => SORT_DESC]); + } + if (!empty($get['order_no'])) {//订单编号 + $query->andWhere(['pd.order_no' => $get['order_no']]); + } + $query->joinWith(['prescription' => function ($p) use ($good_name) { + $p->alias('p'); + if (!empty($good_name)) {//商品名称 + $p->where(['like', 'p.content', $good_name]); + } + }]); + + if (!empty($get['accept_name'])) {//收件人姓名 + $query->where(['like', 'pd.express_name', $get['accept_name']]); + } + if (!empty($post['accept_tel'])) {//收件人电话 + $query->where(['like', 'pd.express_mobile', $get['accept_tel']]); + } + + $query->joinWith(['doctor' => function ($doc) use ($doctor) { + $doc->alias('doc'); + if (!empty($doctor)) {//医生搜索 + $doc->andWhere(['like', 'doc.name', $doctor]); + } + }]); + + if (isset($get['status']) && is_numeric($get['status'])) {//产品订单状态 + if ($get['status'] == 3) { + $query->andWhere(['pd.status' => [3, 6, 7]]); + } else { + $query->andWhere(['pd.status' => $get['status']]); + } + } + + if (!empty($store)) {//门店 + $query->andWhere(['pd.store_id' => $store]); + } + + if (!empty($get['after_status'])) {//售后状态 + $query->andWhere(['pd.refund_status' => $get['after_status']]); + } + + if (!empty($type)) { + $query->andWhere(['pd.prescription_type' => $type]); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time==$end_time){//筛选某一天 + + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + $query->andWhere(['between', 'pd.created_at', $start_time,$end_time]); + } + + + $this->field = [ + ProductOrder::class => [ + 'id', 'store_id','prescription_type', 'user_id', 'up_id', 'p_id', 'status', 'cancel_status', 'order_type', 'order_no', 'total_pay_price', 'type', 'items_price','market_price', 'process_price', 'treatement_price','address_id', 'status', 'trans_expenses', 'free_ship', + 'cancel_time' => function ($pd) { + if($pd->cancel_time){ + return date('Y-m-d H:i:s', $pd->cancel_time); + } + }, 'cancel_remark', 'refund_status', + 'refund_time' => function ($pd) { + if($pd->refund_time){ + return date('Y-m-d H:i:s', $pd->refund_time); + } + }, + 'store' => function ($d) { + return Store::find()->select(['id','drugstore_id','erp_id','plate_id','name','shouzimu','contact','mobile','offical_seal','code','position'])->where([ + 'id' => $d->store_id + ])->one(); + }, + 'drugstore' => function ($d) { + $drugstore_id = Store::find()->select(['drugstore_id'])->where([ + 'id' => $d->store_id + ])->column(); + return DrugStore::find()->select(['name'])->where(['in', 'id', $drugstore_id])->all(); + }, + 'pay_time' => function ($m) { + if($m->pay_time){ + return date('Y-m-d H:i:s', $m->pay_time); + } + }, + 'is_has' => function ($i) { + return $i->p_id ? '有处方' : '无处方'; + }, + 'doctor' => 'doctor.name', + // 'good' => function ($model) { + // return $this->actionProductOrderDetail($model->id); + // }, + 'prescription' => function ($p) { + if($p->p_id){ + $prescription = Prescription::find()->where([ + 'id' => $p->p_id, + 'is_deleted' => 0 + ])->with(['pharmacistInfo','doctorInfo.depart'])->asArray()->one(); + $content = Json::decode($prescription['content']); + $repice = $content['repice']; + if($prescription['prescription_type'] == 2){ //西药 + foreach($repice as $k => $v){ + $repice[$k]['content'] = Json::decode($v['content']); + } + } else { + $repiceContent = Json::decode($repice[0]['content']); + // foreach($repiceContent as $k=>$v){ + // $repiceContent[$k]['content'] = Json::decode($v['content']); + // } + $repice[0]['content'] = $repiceContent; + } + $content['repice'] = $repice; + $prescription['content'] = $content; + } + return $prescription; + }, + 'address' => function ($m) { + return json_decode($m->address); + }, + 'created_at' => function ($mo) { + return date('Y-m-d H:i:s', $mo->created_at); + }, + 'express_name'=>function($e){ + return $this->actionReceiveInfo($e->id,1); + }, + 'express_mobile'=>function($e){ + return $this->actionReceiveInfo($e->id,2); + }, + 'express_region'=>function($e){ + return $this->actionReceiveInfo($e->id,3); + }, + 'express_address'=>function($e){ + return $this->actionReceiveInfo($e->id,4); + }, + 'patient' => 'userPatient.name', + 'user' => 'user.nickname', + 'product_order_items' => function ($m) { + return $this->actionProductOrderItem($m->id); + }, + 'patient_sex' => 'userPatient.sex', + 'patient_age' => 'userPatient.age', + 'patient_mobile' => 'userPatient.mobile', + 'category' => 'prescription.category', + 'productOrderRefund_status' => 'productOrderRefund.status', + 'productOrderRefund_id' => function($m){ + return $this->actionProductOrderRefund($m->id); + }, + 'service_price'=>function($m){ + return $this->actionDaijianFei($m->id); + }, + 'is_decoct','decoct_price','express_no_id', + 'delivery_method', + ] + ]; + return $this->create($query, $get); + } + /** + * @doc-name 收获信息 + * @doc-author huangyuling + */ + public function actionReceiveInfo($id,$type){ + $info=ProductOrder::find()->where(['id'=>$id])->asArray()->one(); + + switch ($type){ + case 1: + if ($info['delivery_method']==0){ + return $info['express_name']; + }else{ + $user_patient=UserPatient::find()->where(['id'=>$info['up_id']])->asArray()->one(); + if (!$user_patient){ + throw new Exception('患者信息不存在'); + + } return $user_patient['name']; + } + break; + case 2: + if ($info['delivery_method']==0){ + return $info['express_name']; + }else{ + $user_patient=UserPatient::find()->where(['id'=>$info['up_id']])->asArray()->one(); + if (!$user_patient){ + throw new Exception('患者信息不存在'); + } + return $user_patient['mobile']; + } + break; + case 3: + if ($info['delivery_method']==0){ + return $info['express_region']; + }else{ + $store=Store::find()->where(['id'=>$info['store_id']])->with(['province','city'])->asArray()->one(); + + if (!$store){ + throw new Exception('门店信息不存在'); + } + return $store['province']['name'].$store['city']['name']; + } + break; + case 4: + if ($info['delivery_method']==0){ + return $info['express_address']; + }else{ + $store=Store::find()->where(['id'=>$info['store_id']])->asArray()->one(); + + if (!$store){ + throw new Exception('门店信息不存在'); + } + return $store['position']; + } + break; + default: + throw new Exception('类型错误'); + + } + + } + /** + * @doc-name 退款申请ID + * @doc-return int id id + */ + public function actionProductOrderRefund($id) + { + $ProductOrderRefund=ProductOrderRefund::find()->select(['id','reason'])->where(['order_id'=>$id])->orderBy(['id'=>SORT_DESC])->one(); + return $ProductOrderRefund; + } + /** + * @doc-name 取消商品(或产品)订单 + * @doc-param int order_id 商品(或产品)订单id + * @doc-param int user_id 用户id + */ + public function actionGoodCancel() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['order_id', 'user_id'], 'required'] + ]); + $form = new ProductCancelForm(); + return $form->cancel($post); + } + + /** + * @doc-name 商品订单退款 + * @doc-param int order_id 商品(或产品)订单id + * @doc-param int user_id 用户id + * @doc-param string reason 退款原因 + * @doc-param string refund_images 退款图片 / optional + */ + public function actionGoodRefund() + { + + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['order_id', 'user_id', 'reason'], 'required'] + ]); + $form = new ProductRefundForm(); + return $form->refund($post); + } + + /** + * @doc-name 发货 + * @doc-param int order_id 商品(或产品)订单id + */ + public function actionSendOperate() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $user = \Yii::$app->user->identity; + + if ($user->role != UserRoleEnum::STORE_ADMIN) { + throw new Exception('您没有该门店权限'); + } + $ProductOrder = ProductOrder::find()->where([ + 'store_id' => $user->store_id, + 'id' => $post['order_id'] + ])->one(); + if (!$ProductOrder) throw new Exception('产品订单不存在'); + + $Prescription=Prescription::find()->where(['id'=>$ProductOrder['p_id'],'is_deleted'=>0])->one(); + if ($Prescription['status']!=1){ + throw new Exception('处方未通过,不能发货'); + } + $ProductOrder->is_send = 1; + $ProductOrder->send_time = date('Y-m-d H:i:s', time()); + if (!$ProductOrder->saveOrFail()) { + throw new Exception('发货失败'); + } + + //订单发货3天后分账结算 + // if($ProductOrder->type == 2){ //易票联支付的产品订单 + // $config = \Yii::$app->params; + // $orderAutoSettlementTime = isset($config['product_order']['settlement_time']) ? $config['product_order']['settlement_time'] : 72*3600; + // $TIME=180; + // \Yii::$app->queue->delay($TIME)->push(new ProductOrderSendJob([ + // 'orderId' => $ProductOrder->id + // ])); + // } + return ['发货成功']; + } + + /** + * @doc-name 产品订单详情 + * @doc-param int product_id 产品订单id + */ + public function actionProductDetail() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['product_id', 'required'] + ]); + + $ProductOrder = ProductOrder::find()->where([ + 'id' => $get['product_id'] + ])->with(['expressNos', 'prescription', 'orderItems'])->asArray()->one(); + if (!$ProductOrder) throw new Exception('产品订单不存在'); + + + if ($ProductOrder['prescription']['prescription_type'] == 1) { + $SystemConfig = SystemConfig::findOne(['type' => 1]); + $ProductOrder['daijianfei'] = $SystemConfig['value']; + } + + return $ProductOrder; + } + + /** + * 订单物流详情 + */ + public function actionExpress(){ + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['order_id', 'required'] + ]); + $express = (new ExpressService())->detail($get['order_id']); + return $express; + } + + /** + * @doc-name 处理处方快照 + */ + public function actionProductOrderDetail($id = null) + { + $p_id = ProductOrder::find()->select(['p_id'])->where(['id' => $id])->column(); + $prescription_type = Prescription::find()->select(['prescription_type'])->where(['id' => $p_id, 'is_deleted' => 0])->column(); + + if ($prescription_type[0] == 1 || $prescription_type[0] == 3) {//中药 配方颗粒 + + $content = Prescription::find()->where(['id' => $p_id, 'is_deleted' => 0])->one(); + $recipe = json_decode($content['content'], true)['repice']; + + $data['content'] = json_decode($recipe[0]['content']); + $data['deployment'] = $recipe[0]['deployment']; + $data['dosage'] = $recipe[0]['dosage']; + $data['consumption'] = $recipe[0]['consumption']; + $data['directions'] = $recipe[0]['directions']; + $data['usage'] = $recipe[0]['usage']; + $data['fufa_id'] = $recipe[0]['fufa_id']; + $data['volume'] = $recipe[0]['volume']; + $data['is_deepfry'] = $recipe[0]['is_deepfry']; + $data['cm_id'] = $recipe[0]['cm_id']; + $data['total_price'] = $recipe[0]['total_price']; + $data['remark'] = $recipe[0]['remark']; + return $data; + } else {//西药 + + $Prescription = Prescription::find()->where(['id' => $p_id, 'is_deleted' => 0])->one(); + if (!$Prescription) throw new Exception('处方不存在'); + + $repice = json_decode($Prescription['content'], true)['repice']; + + $data = []; + foreach ($repice as $v) { + $item = [ + 'id' => $v['id'], + 'content' => json_decode($v['content']), + 'drug_name' => json_decode($v['content'])->drug_name, + 'source' => json_decode($v['content'])->source, + 'function' => json_decode($v['content'])->function, + 'usage' => json_decode($v['content'])->usage, + 'specification' => json_decode($v['content'])->specification, + 'instruction' => json_decode($v['content'])->instruction, + 'image' => json_decode($v['content'])->image, + 'number' => $v['number'], + 'available_days' => $v['available_days'], + 'total_price' => $v['total_price'], + 'created_at' => $v['created_at'], + 'type_id' => json_decode($v['content'])->type_id, + 'time_id' => json_decode($v['content'])->time_id, + 'frequency_id' => json_decode($v['content'])->frequency_id, + 'unit_id' => json_decode($v['content'])->unit_id, + 'usetime' => $v['usetime']['name'], + 'frequency' => $v['frequency']['name'], + 'grain_number' => $v['grain_number'], + 'westUnit' => $v['westUnit']['name'], + 'types' => $v['usetype']['name'], //药的使用方式 + + ]; + + $data[] = $item; + } + return $data; + } + } + + //商品订单的商品明细 + public function actionProductOrderItem($id = null) + { + return ProductOrderItems::find()->with('drug')->where(['product_order_id' => $id])->asArray()->all(); + } + + + /** + * @doc-name 导出产品订单 + */ + public function actionExportProductOrder() + { + \Yii::$app->response->format = Response::FORMAT_RAW; + $params = \Yii::$app->request->get(); + $parameter['header'] = ['易票联订单号','订单号','诊所名称', '商品名称', '规格', '厂家', '单价', '加工费', '诊疗费', '销售价', '采购价','总价', '运费', '医生', '订单状态', '售后状态', '下单时间', '收件人姓名', '电话', '地址', '支付时间']; + $parameter['data'] = ProductOrder::inventory($params,\Yii::$app->user->identity->store_id); + ExportService::ExportByCors($parameter); + + } + /** + * @doc-name 代煎费 + */ + public function actionDaijianFei($id=null) + { + $ProductOrder=ProductOrder::find()->where(['id'=>$id])->one(); + if (!$ProductOrder)throw new Exception('产品订单不存在'); + $Prescription=Prescription::findOne(['id'=>$ProductOrder['p_id'],'is_deleted'=>0]); + if ($Prescription['prescription_type'] == 1 || $Prescription['prescription_type']==3 ) { + $SystemConfig = SystemConfig::findOne(['type' => 1]); + + return $SystemConfig['value']; + }else{ + return '无'; + } + } +} \ No newline at end of file diff --git a/admin/controllers/base/PrescriptionController.php b/admin/controllers/base/PrescriptionController.php new file mode 100644 index 0000000..13a2d4e --- /dev/null +++ b/admin/controllers/base/PrescriptionController.php @@ -0,0 +1,234 @@ +request->get(); + $admin=\Yii::$app->user->identity; + $start_time=strtotime($get['start_time'].' '.'00:00:00'); + $end_time=strtotime($get['end_time'].' '.'23:59:59'); + + if ($admin->role==UserRoleEnum::STORE_ADMIN){//门店 + $query = Prescription::find()->where([ + 'store_id' => $admin->store_id, + 'is_deleted' => 0, + ])->orderBy(['id'=>SORT_DESC]); + }else{ + $query = Prescription::find()->where([ + 'is_deleted' => 0 + ])->orderBy(['id'=>SORT_DESC]); + } + + $name = $get['name']; + $doctor = $get['doctor']; + + if (!empty($get['prescription_no'])) {//处方编号 + $query->andWhere(['prescription_no' => $get['prescription_no']]); + } + if (!empty($name)) {//患者 + $query->joinWith(['userPatient' => function ($u) use ($name) { + $u->where([ + 'like', 'name', $name + ]); + }]); + } + if (!empty($doctor)) {//开方医生 + $query->joinWith(['doctorInfo' => function ($d) use ($doctor) { + $d->where([ + 'like', 'name', $doctor + ]); + }]); + } + if (!empty($get['clinical_diagnose'])) {//临床诊断 + $query->andWhere(['like', 'yii_prescription.clinical_diagnose', $get['clinical_diagnose']]); + } + if (!empty($get['status'])) {//处方状态 + $query->andWhere(['yii_prescription.status' => $get['status']]); + } + if (!empty($get['is_dispense'])) {//是否配药 + $query->andWhere(['yii_prescription.is_dispense' => $get['is_dispense']]); + } + if (!empty($get['start_time']) && !empty($get['end_time'])){ + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + $query->andWhere(['between','yii_prescription.created_at',$start_time,$end_time]); + } + + $this->field = [ + Prescription::class => [ + 'id', 'prescription_no','online_prescription_no','valid_hours','is_online', + 'content' => function ($p) { + $repice = Json::decode($p->content, true)['repice']; + + return $repice; + }, + 'name' => 'userPatient.name', + 'sex' => 'userPatient.sex', + 'patient_age' => 'userPatient.age', + 'dept' => 'doctorInfo.depart.name', + 'patient_mobile' => 'userPatient.mobile', + 'clinical_diagnose', 'doctor_order', 'prescription_type', 'category', 'doctor_sign', + 'doctor' => 'doctorInfo.name', + 'status', 'pharmacist' => 'pharmacistInfo.name', 'pharmacist_view_time'=>function($m){ + return date('Y-m-d H:i:s',$m->pharmacist_view_time); + }, + 'is_pay', 'pay_type', 'pay_time', 'type','register_id','total_pay_price','cancel_status','cancel_time','cancel_remark','refund_status','refund_time','auto_expire_time', + 'is_get' => function ($model) { + return ProductOrder::find()->select('is_pay')->where([ + 'p_id' => $model->id + ])->column(); + }, + 'order_info' => function ($q) { + return ProductOrder::find()->where([ + 'p_id' => $q->id + ])->one(); + }, 'created_at' => function ($m) { + return date('Y-m-d H:i:s', $m->created_at); + }, + ] + ]; + return $this->create($query, $get); + } + + + /** + * @doc-name 打印pdf + */ + public function actionPdf() + { + + $prescription = \Yii::$app->request->post('prescription'); + $mpdf = new \Mpdf\Mpdf([ + 'mode' => 'UTF-8', 'format' => 'A4', 'default_font_size' => 15, 'default_font' => '', 'margin_left' => 20, 'margin_right' => 20]); + $mpdf->autoScriptToLang = true;//支持中文设置 + $mpdf->autoLangToFont = true;//支持中文设置 + $mpdf->WriteHTML($prescription); + $path = 'FILE_UPLOAD' . date('YmdHis') . '_' . mt_rand(1, 5) . '.pdf'; + $mpdf->Output();//直接在页面显示pdf页面内容 + //$mpdf->Output($path,'f');//保存pdf文件到指定目录 + } + + /** + * @doc-name 处方详情 + * @doc-param int id 处方id + */ + public function actionPrescriptionDetail() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['id','required'] + ]); + $Prescription= Prescription::find()->alias('p')->where([ + 'p.id'=>$get['id'], + 'p.is_deleted' => 0 + ])->with(['register','store'])->joinWith(['userPatient'])->asArray()->one(); + if (!$Prescription) throw new Exception('处方不存在'); + + if ( $Prescription['prescription_type']== 1 || $Prescription['prescription_type'] == 3) {//中药 配方颗粒 + + $content=$Prescription['content']; + $recipe = json_decode($content, true)['repice']; + + $data['content']= json_decode($recipe[0]['content']); + $data['deployment']=$recipe[0]['deployment']; + $data['dosage']=$recipe[0]['dosage']; + $data['consumption']=$recipe[0]['consumption']; + $data['directions']=$recipe[0]['directions']; + $data['usage']=$recipe[0]['usage']; + $data['fufa_id']=$recipe[0]['fufa_id']; + $data['volume']=$recipe[0]['volume']; + $data['is_deepfry']=$recipe[0]['is_deepfry']; + $data['cm_id']=$recipe[0]['cm_id']; + $data['total_price']=$recipe[0]['total_price']; + $data['remark']=$recipe[0]['remark']; + + } else {//西药 + $repice = json_decode($Prescription['content'], true)['repice']; + + $data = []; + foreach ($repice as $v) { + $item = [ + 'id' => $v['id'], + 'content' => json_decode($v['content']), + 'drug_name' => json_decode($v['content'])->drug_name, + 'source' => json_decode($v['content'])->source, + 'function' => json_decode($v['content'])->function, + 'usage' => json_decode($v['content'])->usage, + 'specification' => json_decode($v['content'])->specification, + 'instruction' => json_decode($v['content'])->instruction, + 'image' => json_decode($v['content'])->image, + 'number' => $v['number'], + 'available_days' => $v['available_days'], + 'total_price' => $v['total_price'], + 'created_at' => $v['created_at'], + 'type_id' => json_decode($v['content'])->type_id, + 'time_id' => json_decode($v['content'])->time_id, + 'frequency_id' => json_decode($v['content'])->frequency_id, + 'unit_id' => json_decode($v['content'])->unit_id, + 'usetime' => $v['usetime']['name'], + 'frequency' => $v['frequency']['name'], + 'grain_number' => $v['grain_number'], + 'westUnit' => $v['westUnit']['name'], + 'types' => $v['usetype']['name'], //药的使用方式 + ]; + + $data[] = $item; + } + } + + $ProductOrder=ProductOrder::find()->where([ + 'p_id'=>$get['id'] + ])->one(); + return [ + 'content'=>$data, + 'prescription'=>$Prescription, + 'ProductOrder'=>$ProductOrder + ]; + } + + /** + * @doc-name 导出处方 + */ + public function actionExportPrescription() + { +// \Yii::$app->response->format = Response::FORMAT_RAW; + $params=\Yii::$app->request->get(); + $parameter['header']=['订单号','医生','患者','订单状态','价格','是否取药','时间']; + $parameter['data']=Prescription::inventory($params,\Yii::$app->user->identity->store_id); +// $Name='处方记录'; +// $class=new Prescription(); + + ExportService::ExportByCors($parameter); + + } +} \ No newline at end of file diff --git a/admin/controllers/base/RegionController.php b/admin/controllers/base/RegionController.php new file mode 100644 index 0000000..5aa97fe --- /dev/null +++ b/admin/controllers/base/RegionController.php @@ -0,0 +1,60 @@ +request->get(); + + $query = Region::find()->where(['level'=>1]); + $this->field = [ + Region::class => [ + 'id', 'name', 'pid', 'level', 'express_fee' + ] + ]; + + return $this->create($query, $get); + } + + /** + * @doc-name 编辑快递费 + * @doc-param int id id + * @doc-param float express_fee 快递费 + */ + public function actionEditFee() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['id', 'express_fee'], 'required'], + ]); + + $Region = Region::find()->where(['id' => $post['id']])->one(); + if (!$Region) throw new Exception('地区不存在'); + $Region->express_fee = $post['express_fee']; + if (!$Region->saveOrFail()) { + throw new Exception('修改失败'); + }; + return ['修改成功']; + } + /** + * @doc-name 地区列表 + */ + public function actionAllRegionList() + { + $Region = Region::find()->asArray()->all(); + return ArrayHelper::list_to_tree($Region, 'id', 'pid', 'children'); + + } +} \ No newline at end of file diff --git a/admin/controllers/base/RegisterController.php b/admin/controllers/base/RegisterController.php new file mode 100644 index 0000000..b833860 --- /dev/null +++ b/admin/controllers/base/RegisterController.php @@ -0,0 +1,182 @@ +request->get(); + + $admin = \Yii::$app->user->identity; + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + if ($admin->role == UserRoleEnum::STORE_ADMIN) {//门店 + $query = Register::find()->alias('r')->where([ + 'r.store_id' => $admin->store_id, + 'r.is_delete' => 0, + ])->orderBy(['r.id' => SORT_DESC]); + } else { + $query = Register::find()->alias('r')->where([ + 'r.is_delete' => 0 + ])->orderBy(['r.id' => SORT_DESC]); + } + + $patient = $get['patient_name']; + $mobile = $get['mobile']; + $doctor = $get['doctor_name']; + $query->joinWith(['patient' => function ($p) use ($patient, $mobile) { + $p->alias('p'); + if (!empty($patient)) {//患者 + $p->andWhere(['like', 'p.name', $patient]); + } + + if (!empty($mobile)) {//手机号 + $p->andWhere(['p.mobile' => $mobile]); + } + }]); + $query->joinWith(['doctor' => function ($d) use ($doctor) { + $d->alias('d'); + if (!empty($doctor)) {//医生 + $d->andWhere(['like', 'd.name', $doctor]); + } + }]); + if (!empty($get['order_no'])) {//订单号 + $query->andWhere(['like', 'order_no', $get['order_no']]); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time == $end_time) {//筛选当天 + $time = FuncHelper::getDayBE($get['start_time']); + + $end_time = $time[1]; + } + + $query->andWhere(['between', 'r.created_at', $start_time, $end_time]); + } + + $this->field = [ + Register::class => [ + 'id', 'doctor' => 'doctor.name', 'user_patient' => 'patient.name', 'patient_mobile' => 'patient.mobile', 'user_id', 'order_no', 'depart' => 'depart.name', 'order_number', 'price', 'is_pay', 'status', 'refuse_reason', 'pay_type', + 'pay_time' => function ($p) { + if (!empty($p->pay_time)) { + return date('Y-m-d H:i:s', $p->pay_time); + } else { + return '无'; + } + }, + 'is_cancel', 'cancel_status', 'cancel_time', 'cancel_remark', 'refund_status', 'refund_time', 'created_at', + 'patient_age' => 'patient.age' + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 挂号设置 + * @doc-param int su_id 医生ID + * @doc-param int status 1开启0不开启 + * @doc-param float price 价格 / + */ + public function actionRegisterSet() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + [['su_id', 'status'], 'required'], + ]); + + $ServiceUser = ServiceUser::find()->where(['id' => $get['su_id'], 'is_delete' => 0])->one(); + if (!$ServiceUser) throw new Exception('医生不存在'); + $DoctorService = DoctorService::findOne(['su_id' => $get['su_id']]); + if (!$DoctorService) { + throw new Exception('医生基本信息不存在'); + } + + if ($get['status'] == 1) { + $DoctorService->register_status = 1; + $DoctorService->register_price = $get['price'] ?? 0; + $DoctorService->saveOrFail(); + return ['已开启挂号服务']; + } else { + $DoctorService->register_status = 0; + $DoctorService->register_price = 0; + $DoctorService->saveOrFail(); + return ['已关闭挂号服务']; + } + + + } + + /** + * @doc-name 挂号费汇总 + */ + public function actionRegisterStatistic() + { + $get = \Yii::$app->request->get(); + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + $user = \Yii::$app->user->identity; + + $register_query = Register::find()->alias('re'); + + $month_start = strtotime(date('Y-m-01 00:00:00')); + $month_end = strtotime(date('Y-m-t 23:59:59')); + + + if (!empty($start_time) && !empty($end_time)) { + $register_data = ['between', 're.created_at', $start_time, $end_time]; + } else { + $register_data = ['between', 're.created_at', $month_start, $month_end]; + } + + if ($user->role == UserRoleEnum::STORE_ADMIN) { + + $register_query->where(['re.store_id' => $user->store_id]); + } + + //挂号 + $register_price = $register_query + ->andWhere([ + 'and', + ['=', 'is_pay', 1], + ['<>', 'is_cancel', 1], + ['<>', 're.refund_status', 1], + ['=','is_delete' , 0] + ]) + ->andWhere([ + 'and', + ['<>', 're.status', 0], + ['<>', 're.status', 4], + ['<>', 're.status', 7], + ]) + ->andWhere($register_data ?? '')->sum('price'); + + return [ + 'register_price' => $register_price ?? 0, + ]; + } +} \ No newline at end of file diff --git a/admin/controllers/base/SetController.php b/admin/controllers/base/SetController.php new file mode 100644 index 0000000..a16d8a5 --- /dev/null +++ b/admin/controllers/base/SetController.php @@ -0,0 +1,141 @@ +request->get(); + $query=BaseConfig::find()->where([ + 'status'=>0 + ]); + + $this->field=[ + BaseConfig::class=>[ + 'id','type','desc','content','change_at'=>function($m){ + return date('Y-m-d H:i:s',$m->change_at); + }, + 'status','end', + 'created_at'=>function($model){ + return date('Y-m-d H:i:s',$model->created_at); + } + ] + ]; + return $this->create($query,$get); + } + + /** + * @doc-name 删除协议 + * @doc-param int id 协议ID + */ + public function actionAgreeDel() + { + $get= \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['id','required'] + ]); + $AgreeForm=new AgreeForm(); + $AgreeForm->attributes=$get; + return $AgreeForm->del(); + } + + + /** + * @doc-name 编译协议及新增协议 + * @doc-desc 传id即为编辑 + * @doc-param int id 协议ID / optional + * @doc-param string type 类型1服务协议2隐私政策3其他 + * @doc-param string desc 描述 / optional + * @doc-param string content 内容 + */ + public function actionAgreeSave() + { + $post = \Yii::$app->request->post(); + $AgreeForm=new AgreeForm(); + $AgreeForm->attributes=$post; + return $AgreeForm->save(); + } + + /** + * @doc-name 西药包邮 + * @doc-desc 传id即为编辑 + * @doc-param string name name + * @doc-param string rule 规则 + * @doc-param string value 值 + */ + public function actionFreeShip() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['name','required'], + ['rule','required'], + ['value','required'], + ]); + $SystemConfig=SystemConfig::find()->where([ + 'config_type'=>2, + 'type'=>2 + ])->one(); + if (!$SystemConfig){ + throw new Exception('西药包邮配置不存在'); + } + $SystemConfig->name=$post['name']; + $SystemConfig->rule=$post['rule']; + $SystemConfig->value=$post['value']; + $SystemConfig->saveOrFail(); + + return ['设置成功']; + } + + /** + * 小程序版本 + */ + public function actionXcxVersion(){ + + $SystemConfig=SystemConfig::find()->where([ + 'config_type'=>3, + ])->one(); + if (!$SystemConfig){ + throw new Exception('小程序版本配置不存在'); + } + + return $SystemConfig; + } + + /** + * 小程序版本设置 + */ + public function actionXcxVersionSet(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['value','required'], + ]); + $SystemConfig=SystemConfig::find()->where([ + 'config_type'=>3, + ])->one(); + if (!$SystemConfig){ + throw new Exception('小程序版本配置不存在'); + } + + $SystemConfig->value=$post['value']; + $SystemConfig->saveOrFail(); + + return ['设置成功']; + } +} \ No newline at end of file diff --git a/admin/controllers/base/StatementAccountController.php b/admin/controllers/base/StatementAccountController.php new file mode 100644 index 0000000..de33831 --- /dev/null +++ b/admin/controllers/base/StatementAccountController.php @@ -0,0 +1,1048 @@ +request->get(); + $this->requestValidate($get, [ + ['type', 'required'] + ]); + //诊所 + if ($get['type'] == 1) { + if (empty($get['store_id'])) { + throw new Exception('诊所ID不能为空'); + } + $query = Store::find()->alias('s')->where(['s.id' => $get['store_id']]); + + + $this->field = [ + Store::class => [ + 'id', 'name', 'shouzimu', 'position', 'pic', 'contact', 'mobile', 'offical_seal', 'see_rate', + 'sale_number' => function ($s) { + return $this->actionStoreAllNumber($s->id); + }, + 'sale_price' => function ($s) { + return $this->actionStoreSalePrice($s->id); + }, + 'give_price' => function ($s) { + return $this->actionStoreGivePrice($s->id); + }, + ] + ]; + } else {//药品 + $query = Ledger::find()->alias('l')->where(['l.status' => 1]); + $this->field = [ + Ledger::class => [ + 'id', 'order_id', 'user_id', 'user_type', 'su_id', 'drugstore_id', 'drug_id', 'money', 'status', + 'drug_number' => 'drug.drug_number', + 'drug_name' => 'drug.drug_name', + 'store_number' => 'productOrder.store.id', + 'store' => 'productOrder.store.name', + 'sale_number' => function ($s) { + return $this->actionEverySaleNumber($s->order_id, $s->drug_id); + }, + 'sale_price', + 'give_price' + + ] + ]; + } + + return $this->create($query, $get); + } + + /** + * @doc-name 统计门店所有的药的销量 + */ + public function actionStoreAllNumber($store_id = null) + { + $C_Drug = DrugStoreDrug::find()->where(['type' => [1, 3]])->column();//草药 + $C_sale = DrugStoreRelations::find()->where(['in', 'drug_id', $C_Drug])->andWhere(['store_id' => $store_id])->sum('sale_number'); + + $CH_Drug = DrugStoreDrug::find()->where(['type' => [2, 4]])->column();//成药 + $CH_sale = DrugStoreRelations::find()->where(['in', 'drug_id', $CH_Drug])->andWhere(['store_id' => $store_id])->sum('sale_number'); + + + return [ + 'c_sale' => $C_sale, + 'CH_sale' => $CH_sale, + ]; + } + + /** + * @doc-name 统计每个药的销量 + */ + public function actionCategorySaleNumber($order_id = null, $drug_id = null) + { + $order_id = 2; + $drug_id = 1; + + $ProductOrder = ProductOrder::find()->where(['id' => $order_id])->one(); + $DrugStoreRelations = DrugStoreRelations::find()->where(['store_id' => $ProductOrder->store_id, 'drug_id' => $drug_id])->one(); + return $DrugStoreRelations->sale_number; + } + + /** + * @doc-name 统计每个药的销量 + */ + public function actionEverySaleNumber($order_id = null, $drug_id = null,$start_time='',$end_time='') + { + $ProductOrder = ProductOrder::find()->where(['id' => $order_id])->one(); + $DrugStoreRelations = DrugStoreRelations::find()->where(['store_id' => $ProductOrder->store_id, 'drug_id' => $drug_id])->one(); + return $DrugStoreRelations->sale_number; + } + + /** + * @doc-name 对账单 + * @doc-param int type 1诊所2药品 + * @doc-param int drug_type 1草药2成药 / optional + * @doc-param int store_id 诊所ID / optional + * @doc-param int store_name 诊所name / optional + * @doc-param int drug_name 药品 / optional + * @doc-param string start_time 时间 / optional + * @doc-param string end_time 时间 / optional + */ + public function actionDuiZhangDan() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['type', 'required'] + ]); + $user = \Yii::$app->user->identity; + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + //诊所 + if ($get['type'] == 1) { + $query = Store::find()->alias('s'); + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query->andWhere(['s.id' => $user->store_id]); + } + + $store_name = $get['store_name']; + if (!empty($store_name)) { + $query->where(['like', 's.name', $store_name]); + } + + if (!empty($start_time) && !empty($end_time)) { + + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + //按照下单时按筛选 + $query->with(['reconciliation'=>function($r)use($start_time,$end_time){ + $r->alias('re'); + $r->andWhere(['between', 're.xd_time',$start_time,$end_time]); + }]); + + //挂号搜索 + $register_data=['between', 'r.xd_time',$start_time, $end_time]; + } + + $this->field = [ + Store::class => [ + 'id', 'name', 'shouzimu', 'position', 'pic', 'contact', 'mobile', 'offical_seal', 'see_rate', + 'sale_number' => function ($s)use($start_time,$end_time) { + return $this->actionSaleNum($s->id,$start_time,$end_time); + }, + 'trans_fee'=>function($k)use($start_time,$end_time){ + return $this->actionStoreTransFee($k->id,1,$start_time,$end_time); + }, + 'work_fee'=>function($m)use($start_time,$end_time){ + return $this->actionStoreTransFee($m->id,2,$start_time,$end_time); + }, + 'treatement_fee'=>function($m)use($start_time,$end_time){ + return $this->actionStoreTransFee($m->id,3,$start_time,$end_time); + }, + 'register_price'=>function($m)use($register_data){ + $price= Ledger::find()->alias('r')->where(['user_id'=>$m->id,'status'=>1,'user_type'=>1,'order_type'=>2])->andWhere($register_data??'')->sum('money'); +// return $this->actionRegister($m->id,$register_data); + return $price??0; + } + ] + ]; + + } else {//药品 + $query = Reconciliation::find()->alias('r')->where(['r.status' => 1])->orderBy(['id' => SORT_DESC]); + + $store_name = $get['store_name']; + $drug_name = $get['drug_name']; + + $query->joinWith(['store' => function ($s) use ($store_name) { + $s->alias('s'); + if (!empty($store_name)) { + $s->andWhere([ + 'or', + ['like', 's.name', $store_name], + ['like', 's.shouzimu', $store_name], + ]); + } + }]); + + $query->joinWith(['drug' => function ($d) use ($drug_name) { + $d->alias('d'); + if (!empty($drug_name)) { + $d->andWhere([ + 'or', + ['like', 'd.drug_name', $drug_name], + ['like', 'd.pinyin_simple', $drug_name], + ]); + } + }]); + //门店搜索 + if (!empty($get['store_id'])) { + $query->andWhere(['r.store_id' => $get['store_id']]); + } + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query->andWhere(['r.store_id' => $user->store_id]); + } + if (!empty($get['drug_type'])) { + if ($get['drug_type'] == 1) { + $query->andWhere(['r.drug_type' => [1, 3]]); + } else { + $query->andWhere(['r.drug_type' => [2, 4]]); + } + } + + if (!empty($start_time) && !empty($end_time)) { + + if ($start_time==$end_time){//筛选当天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + $query->andWhere(['between', 'r.xd_time',$start_time, $end_time]); + } + + $query->groupBy('drug_id'); + + $this->field = [ + Reconciliation::class => [ + 'id', 'order_id', 'store_id', 'pay_time' => function ($m) { + return date('Y-m-d H:i:s', $m->pay_time); + }, + 'drug_id', 'drug_type', 'total_buy_price', 'status', + 'drug_number' => 'drug.drug_number', + 'drug_name' => 'drug.drug_name', + 'store_number' => 'productOrder.store.id', + 'store' => 'store.name', + 'number' => function ($model) use ($start_time, $end_time) { + return $this->calculateSum($model, 'number', $start_time, $end_time); + }, + 'total_buy_price' => function ($model) use ($start_time, $end_time) { + return $this->calculateSum($model, 'total_buy_price', $start_time, $end_time); + }, + 'total_price' => function ($model) use ($start_time, $end_time) { + return $this->calculateSum($model, 'total_price', $start_time, $end_time); + }, + 'sale_number' => function ($s)use($start_time,$end_time) { + return $this->actionEverySaleNumber($s->order_id, $s->drug_id,$start_time,$end_time); + }, + 'trans_fee'=>'productOrder.trans_expenses', + 'work_fee' => 'productOrder.process_price', + 'treatement_fee' => 'productOrder.treatement_price' + ] + ]; + } + + return $this->create($query, $get); + } + + /** + * @doc-name 销量 + */ + public function actionSaleNum($id = null,$start_time='',$end_time='') + { + + if (!empty($start_time) && !empty($end_time)) { + $get_start_time=date('Y-m-d H:i:s',$start_time); + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get_start_time); + $start_time=strtotime($get_start_time); + $end_time=$time[1]; + } + + $data=['between', 'r.xd_time', $start_time,$end_time]; + } + + $cao_drug_num = Reconciliation::find()->alias('r')->where(['r.status' => 1, 'store_id' => $id, 'drug_type' => [1, 3]]) + ->andWhere($data??'')->groupBy('r.drug_id')->sum('number'); + $cheng_drug_num = Reconciliation::find()->alias('r')->where(['r.status' => 1, 'store_id' => $id, 'drug_type' => [2, 4]]) ->andWhere($data??'')->groupBy('r.drug_id')->sum('number'); + + $cao_give_price = Reconciliation::find()->alias('r')->where(['r.status' => 1, 'store_id' => $id, 'drug_type' => [1, 3]]) ->andWhere($data??'')->groupBy('r.drug_id')->sum('total_buy_price'); + $cheng_give_price = Reconciliation::find()->alias('r')->where(['r.status' => 1, 'store_id' => $id, 'drug_type' => [2, 4]]) ->andWhere($data??'')->groupBy('r.drug_id')->sum('total_buy_price'); + $cao_sale_price = Reconciliation::find()->alias('r')->where(['r.status' => 1, 'store_id' => $id, 'drug_type' => [1, 3]]) ->andWhere($data??'')->groupBy('r.drug_id')->sum('total_price'); + $cheng_sale_price = Reconciliation::find()->alias('r')->where(['r.status' => 1, 'store_id' => $id, 'drug_type' => [2, 4]]) ->andWhere($data??'')->groupBy('r.drug_id')->sum('total_price'); + $register_price= Ledger::find()->alias('r')->where(['user_id'=>$id,'status'=>1,'user_type'=>1,'order_type'=>2])->andWhere($data??'')->sum('money'); + $total_sale_price = bcadd($cao_sale_price,$cheng_sale_price,4); + $total_give_price = bcadd($cao_give_price,$cheng_give_price,4); + return [ + 'cao_drug_num' => $cao_drug_num ?? 0, + 'cheng_drug_num' => $cheng_drug_num ?? 0, + 'cao_give_price' => $cao_give_price ?? 0, + 'cheng_give_price' => $cheng_give_price ?? 0, + 'cao_sale_price' => $cao_sale_price ?? 0, + 'cheng_sale_price' => $cheng_sale_price ?? 0, + 'total_give_price' => $total_give_price, + 'total_sale_price' => $total_sale_price, + 'store_income' => bcadd(bcsub($total_sale_price,$total_give_price,4),$register_price,4) + ]; + } + public function actionRegister($store_id,$register_data){ + + + $register_price=Register::find()->alias('r')->where([ + 'and', + ['<>','r.status',0], + ['<>','r.status',4], + ['<>','r.status',7], + ])->andWhere(['r.store_id'=>$store_id])->andWhere($register_data??'')->sum('price'); + return $register_price??0; + } + + /** + * @doc-name 导出对账单 + */ + public function actionZhangDanExport() + { + \Yii::$app->response->format = Response::FORMAT_RAW; + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['type', 'required'] + ]); + $user = \Yii::$app->user->identity; + $get['limit'] = 10000; + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + //诊所 + if ($get['type'] == 1) { + $query = Store::find()->alias('s'); + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query->andWhere(['s.id' => $user->store_id]); + } + + $store_name = $get['store_name']; + if (!empty($store_name)) { + $query->where(['like', 's.name', $store_name]); + } + + if (!empty($start_time) && !empty($end_time)) { + + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + //按照下单时按筛选 + $query->with(['reconciliation'=>function($r)use($start_time,$end_time){ + $r->alias('re'); + $r->andWhere(['between', 're.xd_time',$start_time,$end_time]); + }]); + + //挂号搜索 + $register_data=['between', 'r.xd_time',$start_time, $end_time]; + } + + $parameter['header'] = ['诊所ID','名称', '草药销量', '草药销售金额', '草药供货金额', '成药销量', '成药销售金额','成药供货金额','总销售金额','总供货金额','快递费','加工费','总诊疗费','诊所总收入','总挂号费']; + $exportData = ArrayHelper::toArray($this->create($query, $get)->getModels(),[ + Store::class => [ + 'id', 'name', + 'sale_number' => function ($s) use($start_time,$end_time) { + return $this->actionSaleNum($s->id,$start_time,$end_time); + }, + 'trans_fee'=>function($k) use($start_time,$end_time){ + return $this->actionStoreTransFee($k->id,1,$start_time,$end_time); + }, + 'work_fee'=>function($m) use($start_time,$end_time){ + return $this->actionStoreTransFee($m->id,2,$start_time,$end_time); + }, + 'treatement_fee'=>function($m) use($start_time,$end_time){ + return $this->actionStoreTransFee($m->id,3,$start_time,$end_time); + }, + 'register_price'=>function($m) use($register_data){ + $price= Ledger::find()->alias('r')->where(['user_id'=>$m->id,'status'=>1,'user_type'=>1,'order_type'=>2])->andWhere($register_data??'')->sum('money'); + return $price??0; + } + ] + ]); + $data = []; + foreach($exportData as $key => $v){ + $data[$key]['id'] = $v['id']; + $data[$key]['name'] = $v['name']; + $data[$key]['cao_drug_num'] = $v['sale_number']['cao_drug_num']; + $data[$key]['cao_sale_price'] = $v['sale_number']['cao_sale_price']; + $data[$key]['cao_give_price'] = $v['sale_number']['cao_give_price']; + $data[$key]['cheng_drug_num'] = $v['sale_number']['cheng_drug_num']; + $data[$key]['cheng_sale_price'] = $v['sale_number']['cheng_sale_price']; + $data[$key]['cheng_give_price'] = $v['sale_number']['cheng_give_price']; + $data[$key]['total_sale_price'] = $v['sale_number']['total_sale_price']; + $data[$key]['total_give_price'] = $v['sale_number']['total_give_price']; + $data[$key]['trans_fee'] = $v['trans_fee']; + $data[$key]['work_fee'] = $v['work_fee']; + $data[$key]['treatement_fee'] = $v['treatement_fee']; + $data[$key]['store_income'] = $v['sale_number']['store_income']; + $data[$key]['register_price'] = $v['register_price']; + } + } elseif($get['type'] == 2) {//药品 + $query = Reconciliation::find()->alias('r')->where(['r.status' => 1])->orderBy(['id' => SORT_DESC]); + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query->andWhere(['store_id' => $user->store_id]); + } + + $store_name = $get['store_name']; + $drug_name = $get['drug_name']; + + $query->joinWith(['store' => function ($s) use ($store_name) { + $s->alias('s'); + if (!empty($store_name)) { + $s->andWhere([ + 'or', + ['like', 's.name', $store_name], + ['like', 's.shouzimu', $store_name], + ]); + } + }]); + + $query->joinWith(['drug' => function ($d) use ($drug_name) { + $d->alias('d'); + if (!empty($drug_name)) { + $d->andWhere([ + 'or', + ['like', 'd.drug_name', $drug_name], + ['like', 'd.pinyin_simple', $drug_name], + ]); + } + }]); + //门店搜索 + if (!empty($get['store_id'])) { + $query->andWhere(['r.store_id' => $get['store_id']]); + } + if (!empty($get['drug_type'])) { + if ($get['drug_type'] == 1) { + $query->andWhere(['r.drug_type' => [1, 3]]); + } else { + $query->andWhere(['r.drug_type' => [2, 4]]); + } + } + + if (!empty($start_time) && !empty($end_time)) { + + if ($start_time==$end_time){//筛选当天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + $query->andWhere(['between', 'r.xd_time',$start_time, $end_time]); + } + + $query->groupBy('drug_id'); + + $parameter['header'] = ['药品名称', '药品编号', '销量', '供货金额', '销售金额']; + $exportData = ArrayHelper::toArray($this->create($query, $get)->getModels(),[ + Reconciliation::class => [ + 'drug_name' => 'drug.drug_name', + 'drug_number' => 'drug.drug_number', + 'number' => function ($model) use ($start_time, $end_time) { + return $this->calculateSum($model, 'number', $start_time, $end_time); + }, + 'total_buy_price' => function ($model) use ($start_time, $end_time) { + return $this->calculateSum($model, 'total_buy_price', $start_time, $end_time); + }, + 'total_price' => function ($model) use ($start_time, $end_time) { + return $this->calculateSum($model, 'total_price', $start_time, $end_time); + }, + ] + ]); + + $data = []; + foreach($exportData as $k=>$v){ + $data[$k]['drug_name'] = $v['drug_name']; + $data[$k]['drug_number'] = $v['drug_number']; + $data[$k]['number'] = $v['number']; + $data[$k]['total_buy_price'] = $v['total_buy_price']; + $data[$k]['total_price'] = $v['total_price']; + } + }else{//医生 + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['store_id', 'required'] + ]); + $store_id = \Yii::$app->request->get(); + + $store = Store::find()->where(['id' => $get['store_id']])->one(); + if (!$store) { + throw new \yii\db\Exception('门店不存在!!'); + } + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time == $end_time) {//筛选当天 + $time = FuncHelper::getDayBE($get['start_time']); + + $end_time = $time; + } + } + + $doctor = StoreDoctor::find()->select('su_id')->where(['store_id' => $get['store_id']])->column(); + + $query = DoctorInfo::find()->where(['in', 'su_id', $doctor]); + + $parameter['header'] = ['医生ID', '医生姓名', '总挂号费', '药品销售金额', '总利润']; + $exportData = ArrayHelper::toArray($this->create($query, $get)->getModels(),[ + DoctorInfo::class => [ + 'su_id', + 'name', + 'register_price' => function ($r) use ($start_time, $end_time, $store_id) { + return $this->actionRegisterPrice($r->su_id, $store_id, $start_time, $end_time); + }, + 'drug_sale_price' => function ($r) use ($start_time, $end_time, $store_id) { + return $this->actionDrugSale($r->su_id, $store_id, $start_time, $end_time); + }, + 'drug_profit_price' => function ($r) use ($start_time, $end_time, $store_id) { + return $this->actionDrugProfit($r->su_id, $store_id, $start_time, $end_time); + }, + ] + ]); + + $data = []; + foreach($exportData as $k=>$v){ + $data[$k]['su_id'] = $v['su_id']; + $data[$k]['name'] = $v['name']; + $data[$k]['register_price'] = $v['register_price']; + $data[$k]['drug_sale_price'] = $v['drug_sale_price']; + $data[$k]['drug_profit_price'] = $v['drug_profit_price']; + } + } + $parameter['data'] = $data; + + ExportService::ExportByCors($parameter); + } + + public function actionStoreTransFee($store_id=null,$type=null,$start_time='',$end_time='') + { + + if (!empty($start_time) && !empty($end_time)) { + $get_start_time=date('Y-m-d H:i:s',$start_time); + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get_start_time); + $start_time=strtotime($get_start_time); + $end_time=$time[1]; + } + + $data=['between', 'pr.created_at', $start_time,$end_time]; + } + + if ($type==1){ + + $price= ProductOrder::find()->alias('pr')->where(['pr.store_id'=>$store_id,'pr.is_pay'=>1,'pr.is_settled'=>1])->andWhere([ + 'or', + ['<>','pr.refund_status','3'], + ['<>','pr.status','4'] + ])->andWhere($data??'')->sum('trans_expenses'); + + }elseif ($type==2){ + $price= ProductOrder::find()->alias('pr')->where(['pr.store_id'=>$store_id,'is_pay'=>1,'pr.is_settled'=>1])->andWhere([ + 'or', + ['<>','pr.refund_status','3'], + ['<>','pr.status','4'] + ])->andWhere($data??'')->sum('process_price'); + + }else{ + $price= ProductOrder::find()->alias('pr')->where(['pr.store_id'=>$store_id,'is_pay'=>1,'pr.is_settled'=>1])->andWhere([ + 'or', + ['<>','pr.refund_status','3'], + ['<>','pr.status','4'] + ])->andWhere($data??'')->sum('treatement_price'); + } + + return $price??0; + } + + /** + * @doc-name 统计--全部诊所 + * @doc-param string start_time 时间 + * @doc-param string end_time 时间 + */ + public function actionStoreStatistic() + { + $get = \Yii::$app->request->get(); + $admin=\Yii::$app->user->identity; + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + if (!empty($start_time) || !empty($end_time)){ + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get['start_time']); + $start_time=$get['start_time']; + $end_time=$time[1]; + } + $data=['between', 'p.created_at', $start_time, $end_time]; + + $datas=['between', 'r.xd_time',$start_time, $end_time]; + + $register_data=['between', 're.xd_time', $start_time, $end_time]; + } + + + if ($admin->role==UserRoleEnum::STORE_ADMIN){ + + $cao_all_num = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [1, 3]])->andWhere($datas??'')->groupBy('r.drug_id')->sum('number'); + $cheng_all_num = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [2, 4]])->andWhere($datas??'')->groupBy('r.drug_id')->sum('number'); + $cao_give_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [1, 3]])->andWhere($datas??'')->sum('total_buy_price'); + $cheng_give_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [2, 4]])->andWhere($datas??'')->sum('total_buy_price'); + $cao_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [1, 3]])->andWhere($datas??'')->sum('total_price'); + $cheng_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [2, 4]])->andWhere($datas??'')->sum('total_price'); + + $trans_expenses_price= ProductOrder::find()->alias('p')->where(['store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('trans_expenses'); + $process_price= ProductOrder::find()->alias('p')->where(['store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('process_price'); + $treatement_price= ProductOrder::find()->alias('p')->where(['store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('treatement_price'); + $decoct_price_price= ProductOrder::find()->alias('p')->where(['is_decoct'=>1,'store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'] + ])->andWhere($data??'')->sum('decoct_price'); + //挂号 +// $register_price=Register::find()->alias('re')->where([ +// 'and', +// ['<>','re.status',0], +// ['<>','re.status',4], +// ['<>','re.status',7], +// 'store_id'=>$admin->store_id +// ])->andWhere($register_data??'')->sum('price'); + $register_price=Ledger::find()->alias('re')->where(['user_id'=>$admin->store_id,'status'=>1,'user_type'=>1,'order_type'=>2])->andWhere($register_data??'')->sum('money'); + + //所有药的销售金额 + $drug_sale_price=Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id])->andWhere($datas??'')->sum('total_price'); + //所有药的进货金额 + $drug_give_price=Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id])->andWhere($datas??'')->sum('total_buy_price'); + + $store_income=bcadd($treatement_price,bcsub(bcadd($drug_sale_price,$register_price,4),$drug_give_price,4),2); + //总金额 + $all_sum=bcadd($drug_sale_price,$register_price,4); + $total_price = ProductOrder::find()->alias('p')->where(['store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('total_pay_price'); + }else{ + + $cao_all_num = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [1, 3]])->andWhere($datas??'')->groupBy('r.drug_id')->sum('number'); + $cheng_all_num = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [2, 4]])->andWhere($datas??'')->groupBy('r.drug_id')->sum('number'); + $cao_give_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [1, 3]])->andWhere($datas??'')->sum('total_buy_price'); + $cheng_give_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [2, 4]])->andWhere($datas??'')->sum('total_buy_price'); + $cao_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [1, 3]])->andWhere($datas??'')->sum('total_price'); + $cheng_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [2, 4]])->andWhere($datas??'')->sum('total_price'); + + $trans_expenses_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('trans_expenses'); + $treatement_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('treatement_price'); + $process_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('process_price'); + $decoct_price_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1,'is_decoct'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('decoct_price'); + $total_price = ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('total_pay_price'); + + //挂号 +// $register_price=Register::find()->alias('re')->where([ +// 'and', +// ['<>','re.status',0], +// ['<>','re.status',4], +// ['<>','re.status',7], +// ])->andWhere($register_data??'')->sum('price'); + $register_price=Ledger::find()->alias('re')->where(['status'=>1,'user_type'=>1,'order_type'=>2])->andWhere($register_data??'')->sum('money'); + + //所有药的销售金额 + $drug_sale_price=Reconciliation::find()->alias('r')->andWhere(['r.status' => 1])->andWhere($datas??'')->sum('total_price'); + //所有药的进货金额 + $drug_give_price=Reconciliation::find()->alias('r')->andWhere(['r.status' => 1])->andWhere($datas??'')->sum('total_buy_price'); + + $store_income=bcadd($treatement_price,bcsub(bcadd($drug_sale_price,$register_price,4),$drug_give_price,4),2); + //总金额 + $all_sum=bcadd($drug_sale_price,$register_price,4); + } + + + return [ + 'cao_all_num' => $cao_all_num ?? 0, + 'cheng_all_num' => $cheng_all_num ?? 0, + 'cao_give_price' => $cao_give_price ?? 0, + 'cheng_give_price' => $cheng_give_price ?? 0, + 'cao_sale_price' => $cao_sale_price ?? 0, + 'cheng_sale_price' => $cheng_sale_price ?? 0, + 'trans_expenses_price' => $trans_expenses_price ?? 0, + 'process_price' => $process_price ?? 0, + 'treatement_price' => $treatement_price ?? 0, + 'decoct_price_price' => $decoct_price_price ?? 0, + 'register_price' => $register_price ?? 0, + 'store_income' => $store_income ?? 0, + 'all_sum' => $all_sum ?? 0, + 'drug_give_price' => $drug_give_price ?? 0, + 'drug_sale_price' => $drug_sale_price ?? 0, + 'total_price' => $total_price ?? 0 + ]; + } + + /** + * @doc-name 统计--所有药 + * @doc-param string start_time 时间 + * @doc-param string end_time 时间 + * 平台 诊所 萧康 + */ + public function actionDrugStatistic() + { + $get = \Yii::$app->request->get(); + $admin=\Yii::$app->user->identity; + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get['start_time']); + $start_time=$get['start_time']; + $end_time=$time[1]; + } + $data=['between', 'r.xd_time', $start_time, $end_time]; + } + + if ($admin->role==UserRoleEnum::STORE_ADMIN){ + $all_sale= Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id])->andWhere($data??'')->groupBy('r.drug_id')->sum('number'); + $all_total_price= Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id])->andWhere($data??'')->groupBy('r.drug_id')->sum('total_price'); + }else{ + $all_sale= Reconciliation::find()->alias('r')->andWhere(['r.status' => 1])->andWhere($data??'')->groupBy('r.drug_id')->sum('number'); + $all_total_price= Reconciliation::find()->alias('r')->andWhere(['r.status' => 1])->andWhere($data??'')->groupBy('r.drug_id')->sum('total_price'); + } + + + return [ + 'all_sale'=>$all_sale??0, + 'all_total_price'=>$all_total_price??0, + ]; + } + + /** + * @doc-name 诊所统计 + * @doc-param string start_time 时间 + * @doc-param string end_time 时间 + */ + public function actionNewStoreStatistic() + { + + $get = \Yii::$app->request->get(); + $admin=\Yii::$app->user->identity; + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time==$end_time){//筛选某一天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time[1]; + } + + $datas=['between', 'r.xd_time',$start_time, $end_time]; + $data=['between', 'p.created_at', $start_time, $end_time]; + $register_data=['between', 're.xd_time', $start_time,$end_time]; + } + + if ($admin->role==UserRoleEnum::STORE_ADMIN){ + + $cao_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [1, 3]])->andWhere($datas??'')->sum('total_price'); + $cheng_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id, 'drug_type' => [2, 4]])->andWhere($datas??'')->sum('total_price'); + + $trans_expenses_price= ProductOrder::find()->alias('p')->where(['store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('trans_expenses'); + $process_price= ProductOrder::find()->alias('p')->where(['store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('process_price'); + $treatement_price= ProductOrder::find()->alias('p')->where(['store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('treatement_price'); + $decoct_price_price= ProductOrder::find()->alias('p')->where(['is_decoct'=>1,'store_id'=>$admin->store_id,'is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('decoct_price'); + + $register_price=Ledger::find()->alias('re')->where(['user_id'=>$admin->store_id,'status'=>1,'user_type'=>1,'order_type'=>2])->andWhere($register_data??'')->sum('money'); +// //挂号 +// $register_price=Register::find()->alias('re')->where([ +// 'and', +// ['<>','re.status',0], +// ['<>','re.status',4], +// ['<>','re.status',7], +// ])->andWhere($register_data??'')->sum('price'); + //所有药的进货金额 + $drug_give_price=Reconciliation::find()->alias('r')->andWhere(['r.status' => 1,'r.store_id'=>$admin->store_id])->andWhere($datas??'')->sum('total_buy_price'); + + $drug_price=bcadd($cao_sale_price,$cheng_sale_price,4); + + }else{ + $cao_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [1, 3]])->andWhere($datas??'')->sum('total_price'); + $cheng_sale_price = Reconciliation::find()->alias('r')->andWhere(['r.status' => 1, 'drug_type' => [2, 4]])->andWhere($datas??'')->sum('total_price'); + + $trans_expenses_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('trans_expenses'); + $process_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('process_price'); + $treatement_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('treatement_price'); + $decoct_price_price= ProductOrder::find()->alias('p')->where(['is_pay'=>1,'is_settled'=>1,'is_decoct'=>1])->andWhere([ + 'or', + ['<>','refund_status','3'], + ['<>','status','4'], + ])->andWhere($data??'')->sum('decoct_price'); + + //挂号 +// $register_price=Register::find()->alias('re')->where([ +// 'and', +// ['<>','re.status',0], +// ['<>','re.status',4], +// ['<>','re.status',7], +// ])->andWhere($register_data??'')->sum('price'); + $register_price=Ledger::find()->alias('re')->where(['status'=>1,'user_type'=>1,'order_type'=>2])->andWhere($register_data??'')->sum('money'); + $drug_price=bcadd($cao_sale_price,$cheng_sale_price,4); + //所有药的进货金额 + $drug_give_price=Reconciliation::find()->alias('r')->andWhere(['r.status' => 1])->andWhere($datas??'')->sum('total_buy_price'); + + } + $data= [ +// '0'=>[ +// 'type'=>'草药销售额', +// 'value'=>$cao_sale_price ?? "0", +// ], +// '1'=>[ +// 'type'=>'成药销售额', +// 'value'=>$cheng_sale_price ?? "0", +// ], + '1'=>[ + 'type'=>'药品销售金额', + 'value'=>$drug_price ?? "0", + ], + '2' => [ + 'type'=>'供货金额', + 'value'=>$drug_give_price ?? "0", + ], + '3'=>[ + 'type'=>'运费', + 'value'=>$trans_expenses_price ?? "0", + ], + // '4'=>[ + // 'type'=>'代煎费', + // 'value'=>$decoct_price_price ?? "0", + // ], + '5'=>[ + 'type'=>'挂号费', + 'value'=>$register_price ?? "0", + ], + '6'=>[ + 'type'=>'加工费', + 'value'=>$process_price ?? "0", + ], + '7'=>[ + 'type'=>'诊疗费', + 'value'=>$treatement_price ?? "0", + ], + + ]; + return $data; + } + + // 计算总和的方法 + protected function calculateSum($model, $field, $start_time, $end_time) { + $where = []; + if ($start_time && $end_time) { + $where = ['between', 'xd_time', $start_time, $end_time]; + } + $andWhere = ['drug_id' => $model->drug_id]; + if($model->store_id){ + $andWhere['store_id'] = $model->store_id; + } + return (new \yii\db\Query()) + ->from($model::tableName()) + ->where($andWhere) + ->andWhere($where)->groupBy('drug_id') + ->sum($field); + } + + /** + * @doc-name 药品总利润 + */ + public function actionDrugProfit($su_id = null, $store_id = null, $start_time = '', $end_time = '') + { + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + + $order_id = ProductOrder::find()->select('id')->where(['su_id' => $su_id, 'is_pay' => 1, 'store_id' => $store_id])->column(); + + //销售额 + $total_price = Reconciliation::find()->alias('r')->where([ + 'in', 'r.order_id', $order_id, + 'r.status' => 1 + ])->andWhere($data ?? '')->sum('total_price'); + + //供货金额 + $total_buy_price = Reconciliation::find()->alias('r')->where([ + 'in', 'r.order_id', $order_id, + 'r.status' => 1 + ])->andWhere($data ?? '')->sum('total_buy_price'); + + $profit = bcsub($total_price, $total_buy_price, 4); + return $profit ?? 0; + } + + /** + * @doc-name 挂号费 + * @doc-param int su_id 医生 + */ + public function actionRegisterPrice($su_id = '', $store_id = '', $start_time = '', $end_time = '') + { + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + + $price = Ledger::find()->alias('r')->where(['r.su_id' => $su_id, 'r.user_id' => $store_id, 'r.status' => 1, 'r.user_type' => 1, 'r.order_type' => 2])->andWhere($data ?? '')->sum('money'); + + + return $price ?? 0; + } + + /** + * @doc-name 药品总销售额 + */ + public function actionDrugSale($su_id = null, $store_id = null, $start_time = '', $end_time = '') + { + + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + $order_id = ProductOrder::find()->select('id')->where(['su_id' => $su_id, 'is_pay' => 1, 'store_id' => $store_id])->column(); + + $total_price = Reconciliation::find()->alias('r')->where([ + 'in', 'r.order_id', $order_id, + 'r.status' => 1 + ])->andWhere($data ?? '')->sum('total_price'); + + return $total_price ?? 0; + } +} \ No newline at end of file diff --git a/admin/controllers/base/SupplyController.php b/admin/controllers/base/SupplyController.php new file mode 100644 index 0000000..e8d20f3 --- /dev/null +++ b/admin/controllers/base/SupplyController.php @@ -0,0 +1,405 @@ +request->get(); + $admin = \Yii::$app->user->identity; + $this->requestValidate($get, [ + ['type', 'required'], + ]); + $search = $get['search']; + $sort = $get['sort']; + $limit_time = $get['limit_time']; + + if ($admin->role == UserRoleEnum::PROVINCE_DAI) {//省代 + switch ($get['type']) { + case 1: + $query = Store::find()->alias('s')->where(['s.is_delete' => 0, 's.province_id' => $admin->province_id]); + break; + case 2: + $query = Reconciliation::find()->orderBy(['id' => SORT_DESC])->alias('r')->where(['r.status' => 1])->joinWith(['store' => function ($store) use ($admin) { + $store->alias('st'); + $store->where(['st.province_id' => $admin->province_id]); + }]); + break; + default: + throw new Exception('参数错误'); + } + } elseif ($admin->role == UserRoleEnum::CITY_DAI) {//市代 + switch ($get['type']) { + case 1: + $query = Store::find()->alias('s')->where(['s.is_delete' => 0, 's.city_id' => $admin->city_id]); + break; + case 2: + $query = Reconciliation::find()->orderBy(['id' => SORT_DESC])->alias('r')->where(['r.status' => 1])->joinWith(['store' => function ($store) use ($admin) { + $store->alias('st'); + $store->where(['st.city_id' => $admin->city_id]); + }]); + break; + default: + throw new Exception('参数错误'); + } + } elseif ($admin->role == UserRoleEnum::SUPPLY) {//业务员 + switch ($get['type']) { + case 1: + $query = Store::find()->alias('s')->where(['s.code' => $admin->code, 's.is_delete' => 0]); + break; + case 2: + $query = Reconciliation::find()->orderBy(['id' => SORT_DESC])->alias('r')->where(['r.status' => 1])->joinWith(['store' => function ($store) use ($admin) { + $store->where(['uid' => $admin->uid]); + }]); + + break; + default: + throw new Exception('参数错误'); + } + } else { + throw new Exception('角色错误'); + } + + switch ($get['type']) { + case 1: + if ($limit_time == 1) { + $start_time = strtotime(date('Y-m-01 00:00:00')); + $end_time = strtotime(date('Y-m-t 23:59:59')); + $query->joinWith(['reconciliation' => function ($r) use ($start_time, $end_time) { + $r->alias('re'); + $r->where(['re.status' => 1])->andWhere([ + 'between', 're.pay_time', $start_time, $end_time]); + }]); + } + if ($limit_time == 2) { + $now = new \DateTime(); + $now->modify('first day of last month'); + $start_time = $now->format('Y-m-01 00:00:00'); + $end_time = date("Y-m-d 23:59:59", strtotime(-date('d') . 'day')); + $query->joinWith(['reconciliation' => function ($r) use ($start_time, $end_time) { + $r->alias('re'); + $r->where(['re.status' => 1])->andWhere([ + 'between', 're.pay_time', strtotime($start_time), strtotime($end_time)]); + }]); + } + + if (!empty($sort)) { + switch ($sort) { + case 1: + if (!empty($search)) $query->andWhere(['like', 's.name', $search]); + break; + case 2: + if (!empty($search)) { + $query->joinWith(['admin' => function ($a) use ($search) { + $a->andWhere(['like', 'username', $search]); + }]); + } + break; + case 3: + if (!empty($search)) { + $query->joinWith(['province' => function ($p) use ($search) { + $p->alias('p')->where(['like', 'p.name', $search]); + }]); + } + break; + case 4: + if (!empty($search)) { + $query->joinWith(['city' => function ($c) use ($search) { + $c->alias('c')->where(['like', 'c.name', $search]); + }]); + } + break; + default: + throw new Exception('参数错误'); + } + } + + $this->field = [ + Store::class => [ + 'id', 'name', 'position', 'mobile', 'offical_seal', 'code', 'uid', + 'supply' => 'admin.username', + 'province' => 'province.name', + 'city' => 'city.name', + 'city_id', + 'province_id', + 'sale_price' => function ($s) { + return $this->actionSalePrice($s->id); + } + ] + ]; + return $this->create($query, $get); + case 2: + if ($limit_time == 1) { + $start_time = strtotime(date('Y-m-01 00:00:00')); + $end_time = strtotime(date('Y-m-t 23:59:59')); + $query->andWhere(['between', 'r.pay_time', $start_time, $end_time]); + } + if ($limit_time == 2) { + $now = new \DateTime(); + $now->modify('first day of last month'); + $start_time = $now->format('Y-m-01 00:00:00'); + $end_time = date("Y-m-d 23:59:59", strtotime(-date('d') . 'day')); + $query->andWhere(['between', 'r.pay_time', strtotime($start_time), strtotime($end_time)]); + } + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $query->andWhere(['between', 'r.pay_time', strtotime($get['start_time']), strtotime($get['end_time'])]); + } + + if (!empty($sort)) { + switch ($sort) { + case 1: + $query->joinWith(['store' => function ($s) use ($search) { + $s->alias('s'); + $s->andWhere([ + 'or', + ['like', 's.name', $search], + ['like', 's.shouzimu', $search], + ]); + }]); + break; + case 2: + if (!empty($search)) { + $query->joinWith(['store' => function ($s) use ($search) { + $s->joinWith(['admin' => function ($a) use ($search) { + $a->andWhere(['like', 'username', $search]); + }]); + }]); + } + break; + case 3: + if (!empty($search)) { + $query->joinWith(['store' => function ($s) use ($search) { + $s->joinWith(['province' => function ($ss) use ($search) { + $ss->alias('pro'); + $ss->andWhere(['like', 'pro.name', $search]); + }]); + }]); + } + break; + case 4: + if (!empty($search)) { + $query->joinWith(['store' => function ($s) use ($search) { + $s->joinWith(['city' => function ($ct) use ($search) { + $ct->alias('city'); + $ct->andWhere(['like', 'city.name', $search]); + }]); + }]); + } + break; + default: + throw new Exception('参数错误'); + } + } + +// +// $query->joinWith(['drug' => function ($d) use ($search) { +// $d->alias('d'); +// $d->andWhere([ +// 'or', +// ['like', 'd.drug_name', $search], +// ['like', 'd.pinyin_simple', $search], +// ]); +// }]); + + if (!empty($search)) { + if ($search == 1) { + $query->andWhere(['r.drug_type' => [1, 3]]); + } else { + $query->andWhere(['r.drug_type' => [2, 4]]); + } + } + + $this->field = [ + Reconciliation::class => [ + 'id', 'order_id', 'store_id', 'pay_time' => function ($m) { + return date('Y-m-d H:i:s', $m->pay_time); + }, + 'drug_id', 'drug_type', 'number', 'total_buy_price', 'total_price', 'status', + 'drug_number' => 'drug.drug_number', + 'drug_name' => 'drug.drug_name', + 'store_number' => 'productOrder.store.id', + 'store' => 'store.name', + 'supply' => 'store.admin.username', + 'province' => 'store.province.name', + 'city' => 'store.city.name', + 'province_id' => 'store.province_id', + 'city_id' => 'store.city_id', + ] + ]; + return $this->create($query, $get); + default: + throw new Exception('参数错误'); + } + } + + public function actionSalePrice($store) + { + $Reconciliation = Reconciliation::find()->where(['store_id' => $store, 'status' => 1])->sum('total_price'); + return $Reconciliation ?? 0; + } + + /** + * @doc-name 按照诊所统计 + * @doc-param string start_time 起始时间 + * @doc-param string end_time 终止时间 + * @doc-param string limit_time 1当月2上月3累计 / optional + */ + public function actionStoreStatics() + { + $admin = \Yii::$app->user->identity; + $get = \Yii::$app->request->get(); + $limit_time = $get['limit_time']; + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $data = ['between', 'pay_time', strtotime($get['start_time']), strtotime($get['end_time'])]; + } + if ($limit_time == 1) { + $start_time = strtotime(date('Y-m-01 00:00:00')); + $end_time = strtotime(date('Y-m-t 23:59:59')); + $data = ['between', 'pay_time', $start_time, $end_time]; + } + if ($limit_time == 2) { + $now = new \DateTime(); + $now->modify('first day of last month'); + $start_time = $now->format('Y-m-01 00:00:00'); + $end_time = date("Y-m-d 23:59:59", strtotime(-date('d') . 'day')); + $data = ['between', 'pay_time', strtotime($start_time), strtotime($end_time)]; + } + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $data = ['between', 'pay_time', strtotime($get['start_time']), strtotime($get['end_time'])]; + } + + if ($admin->role == UserRoleEnum::PROVINCE_DAI) {//省代 + $store_id = Store::find()->select(['id'])->where(['province_id' => $admin->province_id])->column(); + + $total_price = Reconciliation::find()->where(['in', 'store_id', $store_id])->andWhere(['status' => 1])->andWhere($data ?? '')->sum('total_price'); + + $total_buy_price= Reconciliation::find()->where(['in', 'store_id', $store_id])->andWhere(['status' => 1])->andWhere($data ?? '')->sum('total_buy_price'); + + $store = Store::find()->where(['province_id' => $admin->province_id])->count(); + + } elseif ($admin->role == UserRoleEnum::CITY_DAI) {//市代 + $store_id = Store::find()->select(['id'])->where(['city_id' => $admin->city_id])->column(); + + $total_price = Reconciliation::find()->where(['in', 'store_id', $store_id])->andWhere(['status' => 1])->andWhere($data ?? '')->sum('total_price'); + + $total_buy_price= Reconciliation::find()->where(['in', 'store_id', $store_id])->andWhere(['status' => 1])->andWhere($data ?? '')->sum('total_buy_price'); + + $store = Store::find()->where(['city_id' => $admin->city_id])->count(); + } elseif ($admin->role == UserRoleEnum::SUPPLY) {//业务员 + $store_id = Store::find()->select(['id'])->where(['code' => $admin->code])->column(); + + $total_price = Reconciliation::find()->where(['in', 'store_id', $store_id])->andWhere(['status' => 1])->andWhere($data ?? '')->sum('total_price'); + + $total_buy_price= Reconciliation::find()->where(['in', 'store_id', $store_id])->andWhere(['status' => 1])->andWhere($data ?? '')->sum('total_buy_price'); + $store = Store::find()->where(['code' => $admin->code])->count(); + } else { + throw new Exception('角色错误'); + } + + return [ + 'store_num' => $store ?? 0, + 'total_price' => $total_price ?? 0, + 'total_buy_price' => $total_buy_price ?? 0, + ]; + } + + /** + * @doc-name 按照产品统计 + * @doc-param string start_time 起始时间 + * @doc-param string end_time 终止时间 + * @doc-param string limit_time 1当月2上月3累计 / optional + */ + public function actionProductStatics() + { + $get = \Yii::$app->request->get(); + $admin = \Yii::$app->user->identity; + $limit_time = $get['limit_time']; + if ($limit_time == 1) { + $start_time = strtotime(date('Y-m-01 00:00:00')); + $end_time = strtotime(date('Y-m-t 23:59:59')); + $data = ['between', 'pay_time', $start_time, $end_time]; + } + + if ($limit_time == 2) { + $now = new \DateTime(); + $now->modify('first day of last month'); + $start_time = $now->format('Y-m-01 00:00:00'); + $end_time = date("Y-m-d 23:59:59", strtotime(-date('d') . 'day')); + $data = ['between', 'pay_time', strtotime($start_time), strtotime($end_time)]; + } + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $data = ['between', 'pay_time', strtotime($get['start_time']), strtotime($get['end_time'])]; + } + + if ($admin->role == UserRoleEnum::PROVINCE_DAI) {//省代 + $store_id = Store::find()->select(['id'])->where(['province_id' => $admin->province_id])->column(); + $all_sale = Reconciliation::find()->alias('r')->andWhere([ + 'and', + ['r.status' => 1], + ['in', 'r.store_id', $store_id] + ])->andWhere($data ?? '')->sum('number'); + $all_total_price = Reconciliation::find()->alias('r')->andWhere([ + 'and', + ['r.status' => 1], + ['in', 'r.store_id', $store_id] + ])->andWhere($data ?? '')->sum('total_price'); + } elseif ($admin->role == UserRoleEnum::CITY_DAI) {//市代 + + $store_id = Store::find()->select(['id'])->where(['city_id' => $admin->city_id])->column(); + $all_sale = Reconciliation::find()->alias('r')->andWhere([ + 'and', + ['r.status' => 1], + ['in', 'r.store_id', $store_id] + ])->andWhere($data ?? '')->sum('number'); + $all_total_price = Reconciliation::find()->alias('r')->andWhere([ + 'and', + ['r.status' => 1], + ['in', 'r.store_id', $store_id] + ])->andWhere($data ?? '')->sum('total_price'); + } elseif ($admin->role == UserRoleEnum::SUPPLY) {//业务员 + $store_id = Store::find()->select(['id'])->where(['code' => $admin->code])->column(); + + $all_sale = Reconciliation::find()->alias('r')->andWhere([ + 'and', + ['r.status' => 1], + ['in', 'r.store_id', $store_id] + ])->andWhere($data ?? '')->sum('number'); + $all_total_price = Reconciliation::find()->alias('r')->andWhere([ + 'and', + ['r.status' => 1], + ['in', 'r.store_id', $store_id] + ])->andWhere($data ?? '')->sum('total_price'); + } else { + throw new Exception('角色错误'); + } + + + return [ + 'all_sale' => $all_sale ?? 0, + 'all_total_price' => $all_total_price ?? 0, + ]; + } +} \ No newline at end of file diff --git a/admin/controllers/base/SyncController.php b/admin/controllers/base/SyncController.php new file mode 100644 index 0000000..be53044 --- /dev/null +++ b/admin/controllers/base/SyncController.php @@ -0,0 +1,226 @@ +user->identity; + if ($admin->role != UserRoleEnum::SUPER_ADMIN) { + throw new Exception('非超管,您不能同步药品'); + } + $DrugStoreDrug_chinese = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 1])->asArray()->all(); + + $DrugStoreDrug_west = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 2])->asArray()->all(); + + $DrugStoreDrug_grain = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 3])->asArray()->all(); + $DrugStoreDrug_zongcheng = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 4])->asArray()->all(); + $store = Store::find()->select(['id', 'z_buy_percent', 'z_sale_percent', 'g_bug_percent', 'g_sale_percent'])->where(['is_delete' => 0])->all(); + + $t = \Yii::$app->db->beginTransaction(); + try { + foreach ($store as $value) {//中药 + foreach ($DrugStoreDrug_chinese as $val) { + + $Drug = DrugStoreRelations::find()->where([ + 'store_id' => $value['id'], + 'drug_id' => $val['drug_id'] + ])->one(); + if (!$Drug) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $value['id']; + $DrugStoreRelations->drug_id = $val['drug_id']; + $DrugStoreRelations->price = bcdiv(bcmul($val['price'], $value['z_sale_percent']??100, 4), 100, 4); + $DrugStoreRelations->buy_price = bcdiv(bcmul($val['market_price'], $value['z_buy_percent']??100, 4), 100, 4); + $DrugStoreRelations->status = $val['status']; + $DrugStoreRelations->saveOrFail(); + } + } + } + + foreach ($store as $value) {//西药 + foreach ($DrugStoreDrug_west as $v) { + $DrugStore = DrugStoreRelations::find()->where([ + 'store_id' => $value['id'], + 'drug_id' => $v['drug_id'] + ])->one(); + if (!$DrugStore) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $value['id']; + $DrugStoreRelations->drug_id = $v['drug_id']; + $DrugStoreRelations->price = $v['price']; + $DrugStoreRelations->buy_price = $v['market_price'] ?? $v['price']; + $DrugStoreRelations->status = $v['status']; + $DrugStoreRelations->saveOrFail(); + } + } + } + + foreach ($store as $value) {//配方 + foreach ($DrugStoreDrug_grain as $vv) { + $DrugStoreRelations = DrugStoreRelations::find()->where([ + 'store_id' => $value['id'], + 'drug_id' => $vv['drug_id'] + ])->one(); + if (!$DrugStoreRelations) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $value['id']; + $DrugStoreRelations->drug_id = $vv['drug_id']; + $DrugStoreRelations->price = bcdiv(bcmul($vv['price'], $value['g_sale_percent']??100, 4), 100, 4); + $DrugStoreRelations->buy_price = bcdiv(bcmul($vv['market_price'], $value['g_bug_percent']??100, 4), 100, 4); + $DrugStoreRelations->status = $vv['status']; + $DrugStoreRelations->saveOrFail(); + } + } + } + + foreach ($store as $value) {//中成药 + foreach ($DrugStoreDrug_zongcheng as $vv) { + $DrugStoreRelations_z = DrugStoreRelations::find()->where([ + 'store_id' => $value['id'], + 'drug_id' => $vv['drug_id'] + ])->one(); + if (!$DrugStoreRelations_z) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $value['id']; + $DrugStoreRelations->drug_id = $vv['drug_id']; + $DrugStoreRelations->price = $vv['price']; + $DrugStoreRelations->buy_price = $vv['market_price'] ?? $vv['price']; + $DrugStoreRelations->status = $vv['status']; + $DrugStoreRelations->saveOrFail(); + } + } + } + + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + $t->commit(); + return ['同步成功']; + } + + /** + * @doc-name 同步互医 + */ + public function actionSyncHospital() + { + $type=4; + $admin=\Yii::$app->user->identity; + \Yii::$app->queue->delay(0)->push(new SyncHospitalJob([ + 'admin_id'=>$admin->uid, + 'type'=>$type, + ])); + } + + /** + * @doc-name 同步单个门店 + * @doc-param int store_id 门店ID + */ + public function actionSyncUnitStore() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['store_id', 'required'] + ]); + + $DrugStoreDrug_chinese = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 1])->asArray()->all(); + $DrugStoreDrug_west = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 2])->asArray()->all(); + $DrugStoreDrug_grain = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 3])->asArray()->all(); + $DrugStoreDrug_zongcheng = DrugStoreDrug::find()->select(['drug_id', 'price', 'market_price', 'status'])->where(['type' => 4])->asArray()->all(); + $store = Store::find()->select(['id', 'z_buy_percent', 'z_sale_percent', 'g_bug_percent', 'g_sale_percent'])->where(['id' => $get['store_id'], 'is_delete' => 0])->one(); + if (!$store) throw new Exception('门店不存在'); + $t = \Yii::$app->db->beginTransaction(); + try { + //中药 + foreach ($DrugStoreDrug_chinese as $val) { + $Drug = DrugStoreRelations::find()->where([ + 'store_id' => $get['store_id'], + 'drug_id' => $val['drug_id'] + ])->one(); + if (!$Drug) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $get['store_id']; + $DrugStoreRelations->drug_id = $val['drug_id']; + $DrugStoreRelations->price = bcdiv(bcmul($val['price'], $store['z_sale_percent']??100, 4), 100, 4); + $DrugStoreRelations->buy_price = bcdiv(bcmul($val['market_price'], $store['z_buy_percent']??100, 4), 100, 4); + $DrugStoreRelations->status = $val['status']; + $DrugStoreRelations->saveOrFail(); + } + } + + + //西药 + foreach ($DrugStoreDrug_west as $v) { + $DrugStore = DrugStoreRelations::find()->where([ + 'store_id' => $get['store_id'], + 'drug_id' => $v['drug_id'] + ])->one(); + if (!$DrugStore) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $get['store_id']; + $DrugStoreRelations->drug_id = $v['drug_id']; + $DrugStoreRelations->price = $v['price']; + $DrugStoreRelations->buy_price = $v['market_price'] ?? $v['price']; + $DrugStoreRelations->status = $v['status']; + $DrugStoreRelations->saveOrFail(); + } + } + + //配方 + foreach ($DrugStoreDrug_grain as $vv) { + $DrugStoreRelations = DrugStoreRelations::find()->where([ + 'store_id' => $get['store_id'], + 'drug_id' => $vv['drug_id'] + ])->one(); + if (!$DrugStoreRelations) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $get['store_id']; + $DrugStoreRelations->drug_id = $vv['drug_id']; + $DrugStoreRelations->price = bcdiv(bcmul($vv['price'], $store['g_sale_percent']??100, 4), 100, 4); + $DrugStoreRelations->buy_price = bcdiv(bcmul($vv['market_price'], $store['g_bug_percent']??100, 4), 100, 4); + $DrugStoreRelations->status = $vv['status']; + $DrugStoreRelations->saveOrFail(); + } + } + + //中成药 + foreach ($DrugStoreDrug_zongcheng as $vv) { + $DrugStoreRelations_z = DrugStoreRelations::find()->where([ + 'store_id' => $get['store_id'], + 'drug_id' => $vv['drug_id'] + ])->one(); + if (!$DrugStoreRelations_z) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->store_id = $get['store_id']; + $DrugStoreRelations->drug_id = $vv['drug_id']; + $DrugStoreRelations->price = $vv['price']; + $DrugStoreRelations->buy_price = $vv['market_price'] ?? $vv['price']; + $DrugStoreRelations->status = $vv['status']; + $DrugStoreRelations->saveOrFail(); + } + } + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + $t->commit(); + return ['同步成功']; + } +} \ No newline at end of file diff --git a/admin/controllers/dashboard/IndexController.php b/admin/controllers/dashboard/IndexController.php new file mode 100644 index 0000000..b2061f3 --- /dev/null +++ b/admin/controllers/dashboard/IndexController.php @@ -0,0 +1,62 @@ +attributes = \Yii::$app->request->get(); + $form->attributes = \Yii::$app->request->post(); + return $form->data_search(); + } + + + /** + * @doc-name 销量排行榜 + * @doc-return mixed @Week_top_list{num-int-销量,brand-string-品牌,name-string-商品名称} 近7天 + * @doc-return mixed @Mouth_top_list{num-int-销量,brand-string-品牌,name-string-商品名称} 近30天 + */ + public function actionSalesTop() + { + $form = new DataForm(); + $form->attributes = \Yii::$app->request->get(); + $form->attributes = \Yii::$app->request->post(); + return $form->sales_top(); + } + + + /** + * @doc-name 图表 + * @doc-param string date_start 开始时间YYMMDD + * @doc-param string date_end 开始时间YYMMDD + * @doc-return string created_at 日期 + * @doc-return int order_num 订单数量 + * @doc-return double total_pay_price 支付金额 + * @return mixed + */ + public function actionTable() + { + $form = new DataForm(); + $form->attributes = \Yii::$app->request->get(); + $form->attributes = \Yii::$app->request->post(); + return $form->table_search(); + } + + + + +} diff --git a/admin/controllers/doctor/DoctorController.php b/admin/controllers/doctor/DoctorController.php new file mode 100644 index 0000000..e274511 --- /dev/null +++ b/admin/controllers/doctor/DoctorController.php @@ -0,0 +1,804 @@ +request->get(); + $this->requestValidate($get, [ + ['status', 'required'] + ]); + $name = $get['name']; + $mobile = $get['mobile']; + $depart_id = $get['depart_id']; + $title_id = $get['title_id']; + $identity = $get['identity']; + + $admin = \Yii::$app->user->identity; + switch ($get['status']) { + case 0: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::WAIT_JH, + 'su.is_delete' => 0 + ]); + break; + case 1: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::WAIT_SH, + 'su.is_delete' => 0 + ]); + break; + case 2: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::OK, + 'su.is_delete' => 0 + ]); + break; + case 3: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::REFUSED, + 'su.is_delete' => 0 + ]); + break; + case 4://全部医生 + //门店 + if ($admin->role == UserRoleEnum::STORE_ADMIN) { + $su_id = StoreDoctor::find()->select('su_id')->where([ + 'store_id' => $admin->store_id, + 'is_delete' => 0 + ])->column(); + return ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => [UserStatusEnum::REFUSED, UserStatusEnum::OK, UserStatusEnum::WAIT_SH, UserStatusEnum::FORBID], + 'su.is_delete' => 0 + ])->andWhere(['in', 'su.id', $su_id])->with(['docInfo', 'docPracticing', 'docService'])->asArray()->all(); + } + + //超管 + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => [UserStatusEnum::REFUSED, UserStatusEnum::OK, UserStatusEnum::WAIT_SH, UserStatusEnum::FORBID], + 'su.is_delete' => 0 + ]); + break; + case 5: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::FORBID, + 'su.is_delete' => 0 + ]); + break; + default: + throw new \yii\db\Exception('参数错误'); + } + + $departs = Department::find()->select('id,name')->where(['<>', 'id', 0])->asArray()->all(); + + $id = 0; + foreach ($departs as $v) { + if (in_array($depart_id, $v) == true) { + $id = $v['id']; + } + } + + $query->joinWith(['docInfo' => function ($q) use ($name, $id, $mobile, $depart_id, $title_id, $identity) { + $q->alias('i'); + if (!empty($name)) {//搜索姓名 + $q->andWhere(['like', 'i.name', $name]); + } + if (!empty($mobile)) {//手机号 + $q->andWhere(['i.mobile' => $mobile]); + } + if (!empty($depart_id)) {//科室 + $q->andWhere(['i.depart_id' => $depart_id]); + } + if (!empty($title_id)) {//职称搜索 + $q->andWhere(['i.title_id' => $title_id]); + } + if (!empty($identity)) {//身份1中医2西医 + $q->andWhere(['i.identity' => $identity]); + } + }]); + + $this->field = [ + ServiceUser::class => [ + 'id', + 'reason', 'status', 'created_at', 'updated_at', + 'depart_id' => 'docInfo.depart_id', + 'avator' => 'docInfo.avatar', + 'is_star' => 'docInfo.star', + 'name' => 'docInfo.name', + 'mobile', + 'is_sync'=> 'docInfo.is_sync', + 'depart' => 'docInfo.depart.name', + 'title1' => 'docInfo.title.name', + 'intro' => 'docInfo.intro', + 'good_at' => 'docInfo.good_at', + 'identity' => 'docInfo.identity', + 'service' => 'docService', + 'practicing' => 'docPracticing', + 'idcard' => 'docInfo.idcard', + 'store' => function ($m) { + return StoreDoctor::find()->select(['store_id'])->where([ + 'su_id' => $m->id, + 'is_delete' => 0 + ])->with(['store'])->asArray()->all(); + } + ], + DoctorService::class => [ + 'su_id', 'register_status', 'register_price' + ], + DoctorPracticing::class => [ + 'su_id', 'qualification', 'practicing', 'title', + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 审核通过操作+拒绝操作(入驻) + * @doc-desc 当status为2时必填reason + * @doc-param int status 状态1审核通过操作2拒绝操作 + * @doc-param string reason 拒绝的原因 / optional + * @doc-param int doctor_id 医生id + */ + public function actionIntoCheck() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['status', 'doctor_id'], 'required'] + ]); + + $is_exist = ServiceUser::find()->alias('su')->where([ + 'id' => $post['doctor_id'], + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::WAIT_SH, + 'su.is_delete' => 0 + ])->one(); + + switch ($post['status']) { + case 1: + if (!$is_exist) throw new Exception('待审核的医生不存在'); + + $is_exist->status = UserStatusEnum::OK; + $is_exist->updated_at = time(); + $is_exist->saveOrFail(); + + return ['审核通过']; + case 2: + if (!$is_exist) throw new Exception('医生不存在'); + if (empty($post['reason'])) throw new Exception('拒绝的原因不能为空'); + + $is_exist->status = UserStatusEnum::REFUSED; + $is_exist->updated_at = time(); + $is_exist->reason = $post['reason']; + $is_exist->saveOrFail(); + + return ['拒绝审核']; + default: + throw new \yii\db\Exception('参数错误'); + } + } + + /** + * @doc-name 医生详情 + * @doc-param int doctor_id 医生id + * @doc-return mixed @List{ServiceUser{id,is_vip-int-是否平台搜索1否2是,reason-string-拒绝原因,status-int-状态0待激活1待审核2已认证3拒绝(需要修改激活资料),created_at-string-注册时间,updated_at-string-审核通过时间,avator-string-医生头像,is_star-int-是否是名医0否1是,name-string-医生姓名,depart-string-医生科室,hospital_id-int-医院ID,hospital-string-医院,yard-string-院区,title-string-职称,good_at-string-擅长,process-int-用户同步状态0身份审核通过1证书签发2设置签章3用户注销4申请拒绝5用户停用6修改手机号7用户启用9用户删除,note-string-当拒绝时或证书签发时:审核拒绝原因/证书信息,@Service{DoctorService{register_status,register_price},@Practicing{qualification-string-资格证书,practicing-string-执业证书,title-职称证书},@store{store_id-int-门店ID}}} 医生列表 + */ + public function actionInfo() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['doctor_id', 'required'] + ]); + $doctor = $get['doctor_id']; + $ServiceUser = ServiceUser::find()->alias('su')->where([ + 'su.id' => $get['doctor_id'], + 'su.role' => UserRoleEnum::DOCTOR, + 'su.is_delete' => 0 + ])->with(['docInfo', 'docIdentity', 'docPracticing', 'docService']) + ->asArray()->one(); + if (!$ServiceUser) throw new Exception('医生不存在'); + $ServiceUser['store'] = StoreDoctor::find()->select(['store_id'])->where([ + 'su_id' => $doctor, + 'is_delete' => 0 + ])->with(['store'])->asArray()->all(); + + return $ServiceUser; + } + + + + /** + * 医生同步互医审核通过 + * @return string[] + * @throws Exception + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function actionSyncDoctor() + { + $serviceUserId = \Yii::$app->request->post('doctor_id'); + if(empty($serviceUserId)){ + throw new Exception('医生id不能为空'); + } + $serviceUser = ServiceUser::find()->where([ + 'id' => $serviceUserId + ])->with('docInfo', 'docIdentity', 'docPracticing')->one(); + if (empty($serviceUser) || empty($serviceUser->docInfo) || empty($serviceUser->docIdentity) || empty($serviceUser->docPracticing)) { + throw new Exception('医生信息错误'); + } + if($serviceUser->docInfo->is_sync == 2){ + throw new Exception('该医生已同步至互医'); + } + $params = [ + 'id' => $serviceUserId, + 'store_id' => implode(',', json_decode($serviceUser->docInfo->store_id, true)), + 'mobile' => $serviceUser->mobile, + 'avatar' => $serviceUser->docInfo->avatar, + 'name' => $serviceUser->docInfo->name, + 'id_card' => $serviceUser->docInfo->idcard, + 'good_at' => $serviceUser->docInfo->good_at, + 'intro' => $serviceUser->docInfo->intro, + 'card_up' => $serviceUser->docIdentity->card_up, + 'card_down' => $serviceUser->docIdentity->card_down, + 'work_avatar' => $serviceUser->docIdentity->work_avator, + 'qualification' => $serviceUser->docPracticing->qualification, + 'practicing' => $serviceUser->docPracticing->practicing, + 'title' => $serviceUser->docPracticing->title + ]; + + $response = (new Client(['http_errors' => false]))->post( + \Yii::$app->params['platform']['url'] . "/platform/v1/sync/doctor", + [ + 'headers' => ['Content-Type' => 'application/json', 'Authorization' => "Bearer " . \Yii::$app->params['platform']['token']], + \GuzzleHttp\RequestOptions::JSON => $params + ] + ); + $result = json_decode($response->getBody(), true); + + if ($result['errcode']) { + throw new Exception($result['msg']); + } + DoctorInfo::updateAll(['is_sync' => 1], ['su_id' => $serviceUserId]); + return ['同步互医完成']; + } + + /** + * @doc-name 中西医 + * @doc-return array aa bb + */ + public function actionIdentity() + { + return [ + ['key' => 0, 'value' => '中医'], + ['key' => 1, 'value' => '西医'], + ]; + } + + /** + * @doc-name 职称列表 + * @doc-return mixed @DoctorTitle{*} 职称 + */ + public function actionTitle() + { + return DoctorTitle::find()->all(); + } + + /** + * @doc-name 医生绑定门店 + * @doc-param int doctor_id 医生ID + * @doc-param string store_id 门店 + */ + public function actionDocTieStore() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['doctor_id', 'store_id'], 'required'] + ]); + + $store_id = StoreDoctor::find()->select(['store_id'])->where([ + 'su_id' => $post['doctor_id'], + 'is_delete' => 0 + ])->column(); + + $ids = explode(',', $post['store_id']); + + $tie_id = array_diff($ids, $store_id);//要绑定的 + $del_id = array_diff($store_id, $ids);//解除绑定的 + + $t = \Yii::$app->db->beginTransaction(); + try { + if (empty($tie_id) && !empty($del_id)) { + foreach ($del_id as $val) { + \Yii::$app->db->createCommand()->update('yii_store_doctor', ['is_delete' => 1], ['store_id' => $val, 'su_id' => $post['doctor_id']])->execute(); + } + } else { + foreach ($tie_id as $v) { + $store_doctor = new StoreDoctor(); + $store_doctor->store_id = $v; + $store_doctor->su_id = $post['doctor_id']; + $store_doctor->saveOrFail(); + } + } + + + $DoctorInfo = DoctorInfo::find()->where([ + 'su_id' => $post['doctor_id'] + ])->one(); + if (!$DoctorInfo) throw new \Exception('医生基本信息未完善'); + $DoctorInfo->store_id = '[' . $post['store_id'] . ']'; + + $DoctorInfo->saveOrFail(); + + $t->commit(); + return ['绑定成功']; + } catch (\Exception $exception) { + $t->rollBack(); + throw new \Exception($exception->getMessage()); + } + } + + /** + * @doc-name 账号停用或恢复 + * @doc-param int doctor_id 医生 + */ + public function actionAccountForbid() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['doctor_id', 'required'] + ]); + $ServiceUser = ServiceUser::find()->alias('su')->where([ + 'id' => $post['doctor_id'], + 'su.role' => UserRoleEnum::DOCTOR, + 'su.is_delete' => 0 + ])->andWhere([ + 'or', + ['su.status' => UserStatusEnum::OK], + ['su.status' => UserStatusEnum::FORBID], + ])->one(); + if (!$ServiceUser) throw new \yii\db\Exception('医生不存在或账号非已认证状态!!'); + $ServiceUser->status == UserStatusEnum::FORBID ? $ServiceUser->status = UserStatusEnum::OK : $ServiceUser->status = UserStatusEnum::FORBID; + $ServiceUser->saveOrFail(); + + return ['success']; + } + + + /** + * @doc-name 门店的医生明细 + * @doc-param int store_id 医生 + */ + public function actionDoctorDetail() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['store_id', 'required'] + ]); + $store_id = \Yii::$app->request->get(); + + $store = Store::find()->where(['id' => $get['store_id']])->one(); + if (!$store) { + throw new \yii\db\Exception('门店不存在!!'); + } + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time == $end_time) {//筛选当天 + $time = FuncHelper::getDayBE($get['start_time']); + + $end_time = $time; + } + } + + $doctor = StoreDoctor::find()->select('su_id')->where(['store_id' => $get['store_id']])->column(); + + $query = DoctorInfo::find()->where(['in', 'su_id', $doctor]); + + $this->field = [ + DoctorInfo::class => [ + 'su_id', + 'name', + 'register_price' => function ($r) use ($start_time, $end_time, $store_id) { + + return $this->actionRegisterPrice($r->su_id, $store_id, $start_time, $end_time); + }, + 'drug_sale_price' => function ($r) use ($start_time, $end_time, $store_id) { + + return $this->actionDrugSale($r->su_id, $store_id, $start_time, $end_time); + }, + 'drug_give_price' => function ($r) use ($start_time, $end_time, $store_id) { + + return $this->actionDrugGive($r->su_id, $store_id, $start_time, $end_time); + }, + 'drug_profit_price' => function ($r) use ($start_time, $end_time, $store_id) { + + return $this->actionDrugProfit($r->su_id, $store_id, $start_time, $end_time); + }, + 'treatement_price' => function ($r) use ($start_time, $end_time, $store_id) { + + return $this->actionTreatementPrice($r->su_id, $store_id, $start_time, $end_time); + }, + 'process_price' => function ($r) use ($start_time, $end_time, $store_id) { + + return $this->actionProcessPrice($r->su_id, $store_id, $start_time, $end_time); + }, + ] + ]; + + return $this->create($query, $get); + } + + /** + * @doc-name 加工费 + * @doc-param int su_id 医生 + */ + public function actionProcessPrice($su_id = '', $store_id = '', $start_time = '', $end_time = '') + { + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + + $price = Ledger::find()->alias('r')->where(['r.su_id' => $su_id, 'r.user_id' => $store_id, 'r.status' => 1, 'r.user_type' => 1, 'r.order_type' => 1, 'r.fee_type' => 5])->andWhere($data ?? '')->sum('money'); + + + return $price ?? 0; + } + + /** + * @doc-name 诊疗费 + * @doc-param int su_id 医生 + */ + public function actionTreatementPrice($su_id = '', $store_id = '', $start_time = '', $end_time = '') + { + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + + $price = Ledger::find()->alias('r')->where(['r.su_id' => $su_id, 'r.user_id' => $store_id, 'r.status' => 1, 'r.user_type' => 1, 'r.order_type' => 1, 'r.fee_type' => 6])->andWhere($data ?? '')->sum('money'); + + + return $price ?? 0; + } + + /** + * @doc-name 挂号费 + * @doc-param int su_id 医生 + */ + public function actionRegisterPrice($su_id = '', $store_id = '', $start_time = '', $end_time = '') + { + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + + $price = Ledger::find()->alias('r')->where(['r.su_id' => $su_id, 'r.user_id' => $store_id, 'r.status' => 1, 'r.user_type' => 1, 'r.order_type' => 2])->andWhere($data ?? '')->sum('money'); + + + return $price ?? 0; + } + + /** + * @doc-name 药品总销售额 + */ + public function actionDrugSale($su_id = null, $store_id = null, $start_time = '', $end_time = '') + { + + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + $order_id = ProductOrder::find()->select('id')->where(['su_id' => $su_id, 'is_pay' => 1, 'store_id' => $store_id])->column(); + + $total_price = Reconciliation::find()->alias('r')->where([ + 'in', 'r.order_id', $order_id, + 'r.status' => 1 + ])->andWhere($data ?? '')->sum('total_price'); + + return $total_price ?? 0; + } + + /** + * @doc-name 药品总供货金额 + */ + public function actionDrugGive($su_id = null, $store_id = null, $start_time = '', $end_time = '') + { + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + $order_id = ProductOrder::find()->select('id')->where(['su_id' => $su_id, 'is_pay' => 1, 'store_id' => $store_id])->column(); + + //供货金额 + $total_buy_price = Reconciliation::find()->alias('r')->where([ + 'in', 'r.order_id', $order_id, + 'r.status' => 1 + ])->andWhere($data ?? '')->sum('total_buy_price'); + return $total_buy_price ?? 0; + } + + + /** + * @doc-name 药品总利润 + */ + public function actionDrugProfit($su_id = null, $store_id = null, $start_time = '', $end_time = '') + { + if (!empty($start_time) && !empty($end_time)) { + $get_start_time = date('Y-m-d H:i:s', $start_time); + if ($start_time == $end_time) {//筛选某一天 + $time = FuncHelper::getDayBE($get_start_time); + $start_time = strtotime($get_start_time); + $end_time = $time[1]; + } + $data = ['between', 'r.xd_time', $start_time, $end_time]; + } + + $order_id = ProductOrder::find()->select('id')->where(['su_id' => $su_id, 'is_pay' => 1, 'store_id' => $store_id])->column(); + + //销售额 + $total_price = Reconciliation::find()->alias('r')->where([ + 'in', 'r.order_id', $order_id, + 'r.status' => 1 + ])->andWhere($data ?? '')->sum('total_price'); + + //供货金额 + $total_buy_price = Reconciliation::find()->alias('r')->where([ + 'in', 'r.order_id', $order_id, + 'r.status' => 1 + ])->andWhere($data ?? '')->sum('total_buy_price'); + + $profit = bcsub($total_price, $total_buy_price, 4); + return $profit ?? 0; + } + + /** + * @doc-name 门诊收入药品销售 + */ + public function actionStoreIncomeDrugSale() + { + + $get = \Yii::$app->request->get(); + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + + $user = \Yii::$app->user->identity; + + $query = ProductOrder::find()->alias('p'); + +// $Reconciliation_query = Reconciliation::find()->alias('r'); + + $Ledger_query = Ledger::find()->alias('re')->where(['order_type' => 2, 'status' => [0, 1]]); + + $month_start = strtotime(date('Y-m-01 00:00:00')); + $month_end = strtotime(date('Y-m-t 23:59:59')); + + if (!empty($start_time) && !empty($end_time)) { + $data = ['between', 'p.created_at', $start_time, $end_time]; + } + +// if (!empty($start_time) && !empty($end_time)) { +// $datas = ['between', 'r.xd_time', $start_time, $end_time]; +// } + + if (!empty($start_time) && !empty($end_time)) { + $register_data = ['between', 're.xd_time', $start_time, $end_time]; + } + + if ($user->role == UserRoleEnum::STORE_ADMIN) { + $query->andWhere(['p.store_id' => $user->store_id]); + +// $Reconciliation_query->andWhere(['r.store_id' => $user->store_id, 'r.status' => 1]); + + $Ledger_query->andWhere(['re.user_id' => $user->store_id]); + } + + //订单销售 + $order_sale = $query->andWhere([ + 'and', + ['<>', 'p.refund_status', 3], + ['<>', 'p.status', '4'], + ['=', 'p.is_pay', 1], + ])->andWhere($data ?? '')->sum('total_pay_price'); + + $order_id = $query->andWhere([ + 'and', + ['<>', 'p.refund_status', 3], + ['<>', 'p.status', '4'], + ['=', 'p.is_pay', 1], + ])->column(); + + $price = 0; + if ($user->role == UserRoleEnum::STORE_ADMIN) { + foreach ($order_id as $val) { + $Ledger = Ledger::find()->alias('re')->where(['re.user_id' => $user->store_id, 'order_id' => $val, 'order_type' => 1, 'status' => [0, 1]])->all(); + foreach ($Ledger as $v) { + $price_data[] = $v['money']; + $price += $v['money']; + } + } + } else { + + foreach ($order_id as $val) { + $Ledger = Ledger::find()->alias('re')->where(['order_id' => $val, 'order_type' => 1, 'status' => [0, 1]])->all(); + foreach ($Ledger as $v) { + $price_data[] = $v['money']; + $price += $v['money']; + } + } + } + + $register_price_data = $Ledger_query->select('money')->andWhere($register_data ?? '')->column(); + + $register_price = $Ledger_query->andWhere($register_data ?? '')->sum('money'); + + + //利润 + $profit = bcadd($price, $register_price, 4); + + return [ + 'order_sale' => $order_sale ?? 0, + 'store_income' => $profit ?? 0, + 'register_price' => $register_price ?? 0, + 'register_price_data' => $register_price_data, + 'price' => $price ?? 0,//利润 + 'price_data' => $price_data, + + ]; + } + + /** + * @doc-name 平台门诊收入药品销售 + */ + public function actionPlatformStoreIncomeDrugSale() + { + + $get = \Yii::$app->request->get(); + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + $data = []; + if (!empty($start_time) && !empty($end_time)) { + $data = ['between', 'created_at', $start_time, $end_time]; + } + + $where = []; + $admin = \Yii::$app->user->identity; + if($admin->store_id){ + $where['store_id'] = $admin->store_id; + } + + $total=ProductOrder::find()->where([ + 'and', + ['<>', 'refund_status', 3], + ['=', 'is_pay', 1], + ['<>', 'status', '4'], + ])->andWhere($data)->andWhere($where)->select('sum(total_pay_price) as total_sale_price,sum(market_price+trans_expenses+process_price) as total_market_price')->asArray()->one(); + + // $register_price = 0; + // $order_sale = 0; + // $all_price = 0; + + // $all_store = ProductOrder::find()->alias('p')->select('p.store_id')->andWhere([ + // 'and', + // ['<>', 'p.refund_status', 3], + // ['=', 'p.is_pay', 1], + // ['<>', 'p.status', '4'], + // ])->andWhere($data ?? '')->groupBy('store_id')->column(); + + // foreach ($all_store as $key => $value) { + // //订单销售 + // $order_sale = ProductOrder::find()->alias('p')->andWhere([ + // 'and', + // ['<>', 'p.refund_status', 3], + // ['=', 'p.is_pay', 1], + // ['=','p.store_id' ,$value], + // ['<>', 'p.status', '4'], + // ])->andWhere($data ?? '')->sum('total_pay_price'); + + // $order_id = ProductOrder::find()->alias('p')->andWhere([ + // 'and', + // ['<>', 'p.refund_status', 3], + // ['<>', 'p.status', '4'], + // ['=', 'p.is_pay', 1], + // ['=','p.store_id' ,$value], + // ])->andWhere($data ?? '')->column(); + + // foreach ($order_id as $val) { + // $all_price += Ledger::find()->alias('re')->andWhere(['re.user_id' => $value,'re.user_type'=>1, 'order_id' => $val, 'order_type' => 1, 'status' => [0, 1]])->sum('money'); + + // } + + // $register_price += Ledger::find()->alias('re')->where(['re.order_type' => 2 ,'re.user_type'=>1,'status' => [0, 1]])->andWhere(['re.user_id' => $value])->andWhere($register_data ?? '')->sum('money'); + + // } + + // //利润 + // $profit = bcadd($all_price, $register_price, 4); + + return [ + 'order_sale' => $total['total_sale_price'] ?? 0, + 'store_income' => bcsub($total['total_sale_price'],$total['total_market_price'],4), + + ]; + } +} diff --git a/admin/controllers/doctor/PharmacistController.php b/admin/controllers/doctor/PharmacistController.php new file mode 100644 index 0000000..33f555d --- /dev/null +++ b/admin/controllers/doctor/PharmacistController.php @@ -0,0 +1,236 @@ +request->get(); + $this->requestValidate($post,[ + ['status','required'] + ]); + $name=$post['name']; + $mobile=$post['mobile']; + $depart_id=$post['depart_id']; + $title_id=$post['title_id']; + $identity=$post['identity']; + + switch ($post['status']){ + case 0: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DRUG, + 'su.status' => UserStatusEnum::WAIT_JH, + 'su.is_delete' => 0 + ]); + break; + case 1: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DRUG, + 'su.status' => UserStatusEnum::WAIT_SH, + 'su.is_delete' => 0 + ]); + break; + case 2: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DRUG, + 'su.status' => UserStatusEnum::OK, + 'su.is_delete' => 0 + ]); + break; + case 3: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DRUG, + 'su.status' => UserStatusEnum::REFUSED, + 'su.is_delete' => 0 + ]); + break; + case 4: + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DRUG, + 'su.status' =>[ UserStatusEnum::REFUSED,UserStatusEnum::OK, UserStatusEnum::WAIT_SH], + 'su.is_delete' => 0 + ]); + break; + default: + throw new \yii\db\Exception('参数错误'); + } + + $departs = Department::find()->select('id,name')->where(['<>', 'id', 0])->asArray()->all(); + + $id = 0; + foreach ($departs as $v) { + if (in_array($depart_id, $v) == true) { + $id = $v['id']; + } + } + $query->joinWith(['drugInfo' => function ($q) use ($name,$id,$mobile, $depart_id, $title_id,$identity) { + $q->alias('d'); + if (!empty($name)) {//搜索姓名 + $q->andWhere(['like', 'd.name', $name]); + } + if (!empty($mobile)) {//手机号 + $q->andWhere(['d.mobile'=>$mobile]); + } + if (!empty($depart_id)) {//科室 + $q->andWhere(['d.depart_id'=>$depart_id]); + } + if (!empty($title_id)) {//职称搜索 + $q->andWhere(['d.title_id' => $title_id]); + } + if (!empty($identity)) {//身份1中医2西医 + $q->andWhere(['d.identity' => $identity]); + } + }]); + + $this->field = [ + ServiceUser::class => [ + 'id','reason','status','created_at','updated_at', + 'identity'=>'drugInfo.identity', + 'depart_id'=>'drugInfo.depart_id', + 'avatar' => 'drugInfo.avatar', + 'name' => 'drugInfo.name', + 'mobile', + 'depart' => 'drugInfo.depart.name', + 'title1' => 'drugInfo.titles.name', + 'drugIdentity' => 'drugIdentity', + 'drugPracticing' => 'drugPracticing', + 'type'=>'drugInfo.type', + 'id_card'=>'drugInfo.idcard' + ], + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 药师审核通过操作+拒绝操作(入驻) + * @doc-desc 当status为2时必填reason + * @doc-param int status 状态1审核通过2拒绝操作 + * @doc-param string reason 拒绝的原因 / optional + * @doc-param int drug_id 药师id + */ + public function actionIntoCheck() + { + $post = \Yii::$app->request->get(); + $this->requestValidate($post,[ + [['status','drug_id'],'required'] + ]); + + $is_exist = ServiceUser::find()->alias('su')->where([ + 'id'=>$post['drug_id'], + 'su.role' => UserRoleEnum::DRUG, + 'su.status' => UserStatusEnum::WAIT_SH, + 'su.is_delete' => 0 + ])->one(); + + switch ($post['status']){ + case 1: + if (!$is_exist){ + throw new \Exception('药师不存在'); + } + + $is_exist->status=UserStatusEnum::OK; + $is_exist->updated_at=time(); + if (!$is_exist->saveOrFail()){ + throw new \Exception('error'); + } + + return ['药师审核通过']; + case 2: + if (!$is_exist){ + throw new \Exception('药师不存在'); + } + + if (empty($post['reason'])){ + throw new \Exception('拒绝原因不能为空'); + } + + $is_exist->status=UserStatusEnum::REFUSED; + $is_exist->updated_at=time(); + $is_exist->reason=$post['reason']; + + $is_exist->saveOrFail(); + return ['药师审核拒绝']; + default: + throw new \yii\db\Exception('参数错误'); + } + } + + /** + * @doc-name 药师详情 + * @doc-param int drug_id 药师id + */ + public function actionInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['drug_id','required'] + ]); + $ServiceUser = ServiceUser::find()->alias('su')->where([ + 'id'=>$post['drug_id'], + 'su.role' => UserRoleEnum::DRUG, + 'su.is_delete' => 0 + ])->with(['drugInfo','drugIdentity','drugPracticing'])->asArray()->one(); + if (!$ServiceUser){ + throw new \Exception('药师不存在'); + }; + + return $ServiceUser; + } + + /** + * @doc-name 设置药师初审或复审 + * @doc-param int drug_id 药师ID + * @doc-param int type 1初审2复审 + */ + public function actionSetFirstAgain() + { + $get= \Yii::$app->request->get(); + $this->requestValidate($get,[ + [['drug_id','type'],'required'] + ]); + $ServiceUser = ServiceUser::find()->alias('su')->where([ + 'id'=>$get['drug_id'], + 'su.role' => UserRoleEnum::DRUG, + 'status'=>UserStatusEnum::OK, + 'su.is_delete' => 0 + ])->one(); + if (!$ServiceUser){ + throw new \Exception('药师不存在'); + } + + $PharmacistrInfo=PharmacistrInfo::find()->where([ + 'su_id'=>$get['drug_id'] + ])->one(); + if (!$PharmacistrInfo){ + throw new \Exception('药师没完善信息'); + } + $PharmacistrInfo->type=$get['type']; + $PharmacistrInfo->saveOrFail(); + return ['设置成功']; + } + +} \ No newline at end of file diff --git a/admin/controllers/drug/ChineseController.php b/admin/controllers/drug/ChineseController.php new file mode 100644 index 0000000..e67b387 --- /dev/null +++ b/admin/controllers/drug/ChineseController.php @@ -0,0 +1,168 @@ +0,'value'=>'先煎'], + ['key'=>1,'value'=>'后下'], + ]; + } + + /** + * @doc-name 新增中药 + * @doc-param string drug_name 药名 + * @doc-param string pinyin_simple 拼音首拼 + * @doc-param string drug_number 编号 + * @doc-param string drug_alias 别名 / optional + * @doc-param int unit_id 单位 + * @doc-param int status 状态1草稿2下架3上架 + * @doc-param string place 产地 / optional + * @doc-param string instruction 说明书图片 / optional + * @doc-param json drugstore[{"drugstore_id":1,"price":100,"type":1,"stock":100},{"drugstore_id":2,"price":100,"type":1,"stock":200}] 仓库 + */ + public function actionSave() + { + $post=\Yii::$app->request->post(); + + $ChineseForm=new ChineseForm(); + $ChineseForm->attributes=$post; + return $ChineseForm->save(); + } + + /** + * @doc-name 修改中药 + * @doc-param int id 药品ID + * @doc-param string drug_name 药名 / optional + * @doc-param string pinyin_simple 拼音首拼 / optional + * @doc-param string drug_number 编号/ optional + * @doc-param string drug_alias 别名 / optional + * @doc-param int unit_id 单位 / optional + * @doc-param int status 状态1草稿2下架3上架 / optional + * @doc-param string place 产地 / optional + * @doc-param string instruction 说明书图片 / optional + */ + public function actionUpdate() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $ChineseForm=new ChineseForm(); + $ChineseForm->attributes=$post; + return $ChineseForm->update(); + } + /** + * @doc-name 查看中药 + * @doc-param int id 药品ID + */ + public function actionInfo() + { + $get=\Yii::$app->request->get(); + $this->requestValidate($get,[ + ['id','required'] + ]); + $ChineseForm=new ChineseForm(); + $ChineseForm->attributes=$get; + return $ChineseForm->info(); + } + + /** + * @doc-name 导入中药 + * @doc-param file file 文件 + */ + public function actionChineseImport() + { + $request = \Yii::$app->request; + if ($request->isPost) { + //设置最大执行时间 + ini_set("max_execution_time", "360"); + + $file = UploadedFile::getInstanceByName('file'); + if ($file->size > 5 * 1024 * 1024) { + return ['excel文件不能超过5M!']; + } + + //文件名 + $filename = date('His') . $file->getBaseName() . mt_rand(1000, 9999) . '.' . $file->getExtension(); + + //保存文件 + $file->saveAs( $filename); + + $data = Excel::import($filename, [ + 'setFirstRecordAsKeys' => true, + 'getOnlySheet' => 'Sheet1', + ]); + + $ImportForm=new ImportForm(); + return $ImportForm->ChineseImport($data); + } else { + throw new Exception('请求方式错误'); + } + } + + /** + * @doc-name 设置代煎费 + * @doc-param int value 值 + * @doc-param int type 类型1中药2西药3配方颗粒 + * @doc-param int id id + */ + public function actionDaijianPrice() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + [['id','type','value'],'required'] + ]); + $t=\Yii::$app->db->beginTransaction(); + + $SystemConfig=SystemConfig::find()->where([ + 'id'=>$post['id'],'config_type'=>1,'type'=>$post['type'] + ])->one(); + if (!$SystemConfig) throw new Exception('配置不存在'); + + $SystemConfig->value=$post['value']; + if (!$SystemConfig->saveOrFail()){ + $t->rollBack(); + throw new Exception('设置失败'); + } + + $t->commit(); + return ['设置成功']; + } + + /** + * @doc-name 配置 + * @doc-return mixed @List{id,name-string-name,config-int-配置类型1代煎费配置2包邮配置,type-int-类型1中药3配方颗粒,value-int-值} 配置 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionSystemConfig() + { + $get = \Yii::$app->request->get(); + $query = SystemConfig::find(); + $this->field = [ + SystemConfig::class => [ + 'id', 'name', 'type', 'value','config_type','rule' + ] + ]; + return $this->create($query, $get); + } + +} \ No newline at end of file diff --git a/admin/controllers/drug/DrugCategoryController.php b/admin/controllers/drug/DrugCategoryController.php new file mode 100644 index 0000000..4e72c77 --- /dev/null +++ b/admin/controllers/drug/DrugCategoryController.php @@ -0,0 +1,106 @@ +request->get(); + $query = DrugCategories::find()->where([ + 'deleted_at' => null + ]); + + if (!empty($get['name'])){ + $query->andWhere([ + 'like','category_name',$get['name'] + ]); + } + $this->field = [ + DrugCategories::class => [ + 'id', 'category_name', +// 'child_category' => 'child', + 'parent_id', 'level', 'sort', + ], + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 药品分类新增 + * @doc-param string category_name 名字 + * @doc-param int level 级别 + * @doc-param int pid 父级id / optional + * @doc-param int sort 排序 + */ + public function actionSave() + { + $post = \Yii::$app->request->post(); + + $DrugCategoryForm = new DrugCategoryForm(); + $DrugCategoryForm->attributes = $post; + return $DrugCategoryForm->save(); + } + /** + * @doc-name 药品分类修改 + * @doc-param int id ID + * @doc-param string category_name 名字 + * @doc-param int level 级别 + * @doc-param int pid 父级id / optional + * @doc-param int sort 排序 + */ + public function actionUpdate() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $DrugCategoryForm = new DrugCategoryForm(); + $DrugCategoryForm->attributes = $post; + return $DrugCategoryForm->update(); + } + /** + * @doc-name 药品分类删除 + * @doc-param int id 药品分类id + */ + public function actionDelete() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + $DrugCategoryForm = new DrugCategoryForm(); + $DrugCategoryForm->attributes = $get; + return $DrugCategoryForm->del(); + + } + + /** + * @doc-name 药品分类查看详情 + * @doc-param int id 药品分类id + */ + public function actionInfo() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + $DrugCategoryForm = new DrugCategoryForm(); + $DrugCategoryForm->attributes = $get; + return $DrugCategoryForm->info(); + } + + +} \ No newline at end of file diff --git a/admin/controllers/drug/DrugController.php b/admin/controllers/drug/DrugController.php new file mode 100644 index 0000000..24386cd --- /dev/null +++ b/admin/controllers/drug/DrugController.php @@ -0,0 +1,477 @@ + 0, 'value' => '中药'], + ['key' => 1, 'value' => '西药'], + ['key' => 2, 'value' => '颗粒配方'], + ['key' => 3, 'value' => '中成药'], + ]; + } + + /** + * @doc-name 中药的煎熬方式 + */ + public function actionUseWay() + { + return DrugUseWay::find()->all(); + } + /** + * @doc-name 药使用时间 + */ + public function actionUseTime() + { + return DrugUseTime::find()->all(); + } + + /** + * @doc-name 药的使用频率 + */ + public function actionUseFrequency() + { + return DrugUseFrequency::find()->all(); + } + /** + * @doc-name 药的使用方式 + */ + public function actionUseType() + { + return DrugUseType::find()->all(); + } + /** + * @doc-name 西药单位 + */ + public function actionWestUnit() + { + return WestUnit::find()->all(); + } + + + /** + * @doc-name 药品基本信息列表 + * @doc-param int status 状态类型1中药2西药3颗粒配方5全部列表 + * @doc-param string name 搜素药名、编号、条形码、厂家、中西药标签、拼音首拼、别名 + * @doc-return mixed @List{id,drug_name-string-药名,drug_number-string-编号,drug_alias-string-别名,bar_code-string-条形码,guozi_no-string-国字准号,category_first-int-一级分类,category_second-int-二级分类,source-string-货源(厂家),function-string-功能主治,decotion-string-煎法,is_otc-int-是否处方药,usage-string-用法,specification-string-规格,instruction-string-说明书图片,image-string-药品图片,time-string-使用时间,use_type-string-使用方法,frequency-string-频率,unit-string-单位,small_info-string-简介,info-string-基础信息,content-string-详情信息,status-int-状态1草稿2下架3上架,is_shalving-int-状态1下架2上架,stock-int-库存,store-int-门店,type-int-类别1中药2西药3颗粒配方4中成药} 药品列表 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionList() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['status', 'required'] + ]); + + if (!empty($get['start_time']) && !empty($get['end_time'])) { + $start_time = strtotime($get['start_time'] . ' ' . '00:00:00'); + $end_time = strtotime($get['end_time'] . ' ' . '23:59:59'); + } + + $query = Drug::find()->alias('d')->orderBy(['id' => SORT_ASC]); + + $user = \Yii::$app->user->identity; + + if ($user->role == UserRoleEnum::STORE_ADMIN) { //门店 + $query->joinWith(['drugStoreRelationes' => function ($drug) use ($user) { + $drug->alias('ds'); + $drug->andWhere(['ds.store_id' => $user->store_id,'ds.is_forbid'=>0,'ds.status'=>2]); + }]); + } + + switch ($get['status']) { + case 1: + $query->andWhere(['d.type' => 1]); + break; + case 2: + $query->andWhere(['d.type' => 2]); + break; + case 3: + $query->andWhere(['d.type' => 3]); + break; + case 4: + $query->andWhere(['d.type' => 4]); + break; + case 5: + $query->andWhere(['d.type' => [1, 2, 3, 4]]); + break; + default: + throw new Exception('参数错误'); + } + if (!empty($get['name'])) { + $query->andWhere([ + 'or', + ['like', 'drug_name', $get['name']], + ['like', 'drug_number', $get['name']], + ['like', 'bar_code', $get['name']], + ['like', 'source', $get['name'] ], + ['like', 'pinyin_simple', $get['name'] ], + ['like', 'drug_alias', $get['name'] ], + ]); + } + + if (!empty($start_time) && !empty($end_time)) { + if ($start_time==$end_time){//筛选当天 + $time=FuncHelper::getDayBE($get['start_time']); + + $end_time=$time; + } + + $query->andWhere(['between', 'd.created_at', $start_time,$end_time]); + } +// if (!empty($get['drug_name'])) { +// $query->andWhere(['like', 'drug_name', $get['drug_name']]); +// } +// if (!empty($get['drug_number'])) { +// $query->andWhere(['like', 'drug_number', $get['drug_number']]); +// } +// if (!empty($get['bar_code'])) { +// $query->andWhere(['like', 'bar_code', $get['bar_code']]); +// } +// if (!empty($get['source'])) { +// $query->andWhere(['like', 'source', $get['source']]); +// } + if (!empty($get['type'])) { + $query->andWhere(['type' => $get['type']]); + } + + $this->field = [ + Drug::class => [ + 'id', 'pinyin_simple', 'drug_name', 'source', 'type', 'is_otc', 'category_first', 'category_second', 'small_info', 'info', 'content', 'usage', 'specification', 'image', 'status', 'drug_number', 'drug_alias', 'bar_code', 'guozi_no', 'place', 'function', 'instruction', 'decotion_id' => 'decotion', 'decotion' => 'drugUseWay.name', 'unit' => 'unit.name', + 'store' => 'drugStoreRelationes.store_id', + 'price' => 'drugStoreRelationes.price', + 'buy_price' => 'drugStoreRelationes.buy_price', + 'stock' => 'drugStoreRelationes.drugStoreDrug.stock', + 'is_shalving' => 'drugStoreRelationes.status', + 'type_id', 'frequency_id', 'unit_id', 'time_id', + 'use_frequency' => 'drugUseFrequency.name', 'use_type' => 'drugUseType.name', + 'use_time' => 'drugUseTime.name', + 'is_forbid'=>'drugStoreRelationes.is_forbid', + ], + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 基础商品库列表 + * @doc-param string drug_name 药名 / optional + * @doc-param string drug_number 编号 / optional + * @doc-param string bar_code 条形码 / optional + * @doc-param int category_first 一级分类 / optional + * @doc-param int category_second 二级分类 / optional + * @doc-param string source 厂家 / optional + * @doc-param int type 中西药标签 / optional + * @doc-return mixed @List{id,drug_name-string-药名,drug_number-string-编号,drug_alias-string-别名,bar_code-string-条形码,guozi_no-string-国字准号,category_first-int-一级分类,category_second-int-二级分类,source-string-货源(厂家),function-string-功能主治,decotion-string-煎法,is_otc-int-是否处方药,usage-string-用法,specification-string-规格,instruction-string-说明书图片,image-string-药品图片,time-string-使用时间,use_type-string-使用方法,frequency-string-频率,unit-string-单位,small_info-string-简介,info-string-基础信息,content-string-详情信息,status-int-状态1草稿2下架3上架,type-int-类别1中药2西药3颗粒配方4中成药} 药品列表 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionBaseGood() + { + $get = \Yii::$app->request->get(); + $query = Drug::find()->alias('d'); + + if (!empty($get['drug_name'])) { + $query->andWhere(['like', 'drug_name', $get['drug_name']]); + } + if (!empty($get['drug_number'])) { + $query->andWhere(['like', 'drug_number', $get['drug_number']]); + } + if (!empty($get['bar_code'])) { + $query->andWhere(['like', 'bar_code', $get['bar_code']]); + } + if (!empty($get['category_first'])) { + $query->andWhere(['category_first' => $get['category_first']]); + } + if (!empty($get['category_second'])) { + $query->andWhere(['category_second' => $get['category_second']]); + } + if (!empty($get['source'])) { + $query->andWhere(['like', 'source', $get['source']]); + } + if (!empty($get['type'])) { + $query->andWhere(['type' => $get['type']]); + } + + $this->field = [ + Drug::class => [ + 'id', 'pinyin_simple', 'drug_name', 'source', 'type', 'is_otc', 'category_first', 'category_second', 'small_info', 'info', 'content', 'usage', 'specification', 'image', 'status', 'drug_number', 'drug_alias', 'bar_code', 'guozi_no', 'place', 'function', 'instruction', 'decotion_id' => 'decotion', 'decotion' => 'drugUseWay.name', 'unit' => 'unit.name', 'time_id', 'type_id', 'frequency_id', 'unit_id', + 'use_frequency' => 'drugUseFrequency.name', 'use_type' => 'drugUseType.name', + 'use_time' => 'drugUseTime.name', + ], + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 导出基础药品 + */ + public function actionExportDrug() + { + \Yii::$app->response->format = Response::FORMAT_RAW; + $params=\Yii::$app->request->get(); + $parameter['header']=['ID','药名','拼音首拼','货源(厂家)','类型','是否处方药','详情信息','用法','功能主治','规格','药品编号','条形码','国字准号','药品别名','状态']; + $parameter['data']=Drug::inventory($params); + + ExportService::ExportByCors($parameter); + } + /** + * @doc-name 新增西药/或中成药 + * @doc-param string drug_name 药名 + * @doc-param string pinyin_simple 拼音首拼 + * @doc-param int is_otc 是否处方药 + * @doc-param string drug_number 编号 + * @doc-param string bar_code 条形码 + * @doc-param string specification 规格 + * @doc-param string guozi_no 国字准号 + * @doc-param string function 功能主治 + * @doc-param string source 厂家 + * @doc-param string instruction['1','2'] 说明书图片 + * @doc-param json image['1','2'] 药品图片 + * @doc-param int type 分类类型1中药2西药3颗粒配方4中成药 + * @doc-param int status 状态1草稿2下架3上架 + * @doc-param int unit_id 单位 / optional + * @doc-param int frequency_id 频次 + * @doc-param int type_id 方法 / optional + * @doc-param int time_id 时间 / optional + * @doc-param string drug_alias 别名 / optional + * @doc-param string usage 用法 + */ + public function actionSave() + { + $post = \Yii::$app->request->post(); + $DrugForm = new DrugForm(); + $DrugForm->attributes = $post; + + return $DrugForm->save(); + } + + /** + * @doc-name 基础药品上下架 + * @doc-param int id 药品ID + * @doc-param int type 类型类型1中药2西药3颗粒配方 + */ + public function actionIsSale() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + [['id', 'type', 'status'], 'required'] + ]); + $DrugForm = new DrugForm(); + $DrugForm->attributes = $get; + return $DrugForm->IsSale(); + } + /** + * @doc-name 基础药品-草稿 + * @doc-param int id 药品ID + * @doc-param int type 类型类型1中药2西药3颗粒配方 + */ + public function actionDraft() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + [['id', 'type'], 'required'] + ]); + $DrugForm = new DrugForm(); + $DrugForm->attributes = $get; + return $DrugForm->Draft(); + } + + /** + * @doc-name 修改西药/或中成药 + * @doc-param int id 药品ID + * @doc-param string drug_name 药名 + * @doc-param int is_otc 是否处方药 + * @doc-param string drug_number 编号 + * @doc-param string bar_code 条形码 + * @doc-param string specification 规格 + * @doc-param string guozi_no 国字准号 + * @doc-param string function 功能主治 + * @doc-param string source 厂家 + * @doc-param string place 产地 / optional + * @doc-param int category_first 一级分类 + * @doc-param int category_second 二级分类 + * @doc-param string instruction['1','2'] 说明书图片 + * @doc-param json image['1','2'] 药品图片 + * @doc-param int type 分类类型1中药2西药3颗粒配方4中成药 + * @doc-param int unit_id 单位 + * @doc-param int frequency_id 频次 + * @doc-param int type_id 方法 + * @doc-param int time_id 时间 + * @doc-param string drug_alias 别名 / optional + * @doc-param string usage 用法 + */ + public function actionUpdate() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $DrugForm = new DrugForm(); + $DrugForm->attributes = $post; + return $DrugForm->update(); + } + + /** + * @doc-name 查看详情(西药) + * @doc-param int id 药品ID + * @doc-param int type 类型1中药2西药3颗粒配方4中成药 + */ + public function actionInfo() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + [['id', 'type'], 'required'] + ]); + $DrugForm = new DrugForm(); + $DrugForm->attributes = $get; + return $DrugForm->info(); + } + + /** + * @doc-name 导入西药 + * @doc-param file file 文件 + */ + public function actionImport() + { + $request = \Yii::$app->request; + + if ($request->isPost) { + $post = \Yii::$app->request->post(); + //设置最大执行时间 + ini_set("max_execution_time", "360"); + $file = UploadedFile::getInstanceByName('file'); + if ($file->size > 5 * 1024 * 1024) { + return ['excel文件不能超过5M!']; + } + // $relative_path = 'excel/' . date('Y') . '/' . date('m') . '/' . date('d') . '/'; + // $absolute_path = rtrim(\Yii::$app->params['upload_dir'], '/') . '/' . $relative_path; + // if (!file_exists($absolute_path)) { + // try { + // FileHelper::createDirectory($absolute_path, 0777, true); + // } catch (\Exception $e) { + // return ['errno' => 0, 'msg' => '目录创建失败,' . $e->getMessage()]; + // } + // } + + //文件名 + $filename = date('His') . md5($file->getBaseName()) . mt_rand(1000, 9999) . '.' . $file->getExtension(); + //保存文件 + $file->saveAs($filename); + // $fullFileName = $absolute_path . $filename; + $data = Excel::import($filename, [ + 'setFirstRecordAsKeys' => true, + 'getOnlySheet' => 'Sheet1', + ]); + + $ImportForm = new ImportForm(); + $ImportForm->attributes = $post; + return $ImportForm->WestImport($data); + } else { + throw new Exception('请求方式错误'); + } + } + + + /** + * @doc-name 导入中成药 + * @doc-param file file 文件 + */ + public function actionImportZhongcheng() + { + $request = \Yii::$app->request; + + if ($request->isPost) { + $post = \Yii::$app->request->post(); + //设置最大执行时间 + ini_set("max_execution_time", "360"); + $file = UploadedFile::getInstanceByName('file'); + if ($file->size > 5 * 1024 * 1024) { + return ['excel文件不能超过5M!']; + } + + //文件名 + $filename = date('His') . md5($file->getBaseName()) . mt_rand(1000, 9999) . '.' . $file->getExtension(); + //保存文件 + $file->saveAs($filename); + // $fullFileName = $absolute_path . $filename; + $data = Excel::import($filename, [ + 'setFirstRecordAsKeys' => true, + 'getOnlySheet' => 'Sheet1', + ]); + + $ImportForm = new ImportForm(); + $ImportForm->attributes = $post; + return $ImportForm->ImportZhongcheng($data); + } else { + throw new Exception('请求方式错误'); + } + } + + + /** + * @doc-name 单位列表 + */ + public function actionUnit() + { + return WestUnit::find()->all(); + } + + + /** + * @doc-name 仓库导入药品 + */ + public function actionExportReal() + { + $request = \Yii::$app->request; + + if ($request->isPost) { + $post = \Yii::$app->request->post(); + //设置最大执行时间 + ini_set("max_execution_time", "360"); + $file = UploadedFile::getInstanceByName('file'); + if ($file->size > 5 * 1024 * 1024) { + return ['excel文件不能超过5M!']; + } + + //文件名 + $filename = date('His') . md5($file->getBaseName()) . mt_rand(1000, 9999) . '.' . $file->getExtension(); + //保存文件 + $file->saveAs($filename); + // $fullFileName = $absolute_path . $filename; + $data = Excel::import($filename, [ + 'setFirstRecordAsKeys' => true, + 'getOnlySheet' => 'Sheet1', + ]); + + $ImportForm = new ImportForm(); + $ImportForm->attributes = $post; + return $ImportForm->ExportRealDrug($data); + } else { + throw new Exception('请求方式错误'); + } + } +} diff --git a/admin/controllers/drug/GranularController.php b/admin/controllers/drug/GranularController.php new file mode 100644 index 0000000..4fed86d --- /dev/null +++ b/admin/controllers/drug/GranularController.php @@ -0,0 +1,119 @@ +request->post(); + $GranularForm=new GranularForm(); + $GranularForm->attributes=$post; + return $GranularForm->save(); + } + /** + * @doc-name 删除配方颗粒库 + * @doc-param int id 药品ID + */ + public function actionDelete() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $GranularForm=new GranularForm(); + $GranularForm->attributes=$post; + return $GranularForm->del(); + + } + /** + * @doc-name 修改配方颗粒库 + * @doc-param int id 药品ID + * @doc-param string drug_name 药名 + * @doc-param string pinyin_simple 拼音首拼 + * @doc-param string drug_number 编号 + * @doc-param string drug_alias 别名 + * @doc-param int unit_id 单位 + * @doc-param string place 产地 / optional + * @doc-param string instruction 说明书图片 / optional + */ + public function actionUpdate() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $GranularForm=new GranularForm(); + $GranularForm->attributes=$post; + return $GranularForm->update(); + + } + /** + * @doc-name 查看配方颗粒库 + * @doc-param int id 药品ID + */ + public function actionInfo() + { + $get=\Yii::$app->request->get(); + $this->requestValidate($get,[ + ['id','required'] + ]); + $GranularForm=new GranularForm(); + $GranularForm->attributes=$get; + return $GranularForm->info(); + } + + /** + * @doc-name 导入配方颗粒库 + * @doc-param file file 文件 + */ + public function actionGranularImport() + { + $request = \Yii::$app->request; + if ($request->isPost) { + //设置最大执行时间 + ini_set("max_execution_time", "360"); + $file = UploadedFile::getInstanceByName('file'); + if ($file->size > 5 * 1024 * 1024) { + return ['excel文件不能超过5M!']; + } + + //文件名 + $filename = date('His') . md5($file->getBaseName()) . mt_rand(1000, 9999) . '.' . $file->getExtension(); + //保存文件 + $file->saveAs($filename); + + $data = Excel::import($filename, [ + 'setFirstRecordAsKeys' => true, + 'getOnlySheet' => 'Sheet1', + ]); + + $ImportForm=new ImportForm(); + return $ImportForm->GranularImport($data); + } else { + return ['请求方式错误']; + } + } +} \ No newline at end of file diff --git a/admin/controllers/drug/ProcessRuleController.php b/admin/controllers/drug/ProcessRuleController.php new file mode 100644 index 0000000..da6785b --- /dev/null +++ b/admin/controllers/drug/ProcessRuleController.php @@ -0,0 +1,127 @@ +asArray()->all(); + $processRuleTree = Tree::ruleTree($processRule); + return $processRuleTree; + } + + public function actionNoteList(){ + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['rule_id', 'required'] + ]); + $ruleNotes = ProcessRuleNote::find()->where(['rule_id' => $get['rule_id']])->asArray()->all(); + return $ruleNotes; + } + + public function actionAdd(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['name', 'required'], + ['pid','required'], + ['calc_method','in','range'=>[1,2,3]], + [['name','unit'],'string'], + ['price','double'] + ]); + $processRule = new ProcessRule(); + $processRule->attributes = $post; + $res = $processRule->save(); + if(!$res){ + throw new \Exception('添加加工规则失败'); + } + return ['success']; + } + + public function actionAddNote(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['rule_id', 'required'], + ['note', 'required'] + ]); + $processRuleNote = new ProcessRuleNote(); + $processRuleNote->attributes = $post; + $res = $processRuleNote->save(); + if(!$res){ + throw new \Exception('添加加工规则备注失败'); + } + return ['success']; + } + + public function actionUpdate(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['name', 'required'], + ['id','required'] + + ]); + $processRule = ProcessRule::find()->where(['id' => $post['id']])->one(); + $processRule->name = $post['name']; + $processRule->calc_method = $post['calc_method']; + $processRule->price = $post['price']; + $processRule->unit = $post['unit']; + $res = $processRule->saveOrFail(); + if(!$res){ + throw new \Exception('更新加工规则失败'); + } + return ['success']; + } + + public function actionUpdateNote(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['note', 'required'], + ['id','required'] + + ]); + $processRuleNote = ProcessRuleNote::find()->where(['id' => $post['id']])->one(); + $processRuleNote->note = $post['note']; + $res = $processRuleNote->saveOrFail(); + if(!$res){ + throw new \Exception('更新加工规则备注失败'); + } + return ['success']; + } + + + public function actionDelete(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id','required'] + ]); + $processRule = ProcessRule::find()->where(['id' => $post['id']])->one(); + if(!$processRule){ + throw new \Exception("规则不存在"); + } + if($processRule->pid){ + $processRuleNote = new ProcessRuleNote(); + $processRuleNote->rule_id = $processRule->id; + $processRuleNote->delete(); + } + $processRule->delete(); + return ['success']; + } + + public function actionDeleteNote(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id','required'] + ]); + $processRuleNote = ProcessRuleNote::find()->where(['id' => $post['id']])->one(); + if(!$processRuleNote){ + throw new \Exception("规则备注不存在"); + } + $processRuleNote->delete(); + return ['success']; + } + +} \ No newline at end of file diff --git a/admin/controllers/store/StoreController.php b/admin/controllers/store/StoreController.php new file mode 100644 index 0000000..ed00ac0 --- /dev/null +++ b/admin/controllers/store/StoreController.php @@ -0,0 +1,335 @@ +request->get(); + $this->requestValidate($get, [ + ['store_id', 'required'] + ]); + $query = DrugStoreRelations::find()->alias('ds')->where(['ds.store_id' => $get['store_id']]); + $query->joinWith(['drug' => function ($d) { + $d->andWhere(['type' =>[ 2,4]]); + }]); + + if (!empty($get['status'])) { + $query->andWhere(['ds.status' => $get['status']]); + } + + $this->field = [ + DrugStoreRelations::class => [ + 'id', 'drug_id', + 'type' => 'drug.type', + 'name' => 'drug.drug_name', + 'pinyin_simple' => 'drug.pinyin_simple', + 'is_otc' => 'drug.is_otc', + 'store_price' => 'price', + 'drugstore_price' => 'drugStoreDrug.price', + 'market_price' => 'drugStoreDrug.market_price', + 'stock' => 'drugStoreDrug.stock', + 'buy_price', + 'store_status' => 'status', + 'drugstore_status' => 'drugStoreDrug.status', + 'image' => 'drug.image', + 'is_forbid' + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 门店设置西药价格 + * @doc-param int store_id 门店ID + * @doc-param int drug_id 药品ID + * @doc-param float price 销售价 / optional + */ + public function actionUpdatePrice() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['store_id', 'drug_id'], 'required'] + ]); + + $DrugStoreDrug = DrugStoreDrug::find()->where([ + 'drug_id' => $post['drug_id'] + ])->one(); + if (!$DrugStoreDrug) throw new Exception('仓库中没有该药品'); + +// if ($DrugStoreDrug->type == 1 || $DrugStoreDrug->type == 3) throw new Exception('您不能修改中药或配方颗粒的销售价格'); + $DrugStoreRelations = DrugStoreRelations::find()->where([ + 'store_id' => $post['store_id'], + 'drug_id' => $post['drug_id'], + ])->one(); + if (!$DrugStoreRelations) throw new Exception('门店没有该药品'); + + $DrugStoreRelations->price = $post['price'] ?? $DrugStoreRelations->price; + if (!$DrugStoreRelations->saveOrFail()) throw new Exception('修改失败'); + + return ['修改成功']; + } + + /** + * @doc-name 门店设置上下架 + * @doc-param int store_id 门店ID + * @doc-param int drug_id 药品ID + * @doc-param int status 1下架2上架 + */ + public function actionUpdateStatus() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['store_id', 'drug_id', 'status'], 'required'] + ]); + + $DrugStoreRelations = DrugStoreRelations::find()->where([ + 'store_id' => $post['store_id'], + 'drug_id' => $post['drug_id'], + ])->one(); + if (!$DrugStoreRelations) throw new Exception('门店中药品不存在'); + + $DrugStoreRelations->status = $post['status']; + + if (!$DrugStoreRelations->saveOrFail()) { + throw new Exception('修改失败'); + } + + return ['修改成功']; + } + + /** + * @doc-name 添加子账号 + * @doc-param string mobile 手机号 + * @doc-param string role 角色 + * @doc-param string password 密码 + * @doc-param string username 用户名 + * @doc-param int store_id 门店 + */ + public function actionAddAccount() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['mobile', 'password', 'username','store_id','role'], 'required'] + ]); + + $admin = \Yii::$app->user->identity; + + $t = \Yii::$app->db->beginTransaction(); + try { + $is_admin = Admin::find()->where([ + 'mobile' => $post['mobile'], + 'is_delete' => 0 + ])->one(); + + if ($is_admin) throw new Exception('该账号已注册过'); + if (! Store::find()->where(['id'=>$post['store_id']])->one()){ + throw new Exception('门店不存在'); + } + if (! Role::find()->where(['id'=>$post['role']])->one()){ + throw new Exception('角色不存在'); + } + + $model = new Admin(); + $model->is_sub = 1;//子账号 + $model->mobile = $post['mobile']; + $model->role = $post['role']; + $model->username = $post['username']; + $model->store_id = $post['store_id']; + $model->setPassword($post['password']); + $model->role = $admin->role; + $model->store_id = $admin->store_id ?? ''; + $model->saveOrFail(); + + $token = AdminAccessToken::createToken($model->id, 'admin'); + $t->commit(); + + return [ + 'token' => $token, + 'user' => Admin::findOne($model->uid), + ]; + } catch (\yii\db\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 门店设置自己的销售比例 + * @doc-param float store_set_sale_z 门店自己设置中药销售比例 + * @doc-param float store_set_sale_g 门店自己设置配方颗粒的销售比例 + */ + public function actionStoreSetPercent() + { + $post = \Yii::$app->request->post(); + + $admin = \Yii::$app->user->identity; + if ($admin->role != UserRoleEnum::STORE_ADMIN) { + throw new Exception('你不是门店管理员'); + } + $Store = Store::find()->where(['id' => $admin->store_id])->one(); + $t = \Yii::$app->db->beginTransaction(); + try { + $Store->z_sale_percent = $post['store_set_sale_z'] ?? $Store->z_sale_percent; + $Store->g_sale_percent = $post['store_set_sale_g'] ?? $Store->g_sale_percent; + $Store->store_set_sale_z = $post['store_set_sale_z'] ?? $Store->store_set_sale_z; + $Store->store_set_sale_g = $post['store_set_sale_g'] ?? $Store->store_set_sale_g; + $Store->saveOrFail(); + + if (!empty($post['store_set_sale_z'])) { + $chinese = DrugStoreDrug::find()->select(['drug_id'])->where(['type' => 1])->column(); + $chinese_price = DrugStoreDrug::find()->select(['drug_id', 'market_price','price'])->where(['type' => 1])->all(); + + $DrugStoreRelations = DrugStoreRelations::find()->select(['id', 'drug_id'])->where([ + 'store_id' => $admin->store_id, + ])->andWhere(['in','drug_id',$chinese])->all(); + + foreach ($DrugStoreRelations as $val) { + foreach ($chinese_price as $v) { + if ($val['drug_id'] == $v['drug_id']) { + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', ['price' =>bcdiv(bcmul($post['store_set_sale_z'],$v['price'],4) ,100,4)], ['id' => $val['id']])->execute(); + } + } + } + } + + if (!empty($post['store_set_sale_g'])) { + $granular= DrugStoreDrug::find()->select(['drug_id'])->where(['type' => 3])->column(); + $granular_price = DrugStoreDrug::find()->select(['drug_id', 'market_price','price'])->where(['type' => 3])->all(); + + $DrugStoreRelations = DrugStoreRelations::find()->select(['id', 'drug_id'])->where([ + 'store_id' => $admin->store_id, + ])->andWhere(['in','drug_id',$granular])->all(); + + foreach ($DrugStoreRelations as $val) { + foreach ($granular_price as $v) { + if ($val['drug_id'] == $v['drug_id']) { + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', ['price' =>bcdiv(bcmul( $post['store_set_sale_g'],$v['price'],4) ,100,4) ], ['id' => $val['id']])->execute(); + } + } + } + } + + $t->commit(); + return ['设置成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + + } + } + + /** + * @doc-name 设置是否开启查看毛利率 + * @doc-param int store_id 门店id + */ + public function actionSeeRate() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['store_id','required'] + ]); + $admin = \Yii::$app->user->identity; + if ($admin->role != UserRoleEnum::STORE_ADMIN) { + throw new Exception('你不是门店管理员'); + } + $Store = Store::find()->where(['id' => $get['store_id']])->one(); + if (!$Store) throw new Exception('诊所不存在'); + $t = \Yii::$app->db->beginTransaction(); + try { + + $Store->see_rate=$Store->see_rate==0? 1:0; + $Store->saveOrFail(); + $t->commit(); + + return [$Store->see_rate==0?'关闭':'开启']; + }catch (\Exception $exception){ + $t->rollBack(); + throw new $exception; + } + } + /** + * @doc-name 门店查看是否开启毛利 + * @doc-param int store_id 门店id + */ + public function actionIsSeeRate() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['store_id','required'] + ]); + $admin = \Yii::$app->user->identity; + if ($admin->role != UserRoleEnum::STORE_ADMIN) { + throw new \yii\db\Exception('你不是门店管理员'); + } + $Store = Store::find()->where(['id' => $get['store_id']])->one(); + if (!$Store) throw new \yii\base\Exception('诊所不存在'); + return $Store; + } + + /** + * @doc-name 平台控制门店西药是否禁售 + * @doc-param int store_id 门店id + * @doc-param int drug_id 药品id + */ + public function actionSetDrugStatus() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + [['store_id','drug_id'],'required'] + ]); + + $Drug=Drug::find()->where(['id'=>$get['drug_id']])->one(); + if (!$Drug) throw new Exception('药品不存在'); + + $DrugStoreRelations=DrugStoreRelations::find()->where(['store_id'=>$get['store_id'],'drug_id'=>$get['drug_id']])->one(); + if (!$DrugStoreRelations) throw new Exception('门店没有该药品'); + + $DrugStoreRelations->is_forbid=$DrugStoreRelations->is_forbid==0?1 :0; + if ($DrugStoreRelations->is_forbid==1){//禁售 + $DrugStoreRelations->status=1;//下架 + }else{//在售 + $DrugStoreRelations->status=2;//上架 + } + $DrugStoreRelations->saveOrFail(); + + return [ $DrugStoreRelations->is_forbid==1?'禁售':'在售']; + } + + /** + * @doc-name 查看门店信息 + */ + public function actionSeeStorePercent() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['store_id','required'] + ]); + $Store = Store::find()->select(['z_buy_percent','z_sale_percent','g_bug_percent','g_sale_percent'])->where(['id' => $get['store_id'],'is_delete'=>0])->one(); + if (!$Store) throw new Exception('门店不存在'); + return $Store; + } +} \ No newline at end of file diff --git a/admin/controllers/store/WareController.php b/admin/controllers/store/WareController.php new file mode 100644 index 0000000..79fec92 --- /dev/null +++ b/admin/controllers/store/WareController.php @@ -0,0 +1,628 @@ +request->get(); + $name = $get['name']; + + $query = DrugStoreDrug::find()->alias('ds'); + + $query->joinWith(['drug' => function ($d) use ($name) { + if (!empty($name)) { + $d->andWhere([ + 'or', + ['like', 'drug_name', $name], + ['like', 'pinyin_simple', $name], + ['like', 'pinyin_simple', $name], + ]); + } + }]); + + if (!empty($get['type'])) { + $query->andWhere(['ds.type' => $get['type']]); + } + + if (!empty($get['status'])) { + $query->andWhere(['ds.status' => $get['status']]); + } + + $this->field = [ + DrugStoreDrug::class => [ + 'id', 'drug_id', 'type', 'stock', 'price', 'market_price', 'status', + 'name' => 'drug.drug_name', + 'image' => 'drug.image', + 'pinyin_simple' => 'drug.pinyin_simple', + 'is_otc' => 'drug.is_otc','drug_number'=>'drug.drug_number', + 'drug_alias'=>'drug.drug_alias', + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 添加仓库商品 + * @doc-param int drug_id 药id + * @doc-param int type 药品类型 1中药 2西药 3颗粒药 4中成药 + * @doc-param float price 销售价格 + * @doc-param float market_price 市场价格 + * @doc-param int stock 库存 + */ + public function actionSaveWareDrug() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['drug_id', 'type', 'price', 'stock'], 'required'] + ]); + + $DrugStoreDrug = DrugStoreDrug::find()->where([ + 'drugstore_id' => 1, + 'drug_id' => $post['drug_id'], + ])->one(); + if ($DrugStoreDrug) throw new Exception('已存在,请勿重复添加'); + + if ($post['type']==1 || $post['type']==3 ){ + if (empty($post['market_price'])){ + throw new Exception('市场价格不能为空'); + } + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $drug = new DrugStoreDrug(); + $drug->drugstore_id = 1;//仓库默认为1 + $drug->drug_id = $post['drug_id']; + $drug->type = $post['type']; + $drug->price = $post['price']; + $drug->market_price = $post['market_price']??0; + $drug->stock = $post['stock']; + $drug->saveOrFail(); + + $Store = Store::find()->select(['id','z_buy_percent','z_sale_percent','g_bug_percent','g_sale_percent','store_set_sale_z','store_set_sale_g'])->where(['is_delete' => 0])->all(); + + if ($post['type']==1){ + foreach ($Store as $val) { + if (!empty($val['store_set_sale_z'])){ + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->drug_id = $post['drug_id']; + $DrugStoreRelations->store_id = $val['id']; + $DrugStoreRelations->price =bcdiv(bcmul($post['price'], $val['store_set_sale_z']??100, 4), 100, 4);//销售价 + $DrugStoreRelations->buy_price = bcdiv(bcmul($post['market_price'], $val['z_buy_percent']??100, 4), 100, 4);//进货(采购)价 + $DrugStoreRelations->status = 2;//上架 + $DrugStoreRelations->created_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->updated_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->saveOrFail(); + }else{ + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->drug_id = $post['drug_id']; + $DrugStoreRelations->store_id = $val['id']; + $DrugStoreRelations->price =bcdiv(bcmul($post['price'], $val['z_sale_percent']??100, 4), 100, 4);//销售价 + $DrugStoreRelations->buy_price = bcdiv(bcmul($post['market_price'], $val['z_buy_percent']??100, 4), 100, 2);//进货(采购)价 + $DrugStoreRelations->status = 2;//上架 + $DrugStoreRelations->created_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->updated_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->saveOrFail(); + } + } + } + if ($post['type']==3){ + foreach ($Store as $val){ + if (!empty($val['store_set_sale_g'])){ + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->drug_id = $post['drug_id']; + $DrugStoreRelations->store_id = $val['id']; + $DrugStoreRelations->price =bcdiv(bcmul($post['price'], $val['store_set_sale_g']??100, 4), 100, 4);//销售价 + $DrugStoreRelations->buy_price = bcdiv(bcmul($post['market_price'], $val['g_bug_percent']??100, 4), 100, 4);//进货(采购)价 + $DrugStoreRelations->status = 2;//上架 + $DrugStoreRelations->created_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->updated_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->saveOrFail(); + }else{ + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->drug_id = $post['drug_id']; + $DrugStoreRelations->store_id = $val['id']; + + $DrugStoreRelations->price =bcdiv(bcmul($post['price'], $val['g_sale_percent']??100, 4), 100, 4);//销售价 + $DrugStoreRelations->buy_price = bcdiv(bcmul($post['market_price'], $val['g_bug_percent']??100, 4), 100, 4);//进货(采购)价 + $DrugStoreRelations->status = 2;//上架 + $DrugStoreRelations->created_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->updated_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->saveOrFail(); + } + } + + } + if ($post['type']==2|| $post['type']==4){ + foreach ($Store as $val) { + $DrugStoreRelations = new DrugStoreRelations(); + $DrugStoreRelations->drug_id = $post['drug_id']; + $DrugStoreRelations->store_id = $val['id']; + $DrugStoreRelations->price =$post['price'];//销售价 + $DrugStoreRelations->buy_price = $post['market_price']??$post['price'];//进货(采购)价 + $DrugStoreRelations->status = 2;//上架 + $DrugStoreRelations->created_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->updated_at = date('Y-m-d H:i:s', time()); + $DrugStoreRelations->saveOrFail(); + } + } + + $t->commit(); + return ['添加成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 仓库上架下架 + * @doc-param int drug_id 药品ID + * @doc-param int type 类型1中药2西药3颗粒配方4中成药 + * @doc-param int status 1下架2上架 + */ + public function actionIsSale() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['drug_id', 'type', 'status'], 'required'] + ]); + $DrugStoreDrug = DrugStoreDrug::find()->where([ + 'drug_id' => $post['drug_id'], + 'drugstore_id' => 1, + 'type' => $post['type'], + ])->one(); + if (!$DrugStoreDrug) { + throw new Exception('药品不存在'); + } + $t = \Yii::$app->db->beginTransaction(); + try { + $DrugStoreDrug->status= $post['status']; + $DrugStoreDrug->saveOrFail(); + + $ids = DrugStoreRelations::find()->select(['id'])->where([ + 'drug_id' => $post['drug_id'] + ])->column(); + DrugStoreRelations::updateAll(['status' => $post['status']], ['id' => $ids]);//修改门店 + + $t->commit(); + return ['success']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 修改仓库价格 + * @doc-param int drug_id 药品ID + * @doc-param int type 类型1中药2西药3颗粒配方4中成药 + * @doc-param float price 销售价 / optional + * @doc-param int stock 库存 / optional + * @doc-param float market_price 市场价 / optional + */ + public function actionUpdateDrugstorePrice() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['drug_id', 'type'], 'required'] + ]); + + $DrugStoreDrug = DrugStoreDrug::find()->where([ + 'drugstore_id' => 1, + 'drug_id' => $post['drug_id'], + 'type' => $post['type'], + ])->one(); + if (!$DrugStoreDrug) throw new Exception('药品不存在'); + + $t = \Yii::$app->db->beginTransaction(); + try { + $DrugStoreDrug->price = $post['price'] ?? $DrugStoreDrug->price; + $DrugStoreDrug->stock = $post['stock'] ?? $DrugStoreDrug->stock; + $DrugStoreDrug->market_price = $post['market_price'] ?? $DrugStoreDrug->market_price; + $DrugStoreDrug->saveOrFail(); + + switch ($post['type']) { + case 1://中药 + $DrugStoreRelations = DrugStoreRelations::find()->where(['drug_id' => $post['drug_id']])->asArray()->all(); + if ($DrugStoreRelations) { + foreach ($DrugStoreRelations as $val) { + $store = Store::find()->where(['id' => $val['store_id']])->one(); + + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', + ['price' =>bcdiv(bcmul($store['z_sale_percent']??100,$DrugStoreDrug->price,4),100,4), + 'buy_price' =>bcdiv(bcmul($store['z_buy_percent']??100,$DrugStoreDrug->market_price,4),100,4)], + ['drug_id' => $val['drug_id'], 'store_id' => $val['store_id']])->execute(); + } + } + break; + + case 2://西药 + $DrugStoreRelations = DrugStoreRelations::find()->where(['drug_id' => $post['drug_id']])->asArray()->all(); + + if ($DrugStoreRelations) { + foreach ($DrugStoreRelations as $val) { + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', + ['price' =>$DrugStoreDrug->price, + 'buy_price' => $DrugStoreDrug->market_price??0], + ['drug_id' => $val['drug_id'], 'store_id' => $val['store_id']])->execute(); + } + } + + break; + case 3://配方颗粒 + + $DrugStoreRelations = DrugStoreRelations::find()->where(['drug_id' => $post['drug_id']])->asArray()->all(); + if ($DrugStoreRelations) { + foreach ($DrugStoreRelations as $val) { + $store = Store::find()->where(['id' => $val['store_id']])->one(); + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', + ['price' =>bcdiv(bcmul($store['g_sale_percent']??100,$DrugStoreDrug->price,4),100,4), + 'buy_price' =>bcdiv(bcmul($store['g_buy_percent']??100,$DrugStoreDrug->market_price,4),100,4)], + ['drug_id' => $val['drug_id'], 'store_id' => $val['store_id']])->execute(); + } + } + break; + case 4://中成药 + $DrugStoreRelations = DrugStoreRelations::find()->where(['drug_id' => $post['drug_id']])->asArray()->all(); + if ($DrugStoreRelations) { + foreach ($DrugStoreRelations as $val) { + + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', + ['price' =>$DrugStoreDrug->price, + 'buy_price' => $DrugStoreDrug->market_price??$DrugStoreDrug->price], + ['drug_id' => $val['drug_id'], 'store_id' => $val['store_id']])->execute(); + } + } + break; + default: + throw new Exception('参数错误'); + } + + + $t->commit(); + return ['修改成功']; + + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + + } + + /** + * @doc-name 仓库修改门店西药价格 + * @doc-param int store_id 门店id + * @doc-param int drug_id 药品ID + * @doc-param float price 销售价 / optional + * @doc-param float buy_price 采购价 / optional + */ + public function actionUpdatePrice() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['store_id', 'drug_id'], 'required'] + ]); + + if (empty($post['drug_id'])) { + throw new Exception('药品ID不能为空'); + } + $DrugStoreRelations = DrugStoreRelations::find()->where([ + 'store_id' => $post['store_id'], + 'drug_id' => $post['drug_id'] + ])->one(); + if (!$DrugStoreRelations) throw new Exception('药品不存在'); + $DrugStoreRelations->price = $post['price'] ?? $DrugStoreRelations->price; + $DrugStoreRelations->buy_price = $post['buy_price'] ?? $DrugStoreRelations->buy_price; + if (!$DrugStoreRelations->saveOrFail()) throw new Exception('修改失败'); + return ['修改成功']; + + } + + /** + * @doc-name 仓库修改门店比例(中药/配方颗粒) + * @doc-param int store_id 门店ID + * @doc-param int type 类别1中药3配方颗粒 + * @doc-return string z_buy_percent 中药采购比例 / optional + * @doc-return string z_sale_percent 中药销售比例 / optional + * @doc-return string g_bug_percent 配方颗粒采购比例 / optional + * @doc-return string g_sale_percent 配方颗粒销售比例 / optional + */ + public function actionEditPercent() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['store_id', 'type'], 'required'] + ]); + + switch ($post['type']) { + case 1: + $beginTransaction = \Yii::$app->db->beginTransaction(); + try { + $Store = Store::find()->where([ + 'id' => $post['store_id'] + ])->one(); + if (!$Store) throw new Exception('门店不存在'); + $Store->z_buy_percent = $post['z_buy_percent'] ?? $Store->z_buy_percent; + $Store->z_sale_percent = $post['z_sale_percent'] ?? $Store->z_sale_percent; + $Store->saveOrFail(); + + $chinese = DrugStoreDrug::find()->select(['drug_id'])->where(['type' => 1])->column(); + + $chinese_price = DrugStoreDrug::find()->select(['drug_id', 'market_price','price'])->where(['type' => 1])->all(); + $DrugStoreRelations_chinese = DrugStoreRelations::find()->select(['id', 'drug_id'])->where([ + 'store_id' => $post['store_id'], + ])->andWhere(['in', 'drug_id', $chinese])->all(); + + foreach ($DrugStoreRelations_chinese as $val) { + foreach ($chinese_price as $v) { + if ($val['drug_id'] == $v['drug_id']) { + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', + ['price' =>bcdiv(bcmul($post['z_sale_percent'] ??100,$v['price'],4),100,4) , + 'buy_price' =>bcdiv(bcmul($post['z_buy_percent'] ??100,$v['market_price'],4),100,4)], + ['id' => $val['id']])->execute(); + } + } + } + $beginTransaction->commit(); + return ['修改成功']; + } catch (\Exception $e) { + $beginTransaction->rollBack(); + throw new Exception($e->getMessage()); + } + break; + case 3: + try { + $t = \Yii::$app->db->beginTransaction(); + $Store = Store::find()->where([ + 'id' => $post['store_id'] + ])->one(); + + if (!$Store) throw new Exception('门店不存在'); + $Store->g_bug_percent = $post['g_bug_percent'] ?? $Store->g_bug_percent; + $Store->g_sale_percent = $post['g_sale_percent'] ?? $Store->g_sale_percent; + $Store->saveOrFail(); + + $grain = DrugStoreDrug::find()->select(['drug_id'])->where(['type' => 3])->column(); + $grain_price = DrugStoreDrug::find()->select(['drug_id', 'market_price','price'])->where(['type' => 3])->all(); + + $DrugStoreRelations_grain = DrugStoreRelations::find()->select(['id', 'drug_id'])->where([ + 'store_id' => $post['store_id'], + ])->andWhere(['in', 'drug_id', $grain])->all(); + + foreach ($DrugStoreRelations_grain as $value) { + foreach ($grain_price as $vv) { + if ($value['drug_id'] == $vv['drug_id']) { + + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', + ['price' =>bcdiv(bcmul($post['g_sale_percent'] ??100,$vv['price'],4),100,4), + 'buy_price' =>bcdiv(bcmul($post['g_bug_percent']??100 ,$vv['market_price'],4),100,4)], + ['id' => $value['id']])->execute(); + } + } + } + $t->commit(); + return ['修改成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + break; + default: + throw new Exception('参数错误'); + } + } + + /** + * @doc-name 仓库查看比例 + * @doc-param int store_id 门店ID + * @doc-return string z_buy_percent 中药采购比例 + * @doc-return string z_sale_percent 中药销售比例 + * @doc-return string g_bug_percent 配方颗粒采购比例 + * @doc-return string g_sale_percent 配方颗粒销售比例 + */ + public function actionPercent() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['store_id', 'required'] + ]); + + $Store = Store::find()->where([ + 'id' => $get['store_id'] + ])->one(); + if (!$Store) { + throw new Exception('门店不存在'); + } + return $Store; + } + + + /** + * @doc-name 仓库发货 + * @doc-param int order_id 商品(或产品)订单id + * @doc-param string express_company_name 快递公司 / optional + * @doc-param string express_company_code 公司编码 + * @doc-param string express_no 快递单号 + * @doc-param string mobile 手机号码 / optional + * @doc-param string state 物流状态 / optional + */ + public function actionWareSend() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['order_id', 'express_company_code', 'express_no'], 'required'] + ]); + $user = \Yii::$app->user->identity; + + // if ($user->role != UserRoleEnum::SUPER_ADMIN) { + // throw new Exception('您不是超管,没有发货权限'); + // } + $ProductOrder = ProductOrder::find()->where([ + 'id' => $post['order_id'] + ])->one(); + if (!$ProductOrder) throw new Exception('产品订单不存在'); + if($ProductOrder->is_online == 1 && $ProductOrder->online_prescription_status != 1){ + throw new Exception('处方暂未审核,无法发货'); + } + $t = \Yii::$app->db->beginTransaction(); + try { + //快递单号信息 + $ExpressNos = new ExpressNos(); + $ExpressNos->express_company_name = $post['express_company_name']; + $ExpressNos->express_company_code = $post['express_company_code']; + $ExpressNos->express_no = $post['express_no']; + $ExpressNos->mobile = $post['mobile']; + $ExpressNos->state = $post['state']; + $ExpressNos->sync_at = null; + $ExpressNos->created_at = date('Y-m-d H:i:s', time()); + $ExpressNos->updated_at = date('Y-m-d H:i:s', time()); + $ExpressNos->saveOrFail(); + + + + +// $result = json_decode($response->getBody(), true); + + + $ProductOrder->is_send = 1; + $ProductOrder->status = 2; + $ProductOrder->send_time = date('Y-m-d H:i:s', time()); + $ProductOrder->express_no_id = $ExpressNos->attributes['id']; + $ProductOrder->saveOrFail(); + + $log = new Log(); + $log->admin_id = $user->uid; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '仓库发货'; + $log->mold = 2;//订单操作 + $log->content = $user->uid . '操作仓库发货:'; + $log->save(); + + //订单发货自动结算 + \Yii::$app->queue->push(new ProductOrderSend([ + 'orderId' => $ProductOrder->id, + ])); + + //订单自动收货- 发货7天后 + $config = \Yii::$app->params; + $orderAutoReceivedTime = isset($config['product_order']['received_time']) ? $config['product_order']['received_time'] : 7*24*3600; + \Yii::$app->queue->delay($orderAutoReceivedTime)->push(new ProductOrderAutoReceived([ + 'orderId' => $ProductOrder->id + ])); + + + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + //订单发货3天后分账结算 + // if($ProductOrder->type == 2){ //易票联支付的产品订单 + // $config = \Yii::$app->params; + // $orderAutoSettlementTime = isset($config['product_order']['settlement_time']) ? $config['product_order']['settlement_time'] : 72*3600; + // \Yii::$app->queue->delay($orderAutoSettlementTime)->push(new ProductOrderSendJob([ + // 'orderId' => $ProductOrder->id + // ])); + // } + +// //触发订单发货事件-3天后分账结算 +// $event = new ProductOrderEvent(); +// $event->order = $ProductOrder; +// $event->sender = $this; +// \Yii::$app->trigger(ProductOrder::EVENT_SEND, $event); + + $t->commit(); + + (new Client(['http_errors' => false]))->get("https://shop.xiaokang88.com/t/express_update", [ + 'query' => [ + 'id' => $ExpressNos->id, + ], + ]); + + return ['发货成功']; + } catch (\Exception $exception) { + $t->rollBack(); + throw new Exception($exception->getMessage()); + } + } + + /** + * @doc-name 快递公司 + * @doc-return mixed @List{id,name-string-公司名称,code-string-公司编码,type-string-公司类型,sort-int-排序} 快递公司 + * @doc-return mixed @Pagination{total-int-总数量,totalPage-int-总页数,pageSize-int-每页条数} 分页数据 + */ + public function actionExpressCompanyList() + { + $get = \Yii::$app->request->get(); + $query = ExpressCompanies::find()->orderBy(['sort' => SORT_ASC]); + $this->field = [ + ExpressCompanies::class => [ + 'id', 'name', 'code', 'type', 'sort' + ] + ]; + return $this->create($query, $get); + } + + /** + * @doc-name 修改物流 + * @doc-param int express_no_id 快递单号信息ID + * @doc-param string express_company_name 公司名称 / optional + * @doc-param string express_company_code 公司编码 / optional + * @doc-param string express_no 快递单号 / optional + * @doc-param string mobile 手机号码 / optional + * @doc-param int state 物流状态0揽收1揽收2疑难4退签5派件6退回7转投8清关14拒签 / optional + */ + public function actionUpdateExpressNos() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['express_no_id', 'required','message'=>'快递单号信息ID不能为空'] + ]); + + $ExpressNos=ExpressNos::find()->where(['id'=>$post['express_no_id']])->one(); + if (!$ExpressNos) throw new Exception('物流信息不存在'); + + $ExpressNos->express_company_name=$post['express_company_name']??$ExpressNos->express_company_name; + $ExpressNos->express_company_code=$post['express_company_code']?? $ExpressNos->express_company_code; + $ExpressNos->express_no=$post['express_no']??$ExpressNos->express_no; + $ExpressNos->mobile=$post['mobile']??$ExpressNos->mobile; + $ExpressNos->state=$post['state']??$ExpressNos->state; + $ExpressNos->saveOrFail(); + + (new Client(['http_errors' => false]))->get("https://shop.xiaokang88.com/t/express_update", [ + 'query' => [ + 'id' => $ExpressNos->id, + ], + ]); + return ['修改成功']; + } +} \ No newline at end of file diff --git a/admin/controllers/system/AdminController.php b/admin/controllers/system/AdminController.php new file mode 100644 index 0000000..a771ccd --- /dev/null +++ b/admin/controllers/system/AdminController.php @@ -0,0 +1,91 @@ +addRule('aa',DateRangeValidator::class); + //$m->addRule('xx','string'); + $m->addRule('page','default',['value'=>1]); + $m->addRule('pageSize','default',['value'=>10]); + $m->addRule('page','integer',['max'=>1000]); + $m->addRule('pageSize','integer',['min'=>1,'max'=>50]); + $m->load($this->post()); + if(!$m->validate()){ + throw new Exception(json_encode($m->getFirstErrors())); + } + $query = Admin::find(); + + $dataProvider = new ActiveDataProvider([ + 'query' => $query, + 'sort'=>[ + 'defaultOrder'=>['uid'=>SORT_DESC] + ], + 'pagination'=>[ + 'defaultPageSize'=>$m->pageSize, + 'params'=>['page'=>$m->page] + ] + ]); + // add conditions that should always apply here + + return $dataProvider; + } + /** + * 账号信息 + */ + public function actionInfo() + { + $admin= \Yii::$app->user->identity; + + if ($admin->role==UserRoleEnum::SUPER_ADMIN){ + $info= Admin::find()->where(['uid'=>$admin->uid,'role'=>UserRoleEnum::SUPER_ADMIN])->one(); + } + if ($admin->role==UserRoleEnum::STORE_ADMIN){ + $info= Store::find()->where(['id'=>$admin->store_id,'is_delete'=>0])->one(); + } + + if (!$info) throw new \yii\db\Exception('账号信息不存在'); + return $info; + } + + /** + * @doc-name 账号禁用 + * @doc-param int admin_id 后台用户ID + */ + public function actionAccountDisabled() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['admin_id', 'required'] + ]); + $role=\Yii::$app->user->identity->role; + if ($role!=UserRoleEnum::SUPER_ADMIN) throw new \yii\db\Exception('非超级管理员,没有禁用账号的权限'); + $Admin = Admin::find()->where([ + 'uid' => $post['admin_id'], + ])->one(); + if (!$Admin) throw new \yii\db\Exception('账号不存在'); + + + $status=$Admin->status==1?0:1; + $Admin->status=$status; + $Admin->saveOrFail(); + return ['修改成功']; + } + +} diff --git a/admin/controllers/system/AttachmentController.php b/admin/controllers/system/AttachmentController.php new file mode 100644 index 0000000..607faa4 --- /dev/null +++ b/admin/controllers/system/AttachmentController.php @@ -0,0 +1,172 @@ +['nodeName'=>'fileManage']]; + return $this->render('index'); + } + public function actionGroupList($type = null, $is_recycle = null) + { + $params = $this->requestValidate($this->get(),[ + ['is_recycle','integer'], + ['type','string'] + ]); + $query = AttachmentGroup::find()->where([ + 'mall_id' => \Yii::$app->mallId, + 'is_delete' => 0, + ]); + + isset($params->type) || $query->andWhere(['type' => $params->type === 'video' ? 1 : 0]); + + return $query->all(); + } + + public function actionDo(){ + $params = $this->requestValidate($this->get(),[ + ['type','in','range'=>['folder-create','files','folder-delete','folder']], + ['keyword','string'], + ['name','string'], + ['id','integer'], + ['page','integer'] + ]); + /** + * upload: props.uploadUrl, + list: props.fileUrl + '?type=files', + del: props.fileUrl + '?type=files-delete', + cateList: props.fileUrl + '?type=folder', + cateAdd: props.fileUrl + '?type=folder-create', + cateDel: props.fileUrl + '?type=folder-delete' + */ + switch ($params->type){ + case 'folder': + $activeRecords = AttachmentGroup::find()->where(['mall_id' => \Yii::$app->mallId])->andWhere(['is_delete' => 0])->all(); + return ArrayHelper::toArray($activeRecords,[ + AttachmentGroup::class=>[ + 'dir_id'=>'id','name' + ] + ]); + break; + case 'folder-create'; + $attachmentGroup = new AttachmentGroup(); + $attachmentGroup->setAttributes([ + 'mall_id'=>\Yii::$app->mallId, + 'name'=>$params->name, + ]); + if($attachmentGroup->save()){ + return ['id'=>$attachmentGroup->id,'name'=>$attachmentGroup->name]; + }else{ + return ['error'=>$attachmentGroup->getErrors()]; + } + break; + case 'folder-delete'; + Attachment::updateAll(['is_delete'=>1,'deleted_at'=>time()],['attachment_group_id'=>$params->id,'mall_id'=>\Yii::$app->mallId]); + AttachmentGroup::updateAll(['is_delete'=>1,'deleted_at'=>time()],['id'=>$params->id,'mall_id'=>\Yii::$app->mallId]); + return []; + break; + case 'files': + $query = Attachment::find()->where(['mall_id' => \Yii::$app->mallId])->andWhere(['is_delete' => 0])->orderBy('id desc');; + if(isset($params->id) && $params->id>0) { + $query->andWhere(['attachment_group_id'=>$params->id]); + } + $query->andFilterWhere(['like','name',$params->keyword]); + $this->field = [ + Attachment::class=>[ + 'id', + 'title'=>'name', + 'url', + 'ext'=>function($m){ + $implode = explode('.', $m['name']); + return mb_strtolower(array_pop($implode)); + }, + 'time'=>function($model){ + return date("Y-m-d H:i:s",$model['created_at']); + }, + 'size'=>function($model){ + return app_filesize($model['size']); + }, + ] + ]; + $post = array_merge(\Yii::$app->request->post(),\Yii::$app->request->get()); + return $this->create($query,$post); + break; + + + } + } + + public function actionUpload(){ + $params = $this->requestValidate($this->post(),[ + ['id','integer'], + ['id','default','value'=>0], + ['file','file'] + ]); + + $form = new AttachmentUploadForm(); + $form->file = UploadedFile::getInstanceByName('file'); + $form->attachment_group_id = $params->id; + return $form->save(); + } + + /** + * @doc-name oss直传-保存上传信息 + * @doc-param int attachment_group_id 上传的分组 + * @doc-param string name 上传的文件名称 + * @doc-param int size 上传的文件大小 + * @doc-param string url 上传的文件链接 + */ + public function actionSave() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + [['attachment_group_id','name','size','url'],'required'] + ]); + $ext = pathinfo($post['url'])['extension']; + $type = (new AttachmentUploadForm())->checkExt($ext); + + $attachment = new Attachment(); + $attachment->attributes = $post; + $attachment->storage_id = 0; + $attachment->user_id = 0; + $attachment->type = $type; + $attachment->mall_id = \Yii::$app->mallId; + $attachment->thumb_url = $post['url']; + $attachment->saveOrFail(); + return $attachment; + } + + /** + * @doc-name oss直传-获取上传参数 + */ + public function actionParams() + { + $callbackUrl = \Yii::$app->request->hostInfo.'/api/v1/callback/upload-notify'; + $dir = \Yii::$app->mallId ? 'uploads/' . \Yii::$app->mallId.'/' . date('Ymd').'/' : 'uploads/' . date('Ymd').'/'; + + $data = [ + 'callbackUrl' => $callbackUrl, + 'dir' => $dir + ]; + return (new UploadService())->redirectFile($data); + } +} \ No newline at end of file diff --git a/admin/controllers/system/ConfigController.php b/admin/controllers/system/ConfigController.php new file mode 100644 index 0000000..265393c --- /dev/null +++ b/admin/controllers/system/ConfigController.php @@ -0,0 +1,167 @@ +field = $this->_listMap(); + return $searchModel->search(Yii::$app->request->queryParams); + } + + /** + * 保存配置项 + */ + public function actionSave() + { + $id = Yii::$app->request->get('id', 0); + $model = $this->findModel($id); + if ($model->load($this->post(),'') && $model->save()) { + $event = 'add'; + if($id>0){ + $event = 'edit'; + } + $this->callbackEvent(ArrayHelper::toArray([$model],$this->_listMap()),'id',$event); + return []; + }else{ + throw new Exception(current($model->getErrors())[0]); + } + } + + /** + * 配置项详情1 + * @doc-param int id ID + * @doc-return mixed @Config{name,type-int-配置类型0数字1字符2文本3数组4单选5富文本6多选,title,group,extra,remark,value,sort,status,created_at} 配置信息 + */ + public function actionInfo() + { + $post = Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $config = Config::findOne($post['id']); + if ($config['extra']) { + $config['extra'] = Config::parse(3, $config['extra']); + } + return $config; + } + + /** + * 删除配置项 + */ + public function actionDel() + { + $id = (int)$this->get('id'); + if($id<1){ + throw new \Exception('删除失败!'); + } + if(in_array($id,[1])){ + throw new \Exception('禁止删除!'); + } + $model = $this->findModel($id); + if ($model->delete()) { + $this->callbackEvent([$model->toArray()],'id','del'); + return []; + } else { + throw new \Exception('删除失败!'); + } + } + + /** + * 配置 + * @doc-desc 20处理成number,1是text,2textarea,3textarea,4select或者radio,5富文本,6多选 + * @doc-return mixed Data{name-string-分组名称,@Groups{Config{name,type-int-配置类型0数字1字符2文本3数组4单选5富文本6多选,title,group,extra,remark,value,sort,status}}} 配置数据 + */ + public function actionGroup() + { + $config = \common\models\Config::find()->where([ + 'name' => 'GROUP' + ])->one(); + $tab_groups = Config::parse(3, $config['value']); + + $data = []; + foreach($tab_groups as $id => $group) + { + $groups = Config::find() + ->where(['and', ['group' => $id], ['status' => 1]]) + ->orderBy('sort ASC')->asArray()->all(); + foreach ($groups as $key => $value) { + if ($value['extra']) { + $groups[$key]['extra'] = Config::parse(3, $value['extra']); + } + } + $data[$id] = [ + 'name' => $group, + 'groups' => $groups, + ]; + } + return $data; + } + + /** + * 配置保存 + * @doc-param array param 提交的修改数据[配置项name=>配置项的值,配置项name=>配置项的值] + */ + public function actionGroupSave() + { + $data = Yii::$app->request->post('param'); + /* 更改配置值 */ + $isSuccess = true; + foreach ($data as $name => $value) { + $model = Config::findOne(['name' => $name]); + $model->value = $value; + $model->update_time = time(); + if (!$model->save()) { + $isSuccess = false; + continue; + } + } + if ($isSuccess) { + return []; + } else { + throw new Exception('有配置值修改失败'); + } + } + + protected function findModel($id) + { + if ($id == 0) { + return new Config(); + } + if (($model = Config::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } + + private function _listMap() + { + return [ + Config::class=>[ + 'id','title','name', + 'type'=>function($m){ + return Yii::$app->params['config_type'][$m->type]; + }, + 'group','sort','status' + ] + ]; + } +} diff --git a/admin/controllers/system/DeliveryController.php b/admin/controllers/system/DeliveryController.php new file mode 100644 index 0000000..5ae9e7b --- /dev/null +++ b/admin/controllers/system/DeliveryController.php @@ -0,0 +1,135 @@ +model(); + $table->title('角色管理'); + $table->key('id'); + $table->eventName(md5(get_called_class()));//设置事件名,后面更改数据对应 + $table->url(\Yii::$app->urlManager->createUrl("system/delivery/postage-rule-list")); + $table->filter('配置名', 'name',false)->text('请输入配置名')->quick(); + $table->action()->button('添加', $this->createUrl('system/delivery/postage-edit')); + $table->column('规则名','name'); + $table->column('是否默认','status')->status(['否','是'],['gray','red']); + $column = $table->column('操作')->width(200); + $column->link('设为默认',$this->createUrl('system/delivery/postage-status'), ['id' => 'id'])->type('ajax', ['method' => 'post']); + $column->link('编辑', $this->createUrl('system/delivery/postage-edit'), ['id' => 'id']); + $column->link('删除', $this->createUrl('system/delivery/postage-del'), ['id' => 'id'])->type('ajax', ['method' => 'post']); + return $table->renderArray(); + } + public function actionPostageStatus(){ + $params = $this->requestValidate($this->get(),[ + ['id','required'], + ['id','integer'] + ]); + $this->callbackEvent([],'id','refresh'); + return PostageRules::setStatus($params->id); + } + public function actionPostageRuleList() + { + $commonSearch = new CommonSearch(['name']); + $commonSearch->setQuery(PostageRules::find() + ->select(['id', 'name', 'status']) + ->where(['mall_id'=>\Yii::$app->mallId])->andWhere(['is_delete'=>0])); + $commonSearch->additionRules = [ + ['name', 'string'] + ]; + $commonSearch->bindFilter(function(/** @var ActiveQuery $q */ $q) { + $q->andFilterWhere(['like','name',$this->name]); + }); + return $commonSearch->search($this->get()); + + } + public function actionPostageInfo(){ + $id = $this->get('id'); + $model = PostageRules::findOne([ + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + 'id' => $id + ]); + if (!$model) { + $model = new PostageRules(); + $model->mall_id = \Yii::$app->mallId; + } else { + $model->detail = $model->decodeDetail(); + } + + return [ + 'model' => $model, + ]; + } + public function actionPostageEditSave(){ + $id = $this->get('id'); + $model = PostageRules::findOne([ + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + 'id' => $id + ]); + if (!$model) { + $model = new PostageRules(); + $model->mall_id = \Yii::$app->mallId; + } else { + $model->detail = $model->decodeDetail(); + } + $form = new PostageRulesEditForm(); + $form->attributes = \Yii::$app->request->post('form'); + $form->model = $model; + return $form->save(); + } + public function actionPostageEdit(){ + return $this->render('postage-edit'); + } + + public function actionAllList(){ + $allList = PostageRules::find()->where([ + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + ])->select('id as value,name as label')->asArray()->all(); + foreach ($allList as &$v){ + $v['value'] = (int)$v['value']; + } + unset($v); + array_unshift($allList, [ + 'value' => 0, + 'label' => '默认运费' + ]); + + return [ + 'list' => $allList + ]; + } + + public function actionPostageDel(){ + $id = $this->get('id'); + if(PostageRules::updateAll(['is_delete'=>1],['id'=>$id,'mall_id'=>\Yii::$app->mallId])){ + $this->callbackEvent([],'id','refresh'); + return []; + }else{ + throw new ApiException("删除失败"); + } + } +} diff --git a/admin/controllers/system/DistrictController.php b/admin/controllers/system/DistrictController.php new file mode 100644 index 0000000..a0ca1b5 --- /dev/null +++ b/admin/controllers/system/DistrictController.php @@ -0,0 +1,39 @@ +request->isPost) { + $level = $this->post('level',3); + } elseif (\Yii::$app->request->isGet) { + $level = $this->get('level',3); + } + switch ($level) { + case 3: + $level = null; + break; + case 2: + $level = 'district'; + break; + case 1: + $level = 'city'; + break; + default: + $level = null; + } + $list = DistrictArr::getArr(); + $district = DistrictArr::getList($list, $level); + return [ + 'district' => $district + ]; + } +} diff --git a/admin/controllers/system/FreeRuleController.php b/admin/controllers/system/FreeRuleController.php new file mode 100644 index 0000000..90d51c8 --- /dev/null +++ b/admin/controllers/system/FreeRuleController.php @@ -0,0 +1,140 @@ +model(); + $table->title('包邮设置'); + $table->key('id'); + $table->eventName(md5(get_called_class()));//设置事件名,后面更改数据对应 + $table->url(\Yii::$app->urlManager->createUrl("system/free-rule/list")); + $table->filter('规则名称', 'name',false)->text('请输入配置名')->quick(); + $table->action()->button('添加', $this->createUrl('system/free-rule/edit')); + $table->column('规则名称','name'); + $table->column('包邮类型','typeText'); + $table->column('是否默认','status')->status(['否','是'],['gray','red']); + $column = $table->column('操作')->width(200); + $column->link('设为默认',$this->createUrl('system/free-rule/status'), ['id' => 'id'])->type('ajax', ['method' => 'post']); + $column->link('编辑', $this->createUrl('system/free-rule/edit'), ['id' => 'id']); + $column->link('删除', $this->createUrl('system/free-rule/del'), ['id' => 'id'])->type('ajax', ['method' => 'post']); + return $table->renderArray(); + } + public function actionEdit(){ + return $this->render('edit'); + } + public function actionStatus(){ + $params = $this->requestValidate($this->get(),[ + ['id','required'], + ['id','integer'] + ]); + $this->callbackEvent([],'id','refresh'); + return FreeDeliveryRules::setStatus($params->id); + } + public function actionInfo(){ + $id = $this->get('id'); + $model = FreeDeliveryRules::findOne([ + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + 'id' => $id + ]); + if (!$model) { + $model = new FreeDeliveryRules(); + $model->mall_id = \Yii::$app->mallId; + } else { + $model->detail = $model->decodeDetail(); + } + + return [ + 'model' => $model, + ]; + } + public function actionEditSave(){ + $id = $this->get('id'); + $model = FreeDeliveryRules::findOne([ + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + 'id' => $id + ]); + if (!$model) { + $model = new FreeDeliveryRules(); + $model->mall_id = \Yii::$app->mallId; + } else { + $model->detail = $model->decodeDetail(); + } + $form = new FreeRuleEditForm(); + $form->attributes = \Yii::$app->request->post('form'); + $form->model = $model; + return $form->save(); + } + public function actionList() + { + $commonSearch = new CommonSearch(['name']); + $commonSearch->setQuery(FreeDeliveryRules::find() + ->select(['id', 'name', 'type','status']) + ->where(['mall_id'=>\Yii::$app->mallId])->andWhere(['is_delete'=>0])); + $commonSearch->additionRules = [ + ['name', 'string'] + ]; + $commonSearch->bindFilter(function(/** @var ActiveQuery $q */ $q) { + $q->andFilterWhere(['like','name',$this->name]); + }); + $this->field = [ + FreeDeliveryRules::class=>[ + 'id','name','type','status','typeText' + ] + ]; + return $commonSearch->search($this->get()); + + } + public function actionAllList(){ + $allList = FreeDeliveryRules::find()->where([ + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + ])->select('id as value,name as label')->asArray()->all(); + foreach ($allList as &$v){ + $v['value'] = (int)$v['value']; + } + unset($v); + array_unshift($allList, [ + 'value' => 0, + 'label' => '默认包邮规则' + ]); + + return [ + 'list' => $allList + ]; + } + + public function actionDel(){ + $id = $this->get('id'); + if(FreeDeliveryRules::updateAll(['is_delete'=>1],['id'=>$id,'mall_id'=>\Yii::$app->mallId])){ + $this->callbackEvent([],'id','refresh'); + return []; + }else{ + throw new ApiException("删除失败"); + } + } +} diff --git a/admin/controllers/system/GeneratorController.php b/admin/controllers/system/GeneratorController.php new file mode 100644 index 0000000..e84ca45 --- /dev/null +++ b/admin/controllers/system/GeneratorController.php @@ -0,0 +1,117 @@ +db; + if ($db === null) { + return []; + } + $tableNames = []; + //if (strpos($this->tableName, '*') !== false) { + // if (($pos = strrpos($this->tableName, '.')) !== false) { + // $schema = substr($this->tableName, 0, $pos); + // $pattern = '/^' . str_replace('*', '\w+', substr($this->tableName, $pos + 1)) . '$/'; + // } else { + // $schema = ''; + // $pattern = '/^' . str_replace('*', '\w+', $this->tableName) . '$/'; + // } + $schema = ''; + + foreach ($db->schema->getTableNames($schema) as $table) { + $tableNames[] = $schema === '' ? $table : ($schema . '.' . $table); + } + //} elseif (($table = $db->getTableSchema($this->tableName, true)) !== null) { + // $tableNames[] = $this->tableName; + // $this->classNames[$this->tableName] = $this->modelClass; + //} + + return $tableNames; + } + public function actionFields(){ + $tableName = $this->post('table_name'); + $db = \Yii::$app->db; + if ($db === null) { + return []; + } + $tableSchema = $db->getTableSchema($tableName); + return $tableSchema->columns; + } + + public function actionConfig(){ + return [ + 'controllerClass'=>'backend\controllers\\', + 'baseControllerClass'=>'backend\components\BaseBackendController', + 'actionIds'=>'list,save,info,del', + 'vuePath'=>'/Users/chatfeed/arco-work/', + 'controllerNamespace'=>'backend\controllers\\', + ]; + } + public function actionGenerate(){ + //model generate + $modelGen = new Generator(); + $modelGen->setAttributes( + [ + 'db'=>'db', + 'useTablePrefix'=>$this->post('useTablePrefix'), + 'ns'=>'common\modelsgii', + 'tableName'=>$this->post('table_name'), + 'baseClass'=>'common\core\BaseActiveRecord', + 'queryNs'=>'common\models', + ], + ); + $modelClass = $modelGen->generateClassName($this->post('table_name')); + $files = $modelGen->generate(); + //controller 生成 + $conGEn = new \backend\generators\controller\Generator(); + $conGEn->setAttributes([ + 'controllerClass'=>$this->post('controllerClass'), + 'baseClass'=>$this->post('baseControllerClass'), + 'actions'=>$this->post('actionIds'), + 'controllerNamespace'=>$this->post('controllerNamespace') + ]); + $files = $conGEn->generate(); + foreach ($files as $f){ + $f->save(); + } + //vue生成 + $vueGen = new \backend\generators\vue\Generator(); + $vueGen->setAttributes([ + 'className'=>$modelClass, + 'vuePath'=>$this->post('vuePath'), + 'columns'=>$this->post('columns'), + 'pagePath'=>$this->post('pagePath'), + 'apiPath'=>$conGEn->getControllerSubPath().$conGEn->getControllerID(), + 'actions'=>$this->post('actionIds'), + ]); + $files = $vueGen->generate(); + + foreach ($files as $f){ + $f->save(); + } + return $files; + } + + private function generatePHP(){ + + } +} diff --git a/admin/controllers/system/IndexController.php b/admin/controllers/system/IndexController.php new file mode 100644 index 0000000..005be79 --- /dev/null +++ b/admin/controllers/system/IndexController.php @@ -0,0 +1,127 @@ +where(['status'=>StatusEnum::ACTIVE])->orderBy('sort ASC')->asArray()->all(); + $configGroups = []; + foreach ($configs as $config){ + $configGroups[$config['group']][] = $config; + } + foreach (\Yii::$app->params['config_group'] as $idx=>$name){ + + } + + } + + + public function actionIndex(){ + $layout = new Layout("基础配置"); + $tabs = new Tabs(); + //return ['node'=>$layout->render(),'setupScript'=>"\n return {}"]; + //$data = []; + $layout->addChild(Widget::alert("非专业人士或不清楚选项请勿随意修改,否则可能会导致系统崩溃",'安全提示',function ($alert){ + return $alert->type('warning'); + })); + $configs = Config::find()->where(['status'=>StatusEnum::ACTIVE])->orderBy('sort ASC')->asArray()->all(); + $configGroups = []; + foreach ($configs as $config){ + $configGroups[$config['group']][] = $config; + } + foreach (\Yii::$app->params['config_group'] as $idx=>$name){ + $configGroup = isset($configGroups[$idx])?$configGroups[$idx]:[]; + if(!empty($configGroup)){ + $data = ArrayHelper::map($configGroup, 'name', 'value'); + $form = new Form($data); + $form->action(\Yii::$app->urlManager->createUrl('system/index/save')); + foreach ($configGroup as $config){ + $this->buildItem($form,$config); + } + $tabs->addTab($name,$idx,'',$form->renderFormWithoutNode()); + } + } + $layout->addChild($tabs->render()); + return $layout->render(); + } + + public function actionSave(){ + /* 表单验证 */ + $data =$this->post(); + + //var_dump($data);exit; + /* 更改配置值 */ + $error = []; + foreach ($data as $name => $value) { + $model = Config::findOne(['name' => $name]); + $model->value = (string)$value; + $model->update_time = time(); + if (!$model->save()) { + $error[$model->name] = $model->getFirstErrors(); + } + } + if (empty($error)) { + return []; + } else { + return ['error'=>$error]; + } + } + private function buildItem(Form $form,$config){ + //params config_type + /** + * 'config_type' => [ + 0 => '数字', + 1 => '字符', + 2 => '文本', + 3 => '数组', + 4 => '枚举', + 5 => '富文本' + ], + */ + switch ($config['type']){ + case 0: + case 1: + case 2: + $form->text($config['title'], $config['name'])->help($config['remark']); + break; + case 3: + $form->radio($config['title'],$config['name'],Config::parse(3,$config['extra']))->help($config['remark']); + break; + case 4: + $form->textarea($config['title'],$config['name'])->help($config['remark']); + break; + case 5: + $form->editor($config['title'],$config['name']); + //@todo + break; + } + } + private function _parseExtra($str){ + $explode = explode("\n", trim($str)); + $ret =[]; + foreach ($explode as $itemStr){ + list($name,$val) = explode(":",$itemStr); + $ret[$val] = $name; + } + return $ret; + } +} diff --git a/admin/controllers/system/MenuController.php b/admin/controllers/system/MenuController.php new file mode 100644 index 0000000..f811446 --- /dev/null +++ b/admin/controllers/system/MenuController.php @@ -0,0 +1,40 @@ +asArray()->all(); + return ArrayHelper::itemsMerge($menu2s,0,'menuUrl','parentPath','children'); + } + public function actionSave(){ + $menuUrl = $this->post('menuUrl'); + $model = Menu::findOne($menuUrl); + if(!$model){ + $model = new Menu(); + } + $model->load($this->post()); + if( $model->load($this->post(),'') && $model->save()){ + return $model->getAttributes(); + }else{ + throw new Exception("参数不对"); + } + } + + public function actionDel(){ + $menuUrl = $this->post('menuUrl'); + $model = Menu::findOne($menuUrl); + if($model->delete()){ + Menu::updateAll(['parentPath'=>''],['parentPath'=>$menuUrl]); + } + return []; + } +} \ No newline at end of file diff --git a/admin/controllers/system/RefundAddressController.php b/admin/controllers/system/RefundAddressController.php new file mode 100644 index 0000000..655ad3c --- /dev/null +++ b/admin/controllers/system/RefundAddressController.php @@ -0,0 +1,139 @@ +model(); + $table->title('退货地址'); + $table->key('id'); + $table->eventName(md5(get_called_class()));//设置事件名,后面更改数据对应 + $table->url(\Yii::$app->urlManager->createUrl("system/refund-address/list")); + $table->filter('关键字', 'keyword',false)->text('请输入收件人姓名或联系方式')->quick(); + $table->action()->button('添加', $this->createUrl('system/refund-address/edit'))->type('dialog'); + $table->column('ID','id'); + $table->column('收件人姓名','name'); + $table->column('详细地址','full_address'); + $table->column('备注','remark'); + $column = $table->column('操作')->width(200); + $column->link('编辑', $this->createUrl('system/refund-address/edit'), ['id' => 'id'])->type('dialog'); + $column->link('删除', $this->createUrl('system/refund-address/del'), ['id' => 'id'])->type('ajax', ['method' => 'post']); + return $table->renderArray(); + } + public function actionEdit(){ + $id = (int)$this->get('id'); + $config = $this->findModel($id); + $form = new Form($config->getAttributes(['id','name','mobile','address_id','address_detail','remark']),false); + $form->title('配置信息'); + $form->action($this->createUrl('system/refund-address/edit-save')); + $arr = DistrictArr::getArr(); + unset($arr['1']); + $form->card(function (/** @var Form $form */$form) use($arr) { + $form->text("收件人姓名",'name'); + $form->text("联系方式",'mobile'); + $form->cascader('省市区','address_id',$arr); + $form->textarea('详细地址','address_detail'); + $form->textarea('备注','remark'); + }); + return $form->renderArray(); + } + + public function actionDistrict() + { + $district_arr = DistrictArr::getArr(); + $arr = DistrictArr::getList($district_arr); + $str = str_replace('list','children',json_encode($arr)); + $arr = json_decode($str,true); + return $arr; + } + + + public function actionEditSave(){ + $id = $this->get('id'); + $model = RefundAddress::findOne([ + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + 'id' => $id + ]); + + if (!$model) { + $model = new RefundAddress(); + $model->mall_id = \Yii::$app->mallId; + } + $model->load($this->post(),''); + if($model->save()){ + $this->callbackEvent([],'id','refresh'); + return []; + }else{ + return ['error'=>$model->getErrors()]; + } + } + + public function actionDel(){ + $id = $this->get('id'); + if(RefundAddress::updateAll(['is_delete'=>1],['id'=>$id,'mall_id'=>\Yii::$app->mallId])){ + $this->callbackEvent([],'id','refresh'); + return []; + }else{ + throw new ApiException("删除失败"); + } + } + + public function actionList() + { + $commonSearch = new CommonSearch(['keyword']); + $commonSearch->setQuery(RefundAddress::find() + ->select(['id', 'name','address','address_detail','remark']) + ->where(['mall_id'=>\Yii::$app->mallId])->andWhere(['is_delete'=>0])); + $commonSearch->additionRules = [ + ['keyword', 'string'] + ]; + $commonSearch->bindFilter(function(/** @var ActiveQuery $q */ $q) { + $q->andFilterWhere(['like','name',$this->keyword]); + }); + $this->field = [ + RefundAddress::class =>[ + 'id','name','full_address','remark' + ] + ]; + return $commonSearch->search($this->get()); + + } + protected function findModel($id) + { + if ($id == 0) { + return new RefundAddress(); + } + if (($model = RefundAddress::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } +} diff --git a/admin/controllers/system/RoleController.php b/admin/controllers/system/RoleController.php new file mode 100644 index 0000000..b355988 --- /dev/null +++ b/admin/controllers/system/RoleController.php @@ -0,0 +1,64 @@ +asArray()->all(); + return $roles; + } + public function actionSaveUserMenu(){ + $params = $this->requestValidate($this->post(),[ + ['role_id','required'], + ['role_id','integer'], + ['ids','required'] + ]); + if(is_array($params->ids)){ + $insert = []; + foreach ($params->ids as $id){ + $insert[] = [ + 'role_id'=>$params->role_id, + 'menuUrl'=>$id, + 'created_at'=>time(), + 'updated_at'=>time() + ]; + } + RoleMenu::deleteAll(['role_id'=>$params->role_id]); + RoleMenu::getDb()->createCommand()->batchInsert(RoleMenu::tableName(),array_keys($insert[0]),$insert)->execute(); + + } + return []; + } + + public function actionMenuByRoleId(){ + $params = $this->requestValidate($this->post(),[ + ['roleId','required'], + ]); + $roleMenus = RoleMenu::findAll(['role_id' => $params->roleId]); + $keys = ArrayHelper::getColumn($roleMenus,'menuUrl'); + $menus = Menu::find()->asArray()->all(); + return[ + 'menus'=>ArrayHelper::itemsMerge($menus,0,'menuUrl','parentPath','children'), + 'checked'=>$keys + ]; + + + } + public function actionDel(){ + $menuUrl = $this->post('menuUrl'); + $model = Menu::findOne($menuUrl); + if($model->delete()){ + Menu::updateAll(['parentPath'=>''],['parentPath'=>$menuUrl]); + } + return []; + } +} \ No newline at end of file diff --git a/admin/controllers/system/SubAccountController.php b/admin/controllers/system/SubAccountController.php new file mode 100644 index 0000000..84a1fb1 --- /dev/null +++ b/admin/controllers/system/SubAccountController.php @@ -0,0 +1,147 @@ +addRule('aa',DateRangeValidator::class); + //$m->addRule('xx','string'); + $m->addRule('page','default',['value'=>1]); + $m->addRule('pageSize','default',['value'=>10]); + $m->addRule('page','integer',['max'=>1000]); + $m->addRule('pageSize','integer',['min'=>1,'max'=>50]); + $m->load($this->post()); + if(!$m->validate()){ + throw new Exception(json_encode($m->getFirstErrors())); + } + $query = Admin::find()->where(['is_sub'=>1])->andWhere([ + 'role'=>\Yii::$app->user->identity->role, + 'mall_id'=>\Yii::$app->user->identity->mall_id, + 'is_delete'=>0 + ]); + + $this->field = [ + Admin::class => [ + 'uid','username','mobile','last_login_time','last_login_ip'=>function($m){ + return $m->last_login_ip ? long2ip($m->last_login_ip) : ''; + } + ] + ]; + + $dataProvider = new ActiveDataProvider([ + 'query' => $query, + 'sort'=>[ + 'defaultOrder'=>['uid'=>SORT_DESC] + ], + 'pagination'=>[ + 'defaultPageSize'=>$m->pageSize, + 'params'=>['page'=>$m->page] + ] + ]); + // add conditions that should always apply here + + return $dataProvider; + } + + public function actionSave(){ + $id = (int)$this->get('id'); + $model = $this->findModel($id); + $data = $this->post(); + $data['password'] = \Yii::$app->security->generatePasswordHash($data['password']); + $data['role'] = \Yii::$app->user->identity->role; + $data['mall_id'] = \Yii::$app->user->identity->mall_id; + $data['is_sub'] = 1; + $data['last_login_ip'] = isset($data['last_login_ip']) && $data['last_login_ip'] ? ip2long($data['last_login_ip']) : 0; + if($model->load($data,'') && $model->save()){ + return []; + }else{ + throw new Exception("保存失败:".current($model->getFirstErrors())); + } + } + + public function actionMenuByUid(){ + $params = $this->requestValidate($this->post(),[ + ['admin_id','required'], + ]); + $roleMenus = RoleMenu::findAll(['role_id' => \Yii::$app->user->identity->role]); + $roleKeys = ArrayHelper::getColumn($roleMenus,'menuUrl'); + $menus = Menu::find()->where(['in','menuUrl',$roleKeys])->asArray()->all(); + $userMenus = SubAccountMenu::findAll(['admin_id'=>$params->admin_id]); + $keys = ArrayHelper::getColumn($userMenus,'menuUrl'); + return[ + 'menus'=>ArrayHelper::itemsMerge($menus,0,'menuUrl','parentPath','children'), + 'checked'=>$keys + ]; + } + + public function actionDel(){ + $params = $this->requestValidate($this->post(),[ + ['admin_id','required'] + ]); + $model = $this->findModel($params->admin_id); + if(!$model || $model->is_sub!==1){ + throw new Exception("账号不存在"); + } + $model->delete(); +// $model->updateAttributes(['is_delete'=>1]); + return []; + } + public function actionSaveMenu(){ + $params = $this->requestValidate($this->post(),[ + ['admin_id','required'], + ['admin_id','integer'], + ['ids','required'] + ]); + if(is_array($params->ids)){ + $insert = []; + foreach ($params->ids as $id){ + $insert[] = [ + 'admin_id'=>$params->admin_id, + 'menuUrl'=>$id, + 'created_at'=>time(), + 'updated_at'=>time() + ]; + } + SubAccountMenu::deleteAll(['admin_id'=>$params->admin_id]); + SubAccountMenu::getDb()->createCommand()->batchInsert(SubAccountMenu::tableName(),array_keys($insert[0]),$insert)->execute(); + + } + return []; + } + + /** + * @param $id + * @return ActiveRecord + * @throws NotFoundHttpException + */ + protected function findModel($id) + { + if ($id == 0) { + return new $this->modelClass(); + } + if (($model = $this->modelClass::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } + +} diff --git a/admin/exceptions/ApiException.php b/admin/exceptions/ApiException.php new file mode 100644 index 0000000..e78a0e1 --- /dev/null +++ b/admin/exceptions/ApiException.php @@ -0,0 +1,5 @@ +code); + + } +} diff --git a/admin/foundation/Cors.php b/admin/foundation/Cors.php new file mode 100644 index 0000000..88b7e17 --- /dev/null +++ b/admin/foundation/Cors.php @@ -0,0 +1,279 @@ + [ + * 'class' => \yii\filters\Cors::className(), + * ], + * ]; + * } + * ``` + * + * The CORS filter can be specialized to restrict parameters, like this, + * [MDN CORS Information](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) + * + * ```php + * public function behaviors() + * { + * return [ + * 'corsFilter' => [ + * 'class' => \yii\filters\Cors::className(), + * 'cors' => [ + * // restrict access to + * 'Origin' => ['http://www.myserver.com', 'https://www.myserver.com'], + * // Allow only POST and PUT methods + * 'Access-Control-Request-Method' => ['POST', 'PUT'], + * // Allow only headers 'X-Wsse' + * 'Access-Control-Request-Headers' => ['X-Wsse'], + * // Allow credentials (cookies, authorization headers, etc.) to be exposed to the browser + * 'Access-Control-Allow-Credentials' => true, + * // Allow OPTIONS caching + * 'Access-Control-Max-Age' => 3600, + * // Allow the X-Pagination-Current-Page header to be exposed to the browser. + * 'Access-Control-Expose-Headers' => ['X-Pagination-Current-Page'], + * ], + * + * ], + * ]; + * } + * ``` + * + * For more information on how to add the CORS filter to a controller, see + * the [Guide on REST controllers](guide:rest-controllers#cors). + * + * @author Philippe Gaultier + * @since 2.0 + */ +class Cors extends ActionFilter +{ + /** + * @var Request the current request. If not set, the `request` application component will be used. + */ + public $request; + /** + * @var Response the response to be sent. If not set, the `response` application component will be used. + */ + public $response; + /** + * @var array define specific CORS rules for specific actions + */ + public $actions = []; + /** + * @var array Basic headers handled for the CORS requests. + */ + public $cors = [ + 'Origin' => ['*'], + 'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], + 'Access-Control-Request-Headers' => ['*'], + 'Access-Control-Allow-Credentials' => null, + 'Access-Control-Max-Age' => 86400, + 'Access-Control-Expose-Headers' => [], + ]; + + + /** + * {@inheritdoc} + */ + public function beforeAction($action) + { + + $this->request = $this->request ?: Yii::$app->getRequest(); + $this->response = $this->response ?: Yii::$app->getResponse(); + $this->overrideDefaultSettings($action); + $requestCorsHeaders = $this->extractHeaders(); + $responseCorsHeaders = $this->prepareHeaders($requestCorsHeaders); + $this->addCorsHeaders($this->response, $responseCorsHeaders); + if ($this->request->isOptions && $this->request->headers->has('Access-Control-Request-Method')) { + // it is CORS preflight request, respond with 200 OK without further processing + $this->response->setStatusCode(200); + Yii::$app->end(); + + return false; + } + + return true; + } + + /** + * Override settings for specific action. + * @param \yii\base\Action $action the action settings to override + */ + public function overrideDefaultSettings($action) + { + if (isset($this->actions[$action->id])) { + $actionParams = $this->actions[$action->id]; + $actionParamsKeys = array_keys($actionParams); + foreach ($this->cors as $headerField => $headerValue) { + if (in_array($headerField, $actionParamsKeys)) { + $this->cors[$headerField] = $actionParams[$headerField]; + } + } + } + } + + /** + * Extract CORS headers from the request. + * @return array CORS headers to handle + */ + public function extractHeaders() + { + $headers = []; + foreach (array_keys($this->cors) as $headerField) { + $serverField = $this->headerizeToPhp($headerField); + $headerData = isset($_SERVER[$serverField]) ? $_SERVER[$serverField] : null; + if ($headerData !== null) { + $headers[$headerField] = $headerData; + } + } + + return $headers; + } + + /** + * For each CORS headers create the specific response. + * @param array $requestHeaders CORS headers we have detected + * @return array CORS headers ready to be sent + */ + public function prepareHeaders($requestHeaders) + { + $responseHeaders = []; + // handle Origin + if (isset($requestHeaders['Origin'], $this->cors['Origin'])) { + if (in_array($requestHeaders['Origin'], $this->cors['Origin'], true)) { + $responseHeaders['Access-Control-Allow-Origin'] = $requestHeaders['Origin']; + } + + if (in_array('*', $this->cors['Origin'], true)) { + // Per CORS standard (https://fetch.spec.whatwg.org), wildcard origins shouldn't be used together with credentials + if (isset($this->cors['Access-Control-Allow-Credentials']) && $this->cors['Access-Control-Allow-Credentials']) { + if (YII_DEBUG) { + throw new InvalidConfigException("Allowing credentials for wildcard origins is insecure. Please specify more restrictive origins or set 'credentials' to false in your CORS configuration."); + } else { + Yii::error("Allowing credentials for wildcard origins is insecure. Please specify more restrictive origins or set 'credentials' to false in your CORS configuration.", __METHOD__); + } + } else { + $responseHeaders['Access-Control-Allow-Origin'] = '*'; + } + } + } + + $this->prepareAllowHeaders('Headers', $requestHeaders, $responseHeaders); + + if (isset($requestHeaders['Access-Control-Request-Method'])) { + $responseHeaders['Access-Control-Allow-Methods'] = implode(', ', $this->cors['Access-Control-Request-Method']); + } + + if (isset($this->cors['Access-Control-Allow-Credentials'])) { + $responseHeaders['Access-Control-Allow-Credentials'] = $this->cors['Access-Control-Allow-Credentials'] ? 'true' : 'false'; + } + + if (isset($this->cors['Access-Control-Max-Age']) && $this->request->getIsOptions()) { + $responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age']; + } + + if (isset($this->cors['Access-Control-Expose-Headers'])) { + $responseHeaders['Access-Control-Expose-Headers'] = implode(', ', $this->cors['Access-Control-Expose-Headers']); + } + + if (isset($this->cors['Access-Control-Allow-Headers'])) { + $responseHeaders['Access-Control-Allow-Headers'] = implode(', ', $this->cors['Access-Control-Allow-Headers']); + } + + return $responseHeaders; + } + + /** + * Handle classic CORS request to avoid duplicate code. + * @param string $type the kind of headers we would handle + * @param array $requestHeaders CORS headers request by client + * @param array $responseHeaders CORS response headers sent to the client + */ + protected function prepareAllowHeaders($type, $requestHeaders, &$responseHeaders) + { + $requestHeaderField = 'Access-Control-Request-' . $type; + $responseHeaderField = 'Access-Control-Allow-' . $type; + if (!isset($requestHeaders[$requestHeaderField], $this->cors[$requestHeaderField])) { + return; + } + if (in_array('*', $this->cors[$requestHeaderField])) { + $responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]); + } else { + $requestedData = preg_split('/[\\s,]+/', $requestHeaders[$requestHeaderField], -1, PREG_SPLIT_NO_EMPTY); + $acceptedData = array_uintersect($requestedData, $this->cors[$requestHeaderField], 'strcasecmp'); + if (!empty($acceptedData)) { + $responseHeaders[$responseHeaderField] = implode(', ', $acceptedData); + } + } + } + + /** + * Adds the CORS headers to the response. + * @param Response $response + * @param array $headers CORS headers which have been computed + */ + public function addCorsHeaders($response, $headers) + { + if (empty($headers) === false) { + $responseHeaders = $response->getHeaders(); + foreach ($headers as $field => $value) { + $responseHeaders->set($field, $value); + } + } + } + + /** + * Convert any string (including php headers with HTTP prefix) to header format. + * + * Example: + * - X-PINGOTHER -> X-Pingother + * - X_PINGOTHER -> X-Pingother + * @param string $string string to convert + * @return string the result in "header" format + */ + protected function headerize($string) + { + $headers = preg_split('/[\\s,]+/', $string, -1, PREG_SPLIT_NO_EMPTY); + $headers = array_map(function ($element) { + return str_replace(' ', '-', ucwords(strtolower(str_replace(['_', '-'], [' ', ' '], $element)))); + }, $headers); + return implode(', ', $headers); + } + + /** + * Convert any string (including php headers with HTTP prefix) to header format. + * + * Example: + * - X-Pingother -> HTTP_X_PINGOTHER + * - X PINGOTHER -> HTTP_X_PINGOTHER + * @param string $string string to convert + * @return string the result in "php $_SERVER header" format + */ + protected function headerizeToPhp($string) + { + return 'HTTP_' . strtoupper(str_replace([' ', '-'], ['_', '_'], $string)); + } +} diff --git a/admin/foundation/JsonResponseFormatter.php b/admin/foundation/JsonResponseFormatter.php new file mode 100644 index 0000000..3435840 --- /dev/null +++ b/admin/foundation/JsonResponseFormatter.php @@ -0,0 +1,119 @@ +getHeaders()->set('Content-Type', 'text/plain; charset=UTF-8'); + //$response->getHeaders()->set("Access-Control-Allow-Origin","*"); + if ($response->data !== null) { + $options = $this->encodeOptions; + if ($this->prettyPrint) { + $options |= JSON_PRETTY_PRINT; + } + $errcode = 0; + $msg = ''; + $data = []; + if (!$response->isSuccessful) { + $response->statusCode = 200; + $errcode = -1; + if (Yii::$app->errorHandler->exception) { + // if(Yii::$app->errorHandler->exception instanceof ) + if (isset(Yii::$app->errorHandler->exception->statusCode)) { + $errcode = Yii::$app->errorHandler->exception->statusCode; + } elseif (Yii::$app->errorHandler->exception->getCode() > 0) { + $errcode = Yii::$app->errorHandler->exception->getCode(); + } else { + $errcode = $this->defaultErrorCode; + } + $msg = YII_DEBUG ? Yii::$app->errorHandler->exception->getMessage() : '服务器内部错误'; + } + } else { + $data = $response->data; + } + + $response->data = self::formatData($data, $errcode, $msg); + // var_dump($response->data);exit; + // if(!$response->isSuccessful){ + // $response->statusCode = 200; + // if($response->data['code']>20000) + // $code = $response->data['code']; + // else + // $code = ErrorCode::APP_EXCEPTION; + // $redirect = ''; + // $response->data = BController::ApiResponse([],$response->data['message'],$code,$redirect); + // } + // if(isset(Yii::$app->params['response_encrpyt']) && Yii::$app->params['response_encrpyt']){ + // $encryption = new MCrypt(); + // $response->content = $encryption->encrypt(Json::encode($response->data, $options)); + // }else{ + $response->content = Json::encode($response->data, $options); + // } + + } + } + + /** + * Formats response data in JSONP format. + * @param \yii\web\Response $response + */ + protected function formatJsonp($response) + { + $response->getHeaders()->set('Content-Type', 'application/javascript; charset=UTF-8'); + if ($response->data !== null) { + $options = $this->encodeOptions; + if ($this->prettyPrint) { + $options |= JSON_PRETTY_PRINT; + } + if (!$response->isSuccessful) { + $response->statusCode = 200; + if ($response->data['code'] > 20000) + $code = $response->data['code']; + else + $code = $this->defaultErrorCode; + $redirect = ''; + // $response->data = BController::ApiResponse([],$response->data['message'],$code,$redirect); + } + // if(isset(Yii::$app->params['response_encrpyt']) && Yii::$app->params['response_encrpyt']){ + // $encryption = new MCrypt(); + // $response->content = $encryption->encrypt(Json::encode($response->data, $options)); + // }else{ + // $response->content = Json::encode($response->data, $options); + // } + + } + $response->data = ['data' => $response->data, 'callback' => Yii::$app->getRequest()->get('callback')]; + if (is_array($response->data) && isset($response->data['data'], $response->data['callback'])) { + $response->content = sprintf('%s(%s);', $response->data['callback'], Json::htmlEncode($response->data['data'])); + } elseif ($response->data !== null) { + $response->content = ''; + Yii::warning("The 'jsonp' response requires that the data be an array consisting of both 'data' and 'callback' elements.", __METHOD__); + } + } +} diff --git a/admin/foundation/Serializer.php b/admin/foundation/Serializer.php new file mode 100644 index 0000000..5127db9 --- /dev/null +++ b/admin/foundation/Serializer.php @@ -0,0 +1,128 @@ +response->format == Response::FORMAT_RAW) { + return $data; + } + if ($data instanceof Model && $data->hasErrors()) { + throw new InvalidArgumentException('参数错误。' . implode('', $data->getFirstErrors())); + // $data = $this->serializeModelErrors($data); + } elseif ($data instanceof Arrayable) { + $data = $this->serializeModel($data); + } elseif ($data instanceof DataProviderInterface) { + $data = $this->serializeDataProvider($data); + } elseif ($data === null) { + $data = []; + } + + return $data; + // return array_merge($this->extend_result,$data); + } + + /** + * Serializes the validation errors in a model. + * @param Model $model + * @return array the array representation of the errors + */ + protected function serializeModelErrors($model) + { + $result = []; + foreach ($model->getFirstErrors() as $name => $message) { + $result[] = [ + 'field' => $name, + 'message' => $message, + ]; + } + + return $result; + } + + /** + * Serializes a data provider. + * @param DataProviderInterface $dataProvider + * @return array the array representation of the data provider. + */ + protected function serializeDataProvider($dataProvider) + { + if (!empty($this->field)) { + $models = ArrayHelper::toArray($dataProvider->getModels(), $this->field); + } else { + $models = array_values($dataProvider->getModels()); + $models = $this->serializeModels($models); + } + $pagination = $dataProvider->getPagination(); + $result = [ + $this->listkey => $models, + ]; + if ($pagination !== false) { + return array_merge($result, $this->serializePagination($pagination)); + } + + return $result; + } + + /** + * Serializes a set of models. + * @param array $models + * @return array the array representation of the models + */ + protected function serializeModels(array $models) + { + foreach ($models as $i => $model) { + if ($model instanceof Arrayable) { + $models[$i] = $model->toArray(); + } elseif (is_array($model)) { + $models[$i] = ArrayHelper::toArray($model); + } + } + + return $models; + } + /** + * Serializes a model object. + * @param Arrayable $model + * @return array the array representation of the model + */ + protected function serializeModel($model) + { + return $model->toArray(); + } + + /** + * Serializes a pagination into an array. + * @param Pagination $pagination + * @return array the array representation of the pagination + * @see addPaginationHeaders() + */ + protected function serializePagination($pagination) + { + return [ + $this->pagekey => [ + 'total_count' => $pagination->totalCount, + 'page_count' => $pagination->getPageCount(), + 'current_page' => $pagination->getPage() + 1, + 'per_page' => $pagination->getPageSize(), + ], + ]; + } +} diff --git a/admin/models/.gitkeep b/admin/models/.gitkeep new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/admin/models/.gitkeep @@ -0,0 +1 @@ +* diff --git a/admin/models/Admin.php b/admin/models/Admin.php new file mode 100644 index 0000000..b28a2b6 --- /dev/null +++ b/admin/models/Admin.php @@ -0,0 +1,205 @@ +hasMany(AuthAssignment::className(), ['user_id' => 'uid']); + //} + + + /** + * 根据UID获取账号信息 + */ + public static function findIdentity($uid) + { + return static::findOne(['uid' => $uid, 'status' => self::STATUS_ACTIVE,'is_delete'=>0]); + } + + /** + * @inheritdoc + */ + public static function findIdentityByAccessToken($token, $type = null) + { + $adminAccessToken = AdminAccessToken::findOne(['access_token' => $token, 'status' => StatusEnum::ACTIVE]); + if($adminAccessToken){ + return self::findIdentity($adminAccessToken->admin_id); + } + return null; + } + + /** + * 根据用户名获取账号信息 + * + * @param string $username + * @return static|null + */ + public static function findByUsername($username) + { + return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE,'is_delete'=>0]); + } + + /** + * 根据用户名获取账号信息 + * + * @param string $username + * @return static|null + */ + public static function findByMobile($mobile) + { + return static::findOne(['mobile' => $mobile, 'status' => self::STATUS_ACTIVE,'is_delete'=>0]); + } + + /** + * Finds user by password reset token + * + * @param string $token password reset token + * @return static|null + */ + public static function findByPasswordResetToken($token) + { + if (!static::isPasswordResetTokenValid($token)) { + return null; + } + + return static::findOne([ + 'password' => $token, + 'status' => self::STATUS_ACTIVE, + 'is_delete'=>0 + ]); + } + + /** + * Finds out if password reset token is valid + * + * @param string $token password reset token + * @return boolean + */ + public static function isPasswordResetTokenValid($token) + { + if (empty($token)) { + return false; + } + + $timestamp = (int) substr($token, strrpos($token, '_') + 1); + $expire = Yii::$app->params['user.passwordResetTokenExpire']; + return $timestamp + $expire >= time(); + } + + /** + * @inheritdoc + */ + public function getId() + { + return $this->getPrimaryKey(); + } + + /** + * @inheritdoc + */ + public function getAuthKey() + { + return $this->salt; + } + + /** + * @inheritdoc + */ + public function validateAuthKey($authKey) + { + return $this->getAuthKey() === $authKey; + } + + /** + * 验证密码 + * + * @param string $password password to validate + * @return boolean if password provided is valid for current user + */ + public function validatePassword($password) + { + return Yii::$app->security->validatePassword($password, $this->password); + } + + /** + * 设置加密后的密码 + * + * @param string $password + */ + public function setPassword($password) + { + return $this->password = Yii::$app->security->generatePasswordHash($password); + } + + /** + * 设置密码干扰码 + */ + public function generateAuthKey() + { + $this->salt = Yii::$app->security->generateRandomString(); + } + + /** + * Generates new password reset token + */ + public function generatePasswordResetToken() + { + $this->password = Yii::$app->security->generateRandomString() . '_' . time(); + } + + /** + * Removes password reset token + */ + public function removePasswordResetToken() + { + $this->password = null; + } + + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } + + public function getRoles() + { + return $this->hasOne(Role::class,['id'=>'role']); + } + public function getProvince() + { + return $this->hasOne(Region::class,['id'=>'province_id']); + } + public function getCity() + { + return $this->hasOne(Region::class,['id'=>'city_id']); + } +} diff --git a/admin/models/Config.php b/admin/models/Config.php new file mode 100644 index 0000000..492b9e6 --- /dev/null +++ b/admin/models/Config.php @@ -0,0 +1,75 @@ + [ + 'class' => 'yii\behaviors\TimestampBehavior', + 'createdAtAttribute' => 'create_time', + 'updatedAtAttribute' => 'update_time', + 'value' => time(), + ], + ]; + } + + /** + * --------------------------------------- + * 获取 数据库中的 配置列表 + * @return array + * --------------------------------------- + */ + public static function lists(){ + $config = []; + $data = (new \yii\db\Query()) + ->select(['type', 'name', 'value']) + ->from(self::tableName()) + ->where(['status'=>1]) + ->all(); + if (!empty($data) && is_array($data)) { + foreach ($data as $key => $value) { + $config[$value['name']] = self::parse($value['type'], $value['value']); + } + } + return $config; + } + + /** + * --------------------------------------- + * 根据配置类型解析配置 + * @param integer $type 配置类型 + * @param string $value 配置值 + * @return mixed + * --------------------------------------- + */ + public static function parse($type, $value){ + switch ($type) { + case 3: //解析数组 + $array = preg_split('/[,;\r\n]+/', trim($value, ",;\r\n")); + if(strpos($value,':')){ + $value = []; + foreach ($array as $val) { + list($k, $v) = explode(':', $val); + $value[$k] = $v; + } + }else{ + $value = $array; + } + break; + } + return $value; + } +} diff --git a/admin/models/Menu.php b/admin/models/Menu.php new file mode 100644 index 0000000..0f28a1d --- /dev/null +++ b/admin/models/Menu.php @@ -0,0 +1,10 @@ + [ + 'class' => 'yii\behaviors\TimestampBehavior', + 'createdAtAttribute' => 'create_time', + 'updatedAtAttribute' => 'update_time', + 'value' => time(), + ], + ]; + } + + + +} diff --git a/admin/models/RegisterForm.php b/admin/models/RegisterForm.php new file mode 100644 index 0000000..7280fbc --- /dev/null +++ b/admin/models/RegisterForm.php @@ -0,0 +1,247 @@ + function ($model) { + return $this->role == UserRoleEnum::STORE_ADMIN; + }], + ['province_id', 'required', 'when' => function ($model) { + return $this->role == UserRoleEnum::PROVINCE_DAI; + }], + [['province_id','city_id'], 'required', 'when' => function ($model) { + return $this->role == UserRoleEnum::CITY_DAI; + }], + ]; + } + + public function attributeLabels() + { + return [ + 'username'=>'用户名', + 'mobile'=>'电话', + 'password'=>'密码', + 'role'=>'角色', + 'province_id'=>'省份', + 'city_id'=>'城市', + 'store_id'=>'门店', + 'bank_user_name'=>'开户人姓名', + 'bank_card'=>'银行卡号', + 'bank_name'=>'银行名称', + 'bank_account_type'=>'银行账户类型 1:对公,2:对私,5:存折', + 'bank_no'=>'银行联行号bank_account_type=1或5或非62开头的对私银行账户时必选', + ]; + } + + public function register() + { + if (!$this->validate()) { + throw new \yii\base\Exception($this->getErrorMsg()); + } + $is_admin = Admin::find()->where([ + 'mobile' => $this->mobile, + 'is_delete' => 0 + ])->one(); + + if ($is_admin) throw new \yii\base\Exception('该账号已注册过'); + + if ($this->role == UserRoleEnum::STORE_ADMIN) { + if (empty($this->store_id)) throw new Exception('门店不能为空'); + $store=Store::find()->where(['id'=>$this->store_id])->one(); + if (!$store){ + throw new Exception('门店不存在!!'); + } + + } + if ($this->role == UserRoleEnum::SUPER_ADMIN) { + $SUPER_ADMIN = Admin::find()->where([ + 'role' => UserRoleEnum::SUPER_ADMIN, + ])->one(); + if ($SUPER_ADMIN) throw new Exception('超管已经存在'); + } + + if($this->role == UserRoleEnum::SUPPLY){ + $code= FuncHelper::create_invite_code(); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $model = new Admin(); + $model->attributes = $this->attributes; + $model->setPassword($this->password); + $model->role = $this->role; + $model->code = $code??''; + $model->province_id= $this->province_id??$store->province_id; + $model->city_id = $this->city_id??$store->city_id; + $model->store_id = $this->store_id ?? ''; + $model->saveOrFail(); + + + if ($this->role == UserRoleEnum::SUPER_ADMIN) { + //可提现账户表 + $CashAccount = new CashAccount(); + $CashAccount->user_id = 0; + $CashAccount->user_type = 2;//平台 + $CashAccount->total_cash = 0;//累计收益 + $CashAccount->able_cash = 0;//账户余额 + $CashAccount->frozen_cash = 0;//申请提现冻结的金额 + $CashAccount->withdrawn_cash = 0;//已提现金额 + $CashAccount->wait_cash = 0;//待结算收益 + $CashAccount->charge_cash = 0;//手续费 + $CashAccount->last_apply_time = date('Y-m-d H:i:s', time()); + $CashAccount->saveOrFail(); + + $log = new Log(); + $log->admin_id = $model->attributes['uid']; + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '用户注册'; + $log->mold = 0;//注册操作 + $log->content = '用户:' . $this->username . '注册成功,用户ID:' . $model->attributes['uid'] . ',手机号:' . $this->mobile; + $log->save(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + } + if ($this->role == UserRoleEnum::STORE_ADMIN) { + //可提现账户表 + $CashAccount = new CashAccount(); + $CashAccount->user_id = $this->store_id; + $CashAccount->user_type = 1; + $CashAccount->total_cash = 0;//累计收益 + $CashAccount->able_cash = 0;//账户余额 + $CashAccount->frozen_cash = 0;//申请提现冻结的金额 + $CashAccount->withdrawn_cash = 0;//已提现金额 + $CashAccount->wait_cash = 0;//待结算收益 + $CashAccount->charge_cash = 0;//手续费 + $CashAccount->last_apply_time = date('Y-m-d H:i:s', time()); + $CashAccount->saveOrFail(); + + $log = new Log(); + $log->admin_id = \Yii::$app->user->getId(); + $log->operate_time = date('Y-m-d H:i:s', time()); + $log->type = '用户注册'; + $log->mold = 0;//注册操作 + $log->content = '用户:' . $this->username . '注册成功,用户ID:' . $model->attributes['uid'] . ',手机号:' . $this->mobile . ',诊所ID:' . $this->store_id; + $log->save(); + + \Yii::$app->db->createCommand()->update('yii_log', ['content' => Json::encode($log->attributes)], ['id' => $log->attributes['id']])->execute(); + + } + + $token = AdminAccessToken::createToken($model->id, 'admin'); + $t->commit(); + + return [ + 'token' => $token, + 'user' => Admin::findOne($model->id), + ]; + } catch (Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + public function EditStore() + { + $admin = \Yii::$app->user->identity; + + $Store = Store::find()->where(['id' => $this->store_id])->one(); + if (!$Store) throw new Exception('诊所不存在'); + + if (!empty($this->bank_account_type)){ + if ($this->bank_account_type== 1 || $this->bank_account_type == 5) { + if (empty($this->bank_no)) { + throw new Exception('bank_no不能为空'); + } + } else { + if (substr($this->bank_card, 0, 2) != '62') { + if (empty($this->bank_no)) { + throw new Exception('bank_no不能为空'); + } + } + } + } + + $Store->bank_user_name = $this->bank_user_name; + $Store->bank_card = $this->bank_card; + $Store->bank_name = $this->bank_name; + $Store->bank_account_type = $this->bank_account_type; + $Store->bank_no = $this->bank_no; + $Store->saveOrFail(); + + + return ['编辑成功']; + } + + public function EditSuper() + { + $admin = \Yii::$app->user->identity; + $Admin=Admin::find()->where(['uid'=>$admin->getId()])->one(); + if (!$Admin) throw new Exception('超管信息不存在'); + + if (!empty($this->bank_account_type)){ + if ($this->bank_account_type== 1 || $this->bank_account_type == 5) { + if (empty($this->bank_no)) { + throw new Exception('bank_no不能为空'); + } + } else { + if (substr($this->bank_card, 0, 2) != '62') { + if (empty($this->bank_no)) { + throw new Exception('bank_no不能为空'); + } + } + } + } + + $Admin->bank_user_name = $this->bank_user_name; + $Admin->bank_card = $this->bank_card; + $Admin->bank_name = $this->bank_name; + $Admin->bank_account_type = $this->bank_account_type; + $Admin->bank_no = $this->bank_no; + $Admin->saveOrFail(); + + + return ['编辑成功']; + } +} \ No newline at end of file diff --git a/admin/models/User.php b/admin/models/User.php new file mode 100644 index 0000000..b1d79df --- /dev/null +++ b/admin/models/User.php @@ -0,0 +1,66 @@ +$token]); + } + + //通过用户名,返回用户实例 + public static function findByUsername($name) + { + return static::findOne(['name' => $name]); + } + + //获取用户ID + public function getId() + { + return $this->id; + } + + //获取用户认证密钥 + public function getAuthKey() + { + return $this->auth_key; + } + + //生成cookie中的authkey + public function generateAuthKey() + { + $this->auth_key=\Yii::$app->security->generateRandomString(32); + } + + //验证用户认证密钥 + public function validateAuthKey($authKey) + { + // TODO: Implement validateAuthKey() method. + return $this->getAuthKey()===$authKey; + } + + //验证密码是否正确,当然我们也可以自已定义加密解密方式 + public function validatePassword($password) + { + return \Yii::$app->security->validatePassword($password,$this->pwd); + } +} \ No newline at end of file diff --git a/admin/models/forms/ActivityForm.php b/admin/models/forms/ActivityForm.php new file mode 100644 index 0000000..276b4d9 --- /dev/null +++ b/admin/models/forms/ActivityForm.php @@ -0,0 +1,80 @@ +0], + [['mall_id','title','contact','mobile','price','start_time','end_time','p_commission','pp_commission'],'required'], + ['content','default','value'=>''], + ['mobile',MobieValidator::class,'message'=>'手机号格式不正确'], + [['price'],'number','min'=>0], + [['p_commission','pp_commission'],'number','min'=>1], + [['p_commission','pp_commission'], 'match', 'pattern' => '/^\d+(\.\d{1,2})?$/i','message'=>'佣金最多只能有两位小数'] + ]; + } + + public function attributeLabels() + { + return [ + 'mall_id' => '活动门店', + 'title' => '活动标题', + 'contact' => '联系人', + 'mobile' => '联系电话', + 'price' => '活动价格', + 'start_time' => '活动开始时间', + 'end_time' => '活动结束时间', + 'p_commission' => '上级返佣', + 'pp_commission' => '上上级返佣' + ]; + } + + public function save() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg($this)); + } + if($this->id){ + $model = Activity::find()->where([ + 'id' => $this->id, + 'is_delete' => 0 + ])->one(); + if(!$model){ + throw new Exception('活动不存在'); + } + }else{ + $model = new Activity(); + } + $model->attributes = $this->attributes; + $model->start_time = strtotime($this->start_time); + $model->end_time = strtotime($this->end_time); + $model->saveOrFail(); + + return []; + } +} diff --git a/admin/models/forms/AttachmentUpload.php b/admin/models/forms/AttachmentUpload.php new file mode 100644 index 0000000..8eac09f --- /dev/null +++ b/admin/models/forms/AttachmentUpload.php @@ -0,0 +1,108 @@ +saveFileFolder = '/uploads/' . \Yii::$app->mallId.'/' . $dateFolder; + $this->saveThumbFolder = '/uploads/thumbs/' . \Yii::$app->mallId.'/' . $dateFolder; + $this->saveFileName = md5_file($this->file->tempName) . '.' . $this->file->getExtension(); + $this->saveToAliOss(); + return $this->attachmentSave(); + } + + public function attachmentSave() + { + $attachment = new Attachment(); + $attachment->storage_id = $this->storage ? $this->storage->id : 0; + $attachment->user_id = 0; + $attachment->name = $this->file->name; + $attachment->size = $this->file->size; + $attachment->is_delete = 0; + $attachment->url = $this->url; + $attachment->thumb_url = $this->thumbUrl; + $attachment->attachment_group_id = $this->attachment_group_id; + $attachment->type = $this->type; + $attachment->mall_id = $this->mall_id; + $attachment->mch_id = $this->mch_id; + if (!$attachment->save()) { + throw new \Exception(json_encode($attachment->getErrors())); + } + return $attachment; + } + + public function saveToAliOss() + { + $config = \Yii::$app->params['upload']['alioss']; + $isCName = (isset($config['is_cname']) && $config['is_cname'] == 1) ? true : false; + $client = new OssClient($config['access_key'], $config['secret_key'], $config['domain'], $isCName); + + $object = trim($this->saveFileFolder . '/' . $this->saveFileName, '/'); + $client->uploadFile($config['bucket'], $object, $this->file->tempName); + if (!$isCName) { + $endpointNameStart = mb_stripos($config['domain'], '://') + 3; + $urlPrefix = mb_substr($config['domain'], 0, $endpointNameStart) + . $config['bucket'] + . '.' + . mb_substr($config['domain'], $endpointNameStart); + } else { + $urlPrefix = $config['domain']; + } + $this->url = $urlPrefix . $this->saveFileFolder . '/' . $this->saveFileName; + if (in_array($this->file->extension, $this->imageExt) && isset($config['style_api']) && $config['style_api']) { + $this->url = $this->url . $config['style_api']; + } + $this->thumbUrl = $this->url; + } + + public static function getInstanceFromFile($localFilePath) + { + if (!is_string($localFilePath)) { + throw new \Exception('文件名称不是字符串。'); + } + if (!file_exists($localFilePath)) { + throw new \Exception('文件`' . $localFilePath . '`不存在。'); + } + $localFilePath = str_replace('\\', '/', $localFilePath); + $pathInfo = pathinfo($localFilePath); + $name = $pathInfo['basename']; + $size = filesize($localFilePath); + $type = mimetype_from_filename($localFilePath); + return new UploadedFile([ + 'name' => $name, + 'type' => $type, + 'tempName' => $localFilePath, + 'error' => 0, + 'size' => $size, + ]); + } +} diff --git a/admin/models/forms/AttachmentUploadForm.php b/admin/models/forms/AttachmentUploadForm.php new file mode 100644 index 0000000..e744a4e --- /dev/null +++ b/admin/models/forms/AttachmentUploadForm.php @@ -0,0 +1,112 @@ +20,'video'=>100,'doc'=>5]; + public function rules() + { + return [ + [['file'], 'file'], + [['file'], 'validateExt'], + [['attachment_group_id'], 'integer'], + [['type'], 'string'], + ]; + } + + public function validateExt($a, $p) + { + $supportExt = array_merge($this->docExt, $this->imageExt, $this->videoExt); + if (!in_array($this->file->extension, $supportExt)) { + $this->addError($a, '不支持的文件类型: ' . $this->file->extension); + } + + if (in_array($this->file->extension, $this->imageExt)) { + if ( $this->file->size > ($this->maxSize['img'] * 1024 * 1024)) { + $this->addError($a, '图片大小超出限制,当前大小为: ' + . (round($this->file->size / 1024 / 1024, 4)) . 'MB,最大限制为:' + . $this->maxSize['img'] . 'MB'); + } + } + + if (in_array($this->file->extension, $this->videoExt)) { + if ($this->file->size > ($this->maxSize['video'] * 1024 * 1024)) { + $this->addError($a, '视频大小超出限制,当前大小为: ' + . (round($this->file->size / 1024 / 1024, 4)) . 'MB,最大限制为:' + . $this->maxSize['maxSize'] . 'MB'); + } + } + } + + public function checkExt($ext) + { + if (in_array($ext, $this->imageExt)) { + $type = 1; + } elseif (in_array($ext, $this->videoExt)) { + $type = 2; + } elseif (in_array($ext, $this->docExt)) { + $type = 3; + } else { + $type = 0; + } + return $type; + } + + public function save() + { + if (!$this->validate()) { + return ['error'=>$this->getErrors()]; + } + + if ($this->type === 'image') { + $type = 1; + } elseif ($this->type === 'video') { + $type = 2; + } else { + if (in_array($this->file->extension, $this->imageExt)) { + $type = 1; + } elseif (in_array($this->file->extension, $this->videoExt)) { + $type = 2; + } elseif (in_array($this->file->extension, $this->docExt)) { + $type = 3; + } else { + $type = 0; + } + } + + $mallId = \Yii::$app->mallId; + $mchId = 0; + $attachmentUpload = new AttachmentUpload([ + 'file' => $this->file, + 'type' => $type, + 'mall_id' => $mallId, + 'mch_id' => $mchId, + 'attachment_group_id' => $this->attachment_group_id ? $this->attachment_group_id : 0 + ]); + $attachment = $attachmentUpload->upload(); + $attachment->thumb_url = $attachment->thumb_url ? $attachment->thumb_url : $attachment->url; + return $attachment; + + } + + public static function getInstanceFromFile($localFilePath) + { + return AttachmentUpload::getInstanceFromFile($localFilePath); + } +} diff --git a/admin/models/forms/FreeRuleEditForm.php b/admin/models/forms/FreeRuleEditForm.php new file mode 100644 index 0000000..995a72e --- /dev/null +++ b/admin/models/forms/FreeRuleEditForm.php @@ -0,0 +1,80 @@ + 0], + ['price', 'number', 'min' => 0], + ['detail', 'safe'], + ['name', 'required'], + ]; + } + + public function save() + { + if (!$this->validate()) { + return ['error'=>$this->model->getErrors()]; + } + + if ($this->model->isNewRecord) { + $this->model->is_delete = 0; + } + $conditionList = []; + foreach ($this->detail as &$item) { + if (isset($item['condition'])) { + if (in_array($item['condition'], $conditionList)) { + throw new ApiException("同一条规则下,包邮条件不能相同"); + } + $conditionList[] = $item['condition']; + $item['condition'] = trim($item['condition']); + if (!is_numeric($item['condition']) || $item['condition'] < 0 || $item['condition'] > 99999999) { + throw new ApiException("包邮条件必须大于等于0,小于99999999"); + } + if (empty($this->type)) { + throw new ApiException("请选择包邮类型"); + } + if (in_array($this->type, [2, 4])) { + $item['condition'] = (int)$item['condition']; + } + } else { + throw new ApiException("请设置包邮条件"); + } + } + unset($item); + $this->model->detail = json_encode($this->detail); + $this->model->price = $this->price; + $this->model->name = $this->name; + $this->model->type = $this->type; + $this->model->status = $this->status; + if ($this->model->save()) { + return []; + } else { + return ['error'=>$this->model->getErrors()]; + } + } +} diff --git a/admin/models/forms/HospitalDocForm.php b/admin/models/forms/HospitalDocForm.php new file mode 100644 index 0000000..a0e80b0 --- /dev/null +++ b/admin/models/forms/HospitalDocForm.php @@ -0,0 +1,194 @@ +validate()){ + throw new Exception($this->getErrorMsg()); + } + + ServiceUser::find()->where([ + 'id' => $this->doctor_id, + 'role' => UserRoleEnum::DOCTOR, + 'is_delete' => 0, + ])->one(); + + $sql = "select * from yii_doctor_platform where platform_doctor_id= $this->doctor_id and platform_store_id=$store"; + $doctor_is_exist = \Yii::$app->db1->createCommand($sql)->queryOne(); + if (!$doctor_is_exist){ + throw new Exception('您还没成为互医'); + } + + $doctor_id = $doctor_is_exist['su_id']; + + $doctor_info = "select * from yii_doctor_info where su_id=$doctor_id"; + $doctor_info_exist = \Yii::$app->db1->createCommand($doctor_info)->queryOne(); + + $doctor_identity = "select * from yii_doctor_identity where su_id=$doctor_id"; + $doctor_identity_exist = \Yii::$app->db1->createCommand($doctor_identity)->queryOne(); + + $doctor_practicing = "select * from yii_doctor_practicing where su_id=$doctor_id"; + $doctor_practicing_exist = \Yii::$app->db1->createCommand($doctor_practicing)->queryOne(); + + $doctor_service = "select * from yii_doctor_service where su_id=$doctor_id"; + $doctor_service_exist = \Yii::$app->db1->createCommand($doctor_service)->queryOne(); + + return [ + 'doctor'=>$doctor_is_exist, + 'doctor_info'=>$doctor_info_exist, + 'doctor_identity'=>$doctor_identity_exist, + 'doctor_practicing'=>$doctor_practicing_exist, + 'doctor_service'=>$doctor_service_exist + ]; + } + + /** + * 升级为互医 + */ + public function grade() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $ServiceUser = ServiceUser::find()->where([ + 'id' => $this->doctor_id, + 'role' => UserRoleEnum::DOCTOR, + 'is_delete' => 0, + 'plate_type'=>2 //萧康的医生 + ])->one(); + if (!$ServiceUser){ + throw new Exception('萧康不存在该医生'); + } + if (!$ServiceUser->docIdentity || !$ServiceUser->docPracticing || !$ServiceUser->docInfo || !$ServiceUser->docService) + throw new Exception('请完善基本信息'); + + $store_ids=StoreDoctor::find()->where([ + 'su_id'=>$this->doctor_id + ])->select('store_id')->column(); + + if (!$store_ids){ + throw new Exception('您还没有任何门店'); + } + + $params=[ + 'id' => $this->doctor_id, + 'store_id'=>$store_ids, + 'mobile'=>$ServiceUser->mobile, + 'docInfo' =>$ServiceUser->docInfo, + 'docIdentity'=> $ServiceUser->docIdentity, + 'docPracticing'=>$ServiceUser->docPracticing, + 'docService'=> $ServiceUser->docService, + ]; + + $response = (new Client(['http_errors' => false]))->post( + \Yii::$app->params['platform']['url']."/platform/v1/sync/doctor", + [ + 'headers' => ['Content-Type' => 'application/json', 'Authorization' => "Bearer ".\Yii::$app->params['platform']['token']], + \GuzzleHttp\RequestOptions::JSON =>$params + ] + ); + $result = json_decode($response->getBody(),true); + if ($result['errcode']) { + throw new Exception($result['msg']); + } + + return ['升级成功']; + } + + //同步患者 + public function SyncPatient() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $store=\Yii::$app->store; + $patient=DoctorPatient::find()->where([ + 'su_id'=>$this->doctor_id, + ])->all(); + + $sql = "select * from yii_doctor_platform where platform_doctor_id=$this->doctor_id and platform_store_id=$store"; + $doctor_is_exist = \Yii::$app->db1->createCommand($sql)->queryOne(); + + if (!$doctor_is_exist){ + throw new Exception('您还没成为互医'); + } + + $rows=[]; + foreach ($patient as $value){ + $rows[]=[ + 'su_id'=>$doctor_is_exist['su_id'], + 'user_id'=>$value['user_id'], + 'up_id'=>$value['up_id'], + 'name'=>$value['name'], + 'avatar'=>$value['avatar'], + 'id_card'=>$value['id_card'], + 'sex'=>$value['sex'], + 'mobile'=>$value['mobile'], + 'created_at' => time(), + 'updated_at' => time(), + ]; + } + + \Yii::$app->db1->createCommand()->batchInsert('yii_doctor_patient', ['su_id','user_id','up_id','name','avatar','id_card','sex','mobile','created_at','updated_at'],$rows)->execute(); + + return ['患者同步成功']; + } + + //医生审核 + public function ExamineDoc() + { + + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $DoctorApply=DoctorApply::find()->where([ + 'service_user_id'=>$this->doctor_id, + 'status'=>0, + 'is_delete'=>0, + ])->one(); + if (!$DoctorApply){ + throw new Exception('该医生没有升级申请'); + } + + $DoctorApply->id=$DoctorApply->id; + $DoctorApply->service_user_id=$this->doctor_id; + $DoctorApply->status=$this->status; + $DoctorApply->update(); + return []; + } +} \ No newline at end of file diff --git a/admin/models/forms/LoginForm.php b/admin/models/forms/LoginForm.php new file mode 100644 index 0000000..655cfd0 --- /dev/null +++ b/admin/models/forms/LoginForm.php @@ -0,0 +1,98 @@ +hasErrors()) { + $user = $this->getUser(); + if (!$user || !$user->validatePassword($this->password)) { + $this->addError($attribute, 'Incorrect mobile or password.'); + } + } + } + + /** + * Logs in a user using the provided username and password. + * + * @return boolean whether the user is logged in successfully + */ + public function login() + { + if ($this->validate()) { + $adminAccessToken = new AdminAccessToken(); + return $adminAccessToken->createToken($this->_user->uid,'admin'); + } else { + throw new Exception($this->getErrorMsg()); + } + } + + /** + * Finds user by [[username]] + * + * @return Admin|null + */ + public function getUser() + { + if ($this->_user === null) { + $this->_user = Admin::findByMobile($this->mobile); + } + + return $this->_user; + } + + public function ResetPassword() + { + $admin=Admin::find()->where([ + 'mobile'=>$this->mobile + ])->one(); + if (!$admin) return ['账号不存在']; + $admin->password=(new Admin())->setPassword($this->password); + + if (!$admin->saveOrFail())throw new Exception('重置密码或忘记密码失败'); + + return ['重置密码或忘记密码成功']; + } +} diff --git a/admin/models/forms/PostageRulesEditForm.php b/admin/models/forms/PostageRulesEditForm.php new file mode 100644 index 0000000..c3248a3 --- /dev/null +++ b/admin/models/forms/PostageRulesEditForm.php @@ -0,0 +1,85 @@ +validate()) { + return $this->getErrorResponse(); + } + + if (empty($this->detail)) { + throw new ApiException("请填写运费规则"); + } + + foreach ($this->detail as &$item) { + if (isset($item['first'])) { + if(!is_numeric($item['first'])) { + throw new ApiException("首件/首重必须是数字且不小于0"); + } + } else { + $item['first'] = 0; + } + if (isset($item['firstPrice'])) { + if (!is_numeric($item['firstPrice']) || $item['firstPrice'] < 0) { + throw new ApiException("运费必须是数字且不小于0"); + } + } else { + $item['firstPrice'] = 0; + } + if (isset($item['second'])) { + if (!is_numeric($item['second'])) { + throw new ApiException("续件/续重必须是数字且不小于0"); + } + } else { + $item['second'] = 0; + } + if (isset($item['secondPrice'])) { + if (!is_numeric($item['secondPrice']) || $item['secondPrice'] < 0) { + throw new ApiException("运费必须是数字且不小于0"); + } + } else { + $item['secondPrice'] = 0; + } + } + + $this->detail = json_encode($this->detail); + $this->model->attributes = $this->attributes; + if ($this->model->save()) { + return [ + ]; + } else { + return ['errors'=>$this->model->getErrors()]; + } + + } +} diff --git a/admin/models/forms/RefundAddressEditForm.php b/admin/models/forms/RefundAddressEditForm.php new file mode 100644 index 0000000..62e8c68 --- /dev/null +++ b/admin/models/forms/RefundAddressEditForm.php @@ -0,0 +1,62 @@ + '收件人名称', + 'address' => '省市区', + 'address_detail' => '收件人详细地址', + 'mobile' => '收件人手机号', + 'remark' => '备注', + ]; + } + + public function save($runValidation = true, $attributeNames = null) + { + if (!$this->validate()) { + return ['error'=>$this->getErrors()]; + } + $addressArr = []; + $arr = DistrictArr::getArr(); + $area = $arr[$this->addressId]; + + $city = $arr[$area['parent_id']]; + $province = $arr[$city['parent_id']]; + $this->address = json_encode([$province['name'],$city['name'],$area['name']]); + if (!parent::save($runValidation,$attributeNames)) { + throw new \Exception('保存失败'); + }else{ + return []; + } + } +} diff --git a/admin/models/forms/drug/AgreeForm.php b/admin/models/forms/drug/AgreeForm.php new file mode 100644 index 0000000..a581edb --- /dev/null +++ b/admin/models/forms/drug/AgreeForm.php @@ -0,0 +1,73 @@ +validate()) { + throw new Exception($this->getErrorMsg()); + } + + if (!$this->id) { + $BaseConfig = new BaseConfig(); + } else { + $BaseConfig = BaseConfig::find()->where([ + 'id' => $this->id, + ])->one(); + if (!$BaseConfig) { + throw new Exception('协议不存在'); + } + } + + $BaseConfig->end = $this->end ?? $BaseConfig->end; + $BaseConfig->desc = $this->desc ?? $BaseConfig->desc; + $BaseConfig->type = $this->type ?? $BaseConfig->type; + $BaseConfig->content = $this->content ?? $BaseConfig->content; + $BaseConfig->change_at = time(); + $BaseConfig->saveOrFail(); + + return ['success']; + } + + public function del() + { + $BaseConfig = BaseConfig::find()->where([ + 'id' => $this->id + ])->one(); + + if (!$BaseConfig) { + throw new Exception('协议不存在'); + } + + $BaseConfig->status = 1; + if (!$BaseConfig->saveOrFail()) { + throw new Exception('删除失败'); + } + return ['已删除']; + } +} \ No newline at end of file diff --git a/admin/models/forms/drug/ArticleForm.php b/admin/models/forms/drug/ArticleForm.php new file mode 100644 index 0000000..8174430 --- /dev/null +++ b/admin/models/forms/drug/ArticleForm.php @@ -0,0 +1,90 @@ +'0'], + ['read_num','default','value'=>'0'], + ['collection','default','value'=>'0'], + ['is_draft','default','value'=>'0'], + ]; + } + + public function attributeLabels() + { + return [ + 'type'=>'文章类型', + 'cid'=>'分类id', + 'cover'=>'封面', + 'intro'=>'简介', + 'content'=>'内容', + 'title'=>'文章标题', + 'video_url'=>'视频链接', + 'is_draft'=>'是否是草稿0否1是', + 'su_id'=>'医生id 0为后台发布', + ]; + } + + public function save() + { + + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + if (!$this->id){ + $DoctorArticle= new DoctorArticle(); + }else{ + $DoctorArticle= DoctorArticle::find()->where(['id'=>$this->id])->one(); + if (!$DoctorArticle) throw new Exception('文章不存在'); + } + + $DoctorArticle->attributes=$this->attributes; + + if (!$DoctorArticle->saveOrFail()){ + throw new Exception('error'); + }; + return ['success']; + + } + public function del() + { + $article= DoctorArticle::find()->where([ + 'id' => $this->id, + 'is_delete'=>0 + ])->one(); + if (!$article) throw new Exception('文章不存在'); + + $article->is_delete=1; + $article->saveOrFail(); + + return ['删除成功']; + } +} \ No newline at end of file diff --git a/admin/models/forms/drug/ChineseForm.php b/admin/models/forms/drug/ChineseForm.php new file mode 100644 index 0000000..943340a --- /dev/null +++ b/admin/models/forms/drug/ChineseForm.php @@ -0,0 +1,106 @@ +'1'], + ]; + } + + public function attributeLabels() + { + return [ + 'drug_name'=>'药名', + 'drug_number'=>'药品编号', + 'drug_alias'=>'药品别名', + 'unit_id'=>'单位', + 'pinyin_simple'=>'拼音首拼', + 'status'=>'状态 1草稿 2下架 3上架', + 'decotion'=>'煎法', + 'is_otc'=>'是否处方药', + ]; + } + public function save() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $DRUG=new Drug(); + $DRUG->attributes=$this->attributes; + $DRUG->created_at=time(); + $DRUG->saveOrFail(); + + $t->commit(); + return ['新增成功']; + }catch (\Exception $e){ + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + public function update() + { + $drug=Drug::find()->where([ + 'id'=>$this->id, + 'type'=>1, + ])->one(); + + if (!$drug) throw new \yii\base\Exception('该药品不存在'); + + $drug->pinyin_simple=$this->pinyin_simple??$drug->pinyin_simple; + $drug->status=$this->status??$drug->status; + $drug->drug_name=$this->drug_name??$drug->drug_name; + $drug->drug_number=$this->drug_number??$drug->drug_number; + $drug->drug_alias=$this->drug_alias??$drug->drug_alias; + $drug->unit_id=$this->unit_id??$drug->unit_id; + $drug->place=$this->place??$drug->place; + $drug->source=$this->source??$drug->source; + $drug->instruction=$this->instruction??$drug->instruction; + $drug->saveOrFail(); + + return ['编辑成功']; + } + + public function info() + { + $drug=Drug::find()->where([ + 'id'=>$this->id, + 'type'=>1, + ])->one(); + if (!$drug) throw new Exception('该药品不存在'); + return $drug; + } + +} \ No newline at end of file diff --git a/admin/models/forms/drug/DepartForm.php b/admin/models/forms/drug/DepartForm.php new file mode 100644 index 0000000..5157639 --- /dev/null +++ b/admin/models/forms/drug/DepartForm.php @@ -0,0 +1,218 @@ +0], + ]; + } + + public function attributeLabels() + { + return [ + 'erp_id'=>'对接的erp_id', + 'code'=>'推广码', + 'level'=>'级别', + 'offical_seal'=>'公章', + 'name'=>'名字', + 'shouzimu'=>'首字母', + 'start_time'=>'开始营业时间', + 'end_time'=>'结束营业时间', + 'qr_code'=>'门店二维码', + ]; + } + + //新增科室 + public function SaveDepart() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $Department=Department::find()->where([ + 'name'=>$this->name + ])->one(); + if ($Department) throw new Exception('科室已存在'); + if ($this->level != 1){ + if (empty($this->pid)){ + return ['pid不能为空']; + } + } + + $department=new Department(); + $department->attributes=$this->attributes; + $department->saveOrFail(); + return ['添加成功']; + } + + //新增门店 + public function SaveStore() + { + $admin=Admin::find()->where(['code'=>$this->code,'role'=>UserRoleEnum::SUPPLY])->one(); + if (!$admin)throw new Exception('推广码或业务员不存在'); + + if ($this->id){ + $Store=Store::find()->where([ + 'plate_id'=>$this->plate_id, + 'id'=>$this->id + ])->one(); + if (!$Store) throw new Exception('门店不存在'); + + if (!empty($this->bank_account_type)){ + if ($this->bank_account_type== 1 || $this->bank_account_type == 5) { + if (empty($this->bank_no)) { + throw new Exception('bank_no不能为空'); + } + } else { + if (substr($this->bank_card, 0, 2) != '62') { + if (empty($this->bank_no)) { + throw new Exception('bank_no不能为空'); + } + } + } + } + $Store->plate_id=$this->plate_id; + $Store->drugstore_id=$this->drugstore_id; + $Store->name=$this->store_name; + if($this->erp_id){ + $Store->erp_id=$this->erp_id; + } + $Store->shouzimu=$this->shouzimu; + $Store->contact=$this->contact; + $Store->offical_seal=$this->offical_seal??$Store->offical_seal; + $Store->province_id=$this->province_id; + $Store->city_id=$this->city_id; + $Store->position=$this->position; + $Store->mobile=$this->mobile; + $Store->uid=$admin->uid; + $Store->code=$this->code; + $Store->bank_user_name=$this->bank_user_name; + $Store->bank_card=$this->bank_card; + $Store->bank_name=$this->bank_name; + $Store->bank_account_type=$this->bank_account_type; + $Store->bank_no=$this->bank_no; + $Store->start_time=$this->start_time; + $Store->end_time=$this->end_time; + + if(!$Store->qr_code){ + $scene = 'STORE_QR_CODE'.'_'.$this->id; + $weappService = new WeappService(); + $url= $weappService->getQrcode($scene); + $Store->qr_code = $url; + } + + + $Store->saveOrFail(); + return ['编辑成功']; + } + $Store=Store::find()->where([ + 'plate_id'=>$this->plate_id, + 'name'=>$this->name + ])->one(); + if ($Store) throw new Exception('门店已存在'); + + $t=\Yii::$app->db->beginTransaction(); + try { + $Store=new Store(); + $Store->plate_id=$this->plate_id; + $Store->drugstore_id=$this->drugstore_id; + $Store->erp_id=$this->erp_id; + $Store->name=$this->store_name; + $Store->contact=$this->contact; + $Store->offical_seal=$this->offical_seal??''; + $Store->province_id=$this->province_id; + $Store->city_id=$this->city_id; + $Store->position=$this->position; + $Store->mobile=$this->mobile; + $Store->uid=$admin->uid; + $Store->code=$this->code; +// $Store->bank_user_name=$this->bank_user_name; +// $Store->bank_card=$this->bank_card; +// $Store->bank_name=$this->bank_name; +// $Store->bank_account_type=$this->bank_account_type; +// $Store->bank_no=$this->bank_no; + $Store->start_time=$this->start_time; + $Store->end_time=$this->end_time; + $Store->shouzimu=$this->shouzimu; + $Store->saveOrFail(); + + $add_store = Store::find()->where([ + 'id' => $Store->id + ])->one(); + $scene = 'STORE_QR_CODE'.'_'.$add_store->id; + $weappService = new WeappService(); + $url= $weappService->getQrcode($scene); + $add_store->qr_code=$url; + $add_store->saveOrFail(); +// StoreController::actionQrcode($Store->id); + + $t->commit(); + return ['添加成功']; + }catch (\Exception $e){ + $t->rollBack(); + throw new Exception($e->getMessage()); + } + + } +} \ No newline at end of file diff --git a/admin/models/forms/drug/DiagnoseForm.php b/admin/models/forms/drug/DiagnoseForm.php new file mode 100644 index 0000000..85ddcc2 --- /dev/null +++ b/admin/models/forms/drug/DiagnoseForm.php @@ -0,0 +1,104 @@ +validate()){ + throw new Exception($this->getErrorMsg()); + } + if ($this->id){ + $Disease=Disease::find()->where(['id'=>$this->id,'is_delete'=>0])->one(); + $Disease->attributes=$this->attributes; + $Disease->saveOrFail(); + return ['编辑成功']; + } + $is_disease=Disease::find()->where(['name'=>$this->name,'is_delete'=>0])->one(); + if ($is_disease) throw new Exception('改症状已经存在,请勿重复添加'); + $add_disease=new Disease(); + $add_disease->attributes=$this->attributes; + $add_disease->pinyin = (new Pinyin())->abbr($this->name); + $add_disease->saveOrFail(); + return ['添加成功']; + } + + //导入 + public function export($data) + { + if (empty($data)) { + throw new Exception('导入数据为空'); + } else { + foreach ($data as $item) { + try { + $Disease=Disease::find()->where(['diagnose_code'=>$item['编码'],'is_delete'=>0])->one(); + + if (!$Disease){ + $model = new Disease(); + $model->setAttribute('diagnose_code', trim($item['编码'])); + $model->setAttribute('name', trim($item['名称'])); + $model->setAttribute('pinyin', (new Pinyin())->abbr(trim($item['名称']))); + $model->setAttribute('major_number', trim($item['主编号'])); + $model->setAttribute('ref_number',trim($item['次编号']) ); + if (!$model->save()) { + $errorsMsg = array_values($model->getFirstErrors()); + return [$errorsMsg[0]]; + } + + $success[] = '诊断症状导入成功'; + }else{ + $errors[]= '编码:'.$item['编码'].'导入失败,原因:重复导入'; + } + } catch (\Exception $e) { + $errors[] = $e->getMessage(); + continue; + } + } + return ['success'=> $success,'error'=>$errors]; + } + } + + + public function del() + { + $Disease=Disease::find()->where([ + 'id'=>$this->id, + 'is_delete'=>0 + ])->one(); + if (!$Disease) throw new Exception('诊断症状不存在'); + + $Disease->is_delete=1; + $Disease->saveorFail(); + + return ['删除成功']; + } +} \ No newline at end of file diff --git a/admin/models/forms/drug/DrugCategoryForm.php b/admin/models/forms/drug/DrugCategoryForm.php new file mode 100644 index 0000000..7f544a8 --- /dev/null +++ b/admin/models/forms/drug/DrugCategoryForm.php @@ -0,0 +1,108 @@ +'0'], + ['category_name', 'string'], + ]; + } + public function attributeLabels() + { + return [ + 'level'=>'等级', + 'sort'=>'排序', + 'parent_id'=>'父级ID', + ]; + } + public function save() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + $DrugCategories = DrugCategories::find()->where([ + 'category_name' => $this->category_name, + 'deleted_at' => null + ])->one(); + if ($DrugCategories) throw new Exception('药品分类已存在,请勿重复添加'); + + if ($this->level != 1){ + if (empty($this->parent_id)){ + return ['parent_id不能为空']; + } + } + + if (!$this->id){ + $DrugCategories=new DrugCategories(); + } + $DrugCategories->category_name = $this->category_name; + $DrugCategories->parent_id = $this->parent_id; + $DrugCategories->level = $this->level; + $DrugCategories->sort = $this->sort; + $DrugCategories->created_at = date('Y-m-d H:i:s',time()); + $DrugCategories->updated_at = date('Y-m-d H:i:s',time()); + + $DrugCategories->save(); + return ['添加成功']; + + } + + public function update() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + $DrugCategories = DrugCategories::find()->where([ + 'id' => $this->id, + 'deleted_at' => null + ])->one(); + if (!$DrugCategories) throw new Exception('药品分类不存在'); + $DrugCategories->category_name = $this->category_name; + $DrugCategories->parent_id = $this->parent_id; + $DrugCategories->level = $this->level; + $DrugCategories->sort = $this->sort; + $DrugCategories->created_at = date('Y-m-d H:i:s',time()); + $DrugCategories->updated_at = date('Y-m-d H:i:s',time()); + $DrugCategories->saveOrFail(); + return ['编辑成功']; + } + + public function del() + { + $DrugCategories = DrugCategories::find()->where([ + 'id' => $this->id, + 'deleted_at' => null + ])->one(); + if (!$DrugCategories) throw new Exception('药品分类不存在'); + + $DrugCategories->deleted_at=date('Y-m-d H:i:s',time()); + $DrugCategories->saveOrFail(); + return ['删除成功']; + } + + public function info() + { + $DrugCategories = DrugCategories::find()->where([ + 'id' => $this->id, + 'deleted_at' => null + ])->one(); + if (!$DrugCategories) throw new Exception('药品分类不存在'); + return $DrugCategories; + } +} \ No newline at end of file diff --git a/admin/models/forms/drug/DrugForm.php b/admin/models/forms/drug/DrugForm.php new file mode 100644 index 0000000..f6c067f --- /dev/null +++ b/admin/models/forms/drug/DrugForm.php @@ -0,0 +1,188 @@ +'使用频率', + 'type_id'=>'使用方法', + 'unit_id'=>'单位', + 'time_id'=>'使用时间', + 'drug_alias'=>'别名', + 'place'=>'产地', + 'drugstore'=>'仓库', + 'pinyin_simple'=>'拼音首拼', + 'is_otc'=>'是否处方药', + 'drug_name'=>'药名', + 'drug_number'=>'药品编号', + 'usage'=>'用法', + 'status'=>'状态 1草稿 2下架 3上架', + 'image'=>'药品图片', + 'instruction'=>'说明书图片', + 'source'=>'货源(厂家)', + 'function'=>'功能主治', + 'guozi_no'=>'国字准号', + 'specification'=>'规格', + 'bar_code'=>'条形码', + ]; + } + + public function save() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + $Drug = new Drug(); + $Drug->attributes = $this->attributes; + + $Drug->created_at = time(); + $Drug->updated_at = time(); + if (!$Drug->saveOrFail()) { + throw new Exception('新增失败'); + } + + // $decode=json_decode($this->drugstore,true); + // + // foreach ($decode as $value){ + // $DrugStoreDrug = DrugStoreDrug::find()->where([ + // 'drugstore_id' => $value['drugstore_id'], + // 'drug_id' => $DRUG->id, + // 'is_delete' => 0 + // ])->one(); + // if ($DrugStoreDrug) { + // $DrugStoreDrug ->is_delete=1; + // $DrugStoreDrug->saveOrFail(); + // } + // + // $drug = new DrugStoreDrug(); + // $drug->drugstore_id = $value['drugstore_id']; + // $drug->drug_id = $DRUG->id; + // $drug->type = $value['type']; + // $drug->price = $value['price']; + // $drug->stock =$value['stock']; + // $drug->saveOrFail(); + // } + + return ['新增成功']; + } + + public function update() + { + + $drug = Drug::find()->where([ + 'id' => $this->id, + ])->one(); + + if (!$drug) throw new Exception('该药品不存在'); + + $drug->type = $this->type ?? $drug->type; + $drug->drug_name = $this->drug_name ?? $drug->drug_name; + $drug->drug_number = $this->drug_number ?? $drug->drug_number; + $drug->bar_code = $this->bar_code ?? $drug->bar_code; + $drug->specification = $this->specification ?? $drug->specification; + $drug->guozi_no = $this->guozi_no ?? $drug->guozi_no; + $drug->source = $this->source ?? $drug->source; + $drug->function = $this->function ?? $drug->function; + $drug->image = $this->image ?? $drug->image; + $drug->usage = $this->usage ?? $drug->usage; + $drug->instruction = $this->instruction ?? $drug->instruction; + $drug->place = $this->place ?? $drug->place; + $drug->is_otc = $this->is_otc ?? $drug->is_otc; + $drug->status = $this->status ?? $drug->status; + $drug->place = $this->place ?? $drug->place; + $drug->time_id = $this->time_id ?? $drug->time_id; + $drug->type_id = $this->type_id ?? $drug->type_id; + $drug->frequency_id = $this->frequency_id ?? $drug->frequency_id; + $drug->unit_id = $this->unit_id ?? $drug->unit_id; + $drug->drug_alias = $this->drug_alias ?? $drug->drug_alias; + $drug->updated_at = time(); + + if (!$drug->saveOrFail()) { + throw new Exception('编辑失败'); + } + return ['编辑成功']; + } + + //上下架 + public function IsSale() + { + $drug = Drug::find()->where([ + 'id' => $this->id, + 'type' => $this->type, + ])->one(); + if (!$drug) throw new Exception('该药品不存在'); + + $drug->status = $this->status; + if (!$drug->saveOrFail()) throw new Exception('上下架失败'); + + return ['成功上下架']; + } + + //基础药品-草稿 + public function Draft() + { + $drug = Drug::find()->where([ + 'id' => $this->id, + 'type' => $this->type, + ])->one(); + if (!$drug) throw new Exception('该药品不存在'); + + $drug->status = 1; + if (!$drug->saveOrFail()) throw new Exception('修改为草稿失败'); + + return ['成功修改为草稿']; + } + + public function info() + { + $drug = Drug::find()->where([ + 'id' => $this->id, + 'type' => $this->type, + ])->one(); + + if (!$drug) throw new Exception('该药品不存在'); + + return $drug; + } +} diff --git a/admin/models/forms/drug/GranularForm.php b/admin/models/forms/drug/GranularForm.php new file mode 100644 index 0000000..6aa5631 --- /dev/null +++ b/admin/models/forms/drug/GranularForm.php @@ -0,0 +1,103 @@ +'3'], + ]; + } + + public function attributeLabels() + { + return [ + 'drug_name'=>'药名', + 'drug_number'=>'药品编号', + 'drug_alias'=>'药品别名', + 'unit_id'=>'单位', + 'pinyin_simple'=>'拼音首拼', + 'status'=>'状态 1草稿 2下架 3上架', + ]; + } + public function save() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $drug=new Drug(); + $drug->attributes=$this->attributes; + $drug->created_at=time(); + $drug->saveOrFail(); + + $t->commit(); + return ['新增成功']; + }catch (\Exception $e){ + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + public function update() + { + $drug=Drug::find()->where([ + 'id'=>$this->id, + 'type'=>3, + ])->one(); + if (!$drug) throw new Exception('该药品不存在'); + $drug->pinyin_simple=$this->pinyin_simple??$drug->pinyin_simple; + $drug->status=$this->status??$drug->status; + $drug->drug_name=$this->drug_name??$drug->drug_name; + $drug->drug_number=$this->drug_number??$drug->drug_number; + $drug->drug_alias=$this->drug_alias??$drug->drug_alias; + $drug->unit_id=$this->unit_id??$drug->unit_id; + $drug->place=$this->place??$drug->place; + $drug->source=$this->source??$drug->source; + $drug->instruction=$this->instruction??$drug->instruction; + + $drug->saveOrFail(); + return ['编辑成功']; + } + + + public function info() + { + $drug= Drug::find()->where([ + 'id'=>$this->id, + 'type'=>3, + ])->one(); + if (!$drug) throw new Exception('该药品不存在'); + return $drug; + } + +} \ No newline at end of file diff --git a/admin/models/forms/drug/ImportForm.php b/admin/models/forms/drug/ImportForm.php new file mode 100644 index 0000000..8eb6613 --- /dev/null +++ b/admin/models/forms/drug/ImportForm.php @@ -0,0 +1,350 @@ + false, 'extensions' => 'xls,xlsx'], + ]; + } + + public function attributeLabels() + { + return [ + 'file' => '文件上传' + ]; + } + + //首拼 + public function shoupin($name) + { + return ArrayHelper::shouzimu($name); + } + + //西药导入 + public function WestImport($data) + { + if (empty($data)) { + throw new Exception('导入数据为空'); + } else { + $t = \Yii::$app->db->beginTransaction(); + try { + foreach ($data as $item) { + if (empty($item['药名'])) { + throw new Exception('药名不能为空,导入失败'); + } + $drug = Drug::find()->where([ + 'or', + ['bar_code' => $item['条形码']], + ['guozi_no' => $item['国字准号']] + ])->one(); + if (!$drug) { + $model = new Drug(); + $model->setAttribute('drug_name', trim($item['药名'])); + $model->setAttribute('drug_alias', trim($item['商品名'])); + $model->setAttribute('pinyin_simple', (new Pinyin())->abbr(trim($item['药名']))); + $model->setAttribute('drug_number', trim($item['编号'])); + $model->setAttribute('bar_code',trim( $item['条形码'])); + $model->setAttribute('specification', trim($item['规格'])); + $model->setAttribute('guozi_no', trim($item['国字准号'])); + $model->setAttribute('status',trim( $item['药品状态'])); + $model->setAttribute('function', trim($item['功能主治'])); + $model->setAttribute('source', trim($item['厂家'])); + $model->setAttribute('status', trim($item['状态'])); + $model->setAttribute('is_otc', trim($item['是否处方药'])); + $model->setAttribute('time_id', trim($item['服用时间'])); + $model->setAttribute('type_id', trim($item['服用方法'])); + $model->setAttribute('frequency_id',trim( $item['使用频率'])); + $model->setAttribute('unit_id', trim($item['用量单位'])); + $model->setAttribute('usage', trim($item['用法'])); + $model->setAttribute('type', '2'); + $model->setAttribute('created_at', time()); + if (!$model->save()) { + $errorsMsg = array_values($model->getFirstErrors()); + $errors[] = '条形码:' . $item['条形码'] . ',国子准号:' . $item['国字准号'] . '的西药导入失败,原因:保存失败;'.$errorsMsg[0]; + }else{ + $success[] = '条形码:' . $item['条形码'] . ',国子准号:' . $item['国字准号'] . '的西药导入成功'; + } + } else { + $errors[] = '条形码:' . $item['条形码'] . ',国子准号:' . $item['国字准号'] . '的西药导入失败,原因:重复导入'; + } + } + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + $errors[] = $e->getMessage(); + + } + return ['success' => $success, 'error' => $errors]; + } + } + + //导入中药 + public function ChineseImport($data) + { + if (empty($data)) { + throw new Exception('导入数据为空'); + } else { + $t = \Yii::$app->db->beginTransaction(); + try { + foreach ($data as $item) { + if (empty($item['药名'])) { + throw new Exception('药名不能为空,导入失败'); + } + $drug = Drug::find()->where(['drug_number' => trim($item['编号'])])->one(); + + if (!$drug) { + $model = new Drug(); + $model->setAttribute('drug_name', trim($item['药名'])); + $model->setAttribute('pinyin_simple', (new Pinyin())->abbr(trim($item['药名']))); + $model->setAttribute('drug_number', trim($item['编号'])); + $model->setAttribute('drug_alias', trim($item['别名'])); + $model->setAttribute('unit_id', trim($item['单位'])); + $model->setAttribute('status', trim($item['状态'])); + $model->setAttribute('type', '1'); + $model->setAttribute('created_at', time()); + $model->setAttribute('updated_at', time()); + if (!$model->saveOrFail()) { + $errorsMsg = array_values($model->getFirstErrors()); + $errors[] = '编号:' . $item['编号'] . '的导入失败,原因:保存失败,' . $errorsMsg[0]; + } else { + $success[] = '编号:' . $item['编号'] . '的中药导入成功'; + } + } else { + $errors[] = '编号:' . $item['编号'] . '的中药导入失败,原因:重复导入'; + } + } + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + $errors[] = $e->getMessage(); + } + return ['success' => $success, 'error' => $errors]; + } + } + + //颗粒配方 + public function GranularImport($data) + { + if (empty($data)) { + throw new Exception('导入数据为空'); + } else { + $t = \Yii::$app->db->beginTransaction(); + try { + foreach ($data as $item) { + if (empty($item['药名'])) { + throw new Exception('药名不能为空,导入失败'); + } + + $drug = Drug::find()->where(['drug_number' => trim($item['编号'])])->one(); + if (!$drug) { + $model = new Drug(); + $model->setAttribute('drug_name', trim($item['药名'])); + $model->setAttribute('pinyin_simple',(new Pinyin())->abbr(trim($item['药名']))); + $model->setAttribute('drug_number', trim($item['编号'])); + $model->setAttribute('drug_alias', trim($item['别名'])); + $model->setAttribute('place', trim($item['产地'])); + $model->setAttribute('source',trim( $item['厂家'])); + $model->setAttribute('status', trim($item['状态'])); + $model->setAttribute('is_otc', trim($item['是否处方药'])); + $model->setAttribute('type', '3'); + $model->setAttribute('created_at', time()); + if (!$model->save()) { + $errorsMsg = array_values($model->getFirstErrors()); + $errors[] = '编号:' . $item['编号'] . '导入失败,原因:保存失败;'.$errorsMsg[0]; + }else{ + $success[] = '编号:' . $item['编号'] . '的颗粒配方导入成功'; + } + } else { + $errors[] = '编号:' . $item['编号'] . '的颗粒配方导入失败,原因:重复导入'; + } + } + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + $errors[] = $e->getMessage(); + } + return ['success' => $success, 'error' => $errors]; + } + } + + + //中成药导入 + public function ImportZhongcheng($data) + { + if (empty($data)) { + throw new Exception('导入数据为空'); + } else { + $t = \Yii::$app->db->beginTransaction(); + try { + foreach ($data as $item) { + if (empty($item['药名'])) { + throw new Exception('药名不能为空,导入失败'); + } + + $drug = Drug::find()->where([ + 'or', + ['bar_code' => trim($item['条形码'])], + ['guozi_no' => trim($item['国字准号'])] + ])->one(); + if (!$drug) { + $model = new Drug(); + $model->setAttribute('drug_name',trim( $item['药名'])); + $model->setAttribute('drug_alias', trim($item['别名'])); + $model->setAttribute('pinyin_simple', (new Pinyin())->abbr(trim($item['药名']))); + $model->setAttribute('drug_number', trim($item['编号'])); + $model->setAttribute('bar_code', trim($item['条形码'])); + $model->setAttribute('specification', trim($item['规格'])); + $model->setAttribute('guozi_no',trim( $item['国字准号'])); + $model->setAttribute('function', trim($item['功能主治'])); + $model->setAttribute('source',trim( $item['厂家'])); + $model->setAttribute('status', trim($item['状态'])); + $model->setAttribute('is_otc',trim( $item['是否处方药'])); + $model->setAttribute('time_id',trim( $item['服用时间'])); + $model->setAttribute('type_id', trim($item['服用方法'])); + $model->setAttribute('frequency_id', trim($item['使用频率'])); + $model->setAttribute('unit_id', trim($item['用量单位'])); + $model->setAttribute('usage', trim($item['用法'])); + $model->setAttribute('type', '4'); + $model->setAttribute('created_at', time()); + if (!$model->save()) { + $errorsMsg = array_values($model->getFirstErrors()); + $errors[] = '条形码:' . $item['条形码'] . ',国子准号:' . $item['国字准号'] . '的中成药导入失败,原因:保存失败;'.$errorsMsg[0]; + }else{ + $success[] = '条形码:' . $item['条形码'] . ',国子准号:' . $item['国字准号'] . '的中成药导入成功'; + } + } else { + $errors[] = '条形码:' . $item['条形码'] . ',国子准号:' . $item['国字准号'] . '的中成药导入失败,原因:重复导入'; + } + } + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + $errors[] = $e->getMessage(); + } + return ['success' => $success, 'error' => $errors]; + } + } + + public function DivisionImport($data) + { + $user = \Yii::$app->user->identity; + $Platform_id = Platform::find()->select('id')->where([ + 'drugstore_id' => $user->drugstore, + ])->one(); + if (empty($data)) { + throw new Exception('导入数据为空'); + } else { + foreach ($data as $item) { + $t = \Yii::$app->db->beginTransaction(); + try { + $Is_PlatformDrug = PlatformDrug::find()->where([ + 'platform_id' => $Platform_id->id, + 'drug_id' => $item['药品ID'], + 'platform_drug_id' => $item['平台药品ID'], + 'is_deleted' => 0 + ])->one(); + + if (!$Is_PlatformDrug) { + $PlatformDrug = new PlatformDrug(); + $PlatformDrug->setAttribute('platform_drug_id', trim($item['平台药品ID'])); + $PlatformDrug->setAttribute('drug_id', trim($item['药品ID'])); + $PlatformDrug->setAttribute('platform_id', $Platform_id->id); + if (!$PlatformDrug->save()) { + $errorsMsg = array_values($PlatformDrug->getFirstErrors()); + return [$errorsMsg[0]]; + } + } + + $Drug = Drug::find()->where([ + 'id' => $item['药品ID'], + 'is_delete' => 0 + ])->one(); + if (!$Drug) throw new Exception('该药品不存在'); + + $Is_DrugStoreDrug = DrugStoreDrug::find()->where([ + 'drug_id' => $item['药品ID'], + 'drugstore_id' => $user->drugstore, + 'is_delete' => 0 + ])->one(); + if (!$Is_DrugStoreDrug) { + $model = new DrugStoreDrug(); + $model->setAttribute('drugstore_id', $user->drugstore); + $model->setAttribute('drug_id', trim($item['药品ID'])); + $model->setAttribute('type', $Drug->type); + $model->setAttribute('stock', $item['库存']); + $model->setAttribute('price', $item['价格']); + if (!$model->save()) { + $errorsMsg = array_values($model->getFirstErrors()); + return [$errorsMsg[0]]; + } + } + + $t->commit(); + $success[] = '分仓药品导入成功!'; + + } catch (\Exception $e) { + $t->rollBack(); + $errors[] = $e->getMessage(); + continue; + } + } + return ['success' => $success, 'error' => $errors]; + } + } + + public function ExportRealDrug($data) + { + if (empty($data)) { + throw new Exception('导入数据为空'); + } else { + $t=\Yii::$app->db->beginTransaction(); + try { + foreach ($data as $item) { + $DrugStoreDrug = DrugStoreDrug::find()->where(['drug_id' => trim($item['药品ID']), 'type' => trim($item['类别'])])->one(); + + if (!$DrugStoreDrug) { + $model = new DrugStoreDrug(); + $model->setAttribute('drugstore_id', 1); + $model->setAttribute('drug_id', trim($item['药品ID'])); + $model->setAttribute('type', trim($item['类别'])); + $model->setAttribute('price', trim($item['销售价格'])); + $model->setAttribute('market_price', trim($item['市场(指导价)价']) ?? ''); + $model->setAttribute('stock', trim($item['库存'])); + if (!$model->save()) { + $errorsMsg = array_values($model->getFirstErrors()); + $errors[] = $item['药品ID'] . '导入失败,原因:保存失败;'.$errorsMsg[0]; + }else{ + $success[] = $item['药品ID'] . '导入成功!'; + } + } else { + $errors[] = $item['药品ID'] . '导入失败,原因:重复导入'; + } + } + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + $errors[] = $e->getMessage(); + } + return ['success' => $success, 'error' => $errors]; + } + } +} \ No newline at end of file diff --git a/admin/models/forms/drug/NavForm.php b/admin/models/forms/drug/NavForm.php new file mode 100644 index 0000000..db8dae2 --- /dev/null +++ b/admin/models/forms/drug/NavForm.php @@ -0,0 +1,97 @@ + 'http'], + ['external_link', 'IsGet'], //定义验证方法 + ]; + } + + public function IsGet($attribute){ + $temp = get_headers($this->external_link,true); + if(!preg_match('/200/',$temp[0])){ + $this->addError($attribute,'该链接无效, 无法访问'); + }else{ + return true; + } + } + + public function save() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $nav=new Nav(); + $nav->pic=$this->pic; + $nav->external_link=$this->external_link; + $nav->type=$this->type; + $nav->store_id=$this->store_id; + $nav->sort=$this->sort; + $nav->link_type=$this->link_type; + if ($this->is_home==1){ + $nav->is_home=$this->is_home; + $nav->home_time=date('Y-m-d H:i:s',time()); + } + $nav->saveOrFail(); + } + + public function update() + { + $nav=Nav::find()->where([ + 'id'=>$this->id, + 'is_delete'=>0 + ])->one(); + if (!$nav) throw new Exception('轮播图不存在'); + + $nav->pic=$this->pic?? $nav->pic; + $nav->external_link=$this->external_link?? $nav->external_link; + $nav->type=$this->type?? $nav->type; + $nav->store_id=$this->store_id?? $nav->store_id; + $nav->sort=$this->sort?? $nav->sort; + $nav->link_type=$this->link_type?? $nav->link_type; + + if ($this->is_home==1) { + $nav->home_time=date('Y-m-d H:i:s',time()); + } + + $nav->saveOrFail(); + return ['编辑成功']; + } + + public function del() + { + $nav=Nav::find()->where([ + 'id'=>$this->id, + 'is_delete'=>0 + ])->one(); + if (!$nav)throw new Exception('轮播图不存在'); + $nav->is_delete=1; + $nav->saveOrFail(); + return ['删除成功']; + } + +} \ No newline at end of file diff --git a/admin/models/forms/statistics/DataForm.php b/admin/models/forms/statistics/DataForm.php new file mode 100644 index 0000000..dcbd88e --- /dev/null +++ b/admin/models/forms/statistics/DataForm.php @@ -0,0 +1,343 @@ + 1], + [['status',], 'default', 'value' => -1], + [['date_start', 'date_end', 'fields'], 'trim'], +// [['mch_per',], 'default', 'value' => false], + ]; + } + + public function init() + { + parent::init(); // TODO: Change the autogenerated stub + } + + protected function get_all_data() + { + //以下随时间查询改变 + $order_query = Order::find()->alias('o')->where(['o.is_recycle' => 0, 'o.is_delete' => 0]) + ->andWhere(['not', ['o.cancel_status' => 1]]); + + if(\Yii::$app->mallId){ + $order_query->andWhere(['o.mall_id' => \Yii::$app->mallId]); + } + + //插件分类查询 + if ($this->sign == 'all') { + } else if ($this->sign == 'mall') { + $order_query->andWhere(['o.sign' => '']); + } else { + $order_query->andWhere(['o.sign' => $this->sign]); + } + + $wait_query = clone $order_query; + $data_arr['wait_send_num'] = $wait_query->andWhere(['is_send' => 0]) + ->andWhere(['or', ['o.is_pay' => 1], ['o.pay_type' => 2]]) + ->andWhere(['o.cancel_status' => 0, 'o.sale_status' => 0]) + ->count(); + + $refund_query = OrderRefund::find()->where([ + 'status' => 1, + 'is_delete' => 0 + ]); + if(\Yii::$app->mallId){ + $refund_query->andWhere(['mall_id' => \Yii::$app->mallId,]); + } + $data_arr['wait_refund_num'] = $refund_query->count(); + + return $data_arr; + } + + //经营概况 + public function data_search() + { + if (!$this->validate()) { + throw new ApiException(implode(",",$this->getFirstErrors())); + } + $arr_list = []; + + //订单数据 + $arr_list['total_data'] = $this->today_order_data(); + + //wait数据 + $arr_list['wait_data'] = $this->get_all_data(); + + return $arr_list; + } + + /** + * 销量排行榜 + */ + public function sales_top() + { + $this->goods_order = 'num DESC'; + $goods_query = Order::find()->alias('o') + ->where([ 'o.is_recycle' => 0, 'o.is_delete' => 0])->andWhere(['not', ['o.cancel_status' => 1]]) + ->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id = o.id') + ->leftJoin(['g' => Goods::tableName()], 'g.id = od.goods_id') + ->leftJoin(['gw' => GoodsWarehouse::tableName()], 'g.goods_warehouse_id = gw.id'); + if(\Yii::$app->mallId){ + $goods_query->andWhere(['g.mall_id' => \Yii::$app->mallId,]); + } + + //排序 + $goods_query->orderBy('num DESC,g.goods_warehouse_id'); + + $goods_query->select("COALESCE(SUM(od.`num`),0) AS `num`,gw.brand,gw.name") + ->groupBy('g.goods_warehouse_id'); + + $goods_query_2 = clone $goods_query; + + $week_top_list = $goods_query + ->andWhere(['>=', 'od.created_at', strtotime(date('Y-m-d',strtotime('-7 day')) . ' 00:00:00')]) + ->andWhere(['<=', 'od.created_at', strtotime(date('Y-m-d') . ' 23:59:59')]) + ->limit(10) + ->asArray() + ->all(); + + $mouth_top_list = $goods_query_2 + ->andWhere(['>=', 'od.created_at', strtotime(date('Y-m-d',strtotime('-30 day')) . ' 00:00:00')]) + ->andWhere(['<=', 'od.created_at', strtotime(date('Y-m-d') . ' 23:59:59')]) + ->limit(10) + ->asArray() + ->all(); + + return [ + 'week_top_list' => $week_top_list, + 'mouth_top_list' => $mouth_top_list + ]; + } + + public function table_search() + { + if (!$this->validate()) { + throw new ApiException(implode(",",$this->getFirstErrors())); + } + $query = $this->table_where(); + $query->select("FROM_UNIXTIME(`o`.`created_at`, '%Y-%m-%d') AS `time`, + COALESCE(COUNT(DISTINCT `o`.`id`),0) AS `order_num`,SUM(`o`.`total_pay_price`) AS `total_pay_price`"); + + //时间查询 + if ($this->date_start) { + $query->andWhere(['>=', 'o.created_at', strtotime($this->date_start . ' 00:00:00')]); + } + if ($this->date_end) { + $query->andWhere(['<=', 'o.created_at', strtotime($this->date_end . ' 23:59:59')]); + } + + $list = $query->groupBy('time') + ->orderBy('time')->asArray()->all(); + + $day = floor((strtotime($this->date_end) - strtotime($this->date_start)) / 86400) + 1; + + for ($i = 0; $i < $day; $i++) { + $date = date('Y-m-d', strtotime("-$i day",strtotime($this->date_end))); + $bool = false; + foreach ($list as $item) { + if ($date == $item['time']) { + $bool = true; + $arr[$i]['created_at'] = $item['time']; + $arr[$i]['order_num'] = $item['order_num']; + $arr[$i]['total_pay_price'] = $item['total_pay_price']; + } + } + if (!$bool) { + $arr[$i]['created_at'] = $date; + $arr[$i]['order_num'] = '0'; + $arr[$i]['total_pay_price'] = '0.00'; + } + } + $list = !empty($arr) ? array_reverse($arr) : []; + + return $list; + } + + protected function table_where() + { + $orderQuery = OrderDetail::find()->alias('od')->where(['is_delete' => 0]) + ->select(['od.order_id', 'SUM(`od`.`num`) num'])->groupBy('od.order_id'); + //时间查询 + if ($this->date_start) { + $orderQuery->andWhere(['>=', 'od.created_at', strtotime($this->date_start . ' 00:00:00')]); + } + if ($this->date_end) { + $orderQuery->andWhere(['<=', 'od.created_at', strtotime($this->date_end . ' 23:59:59')]); + } + + $query = Order::find()->alias('o') + ->where(['o.is_recycle' => 0, 'o.is_pay' => 1]) + ->andWhere(['o.is_delete' => 0])->andWhere(['not', ['o.cancel_status' => 1]]) + ->leftJoin(['d' => $orderQuery], 'd.order_id = o.id'); +// ->leftJoin(['d' => OrderDetail::tableName()], 'd.order_id = o.id'); + + if(\Yii::$app->mallId){ + $query->andWhere(['o.mall_id' => \Yii::$app->mallId]); + } + + //插件分类查询 + if ($this->sign == 'all') { + } else if ($this->sign == 'mall') { + $query->andWhere(['o.sign' => '']); + } else { + $query->andWhere(['o.sign' => $this->sign]); + } + + return $query; + } + + protected function goods_where() + { + $query = Order::find()->alias('o') + ->where(['o.is_recycle' => 0, 'o.is_delete' => 0])->andWhere(['not', ['o.cancel_status' => 1]]) + ->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id = o.id and od.is_refund = 0')//过滤退款 + ->leftJoin(['g' => Goods::tableName()], 'g.id = od.goods_id'); + + //时间查询 + if ($this->date_start) { + $query->andWhere(['>=', 'od.created_at', $this->date_start . ' 00:00:00']); + } + + if ($this->date_end) { + $query->andWhere(['<=', 'od.created_at', $this->date_end . ' 23:59:59']); + } + + if(\Yii::$app->mallId){ + $query->andWhere(['g.mall_id' => \Yii::$app->mallId, ]); + } + + //排序 + $query->orderBy((!empty($this->goods_order) ? $this->goods_order : 'total_price DESC') . ',g.goods_warehouse_id'); + + return $query; + } + + public function today_order_data() + { + $this->date_start = date('Y-m-d',time()); + $this->date_end = date('Y-m-d',time()); + + $order_query = $this->table_where(); + + $order_query->select("COALESCE(COUNT(DISTINCT `o`.`id`),0) AS `order_num`, + COALESCE(SUM(`o`.`total_pay_price`),0) AS `total_pay_price`"); + + //比较昨日 + $list_1 = [ + 'order_num' => 0, + 'total_pay_price' => 0, + ]; + $order_query_1 = clone $order_query; + $order_query_1->andWhere(['>=', 'o.created_at', strtotime(date('Y-m-d', strtotime('-1 day')) . ' 00:00:00')]); + $order_query_1->andWhere(['<=', 'o.created_at', strtotime(date('Y-m-d', strtotime('-1 day')) . ' 23:59:59')]); + $list_1 = $order_query_1->asArray()->one(); + + //比较上周的这一日 + $list_2 = [ + 'order_num' => 0, + 'total_pay_price' => 0, + ]; + $order_query_2 = clone $order_query; + $order_query_2->andWhere(['>=', 'o.created_at', strtotime(date('Y-m-d', strtotime('-7 day')) . ' 00:00:00')]); + $order_query_2->andWhere(['<=', 'o.created_at', strtotime(date('Y-m-d', strtotime('-7 day')) . ' 23:59:59')]); + $list_2 = $order_query_2->asArray()->one(); + + //时间查询 + if ($this->date_start) { + $order_query->andWhere(['>=', 'o.created_at', strtotime($this->date_start . ' 00:00:00')]); + } + if ($this->date_end) { + $order_query->andWhere(['<=', 'o.created_at', strtotime($this->date_end . ' 23:59:59')]); + } + $list = $order_query->asArray()->one(); + + + //------------------------------------------------------------------------ + $user_query = User::find(); + + //比较昨日 + $user_num_1 = 0; + $user_query_1 = clone $user_query; + $user_query_1->andWhere(['>=', 'created_at', strtotime(date('Y-m-d', strtotime('-1 day')) . ' 00:00:00')]); + $user_query_1->andWhere(['<=', 'created_at', strtotime(date('Y-m-d', strtotime('-1 day')) . ' 23:59:59')]); + $user_num_1 = $user_query_1->count(); + + //比较上周的这一日 + $user_num_2 = 0; + $user_query_2 = clone $user_query; + $user_query_2->andWhere(['>=', 'created_at', strtotime(date('Y-m-d', strtotime('-7 day')) . ' 00:00:00')]); + $user_query_2->andWhere(['<=', 'created_at', strtotime(date('Y-m-d', strtotime('-7 day')) . ' 23:59:59')]); + $user_num_2 = $user_query_2->count(); + + if ($this->date_start) { + $user_query->andWhere(['>=', 'created_at', strtotime($this->date_start . ' 00:00:00')]); + } + if ($this->date_end) { + $user_query->andWhere(['<=', 'created_at', strtotime($this->date_end . ' 23:59:59')]); + } + $user_num = $user_query->count(); + //------------------------------------------------------------------------ + + $yestoday = []; + $yestoday['order_num_status'] = empty($list_1) || $list['order_num'] > $list_1['order_num'] ? 'up' : ($list['order_num'] < $list_1['order_num'] ? 'down' : 'equal'); + $yestoday['order_num_abs'] = abs($list['order_num']-$list_1['order_num']); + $yestoday['total_pay_price_status'] = empty($list_1) || $list['total_pay_price'] > $list_1['total_pay_price'] ? 'up' : ($list['total_pay_price'] < $list_1['total_pay_price'] ? 'down' : 'equal'); + $yestoday['total_pay_price_abs'] = abs($list['total_pay_price']-$list_1['total_pay_price']); + + $yestoday['user_num_status'] = $user_num > $user_num_1 ? 'up' : ($user_num < $user_num_1 ? 'down' : 'equal'); + $yestoday['user_num_abs'] = abs($user_num-$user_num_1); + + + $lastweek = []; + $lastweek['order_num_status'] = empty($list_2) || $list['order_num'] > $list_2['order_num'] ? 'up' : ($list['order_num'] < $list_2['order_num'] ? 'down' : 'equal'); + $lastweek['order_num_abs'] = abs($list['order_num']-$list_2['order_num']); + + $lastweek['total_pay_price_status'] = empty($list_2) || $list['total_pay_price'] > $list_2['total_pay_price'] ? 'up' : ($list['total_pay_price'] < $list_2['total_pay_price'] ? 'down' : 'equal'); + $lastweek['total_pay_price_abs'] = abs(bcsub($list['total_pay_price'],$list_2['total_pay_price'],2)); + + $lastweek['user_num_status'] = $user_num > $user_num_2 ? 'up' : ($user_num < $user_num_2 ? 'down' : 'equal'); + $lastweek['user_num_abs'] = abs($user_num-$user_num_2); + + $list['user_num'] = $user_num; + return [ + 'today' => $list, + 'yestoday' => $yestoday, + 'lastweek' => $lastweek + ]; + } +} diff --git a/admin/models/forms/statistics/ServiceDataForm.php b/admin/models/forms/statistics/ServiceDataForm.php new file mode 100644 index 0000000..5476599 --- /dev/null +++ b/admin/models/forms/statistics/ServiceDataForm.php @@ -0,0 +1,174 @@ + 1], + [['limit'], 'default', 'value' => 20], + [['date_start', 'date_end'], 'trim'], + ['is_export','default','value'=> 0] + ]; + } + + public function init() + { + parent::init(); // TODO: Change the autogenerated stub + } + + public function head_search() + { + if (!$this->validate()) { + throw new ApiException(implode(",",$this->getFirstErrors())); + } + if(!$this->date_start){ + $this->date_start = date('Y-m').'-01'; + } + if(!$this->date_end){ + $this->date_end = date('Y-m-t'); + } + + $query = ImMessageSession::find()->alias('i')->where([ + 'i.mall_id' => \Yii::$app->mallId, + 'i.type' => 0, + ])->andWhere(['<>','i.imuser_id',0])->joinWith(['imUser u'=>function($q){ + $q->andWhere(['not', ['u.id' => null]]); + }]); + if ($this->date_start) { + $query->andWhere(['>=', 'i.created_at', strtotime($this->date_start . ' 00:00:00')]); + } + if ($this->date_end) { + $query->andWhere(['<=', 'i.created_at', strtotime($this->date_end . ' 23:59:59')]); + } + $query->select("count(i.user_id) as `times`,count(distinct(i.user_id)) as `peoples`"); + $data = $query->all(); + + + $query2 = ImMessageSession::find()->alias('i')->where([ + 'i.mall_id' => \Yii::$app->mallId, + 'i.type' => 0, + ])->andWhere(['<>','i.imuser_id',0])->joinWith(['imUser u'=>function($q){ + $q->andWhere(['not', ['u.id' => null]]); + }]); + if ($this->date_start) { + $query2->andWhere(['>=', 'i.created_at', strtotime($this->date_start . ' 00:00:00')]); + } + if ($this->date_end) { + $query2->andWhere(['<=', 'i.created_at', strtotime($this->date_end . ' 23:59:59')]); + } + $query2->select("FROM_UNIXTIME(i.`created_at`, '%Y-%m-%d') AS `time`,count(i.user_id) as `times`,count(distinct(i.user_id)) as `peoples`"); + $list= $query2->groupBy('time')->orderBy('time')->asArray()->all(); + + + + $day = floor((strtotime($this->date_end) - strtotime($this->date_start)) / 86400) + 1; + for ($i = 0; $i < $day; $i++) { + $date = date('Y-m-d', strtotime("-$i day",strtotime($this->date_end))); + $bool = false; + foreach ($list as $item) { + if ($date == $item['time']) { + $bool = true; + $arr[$i]['created_at'] = $item['time']; + $arr[$i]['times'] = $item['times']; + $arr[$i]['peoples'] = $item['peoples']; + } + } + if (!$bool) { + $arr[$i]['created_at'] = $date; + $arr[$i]['times'] = 0; + $arr[$i]['peoples'] = 0; + } + } + $list = !empty($arr) ? array_reverse($arr) : []; + return [ + 'data' => $data[0], + 'table' => $list + ]; + } + + public function bottom_query() + { + if(!$this->date_start){ + $this->date_start = date('Y-m').'-01'; + } + if(!$this->date_end){ + $this->date_end = date('Y-m-t'); + } + + $query = ImMessageSession::find()->alias('i')->where([ + 'i.mall_id' => \Yii::$app->mallId, + 'i.type' => 0, + ])->andWhere(['<>','i.imuser_id',0]); + if ($this->date_start) { + $query->andWhere(['>=', 'i.created_at', strtotime($this->date_start . ' 00:00:00')]); + } + if ($this->date_end) { + $query->andWhere(['<=', 'i.created_at', strtotime($this->date_end . ' 23:59:59')]); + } + $query->joinWith(['imUser u'=>function($q){ + $q->andWhere(['not', ['u.id' => null]]); + }])->select(['i.imuser_id,COUNT(i.user_id) AS `times`,COUNT(distinct(i.user_id)) AS `peoples`'])->groupBy('i.imuser_id')->orderBy('i.imuser_id desc'); + return $query; + } + public function bottom_search() + { + if (!$this->validate()) { + throw new ApiException(implode(",",$this->getFirstErrors())); + } + $query = $this->bottom_query(); + + if ($this->is_export) { + $fields = [ + 'imuser_name','times','peoples' + ]; + $queueId = CommonExport::handle([ + 'export_class' => 'backend\\models\\forms\\export\\ServiceExport', + 'params' => [ + 'fieldsKeyList' => $fields, + ], + 'model_class' => 'backend\\models\\forms\\statistics\\ServiceDataForm', + 'model_params' => $this->attributes, + 'function_name' => 'bottom_query' + ]); + return [ + 'queue_id' => $queueId + ]; + } + $data = new ActiveDataProvider([ + 'query' => $query, + 'pagination' => [ + 'defaultPageSize' => $this->limit, + 'params' => [ + 'page' => $this->page + ] + ] + ]); + + return $data; + } + +} diff --git a/admin/models/search/AdminSearch.php b/admin/models/search/AdminSearch.php new file mode 100644 index 0000000..3017fc0 --- /dev/null +++ b/admin/models/search/AdminSearch.php @@ -0,0 +1,85 @@ + $query, + 'pagination' => [ + 'pageSize' => 10, + ], + ]); + + $this->load($params); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + $query->andFilterWhere([ + 'uid' => $this->uid, + 'reg_time' => $this->reg_time, + 'reg_ip' => $this->reg_ip, + 'last_login_time' => $this->last_login_time, + 'last_login_ip' => $this->last_login_ip, + 'update_time' => $this->update_time, + 'status' => $this->status, + ]); + + $query->andFilterWhere(['like', 'username', $this->username]) + ->andFilterWhere(['like', 'password', $this->password]) + ->andFilterWhere(['like', 'salt', $this->salt]) + ->andFilterWhere(['like', 'email', $this->email]) + ->andFilterWhere(['like', 'mobile', $this->mobile]); + + /* 排序 */ + $query->orderBy([ + 'uid' => SORT_ASC, + ]); + + return $dataProvider; + } +} diff --git a/admin/models/search/CommonSearch.php b/admin/models/search/CommonSearch.php new file mode 100644 index 0000000..e41906f --- /dev/null +++ b/admin/models/search/CommonSearch.php @@ -0,0 +1,184 @@ +defaultSort = $sort; + } + + public function injectFilters($filters){ + foreach ($filters as $filter){ + if(!isset($filter['rules'])){ + $this->addRule($filter['field'],'string'); + }else{ + foreach ($filter['rules'] as $rule){ + $this->addRule(...$rule); + } + } + $searchField = $filter['field']; + if(isset($filter['searchFields'])){ + $searchField = $filter['searchFields']; + } + $searchFields = explode(',',$searchField); + if(isset($filter['searchType'])) { + switch ($filter['searchType']) { + case 'like': + if (count($searchFields) > 1) { + $condition[] = 'or'; + foreach ($searchFields as $sf) { + $condition[] = ['like', 'name', $this->$sf]; + } + } else { + $condition = ['like', 'name', $this->{$searchFields[0]}]; + } + $this->bindFilter(function ($q) use ($condition) { + return $q->andFilterWhere($condition); + }); + break; + case 'equal': + if (count($searchFields) > 1) { + $condition[] = 'or'; + foreach ($searchFields as $sf) { + $condition[] = ['like', 'name', $this->$sf]; + } + } else { + $condition = ['like', 'name', $this->{$searchFields[0]}]; + } + $this->bindFilter(function ($q) use ($condition) { + return $q->andFilterWhere($condition); + }); + break; + default: + //$condition[] = 'or'; + //foreach ($searchFields as $sf) { + // $condition[] = [$sf => $this->$sf]; + //} + //$this->bindFilter(function ($q) use ($condition) { + // return $q->andFilterWhere($condition); + //}); + break; + break; + + //case 'select': + // $filter1->select($filter['data']); + // break; + //case 'cascader': + // $filter1->cascader($filter['data']); + // break; + //case 'date': + // $filter1->date($filter['placeholder']); + // break; + //case 'datetime': + // $filter1->datetime($filter['placeholder']); + // break; + //case 'daterange': + // $filter1->daterange($filter['placeholder']); + // break; + } + } + } + } + + public function setQuery($query){ + $this->query = $query; + } + + /** + * @inheritdoc + */ + public function rules() + { + return array_merge([ + ['page','integer','min'=>1,'max'=>99999], + ['limit','integer','min'=>1,'max'=>500], + ],$this->additionRules); + } + + /** + * @inheritdoc + */ + public function scenarios() + { + // bypass scenarios() implementation in the parent class + return Model::scenarios(); + } + /** + * Creates data provider instance with search query applied + * + * @param array $params + * + * @return ActiveDataProvider|array + */ + public function search($params) + { + + $dataProvider = new ActiveDataProvider([ + 'query' => $this->query, + 'sort'=>[ + 'defaultOrder'=>$this->defaultSort + ] + ]); + $this->load($params,''); + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return ['error'=>$this->getErrors()]; + } // add conditions that should always apply here + $pagination = []; + $defaultPageSize = 20; + if (isset($this->page)) { + $pagination['page'] = $this->page; + } + if (isset($this->limit)) { + $defaultPageSize = $this->limit; + } + $pagination = [ + 'defaultPageSize' => $defaultPageSize, + 'params' => $pagination + ]; + $dataProvider->setPagination($pagination); + // grid filtering conditions + + if(!empty($this->filters)){ + foreach($this->filters as $filter){ + $filter->call($this,$this->query); + } + } + return $dataProvider; + } + + public function bindFilter(\Closure $func){ + $this->filters[] = $func->bindTo($this,static::class); + } +} diff --git a/admin/models/search/ConfigSearch.php b/admin/models/search/ConfigSearch.php new file mode 100644 index 0000000..6a57d08 --- /dev/null +++ b/admin/models/search/ConfigSearch.php @@ -0,0 +1,92 @@ + $query, + 'pagination' => [ + 'pageSize' => isset($params['limit']) ? $params['limit'] : 10, + ], + ]); + + $this->load($params,''); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + $query->andFilterWhere([ + 'id' => $this->id, + 'group' => $this->group, + 'type' => $this->type, + 'create_time' => $this->create_time, + 'update_time' => $this->update_time, + 'sort' => $this->sort, + 'status' => $this->status, + ]); + + $query->andFilterWhere(['like', 'name', $this->name]) + ->andFilterWhere(['like', 'title', $this->title]) + ->andFilterWhere(['like', 'value', $this->value]) + ->andFilterWhere(['like', 'extra', $this->extra]) + ->andFilterWhere(['like', 'remark', $this->remark]); + + /* 条件搜索 */ + + + /* 排序 */ + $query->orderBy([ + 'sort' => SORT_ASC, + ]); + + return $dataProvider; + } +} diff --git a/admin/models/search/MenuSearch.php b/admin/models/search/MenuSearch.php new file mode 100644 index 0000000..2001149 --- /dev/null +++ b/admin/models/search/MenuSearch.php @@ -0,0 +1,75 @@ + $query, + ]); + + $this->load($params); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + /* 条件搜索 */ + $pid = Yii::$app->request->get('pid',0); + $query->andFilterWhere(['pid' => $pid]); + + $query->andFilterWhere([ + 'hide' => $this->hide, + ]); + + $query->andFilterWhere(['like', 'title', $this->title]); + + /* 排序 */ + $query->orderBy([ + 'sort' => SORT_ASC, + ]); + + return $dataProvider; + } +} diff --git a/admin/tests/_bootstrap.php b/admin/tests/_bootstrap.php new file mode 100644 index 0000000..637ce14 --- /dev/null +++ b/admin/tests/_bootstrap.php @@ -0,0 +1,10 @@ + 'erau', + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', + // password_0 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', + 'created_at' => '1392559490', + 'updated_at' => '1392559490', + 'email' => 'sfriesen@jenkins.info', + ], +]; diff --git a/admin/tests/_output/.gitignore b/admin/tests/_output/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/admin/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/admin/tests/_support/.gitignore b/admin/tests/_support/.gitignore new file mode 100644 index 0000000..36e264c --- /dev/null +++ b/admin/tests/_support/.gitignore @@ -0,0 +1 @@ +_generated diff --git a/admin/tests/_support/FunctionalTester.php b/admin/tests/_support/FunctionalTester.php new file mode 100644 index 0000000..092e16e --- /dev/null +++ b/admin/tests/_support/FunctionalTester.php @@ -0,0 +1,26 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'login_data.php' + ] + ]; + } + + /** + * @param FunctionalTester $I + */ + public function loginUser(FunctionalTester $I) + { + $I->amOnRoute('/site/register'); + $I->fillField('Username', 'erau'); + $I->fillField('Password', 'password_0'); + $I->click('register-button'); + + $I->see('Logout (erau)', 'form button[type=submit]'); + $I->dontSeeLink('register'); + $I->dontSeeLink('Signup'); + } +} diff --git a/admin/tests/functional/_bootstrap.php b/admin/tests/functional/_bootstrap.php new file mode 100644 index 0000000..30ed54b --- /dev/null +++ b/admin/tests/functional/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/admin/tests/unit.suite.yml b/admin/tests/unit.suite.yml new file mode 100644 index 0000000..a5d4e7d --- /dev/null +++ b/admin/tests/unit.suite.yml @@ -0,0 +1,2 @@ +suite_namespace: admin\tests\unit +actor: UnitTester diff --git a/admin/tests/unit/_bootstrap.php b/admin/tests/unit/_bootstrap.php new file mode 100644 index 0000000..e432ce5 --- /dev/null +++ b/admin/tests/unit/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Tests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ diff --git a/admin/views/register.php b/admin/views/register.php new file mode 100644 index 0000000..b0b985a --- /dev/null +++ b/admin/views/register.php @@ -0,0 +1,22 @@ + + + + + + + + + 表单提交 + + +
+ 姓名:
+ 密码:
+ + +
+ + diff --git a/common/codeception.yml b/common/codeception.yml new file mode 100644 index 0000000..1dfaf97 --- /dev/null +++ b/common/codeception.yml @@ -0,0 +1,15 @@ +namespace: common\tests +actor_suffix: Tester +paths: + tests: tests + output: tests/_output + data: tests/_data + support: tests/_support +bootstrap: _bootstrap.php +settings: + colors: true + memory_limit: 1024M +modules: + config: + Yii2: + configFile: 'config/codeception-local.php' diff --git a/common/components/Aliyunoss.php b/common/components/Aliyunoss.php new file mode 100644 index 0000000..b3952e0 --- /dev/null +++ b/common/components/Aliyunoss.php @@ -0,0 +1,120 @@ +params['oss']['accessKeyId']; //获取阿里云oss的accessKeyId + + $accessKeySecret = Yii::$app->params['oss']['accessKeySecret']; //获取阿里云oss的accessKeySecret + + $endpoint = Yii::$app->params['oss']['endPoint']; //获取阿里云oss的endPoint + + self::$oss = new OssClient($accessKeyId, $accessKeySecret, $endpoint); //实例化OssClient对象 + + } + + + + /** + + * 使用阿里云oss上传文件 + + * @param $object 保存到阿里云oss的文件名 + + * @param $filepath 文件在本地的绝对路径 + + * @return bool 上传是否成功 + + */ + + public function upload($object, $filepath) + + { + $bucket = Yii::$app->params['oss']['bucket']; //获取阿里云oss的bucket + $result=array(); + try{ + $getOssInfo=self::$oss->uploadFile($bucket, $object, $filepath); + $result['url'] = $getOssInfo['info']['url']; + if($getOssInfo['info']['url']){ + @unlink(substr($_path, 1)); + } + }catch(OssException $e){ + + var_dump($e); + + return; + }; + + $url=$result['url']; + + return $url; + // var_dump("$url");die(); + // $res = true; + // return $url; + } + + /** + + * 删除指定文件 + + * @param $object 被删除的文件名 + + * @return bool 删除是否成功 + + */ + + public function delete($object) + + { + + $res = false; + + $bucket = Yii::$app->params['oss']['bucket']; //获取阿里云oss的bucket + + if (self::$oss->deleteObject($bucket, $object)){ + + //调用deleteObject方法把服务器文件上传到阿里云oss + + $res = true; + } + return $res; + + } + +//测试 + public function test(){ + echo 123; + echo "success"; + + } + +} diff --git a/common/components/ApiErrorHandler.php b/common/components/ApiErrorHandler.php new file mode 100644 index 0000000..14f967b --- /dev/null +++ b/common/components/ApiErrorHandler.php @@ -0,0 +1,12 @@ + 'zh-CN', //全局设置为中文 + 'aliases' => [ + '@bower' => '@vendor/bower-asset', + '@npm' => '@vendor/npm-asset', + ], + 'vendorPath' => dirname(dirname(__DIR__)) . '/vendor', + 'bootstrap' => ['queue','queue4'], + 'components' => [ + 'queue' => [ + 'class' => \yii\queue\db\Queue::class, + 'db' => 'db', // DB connection component or its config + 'tableName' => '{{%queue}}', // Table name + 'channel' => 'default', // Queue channel key + 'mutex' => \yii\mutex\MysqlMutex::class, // Mutex used to sync queries + 'ttr' => 5 * 60, // Max time for job execution + 'attempts' => 3, // Max number of attempts + 'as log' => \yii\queue\LogBehavior::class, +// 'commandClass'=>\common\foundation\MyCommand::class + ], + 'queue4' => [ + 'class' => \yii\queue\db\Queue::class, + 'db' => 'db', // DB connection component or its config + 'tableName' => '{{%queue}}', // Table name + 'channel' => 'default', // Queue channel key + 'mutex' => \yii\mutex\MysqlMutex::class, + 'ttr' => 5 * 60, // Max time for job execution + 'attempts' => 3, // Max number of attempts + 'as log' => \yii\queue\LogBehavior::class, +// 'commandClass'=>\common\components\MyCommand::class + ], + 'redis' => [ + 'class' => 'yii\redis\Connection', + 'hostname' => env('REDIS_HOST'), + 'port' => env('REDIS_PORT'), + 'password' => env('REDIS_PASSWORD'), + 'database' => 1, + ], +// 'cache' => [ +// 'class' => \yii\caching\FileCache::class, +// ], + 'cache' => [ + 'class' => \yii\redis\Cache::class, + 'redis'=>'redis' + ], + 'Aliyunoss' => [ + 'class' => 'common\components\Aliyunoss', + ], + 'log' => [ + 'traceLevel' => YII_DEBUG ? 3 : 0, + 'targets' => [ + [ + 'logVars' => [], + 'class' => 'yii\log\FileTarget', + 'levels' => ['info'], + 'categories' => ['yii\db\Command::query'], + 'maxFileSize' => 10240, + 'maxLogFiles' => 30, + 'logFile' => '@app/runtime/logs/sql/sql-' . date('Y-m-d') . '.log', + ], + [ + 'class' => 'yii\log\FileTarget', + 'levels' => ['info'], + 'logFile' => '@app/runtime/logs/all-' . date('Y-m-d') . '.log', + ], + ], + ], + ], + +]; diff --git a/common/config/params.php b/common/config/params.php new file mode 100644 index 0000000..17be120 --- /dev/null +++ b/common/config/params.php @@ -0,0 +1,10 @@ + 'admin@example.com', + 'supportEmail' => 'support@example.com', + 'senderEmail' => 'noreply@example.com', + 'senderName' => 'Example.com mailer', + 'user.passwordResetTokenExpire' => 3600, + 'user.passwordMinLength' => 8, +]; diff --git a/common/config/test-local.php b/common/config/test-local.php new file mode 100644 index 0000000..a010219 --- /dev/null +++ b/common/config/test-local.php @@ -0,0 +1,9 @@ + [ + 'db' => [ + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced_test', + ], + ], +]; diff --git a/common/config/test.php b/common/config/test.php new file mode 100644 index 0000000..c50955f --- /dev/null +++ b/common/config/test.php @@ -0,0 +1,11 @@ + 'app-common-tests', + 'basePath' => dirname(__DIR__), + 'components' => [ + 'user' => [ + 'class' => \yii\web\User::class, + 'identityClass' => 'common\models\User', + ], + ], +]; diff --git a/common/core/Application.php b/common/core/Application.php new file mode 100644 index 0000000..2dda4e2 --- /dev/null +++ b/common/core/Application.php @@ -0,0 +1,39 @@ +hostInfo) { + return $this->hostInfo; + } + return ''; + } + public function setHostInfo($hostInfo) + { + $this->hostInfo = $hostInfo; + } + + public function getBaseUrl() + { + if ($this->baseUrl) { + return $this->baseUrl; + } + return ''; + } + public function setBaseUrl($baseUrl) + { + $this->baseUrl = $baseUrl; + } +} \ No newline at end of file diff --git a/common/core/BackendApplication.php b/common/core/BackendApplication.php new file mode 100644 index 0000000..c34e701 --- /dev/null +++ b/common/core/BackendApplication.php @@ -0,0 +1,97 @@ +loadAppHandler(); + } + + /** + * @return $this + */ + protected function loadAppHandler() + { + $register = new HandlerRegister(); + $HandlerClasses = $register->getHandlers(); + foreach ($HandlerClasses as $HandlerClass) { + $handler = new $HandlerClass(); + if ($handler instanceof HandlerBase) { + /** @var HandlerBase $handler */ + $handler->register(); + } + } + return $this; + } + + public function setMall($mall) + { + $this->mall = $mall; + } + public function getMall() + { + if(!$this->mall){ + $mallId = $this->mallId; + if(!$mallId){ + throw new Exception('门店不存在'); + } + $mall = Mall::findOne($mallId); + if(!$mall){ + throw new Exception('门店不存在'); + } + $this->mall = $mall; + } + return $this->mall; + } + + public function getHostInfo() + { + if ($this->hostInfo) { + return $this->hostInfo; + } + return ''; + } + public function setHostInfo($hostInfo) + { + $this->hostInfo = $hostInfo; + } + + + public function getBaseUrl() + { + if ($this->baseUrl) { + return $this->baseUrl; + } + return ''; + } + public function setBaseUrl($baseUrl) + { + $this->baseUrl = $baseUrl; + } +} \ No newline at end of file diff --git a/common/core/BaseActiveRecord.php b/common/core/BaseActiveRecord.php new file mode 100644 index 0000000..a0cc596 --- /dev/null +++ b/common/core/BaseActiveRecord.php @@ -0,0 +1,18 @@ +save($runValidation, $attributeNames)){ + throw new Exception(implode(',',$this->getFirstErrors())); + } + return true; + } +} diff --git a/common/core/BaseAdminController.php b/common/core/BaseAdminController.php new file mode 100644 index 0000000..b33695c --- /dev/null +++ b/common/core/BaseAdminController.php @@ -0,0 +1,57 @@ +language = Yii::$app->request->getHeaders()->get('app-language'); //'en-US'; + \Yii::$app->params['web'] = Config::lists(); + } + + final public function behaviors() + { + $behaviors = parent::behaviors(); + $newBehaviors = []; + $newBehaviors['corsFilter'] = [ + 'class' => Cors::class, + ]; + foreach ($behaviors as $k=>$v){ + $newBehaviors[$k]=$v; + } + //unset($behaviors['authenticator']); //删掉,保持先cors,后authenticator + // 设置认证方式,接口才认证 + $newBehaviors['authenticator'] = [ + 'class' => HttpBearerAuth::class, + 'optional' => $this->optional, + ]; + return $newBehaviors; + } + public function beforeAction($action) + { + $ret = parent::beforeAction($action); // TODO: Change the autogenerated stub + //不同角色权限 + if(!\Yii::$app->user->isGuest){ + $admin = \Yii::$app->user->identity; + $this->mallId = 0; + switch ($admin->role){ + //角色1为官方管理 + case 1: + //官方管理 +// $this->mallId = FakeId::decodeId($this->get("mallId",0)); + break; + } + \Yii::$app->mallId=$this->mallId; + } + return $ret; + } +} diff --git a/common/core/BaseAppController.php b/common/core/BaseAppController.php new file mode 100644 index 0000000..750226f --- /dev/null +++ b/common/core/BaseAppController.php @@ -0,0 +1,45 @@ +language = Yii::$app->request->getHeaders()->get('app-language'); //'en-US'; + \Yii::$app->params['web'] = Config::lists(); + } + + /** + * 行为 + */ + final public function behaviors() + { + $behaviors = parent::behaviors(); + $newBehaviors = []; + $newBehaviors['corsFilter'] = [ + 'class' => Cors::class, + ]; + foreach ($behaviors as $k=>$v){ + $newBehaviors[$k]=$v; + } + unset($behaviors['authenticator']); //删掉,保持先cors,后authenticator + //设置认证方式,接口才认证 + $newBehaviors['authenticator'] = [ + 'class' => HttpBearerAuth::class, + 'optional' => $this->optional, + ]; + $newBehaviors['storeId'] = [ + 'class' => MallBehavior::class, + ]; + return $newBehaviors; + } + +} diff --git a/common/core/BaseController.php b/common/core/BaseController.php new file mode 100644 index 0000000..101d1b6 --- /dev/null +++ b/common/core/BaseController.php @@ -0,0 +1,178 @@ + $query, + 'pagination' => [ + 'defaultPageSize' => $defaultPageSize, + 'params' => $pagination + ] + ]); + } + + /** + * 当前登陆用户ID + * @return int|string + */ + public function getCurrentUserId() + { + return Yii::$app->user->identity->getId(); + } + + /** + * 取post参数 + * @param $name + * @param $defaultValue + * @return array|mixed + */ + public function post($name = null, $defaultValue = null) + { + return Yii::$app->request->post($name, $defaultValue); + } + + /** + * 取get参数 + * @param $name + * @param $defaultValue + * @return array|mixed + */ + public function get($name = null, $defaultValue = null) + { + return Yii::$app->request->get($name, $defaultValue); + } + + /** + * 参数验证 + * @param $data + * @param $rules + * @return DynamicModel|\stdClass + * @throws + */ + public function requestValidate($data, $rules) + { + foreach ($rules as $rule) { + if (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type + foreach ((array)$rule[0] as $r) { + if (!isset($data[$r])) { + $data[$r] = null; + } + } + } + } + $validate = DynamicModel::validateData($data, $rules); + if ($validate->hasErrors()) { + throw new InvalidArgumentException(current($validate->getFirstErrors())); + } + return $validate; + } + + public function serializeData($data) + { + if(Yii::$app->response->format== Response::FORMAT_RAW){ + return $data; + } + if ($data instanceof Model && $data->hasErrors()) { + throw new InvalidArgumentException('参数错误。'.implode('',$data->getFirstErrors())); +// $data = $this->serializeModelErrors($data); + } elseif ($data instanceof Arrayable) { + $data = $this->serializeModel($data); + } elseif ($data instanceof DataProviderInterface) { + $data = $this->serializeDataProvider($data); + }elseif($data ===null){ + $data = []; + } + return array_merge($this->extend_result,$data); + } + + protected function serializeDataProvider($dataProvider) + { + if(!empty($this->field)){ + $models = ArrayHelper::toArray($dataProvider->getModels(),$this->field); + }else{ + $models = array_values($dataProvider->getModels()); + $models = $this->serializeModels($models); + } + $pagination = $dataProvider->getPagination(); + $result = [ + $this->listkey => $models, + ]; + if ($pagination !== false) { + return array_merge($result, $this->serializePagination($pagination)); + } + + return $result; + } + + /** + * Serializes a model object. + * @param Arrayable $model + * @return array the array representation of the model + */ + protected function serializeModel($model) + { + return $model->toArray(); + } + + protected function serializeModels(array $models) + { + foreach ($models as $i => $model) { + if ($model instanceof Arrayable) { + $models[$i] = $model->toArray(); + } elseif (is_array($model)) { + $models[$i] = ArrayHelper::toArray($model); + } + } + + return $models; + } + + protected function serializePagination($pagination) + { + return [ + $this->pagekey => [ + 'total' => $pagination->totalCount, + 'totalPage' => $pagination->getPageCount(), + 'pageSize' => $pagination->getPageSize(), + ], + ]; + } + + final public function afterAction($action, $result) + { + $result = parent::afterAction($action, $result); + return $this->serializeData($result); + } +} diff --git a/common/core/BaseModel.php b/common/core/BaseModel.php new file mode 100644 index 0000000..2c8c80c --- /dev/null +++ b/common/core/BaseModel.php @@ -0,0 +1,35 @@ +errors) ? current($model->errors)[0] : '数据异常!'; + return $msg; + } + + public function setSign($val) + { + $this->sign = $val; + return $this; + } +} diff --git a/common/core/BasePharmacistController.php b/common/core/BasePharmacistController.php new file mode 100644 index 0000000..1ef3e04 --- /dev/null +++ b/common/core/BasePharmacistController.php @@ -0,0 +1,42 @@ +language = Yii::$app->request->getHeaders()->get('app-language'); //'en-US'; + \Yii::$app->params['web'] = Config::lists(); + } + + /** + * 行为 + */ + final public function behaviors() + { + $behaviors = parent::behaviors(); + $newBehaviors = []; + $newBehaviors['corsFilter'] = [ + 'class' => Cors::class, + ]; + foreach ($behaviors as $k=>$v){ + $newBehaviors[$k]=$v; + } + unset($behaviors['authenticator']); //删掉,保持先cors,后authenticator + //设置认证方式,接口才认证 + $newBehaviors['authenticator'] = [ + 'class' => HttpBearerAuth::class, + 'optional' => $this->optional, + ]; + return $newBehaviors; + } + +} diff --git a/common/core/BasePlatformController.php b/common/core/BasePlatformController.php new file mode 100644 index 0000000..2c1de02 --- /dev/null +++ b/common/core/BasePlatformController.php @@ -0,0 +1,37 @@ +language = Yii::$app->request->getHeaders()->get('app-language'); //'en-US'; + \Yii::$app->params['web'] = Config::lists(); + } + + final public function behaviors() + { + $behaviors = parent::behaviors(); + $newBehaviors = []; + $newBehaviors['corsFilter'] = [ + 'class' => Cors::class, + ]; + foreach ($behaviors as $k=>$v){ + $newBehaviors[$k]=$v; + } + unset($behaviors['authenticator']); //删掉,保持先cors,后authenticator + //设置认证方式,接口才认证 + $newBehaviors['authenticator'] = [ + 'class' => HttpBearerAuth::class, + 'optional' => $this->optional, + ]; + return $newBehaviors; + } +} diff --git a/common/core/BaseServiceController.php b/common/core/BaseServiceController.php new file mode 100644 index 0000000..9b6e66f --- /dev/null +++ b/common/core/BaseServiceController.php @@ -0,0 +1,65 @@ +language = Yii::$app->request->getHeaders()->get('app-language'); //'en-US'; + \Yii::$app->params['web'] = Config::lists(); + } + + final public function behaviors() + { + $behaviors = parent::behaviors(); + $newBehaviors = []; + $newBehaviors['corsFilter'] = [ + 'class' => Cors::class, + ]; + foreach ($behaviors as $k=>$v){ + $newBehaviors[$k]=$v; + } + unset($behaviors['authenticator']); //删掉,保持先cors,后authenticator + //设置认证方式,接口才认证 + $newBehaviors['authenticator'] = [ + 'class' => HttpBearerAuth::class, + 'optional' => $this->optional, + ]; + return $newBehaviors; + } + + public function beforeAction($action) + { + $ret = parent::beforeAction($action); // TODO: Change the autogenerated stub + //判断是否是游客 + if(!\Yii::$app->user->isGuest){ + if (\Yii::$app->request->isPost){ + $this->store=$this->post('store_id'); + } + if (\Yii::$app->request->isGet){ + $this->store=$this->get('store_id'); + } + \Yii::$app->store=$this->store; + if (empty(\Yii::$app->store)){ + throw new Exception('参数store_id不能为空'); + } + }else{ + //游客模式 + \Yii::$app->store=$this->store=11001;//默认门店 + } + return $ret; + } +} diff --git a/common/core/ConsoleApplication.php b/common/core/ConsoleApplication.php new file mode 100644 index 0000000..452bb13 --- /dev/null +++ b/common/core/ConsoleApplication.php @@ -0,0 +1,32 @@ +loadAppHandler(); + } + + protected function loadAppHandler() + { + + } + + + +} \ No newline at end of file diff --git a/common/core/Request.php b/common/core/Request.php new file mode 100644 index 0000000..5c4d33a --- /dev/null +++ b/common/core/Request.php @@ -0,0 +1,39 @@ +get($name); + $value = (!empty($value)) ? $this->get($name) : $this->post($name); + $value = (!empty($value)) ? $value : $defaultValue; + return $value; + } + + /** + * --------------------------------------- + * 获取页面GET/POST的int数据 + * @param string $name 参数名 + * @param string $defaultValue 默认值 + * @return mixed + * --------------------------------------- + */ + public function paramInt($name, $defaultValue = null) + { + return intval($this->param($name, $defaultValue)); + } +} diff --git a/common/core/TokenAuth.php b/common/core/TokenAuth.php new file mode 100644 index 0000000..edf5871 --- /dev/null +++ b/common/core/TokenAuth.php @@ -0,0 +1,149 @@ + [ + * 'class' => \common\core\TokenAuth::className(), + * ], + * ]; + * } + * ``` + * + * @author longfei + * @since 2.0 + */ +class TokenAuth extends HttpBearerAuth +{ + + //public $optional = ['*']; + + /** + * --------------------------------------- + * 功能说明 + * + * @param \yii\base\Action $action + * @return bool + * @throws UnauthorizedHttpException + * @author hlf 2020/5/21 + * --------------------------------------- + */ + public function beforeAction($action) + { + $response = $this->response ?: Yii::$app->getResponse(); + + try { + $identity = $this->authenticate( + $this->user ?: Yii::$app->getUser(), + $this->request ?: Yii::$app->getRequest(), + $response + ); + } catch (UnauthorizedHttpException $e) { + if ($this->isOptional($action)) { + return true; + } + + throw $e; + } + + if ($identity !== null || $this->isOptional($action)) { + return true; + } + + $this->challenge($response); + $this->handleFailure($response); + + return false; + } + + /** + * --------------------------------------- + * 验证当前用户 + * + * @param User $user + * @param Request $request + * @param Response $response + * @return null|\yii\web\IdentityInterface + * @throws UnauthorizedHttpException + * @author hlf 2020/5/21 + * --------------------------------------- + */ + public function authenticate($user, $request, $response) + { + // 当 $identity = null 时表示无法获取的认证信息或者认证失败 + // $identity = null 时为游客 + // $identity = parent::authenticate($user, $request, $response); + $authHeader = $request->getHeaders()->get($this->header); + + if ($authHeader !== null) { + if ($this->pattern !== null) { + if (preg_match($this->pattern, $authHeader, $matches)) { + $authHeader = $matches[1]; + } else { + return null; + } + } + + $identity = $user->loginByAccessToken($authHeader, get_class($this)); + if ($identity === null) { + $this->challenge($response); + $this->handleFailure($response); + } + + return $identity; + } + + return null; + + } + + /** + * --------------------------------------- + * 身份认证失败时 + * 例如,可以生成一些适当的HTTP头。 + * + * @param Response $response + * @author hlf 2020/5/21 + * --------------------------------------- + */ + public function challenge($response) + { + $response->getHeaders()->set('WWW-Authenticate', "Bearer realm=\"{$this->realm}\""); + + } + + /** + * --------------------------------------- + * 处理身份认证失败 + * 通常应该抛出UnauthorizedHttpException以指示身份验证失败。 + * + * @param Response $response + * @throws UnauthorizedHttpException + * @author hlf 2020/5/21 + * --------------------------------------- + */ + public function handleFailure($response) + { + throw new UnauthorizedHttpException(Yii::t('api', 'Token权限认证失败')); + } +} diff --git a/common/core/UrlManager.php b/common/core/UrlManager.php new file mode 100644 index 0000000..f988a24 --- /dev/null +++ b/common/core/UrlManager.php @@ -0,0 +1,13 @@ +loadAppHandler(); + + } + + protected function loadAppHandler() + { + \Yii::$app->on(Prescription::AUTO_EXPIRE, function ($event) { + /** @var PrescriptionEvent $event */ + $handler = new PrescriptionAutoExpireHandlerClass(); + $handler->event = $event; + $handler->handle(); + }); + + \Yii::$app->on(ProductOrder::EVENT_CREATED, function ($event) { + /** @var ProductOrderEvent $event */ + $handler = new ProductOrderCreatedHandlerClass(); + $handler->event = $event; + $handler->handle(); + }); + + \Yii::$app->on(ProductOrder::EVENT_PAYED, function ($event) { + /** @var ProductOrderEvent $event */ + $handler = new ProductOrderPayedHandlerClass(); + $handler->event = $event; + $handler->handle(); + }); + + \Yii::$app->on(Register::EVENT_CREATED, function ($event) { + /** @var RegisterEvent $event */ + $handler = new RegisterCreatedHandler(); + $handler->event = $event; + $handler->handle(); + }); + + \Yii::$app->on(Register::EVENT_PAYED, function ($event) { + /** @var RegisterEvent $event */ + $handler = new RegisterPayHandler(); + $handler->event = $event; + $handler->handle(); + }); + + } + + + +} \ No newline at end of file diff --git a/common/core/rbac/DbManager.php b/common/core/rbac/DbManager.php new file mode 100644 index 0000000..6638129 --- /dev/null +++ b/common/core/rbac/DbManager.php @@ -0,0 +1,94 @@ +getRule($name)) { + /* 更新 */ + + } else { + /* 添加 */ + $rule = new Rule(); + $rule->name = $name; + $this->add($rule); + } + + /* 判断auth_item表是否存在 */ + if ($item = $this->getItem($name)) { + /* 更新 */ + + } else { + /* 添加 */ + $item = new Item(); + $item->name = $name; + $item->type = 2; + $item->ruleName = $name; + $this->add($item); + } + } + + /** + * --------------------------------------- + * 保存角色的权限分配 + * @param string $parent 角色name + * @param string $child 权限name + * --------------------------------------- + */ + public function saveChild($parent, $child){ + /* 判断auth_item_child表是否存在 */ + $parent = $this->getRole($parent); + $child = $this->getItem($child); + if (!$this->hasChild($parent, $child)) { + $this->addChild($parent, $child); + } + + } + + /** + * --------------------------------------- + * 更新auth_item + * --------------------------------------- + */ + protected function updateRule($name, $rule) + { + if ($rule->name !== $name && !$this->supportsCascadeUpdate()) { + $this->db->createCommand() + ->update($this->itemTable, [ + 'rule_name' => $rule->name, + 'name' => $rule->name, + ], [ + 'rule_name' => $name + ])->execute(); + } + + $rule->updatedAt = time(); + + $this->db->createCommand() + ->update($this->ruleTable, [ + 'name' => $rule->name, + 'data' => serialize($rule), + 'updated_at' => $rule->updatedAt, + ], [ + 'name' => $name, + ])->execute(); + + $this->invalidateCache(); + + return true; + } + + +} \ No newline at end of file diff --git a/common/core/rbac/Rule.php b/common/core/rbac/Rule.php new file mode 100644 index 0000000..e842546 --- /dev/null +++ b/common/core/rbac/Rule.php @@ -0,0 +1,27 @@ +captcha = $captcha; + $this->captchaConfig = $captchaConfig; + } + + // 定义直接使用内容发送平台的内容 + public function getContent(GatewayInterface $gateway = null) + { + return sprintf('您的验证码为:', $this->captcha); + } + + // 定义使用模板发送方式平台所需要的模板 ID + public function getTemplate(GatewayInterface $gateway = null) + { + return $this->captchaConfig['template_id']; + } + + // 模板参数 + public function getData(GatewayInterface $gateway = null) + { + return [ + $this->captchaConfig['template_variable'] => $this->captcha + ]; + } +} diff --git a/common/core/sms/NewOrderMessage.php b/common/core/sms/NewOrderMessage.php new file mode 100644 index 0000000..61cdb7b --- /dev/null +++ b/common/core/sms/NewOrderMessage.php @@ -0,0 +1,46 @@ +order_no = $order_no; + $this->smsConfig = $smsConfig; + } + + // 定义直接使用内容发送平台的内容 + public function getContent(GatewayInterface $gateway = null) + { + return sprintf('您有一条新的订单,订单号:', $this->order_no); + } + + // 定义使用模板发送方式平台所需要的模板 ID + public function getTemplate(GatewayInterface $gateway = null) + { + return $this->smsConfig['template_id']; + } + + // 模板参数 + public function getData(GatewayInterface $gateway = null) + { + return [ + $this->smsConfig['template_variable'] => $this->order_no + ]; + } +} diff --git a/common/core/sms/OrderRefundMessage.php b/common/core/sms/OrderRefundMessage.php new file mode 100644 index 0000000..718585e --- /dev/null +++ b/common/core/sms/OrderRefundMessage.php @@ -0,0 +1,46 @@ +order_no = $order_no; + $this->smsConfig = $smsConfig; + } + + // 定义直接使用内容发送平台的内容 + public function getContent(GatewayInterface $gateway = null) + { + return sprintf('您有一条新的退款订单,订单号:', $this->order_no . ',请登录商城后台查看'); + } + + // 定义使用模板发送方式平台所需要的模板 ID + public function getTemplate(GatewayInterface $gateway = null) + { + return $this->smsConfig['template_id']; + } + + // 模板参数 + public function getData(GatewayInterface $gateway = null) + { + return [ + $this->smsConfig['template_variable'] => $this->order_no + ]; + } +} diff --git a/common/core/sms/PrescriptionPassMessage.php b/common/core/sms/PrescriptionPassMessage.php new file mode 100644 index 0000000..c6d17cb --- /dev/null +++ b/common/core/sms/PrescriptionPassMessage.php @@ -0,0 +1,38 @@ +prescription_no = $prescription_no; + $this->smsConfig = $smsConfig; + } + + // 定义直接使用内容发送平台的内容 + public function getContent(GatewayInterface $gateway = null) + { + return sprintf('您的编号为 %s 的处方已通过审核,详情前往萧康云医小程序查看!', $this->prescription_no); + } + + // 定义使用模板发送方式平台所需要的模板 ID + public function getTemplate(GatewayInterface $gateway = null) + { + return $this->smsConfig['template_id']; + } + + // 模板参数 + public function getData(GatewayInterface $gateway = null) + { + return [ + $this->smsConfig['template_variable'] => $this->prescription_no + ]; + } +} diff --git a/common/core/sms/PrescriptionRefuseMessage.php b/common/core/sms/PrescriptionRefuseMessage.php new file mode 100644 index 0000000..a84a4ac --- /dev/null +++ b/common/core/sms/PrescriptionRefuseMessage.php @@ -0,0 +1,39 @@ +prescription = $prescription; + $this->smsConfig = $smsConfig; + } + + // 定义直接使用内容发送平台的内容 + public function getContent(GatewayInterface $gateway = null) + { + return sprintf('你的处方号为:%s 的处方未通过审核,驳回原因:%s,请前往萧康云医小程序查看!', $this->prescription['prescription_no'],$this->prescription['reason']); + } + + // 定义使用模板发送方式平台所需要的模板 ID + public function getTemplate(GatewayInterface $gateway = null) + { + return $this->smsConfig['template_id']; + } + + // 模板参数 + public function getData(GatewayInterface $gateway = null) + { + return [ + $this->smsConfig['template_variable'][0]=> $this->prescription['prescription_no'], + $this->smsConfig['template_variable'][1]=> $this->prescription['reason'] + ]; + } +} diff --git a/common/core/sms/RegisterMessage.php b/common/core/sms/RegisterMessage.php new file mode 100644 index 0000000..562cee0 --- /dev/null +++ b/common/core/sms/RegisterMessage.php @@ -0,0 +1,35 @@ +smsConfig = $smsConfig; + } + + // 定义直接使用内容发送平台的内容 + public function getContent(GatewayInterface $gateway = null) + { + return sprintf('您有新的挂号订单,请打开萧康云医小程序及时处理!'); + } + + // 定义使用模板发送方式平台所需要的模板 ID + public function getTemplate(GatewayInterface $gateway = null) + { + return $this->smsConfig['template_id']; + } + +} diff --git a/common/core/sms/WaitApprovalMessage.php b/common/core/sms/WaitApprovalMessage.php new file mode 100644 index 0000000..42aac41 --- /dev/null +++ b/common/core/sms/WaitApprovalMessage.php @@ -0,0 +1,35 @@ +smsConfig = $smsConfig; + } + + // 定义直接使用内容发送平台的内容 + public function getContent(GatewayInterface $gateway = null) + { + return sprintf('你有新的待审核药方,详情请前往萧康云医小程序查看!'); + } + + // 定义使用模板发送方式平台所需要的模板 ID + public function getTemplate(GatewayInterface $gateway = null) + { + return $this->smsConfig['template_id']; + } + +} diff --git a/common/enums/BaseEnum.php b/common/enums/BaseEnum.php new file mode 100644 index 0000000..a25f41c --- /dev/null +++ b/common/enums/BaseEnum.php @@ -0,0 +1,7 @@ + [ + '半夏','瓜蒌','贝母','白蔹','白芨' + ], + '甘草' => [ + '海藻','大戟','甘遂','芫花' + ], + '藜芦' => [ + '元参','沙参','丹参','玄参','苦参','细辛','白芍','赤芍' + ] + ]; + //十八冲 + const CONFLCT = [ + ['硫磺','朴硝'], + ['水银','砒霜'], + ['狼毒','密陀僧'], + ['巴豆','牵牛'], + ['丁香','郁金'], + ['牙硝','京三棱'], + ['川乌','犀角'], + ['草乌','犀角'], + ['人参','五灵脂'], + ['官桂','赤石脂'] + ]; + //有毒 + const POISONOUS = [ + '红砒','白砒','砒霜','水银','生马前子','生川乌','生草乌','生白附子','生附子','生半夏','生南星','生巴豆','斑蝥','青娘虫','红娘虫','生甘遂','生狼毒','生藤黄','生千金子','生天仙子','闹阳花','雪上一枝蒿',' 白降丹','蟾酥','洋金花','红粉','轻粉','雄黄' + ]; +} diff --git a/common/enums/ImMessageSendTypeEnum.php b/common/enums/ImMessageSendTypeEnum.php new file mode 100644 index 0000000..94a5eca --- /dev/null +++ b/common/enums/ImMessageSendTypeEnum.php @@ -0,0 +1,9 @@ + '全部', + self::UNPAY => '待支付', + self::WAIT_SEND => '待发货', + self::WAIT_ACCEPT => '待收货', + self::WAIT_COMMENT => '待评价', + self::REFUND => '已退款', + self::REFUNDING => '退款中', + self::ACCEPTED => '已收货', + self::CONFIRM => '确认收货', + self::CANCEL => '已取消' + ]; + const CANCEL_STATUS_TEXT = [ + 0 => '未取消', + 1=> '已取消' + ]; + //0未退款1申请退款2同意退款3已退款4拒绝退款9取消退款 + const REFUND_STATUS_TEXT = [ + 0 => '未退款', + 1=> '申请退款', + 2 => '同意退款', + 3 => '已退款', + 4 => '拒绝退款', + 9 => '取消退款' + ]; +} \ No newline at end of file diff --git a/common/enums/RegisterEnum.php b/common/enums/RegisterEnum.php new file mode 100644 index 0000000..1b98461 --- /dev/null +++ b/common/enums/RegisterEnum.php @@ -0,0 +1,17 @@ + $id, + 'is_deleted' => 0 + ]); + + if($prescription->wr_ids){ + $repice = WestRepice::find()->where([ + 'in', 'id', explode(',', $prescription->wr_ids) + ])->select('content,number')->asArray()->all(); + foreach($repice as $v){ + $content = Json::decode($v['content']); + $drug = DrugStoreDrug::findOne(['id' => $content['id']]); + if($drug && $drug->frozen_number > $v['number']){ + $drug->stock = $drug->stock + $v['number']; + $drug->frozen_number = $drug->frozen_number - $v['number']; + $drug->saveOrFail(); + } + } + } elseif($prescription->cr_ids) { + $repice = ChineseRepice::find()->where([ + 'in', 'id', explode(',', $prescription->cr_ids) + ])->select('content,dosage')->asArray()->all(); + foreach($repice as $value){ + $content = Json::decode($value['content']); + foreach($content as $v){ + $drug = DrugStoreDrug::findOne(['id' => $content['drug_id']]); + $drugNumber = $v['number'] * $value['dosage']; + if($drug && $drug->frozen_number > $drugNumber){ + $drug->stock = $drug->stock + $drugNumber; + $drug->frozen_number = $drug->frozen_number - $drugNumber; + $drug->saveOrFail(); + } + } + } + } else { + $repice = GranularRepice::find()->where([ + 'in', 'id', explode(',', $prescription->gr_ids) + ])->select('content,dosage')->asArray()->all(); + foreach($repice as $value){ + $content = Json::decode($value['content']); + foreach($content as $v){ + $drug = DrugStoreDrug::findOne(['id' => $content['drug_id']]); + $drugNumber = $v['number'] * $value['dosage']; + if($drug && $drug->frozen_number > $drugNumber){ + $drug->stock = $drug->stock + $drugNumber; + $drug->frozen_number = $drug->frozen_number - $drugNumber; + $drug->saveOrFail(); + } + } + } + } + } else { + $items = ProductOrderItems::find()->where([ + 'product_order_id' => $id + ])->select('drug_id,number')->asArray()->all(); + foreach($items as $v){ + $drug = DrugStoreDrug::findOne(['id' => $v['drug_id']]); + if($drug && $drug->frozen_number > $v['number']){ + $drug->stock = $drug->stock + $v['number']; + $drug->frozen_number = $drug->frozen_number - $v['number']; + $drug->saveOrFail(); + } + } + } + + return true; + } +} \ No newline at end of file diff --git a/common/forms/ImMessageForm.php b/common/forms/ImMessageForm.php new file mode 100644 index 0000000..687ec9e --- /dev/null +++ b/common/forms/ImMessageForm.php @@ -0,0 +1,213 @@ +ImMessageSendTypeEnum::USER_SEND],//区分是user_id发给service_id还是service_id发给user_id + ['to_id','default','value'=>0],//发给导医和客服可能有会话id,没有接收人 + ]; + } + + public function attributeLabels() + { + return [ + 'ims_id' => '会话id', + 'from_id' => '发送人', + 'to_id' => '接收人', + 'content' => '消息内容', + ]; + } + + /** + * @param $canOffline bool 是否可发送离线消息 如果在线会发送在线消息 + * @return array + * @throws Exception + */ + public function sendMessage($canOffline = false) + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + $imMessageSession = ImMessageSession::find()->where([ + 'id' => $this->ims_id, + 'is_delete' => 0, + ])->one(); + switch($this->type){ + case 0: + //user_id发 + $user_id = $this->from_id; + $service_id = $this->to_id; + + //检查用户信息 + switch($imMessageSession->type) { + case ImSessionTypeEnum::USER_USER: + + $to = User::findOne($service_id); + if(!$to){ + throw new Exception('该用户不存在'); + } + $to_role = UserRoleEnum::USER; + + break; + case ImSessionTypeEnum::USER_DOC: + + $to = ServiceUser::findOne($service_id); + if(!$to || $to->is_delete || $to->status!=2){ + throw new Exception('该'.UserRoleEnum::NAME[$to->role].'不存在'); + } + $to_role = $to->role; + + break; + case ImSessionTypeEnum::USER_LEAD: + if($service_id){ + $to = ServiceUser::findOne($service_id); + if(!$to || $to->is_delete || $to->status!=2){ + throw new Exception('该'.UserRoleEnum::NAME[$to->role].'不存在'); + } + $to_role = $to->role; + }else{ + //说明新创建的会话,没人接入,群发 + $to_role = UserRoleEnum::LEADER; + } + break; + case ImSessionTypeEnum::DOC_SERV: + case ImSessionTypeEnum::DRUG_SERV: + case ImSessionTypeEnum::LEAD_SERV: + if($service_id){ + $to = ServiceUser::findOne($service_id); + if(!$to || $to->is_delete || $to->status!=2){ + throw new Exception('该'.UserRoleEnum::NAME[$to->role].'不存在'); + } + $to_role = $to->role; + }else{ + //说明新创建的会话,没人接入,群发 + $to_role = UserRoleEnum::SERVICE; + } + break; + } + break; + case 1: + //service_id发 + $user_id = $this->to_id; + $service_id = $this->from_id; + + //检查用户信息 + switch($imMessageSession->type) { + case ImSessionTypeEnum::USER_USER: + case ImSessionTypeEnum::USER_DOC: + case ImSessionTypeEnum::USER_LEAD: + + $to = User::findOne($user_id); + if(!$to){ + throw new Exception('该用户不存在'); + } + $to_role = UserRoleEnum::USER; + + break; + case ImSessionTypeEnum::DOC_SERV: + case ImSessionTypeEnum::DRUG_SERV: + case ImSessionTypeEnum::LEAD_SERV: + + $to = ServiceUser::findOne($user_id); + if(!$to || $to->is_delete || $to->status!=2){ + throw new Exception('该'.UserRoleEnum::NAME[$to->role].'不存在'); + } + $to_role = $to->role; + + break; + } + break; + default: + throw new Exception('不支持的消息'); + break; + } + if(!$imMessageSession || $imMessageSession->user_id!=$user_id || $imMessageSession->service_id!=$service_id){ + throw new Exception('会话不存在'); + } + // if($imMessageSession->status == ImSessionStatusEnum::END){ + // //会话已结束 + // throw new Exception('会话已结束,无法发送消息'); + // } + // $ims_id = $imMessageSession->id; + // + // $t = \Yii::$app->db->beginTransaction(); + // try { + // ImMessage::sendMessage($ims_id,$user_id,$service_id,$this->content,$this->type); + // + // \Yii::$app->queue->delay(0)->push(new MessageSendJob([ + // 'ims_id' => $ims_id, + // 'to_id' => $this->to_id, + // 'to_role' => $to_role, + // 'content' => $this->content, + // ])); + // + // $t->commit(); + // }catch (\Exception $exception){ + // $t->rollBack(); + // throw new Exception('发送失败:'.$exception->getMessage()); + // } + // return []; + $isEnd = $imMessageSession->status == ImSessionStatusEnum::END; + if(!$canOffline && $isEnd){ + //会话已结束 + throw new Exception('会话已结束,无法发送消息'); + } + $ims_id = $imMessageSession->id; + + $t = \Yii::$app->db->beginTransaction(); + try { + ImMessage::sendMessage($ims_id,$user_id,$service_id,$this->content,$this->type); + + if (!$canOffline || !$isEnd) { + \Yii::$app->queue->delay(0)->push(new MessageSendJob([ + 'ims_id' => $ims_id, + 'to_id' => $this->to_id, + 'to_role' => $to_role, + 'content' => $this->content, + ])); + } + + $t->commit(); + }catch (\Exception $exception){ + $t->rollBack(); + throw new Exception('发送失败:'.$exception->getMessage()); + } + return []; + } + + //接入的消息发送 + public function sessionIn($ims_id,$to_id = 0,$to_role,$message) + { + \Yii::$app->queue->delay(0)->push(new MessageSendJob([ + 'ims_id' => $ims_id, + 'to_id' => $to_id, + 'to_role' => $to_role, + 'content' => $message, + ])); + } + + + +} \ No newline at end of file diff --git a/common/forms/ImSessionForm.php b/common/forms/ImSessionForm.php new file mode 100644 index 0000000..2a73fbe --- /dev/null +++ b/common/forms/ImSessionForm.php @@ -0,0 +1,48 @@ +UserRoleEnum::DOCTOR],//默认医生会话 + ]; + } + + public function attributeLabels() + { + return [ + 'user_id' => '用户端id', + 'service_id' => '服务端id', + ]; + } + + //创建会话 + public function session() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + $ims = new ImMessageSession(); + $ims->attributes = $this->attributes; + $ims->saveOrFail(); + return $ims; + } +} \ No newline at end of file diff --git a/common/forms/LedgerForm.php b/common/forms/LedgerForm.php new file mode 100644 index 0000000..267917a --- /dev/null +++ b/common/forms/LedgerForm.php @@ -0,0 +1,578 @@ + [1,2]] + ]; + } + + public function create($type = 'productorder'){ + switch ($type) { + case 'register': + RegisterLog::saveLog($this->order_id, '挂号订单增加待结算记录开始'); + $t = \Yii::$app->db->beginTransaction(); + try { + $register = Register::find()->where(['id' => $this->order_id])->one(); + if(!$register){ + throw new Exception('挂号订单不存在'); + } + $store = Store::findOne(['id' => $register->store_id]); + if(!$store){ + throw new Exception('门店不存在'); + } + + + + $time = time(); + $ledger[] = [ + 'order_id' => $this->order_id, + 'user_id' => $store->id, + 'user_type' => 1, //诊所 + 'order_type' => 2,//挂号订单 + 'fee_type' => 2,//挂号费用 + 'su_id' => $register->service_user_id, + 'drugstore_id' => 0, + 'drug_id' =>0, + 'xd_time' => strtotime($register->created_at), + 'number' => 1, + 'money' => $register->price, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + \Yii::$app->db->createCommand()->batchInsert(Ledger::tableName(), [ + 'order_id', 'user_id', 'user_type', 'order_type', 'fee_type', 'su_id', 'drugstore_id', + 'drug_id','xd_time', 'number', 'money', 'status', 'created_at', 'updated_at' + ], $ledger)->execute(); + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + RegisterLog::saveLog($this->order_id, '挂号订单增加待结算记录异常:'.$e->getMessage()); + throw $e; + } + break; + + default: //产品订单 + ProductOrderLog::saveLog($this->order_id, '产品订单增加待结算记录开始'); + $t = \Yii::$app->db->beginTransaction(); + try { + $productOrder = ProductOrder::find()->where(['id' => $this->order_id])->one(); + if(!$productOrder){ + throw new Exception('产品订单不存在'); + } + $store = Store::findOne(['id' => $productOrder->store_id]); + if(!$store){ + throw new Exception('仓库不存在'); + } + $isLegder = Ledger::find()->where(['order_id' => $this->order_id])->one(); + if(!empty($isLegder)){ + throw new Exception('该订单已增加待结算记录'); + } + $time = time(); + $ledgerData = []; + if($productOrder->decoct_price > 0){ + $ledgerData[] = [ + 'order_id' => $this->order_id, + 'user_id' => 0, + 'user_type' => 2, //平台 + 'order_type' => 1,//产品订单 + 'fee_type' => 4,//代煎费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'drug_id' => 0, + 'xd_time' => $productOrder->created_at, + 'number' => 1, + 'money' => $productOrder->decoct_price, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + } + if($productOrder->process_price > 0){ + $ledgerData[] = [ + 'order_id' => $this->order_id, + 'user_id' => 0, + 'user_type' => 2, //平台 + 'order_type' => 1,//产品订单 + 'fee_type' => 5,//加工费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'drug_id' => 0, + 'xd_time' => $productOrder->created_at, + 'number' => 1, + 'money' => $productOrder->process_price, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + } + if($productOrder->treatement_price > 0){ + $ledgerData[] = [ + 'order_id' => $this->order_id, + 'user_id' => $store->id, + 'user_type' => 1, //门店 + 'order_type' => 1,//产品订单 + 'fee_type' => 6,//诊疗费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'drug_id' => 0, + 'xd_time' => $productOrder->created_at, + 'number' => 1, + 'money' => $productOrder->treatement_price, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + } + if($productOrder->trans_expenses > 0){ + $ledgerData[] = [ + 'order_id' => $this->order_id, + 'user_id' => 0, + 'user_type' => 2, //平台 + 'order_type' => 1,//产品订单 + 'fee_type' => 3,//快递费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'drug_id' => 0, + 'xd_time' => $productOrder->created_at, + 'number' => 1, + 'money' => $productOrder->trans_expenses, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + } + if(!empty($ledgerData)){ + \Yii::$app->db->createCommand()->batchInsert(Ledger::tableName(), [ + 'order_id', 'user_id', 'user_type', 'order_type', 'fee_type', 'su_id', 'drugstore_id', + 'drug_id', 'xd_time','number','money', 'status', 'created_at', 'updated_at' + ], $ledgerData)->execute(); + } + $productOrderItems = ProductOrderItems::find()->where(['product_order_id' => $productOrder->id])->all(); + + switch ($productOrder->prescription_type) { + case '1':case '3': //中药/颗粒药分佣 + foreach($productOrderItems as $v){ + $ledger = []; + $number = $v['number']; + $totalPrice = round($number * $v['price'], 4); + $totalBuyPrice = round($number * $v['buy_price'], 4); + + $ledger[] = [ + 'order_id' => $this->order_id, + 'user_id' => $store->id, + 'user_type' => 1, //门店 + 'order_type' => 1,//产品订单 + 'fee_type' => 1,//药品费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'drug_id' => $v['drug_id'], + 'xd_time' => $productOrder->created_at, + 'number' => $number, + 'money' => $totalPrice - $totalBuyPrice, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + + $ledger[] = [ + 'order_id' => $this->order_id, + 'user_id' => 0, + 'user_type' => 2, //平台 + 'order_type' => 1,//产品订单 + 'fee_type' => 1,//药品费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'drug_id' => $v['drug_id'], + 'xd_time' => $productOrder->created_at, + 'number' => $number, + 'money' => $totalBuyPrice, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + \Yii::$app->db->createCommand()->batchInsert(Ledger::tableName(), [ + 'order_id', 'user_id', 'user_type', 'order_type', 'fee_type', 'su_id', 'drugstore_id', + 'drug_id','xd_time', 'number', 'money', 'status', 'created_at', 'updated_at' + ], $ledger)->execute(); + } + break; + case '2': //西药分佣 + $ledger = []; + foreach($productOrderItems as $v){ + $totalPrice = round($v['number'] * $v['price'], 4); + $totalBuyPrice = round($v['number'] * $v['buy_price'], 4); + $ledger[] = [ + 'order_id' => $this->order_id, + 'user_id' => $store->id, + 'user_type' => 1, //门店 + 'order_type' => 1,//产品订单 + 'fee_type' => 1,//药品费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'xd_time' => $productOrder->created_at, + 'drug_id' => $v['drug_id'], + 'number' => $v['number'], + 'money' => $totalPrice - $totalBuyPrice, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + + $ledger[] = [ + 'order_id' => $this->order_id, + 'user_id' => 0, + 'user_type' => 2, //平台 + 'order_type' => 1,//产品订单 + 'fee_type' => 1,//药品费用 + 'su_id' => $productOrder->su_id, + 'drugstore_id' => $productOrder->store_id, + 'drug_id' => $v['drug_id'], + 'xd_time' => $productOrder->created_at, + 'number' => $v['number'], + 'money' => $totalBuyPrice, + 'status' => 0, + 'created_at' => $time, + 'updated_at' => $time + ]; + \Yii::$app->db->createCommand()->batchInsert(Ledger::tableName(), [ + 'order_id', 'user_id', 'user_type', 'order_type', 'fee_type', 'su_id', 'drugstore_id', + 'drug_id','xd_time', 'number','money', 'status', 'created_at', 'updated_at' + ], $ledger)->execute(); + } + + break; + default: + throw new Exception('错误的处方类型'); + break; + } + $t->commit(); + + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $this->order_id; + $ledgerForm->status = 1; // 已结算 + $ledgerForm->update(); + + ProductOrderLog::saveLog($this->order_id, '产品订单增加待结算记录结束'); + } catch (\Exception $e) { + $t->rollBack(); + ProductOrderLog::saveLog($this->order_id, '产品订单增加待结算记录异常:'.$e->getMessage().'——'.$e->getLine()); + throw $e; + } + break; + } + + } + + //更新记录状态 1已结算 2已取消 + public function update($type = 'productorder'){ + switch ($type) { + case 'register': //挂号订单 + RegisterLog::saveLog($this->order_id, '挂号订单结算更新开始'); + $Register = Register::find()->where(['id' => $this->order_id])->one(); + if(!$Register){ + throw new Exception('产品订单不存在'); + } + $store = Store::findOne(['id' => $Register->store_id]); + if(!$store){ + throw new Exception('门店不存在'); + } + $time = time(); + $t = \Yii::$app->db->beginTransaction(); + $model = new LedgerLog(); + try { + switch ($this->status) { + case 1: // 已结算 + //更新挂号订单为已结算 + $Register->is_settled = 1; + $Register->created_at = strtotime($Register->created_at); + $Register->updated_at = $time; + $Register->saveOrFail(); + + //分账表批量更新状态为已结算 + Ledger::updateAll(['status' => 1, 'updated_at' => $time], ['order_id' => $this->order_id, 'order_type' => 2]); //1产品订单 2挂号订单 + + /******************************************** 门店 ********************************************** */ + $storeTotal = Ledger::find()->where(['order_id' => $this->order_id, 'user_id' => $store->id, 'user_type' => 1, 'order_type' => 2, 'fee_type' => 2])->sum('money'); // 该订单门店分佣总金额 + $storeTotal = round($storeTotal, 2);//4舍5入 + + //增加门店分佣 + $log = clone $model; + $log->order_id = $this->order_id; + $log->user_id = $store->id; + $log->user_type = 1;// 门店 + $log->order_type = 2; //挂号订单 + $log->fee_type = 2; //挂号费用 + $log->type = 1;// 增加 + $log->amount = $storeTotal; + $log->content = '挂号订单结算后增加挂号分佣金额'; + $log->created_at = $time; + $log->updated_at = $time; + $log->saveOrFail(); + + //门店可提现及累计金额更新 + CashAccount::updateAllCounters(['able_cash' => $storeTotal, 'total_cash' => $storeTotal],['user_type' => 1, 'user_id' => $store->id]); //门店 + + break; + case 2://已取消 + if($Register->is_settled == 1){ //已结算回退 + //已结算对账单状态更新 + Reconciliation::updateAll(['status' => -1], ['order_id' => $this->order_id]); + //分账表批量更新状态为已取消 + Ledger::updateAll(['status' => 2, 'updated_at' => $time], ['order_id' => $this->order_id, 'order_type' => 1]);//1产品订单 2挂号订单 + + $ledgerLog = LedgerLog::find()->where(['order_id' => $this->order_id])->asArray()->all(); + foreach($ledgerLog as $v){ + $log = clone $model; + $log->order_id = $v['order_id']; + $log->user_id = $v['user_id']; + $log->user_type = $v['user_type']; + $log->order_type = $v['order_type']; + $log->fee_type = $v['fee_type']; + $log->type = 2;// 扣减 + $log->amount = $v['amount']; + $log->content = '订单结算后用户退货退款,扣减金额'; + $log->created_at = $time; + $log->updated_at = $time; + $log->saveOrFail(); + + //可提现及累计金额更新 + CashAccount::updateAllCounters(['able_cash' => $v['amount'] * -1, 'total_cash' => $v['amount'] * -1],['user_type' => $v['user_type'], 'user_id' => $v['user_id'], 'order_type' => $v['order_type'], 'fee_type' => $v['fee_type']]); + } + } else { // 未结算 + Ledger::updateAll(['status' => 2, 'updated_at' => $time], ['order_id' => $this->order_id, 'order_type' => 2]); + } + break; + default: + # code... + break; + } + $t->commit(); + ProductOrderLog::saveLog($this->order_id, '挂号订单结算更新结束'); + } catch (\Exception $e){ + $t->rollBack(); + ProductOrderLog::saveLog($this->order_id, '挂号订单结算更新异常:'.$e->getMessage().'——'.$e->getLine()); + throw $e; + } + break; + + default: //产品订单 + ProductOrderLog::saveLog($this->order_id, '产品订单结算更新开始'); + $productOrder = ProductOrder::find()->where(['id' => $this->order_id])->one(); + if(!$productOrder){ + throw new Exception('产品订单不存在'); + } + $store = Store::findOne(['id' => $productOrder->store_id]); + if(!$store){ + throw new Exception('门店不存在'); + } + $time = time(); + $t = \Yii::$app->db->beginTransaction(); + $model = new LedgerLog(); + try { + switch ($this->status) { + case 1: // 已结算 + //更新产品订单为已结算 + $productOrder->is_settled = 1; + $productOrder->saveOrFail(); + + $productOrderItems = ProductOrderItems::find()->where(['product_order_id' => $productOrder->id])->asArray()->all(); + $Reconciliation = new Reconciliation(); + foreach($productOrderItems as $v){ + $item = clone $Reconciliation; + $item->store_id = $productOrder->store_id; + $item->order_id = $productOrder->id; + $item->pay_time = $productOrder->pay_time; + $item->xd_time = $productOrder->created_at; + $item->drug_id = $v['drug_id']; + $item->drug_type = $v['type']; + $item->number = $v['number']; + $item->total_buy_price = $v['number'] * $v['buy_price']; + $item->total_price = $v['number'] * $v['price']; + $item->created_at = $time; + $item->updated_at = $time; + $item->saveOrFail(); + } + + //分账表批量更新状态为已结算 + Ledger::updateAll(['status' => 1, 'updated_at' => $time], ['order_id' => $this->order_id, 'order_type' => 1]); //1产品订单 2挂号订单 + + /******************************************** 平台 ********************************************** */ + $platformDrugTotal = Ledger::find()->where(['order_id' => $this->order_id, 'user_type' => 2, 'order_type' => 1, 'fee_type' => 1])->sum('money'); // 该订单平台分佣总金额 + //增加药品分佣 + $log = clone $model; + $log->order_id = $this->order_id; + $log->user_id = 0; + $log->user_type = 2;// 平台 + $log->order_type = 1; //产品订单 + $log->fee_type = 1; //药品费用 + $log->type = 1;// 增加 + $log->amount = round($platformDrugTotal, 2); + $log->content = '订单结算后增加药品分佣金额'; + $log->created_at = $time; + $log->updated_at = $time; + $log->saveOrFail(); + + //增加代煎费 + if($productOrder->decoct_price > 0){ + $platformDecoctTotal = Ledger::find()->where(['order_id' => $this->order_id, 'user_type' => 2, 'order_type' => 1, 'fee_type' => 4])->sum('money'); // 该订单代煎费用 + $logDecoct = clone $model; + $logDecoct->order_id = $this->order_id; + $logDecoct->user_id = 0; + $logDecoct->user_type = 2;// 平台 + $logDecoct->order_type = 1; //产品订单 + $logDecoct->fee_type = 4; //代煎费用 + $logDecoct->type = 1;// 增加 + $logDecoct->amount = round($platformDecoctTotal, 2); + $logDecoct->content = '订单结算后增加代煎费用'; + $logDecoct->created_at = $time; + $logDecoct->updated_at = $time; + $logDecoct->saveOrFail(); + } + + //增加加工费 + if($productOrder->process_price > 0){ + $platformProcessTotal = Ledger::find()->where(['order_id' => $this->order_id, 'user_type' => 2, 'order_type' => 1, 'fee_type' => 5])->sum('money'); // 该订单加工费用 + $logProcess = clone $model; + $logProcess->order_id = $this->order_id; + $logProcess->user_id = 0; + $logProcess->user_type = 2;// 平台 + $logProcess->order_type = 1; //产品订单 + $logProcess->fee_type = 5; //代煎费用 + $logProcess->type = 1;// 增加 + $logProcess->amount = round($platformProcessTotal, 2); + $logProcess->content = '订单结算后增加加工费用'; + $logProcess->created_at = $time; + $logProcess->updated_at = $time; + $logProcess->saveOrFail(); + } + + //增加快递记录 + if($productOrder->trans_expenses > 0){ + $platformDeliveryTotal = Ledger::find()->where(['order_id' => $this->order_id, 'user_type' => 2, 'order_type' => 1, 'fee_type' => 3])->sum('money'); // 该订单快递费用 + $logDelivery = clone $model; + $logDelivery->order_id = $this->order_id; + $logDelivery->user_id = 0; + $logDelivery->user_type = 2;// 平台 + $logDelivery->order_type = 1; //产品订单 + $logDelivery->fee_type = 3; //快递费用 + $logDelivery->type = 1;// 增加 + $logDelivery->amount = round($platformDeliveryTotal, 2);; + $logDelivery->content = '订单结算后增加快递费用'; + $logDelivery->created_at = $time; + $logDelivery->updated_at = $time; + $logDelivery->saveOrFail(); + } + + $platformTotal = round($platformDrugTotal+$platformDeliveryTotal+$platformDecoctTotal, 2); //该订单平台分佣总金额 + //可提现金额表更新 + CashAccount::updateAllCounters(['able_cash' => $platformTotal, 'total_cash' => $platformTotal],['user_type' => 2]); //平台 + + + /******************************************** 门店 ********************************************** */ + $storeTotal = Ledger::find()->where(['order_id' => $this->order_id, 'user_id' => $store->id, 'user_type' => 1, 'order_type' => 1, 'fee_type' => 1])->sum('money'); // 该订单门店分佣总金额 + $storeTotal = round($storeTotal, 2);//4舍5入 + //增加门店分佣 + $log = clone $model; + $log->order_id = $this->order_id; + $log->user_id = $store->id; + $log->user_type = 1;// 门店 + $log->order_type = 1; //产品订单 + $log->fee_type = 1; //药品费用 + $log->type = 1;// 增加 + $log->amount = $storeTotal; + $log->content = '订单结算后增加药品分佣金额'; + $log->created_at = $time; + $log->updated_at = $time; + $log->saveOrFail(); + + //增加诊疗费 + if($productOrder->treatement_price > 0){ + $platformTreatementTotal = Ledger::find()->where(['order_id' => $this->order_id, 'user_type' => 2, 'order_type' => 1, 'fee_type' => 6])->sum('money'); // 该订单诊疗费用 + $logTreatement = clone $model; + $logTreatement->order_id = $this->order_id; + $logTreatement->user_id = $store->id; + $logTreatement->user_type = 1;// 门店 + $logTreatement->order_type = 1; //产品订单 + $logTreatement->fee_type = 6; //诊疗费用 + $logTreatement->type = 1;// 增加 + $logTreatement->amount = round($platformTreatementTotal, 2); + $logTreatement->content = '订单结算后增加诊疗费用'; + $logTreatement->created_at = $time; + $logTreatement->updated_at = $time; + $logTreatement->saveOrFail(); + } + + //门店可提现及累计金额更新 + CashAccount::updateAllCounters(['able_cash' => $storeTotal, 'total_cash' => $storeTotal],['user_type' => 1, 'user_id' => $store->id]); //门店 + + break; + case 2://已取消 + if($productOrder->is_settled == 1){ //已结算回退 + //已结算对账单状态更新 + Reconciliation::updateAll(['status' => -1], ['order_id' => $this->order_id]); + //分账表批量更新状态为已取消 + Ledger::updateAll(['status' => 2, 'updated_at' => $time], ['order_id' => $this->order_id, 'order_type' => 1]);//1产品订单 2挂号订单 + + $ledgerLog = LedgerLog::find()->where(['order_id' => $this->order_id])->asArray()->all(); + foreach($ledgerLog as $v){ + $log = clone $model; + $log->order_id = $v['order_id']; + $log->user_id = $v['user_id']; + $log->user_type = $v['user_type']; + $log->order_type = $v['order_type']; + $log->fee_type = $v['fee_type']; + $log->type = 2;// 扣减 + $log->amount = $v['amount']; + $log->content = '订单结算后用户退货退款,扣减金额'; + $log->created_at = $time; + $log->updated_at = $time; + $log->saveOrFail(); + + //可提现及累计金额更新 + CashAccount::updateAllCounters(['able_cash' => $v['amount'] * -1, 'total_cash' => $v['amount'] * -1],['user_type' => $v['user_type'], 'user_id' => $v['user_id']]); + } + } else { // 未结算 + Ledger::updateAll(['status' => 2, 'updated_at' => $time], ['order_id' => $this->order_id, 'order_type' => 1]);//order_type 1产品订单 2挂号订单 + } + break; + default: + # code... + break; + } + $t->commit(); + ProductOrderLog::saveLog($this->order_id, '产品订单结算更新结束'); + } catch (\Exception $e){ + $t->rollBack(); + ProductOrderLog::saveLog($this->order_id, '产品订单结算更新异常'.$e->getMessage().'——'.$e->getLine()); + throw $e; + } + break; + } + } + +} \ No newline at end of file diff --git a/common/forms/OrderRefundForm.php b/common/forms/OrderRefundForm.php new file mode 100644 index 0000000..fc67925 --- /dev/null +++ b/common/forms/OrderRefundForm.php @@ -0,0 +1,211 @@ +where([ + 'user_id' => \Yii::$app->user->identity->id, + 'id' => $order_id + ])->with('session')->one(); + if(!$order || $order->cancel_status){ + throw new Exception('订单不存在'); + } + switch($order->is_pay){ + case 0://未支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $order->cancel_status = 1; + $order->cancel_time = time(); + $order->cancel_remark = '主动取消订单'; + $order->saveOrFail(); + + + //生成系统消息 + $SystemNotice=new SystemNotice(); + $SystemNotice->content='您已主动取消订单'; + $SystemNotice->base_type=SystemNoticeTypeEnum::ORDER_CANCEL; + $SystemNotice->scene_type=1;//用户端 + $SystemNotice->user_id=\Yii::$app->user->identity->getId(); + $SystemNotice->notice_at=date('Y-m-d H:i:s',time()); + $SystemNotice->saveOrFail(); + + + $event = new OrderEvent([ + 'order' => $order, + ]); + \Yii::$app->trigger(Order::EVENT_CANCELED, $event); + $t->commit(); + + return []; + } catch (\Exception $exception) { + $t->rollBack(); + throw $exception; + } + break; + case 1://已支付 + if($order->accept_status!=OrderAcceptEnum::WAIT_ACCEPT){ + throw new Exception('只有待接诊状态可以取消订单'); + } + $ims_id = $order->session->ims_id; + $ImMessageSession = ImMessageSession::findOne($ims_id); + if(!$ImMessageSession){ + throw new Exception('未接诊订单会话不存在'); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + //生成记录 + $orderRefund = new OrderRefund(); + $orderRefund->user_id = $order->user_id; + $orderRefund->order_id = $order->id; + $orderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $orderRefund->refund_price = $order->total_pay_price; + $orderRefund->remark = '主动取消订单'; + $orderRefund->saveOrFail(); + + //取消状态 + $order->cancel_status = 1; + $order->cancel_time = time(); + $order->cancel_remark = '主动取消订单'; + //接诊状态 + $order->accept_status = OrderAcceptEnum::CANCEL; + //退款状态 + $order->refund_status = 1; + $order->refund_time = time(); + $order->saveOrFail(); + + //会话修改为已结束 + $ImMessageSession->status = ImSessionStatusEnum::END; + $ImMessageSession->saveOrFail(); + + //生成系统消息 + $SystemNotice=new SystemNotice(); + $SystemNotice->content='您已主动取消订单'; + $SystemNotice->base_type=SystemNoticeTypeEnum::ORDER_CANCEL; + $SystemNotice->scene_type=1;//用户端 + $SystemNotice->user_id=\Yii::$app->user->identity->getId(); + $SystemNotice->notice_at=date('Y-m-d H:i:s',time()); + $SystemNotice->saveOrFail(); + + //退款操作 + $this->refundMoney($orderRefund); //可能报错 无效的订单号 + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + break; + } + + } + + public function refundMoney($orderRefund) + { + $orderNo = $orderRefund->order->order_no; + $order = Order::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); + $paymentOrder = PaymentOrder::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); + if (!$order || !$paymentOrder) { + throw new Exception('无效的订单号'); + } + $price = $orderRefund->refund_price; + if(bccomp($paymentOrder->amount,$price,2)==-1){ + throw new Exception('退款金额大于可退款金额'); + } + + $transaction = \Yii::$app->db->beginTransaction(); + try { + $paymentRefund = new PaymentRefund(); + $paymentRefund->refund_no = $orderRefund->refund_no; + $paymentRefund->amount = $price; + $paymentRefund->is_pay = 0; + $paymentRefund->pay_type = 0; + $paymentRefund->created_at = time(); + $paymentRefund->saveOrFail(); + if(bccomp($price,0,2)<=0) { + $paymentRefund->is_pay = 1; + $paymentRefund->save(); + + $orderRefund->is_refund = 1; + $orderRefund->refund_time = time(); + $orderRefund->save(); + }else{ + switch ($order->pay_type) { + case 1://微信退款 + if(\Yii::$app instanceof \yii\web\Application){ + $notifyUrl = \Yii::$app->request->hostInfo."/member/v1/callback/refund-notify/"; + }else{ + //如果是job中调用的 + $notifyUrl = \Yii::$app->getHostInfo()."/member/v1/callback/refund-notify/"; + } + + $order_amount = bcmul($paymentOrder->amount,100,0); + $refund_amount = bcmul($price,100,0); + + $result = WechatService::getInstance()->payment->refund->byTransactionId($paymentOrder->transaction_id, $paymentRefund->refund_no,$order_amount, $refund_amount, [ + 'refund_desc' => '订单申请退款', + 'notify_url' => $notifyUrl + ]); + if($result['return_code']!='SUCCESS' || $result['result_code']!='SUCCESS'){ + $error = isset($result['err_code_des']) ? $result['err_code_des'] : $result['return_msg']; + throw new Exception($error); + } + break; + case 2://易票联退款 + $eplResult = EplPayService::getInstance()->refund([ + 'refund_no' => $paymentRefund->refund_no, + 'transaction_id' => $paymentOrder->transaction_id, + 'total_pay_price' => $paymentOrder->amount, + 'refund_price' => $price, + ]); + if(!isset($eplResult['returnCode']) || $eplResult['returnCode'] != '0000'){ + throw new Exception($eplResult['returnMsg']); + } + break; + + default: + throw new Exception('退款失败,请联系客服'); + break; + } + //其他状态变更在回调 + } + $transaction->commit(); + return []; + }catch (\Exception $exception){ + $transaction->rollBack(); + throw $exception; + } + } +} diff --git a/common/forms/PrescripRefundForm.php b/common/forms/PrescripRefundForm.php new file mode 100644 index 0000000..391ae26 --- /dev/null +++ b/common/forms/PrescripRefundForm.php @@ -0,0 +1,164 @@ +where([ + 'user_id' =>\Yii::$app->user->identity->getId(), + 'id' => $order_id + ])->one(); + if(!$prescription || $prescription->cancel_status){ + throw new Exception('订单不存在'); + } + + switch($prescription->is_pay){ + case 0://未支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $prescription->cancel_status = 1; + $prescription->cancel_time = time(); + $prescription->cancel_remark = '主动取消订单'; + $prescription->saveOrFail(); + + $event = new OrderEvent([ + 'order' => $prescription, + ]); + \Yii::$app->trigger(Prescription::AUTO_EXPIRE, $event); + $t->commit(); + + return []; + } catch (\Exception $exception) { + $t->rollBack(); + throw $exception; + } + case 1://已支付 + + $config = \Yii::$app->params; + $orderForbiddenRefundTime = isset($config['product_order']['forbidden_refund_time']) ? $config['product_order']['forbidden_refund_time'] :3600*24*7; + + if ($prescription->prescription_type==1 || $prescription->prescription_type==3 ){ + throw new Exception('中药饮片和配方颗粒禁止退款'); + } + if ($prescription->prescription_type==2 &&$prescription->prescription_type==4 ){ + if (time()-$prescription->pay_time>=120){ + throw new Exception('西药一周之后禁止退款'); + } + } + + $t = \Yii::$app->db->beginTransaction(); + try { + //生成记录 + $prescripOrderRefund = new PrescripOrderRefund(); + $prescripOrderRefund->user_id = $prescription->user_id; + $prescripOrderRefund->order_id = $prescription->id; + $prescripOrderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $prescripOrderRefund->refund_price = $prescription->total_pay_price; + $prescripOrderRefund->remark = '主动取消订单'; + $prescripOrderRefund->saveOrFail(); + + //取消状态 + $prescription->cancel_status = 1; + $prescription->cancel_time = time(); + $prescription->cancel_remark = '主动取消订单'; + + //退款状态 + $prescription->refund_status = 1; + $prescription->refund_time = time(); + $prescription->saveOrFail(); + + //退款操作 + $this->refundMoney($prescripOrderRefund); //可能报错 无效的订单号 + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + break; + } + } + + public function refundMoney($prescripOrderRefund) + { + $orderNo = $prescripOrderRefund->order->order_no; + $prescription = Prescription::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); + $paymentPrescripOrder = PaymentPrescripOrder::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); + if (!$prescription || !$paymentPrescripOrder) { + throw new Exception('无效的订单号'); + } + $price = $prescripOrderRefund->refund_price; + if(bccomp($paymentPrescripOrder->amount,$price,2)==-1){ + throw new Exception('退款金额大于可退款金额'); + } + + $transaction = \Yii::$app->db->beginTransaction(); + try { + $paymentPrescripRefund = new PaymentPrescripRefund(); + $paymentPrescripRefund->refund_no = $prescripOrderRefund->refund_no; + $paymentPrescripRefund->amount = $price; + $paymentPrescripRefund->is_pay = 0; + $paymentPrescripRefund->pay_type = 0; + $paymentPrescripRefund->created_at = time(); + $paymentPrescripRefund->saveOrFail(); + if(bccomp($price,0,2)<=0) { + $paymentPrescripRefund->is_pay = 1; + $paymentPrescripRefund->save(); + + $prescripOrderRefund->is_refund = 1; + $prescripOrderRefund->refund_time = time(); + $prescripOrderRefund->save(); + }else{ + if(\Yii::$app instanceof \yii\web\Application){ + $notifyUrl = \Yii::$app->request->hostInfo."/member/v1/callback/refund-notify/"; + }else{ + //如果是job中调用的 + $notifyUrl = \Yii::$app->getHostInfo()."/member/v1/callback/refund-notify/"; + } + + $order_amount = bcmul($paymentPrescripOrder->amount,100,0); + $refund_amount = bcmul($price,100,0); + + $result = WechatService::getInstance()->payment->refund->byTransactionId($paymentPrescripOrder->transaction_id, $paymentPrescripRefund->refund_no,$order_amount, $refund_amount, [ + 'refund_desc' => '订单取消退款', + 'notify_url' => $notifyUrl + ]); + if($result['return_code']!='SUCCESS' || $result['result_code']!='SUCCESS'){ + $error = isset($result['err_code_des']) ? $result['err_code_des'] : $result['return_msg']; + throw new Exception($error); + } + //其他状态变更在回调 + } + $transaction->commit(); + return []; + }catch (\Exception $exception){ + $transaction->rollBack(); + throw $exception; + } + } +} \ No newline at end of file diff --git a/common/forms/ProductCancelForm.php b/common/forms/ProductCancelForm.php new file mode 100644 index 0000000..1062c32 --- /dev/null +++ b/common/forms/ProductCancelForm.php @@ -0,0 +1,67 @@ + 0) { + $user_id = $post['user_id']; + }else{ + $user_id = \Yii::$app->user->identity->getId(); + } + + $productOrder = ProductOrder::find()->where([ + 'user_id' => $user_id, + 'id' => $post['order_id'] + ])->one(); + if(!$productOrder || $productOrder->cancel_status){ + throw new Exception('订单不存在'); + } + if($productOrder->is_pay == 1){ + throw new Exception('订单无法取消'); + } + if($productOrder->order_type == 1){ + $prescription = Prescription::findOne(['id' => $productOrder->p_id]); + $prescription->cancel_status = 1; + $prescription->cancel_time = time(); + $prescription->cancel_remark = '主动取消订单'; + $prescription->saveOrFail(); + } + + $productOrder->status = ProductOrderEnum::CANCEL; + $productOrder->cancel_status = 1; + $productOrder->cancel_time = time(); + $productOrder->cancel_remark = $remark; + $productOrder->saveOrFail(); + + //药品库存回滚 + $DrugRollBackForm = new DrugRollBackForm(); + $DrugRollBackForm->rollBack($productOrder->order_type == 1?$productOrder->p_id:$productOrder->id, $productOrder->order_type); + + if($productOrder->is_online){ //平台订单状态同步 + \Yii::$app->queue->push(new ProductOrderSyncPlatformJob([ + 'orderId' => $productOrder->id, + 'status' => 2 + ])); + } + + return ['取消成功']; + } +} \ No newline at end of file diff --git a/common/forms/ProductRefundCancelForm.php b/common/forms/ProductRefundCancelForm.php new file mode 100644 index 0000000..ea30870 --- /dev/null +++ b/common/forms/ProductRefundCancelForm.php @@ -0,0 +1,67 @@ +where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'id' => $order_id + ])->one(); + + if(!$productOrder || $productOrder->cancel_status || $productOrder->is_pay != 1 || $productOrder->refund_status!=1){ + throw new Exception('订单不存在'); + } + + $productOrderRefund = ProductOrderRefund::find()->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'order_id' => $order_id, + 'is_refund' => 0, //未退款 + 'status' => 0 //申请退款中 + ])->one(); + + if(!$productOrderRefund){ + throw new Exception('订单不存在'); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + if($productOrder->is_send ==1){ + $productOrder->status = ProductOrderEnum::ACCEPTED; + } else { + $productOrder->status = ProductOrderEnum::WAIT_SEND; + } + $productOrder->refund_status = 0; + $productOrder->refund_time = 0; + $productOrder->saveOrFail(); + + $productOrderRefund->status = 2; + $productOrderRefund->saveOrFail(); + + $t->commit(); + + return ['撤销退款申请成功']; + } catch (\Exception $exception) { + $t->rollBack(); + throw $exception; + } + + } +} \ No newline at end of file diff --git a/common/forms/ProductRefundForm.php b/common/forms/ProductRefundForm.php new file mode 100644 index 0000000..356bb80 --- /dev/null +++ b/common/forms/ProductRefundForm.php @@ -0,0 +1,180 @@ + 0) { + $user_id = $post['user_id']; + }else{ + $user_id = \Yii::$app->user->identity->getId(); + } + + $productOrder = ProductOrder::find()->where([ + 'user_id' => $user_id, + 'id' => $post['order_id'] + ])->one(); + if(!$productOrder || $productOrder->cancel_status){ + throw new Exception('订单不存在'); + } + + $productOrderRefund = ProductOrderRefund::find()->with(['order'])->where([ + 'order_id' => $post['order_id'], + 'user_id' => $user_id, + + ])->andWhere(['in','status', [0, 1]])->one(); + if($productOrderRefund){ + throw new Exception('请勿重复操作'); + } + // $productOrderStatus = $productOrder->status; + $t = \Yii::$app->db->beginTransaction(); + try { + //更新订单退款状态 + $productOrder->status = ProductOrderEnum::REFUNDING; //状态变为退款中 + $productOrder->refund_status = 1; //退款中 + $productOrder->refund_time = time(); + $productOrder->saveOrFail(); + + //生成订单退款记录 + $productOrderRefund = new ProductOrderRefund(); + $productOrderRefund->user_id = $productOrder->user_id; + $productOrderRefund->order_id = $productOrder->id; + $productOrderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $productOrderRefund->refund_price = $productOrder->total_pay_price; + + if( $type == 'auto'){ + $productOrderRefund->status = 1; //直接退款,不需要申请 + $productOrderRefund->reason = '处方失效自动退款'; + $productOrderRefund->remark = '处方失效自动退款'; + $productOrderRefund->saveOrFail(); + //微信退款操作 + $this->refundMoney($productOrderRefund); + }else{ + $productOrderRefund->reason = $post['reason'] ?? ''; + $productOrderRefund->remark = $post['remark'] ?? '主动申请退款'; + $productOrderRefund->refund_images = $post['refund_images'] ?? ''; + $productOrderRefund->status = 0; //申请退款 + $productOrderRefund->refund_type = 1; //退货退款 + $productOrderRefund->saveOrFail(); + } + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + return ['操作成功']; + } + + public function refundMoney($productOrderRefund) + { + $orderNo = $productOrderRefund->order->order_no; + $productOrder = ProductOrder::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); + $paymentProductOrder = PaymentProductOrder::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); + if (!$productOrder || !$paymentProductOrder) { + throw new Exception('无效的订单号'); + } + $price = $productOrderRefund->refund_price; + if(bccomp($paymentProductOrder->amount,$price,2)==-1){ + throw new Exception('退款金额大于可退款金额'); + } + $transaction = \Yii::$app->db->beginTransaction(); + try { + $paymentProductRefund = new PaymentProductRefund(); + $paymentProductRefund->refund_no = $productOrderRefund->refund_no; + $paymentProductRefund->amount = $price; + $paymentProductRefund->is_pay = 0; + $paymentProductRefund->pay_type = 0; + $paymentProductRefund->created_at = time(); + $paymentProductRefund->saveOrFail(); + if(bccomp($price,0,2)<=0) { + $paymentProductRefund->is_pay = 1; + $paymentProductRefund->save(); + + $productOrder->refund_status = 3;//已退款 + $productOrder->staus = ProductOrderEnum::REFUND;//订单状态变成已退款 + $productOrder->save(); + + $productOrderRefund->is_refund = 1; + $productOrderRefund->refund_time = time(); + $productOrderRefund->save(); + + //药品库存回滚 + $DrugRollBackForm = new DrugRollBackForm(); + $DrugRollBackForm->rollBack($productOrder->order_type == 1?$productOrder->p_id:$productOrder->id,$productOrder->order_type == 1?1:0); + }else{ + switch ($paymentProductOrder->pay_type) { + case 1://微信退款 + if(\Yii::$app instanceof \yii\web\Application){ + $notifyUrl = \Yii::$app->request->hostInfo."/member/v1/callback/refund-notify/"; + }else{ + //如果是job中调用的 + $notifyUrl = \Yii::$app->getHostInfo()."/member/v1/callback/refund-notify/"; + } + + $order_amount = bcmul($paymentProductOrder->amount,100,0); + $refund_amount = bcmul($price,100,0); + + $result = WechatService::getInstance()->payment->refund->byTransactionId($paymentProductOrder->transaction_id, $paymentProductRefund->refund_no,$order_amount, $refund_amount, [ + 'refund_desc' => '订单申请退款', + 'notify_url' => $notifyUrl + ]); + if($result['return_code']!='SUCCESS' || $result['result_code']!='SUCCESS'){ + $error = isset($result['err_code_des']) ? $result['err_code_des'] : $result['return_msg']; + throw new Exception($error); + } + break; + case 2://易票联退款 + $eplResult = EplPayService::getInstance()->refund([ + 'refund_no' => $paymentProductRefund->refund_no, + 'transaction_id' => $paymentProductOrder->transaction_id, + 'total_pay_price' => $paymentProductOrder->amount, + 'refund_price' => $price, + ]); + if(!isset($eplResult['returnCode']) || $eplResult['returnCode'] != '0000'){ + throw new Exception($eplResult['returnMsg']); + } + break; + + default: + throw new Exception('退款失败,请联系客服'); + break; + } + //其他状态变更在回调 + } + $transaction->commit(); + return true; + } catch (\Exception $exception){ + $transaction->rollBack(); + throw $exception; + } + } +} \ No newline at end of file diff --git a/common/forms/RegisterRefundForm.php b/common/forms/RegisterRefundForm.php new file mode 100644 index 0000000..e986e7d --- /dev/null +++ b/common/forms/RegisterRefundForm.php @@ -0,0 +1,210 @@ +where([ +// 'user_id' => \Yii::$app->user->identity->id, + 'id' => $register_id + ])->one(); + + + if (!$Register || $Register->is_cancel==1) { + throw new Exception('订单不存在'); + } + if ($Register->status == 2 || $Register->status == 3 || $Register->status == 5 || $Register->status == 6) { + throw new Exception('医生接诊后不能取消挂号!!'); + } + switch ($Register->is_pay) { + case 0://未支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $Register->status = RegisterEnum::CANCEL; + $Register->is_cancel = 1; + $Register->cancel_time = time(); + $Register->cancel_remark = '您已主动取消订单'; + $Register->created_at = time(); + $Register->updated_at = time(); + $Register->saveOrFail(); + + //生成系统消息 + $SystemNotice = new SystemNotice(); + $SystemNotice->content = '您已主动取消订单'; + $SystemNotice->base_type = SystemNoticeTypeEnum::ORDER_CANCEL; + $SystemNotice->scene_type = 1;//用户端 + $SystemNotice->user_id = \Yii::$app->user->identity->getId(); + $SystemNotice->notice_at = date('Y-m-d H:i:s', time()); + $SystemNotice->saveOrFail(); + + //分账状态更新 + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $Register->id; + $ledgerForm->status = 2; + $ledgerForm->update('register'); + // $event = new RegisterEvent([ + // 'register' => $Register, + // ]); + // \Yii::$app->trigger(Register::EVENT_CANCELED, $event); + $t->commit(); + + return []; + } catch (\Exception $exception) { + $t->rollBack(); + throw $exception; + } + break; + case 1://已支付 + $t = \Yii::$app->db->beginTransaction(); + try { + //生成记录 + $RegisterRefund = new RegisterRefund(); + $RegisterRefund->user_id = $Register->user_id; + $RegisterRefund->register_id = $Register->id; + $RegisterRefund->refund_no = FuncHelper::generate_order_no('RF'); + $RegisterRefund->refund_price = $Register->price; + $RegisterRefund->remark = '主动取消订单'; + $RegisterRefund->saveOrFail(); + + //取消状态 + $Register->is_cancel = 1; + $Register->cancel_time = time(); + $Register->cancel_remark = '您已主动取消订单'; + //退款状态 + $Register->refund_status = 1; + $Register->refund_time = time(); + $Register->status = RegisterEnum::CANCEL; + $Register->created_at = time(); + $Register->updated_at = time(); + $Register->saveOrFail(); + + //生成系统消息 + $SystemNotice = new SystemNotice(); + $SystemNotice->content = '您已主动取消订单'; + $SystemNotice->base_type = SystemNoticeTypeEnum::ORDER_CANCEL; + $SystemNotice->scene_type = 1;//用户端 + $SystemNotice->user_id = \Yii::$app->user->identity->getId(); + $SystemNotice->notice_at = date('Y-m-d H:i:s', time()); + $SystemNotice->saveOrFail(); + + //退款操作 + $this->refundMoney($RegisterRefund); //可能报错 无效的订单号 + + $t->commit(); + } catch (Exception $exception) { + $t->rollBack(); + throw $exception; + } + break; + } + } + + public function refundMoney($RegisterRefund) + { + $orderNo = $RegisterRefund->register->order_no; + $Register = Register::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); + $PaymentRegister = PaymentRegister::findOne([ + 'order_no' => $orderNo, + 'is_pay' => 1 + ]); +// return [$PaymentRegister->transaction_id]; + if (!$Register || !$PaymentRegister) { + throw new Exception('无效的订单号'); + } + $price = $RegisterRefund->refund_price; + if (bccomp($PaymentRegister->amount, $price, 2) == -1) { + throw new Exception('退款金额大于可退款金额'); + } + + $transaction = \Yii::$app->db->beginTransaction(); + try { + $PaymentRegisterRefund = new PaymentRegisterRefund(); + $PaymentRegisterRefund->refund_no = $RegisterRefund->refund_no; + $PaymentRegisterRefund->amount = $price; + $PaymentRegisterRefund->is_pay = 0; + $PaymentRegisterRefund->pay_type = 0; + $PaymentRegisterRefund->created_at = time(); + $PaymentRegisterRefund->saveOrFail(); + + if (bccomp($price, 0, 2) <= 0) { + $PaymentRegisterRefund->is_pay = 1; + $PaymentRegisterRefund->save(); + + $RegisterRefund->is_refund = 1; + $RegisterRefund->refund_time = time(); + $RegisterRefund->save(); + } else { + switch ($PaymentRegister->pay_type) { + case 1://微信退款 + if (\Yii::$app instanceof \yii\web\Application) { + $notifyUrl = \Yii::$app->request->hostInfo . "/member/v1/callback/refund-notify/"; + } else { + //如果是job中调用的 + $notifyUrl = \Yii::$app->getHostInfo() . "/member/v1/callback/refund-notify/"; + } + + $order_amount = bcmul($PaymentRegister->amount, 100, 0); + $refund_amount = bcmul($price, 100, 0); + + $result = WechatService::getInstance()->payment->refund->byTransactionId($PaymentRegister->transaction_id, $PaymentRegisterRefund->refund_no, $order_amount, $refund_amount, [ + 'refund_desc' => '订单申请退款', + 'notify_url' => $notifyUrl + ]); + if ($result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS') { + $error = isset($result['err_code_des']) ? $result['err_code_des'] : $result['return_msg']; + throw new Exception($error); + } + break; + case 2://易票联退款 + $eplResult = EplPayService::getInstance()->refund([ + 'refund_no' => $PaymentRegisterRefund->refund_no, + 'transaction_id' => $PaymentRegister->transaction_id, + 'total_pay_price' => $PaymentRegister->amount, + 'refund_price' => $price, + ]); + if (!isset($eplResult['returnCode']) || $eplResult['returnCode'] != '0000') { + throw new Exception($eplResult['returnMsg']); + } + break; + + default: + throw new Exception('退款失败,请联系客服'); + break; + } + //其他状态变更在回调 + } + $transaction->commit(); + return []; + } catch (\Exception $exception) { + $transaction->rollBack(); + throw $exception; + } + } +} \ No newline at end of file diff --git a/common/foundation/Cors.php b/common/foundation/Cors.php new file mode 100644 index 0000000..ef62ef8 --- /dev/null +++ b/common/foundation/Cors.php @@ -0,0 +1,279 @@ + [ + * 'class' => \yii\filters\Cors::className(), + * ], + * ]; + * } + * ``` + * + * The CORS filter can be specialized to restrict parameters, like this, + * [MDN CORS Information](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) + * + * ```php + * public function behaviors() + * { + * return [ + * 'corsFilter' => [ + * 'class' => \yii\filters\Cors::className(), + * 'cors' => [ + * // restrict access to + * 'Origin' => ['http://www.myserver.com', 'https://www.myserver.com'], + * // Allow only POST and PUT methods + * 'Access-Control-Request-Method' => ['POST', 'PUT'], + * // Allow only headers 'X-Wsse' + * 'Access-Control-Request-Headers' => ['X-Wsse'], + * // Allow credentials (cookies, authorization headers, etc.) to be exposed to the browser + * 'Access-Control-Allow-Credentials' => true, + * // Allow OPTIONS caching + * 'Access-Control-Max-Age' => 3600, + * // Allow the X-Pagination-Current-Page header to be exposed to the browser. + * 'Access-Control-Expose-Headers' => ['X-Pagination-Current-Page'], + * ], + * + * ], + * ]; + * } + * ``` + * + * For more information on how to add the CORS filter to a controller, see + * the [Guide on REST controllers](guide:rest-controllers#cors). + * + * @author Philippe Gaultier + * @since 2.0 + */ +class Cors extends ActionFilter +{ + /** + * @var Request the current request. If not set, the `request` application component will be used. + */ + public $request; + /** + * @var Response the response to be sent. If not set, the `response` application component will be used. + */ + public $response; + /** + * @var array define specific CORS rules for specific actions + */ + public $actions = []; + /** + * @var array Basic headers handled for the CORS requests. + */ + public $cors = [ + 'Origin' => ['*'], + 'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], + 'Access-Control-Request-Headers' => ['*'], + 'Access-Control-Allow-Credentials' => null, + 'Access-Control-Max-Age' => 86400, + 'Access-Control-Expose-Headers' => [], + ]; + + + /** + * {@inheritdoc} + */ + public function beforeAction($action) + { + $this->request = $this->request ?: Yii::$app->getRequest(); + $this->response = $this->response ?: Yii::$app->getResponse(); + + $this->overrideDefaultSettings($action); + + $requestCorsHeaders = $this->extractHeaders(); + $responseCorsHeaders = $this->prepareHeaders($requestCorsHeaders); + $this->addCorsHeaders($this->response, $responseCorsHeaders); + + if ($this->request->isOptions && $this->request->headers->has('Access-Control-Request-Method')) { + // it is CORS preflight request, respond with 200 OK without further processing + $this->response->setStatusCode(200); + Yii::$app->end(); + return false; + } + + return true; + } + + /** + * Override settings for specific action. + * @param \yii\base\Action $action the action settings to override + */ + public function overrideDefaultSettings($action) + { + if (isset($this->actions[$action->id])) { + $actionParams = $this->actions[$action->id]; + $actionParamsKeys = array_keys($actionParams); + foreach ($this->cors as $headerField => $headerValue) { + if (in_array($headerField, $actionParamsKeys)) { + $this->cors[$headerField] = $actionParams[$headerField]; + } + } + } + } + + /** + * Extract CORS headers from the request. + * @return array CORS headers to handle + */ + public function extractHeaders() + { + $headers = []; + foreach (array_keys($this->cors) as $headerField) { + $serverField = $this->headerizeToPhp($headerField); + $headerData = isset($_SERVER[$serverField]) ? $_SERVER[$serverField] : null; + if ($headerData !== null) { + $headers[$headerField] = $headerData; + } + } + + return $headers; + } + + /** + * For each CORS headers create the specific response. + * @param array $requestHeaders CORS headers we have detected + * @return array CORS headers ready to be sent + */ + public function prepareHeaders($requestHeaders) + { + $responseHeaders = []; + // handle Origin + if (isset($requestHeaders['Origin'], $this->cors['Origin'])) { + if (in_array($requestHeaders['Origin'], $this->cors['Origin'], true)) { + $responseHeaders['Access-Control-Allow-Origin'] = $requestHeaders['Origin']; + } + + if (in_array('*', $this->cors['Origin'], true)) { + // Per CORS standard (https://fetch.spec.whatwg.org), wildcard origins shouldn't be used together with credentials + if (isset($this->cors['Access-Control-Allow-Credentials']) && $this->cors['Access-Control-Allow-Credentials']) { + if (YII_DEBUG) { + throw new InvalidConfigException("Allowing credentials for wildcard origins is insecure. Please specify more restrictive origins or set 'credentials' to false in your CORS configuration."); + } else { + Yii::error("Allowing credentials for wildcard origins is insecure. Please specify more restrictive origins or set 'credentials' to false in your CORS configuration.", __METHOD__); + } + } else { + $responseHeaders['Access-Control-Allow-Origin'] = '*'; + } + } + } + + $this->prepareAllowHeaders('Headers', $requestHeaders, $responseHeaders); + + if (isset($requestHeaders['Access-Control-Request-Method'])) { + $responseHeaders['Access-Control-Allow-Methods'] = implode(', ', $this->cors['Access-Control-Request-Method']); + } + + if (isset($this->cors['Access-Control-Allow-Credentials'])) { + $responseHeaders['Access-Control-Allow-Credentials'] = $this->cors['Access-Control-Allow-Credentials'] ? 'true' : 'false'; + } + + if (isset($this->cors['Access-Control-Max-Age']) && $this->request->getIsOptions()) { + $responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age']; + } + + if (isset($this->cors['Access-Control-Expose-Headers'])) { + $responseHeaders['Access-Control-Expose-Headers'] = implode(', ', $this->cors['Access-Control-Expose-Headers']); + } + + if (isset($this->cors['Access-Control-Allow-Headers'])) { + $responseHeaders['Access-Control-Allow-Headers'] = implode(', ', $this->cors['Access-Control-Allow-Headers']); + } + + return $responseHeaders; + } + + /** + * Handle classic CORS request to avoid duplicate code. + * @param string $type the kind of headers we would handle + * @param array $requestHeaders CORS headers request by client + * @param array $responseHeaders CORS response headers sent to the client + */ + protected function prepareAllowHeaders($type, $requestHeaders, &$responseHeaders) + { + $requestHeaderField = 'Access-Control-Request-' . $type; + $responseHeaderField = 'Access-Control-Allow-' . $type; + if (!isset($requestHeaders[$requestHeaderField], $this->cors[$requestHeaderField])) { + return; + } + if (in_array('*', $this->cors[$requestHeaderField])) { + $responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]); + } else { + $requestedData = preg_split('/[\\s,]+/', $requestHeaders[$requestHeaderField], -1, PREG_SPLIT_NO_EMPTY); + $acceptedData = array_uintersect($requestedData, $this->cors[$requestHeaderField], 'strcasecmp'); + if (!empty($acceptedData)) { + $responseHeaders[$responseHeaderField] = implode(', ', $acceptedData); + } + } + } + + /** + * Adds the CORS headers to the response. + * @param Response $response + * @param array $headers CORS headers which have been computed + */ + public function addCorsHeaders($response, $headers) + { + if (empty($headers) === false) { + $responseHeaders = $response->getHeaders(); + foreach ($headers as $field => $value) { + $responseHeaders->set($field, $value); + } + } + } + + /** + * Convert any string (including php headers with HTTP prefix) to header format. + * + * Example: + * - X-PINGOTHER -> X-Pingother + * - X_PINGOTHER -> X-Pingother + * @param string $string string to convert + * @return string the result in "header" format + */ + protected function headerize($string) + { + $headers = preg_split('/[\\s,]+/', $string, -1, PREG_SPLIT_NO_EMPTY); + $headers = array_map(function ($element) { + return str_replace(' ', '-', ucwords(strtolower(str_replace(['_', '-'], [' ', ' '], $element)))); + }, $headers); + return implode(', ', $headers); + } + + /** + * Convert any string (including php headers with HTTP prefix) to header format. + * + * Example: + * - X-Pingother -> HTTP_X_PINGOTHER + * - X PINGOTHER -> HTTP_X_PINGOTHER + * @param string $string string to convert + * @return string the result in "php $_SERVER header" format + */ + protected function headerizeToPhp($string) + { + return 'HTTP_' . strtoupper(str_replace([' ', '-'], ['_', '_'], $string)); + } +} diff --git a/common/foundation/JsonResponseFormatter.php b/common/foundation/JsonResponseFormatter.php new file mode 100644 index 0000000..f45e701 --- /dev/null +++ b/common/foundation/JsonResponseFormatter.php @@ -0,0 +1,115 @@ +$data,'errcode'=>$errno,'msg'=>$msg]; + } + public $encrypt = true;//是不加密 + /** + * Formats response data in JSON format. + * @param \yii\web\Response $response + */ + protected function formatJson($response) + { + //$response->getHeaders()->set('Content-Type', 'text/plain; charset=UTF-8'); + //$response->getHeaders()->set("Access-Control-Allow-Origin","*"); + if ($response->data !== null) { + $options = $this->encodeOptions; + if ($this->prettyPrint) { + $options |= JSON_PRETTY_PRINT; + } + $errcode = 0; + $msg = ''; + $data=[]; + if(!$response->isSuccessful){ + $response->statusCode = 200; + $errcode=-1; + if(Yii::$app->errorHandler->exception){ +// if(Yii::$app->errorHandler->exception instanceof ) + if(isset(Yii::$app->errorHandler->exception->statusCode)){ + $errcode = Yii::$app->errorHandler->exception->statusCode; + }elseif (Yii::$app->errorHandler->exception->getCode()>0){ + $errcode=Yii::$app->errorHandler->exception->getCode(); + }else{ + $errcode = $this->defaultErrorCode; + } + $msg= YII_DEBUG?Yii::$app->errorHandler->exception->getMessage():'服务器内部错误'; + + } + }else{ + $data = $response->data; + } + + $response->data = self::formatData($data,$errcode,$msg); +// var_dump($response->data);exit; +// if(!$response->isSuccessful){ +// $response->statusCode = 200; +// if($response->data['code']>20000) +// $code = $response->data['code']; +// else +// $code = ErrorCode::APP_EXCEPTION; +// $redirect = ''; +// $response->data = BController::ApiResponse([],$response->data['message'],$code,$redirect); +// } +// if(isset(Yii::$app->params['response_encrpyt']) && Yii::$app->params['response_encrpyt']){ +// $encryption = new MCrypt(); +// $response->content = $encryption->encrypt(Json::encode($response->data, $options)); +// }else{ + $response->content = Json::encode($response->data, $options); +// } + + } + } + + /** + * Formats response data in JSONP format. + * @param \yii\web\Response $response + */ + protected function formatJsonp($response) + { + $response->getHeaders()->set('Content-Type', 'application/javascript; charset=UTF-8'); + if ($response->data !== null) { + $options = $this->encodeOptions; + if ($this->prettyPrint) { + $options |= JSON_PRETTY_PRINT; + } + if(!$response->isSuccessful){ + $response->statusCode = 200; + if($response->data['code']>20000) + $code = $response->data['code']; + else + $code = $this->defaultErrorCode; + $redirect = ''; +// $response->data = BController::ApiResponse([],$response->data['message'],$code,$redirect); + } +// if(isset(Yii::$app->params['response_encrpyt']) && Yii::$app->params['response_encrpyt']){ +// $encryption = new MCrypt(); +// $response->content = $encryption->encrypt(Json::encode($response->data, $options)); +// }else{ +// $response->content = Json::encode($response->data, $options); +// } + + } + $response->data= ['data'=>$response->data,'callback' => Yii::$app->getRequest()->get('callback')]; + if (is_array($response->data) && isset($response->data['data'], $response->data['callback'])) { + $response->content = sprintf('%s(%s);', $response->data['callback'], Json::htmlEncode($response->data['data'])); + } elseif ($response->data !== null) { + $response->content = ''; + Yii::warning("The 'jsonp' response requires that the data be an array consisting of both 'data' and 'callback' elements.", __METHOD__); + } + } +} \ No newline at end of file diff --git a/common/handlers/BaseOrderHandler.php b/common/handlers/BaseOrderHandler.php new file mode 100644 index 0000000..c3bd06d --- /dev/null +++ b/common/handlers/BaseOrderHandler.php @@ -0,0 +1,19 @@ +autoCancel(); + return $this; + } + + public function autoCancel() + { + $config = \Yii::$app->params; + $orderAutoCancelMinute = isset($config['order']['over_time']) ? $config['order']['over_time'] : 900; + if (is_numeric($orderAutoCancelMinute) && $orderAutoCancelMinute >= 0) { + // 订单自动取消任务 + \Yii::$app->queue->delay($orderAutoCancelMinute)->push(new OrderCancelJob([ + 'orderId' => $this->event->order->id, + ])); + $autoCancelTime = $this->event->order->created_at + $orderAutoCancelMinute; + $this->event->order->auto_cancel_time = $autoCancelTime; + $this->event->order->save(); + } + return $this; + } +} diff --git a/common/handlers/OrderPayedHandler.php b/common/handlers/OrderPayedHandler.php new file mode 100644 index 0000000..2611e8e --- /dev/null +++ b/common/handlers/OrderPayedHandler.php @@ -0,0 +1,24 @@ +on(Order::EVENT_PAYED, function ($event) { + /** @var OrderEvent $event */ + $commonOrder = CommonOrder::getCommonOrder($event->order->sign); + $orderHandler = $commonOrder->getOrderHandler(); + $handler = $orderHandler->orderPayedHandlerClass; + $handler->event = $event; + $handler->setMall()->handle(); + }); + } +} diff --git a/common/handlers/OrderPayedHandlerClass.php b/common/handlers/OrderPayedHandlerClass.php new file mode 100644 index 0000000..389f227 --- /dev/null +++ b/common/handlers/OrderPayedHandlerClass.php @@ -0,0 +1,98 @@ +event->order->id); + if ($order->cancel_status == 1 && $order->pay_type == 1) { + OrderLog::saveLog($this->event->order->id,'调起支付后已经自动取消的订单进行退款'); + + $t = \Yii::$app->db->beginTransaction(); + try { + //生成记录 + $orderRefund = new OrderRefund(); + $orderRefund->user_id = $order->user_id; + $orderRefund->order_id = $order->id; + $orderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $orderRefund->refund_price = $order->total_pay_price; + $orderRefund->saveOrFail(); + + $order->cancel_status = 1; + $order->cancel_time = time(); + $order->cancel_remark = '超时未支付取消订单'; + //修改未默认状态 + $order->accept_status = OrderAcceptEnum::NO; + //修改退款状态 + $order->refund_status = 1; + $order->refund_time = time(); + $order->saveOrFail(); + + //退款操作 + $refundForm = new \common\forms\OrderRefundForm(); + $refundForm->refundMoney($orderRefund); + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + OrderLog::saveLog($this->event->order->id,'调起支付后已经自动取消的订单进行退款异常:'.$e->getMessage()); + } + return $this; + }else{ + + //正常支付后操作 + $this->actionAutoRefund()->sendInquiry(); + } + return $this; + } + + //超时自动退款队列 + public function actionAutoRefund() + { + $config = \Yii::$app->params; + $orderAutoRefundMinute = isset($config['order']['refund_time']) ? $config['order']['refund_time'] : 24*60*60; + if (is_numeric($orderAutoRefundMinute) && $orderAutoRefundMinute >= 0) { + // 订单自动取消任务 + \Yii::$app->queue->delay($orderAutoRefundMinute)->push(new OrderRefundJob([ + 'orderId' => $this->event->order->id, + ])); + $autoRefundTime = $this->event->order->created_at + $orderAutoRefundMinute; + $this->event->order->auto_refund_time = $autoRefundTime; + $this->event->order->save(); + } + + return $this; + } + + //发送问诊消息 - 添加会话结束队列 + public function sendInquiry() + { + \Yii::$app->queue->delay(0)->push(new OrderPayImJob([ + 'orderId' => $this->event->order->id, + ])); + return $this; + } + +} diff --git a/common/handlers/PrescripPayHandlerClass.php b/common/handlers/PrescripPayHandlerClass.php new file mode 100644 index 0000000..68609ef --- /dev/null +++ b/common/handlers/PrescripPayHandlerClass.php @@ -0,0 +1,84 @@ +event->order->id); + if ($Prescription->cancel_status == 1 && $Prescription->pay_type == 1) { + PrescripOrderLog::saveLog($this->event->order->id,'调起支付后已经自动取消的订单进行退款'); + + $t = \Yii::$app->db->beginTransaction(); + try { + //生成记录 + $PrescripOrderRefund = new PrescripOrderRefund(); + $PrescripOrderRefund->user_id = $Prescription->user_id; + $PrescripOrderRefund->order_id = $Prescription->id; + $PrescripOrderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $PrescripOrderRefund->refund_price = $Prescription->total_pay_price; + $PrescripOrderRefund->saveOrFail(); + + $Prescription->cancel_status = 1; + $Prescription->cancel_time = time(); + $Prescription->cancel_remark = '超时未支付取消订单'; + + //修改退款状态 + $Prescription->refund_status = 1; + $Prescription->refund_time = time(); + $Prescription->saveOrFail(); + + //退款操作 + $PrescripRefundForm = new PrescripRefundForm(); + $PrescripRefundForm->refundMoney($PrescripOrderRefund); + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + PrescripOrderLog::saveLog($this->event->order->id,'调起支付后已经自动取消的订单进行退款异常:'.$e->getMessage()); + } + return $this; + }else{ + + //正常支付后操作 + $this->actionAutoRefund(); + } + return $this; + } + + //超时自动退款队列 + public function actionAutoRefund() + { + $config = \Yii::$app->params; + $orderAutoRefundMinute = isset($config['order']['refund_time']) ? $config['order']['refund_time'] : 24*60*60; + if (is_numeric($orderAutoRefundMinute) && $orderAutoRefundMinute >= 0) { + // 订单自动取消任务 + \Yii::$app->queue->delay($orderAutoRefundMinute)->push(new PrescripRefundJob([ + 'orderId' => $this->event->order->id, + ])); + $autoRefundTime = $this->event->order->created_at + $orderAutoRefundMinute; + $this->event->order->auto_refund_time = $autoRefundTime; + $this->event->order->save(); + } + + return $this; + } +} \ No newline at end of file diff --git a/common/handlers/PrescriptionAutoExpireHandlerClass.php b/common/handlers/PrescriptionAutoExpireHandlerClass.php new file mode 100644 index 0000000..c183503 --- /dev/null +++ b/common/handlers/PrescriptionAutoExpireHandlerClass.php @@ -0,0 +1,34 @@ +params; + $autoExpireTime = isset($config['prescription']['over_time']) ? $config['prescription']['over_time'] : 900; + if (is_numeric($autoExpireTime) && $autoExpireTime >= 0) { + // 处方自动失效任务 + \Yii::$app->queue->delay($autoExpireTime)->push(new PrescriptionAutoExpireJob([ + 'orderId' => $this->event->prescription->id, + ])); + if($this->event->prescription->auto_expire_time){ + $autoExpire = $this->event->prescription->auto_expire_time + $autoExpireTime; + } else { + $autoExpire = $this->event->prescription->created_at + $autoExpireTime; + } + $this->event->prescription->auto_expire_time = $autoExpire; + $this->event->prescription->save(); + } + return $this; + } +} diff --git a/common/handlers/ProductOrderCreatedHandlerClass.php b/common/handlers/ProductOrderCreatedHandlerClass.php new file mode 100644 index 0000000..50e5cae --- /dev/null +++ b/common/handlers/ProductOrderCreatedHandlerClass.php @@ -0,0 +1,34 @@ +autoCancel(); + return $this; + } + + public function autoCancel() + { + $config = \Yii::$app->params; + $orderAutoCancelMinute = isset($config['product_order']['over_time']) ? $config['product_order']['over_time'] : 900; + if (is_numeric($orderAutoCancelMinute) && $orderAutoCancelMinute >= 0) { + // 订单自动取消任务 + \Yii::$app->queue->delay($orderAutoCancelMinute)->push(new ProductOrderCancelJob([ + 'orderId' => $this->event->order->id, + ])); + $autoCancelTime = $this->event->order->created_at + $orderAutoCancelMinute; + $this->event->order->auto_cancel_time = $autoCancelTime; + $this->event->order->save(); + } + return $this; + } +} diff --git a/common/handlers/ProductOrderPayedHandlerClass.php b/common/handlers/ProductOrderPayedHandlerClass.php new file mode 100644 index 0000000..073261c --- /dev/null +++ b/common/handlers/ProductOrderPayedHandlerClass.php @@ -0,0 +1,26 @@ +autoSync(); + return $this; + } + + public function autoSync() + { + // 订单自动同步任务 + \Yii::$app->queue->push(new ProductOrderSyncJob([ + 'orderId' => $this->event->order->id, + ])); + } +} diff --git a/common/handlers/RegisterCreatedHandler.php b/common/handlers/RegisterCreatedHandler.php new file mode 100644 index 0000000..285c3ae --- /dev/null +++ b/common/handlers/RegisterCreatedHandler.php @@ -0,0 +1,27 @@ +params; + $autoCancelTime = isset($config['register']['cancel_time']) ? $config['register']['cancel_time'] : 1800; + if (is_numeric($autoCancelTime) && $autoCancelTime >= 0) { + // 挂号自动取消任务 + \Yii::$app->queue->delay($autoCancelTime)->push(new RegisterCancelJob([ + 'orderId' => $this->event->register->id, + ])); + } + return $this; + } + +} \ No newline at end of file diff --git a/common/handlers/RegisterPayHandler.php b/common/handlers/RegisterPayHandler.php new file mode 100644 index 0000000..7d07194 --- /dev/null +++ b/common/handlers/RegisterPayHandler.php @@ -0,0 +1,107 @@ +where(['id'=> $this->event->register->id, 'is_pay' => 1])->one(); + if ($Register->is_cancel == 1 ) { + RegisterLog::saveLog($this->event->register->id,'调起支付后针对已经自动取消的订单进行退款_start'); + + $t = \Yii::$app->db->beginTransaction(); + try { + //生成记录 + $RegisterRefund = new RegisterRefund(); + $RegisterRefund->user_id = $Register->user_id; + $RegisterRefund->register_id = $Register->id; + $RegisterRefund->refund_no = FuncHelper::generate_order_no('RF'); + $RegisterRefund->refund_price = $Register->price; + $RegisterRefund->saveOrFail(); + + $Register->is_cancel = 1; + $Register->cancel_time = time(); +// $order->cancel_remark = '超时未支付取消订单'; + + //修改退款状态 + $Register->refund_status = 1; + $Register->refund_time = time(); + $Register->saveOrFail(); + + //退款操作 + $RegisterRefundForm= new \common\forms\RegisterRefundForm(); + $RegisterRefundForm->refundMoney($RegisterRefund); + + $t->commit(); + RegisterLog::saveLog($this->event->register->id,'调起支付后针对已经自动取消的订单进行退款_end'); + } catch (\Exception $e) { + $t->rollBack(); + RegisterLog::saveLog($this->event->order->id,'调起支付后已经自动取消的订单进行退款异常:'.$e->getMessage()); + } + return $this; + }else{ + //正常支付后操作 + $this->actionLedger()->autoOver()->actionAutoRefund(); + } + return $this; + } + + //分账 + public function actionLedger() + { + // 挂号订单分账 - 诊所 + \Yii::$app->queue->delay(0)->push(new RegisterPaidJob([ + 'orderId' => $this->event->register->id, + ])); + return $this; + } + + //自动完成队列 + public function autoOver() + { + // 订单自动完成任务 + $time = time(); + $endTime = strtotime(date('Y-m-d',strtotime('+1 day')));//第二天零点 + $delay=$endTime-$time;//延迟时间 + \Yii::$app->queue->delay($delay)->push(new RegisterOverJob([ + 'orderId' => $this->event->register->id, + ])); + return $this; + } + + + + //超时自动退款队列 + public function actionAutoRefund() + { + $config = \Yii::$app->params; + $orderAutoRefundMinute = isset($config['order']['refund_time']) ? $config['order']['refund_time'] : 24*60*60; + if (is_numeric($orderAutoRefundMinute) && $orderAutoRefundMinute >= 0) { + // 订单自动取消任务 + \Yii::$app->queue->delay($orderAutoRefundMinute)->push(new RegisterRefundJob([ + 'orderId' => $this->event->register->id, + ])); + } + + return $this; + } +} \ No newline at end of file diff --git a/common/handlers/orderHandler/BaseOrderCanceledHandler.php b/common/handlers/orderHandler/BaseOrderCanceledHandler.php new file mode 100644 index 0000000..97cad72 --- /dev/null +++ b/common/handlers/orderHandler/BaseOrderCanceledHandler.php @@ -0,0 +1,158 @@ +cancel(); + } + + protected function cancel() + { + $t = \Yii::$app->db->beginTransaction(); + try { + CommonLog::saveLog($this->event->order->id,'订单取消canceled事件start'); + /* @var OrderEvent $event */ + $this->action(); + $t->commit(); + + CommonLog::saveLog($this->event->order->id,'订单取消canceled事件end'); + } catch (\Exception $exception) { + $t->rollBack(); + throw $exception; + } + } + + protected function action() + { + $this->couponResume()->extraCancel($this->event->order)->goodsAddStock($this->event->order); +// $this->couponResume()->sendTemplate()->goodsAddStock($this->event->order)->sendSmsToUser(); + } + + /** + * 优惠券恢复 + * @return $this + */ + protected function couponResume() + { + // 优惠券恢复 + if ($this->event->order->use_user_coupon_id) { + $userCoupon = UserCoupon::findOne(['id' => $this->event->order->use_user_coupon_id]); + $userCoupon->is_use = 0; + $userCoupon->save(); + } + CommonLog::saveLog($this->event->order->id,'订单取消优惠券恢复'); + return $this; + } + + /** + * 额外的取消处理 + * @param $order + * @throws Exception + * @throws \yii\base\Exception + */ + protected function extraCancel($order) + { + (new CommonOrder())->extraCancel($order); + return $this; + } + + protected function sendTemplate() + { +// try { +// $order = $this->event->order; +// $remark = $order->cancel_status == 1 ? '商家同意取消' : '商家拒绝取消'; +// +// $goodsName = ''; +// foreach ($order->detail as $orderDetail) { +// $goodsName .= $orderDetail->goods->name; +// } +// +// TemplateList::getInstance()->getTemplateClass(OrderCancelInfo::TPL_NAME)->send([ +// 'goodsName' => $goodsName, +// 'order_no' => $order->order_no, +// 'price' => $order->total_pay_price, +// 'remark' => $remark, +// 'user' => $order->user, +// 'page' => 'pages/order/index/index?status=2' +// ]); +// } catch (\Exception $exception) { +// \Yii::error('模板消息发送: ' . $exception->getMessage()); +// } + + return $this; + } + + /** + * @param Order $order + * @throws Exception + */ + protected function goodsAddStock($order) + { + /* @var OrderDetail[] $orderDetail */ + $orderDetail = $order->detail; + $goodsAttrIdList = []; + $goodsNum = []; + foreach ($orderDetail as $item) { + $goodsInfo = json_decode($item->goods_info,true); + $goodsAttrIdList[] = $goodsInfo['goods_attr']['id']; + $goodsNum[$goodsInfo['goods_attr']['id']] = $item->num; + } + $goodsAttrList = GoodsAttr::find()->where(['id' => $goodsAttrIdList])->all(); + /* @var GoodsAttr[] $goodsAttrList */ + foreach ($goodsAttrList as $goodsAttr) { + $goodsAttr->updateStock($goodsNum[$goodsAttr->id], 'add'); + } + + CommonLog::saveLog($this->event->order->id,'订单取消商品库存返还'); + return $this; + } + + protected function sendSmsToUser() + { +// try { +// \Yii::warning('----消息发送提醒----'); +// $order = $this->event->order; +// if (!$order->user->mobile) { +// throw new \Exception('用户未绑定手机号无法发送'); +// } +// $messageService = new MessageService(); +// $messageService->user = $order->user; +// $messageService->content = [ +// 'mch_id' => $order->mch_id, +// 'args' => [substr($order->order_no, -6)] +// ]; +// $messageService->platform = PlatformConfig::getInstance()->getPlatform($order->user); +// $messageService->tplKey = OrderCancelInfo::TPL_NAME; +// $res = $messageService->templateSend(); +// } catch (\Exception $exception) { +// \Yii::error('向用户发送短信消息失败'); +// \Yii::error($exception); +// } + return $this; + } +} diff --git a/common/handlers/orderHandler/BaseOrderCreatedHandler.php b/common/handlers/orderHandler/BaseOrderCreatedHandler.php new file mode 100644 index 0000000..9ec4e5a --- /dev/null +++ b/common/handlers/orderHandler/BaseOrderCreatedHandler.php @@ -0,0 +1,39 @@ +mall->getMallSettingOne('over_time'); + if (is_numeric($orderAutoCancelMinute) && $orderAutoCancelMinute >= 0) { + CommonLog::saveLog($this->event->order->id,'添加自动取消延迟队列'); + // 订单自动取消任务 + \Yii::$app->queue->delay($orderAutoCancelMinute * 60)->push(new OrderCancelJob([ + 'orderId' => $this->event->order->id, + ])); + $autoCancelTime = $this->event->order->created_at + $orderAutoCancelMinute * 60; + $this->event->order->auto_cancel_time = $autoCancelTime; + $this->event->order->save(); + } + return $this; + } + + /** + * 购物车商品购买后删除 + */ + protected function deleteCartGoods() + { + Cart::deleteAll(['id' => $this->event->cartIds]); + CommonLog::saveLog($this->event->order->id,'删除购物车'); + } +} diff --git a/common/handlers/orderHandler/BaseOrderHandler.php b/common/handlers/orderHandler/BaseOrderHandler.php new file mode 100644 index 0000000..30ad261 --- /dev/null +++ b/common/handlers/orderHandler/BaseOrderHandler.php @@ -0,0 +1,37 @@ +mall = \Yii::$app->mall; + } catch (\Exception $exception) { + $mall = Mall::findOne(['id' => $this->event->order->mall_id]); + \Yii::$app->setMall($mall); + $this->mall = \Yii::$app->mall; + } + return $this; + } +} diff --git a/common/handlers/orderHandler/BaseOrderPayedHandler.php b/common/handlers/orderHandler/BaseOrderPayedHandler.php new file mode 100644 index 0000000..2d7e26a --- /dev/null +++ b/common/handlers/orderHandler/BaseOrderPayedHandler.php @@ -0,0 +1,376 @@ +sendCard(); + $userCouponList = $this->sendCoupon(); + $userCouponList = array_merge($userCouponList, $this->sendCouponUse(), $this->sendCouponByGoods()); + $data = [ + 'card_list' => $cardList, + 'user_coupon_list' => $userCouponList, + ]; + $orderPayResult = new OrderPayResult(); + $orderPayResult->order_id = $this->event->order->id; + $orderPayResult->data = $orderPayResult->encodeData($data); + $orderPayResult->save(); + return $this; + } + + /** + * @return array + * 向用户发送商品卡券 + */ + protected function sendCard() + { + try { + $cardSendForm = new CommonSend(); + $cardSendForm->mall_id = \Yii::$app->mall->id; + $cardSendForm->user_id = $this->event->order->user_id; + $cardSendForm->order_id = $this->event->order->id; + /** @var UserCard[] $userCardList */ + $userCardList = $cardSendForm->save(); + $cardList = []; + foreach ($userCardList as $userCard) { + $cardList[] = $userCard->attributes; + } + } catch (\Exception $exception) { + \Yii::error('卡券发放失败: ' . $exception->getMessage()); + $cardList = []; + } + return $cardList; + } + + /** + * @return array + * 向用户发送优惠券(自动发送方案--订单支付成功发送优惠券) + */ + protected function sendCoupon() + { + try { + $couponSendForm = new CommonCouponAutoSend(); + $couponSendForm->event = CouponAutoSend::PAY; + $couponSendForm->user = $this->user; + $couponSendForm->mall = $this->mall; + $userCouponList = $couponSendForm->send(); + } catch (\Exception $exception) { + \Yii::error('优惠券发放失败: ' . $exception->getMessage()); + $userCouponList = []; + } + return $userCouponList; + } + + /** + * @return array + * 向用户发送优惠券(购买商品赠送--订单支付成功发送优惠券) + */ + protected function sendCouponByGoods() + { + try { + $couponSendForm = new CommonCouponGoodsSend(); + $couponSendForm->user = $this->user; + $couponSendForm->mall = $this->mall; + $couponSendForm->order_id = $this->event->order->id; + $userCouponList = $couponSendForm->send(); + \Yii::warning('购买商品赠送优惠券发放数据'); + \Yii::warning($userCouponList); + } catch (\Exception $exception) { + \Yii::error('商品赠送优惠券发放失败: ' . $exception->getMessage()); + $userCouponList = []; + } + return $userCouponList; + } + + /** + * 优惠券自动赠送规则 + * @return array + */ + protected function sendCouponUse() + { + try { + if ($this->event->order->use_user_coupon_id && $userCoupon = UserCoupon::findOne($this->event->order->use_user_coupon_id)) { + $couponUseSendForm = new CommonCouponGoodsSend(); + $couponUseSendForm->user = $this->user; + $couponUseSendForm->mall = $this->mall; + $couponUseSendForm->order_id = $this->event->order->id; + $couponData = $couponUseSendForm->useSend($userCoupon->coupon_id); + return [$couponData]; + } + throw new \Exception('订单或优惠券问题'); + } catch (\Exception $e) { + \Yii::error('优惠券购赠失败:' . $e->getMessage()); + return []; + } + } + + /** + * @return $this + * 短信发送--新订单通知 + */ + protected function sendSms() + { + try { + if ($this->orderConfig->is_sms != 1) { + throw new \Exception('未开启短信提醒'); + } + $sms = new Sms(['mch_id' => $this->event->order->mch_id]); + $smsConfig = CommonAppConfig::getSmsConfig($this->event->order->mch_id); + if ($smsConfig['status'] == 1 && $smsConfig['mobile_list']) { + $sms->sendOrderMessage($smsConfig['mobile_list'], $this->event->order->order_no); + } + } catch (NoGatewayAvailableException $exception) { + \Yii::error('短信发送: ' . $exception->getExceptions()); + } catch (\Exception $exception) { + \Yii::error('短信发送: ' . $exception->getMessage()); + } + return $this; + } + + /** + * @return $this + * 邮件发送--新订单通知 + */ + protected function sendMail() + { + // 发送邮件 + try { + if ($this->orderConfig->is_mail != 1) { + throw new \Exception('未开启邮件提醒'); + } + $mailer = new SendMail(); + $mailer->mall = $this->mall; + $mailer->mch_id = $this->event->order->mch_id; + $mailer->order = $this->event->order; + $mailer->orderPayMsg(); + } catch (\Exception $exception) { + \Yii::error('邮件发送: ' . $exception->getMessage()); + } + return $this; + } + + /** + * @return $this + * 首次付款成为下级 + */ + protected function becomeJuniorByFirstPay() + { + try { + $commonShare = new CommonShare(); + $commonShare->mall = $this->mall; + $commonShare->user = $this->user; + $commonShare->bindParent($this->user->userInfo->temp_parent_id, 3); + } catch (\Exception $exception) { + \Yii::error('首次付款成为下级:' . $exception->getMessage()); + } + return $this; + } + + /** + * @return $this + * 下单成为分销商 + */ + protected function becomeShare() + { + try { + $commonShare = new CommonShare(); + $commonShare->mall = $this->mall; + $commonShare->becomeShareByAuto($this->event->order); + } catch (\Exception $exception) { + \Yii::error('下单成为分销商: ' . $exception->getMessage()); + } + return $this; + } + + /** + * @return $this + * 通过小程序模板消息发送给用户支付成功通知 + */ + protected function sendTemplate() + { + try { + $order = $this->event->order; + $goodsName = ''; + foreach ($order->detail as $orderDetail) { + $goodsName .= $orderDetail->goods->name; + } + TemplateList::getInstance()->getTemplateClass(OrderPayInfo::TPL_NAME)->send([ + 'order_no' => $order->order_no, + 'pay_time' => $order->pay_time, + 'price' => $order->total_pay_price, + 'goodsName' => $goodsName, + 'user' => $order->user, + 'page' => 'pages/order/index/index' + ]); + } catch (\Exception $exception) { + \Yii::error('模板消息发送: ' . $exception->getMessage()); + } + return $this; + } + + /** + * @return $this + * 通过公众号向商家发送公众号消息 + */ + protected function sendMpTemplate() + { + if ($this->event->order->mch_id > 0) { + \Yii::warning('多商户订单无需向平台管理员发送模板消息'); + return $this; + } + + $goodsName = ''; + foreach ($this->event->order->detail as $detail) { + $goodsName .= $detail->goods->name; + } + try { + $tplMsg = new MpTplMsgSend(); + $tplMsg->method = 'newOrderTpl'; + $tplMsg->params = [ + 'sign' => $this->event->order->sign, + 'goods' => $goodsName, + 'time' => date('Y-m-d H:i:s'), + 'user' => $this->user->nickname, + 'total_pay_price' => $this->event->order->total_pay_price, + ]; + $tplMsg->sendTemplate(new MpTplMsgDSend()); + } catch (\Exception $exception) { + \Yii::error('公众号模板消息发送: ' . $exception->getMessage()); + } + return $this; + } + + + protected function sendTemplateMsgToMch() + { + if ($this->event->order->mch_id == 0) { + return $this; + } + \Yii::warning('多商户发送商家模板消息'); + + try { + /** @var Mch $mch */ + $mch = Mch::find()->where(['id' => $this->event->order->mch_id])->with('user')->one(); + if (!$mch) { + throw new \Exception('商户不存在,商户审核订阅消息发送失败'); + } + + if (!$mch->user) { + throw new \Exception('用户不存在,商户审核订阅消息发送失败'); + } + + TemplateList::getInstance()->getTemplateClass(MchSuccessInfo::TPL_NAME)->send([ + 'order_no' => $this->event->order->order_no, + 'price' => $this->event->order->total_pay_price, + 'time' => $this->event->order->created_at, + 'remark' => $this->event->order->remark ? '备注:' . $this->event->order->remark : '有用户下单,请尽快处理', + 'user' => $mch->user, + 'page' => 'plugins/mch/mch/order/order?mch_id=' . $this->event->order->mch_id + ]); + } catch (\Exception $exception) { + \Yii::error('模板消息发送: ' . $exception->getMessage()); + } + try { + \Yii::warning('----消息发送提醒----'); + if (!$mch->user->mobile) { + throw new \Exception('用户未绑定手机号无法发送'); + } + $messageService = new MessageService(); + $messageService->user = $mch->user; + $messageService->content = [ + 'mch_id' => $this->event->order->mch_id, + 'args' => [\Yii::$app->mall->name] + ]; + $messageService->platform = PlatformConfig::getInstance()->getPlatform($mch->user); + $messageService->tplKey = OrderPayInfo::TPL_NAME; + $res = $messageService->templateSend(); + } catch (\Exception $exception) { + \Yii::error('向用户发送短信消息失败'); + \Yii::error($exception); + } + + return $this; + } + + /** + * @return $this + * 向小程序端发送购买提示消息 + */ + protected function sendBuyPrompt() + { + if (count($this->event->order->detail) > 0) { + $details = $this->event->order->detail; + $goods = $details[0]->goods; + $goodsId = $goods->id; + $goodsName = $goods->name; + } else { + $goodsId = 0; + $goodsName = ''; + } + try { + $buy_data = new CommonBuyPrompt(); + $buy_data->nickname = $this->user->nickname; + $buy_data->avatar = $this->user->userInfo->avatar; + $buy_data->url = '/pages/goods/goods/id=' . $goodsId; + $buy_data->goods_name = $goodsName; + $buy_data->set(); + } catch (\Exception $exception) { + \Yii::error('首页购买提示失败: ' . $exception->getMessage()); + } + return $this; + } + + protected function setGoods() + { + try { + CommonLog::saveLog($this->event->order->id,'增加支付统计修改支付销量'); + CommonGoods::getCommon()->setGoodsPayment($this->event->order, 'add'); + CommonGoods::getCommon()->setGoodsSales($this->event->order); + } catch (\Exception $exception) { + CommonLog::saveLog($this->event->order->id,'增加支付统计修改支付销量异常:'.$exception->getMessage()); + } + return $this; + } + + /** + * @return $this + * 向用户发送短信提醒 + */ + protected function sendSmsToUser() + { + try { + \Yii::warning('----消息发送提醒----'); + $order = $this->event->order; + if (!$order->user->mobile) { + throw new \Exception('用户未绑定手机号无法发送'); + } + $messageService = new MessageService(); + $messageService->user = $order->user; + $messageService->content = [ + 'mch_id' => $order->mch_id, + 'args' => [\Yii::$app->mall->name] + ]; + $messageService->platform = PlatformConfig::getInstance()->getPlatform($order->user); + $messageService->tplKey = OrderPayInfo::TPL_NAME; + $res = $messageService->templateSend(); + } catch (\Exception $exception) { + \Yii::error('向用户发送短信消息失败'); + \Yii::error($exception); + } + return $this; + } +} diff --git a/common/handlers/orderHandler/BaseOrderSalesHandler.php b/common/handlers/orderHandler/BaseOrderSalesHandler.php new file mode 100644 index 0000000..57199e1 --- /dev/null +++ b/common/handlers/orderHandler/BaseOrderSalesHandler.php @@ -0,0 +1,351 @@ +sales(); + } + + protected function sales() + { + /**@var OrderEvent $event */ + $event = $this->event; + CommonLog::saveLog($event->order->id,'过售后sales事件start'); + try { + $this->order = $event->order; + $this->user = User::find()->where(['id' => $this->order->user_id])->one(); + + $orderRefundList = OrderRefund::find()->where([ + 'order_id' => $this->order->id, + 'is_delete' => 0, + ])->all(); + // 已退款的订单详情id列表 + $notOrderDetailIdList = []; + if ($orderRefundList) { + /* @var OrderRefund[] $orderRefundList */ + foreach ($orderRefundList as $orderRefund) { + //退货退款,为拒绝,并且未实际退款,退款进行中不进行 + if ($orderRefund->status != 3 && in_array($orderRefund->type, [1, 3]) && $orderRefund->is_refund == 0) { + return false; + } else if ($orderRefund->status != 3 && $orderRefund->type == 2 && $orderRefund->is_confirm == 0) { + return false; + } + } + } + + $query = OrderDetail::find()->where(['order_id' => $this->order->id, 'is_delete' => 0])->with('goods', 'refund','goods.supplierDrugMall'); + if(!empty($notOrderDetailIdList)){ + $query->andWhere(['not in', 'id', $notOrderDetailIdList]); + }; + $this->orderDetailList = $query->all(); + + $this->action(); + + CommonLog::saveLog($event->order->id,'过售后sales事件end'); + } catch (\Exception $e) { + \Yii::error($e); + } + } + + protected function action() + { + // 发放佣金 +// $res = $this->giveShareMoney(); + // 过售后成为分销商 +// $this->becomeShare(); + // 发放积分 + $this->giveClerkIntegral(); + $this->giveIntegral(); + //如果是微信支付,添加分账方并请求分账 + $this->wechatSub(); + + + //确认分账 - 没有异步也就没有确认 +// $this->confirmSubAmount(); + + // 发放余额 +// $this->giveBalance(); + // 入驻商订单金额转到商户余额 +// $this->transferToMch($res); + // 消费升级会员等级 +// $this->level(); + //自动评价 + $this->autoOrderCommon(); + } + + public function wechatSub() + { + try { + $order = $this->event->order; + if(!$order->is_shareing){ + return true; + } + $payment = PaymentOrder::find()->where([ + 'order_no' => $order->order_no, + 'is_pay' => 1, + 'pay_type' => 1 + ])->one(); + if(!$payment){ + throw new Exception('未找到支付订单'); + } + + CommonLog::saveLog($this->event->order->id,'微信请求分账start'); + //添加分账方 + $data = [ + 'receiver' => [ + 'type' => 'MERCHANT_ID', + 'account' => \Yii::$app->params['huiliao_wechat']['merchant_id'], + 'name'=>\Yii::$app->params['huiliao_wechat']['full_name'], + 'relation_type' => 'DISTRIBUTOR', + ] + ]; + + $wechat = new WechatService(); + $res = $wechat->profitSharingAddReceiver($data); + if(!$res){ + throw new Exception('添加分账接收方失败'); + } + $shareing_percent = \Yii::$app->params['company']['shareing_percent']; + //请求分账 - 分账金额低于0.01的不再分账,直接完结分账 + $sub_amount = bcmul($order->total_pay_price,bcdiv($shareing_percent,100,2),2); + + $sub = new OrderWechatSubAmount(); + $sub->order_no = $order->order_no; + $sub->total_amount = $order->total_pay_price; + $sub->sub_order_no = FuncHelper::generate_order_no('SH'); + $sub->sub_id = \Yii::$app->params['huiliao_wechat']['merchant_id']; + $sub->sub_percent = $shareing_percent; + $sub->sub_amount = $sub_amount; + + if(bccomp($sub_amount,0,2) == 1){ + //单次分账 + $data = [ + 'transaction_id' => $payment->transaction_id, + 'out_order_no' => $sub->sub_order_no, + 'receivers' => [ + [ + "type" => "MERCHANT_ID", + "account" => \Yii::$app->params['huiliao_wechat']['merchant_id'], + "amount" => intval(bcmul($sub->sub_amount,100,0)), + "description" => '订单单次分账,分账来源商户号:'.\Yii::$app->params['wechat']['merchant_id'] + ] + ] + ]; + $sub->data = json_encode($data); + $sub->saveOrFail(); + + $wechat = new WechatService(); + $wechat->profitSharing($data); + + }else{ + //完结分账 + $data = [ + 'transaction_id' => $payment->transaction_id, + 'out_order_no' => $sub->sub_order_no, + 'description' => '订单完成分账' + ]; + + $sub->data = json_encode($data); + $sub->saveOrFail(); + + $wechat = new WechatService(); + $wechat->profitSharingFinish($data); + } + //添加分账查询队列 + //定时查询 + \Yii::$app->queue->delay(30)->push(new WechatShareingQueryJob([ + 'shareing' => $sub, + 'key' => 0 + ])); + }catch (\Exception $exception){ + CommonLog::saveLog($this->event->order->id,'微信请求分账异常:'.$exception->getMessage()); + } + } + +// public function confirmSubAmount() +// { +// try { +// CommonLog::saveLog($this->event->order->id,'分账确认start'); +// +// $order = $this->event->order; +// if($order->pay_type==4) +// { +// $orderSubAmount = OrderSubAmount::find()->where([ +// 'mall_id' => $order->mall_id, +// 'order_id' => $order->id, +// 'status' => 1, +// ])->orderBy('id desc')->one(); +// if($orderSubAmount) +// { +// $data = json_decode($orderSubAmount['data'],true); +// +// $param = []; +// $param['merOrderId'] = $data['merOrderId']; +// $param['platformAmount'] = $data['platformAmount']; +// $param['subOrders'] = $data['subOrders']; +// $re = (new BankService())->orderComplete($data); +// if($re){ +// OrderSubAmount::updateAll(['status'=>2],[ +// 'mall_id' => $order->mall_id, +// 'order_id' => $order->id, +// 'status' => 1, +// ]); +// }else{ +// OrderSubAmount::updateAll(['status'=>-1],[ +// 'mall_id' => $order->mall_id, +// 'order_id' => $order->id, +// 'status' => 1, +// ]); +// } +// $orderSubAmount->save(); +// } +// } +// CommonLog::saveLog($this->event->order->id,'分账确认end'); +// }catch (\Exception $exception){ +// CommonLog::saveLog($this->event->order->id,'分账确认异常:'.$exception->getMessage()); +// } +// } + + private function autoOrderCommon() + { + $mallSetting = (new Mall())->getMallSetting(['has_order_evaluate', 'order_evaluate_day']); + if ($mallSetting['has_order_evaluate']) { + foreach ($this->orderDetailList as $orderDetail) { + if ($orderDetail instanceof OrderDetail) { + CommonLog::saveLog($this->event->order->id,'添加自动评价队列'); + \Yii::$app->queue->delay(60 * 60 * 24 * (int)$mallSetting['order_evaluate_day'])->push(new OrderAutoComments([ + 'orderDetail' => $orderDetail, + ])); + } + } + } + } + + //用户积分发放 + protected function giveIntegral() + { + $transaction = \Yii::$app->db->beginTransaction(); + try { + CommonLog::saveLog($this->event->order->id,'用户积分发放start'); + foreach ($this->orderDetailList as $orderDetail) { + + if ($orderDetail->goods->give_integral_type == 1) { + $sendIntegral = bcmul($orderDetail->goods->give_integral,$orderDetail->num,4); + } else { + $sendIntegral = bcmul($orderDetail->total_price,bcdiv($orderDetail->goods->give_integral,100,2),4); + } + + if(bccomp($sendIntegral,0,4) <=0){ + continue; + } + + $user = User::findOne($this->order->user_id); + if(!$user->updateCounters(['current_integral_common' => $sendIntegral,'total_integral_common'=>$sendIntegral])){ + throw new Exception('更新账户失败'); + }; + + $integralLog = new IntegralLog(); + $integralLog->mall_id = \Yii::$app->mall->id; + $integralLog->user_id = $this->order->user_id; + $integralLog->type = 1; + $integralLog->integral = $sendIntegral; + $integralLog->desc = "订单购买赠送积分"; + $integralLog->custom_desc = json_encode(['msg' => '用户积分变动说明']); + $integralLog->order_id = $this->order->id; + $integralLog->order_detail_id = $orderDetail->id; + if (!$integralLog->save()) { + throw new \Exception($this->getErrorMsg($integralLog)); + } + } + $transaction->commit(); + CommonLog::saveLog($this->event->order->id,'用户积分发放end'); + return true; + } catch (\Exception $e) { + $transaction->rollBack(); + CommonLog::saveLog($this->event->order->id,'用户积分发货异常:'.$e->getMessage()); + return false; + } + } + + // 店员积分发放 + protected function giveClerkIntegral() + { + $transaction = \Yii::$app->db->beginTransaction(); + try { + CommonLog::saveLog($this->event->order->id,'店员积分发放start'); + + foreach ($this->orderDetailList as $orderDetail) { + + if(!$this->order->clerk_id){ + continue;//如果没有对应店员不处理 + } + + if(!$orderDetail->supplier_id || !$orderDetail->agent_id){ + continue;//没有积分关系 + } + $sendIntegral = bcmul($orderDetail->total_price,$orderDetail->dy_integral,4); + if(bccomp($sendIntegral,0,4) <= 0){ + continue; + } + $model = new ClerkIntegralGive(); + $model->agent_id = $orderDetail->agent_id; + $model->supplier_id = $orderDetail->supplier_id; + + + $model->mall_id = \Yii::$app->mall->id; + $model->user_id = $this->order->clerk_id; + $model->order_id = $this->order->id; + $model->order_detail_id = $orderDetail->id; + $model->integral = $sendIntegral; + $model->saveOrFail(); + + $user = User::findOne($this->order->clerk_id); + if(!$user->updateCounters(['current_integral' => $sendIntegral,'total_integral'=>$sendIntegral])){ + throw new Exception('更新账户失败'); + }; + } + $transaction->commit(); + CommonLog::saveLog($this->event->order->id,'店员积分发放end'); + return true; + } catch (\Exception $e) { + $transaction->rollBack(); + CommonLog::saveLog($this->event->order->id,'店员积分发放异常:'.$e->getMessage()); + return false; + } + } +} diff --git a/common/handlers/orderHandler/OrderCanceledHandlerClass.php b/common/handlers/orderHandler/OrderCanceledHandlerClass.php new file mode 100644 index 0000000..3303fc2 --- /dev/null +++ b/common/handlers/orderHandler/OrderCanceledHandlerClass.php @@ -0,0 +1,12 @@ +user = $this->event->order->user; + + $this->cancel(); + } +} diff --git a/common/handlers/orderHandler/OrderCreatedHandlerClass.php b/common/handlers/orderHandler/OrderCreatedHandlerClass.php new file mode 100644 index 0000000..ecb05eb --- /dev/null +++ b/common/handlers/orderHandler/OrderCreatedHandlerClass.php @@ -0,0 +1,15 @@ +event->order->id,'下单created事件start'); + $this->user = $this->event->order->user; + $this->setAutoCancel()->deleteCartGoods(); + CommonLog::saveLog($this->event->order->id,'下单created事件end'); + } +} diff --git a/common/handlers/orderHandler/OrderHandler.php b/common/handlers/orderHandler/OrderHandler.php new file mode 100644 index 0000000..2f1178b --- /dev/null +++ b/common/handlers/orderHandler/OrderHandler.php @@ -0,0 +1,44 @@ +event->order->id,'订单支付事件start'); + self::execute(); + CommonLog::saveLog($this->event->order->id,'订单支付事件end'); + } + + protected function execute() + { + $this->user = $this->event->order->user; + /** + * 订单是否取消状态(针对调起支付后,自动取消的订单) + * 退款且不执行后续操作 + * $order 重新查一次最新的订单数据 + */ + $order = Order::findOne($this->event->order->id); + if ($order->cancel_status == 1 && ($order->pay_type == 1 || $order->pay_type == 4)) { + CommonLog::saveLog($this->event->order->id,'调起支付后已经自动取消的订单进行退款'); + + $t = \Yii::$app->db->beginTransaction(); + try { + // 生成售后订单 + $orderRefund = new OrderRefund(); + $orderRefund->mall_id = \Yii::$app->mall->id; + $orderRefund->user_id = $this->user->id; + $orderRefund->order_id = $order->id; + $orderRefund->order_detail_id = 0; + $orderRefund->order_no = Order::getOrderNo('RE'); + $orderRefund->type = 1; + $orderRefund->refund_price = $order->total_pay_price; + $orderRefund->status = 2; + $orderRefund->is_refund = 1; + $res = $orderRefund->save(); + if (!$res) { + throw new \Exception((new BaseModel())->getErrorMsg($orderRefund)); + } + + (new CommonOrder())->extraCancel($order); + + (new OrderRefundForm())->refundMoney($orderRefund,$orderRefund->refund_price); + + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + CommonLog::saveLog($this->event->order->id,'调起支付后已经自动取消的订单进行退款异常:'.$e->getMessage()); + } + return $this; + }else{ + static::notice(); +// static::pay(); + } + return $this; + } + + protected function notice() + { +// $this->sendSms()->sendMail()->receiptPrint('pay') +// ->sendTemplate()->sendMpTemplate()->sendTemplateMsgToMch()->sendBuyPrompt()->setGoods()->sendSmsToUser()->addShareOrder(); + $this->setGoods()->setAutoCancel()->sendCfTemplate()->setSubAmount(); + return $this; + } + + /** + * 支付后分账记录状态调整 + */ + public function setSubAmount() + { + OrderSubAmount::updateAll(['status'=>1],[ + 'order_id' => $this->event->order->id, + 'mall_id' => $this->event->order->mall_id, + 'status' => 0 + ]); + } + + /** + * 超时未填写处方单取消订单退款 + */ + public function setAutoCancel() + { + $order = Order::findOne($this->event->order->id); + if($order->prescription_status == 1){ + \Yii::$app->queue4->delay(48*60*60)->push(new CfOrderCancelJob([ + 'orderId' => $this->event->order->id, + ])); + } + return $this; + } + + /** + * 处方单提醒消息 + */ + public function sendCfTemplate() + { + $order = Order::findOne($this->event->order->id); + if($order->prescription_status == 1){ + \Yii::$app->queue4->delay(5*60)->push(new CfTemplateJob([ + 'orderId' => $this->event->order->id, + "data" => [ + 'character_string1' => [ + 'value' => $this->event->order->order_no, + ], + 'phrase2' => [ + 'value' => '已付款', + ], + 'date3' => [ + 'value' => date("Y/m/d",$this->event->order->created_at), + ], + 'thing4' => [ + 'value' => '您的订单含有处方药,请尽快填写用药信息', + ], + ], + "page" => "/pages/PreliminaryInformation/PreliminaryInformation?orderInfo=".urlencode('{"order_id":'.$this->event->order->id.'}') + ])); + + \Yii::$app->queue4->delay(55*60)->push(new CfTemplateJob([ + 'orderId' => $this->event->order->id, + "data" => [ + 'character_string1' => [ + 'value' => $this->event->order->order_no, + ], + 'phrase2' => [ + 'value' => '已付款', + ], + 'date3' => [ + 'value' => date("Y/m/d",$this->event->order->created_at), + ], + 'thing4' => [ + 'value' => '您的订单含有处方药,请尽快填写用药信息', + ], + ], + "page" => "/pages/PreliminaryInformation/PreliminaryInformation?orderInfo=".urlencode('{"order_id":'.$this->event->order->id.'}') + ])); + + \Yii::$app->queue4->delay(24*60*60)->push(new CfTemplateJob([ + 'orderId' => $this->event->order->id, + "data" => [ + 'character_string1' => [ + 'value' => $this->event->order->order_no, + ], + 'phrase2' => [ + 'value' => '已付款', + ], + 'date3' => [ + 'value' => date("Y/m/d",$this->event->order->created_at), + ], + 'thing4' => [ + 'value' => '请尽快填写用药信息,超期将退款并关闭订单', + ], + ], + "page" => "/pages/PreliminaryInformation/PreliminaryInformation?orderInfo=".urlencode('{"order_id":'.$this->event->order->id.'}') + ])); + } + return $this; + } + +// protected function pay() +// { +// \Yii::error('--mall pay--'); +// // 首次付款绑定下级--生成分销订单--下单用户成为分销商--设置卡密数据 +// $this->saveResult()->becomeJuniorByFirstPay()->addShareOrder()->becomeShare()->setTypeData(); +// return $this; +// } +} diff --git a/common/handlers/orderHandler/OrderSalesHandlerClass.php b/common/handlers/orderHandler/OrderSalesHandlerClass.php new file mode 100644 index 0000000..86bee68 --- /dev/null +++ b/common/handlers/orderHandler/OrderSalesHandlerClass.php @@ -0,0 +1,12 @@ +user = $this->event->order->user; + + $this->sales(); + } +} diff --git a/common/helpers/ArrayHelper.php b/common/helpers/ArrayHelper.php new file mode 100644 index 0000000..53fff47 --- /dev/null +++ b/common/helpers/ArrayHelper.php @@ -0,0 +1,381 @@ + + * @since 2.0 + */ +class ArrayHelper extends \yii\helpers\ArrayHelper +{ + /** + * ------------------------------------------ + * 把返回的数据集转换成Tree + * @param array $list 要转换的数据集 + * @param string $pk 主键 + * @param string $pid parent标记字段 + * @param string $child + * @param int $root + * @return array + * ------------------------------------------ + */ + public static function list_to_tree($list, $pk='id', $pid = 'pid', $child = '_child', $root = 0) { + + // 创建Tree + $tree = []; + if(is_array($list)) { + // 创建基于主键的数组引用 + $refer = array(); + foreach ($list as $key => $data) { + $refer[$data[$pk]] =& $list[$key]; + } + foreach ($list as $key => $data) { + // 判断是否存在parent + $parentId = $data[$pid]; + if ($root == $parentId) { + $tree[] =& $list[$key]; + }else{ + if (isset($refer[$parentId])) { + $parent =& $refer[$parentId]; + $parent[$child][] =& $list[$key]; + } + } + } + } + return $tree; + } + + /** + * --------------------------------------------------- + * 将list_to_tree的树还原成列表 + * @param array $tree 原来的树 + * @param string $child 孩子节点的键 + * @param string $order 排序显示的键,一般是主键 升序排列 + * @param array $list 过渡用的中间数组, + * @return array 返回排过序的列表数组 + * --------------------------------------------------- + */ + public static function tree_to_list($tree, $child = '_child', $order='id', &$list = []){ + if(is_array($tree)) { + $refer = []; + foreach ($tree as $key => $value) { + $reffer = $value; + if(isset($reffer[$child])){ + unset($reffer[$child]); + static::tree_to_list($value[$child], $child, $order, $list); + } + $list[] = $reffer; + } + $list = static::list_sort_by($list, $order, $sortby='asc'); + } + return $list; + } + + /** + * -------------------------------------------------- + * 对查询结果集进行排序 + * @access public + * @param array $list 查询结果 + * @param string $field 排序的字段名 + * @param string $sortby 排序类型 asc正向排序 desc逆向排序 nat自然排序 + * @return array|boolean + * -------------------------------------------------- + */ + public static function list_sort_by($list, $field, $sortby = 'asc') { + if(is_array($list)){ + $refer = $resultSet = array(); + foreach ($list as $i => $data) + $refer[$i] = &$data[$field]; + switch ($sortby) { + case 'asc': // 正向排序 + asort($refer); + break; + case 'desc':// 逆向排序 + arsort($refer); + break; + case 'nat': // 自然排序 + natcasesort($refer); + break; + } + foreach ( $refer as $key=> $val) + $resultSet[] = &$list[$key]; + return $resultSet; + } + return false; + } + + /** + * --------------------------------------- + * 递归方式将tree结构转化为 表单中select可使用的格式 + * @param array $tree 树型结构的数组 + * @param string $title 将格式化的字段 + * @param int $level 当前循环的层次,从0开始 + * @return array + * --------------------------------------- + */ + public static function format_tree($tree, $title = 'title', $level = 0){ + static $list; + /* 按层级格式的字符串 */ + $tmp_str=str_repeat("  ",$level)."└"; + $level == 0 && $tmp_str = ''; + + foreach ($tree as $key => $value) { + $value[$title] = $tmp_str.$value[$title]; + $arr = $value; + if (isset($arr['_child'])) unset($arr['_child']); + $list[] = $arr; + if (array_key_exists('_child', $value)) { + static::format_tree($value['_child'], $title, $level+1); + } + } + return $list; + } + + /** + * --------------------------------------- + * 获取dropDownList的data数据,主要是二级栏目及以上数据,一级栏目可以用ArrayHelper::map()生成 + * 示例:ArrayHelper::listDataLevel(\backend\models\Menu::find()->asArray()->all(), 'id', 'title', 'id', 'pid') + * @param $list array 由findAll或->all()生成的数据 + * @param $key string dropDownList的data数据的key + * @param $value string dropDownList的data数据的value + * @param string $pk 主键字段名 + * @param string $pid 父id字段名 + * @param int $root 根ID + * @return array + * --------------------------------------- + */ + public static function listDataLevel($list, $key, $value, $pk = 'id', $pid = 'pid', $root = 0){ + if (!is_array($list)) { + return []; + } + $_tmp = $list; + /* 判断$list是否由findAll生成的数据 */ + if (array_shift($_tmp) instanceof \yii\base\Model) { + $list = array_map(function($record) {return $record->attributes;},$list); + } + unset($_tmp); + $tree = static::list_to_tree($list,$pk,$pid,'_child',$root); + return static::map( static::format_tree($tree, $value), $key, $value); + } + + /** + * --------------------------------------- + * 生成jQuery tree所需的数据 + * @param $list array 由self::list_to_tree生成的数据 + * @return array + * --------------------------------------- + */ + public static function jstree($list){ + $node = []; + if ($list) { + foreach ($list as $value) { + $_tmp = []; + $_tmp['id'] = $value['id']; + $_tmp['text'] = $value['title']; + if (isset($value['_child'])) { + $_tmp['icon'] = 'fa fa-folder icon-state-warning'; + $_tmp['state']['opened'] = true; + $_tmp['children'] = self::jstree($value['_child']); + } else { + $_tmp['icon'] = 'fa fa-file icon-state-warning'; + } + $node[] = $_tmp; + } + } + return $node; + } + + /** + * 递归数组 + * + * @param array $items + * @param string $idField + * @param int $pid + * @param string $pidField + * @return array + */ + public static function itemsMerge(array $items, $pid = 0, $idField = "id", $pidField = 'pid', $child = '-') + { + $map = []; + $tree = []; + foreach ($items as &$it) { + //$it[$child] = []; + $map[$it[$idField ]] = &$it; + } + + foreach ($items as &$it) { + $parent = &$map[$it[$pidField]]; + if ($parent) { + $parent[$child][] = &$it; + } else { + $pid == $it[$pidField] && $tree[] = &$it; + } + } + + unset($items, $map); + + return $tree; + } + + public static function shouzimu($name) + { + $ret = ""; + $s1 = iconv("UTF-8", "gb2312", $name); + $s2 = iconv("gb2312", "UTF-8", $s1); + if ($s2 == $name) { + $post['name'] = $s1; + } + for ($i = 0; $i < strlen($name); $i++) { + $s1 = substr($post['name'], $i, 1); + $p = ord($s1); + if ($p > 160) { + $s2 = substr($post['name'], $i++, 2); + $ret .= ArrayHelper::ff_letter_first($s2); + } else { + $ret .= $s1; + } + } + return $ret; + } + //生成字母前缀 + public static function ff_letter_first($s0){ +// if (empty($s0)) { +// return ''; +// } +// //取出参数字符串中的首个字符 +// $temp_str = substr($s0, 0, 1); +// if (ord($temp_str) > 127) { +// $str = substr($s0, 0, 3); +// } else { +// $str = $temp_str; +// $fchar = ord($str[0]); +// if ($fchar >= ord('A') && $fchar <= ord('z')) { +// return strtoupper($temp_str); +// } else { +// return null; +// } +// } +// $s1 = iconv('UTF-8', 'gbk', $str); +// if (empty($s1)) { +// return null; +// } +// $s2 = iconv('gbk', 'UTF-8', $s1); +// if (empty($s2)) { +// return null; +// } +// $s = $s2 == $str ? $s1 : $str; +// $asc = ord($s[0]) * 256 + ord($s[1]) - 65536; + $firstchar_ord=ord(strtoupper($s0[0])); + if (($firstchar_ord>=65 and $firstchar_ord<=91)or($firstchar_ord>=48 and $firstchar_ord<=57)){ + $s0=iconv("UTF-8","gb2312//IGNORE", $s0); + } + $asc=ord($s0[0])*256+ord($s0[1])-65536; + if($asc>=-20319 and $asc<=-20284)return "A"; + if($asc>=-20283 and $asc<=-19776)return "B"; + if($asc>=-19775 and $asc<=-19219)return "C"; + if($asc>=-19218 and $asc<=-18711)return "D"; + if($asc>=-18710 and $asc<=-18527)return "E"; + if($asc>=-18526 and $asc<=-18240)return "F"; + if($asc>=-18239 and $asc<=-17923)return "G"; + if($asc>=-17922 and $asc<=-17418)return "H"; + if($asc>=-17417 and $asc<=-16475)return "J"; + if($asc>=-16474 and $asc<=-16213)return "K"; + if($asc>=-16212 and $asc<=-15641)return "L"; + if($asc>=-15640 and $asc<=-15166)return "M"; + if($asc>=-15165 and $asc<=-14923)return "N"; + if($asc>=-14922 and $asc<=-14915)return "O"; + if($asc>=-14914 and $asc<=-14631)return "P"; + if($asc>=-14630 and $asc<=-14150)return "Q"; + if($asc>=-14149 and $asc<=-14091)return "R"; + if($asc>=-14090 and $asc<=-13319)return "S"; + if($asc>=-13318 and $asc<=-12839)return "T"; + if($asc>=-12838 and $asc<=-12557)return "W"; + if($asc>=-12556 and $asc<=-11848)return "X"; + if($asc>=-11847 and $asc<=-11056)return "Y"; + if($asc>=-11055 and $asc<=-10247)return "Z"; + return self::rare_words($asc); + } + /** + * 百家姓中的生僻字 + */ + public static function rare_words($asc = '') + { + $rare_arr = array( + -3652 => array('word' => "窦", 'first_char' => 'D'), + -8503 => array('word' => "奚", 'first_char' => 'X'), + -9286 => array('word' => "酆", 'first_char' => 'F'), + -7761 => array('word' => "岑", 'first_char' => 'C'), + -5128 => array('word' => "滕", 'first_char' => 'T'), + -9479 => array('word' => "邬", 'first_char' => 'W'), + -5456 => array('word' => "臧", 'first_char' => 'Z'), + -7223 => array('word' => "闵", 'first_char' => 'M'), + -2877 => array('word' => "裘", 'first_char' => 'Q'), + -6191 => array('word' => "缪", 'first_char' => 'M'), + -5414 => array('word' => "贲", 'first_char' => 'B'), + -4102 => array('word' => "嵇", 'first_char' => 'J'), + -8969 => array('word' => "荀", 'first_char' => 'X'), + -4938 => array('word' => "於", 'first_char' => 'Y'), + -9017 => array('word' => "芮", 'first_char' => 'R'), + -2848 => array('word' => "羿", 'first_char' => 'Y'), + -9477 => array('word' => "邴", 'first_char' => 'B'), + -9485 => array('word' => "隗", 'first_char' => 'K'), + -6731 => array('word' => "宓", 'first_char' => 'M'), + -9299 => array('word' => "郗", 'first_char' => 'X'), + -5905 => array('word' => "栾", 'first_char' => 'L'), + -4393 => array('word' => "钭", 'first_char' => 'T'), + -9300 => array('word' => "郜", 'first_char' => 'G'), + -8706 => array('word' => "蔺", 'first_char' => 'L'), + -3613 => array('word' => "胥", 'first_char' => 'X'), + -8777 => array('word' => "莘", 'first_char' => 'S'), + -6708 => array('word' => "逄", 'first_char' => 'P'), + -9302 => array('word' => "郦", 'first_char' => 'L'), + -5965 => array('word' => "璩", 'first_char' => 'Q'), + -6745 => array('word' => "濮", 'first_char' => 'P'), + -4888 => array('word' => "扈", 'first_char' => 'H'), + -9309 => array('word' => "郏", 'first_char' => 'J'), + -5428 => array('word' => "晏", 'first_char' => 'Y'), + -2849 => array('word' => "暨", 'first_char' => 'J'), + -7206 => array('word' => "阙", 'first_char' => 'Q'), + -4945 => array('word' => "殳", 'first_char' => 'S'), + -9753 => array('word' => "夔", 'first_char' => 'K'), + -10041 => array('word' => "厍", 'first_char' => 'S'), + -5429 => array('word' => "晁", 'first_char' => 'C'), + -2396 => array('word' => "訾", 'first_char' => 'Z'), + -7205 => array('word' => "阚", 'first_char' => 'K'), + -10049 => array('word' => "乜", 'first_char' => 'N'), + -10015 => array('word' => "蒯", 'first_char' => 'K'), + -3133 => array('word' => "竺", 'first_char' => 'Z'), + -6698 => array('word' => "逯", 'first_char' => 'L'), + -9799 => array('word' => "俟", 'first_char' => 'Q'), + -6749 => array('word' => "澹", 'first_char' => 'T'), + -7220 => array('word' => "闾", 'first_char' => 'L'), + -10047 => array('word' => "亓", 'first_char' => 'Q'), + -10005 => array('word' => "仉", 'first_char' => 'Z'), + -3417 => array('word' => "颛", 'first_char' => 'Z'), + -6431 => array('word' => "驷", 'first_char' => 'S'), + -7226 => array('word' => "闫", 'first_char' => 'Y'), + -9293 => array('word' => "鄢", 'first_char' => 'Y'), + -6205 => array('word' => "缑", 'first_char' => 'G'), + -9764 => array('word' => "佘", 'first_char' => 'S'), + -9818 => array('word' => "佴", 'first_char' => 'N'), + -9509 => array('word' => "谯", 'first_char' => 'Q'), + -3122 => array('word' => "笪", 'first_char' => 'D'), + -9823 => array('word' => "佟", 'first_char' => 'T'), + ); + if (array_key_exists($asc, $rare_arr) && $rare_arr[$asc]['first_char']) { + return $rare_arr[$asc]['first_char']; + } else { + return null; + } + } + + +} diff --git a/common/helpers/FakeId.php b/common/helpers/FakeId.php new file mode 100644 index 0000000..c8284e1 --- /dev/null +++ b/common/helpers/FakeId.php @@ -0,0 +1,40 @@ +612155,'GY'=>215851,'YD'=>721143,'XS'=>116555,'YH'=>135435,'ZY'=> 123456]; + + public static function encodeId($type,$id){ + if(!isset(self::$offset[$type])){ + throw new ApiException("{$type}类型不存在"); + } + return $type.($id+self::$offset[$type]); + } + + public static function decodeId($id){ + if(!$id){ + return 0; + } + preg_match('/([A-Z]{2})(\d+)/s',$id,$macths); + if(!isset($macths[1]) || !isset(self::$offset[$macths[1]])){ + throw new ApiException("{$macths[1]}类型不存在"); + } + ; + return (int)$macths[2]-self::$offset[$macths[1]]; + } + +} diff --git a/common/helpers/FuncHelper.php b/common/helpers/FuncHelper.php new file mode 100644 index 0000000..60ba7ac --- /dev/null +++ b/common/helpers/FuncHelper.php @@ -0,0 +1,376 @@ + $code, + 'msg' => $msg, + 'obj' => $obj, + ); + header('Content-Type:application/json; charset=utf-8'); + exit(json_encode($json)); + } + + /** + * --------------------------------------- + * 分析枚举类型字段值 格式 a:名称1,b:名称2 + * @param $string string 字符串 + * @return mixed + * --------------------------------------- + */ + public static function parse_field_attr($string) + { + if (0 === strpos($string, ':')) { + // 采用函数定义 + return eval(substr($string, 1) . ';'); + } + $array = preg_split('/[,;\r\n]+/', trim($string, ",;\r\n")); + if (strpos($string, ':')) { + $value = array(); + foreach ($array as $val) { + [$k, $v] = explode(':', $val); + $value[$k] = $v; + } + } else { + $value = $array; + } + return $value; + } + + /** + * Create the directory by pathname + * @param string $pathname The directory path. + * @param int $mode + * @return bool + */ + public static function make_dir($pathname, $mode = 0777) + { + if (is_dir($pathname)) { + return true; + } + if (is_dir(dirname($pathname))) { + return mkdir($pathname, $mode); + } + self::make_dir(dirname($pathname)); + return mkdir($pathname, $mode); + } + + /** + * @param string $words + * @param string $separator + * @return string + * 下划线转驼峰或者字符串第一个字母大写 + */ + function hump($words, $separator = '_') + { + if (strpos($words, $separator) !== false) { + $newWords = str_replace($separator, " ", strtolower($words)); + return ltrim(str_replace(" ", "", ucwords($newWords)), $separator); + } else { + return ucfirst($words); + } + } + + /** + * 生成 前缀+24位数字的订单号 + * @param string $prefix 前缀 + * @return string + */ + public static function generate_order_no($prefix = '', $length = 6) + { + $randLen = $length; + $id = base_convert(substr(uniqid(), 0 - $randLen), 16, $length); + if (strlen($id) > $length) { + $id = substr($id, -$length); + } elseif (strlen($id) < $length) { + $rLen = $length - strlen($id); + $id = $id . rand(pow($length, $rLen - 1), pow($length, $rLen) - 1); + } + $dateTimeStr = date('YmdHis'); + return $prefix . $dateTimeStr . $id; + } + + /** + * 根据身份证获取年龄 + * @param string $idno + * @return false|int|string + */ + public static function getAgeFromIdNo($idno = '') + { + $btime = strtotime(substr($idno, 6, 8));//idno是身份证号 截取日期并转为时间戳 + $byear = date('Y', $btime); + $bmonth = date('m', $btime); + $bday = date('d', $btime); + $curYear = date('Y'); + $curMoth = date('m'); + $curDay = date('d'); + $age = $curYear - $byear; + if ($curMoth < $bmonth || ($curMoth == $bmonth && $curDay < $bday)) { + $age--; + } + return $age; + } + + //获取工作年限 + public static function getYears($btime) + { + $byear = date('Y', $btime); + $bmonth = date('m', $btime); + $bday = date('d', $btime); + $curYear = date('Y'); + $curMoth = date('m'); + $curDay = date('d'); + $age = $curYear - $byear; + if ($curMoth < $bmonth || ($curMoth == $bmonth && $curDay < $bday)) { + $age--; + } + return $age; + } + + //获取前 + public static function time_tran($the_time) + { + $now_time = time(); + $show_time = $the_time; + $dur = $now_time - $show_time; + if ($dur < 0) { + return $the_time; + } else { + if ($dur < 60) { + return $dur . '秒前'; + } else { + if ($dur < 3600) { + return floor($dur / 60) . '分钟前'; + } else { + if ($dur < 86400) { + return floor($dur / 3600) . '小时前'; + } else { + if ($dur < 259200) {//3天内 + return floor($dur / 86400) . '天前'; + } else { + return $the_time; + } + } + } + } + } + } + + //获取还剩多少天多少小时多少分多少秒 + //$diff两个数之差 + public static function time_left($diff) + { + $str = ''; + $date = floor($diff / 86400); + if ($date) { + $str .= $date . '天'; + } + + $hour = floor($diff % 86400 / 3600); + if ($hour) { + $str .= $hour . '小时'; + } + $minute = floor($diff % 86400 % 3600 / 60); + if ($minute) { + $str .= $minute . '分'; + } + $second = floor($diff % 86400 % 3600 % 60); + if ($second) { + $str .= $second . '秒'; + } + return $str; + } + + /** + * 获取文件真实路径 + * + * @param string $type 模块 + * @param string $path 路径 + * @return string + */ + public static function getRealFilepath(string $type, string $path): string + { + return __DIR__ . '/../../web/' . $type . '/' . trim($path, '/'); + } + + + /** + * 生成随机字符串 + */ + public static function uuid() + { + if (function_exists('com_create_guid')) { + return com_create_guid(); + } else { + $charid = md5(uniqid(rand(), true)); + $hyphen = chr(45);// "-" + $uuid = substr($charid, 0, 8) . $hyphen + . substr($charid, 8, 4) . $hyphen + . substr($charid, 12, 4) . $hyphen + . substr($charid, 16, 4) . $hyphen + . substr($charid, 20, 12); + + return $uuid; + } + } + + //生成推广码 + public static function create_invite_code() + { + $num = rand(1111, 9999); + $str = range('A', 'Z'); + unset($str[array_search('O', $str)]); + shuffle($str); + $inviteCode = ''; + $arr_len = count($str); + for ($i = 0; $i < 4; $i++) { + $rand = mt_rand(0, $arr_len - 1); + $inviteCode .= $str[$rand]; + } + $inviteCode=str_shuffle($num.$inviteCode); + return $inviteCode; + } + + /** + * 获取当天时间戳 + */ + public static function getDayTime(){ + $year = date("Y"); + $month = date("m"); + $day = date("d"); + $start_time = mktime(0,0,0,$month,$day,$year);//当天开始时间戳 + $end_time= mktime(23,59,59,$month,$day,$year);//当天结束时间戳 + + return [ + 'start_time'=>$start_time, + 'end_time'=>$end_time, + ]; + } + + + //返回今天的开始时间和结束时间 + public static function day_now() + { + $arr = [ + mktime(0, 0, 0, date('m'), date('d'), date('Y')), + mktime(23, 59, 59, date('m'), date('d'), date('Y')), + ]; + return $arr; + } + + //返回昨天开始结束时间 改造上边的方法 + public static function day_yesterday() + { + $yesterday = date('d') - 1; + $arr = [ + mktime(0, 0, 0, date('m'), $yesterday, date('Y')), + mktime(23, 59, 59, date('m'), $yesterday, date('Y')), + ]; + return $arr; + } + + //获取当前时间的本周开始结束时间 + public static function week_now() + { + $arr = [ + strtotime(date('Y-m-d', strtotime("-1 week Monday", time()))), + strtotime(date('Y-m-d', strtotime("+0 week Sunday", time()))) - 1 + ]; + + return $arr; + } + +//返回上周开始和结束的时间戳 + public static function last_week() + { + // 1520179200 1520783999 + $arr = [ + // date('Y-m-d',strtotime('last week Monday',time())), + // date('Y-m-d',strtotime('last week Sunday',time())) + strtotime('last week Monday', time()), + strtotime('last week Sunday +1 days -1 seconds', time()) + ]; + return $arr; + } + +// 返回本月开始和结束的时间戳 + public static function now_month() + { + $arr = [ + mktime(0, 0, 0, date('m'), 1, date('Y')), + mktime(23, 59, 59, date('m'), date('t'), date('Y')) + ]; + return $arr; + } + +// 返回某一年某一月的开始和结束的时间戳 + public static function month_year($year, $month) + { + return [ + $begin = mktime(0, 0, 0, $month, 1, $year), + $end = mktime(23, 59, 59, $month, date('t', $begin), $year) + ]; + } + + +// 返回当前季度的开始时间和结束时间 + public static function now_quarter($month = 0) + { + $month = $month != 0 ? $month : date('n'); + $season = ceil($month / 3); + return [ + mktime(0, 0, 0, ($season - 1) * 3 + 1, 1, date('Y')), + mktime(0, 0, 0, $season * 3, date('t'), date('Y')) - 1 + ]; + } + +// 返回上个月开始和结束的时间戳 + public static function lastMonth() + { + $begin = mktime(0, 0, 0, date('m') - 1, 1, date('Y')); + $end = mktime(23, 59, 59, date('m') - 1, date('t', $begin), date('Y')); + + return [$begin, $end]; + } + +// 返回某天的结束时间戳 + public static function getDayBE($day) { + + return array(strtotime($day), strtotime($day)+24*3600-1); + + } + + public static function is_not_null($str){ + //json_encode返回的是字符串, 而json_decode返回的是对象. + return is_null(json_decode($str)); + } + + //是否药性相畏 + public static function is_drug_wei(){ + + } + + //是否药性相反 + public static function is_drug_opposite(){ + + } +} diff --git a/common/helpers/LogHelper.php b/common/helpers/LogHelper.php new file mode 100644 index 0000000..4bcb2aa --- /dev/null +++ b/common/helpers/LogHelper.php @@ -0,0 +1,68 @@ +log($level, $message); + } + + /** + * @param string $path + * @param string $filename + * @return \Yiisoft\Log\Logger + */ + protected static function logger(string $path = '', string $filename = ''): \Yiisoft\Log\Logger + { + if (!$path) { + $path = 'sample'; + } + if (!$filename) { + $filename = 'log'; + } + $filepath = \Yii::$app->basePath . '/runtime/logs/' . $path . '/' . $filename . '-' . date('Y-m-d') . '.log'; + $fileTarget = new \Yiisoft\Log\Target\File\FileTarget($filepath); + $fileTarget->setFormat(static function (\Yiisoft\Log\Message $message) { + return '[' . date('Y-m-d H:i:s') . "] [{$message->level()}] {$message->message()}"; + }); + return new \Yiisoft\Log\Logger([$fileTarget]); + } +} diff --git a/common/helpers/QrcodeHelper.php b/common/helpers/QrcodeHelper.php new file mode 100644 index 0000000..1545f7a --- /dev/null +++ b/common/helpers/QrcodeHelper.php @@ -0,0 +1,48 @@ +writer(new PngWriter()) + ->writerOptions([]) + ->data($url) + ->encoding(new Encoding('UTF-8')) + ->errorCorrectionLevel(new ErrorCorrectionLevelHigh()) + ->size(300) + ->margin(30) + ->roundBlockSizeMode(new RoundBlockSizeModeMargin()) + ->build(); + return $result->getDataUri(); + } + + public static function imageUrl($url) + { + @ini_set('memory_limit', '512M'); + $result = Builder::create() + ->writer(new PngWriter()) + ->writerOptions([]) + ->data($url) + ->encoding(new Encoding('UTF-8')) + ->errorCorrectionLevel(new ErrorCorrectionLevelHigh()) + ->size(300) + ->margin(10) + ->roundBlockSizeMode(new RoundBlockSizeModeMargin()) + ->build(); + return $result; +// ob_start(); +// imagepng($result->getImage()); +// $rawImage = ob_get_contents(); +// ob_end_clean(); +// return $rawImage; +// return \Yii::$app->upload->AliOssPutObject(\Yii::$app->upload->getFileName('image').'.png',$rawImage); + } +} \ No newline at end of file diff --git a/common/helpers/README.md b/common/helpers/README.md new file mode 100644 index 0000000..f7017d6 --- /dev/null +++ b/common/helpers/README.md @@ -0,0 +1,4 @@ + +# 开发注意事项 + +- 全站公共的助手类 \ No newline at end of file diff --git a/common/helpers/StringHelper.php b/common/helpers/StringHelper.php new file mode 100644 index 0000000..931bb92 --- /dev/null +++ b/common/helpers/StringHelper.php @@ -0,0 +1,100 @@ += 3) { + $firstStr = mb_substr($string, 0, 1, 'utf-8'); + $lastStr = mb_substr($string, -1, 1, 'utf-8'); + return $firstStr . str_repeat('*', $length - 2) . $lastStr; + } elseif ($length == 2) { + $firstStr = mb_substr($string, 0, 1, 'utf-8'); + return $firstStr . '*'; + } elseif ($length == 1) { + return $string . '*'; + } else { + $firstStr = mb_substr($string, 0, 3, 'utf-8'); + $lastStr = mb_substr($string, -4, 2, 'utf-8'); + return $firstStr . str_repeat('*', mb_strlen($string, 'utf-8') - 5) . $lastStr . '**'; + } + } +} diff --git a/common/jobs/ArticleMassSendJob.php b/common/jobs/ArticleMassSendJob.php new file mode 100644 index 0000000..980ef37 --- /dev/null +++ b/common/jobs/ArticleMassSendJob.php @@ -0,0 +1,79 @@ +db->beginTransaction(); + try { + $this->setRequest(); + + $successCount = 0; + $user_ids = []; + foreach ($this->up_ids as $up_id) { + /* @var Order $order */ + $order = Order::find() + ->where([ + 'su_id' => $this->su_id, + 'up_id' => $up_id, + ]) + ->one(); + if (!$order) { + continue; // 无订单记录跳过 + } + if (in_array($order->user_id, $user_ids)) { + continue; // 已发送过跳过 + } + $user_ids[] = $order->user_id; + /* @var ImMessageSession $ims */ + $ims = ImMessageSession::find()->where([ + 'user_id' => $order->user_id, + 'service_id' => $this->su_id, + 'type' => ImSessionTypeEnum::USER_DOC, + ]) + ->orderBy(['updated_at' => SORT_ASC]) + ->one(); + if (!$ims) { + continue; // 无历史会话跳过 + } + $form = new ImMessageForm; + $form->ims_id = $ims->id; + $form->from_id = $this->su_id; + $form->to_id = $order->user_id; + $form->content = $this->content; + $form->type = ImMessageSendTypeEnum::SERVICE_SEND; + + try { + $form->sendMessage(true); + $successCount++; + } catch (\Exception $exception) { + \Yii::error($exception); + } + } + $t->commit(); + \Yii::info(Carbon::now()->toDateTimeString() . "{$this->su_id}成功群发{$successCount}个用户"); + } catch (\Exception $exception) { + $t->rollBack(); + \Yii::error($exception); + } + } +} diff --git a/common/jobs/BaseJob.php b/common/jobs/BaseJob.php new file mode 100644 index 0000000..148bb17 --- /dev/null +++ b/common/jobs/BaseJob.php @@ -0,0 +1,37 @@ +hostInfo) { + $this->hostInfo = \Yii::$app->request->hostInfo; + } + if (!$this->baseUrl) { + $this->baseUrl = \Yii::$app->request->baseUrl; + } + } else { + if (!$this->hostInfo) { + $this->hostInfo = \Yii::$app->getHostInfo(); + } + if (!$this->baseUrl) { + $this->baseUrl = \Yii::$app->getBaseUrl(); + } + } + $this->setRequest(); + } + + public function setRequest() + { + \Yii::$app->setHostInfo($this->hostInfo); + \Yii::$app->setBaseUrl($this->baseUrl); + } +} diff --git a/common/jobs/DivideAccountJob.php b/common/jobs/DivideAccountJob.php new file mode 100644 index 0000000..317b404 --- /dev/null +++ b/common/jobs/DivideAccountJob.php @@ -0,0 +1,21 @@ +sendToUid($this->ims_id,$this->to_id,$this->to_role,$this->content); + } + + public function getTtr() + { + return 60; + } + + public function canRetry($attempt, $error) + { + return ($attempt < 5) && ($error instanceof \Exception); + } +} diff --git a/common/jobs/NewSendJob.php b/common/jobs/NewSendJob.php new file mode 100644 index 0000000..48e3d3c --- /dev/null +++ b/common/jobs/NewSendJob.php @@ -0,0 +1,65 @@ +db->beginTransaction(); + try { + $this->setRequest(); + \Yii::info('su_id为:'.$this->su_id.'的医生群发消息队列 start:'.Json::encode($this->doctor_patient_ids)); + $doctorInfo = DoctorInfo::find()->select('su_id,name,depart_id,avatar')->where(['su_id' => $this->su_id])->with(['depart'])->asArray()->one(); + $store = Store::find()->select('name')->where(['id' => $this->store_id])->asArray()->one(); + $successCount = 0; + $array=array( + 'doctor'=> $doctorInfo['name'], + 'avatar'=> $doctorInfo['avatar'], + 'content'=> $this->content, + ); + $item=new SystemNotice(); + foreach ($this->doctor_patient_ids as $v) { + $doctorPatient = DoctorPatient::find()->where(['su_id'=>$this->su_id,'up_id' => $v])->asArray()->one(); + if (!$doctorPatient){ + continue; + } + + $item->store_id=$this->store_id; + $item->content =Json::encode($array); + $item->user_id=$doctorPatient['user_id']??0; + $item->scene_type=1;//发给用户端 + $item->base_type=SystemNoticeTypeEnum::DOCTOR_NOTICE; + $item->notice_at=date('Y-m-d H:i:s',time()); + $item->saveOrFail(); + + $successCount++; + } + $t->commit(); + \Yii::info('su_id为:'.$this->su_id.'的医生群发消息队列 end: '.Carbon::now()->toDateTimeString() . "{$this->su_id}成功群发{$successCount}个用户"); + } catch (\Exception $exception) { + $t->rollBack(); + + \Yii::error('su_id为:'.$this->su_id.'的医生群发消息队列 异常: '.$exception); + throw new Exception($exception->getMessage()); + } + } +} \ No newline at end of file diff --git a/common/jobs/OrderCancelJob.php b/common/jobs/OrderCancelJob.php new file mode 100644 index 0000000..5d979f3 --- /dev/null +++ b/common/jobs/OrderCancelJob.php @@ -0,0 +1,56 @@ +orderId,'订单自动取消队列start'); + + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $order = Order::findOne([ + 'id' => $this->orderId, + 'is_pay' => 0, +// 'pay_type' => 0, + ]); + if (!$order || $order->cancel_status == 1) { + throw new \Exception('未支付订单不存在或已取消'); + } + + $order->cancel_status = 1; + $order->cancel_time = time(); + $order->cancel_remark = '超时自动取消订单'; + if ($order->save()) { + + OrderLog::saveLog($this->orderId,'队列触发订单取消canceled事件'); + $event = new OrderEvent([ + 'order' => $order, + ]); + \Yii::$app->trigger(Order::EVENT_CANCELED, $event); + $t->commit(); + } else { + throw new \Exception((new BaseModel())->getErrorMsg($order)); + } + + OrderLog::saveLog($this->orderId,'订单自动取消队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + OrderLog::saveLog($this->orderId,'订单自动取消队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/OrderOverJob.php b/common/jobs/OrderOverJob.php new file mode 100644 index 0000000..3e32021 --- /dev/null +++ b/common/jobs/OrderOverJob.php @@ -0,0 +1,115 @@ +exec($this->orderId); + } + + //方便调试 + public function exec($orderId){ + $this->orderId = $orderId; + OrderLog::saveLog($this->orderId,'订单接诊自动结束队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $order = Order::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + 'accept_status' => OrderAcceptEnum::ACCEPTING + ])->with('session','serviceUser')->one(); + if(!$order){ + throw new Exception('接诊订单不存在'); + } + $ims_id = $order->session->ims_id; + $ImMessageSession = ImMessageSession::findOne($ims_id); + if(!$ImMessageSession){ + throw new Exception('接诊订单会话不存在'); + } + + //修改状态 + $order->accept_status = OrderAcceptEnum::OVER; + $order->over_time = time(); + $order->saveOrFail(); + + //-----------------------------------------------------发送消息--------------------------------------------- + //以用户身份给服务人员发送event的消息 + + $message = [ + 'type' => 'end', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => '会话已结束' + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + + //以服务人员身份给用户发送event的消息 + $message = [ + 'type' => 'end', + 'from_User' => [ + 'id' => $order->su_id, + 'name' => $order->serviceUser->docInfo->name, + 'avatar' => $order->serviceUser->docIdentity->work_avator + ], + 'data' => [ + 'text' => '会话已结束' + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->su_id; + $form->to_id = $order->user_id; + $form->type = ImMessageSendTypeEnum::SERVICE_SEND;//!! + $form->content = json_encode($message); + $form->sendMessage(); + //-----------------------------------------------------发送消息--------------------------------------------- + + //会话修改为已结束 - 先发消息,再修改为结束,不然会报会话已结束的错误 + $ImMessageSession->status = ImSessionStatusEnum::END; + $ImMessageSession->saveOrFail(); + + $t->commit(); + OrderLog::saveLog($this->orderId,'订单接诊自动结束队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + \Yii::error($exception); + OrderLog::saveLog($this->orderId,'订单接诊自动结束队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/OrderPayImJob.php b/common/jobs/OrderPayImJob.php new file mode 100644 index 0000000..3d6d0ad --- /dev/null +++ b/common/jobs/OrderPayImJob.php @@ -0,0 +1,198 @@ +exec($this->orderId); + } + + //方便调试 + public function exec($orderId){ + $this->orderId = $orderId; + OrderLog::saveLog($this->orderId,'发送问诊消息start'); + + $t = \Yii::$app->db->beginTransaction(); + try { + + $this->setRequest(); + /* @var Order $order */ + $order = Order::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0 + ])->with('inquiry','user')->one(); + if (!$order || !$order->inquiry) { + OrderLog::saveLog($this->orderId,'订单不存在或者问诊信息不存在'); + throw new \Exception('订单不存在或者问诊信息不存在'); + } + + //------------------------------------------发消息----------------------------------------------------------- + //创建会话 + $ims = new ImMessageSession(); + $ims->user_id = $order->user_id; + $ims->service_id = $order->su_id; + $ims->type = UserRoleEnum::DOCTOR; + $ims->saveOrFail(); + + $ims_id = $ims->id; + + //绑定订单和会话消息的关系 + $session_order = new ImMessageSessionOrder(); + $session_order->ims_id = $ims_id; + $session_order->order_id = $this->orderId; + $session_order->saveOrFail(); + + //发送病情 + $message = [ + 'type' => 'desc', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => $order->inquiry->desc + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + + //发送基本健康信息 + $message = [ + 'type' => 'text_a', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => $order->id + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + + //发送图片信息 + $message = [ + 'type' => 'images', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => $order->inquiry->images + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + + //就诊记录 + if($order->inquiry->is_visit && $order->inquiry->visit_desc){ + $message = [ + 'type' => 'record', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => $order->inquiry->visit_desc + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + } + + //以医生身份给用户发送一条提示信息 + $message = [ + 'type' => 'system', + 'from_User' => [ + 'id' => $order->su_id, + 'name' => $order->serviceUser->docInfo->name, + 'avatar' => $order->serviceUser->docIdentity->work_avator + ], + 'data' => [ + 'text' => '温馨提示:您可继续补充问诊内容,便于更快确认病情,医生均在临床一线工作,还请耐心等待,医生接诊时会第一时间短信通知您' + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->su_id; + $form->to_id = $order->user_id; + $form->type = ImMessageSendTypeEnum::SERVICE_SEND;//!! + $form->content = json_encode($message); + $form->sendMessage(); + + //以用户身份给医生发送一条事件消息 + $message = [ + 'type' => 'end', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => '请在24小时内接诊,超时将会自动退诊' + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + //----------------------------------------发消息------------------------------------------------------------- + + $t->commit(); + OrderLog::saveLog($this->orderId,'发送问诊消息end'); + } catch (\Exception $exception) { + $t->rollBack(); + \Yii::error($exception); + OrderLog::saveLog($this->orderId,'发送问诊消息异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/OrderRefundJob.php b/common/jobs/OrderRefundJob.php new file mode 100644 index 0000000..c579bed --- /dev/null +++ b/common/jobs/OrderRefundJob.php @@ -0,0 +1,83 @@ +orderId,'订单自动退款队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $order = Order::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + 'accept_status' => OrderAcceptEnum::WAIT_ACCEPT + ])->with('session')->one(); + if(!$order){ + throw new Exception('未接诊订单不存在'); + } + $ims_id = $order->session->ims_id; + $ImMessageSession = ImMessageSession::findOne($ims_id); + if(!$ImMessageSession){ + throw new Exception('未接诊订单会话不存在'); + } + + //生成记录 + $orderRefund = new OrderRefund(); + $orderRefund->user_id = $order->user_id; + $orderRefund->order_id = $order->id; + $orderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $orderRefund->refund_price = $order->total_pay_price; + $orderRefund->remark = '超时未接诊自动退款'; + $orderRefund->saveOrFail(); + + //取消状态 + $order->cancel_status = 1; + $order->cancel_time = time(); + $order->cancel_remark = '超时未接诊自动取消'; + //接诊状态 + $order->accept_status = OrderAcceptEnum::TIMEOUT_ACCEPT; + //退款状态 + $order->refund_status = 1; + $order->refund_time = time(); + $order->saveOrFail(); + + //会话修改为已结束 + $ImMessageSession->status = ImSessionStatusEnum::END; + $ImMessageSession->saveOrFail(); + + //退款操作 + $refundForm = new \common\forms\OrderRefundForm(); + $refundForm->refundMoney($orderRefund); + + $t->commit(); + OrderLog::saveLog($this->orderId,'订单自动退款队列end'); + + } catch (\Exception $exception) { + $t->rollBack(); + OrderLog::saveLog($this->orderId,'订单自动退款队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/PrescripCancelJob.php b/common/jobs/PrescripCancelJob.php new file mode 100644 index 0000000..3131b94 --- /dev/null +++ b/common/jobs/PrescripCancelJob.php @@ -0,0 +1,58 @@ +orderId,'订单自动取消队列start'); + + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $Prescription = Prescription::findOne([ + 'id' => $this->orderId, + 'is_pay' => 0, +// 'pay_type' => 0, + ]); + if (!$Prescription || $Prescription->cancel_status == 1) { + throw new \Exception('未支付订单不存在或已取消'); + } + + $Prescription->cancel_status = 1; + $Prescription->cancel_time = time(); + $Prescription->cancel_remark = '超时自动取消订单'; + if ($Prescription->save()) { + + PrescripOrderLog::saveLog($this->orderId,'队列触发订单取消canceled事件'); + $event = new OrderEvent([ + 'order' => $Prescription, + ]); + \Yii::$app->trigger(Prescription::EVENT_CANCELED, $event); + $t->commit(); + } else { + throw new \Exception((new BaseModel())->getErrorMsg($Prescription)); + } + + PrescripOrderLog::saveLog($this->orderId,'订单自动取消队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + PrescripOrderLog::saveLog($this->orderId,'订单自动取消队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/PrescripRefundJob.php b/common/jobs/PrescripRefundJob.php new file mode 100644 index 0000000..1de5d88 --- /dev/null +++ b/common/jobs/PrescripRefundJob.php @@ -0,0 +1,70 @@ +orderId,'订单自动退款队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $Prescription = Prescription::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + ])->one(); + if(!$Prescription){ + throw new Exception('处方订单不存在'); + } + + //生成记录 + $PrescripOrderRefund = new PrescripOrderRefund(); + $PrescripOrderRefund->user_id = $Prescription->user_id; + $PrescripOrderRefund->order_id = $Prescription->id; + $PrescripOrderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $PrescripOrderRefund->refund_price = $Prescription->total_pay_price; + $PrescripOrderRefund->remark = '超时未接诊自动退款'; + $PrescripOrderRefund->saveOrFail(); + + //取消状态 + $Prescription->cancel_status = 1; + $Prescription->cancel_time = time(); + $Prescription->cancel_remark = '超时未接诊自动取消'; + + //退款状态 + $Prescription->refund_status = 1; + $Prescription->refund_time = time(); + $Prescription->saveOrFail(); + + + //退款操作 + $PrescripRefundForm = new PrescripRefundForm(); + $PrescripRefundForm->refundMoney($PrescripOrderRefund); + + $t->commit(); + PrescripOrderLog::saveLog($this->orderId,'订单自动退款队列end'); + + } catch (\Exception $exception) { + $t->rollBack(); + PrescripOrderLog::saveLog($this->orderId,'订单自动退款队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/PrescriptionAutoExpireJob.php b/common/jobs/PrescriptionAutoExpireJob.php new file mode 100644 index 0000000..08dcf72 --- /dev/null +++ b/common/jobs/PrescriptionAutoExpireJob.php @@ -0,0 +1,73 @@ +db->beginTransaction(); + try { + PrescriptionLog::saveLog($this->orderId,'处方自动失效队列start'.$this->orderId); + + $this->setRequest(); + $Prescription = Prescription::findOne([ + 'id' => $this->orderId, + 'status' => PrescriptionEnum::WAIT_CHECK + ]); + + if (!$Prescription) { + throw new \Exception('处方不存在或已是最终态'); + } + + $Prescription->status = PrescriptionEnum::UNPASSED; + $Prescription->saveOrFail(); + + // 判断订单是否已付款且代发货,是进行退款操作 + $productOrder = ProductOrder::findOne([ + 'p_id' => $this->orderId, + 'cancel_status' => 0, + 'refund_status' => 0, + ]); + + if($productOrder->status == 1 && $productOrder->is_pay == 1){ + // 自动退款 + $ProductRefundForm = new ProductRefundForm(); + $ProductRefundForm->refund([ + 'order_id' => $productOrder->id, + 'user_id' => $productOrder->user_id + ]); + } else { + // 订单自动失效 + $ProductCancelForm = new ProductCancelForm(); + $ProductCancelForm->cancel([ + 'order_id' => $productOrder->id, + 'user_id' => $productOrder->user_id + ], '处方失效,订单自动失效'); + } + + $t->commit(); + PrescriptionLog::saveLog($this->orderId,'处方自动失效队列end'.$this->orderId); + } catch (\Exception $exception) { + $t->rollBack(); + PrescriptionLog::saveLog($this->orderId,'处方自动失效队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/ProductOrderAutoReceivedJob.php b/common/jobs/ProductOrderAutoReceivedJob.php new file mode 100644 index 0000000..b0ca1dc --- /dev/null +++ b/common/jobs/ProductOrderAutoReceivedJob.php @@ -0,0 +1,48 @@ +orderId,'产品订单自动收货队列start'); + $this->setRequest(); + //判断是否已发货状态且到达自动收货时间 + $ProductOrder = ProductOrder::findOne([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'is_send' => 1, // 已发货 + 'status' => 2 //待收货 + ]); + if (!$ProductOrder) { + throw new \Exception('订单不存在'); + } + + $ProductOrder->status = ProductOrderEnum::CONFIRM; + $ProductOrder->received_time = time(); + $ProductOrder->save(); + + + ProductOrderLog::saveLog($this->orderId,'产品订单自动收货队列end'); + } catch (\Exception $exception) { + ProductOrderLog::saveLog($this->orderId,'产品订单自动收货队列异常:'.$exception->getMessage().'------'.$exception->getLine()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/ProductOrderCancelJob.php b/common/jobs/ProductOrderCancelJob.php new file mode 100644 index 0000000..b5c11ac --- /dev/null +++ b/common/jobs/ProductOrderCancelJob.php @@ -0,0 +1,58 @@ +orderId,'订单自动取消队列start'); + + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $ProductOrder = ProductOrder::findOne([ + 'id' => $this->orderId, + 'is_pay' => 0, +// 'pay_type' => 0, + ]); + if (!$ProductOrder || $ProductOrder->cancel_status == 1) { + throw new \Exception('未支付订单不存在或已取消'); + } + $ProductOrder->status = ProductOrderEnum::CANCEL; + $ProductOrder->cancel_status = 1; + $ProductOrder->cancel_time = time(); + $ProductOrder->cancel_remark = '超时自动取消订单'; + if ($ProductOrder->save()) { + ProductOrderLog::saveLog($this->orderId,'队列触发订单取消canceled事件'); + $event = new OrderEvent([ + 'order' => $ProductOrder, + ]); + \Yii::$app->trigger(ProductOrder::EVENT_CANCELED, $event); + $t->commit(); + } else { + throw new \Exception((new BaseModel())->getErrorMsg($ProductOrder)); + } + + ProductOrderLog::saveLog($this->orderId,'订单自动取消队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + ProductOrderLog::saveLog($this->orderId,'订单自动取消队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/ProductOrderPaidJob.php b/common/jobs/ProductOrderPaidJob.php new file mode 100644 index 0000000..b6021b3 --- /dev/null +++ b/common/jobs/ProductOrderPaidJob.php @@ -0,0 +1,51 @@ +orderId,'产品订单支付分账队列start'); + $this->setRequest(); + $ProductOrder = ProductOrder::findOne([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + 'refund_status' => 0, + ]); + if (!$ProductOrder || $ProductOrder->type != 2) { + throw new \Exception('订单不存在'); + } + + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $this->orderId; + $ledgerForm->create(); + + //订单支付分账后立即结算 + // \Yii::$app->queue->delay(0)->push(new ProductOrderSendJob([ + // 'orderId' => $this->orderId + // ])); + + ProductOrderLog::saveLog($this->orderId,'产品订单支付分账队列end'); + } catch (\Exception $exception) { + ProductOrderLog::saveLog($this->orderId,'产品订单支付分账队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/ProductOrderRefundJob.php b/common/jobs/ProductOrderRefundJob.php new file mode 100644 index 0000000..75dfbd7 --- /dev/null +++ b/common/jobs/ProductOrderRefundJob.php @@ -0,0 +1,45 @@ +orderId,'产品订单退款分账结算更新队列start'); + $this->setRequest(); + $ProductOrder = ProductOrder::findOne([ + 'id' => $this->orderId, + 'status' => 4, + ]); + if (!$ProductOrder || $ProductOrder->type != 2) { + throw new \Exception('订单不存在'); + } + + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $this->orderId; + $ledgerForm->status = 2; + $ledgerForm->update(); + + ProductOrderLog::saveLog($this->orderId,'产品订单退款分账结算更新队列end'); + } catch (\Exception $exception) { + ProductOrderLog::saveLog($this->orderId,'产品订单退款分账结算更新队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/ProductOrderSendJob.php b/common/jobs/ProductOrderSendJob.php new file mode 100644 index 0000000..1b7a253 --- /dev/null +++ b/common/jobs/ProductOrderSendJob.php @@ -0,0 +1,46 @@ +orderId,'产品订单分账结算队列start'); + $this->setRequest(); + //支付后立即结算 + $ProductOrder = ProductOrder::findOne([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'is_settled' => 0 + ]); + if (!$ProductOrder || $ProductOrder->type != 2) { + throw new \Exception('订单不存在'); + } + + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $this->orderId; + $ledgerForm->status = 1; // 已结算 + $ledgerForm->update(); + + ProductOrderLog::saveLog($this->orderId,'产品订单分账结算队列end'); + } catch (\Exception $exception) { + ProductOrderLog::saveLog($this->orderId,'产品订单分账结算队列异常:'.$exception->getMessage().'------'.$exception->getLine()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/ProductOrderSyncJob.php b/common/jobs/ProductOrderSyncJob.php new file mode 100644 index 0000000..9600fec --- /dev/null +++ b/common/jobs/ProductOrderSyncJob.php @@ -0,0 +1,107 @@ +orderId,'订单自动同步江奥川ERP start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $ProductOrder = ProductOrder::find()->with(['prescription','store'])->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'is_online' => 0, + 'status' => 1 //已付款待发货 + ])->one(); + if (!$ProductOrder || !$ProductOrder->prescription || $ProductOrder->cancel_status == 1 || !$ProductOrder->store) { + throw new \Exception('订单不存在或已取消'); + } + if($ProductOrder->prescription->status != 1){ + throw new \Exception('处方未审核'); + } + $prescriptionContent = Json::decode($ProductOrder->prescription->content); + $recipe = $prescriptionContent['repice'][0]; + $recipeContent = Json::decode($recipe['content']); + $processContent = ''; + if($recipe['process_rule_id']){ + $processContent = $recipe['process_rule']; + } + $params = [ + 'cht_id' => 'XK_'.$ProductOrder->user_id.'_'.$ProductOrder->up_id.'_'.$ProductOrder->prescription->register_id, + 'ps_seq' => $ProductOrder->prescription->prescription_no, + 'pat_name' => $prescriptionContent['patient']['name'], + 'sex' => $prescriptionContent['patient']['sex'] == 1 ? '男':'女', + 'age' => FuncHelper::getAgeFromIdNo($prescriptionContent['patient']['id_card']), + 'tot_posts' => $recipe['dosage'], + 'tisane_posts' => $recipe['dosage'], + 'usage' => '煎服,每天'.$recipe['deployment'].'次。'.$processContent,//`, 每次'.$recipe['volume'].'ml + 'doctor' => $prescriptionContent['doctor']['name'], + 'department' => $prescriptionContent['doctor']['depart']['name'],//科室 + 'post_weight' => count($recipeContent), + 'post_amount' => round($recipe['total_price']/$recipe['dosage'],2), + 'diagnose' => $prescriptionContent['clinical_diagnose'], + 'yw_type' => '1', + 'submit_date' => date('Y-m-d'), + 'get_no' => substr($ProductOrder->user_id.rand(1000,999).$ProductOrder->up_id,0,10) + ]; + if($ProductOrder->delivery_method){ //到店取货 + $params['send_way'] = '0'; + $params['telphone'] = $prescriptionContent['patient']['mobile']; + $params['addr'] = $ProductOrder->store->position; + } else { //快递到家 + $params['send_way'] = '1'; + $params['telphone'] = $ProductOrder->express_mobile; + $params['addr'] = $ProductOrder->express_region.$ProductOrder->express_address; + } + $details = []; + foreach ($recipeContent as $value) { + $detail = [ + 'drug_seq' => $value['drug_id'], + 'his_prc_cod' => 'XK'.$value['id'], + 'drug_name' => $value['name'], + 'spec' => $value['number'].$value['unit']['name'], + 'post_quantity' => $value['number'], + 'note' => $value['order']?$value['useWay']['name']:'无', + 'drug_price' => $value['price'], + 'wholesale_price' => $value['buy_price'], + 'unit' => $value['unit']['name'], + 'tisane_prc_code' => $value['drug_number'] + ]; + $details[] = $detail; + } + $params['details'] = $details; + \Yii::info(__METHOD__."——同步订单至江奥川erp(".$ProductOrder->store->erp_id.")原始数据: ".Json::encode($params)); + $result = JacErpService::getInstance($ProductOrder->store->erp_id)->syncOrder($params); + if(!$result){ + throw new \Exception('订单同步江奥川ERP失败:'.$this->getErrorMsg()); + } + //订单更新为已同步erp + $ProductOrder->is_sync_erp = 1; + $ProductOrder->save(); + + ProductOrderLog::saveLog($this->orderId,'订单自动同步江奥川ERP('.$ProductOrder->store->erp_id.') end'); + $t->commit(); + } catch (\Exception $exception) { + $t->rollBack(); + ProductOrderLog::saveLog($this->orderId,'订单自动同步江奥川ERP('.$ProductOrder->store->erp_id.')异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/ProductOrderSyncPlatformJob.php b/common/jobs/ProductOrderSyncPlatformJob.php new file mode 100644 index 0000000..fa98dd9 --- /dev/null +++ b/common/jobs/ProductOrderSyncPlatformJob.php @@ -0,0 +1,57 @@ +orderId,'产品订单状态同步平台队列start'); + $this->setRequest(); + $ProductOrder = ProductOrder::findOne([ + 'id' => $this->orderId, + 'is_online' => 1, + ]); + if (!$ProductOrder || !$ProductOrder->sync_order_no) { + throw new \Exception('订单不存在'); + } + + $result = (new PlatformService())->updateOrder([ + 'store_id' => 0, + 'order_no' => $ProductOrder->sync_order_no, + 'status' => $this->status + ]); + + ProductOrderLog::saveLog($this->orderId,'产品订单状态同步平台队列end'); + } catch (\Exception $exception) { + ProductOrderLog::saveLog($this->orderId,'产品订单状态同步平台队列异常:'.$exception->getMessage()); + return; + } + return $result; + } +} \ No newline at end of file diff --git a/common/jobs/ProductRefundJob.php b/common/jobs/ProductRefundJob.php new file mode 100644 index 0000000..e7dc6a1 --- /dev/null +++ b/common/jobs/ProductRefundJob.php @@ -0,0 +1,72 @@ +orderId,'订单自动退款队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $ProductOrder = ProductOrder::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + ])->one(); + if(!$ProductOrder){ + throw new Exception('产品订单不存在'); + } + + + //生成记录 + $ProductOrderRefund = new ProductOrderRefund(); + $ProductOrderRefund->user_id = $ProductOrder->user_id; + $ProductOrderRefund->order_id = $ProductOrder->id; + $ProductOrderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $ProductOrderRefund->refund_price = $ProductOrder->total_pay_price; + $ProductOrderRefund->remark = '超时未接诊自动退款'; + $ProductOrderRefund->saveOrFail(); + + //取消状态 + $ProductOrder->cancel_status = 1; + $ProductOrder->cancel_time = time(); + $ProductOrder->cancel_remark = '超时未接诊自动取消'; + + //退款状态 + $ProductOrder->refund_status = 1; + $ProductOrder->refund_time = time(); + $ProductOrder->saveOrFail(); + + + + //退款操作 + $ProductRefundForm = new ProductRefundForm(); + $ProductRefundForm->refundMoney($ProductOrderRefund); + + $t->commit(); + ProductOrderLog::saveLog($this->orderId,'订单自动退款队列end'); + + } catch (\Exception $exception) { + $t->rollBack(); + ProductOrderLog::saveLog($this->orderId,'订单自动退款队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/RegisterAcceptJob.php b/common/jobs/RegisterAcceptJob.php new file mode 100644 index 0000000..78a3edd --- /dev/null +++ b/common/jobs/RegisterAcceptJob.php @@ -0,0 +1,47 @@ +orderId,'挂号接诊分账结算队列 start'); + try { + $this->setRequest(); + $Register = Register::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + ])->andWhere([ + 'in','status',[2,3,5,6] + ])->one(); + if(!$Register){ + throw new Exception('挂号订单不存在'); + } + + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $this->orderId; + $ledgerForm->status = 1; + $ledgerForm->update('register'); + + RegisterLog::saveLog($this->orderId,'挂号接诊分账结算队列 end'); + } catch (\Exception $exception) { + RegisterLog::saveLog($this->orderId,'挂号接诊分账结算队列异常:'.$exception->getMessage().'——'.$exception->getLine()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/RegisterCancelJob.php b/common/jobs/RegisterCancelJob.php new file mode 100644 index 0000000..dde158a --- /dev/null +++ b/common/jobs/RegisterCancelJob.php @@ -0,0 +1,50 @@ +orderId,'挂号订单30分钟未支付自动取消队列 start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $Register = Register::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 0, + 'cancel_status' => 0, + 'status' => 0 + ])->one(); + if(!$Register){ + throw new Exception('挂号订单不存在'); + } + + //已取消状态 + $Register->status = RegisterEnum::CANCEL; // 已取消 + $Register->created_at = strtotime($Register->created_at); + $Register->updated_at = time(); + $Register->saveOrFail(); + + $t->commit(); + RegisterLog::saveLog($this->orderId,'挂号订单30分钟未支付自动取消队列 end'); + } catch (\Exception $exception) { + $t->rollBack(); + RegisterLog::saveLog($this->orderId,'挂号订单30分钟未支付自动取消队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/RegisterOverJob.php b/common/jobs/RegisterOverJob.php new file mode 100644 index 0000000..c66f950 --- /dev/null +++ b/common/jobs/RegisterOverJob.php @@ -0,0 +1,51 @@ +orderId,'订单自动完成队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $Register = Register::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0 + ])->one(); + if(!$Register){ + throw new Exception('挂号不存在'); + } + //已取消或已拒诊的不能自动完成 + if ($Register->status==4 || $Register->status ==7){ + return; + } + //已完成状态 + $Register->status = 3; // 已完成 + $Register->created_at = strtotime($Register->created_at); + $Register->updated_at = time(); + $Register->saveOrFail(); + + $t->commit(); + RegisterLog::saveLog($this->orderId,'订单自动完成队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + RegisterLog::saveLog($this->orderId,'订单自动完成队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/RegisterPaidJob.php b/common/jobs/RegisterPaidJob.php new file mode 100644 index 0000000..cbc8e01 --- /dev/null +++ b/common/jobs/RegisterPaidJob.php @@ -0,0 +1,49 @@ +orderId,'挂号订单支付分账队列 start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $Register = Register::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + 'status' => 1 + ])->one(); + if(!$Register){ + throw new Exception('挂号订单不存在'); + } + + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $this->orderId; + $ledgerForm->create('register'); + + $t->commit(); + RegisterLog::saveLog($this->orderId,'挂号订单支付分账队列 end'); + } catch (\Exception $exception) { + $t->rollBack(); + RegisterLog::saveLog($this->orderId,'挂号订单支付分账队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/RegisterRefundJob.php b/common/jobs/RegisterRefundJob.php new file mode 100644 index 0000000..b7c9b9f --- /dev/null +++ b/common/jobs/RegisterRefundJob.php @@ -0,0 +1,77 @@ +orderId,'订单自动退款队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $Register = Register::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'cancel_status' => 0, + 'refund_status' => 0, + 'status' => 1 + ])->one(); + if(!$Register){ + throw new Exception('超时未接诊自动退款挂号订单不存在'); + } + + //生成记录 + $RegisterRefund = new RegisterRefund(); + $RegisterRefund->user_id = $Register->user_id; + $RegisterRefund->register_id = $Register->id; + $RegisterRefund->refund_no = FuncHelper::generate_order_no('RF'); + $RegisterRefund->refund_price = $Register->total_pay_price; + $RegisterRefund->remark = '超时未接诊自动退款'; + $RegisterRefund->saveOrFail(); + + //取消状态 + $Register->status = 4; // 已取消 + $Register->is_cancel = 1; + $Register->cancel_time = time(); + $Register->cancel_remark = '超时未接诊自动取消'; + //退款状态 + $Register->refund_status = 1; + $Register->refund_time = time(); + $Register->saveOrFail(); + + //退款操作 + $RegisterRefundForm = new RegisterRefundForm(); + $RegisterRefundForm->refundMoney($RegisterRefund); + + //分账更新状态 + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $this->orderId; + $ledgerForm->status = 2; + $ledgerForm->update('register'); + + $t->commit(); + RegisterLog::saveLog($this->orderId,'订单自动退款队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + RegisterLog::saveLog($this->orderId,'订单自动退款队列异常:'.$exception->getMessage()); + return; + } + } +} \ No newline at end of file diff --git a/common/jobs/Sms/PrescriptionPassMessageJob.php b/common/jobs/Sms/PrescriptionPassMessageJob.php new file mode 100644 index 0000000..ae66391 --- /dev/null +++ b/common/jobs/Sms/PrescriptionPassMessageJob.php @@ -0,0 +1,57 @@ +orderId,'处方审核通过通知医生短信息发送队列start'); + try { + $this->setRequest(); + $prescription = Prescription::find()->where([ + 'id' => $this->orderId, + 'status' => PrescriptionEnum::PASSED + ])->with('doctorInfo')->one(); + if (!$prescription) { + throw new Exception('处方不存在'); + } + + $serviceUser = ServiceUser::find()->where([ + 'role' => 2, //药师 + 'status' => 2, //已审核 + 'is_delete' => 0 + ])->asArray()->all(); + if(!$serviceUser || count($serviceUser)==0){ + throw new Exception('获取药师数据错误'); + } + + (new SmsService())->sendPrescriptionPass($prescription->doctorInfo->mobile, $prescription->prescription_no); + + PrescriptionLog::saveLog($this->orderId,'处方审核通过通知医生短信息发送队列end'); + } catch (\Exception $exception) { + PrescriptionLog::saveLog($this->orderId,'处方审核通过通知医生短信息发送队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/Sms/PrescriptionRefuseMessageJob.php b/common/jobs/Sms/PrescriptionRefuseMessageJob.php new file mode 100644 index 0000000..75a3459 --- /dev/null +++ b/common/jobs/Sms/PrescriptionRefuseMessageJob.php @@ -0,0 +1,60 @@ +orderId,'处方审核被拒绝通知医生短信息发送队列start'); + try { + $this->setRequest(); + $prescription = Prescription::find()->where([ + 'id' => $this->orderId, + 'status' => PrescriptionEnum::UNPASSED + ])->with('doctorInfo')->one(); + if (!$prescription) { + throw new Exception('处方不存在'); + } + + $serviceUser = ServiceUser::find()->where([ + 'role' => 2, //药师 + 'status' => 2, //已审核 + 'is_delete' => 0 + ])->asArray()->all(); + if(!$serviceUser || count($serviceUser)==0){ + throw new Exception('获取药师数据错误'); + } + + (new SmsService())->sendPrescriptionRefuse($prescription->doctorInfo->mobile, [ + 'prescription_no' => $prescription->prescription_no, + 'reason' => $prescription->reject_reason + ]); + + PrescriptionLog::saveLog($this->orderId,'处方审核被拒绝通知医生短信息发送队列end'); + } catch (\Exception $exception) { + PrescriptionLog::saveLog($this->orderId,'处方审核被拒绝通知医生短信息发送队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/Sms/RegisterMessageJob.php b/common/jobs/Sms/RegisterMessageJob.php new file mode 100644 index 0000000..f61568f --- /dev/null +++ b/common/jobs/Sms/RegisterMessageJob.php @@ -0,0 +1,47 @@ +orderId,'患者挂号成功后通知医生接诊短信息发送队列start'); + try { + $this->setRequest(); + $register = Register::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'status' => RegisterEnum::WAIT + ])->with(['user','doctor'])->one(); + if (!$register||!$register->user||!$register->doctor) { + throw new Exception('挂号订单不存在或已取消'); + } + + (new SmsService())->sendRegister($register->doctor->mobile); + + RegisterLog::saveLog($this->orderId,'患者挂号成功后通知医生接诊短信息发送队列end'); + } catch (\Exception $exception) { + RegisterLog::saveLog($this->orderId,'患者挂号成功后通知医生接诊短信息发送队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/Sms/WaitApprovalMessageJob.php b/common/jobs/Sms/WaitApprovalMessageJob.php new file mode 100644 index 0000000..3dc5b20 --- /dev/null +++ b/common/jobs/Sms/WaitApprovalMessageJob.php @@ -0,0 +1,59 @@ +orderId,'生成处方通知药师短信息发送队列start'); + try { + $this->setRequest(); + $prescription = Prescription::find()->where([ + 'id' => $this->orderId, + 'status' => PrescriptionEnum::WAIT_CHECK + ])->one(); + if (!$prescription) { + throw new Exception('处方不存在'); + } + + $serviceUser = ServiceUser::find()->where([ + 'role' => 2, //药师 + 'status' => 2, //已审核 + 'is_delete' => 0 + ])->asArray()->all(); + if(!$serviceUser || count($serviceUser)==0){ + throw new Exception('获取药师数据错误'); + } + + foreach($serviceUser as $v){ + (new SmsService())->sendWaitApproval($v['mobile']); + PrescriptionLog::saveLog($this->orderId,'生成处方通知药师短信息发送队列:'.$v['mobile']); + } + + PrescriptionLog::saveLog($this->orderId,'生成处方通知药师短信息发送队列end'); + } catch (\Exception $exception) { + PrescriptionLog::saveLog($this->orderId,'生成处方通知药师短信息发送队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/SyncHospitalJob.php b/common/jobs/SyncHospitalJob.php new file mode 100644 index 0000000..7628a16 --- /dev/null +++ b/common/jobs/SyncHospitalJob.php @@ -0,0 +1,53 @@ +admin_id,$this->type,'同步互医队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $DrugStoreDrug = DrugStoreDrug::find()->select(['drug_id', 'price', 'stock', 'status'])->all(); + if (!$DrugStoreDrug) throw new Exception('暂无数据'); + foreach ($DrugStoreDrug as $value) { + $item= [ + 'platform_store_id' => 0, + 'id' => $value['drug_id'], + 'price' => $value['price'], + 'stock' => $value['stock'], + 'is_sale' => $value['status'] == 1 ? 0 : 1, + ]; + $response = (new PlatformService())->syncDrug($item); + if($response){ + $success[]='药品ID:'.$value['drug_id'].'同步成功'; + }else{ + $error[] = '错误:药品ID:'.$value['drug_id'].'同步失败'; + } + } + $t->commit(); + Log::saveLog($this->admin_id,$this->type,'同步互医队列end'); + }catch (\Exception $e){ + + $t->rollBack(); + Log::saveLog($this->admin_id,$this->type,'同步互医队列异常:'.$e->getMessage()); + return ; + } + + } +} \ No newline at end of file diff --git a/common/jobs/templateMessage/DoctorMessage.php b/common/jobs/templateMessage/DoctorMessage.php new file mode 100644 index 0000000..e69de29 diff --git a/common/jobs/templateMessage/PrescriptionCreated.php b/common/jobs/templateMessage/PrescriptionCreated.php new file mode 100644 index 0000000..2c165fc --- /dev/null +++ b/common/jobs/templateMessage/PrescriptionCreated.php @@ -0,0 +1,70 @@ +orderId,'处方订单生成通知用户支付订阅消息发送队列 start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $Prescription = Prescription::find()->where([ + 'id' => $this->orderId + ])->with(['user','doctorInfo','userPatient'])->one(); + if (!$Prescription||!$Prescription->user||!$Prescription->doctorInfo) { + throw new Exception('处方不存在或已取消'); + } + + $result = WechatService::getInstance()->app->subscribe_message->send([ + 'touser' => $Prescription->user->openid, + 'template_id' => \Yii::$app->params['template']['user']['prescription_created'], + 'page' => 'subPackages/my/myrecord-detail?id='.$Prescription->id.'&no='.$Prescription->prescription_no, + 'data' => [ + 'name1' => [ + 'value' => $Prescription->userPatient->name, + ], + 'thing2' => [ + 'value' => $Prescription->clinical_diagnose, + ], + 'name4' => [ + 'value' => $Prescription->doctorInfo->name, + ], + 'time9' => [ + 'value' => date('Y-m-d H:i:s',$Prescription->created_at), + ], + 'thing11' => [ + 'value' => '医生已为您开具处方,请尽快前往支付!', + ] + ] + ]); + if(isset($result['errcode']) && $result['errcode']){ + throw new Exception('发送失败,失败原因:'.$result['errmsg']); + } + PrescriptionLog::saveLog($this->orderId,'处方订单生成通知用户支付订阅消息发送队列 end'); + } catch (\Exception $exception) { + $t->rollBack(); + PrescriptionLog::saveLog($this->orderId,'处方订单生成通知用户支付订阅消息发送队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/templateMessage/ProductOrderSend.php b/common/jobs/templateMessage/ProductOrderSend.php new file mode 100644 index 0000000..4d6006a --- /dev/null +++ b/common/jobs/templateMessage/ProductOrderSend.php @@ -0,0 +1,75 @@ +orderId,'订单发货通知用户订阅消息发送队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $ProductOrder = ProductOrder::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'status' => ProductOrderEnum::WAIT_ACCEPT + ])->with(['user','expressNos'])->one(); + if (!$ProductOrder||!$ProductOrder->user||!$ProductOrder->expressNos) { + throw new Exception('订单不存在'); + } + + $result = WechatService::getInstance()->app->subscribe_message->send([ + 'touser' => $ProductOrder->user->openid, + 'template_id' => \Yii::$app->params['template']['user']['order_send'], + 'page' => 'subPackages/my/my-drug/drug-info?id='.$ProductOrder->id."&store_id=".$ProductOrder->store_id, + 'data' => [ + 'character_string2' =>[ + 'value' => $ProductOrder->order_no, + ], + 'thing3' => [ + 'value' => $ProductOrder->expressNos->express_company_name, + ], + 'character_string4' => [ + 'value' => $ProductOrder->expressNos->express_no, + ], + 'thing5' => [ + 'value' => '您的订单已发货,请注意接收!', + ] + ] + ]); + if(isset($result['errcode']) && $result['errcode']){ + throw new Exception('发送失败,失败原因:'.$result['errmsg']); + } + ProductOrderLog::saveLog($this->orderId,'订单发货通知用户订阅消息发送队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + ProductOrderLog::saveLog($this->orderId,'订单发货通知用户订阅消息发送队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/templateMessage/RegisterAccept.php b/common/jobs/templateMessage/RegisterAccept.php new file mode 100644 index 0000000..758cd11 --- /dev/null +++ b/common/jobs/templateMessage/RegisterAccept.php @@ -0,0 +1,69 @@ +orderId,'医生接诊后通知用户订阅消息发送队列start'); + $t = \Yii::$app->db->beginTransaction(); + try { + $this->setRequest(); + $register = Register::find()->where([ + 'id' => $this->orderId, + 'is_pay' => 1, + 'status' => RegisterEnum::ACCEPTING + ])->with(['user','doctor'])->one(); + if (!$register||!$register->user||!$register->doctor) { + throw new Exception('挂号订单不存在或已取消'); + } + + $result = WechatService::getInstance()->app->subscribe_message->send([ + 'touser' => $register->user->openid, + 'template_id' => \Yii::$app->params['template']['user']['register_accept'], + 'page' => 'subPackages/register/register-info?id='.$register->id.'$store_id='.$register->store_id, + 'data' => [ + 'thing1' => [ + 'value' => $register->doctor->name, + ], + 'thing2' => [ + 'value' => '您的挂号已被接诊,请尽快到医生处就诊', + ] + ] + ]); + if(isset($result['errcode']) && $result['errcode']){ + throw new Exception('发送失败,失败原因:'.$result['errmsg']); + } + RegisterLog::saveLog($this->orderId,'医生接诊后通知用户订阅消息发送队列end'); + } catch (\Exception $exception) { + $t->rollBack(); + RegisterLog::saveLog($this->orderId,'医生接诊后通知用户订阅消息发送队列异常:'.$exception->getMessage()); + return; + } + } +} diff --git a/common/jobs/templateMessage/SystemNotice.php b/common/jobs/templateMessage/SystemNotice.php new file mode 100644 index 0000000..e69de29 diff --git a/common/mail/emailVerify-html.php b/common/mail/emailVerify-html.php new file mode 100644 index 0000000..3b63e8c --- /dev/null +++ b/common/mail/emailVerify-html.php @@ -0,0 +1,16 @@ +urlManager->createAbsoluteUrl(['site/verify-email', 'token' => $user->verification_token]); +?> +
+

Hello username) ?>,

+ +

Follow the link below to verify your email:

+ +

+
diff --git a/common/mail/emailVerify-text.php b/common/mail/emailVerify-text.php new file mode 100644 index 0000000..48a68fc --- /dev/null +++ b/common/mail/emailVerify-text.php @@ -0,0 +1,12 @@ +urlManager->createAbsoluteUrl(['site/verify-email', 'token' => $user->verification_token]); +?> +Hello username ?>, + +Follow the link below to verify your email: + + diff --git a/common/mail/layouts/html.php b/common/mail/layouts/html.php new file mode 100644 index 0000000..8560d47 --- /dev/null +++ b/common/mail/layouts/html.php @@ -0,0 +1,24 @@ + +beginPage() ?> + + + + + <?= Html::encode($this->title) ?> + head() ?> + + + beginBody() ?> + + endBody() ?> + + +endPage(); diff --git a/common/mail/layouts/text.php b/common/mail/layouts/text.php new file mode 100644 index 0000000..9b4c548 --- /dev/null +++ b/common/mail/layouts/text.php @@ -0,0 +1,12 @@ + +beginPage() ?> +beginBody() ?> + +endBody() ?> +endPage() ?> diff --git a/common/mail/passwordResetToken-html.php b/common/mail/passwordResetToken-html.php new file mode 100644 index 0000000..9f6e470 --- /dev/null +++ b/common/mail/passwordResetToken-html.php @@ -0,0 +1,16 @@ +urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); +?> +
+

Hello username) ?>,

+ +

Follow the link below to reset your password:

+ +

+
diff --git a/common/mail/passwordResetToken-text.php b/common/mail/passwordResetToken-text.php new file mode 100644 index 0000000..6a5120f --- /dev/null +++ b/common/mail/passwordResetToken-text.php @@ -0,0 +1,12 @@ +urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); +?> +Hello username ?>, + +Follow the link below to reset your password: + + diff --git a/common/models/Address.php b/common/models/Address.php new file mode 100644 index 0000000..44429ee --- /dev/null +++ b/common/models/Address.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/Admin.php b/common/models/Admin.php new file mode 100644 index 0000000..f485df9 --- /dev/null +++ b/common/models/Admin.php @@ -0,0 +1,30 @@ +isNewRecord){ + $this->reg_time = time(); + $this->reg_ip = ip2long(\Yii::$app->request->getUserIP()); + } + $this->last_login_time = time(); + $this->last_login_ip = ip2long(\Yii::$app->request->getUserIP()); + $this->update_time = time(); + return true; // TODO: Change the autogenerated stub + } + + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } +} diff --git a/common/models/AdminAccessToken.php b/common/models/AdminAccessToken.php new file mode 100644 index 0000000..cfe34c3 --- /dev/null +++ b/common/models/AdminAccessToken.php @@ -0,0 +1,42 @@ + yii\behaviors\TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + static public function createToken($uid, $group = "") + { + $adminAccessToken = new static(); + $adminAccessToken->setAttributes([ + 'access_token' => Yii::$app->security->generateRandomString(), + 'admin_id' => $uid, + 'expired_at'=>time()+24*30*3600, + 'group' => $group, + 'status' => StatusEnum::ACTIVE + ]); + if ($adminAccessToken->save()) { + return $adminAccessToken; + } + return false; + } +} diff --git a/common/models/Attachment.php b/common/models/Attachment.php new file mode 100644 index 0000000..f344a8a --- /dev/null +++ b/common/models/Attachment.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} diff --git a/common/models/AttachmentGroup.php b/common/models/AttachmentGroup.php new file mode 100644 index 0000000..bc65098 --- /dev/null +++ b/common/models/AttachmentGroup.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} diff --git a/common/models/AuthItem.php b/common/models/AuthItem.php new file mode 100644 index 0000000..482067e --- /dev/null +++ b/common/models/AuthItem.php @@ -0,0 +1,8 @@ +hasOne(AuthRule::class,['id'=>'rule_id']); + } +} \ No newline at end of file diff --git a/common/models/AuthRule.php b/common/models/AuthRule.php new file mode 100644 index 0000000..120d47d --- /dev/null +++ b/common/models/AuthRule.php @@ -0,0 +1,8 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/Callback.php b/common/models/Callback.php new file mode 100644 index 0000000..53db224 --- /dev/null +++ b/common/models/Callback.php @@ -0,0 +1,21 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/CashAccount.php b/common/models/CashAccount.php new file mode 100644 index 0000000..7c82014 --- /dev/null +++ b/common/models/CashAccount.php @@ -0,0 +1,27 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + //关联后台用户表 + public function getAdmin() + { + return $this->hasOne(Admin::class,['uid'=>'user_id']); + } +} diff --git a/common/models/CashApply.php b/common/models/CashApply.php new file mode 100644 index 0000000..6506491 --- /dev/null +++ b/common/models/CashApply.php @@ -0,0 +1,146 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + public function getAdmin() + { + return $this->hasOne(Admin::class,['uid'=>'user_id']); + } + + //导出提现申请 + public static function inventory($params) + { + $where = $andWhere = []; + + switch ($params['status']) { + case 1: + $where['check_status'] = [0, 1]; + break; + case 2: + $where['check_status'] = 2; + break; + case 3: + $where['check_status'] = 3; + break; + } + //统计时间范围 + if (!empty($params['start_time']) && !empty($params['end_time'])) { + $start_time=strtotime($params['start_time']); + $end_time=strtotime($params['end_time'] ." 23:59:59"); + }else{ + $start_time = strtotime(date('Y-m-01')); + $end_time = strtotime(date('Y-m-01',strtotime("+1 month"))); + } + $andWhere = ['between', 'created_at', $start_time, $end_time]; + + if(!empty($params['name'])){ + if($params['name'] == '平台'){ + $where['user_id'] = 0; + }else{ + $store = Store::find()->where(['name'=>$params['name']])->asArray()->one(); + if($store){ + $where['user_id'] = intval($store['id']); + }else{ + $where['user_id'] = -1; + } + } + } + //查询数据 + $list=CashApply::find()->where($where)->andWhere($andWhere)->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + $inventory[$key]['order_no'] = $value['order_no']; + if($value['user_id']){ + + $payee = Store::find()->where(['id' => $value['user_id']])->one(); + $inventory[$key]['store'] = $payee['name']; + }else{ + $inventory[$key]['store'] = "平台"; + $payee = Admin::find()->where(['role' => UserRoleEnum::SUPER_ADMIN])->one(); + } + + $inventory[$key]['payee'] = $payee['bank_user_name']; + $inventory[$key]['apply_cash'] = $value['apply_cash'];// + + $inventory[$key]['created_at'] = date('Y-m-d H:i:s',$value['created_at']);//下单时间 + } + + }else{ + $inventory[0]['prescription_no']= '无数据导出'; + } + return $inventory; + } + + //导出提现申请 + public static function inventory1($params) + { + $where = $andWhere = []; + //统计时间范围 + if (!empty($params['start_time']) && !empty($params['end_time'])) { + $start_time=strtotime($params['start_time']); + $end_time=strtotime($params['end_time'] ." 23:59:59"); + }else{ + $start_time = strtotime(date('Y-m-01')); + $end_time = strtotime(date('Y-m-01',strtotime("+1 month"))); + } + $andWhere = ['between', 'created_at', $start_time, $end_time]; + + //查询数据 + $list=CashApply::find()->where($where)->andWhere($andWhere)->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + $inventory[$key]['order_no'] = $value['order_no']; + if($value['user_id']){ + $payee = Store::find()->where(['id' => $value['user_id']])->one(); + $inventory[$key]['payee'] = $payee['contact']; + }else{ + $payee = Admin::find()->where(['role' => UserRoleEnum::SUPER_ADMIN])->one(); + $inventory[$key]['payee'] = $payee['username']; + } + + $inventory[$key]['apply_cash'] = $value['apply_cash'];// + $inventory[$key]['true_cash'] = $value['true_cash'];// + $inventory[$key]['charge_cash'] = $value['charge_cash'];// + if ($value['check_status'] == 1) { + $inventory[$key]['status'] = '审核中'; + } elseif ($value['check_status'] == 2) { + $inventory[$key]['status'] = '审核通过,提现成功'; + } elseif ($value['check_status'] == 3) { + $inventory[$key]['status'] = '申请已拒绝,手续费未扣'; + } elseif ($value['check_status'] == 4) { + $inventory[$key]['status'] = '审核通过,提现失败'; + } else { + $inventory[$key]['status'] = '未知'; + } + $inventory[$key]['created_at'] = date('Y-m-d H:i:s',$value['created_at']);//下单时间 + } + + }else{ + $inventory[0]['id']= '无数据导出'; + } + return $inventory; + } +} \ No newline at end of file diff --git a/common/models/Categories.php b/common/models/Categories.php new file mode 100644 index 0000000..0bdc272 --- /dev/null +++ b/common/models/Categories.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/ChineseRepice.php b/common/models/ChineseRepice.php new file mode 100644 index 0000000..da18944 --- /dev/null +++ b/common/models/ChineseRepice.php @@ -0,0 +1,36 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 关联剂数表 + */ + public function getDosage(){ + return $this->hasMany(DrugDosage::class,['id'=>'dosage']); + } + /** + * 关联用量表 + */ + public function getUseNum(){ + return $this->hasMany(DrugUseNum::class,['id'=>'consumption']); + } +} \ No newline at end of file diff --git a/common/models/Config.php b/common/models/Config.php new file mode 100644 index 0000000..604337d --- /dev/null +++ b/common/models/Config.php @@ -0,0 +1,69 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * --------------------------------------- + * 获取 数据库中的 配置列表 + * @return array + * --------------------------------------- + */ + public static function lists(){ + $config = []; + $data = (new \yii\db\Query()) + ->select(['type', 'name', 'value']) + ->from(self::tableName()) + ->where(['status'=>1]) + ->all(); + if (!empty($data) && is_array($data)) { + foreach ($data as $key => $value) { + $config[$value['name']] = self::parse($value['type'], $value['value']); + } + } + return $config; + } + + /** + * --------------------------------------- + * 根据配置类型解析配置 + * @param integer $type 配置类型 + * @param string $value 配置值 + * @return mixed + * --------------------------------------- + */ + public static function parse($type, $value){ + switch ($type) { + case 3: //解析数组 + $array = preg_split('/[,;\r\n]+/', trim($value, ",;\r\n")); + if(strpos($value,':')){ + $value = []; + foreach ($array as $val) { + list($k, $v) = explode(':', $val); + $value[$k] = $v; + } + }else{ + $value = $array; + } + break; + } + return $value; + } +} diff --git a/common/models/Department.php b/common/models/Department.php new file mode 100644 index 0000000..6290d4c --- /dev/null +++ b/common/models/Department.php @@ -0,0 +1,34 @@ +TimestampBehavior::class, + 'attributes'=>[ + ActiveRecord::EVENT_BEFORE_INSERT=>['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE=>['updated_at'], + ] + ] + ]; + } + public function getChild() + { + return $this->hasMany(Department::class,['pid'=>'id']); + } + + + //科室 + public function getDepart(){ + //一个门店对应多个科室,一个科室对应多个门店 + return $this->hasMany(Store::class, ['id' => 'store_id']) + ->viaTable(StoreDepartment::tableName(), ['depart_id' => 'id']); + } +} \ No newline at end of file diff --git a/common/models/DiagnoseCommon.php b/common/models/DiagnoseCommon.php new file mode 100644 index 0000000..791f7e3 --- /dev/null +++ b/common/models/DiagnoseCommon.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/Disease.php b/common/models/Disease.php new file mode 100644 index 0000000..7218770 --- /dev/null +++ b/common/models/Disease.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/DiseaseCommon.php b/common/models/DiseaseCommon.php new file mode 100644 index 0000000..36193a2 --- /dev/null +++ b/common/models/DiseaseCommon.php @@ -0,0 +1,28 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getDisease() + { + return $this->hasOne(Disease::class,['id'=>'disease_id'])->select('id,name'); + } + +} \ No newline at end of file diff --git a/common/models/DistrictArr.php b/common/models/DistrictArr.php new file mode 100644 index 0000000..720b163 --- /dev/null +++ b/common/models/DistrictArr.php @@ -0,0 +1,215 @@ +"; + var_export($arr); + echo ""; + + exit(); + } + + /** + * 获取已父级id为$parent_id为根节点的树型结构数组 + * @param array $arr 省市区数据 + * @param string $level 不需要的数据的level,当前等级且包含其下级都排除 + * @return array + */ + public static function getList(&$arr, $level = null) + { + $treeData = [];// 保存结果 + $catList = $arr; + foreach ($catList as &$item) { + if ($level && $item['level'] == $level) { + continue; + } + $parent_id = $item['parent_id']; + if (isset($catList[$parent_id]) && !empty($catList[$parent_id])) {// 肯定是子分类 + $catList[$parent_id]['list'][] = &$catList[$item['id']]; + } else {// 肯定是一级分类 + $treeData[] = &$catList[$item['id']]; + } + } + unset($item); + return $treeData[0]['list']; + } + + // 根据id获取信息 + public static function getDistrict($param) + { + if (is_array($param)) { + $id = $param['id']; + } else { + $id = $param; + } + $arr = self::getArr(); + if (!isset($arr[$id])) { + throw new \Exception('未找到省市区,请重新选择'); + } + $list = $arr[$id]; + $str = json_encode($list); + return json_decode($str,true); + } + + // 根据指定的key=>value查找需要的数组 + public static function getInfo($param) + { + $newParam = []; + foreach ($param as $key => $value) { + $newParam[0] = $key; + $newParam[1] = $value; + } + $arr = self::getArr(); + $list = array_filter($arr, function ($v) use ($newParam) { + return $v[$newParam[0]] == $newParam[1]; + }); + $str = json_encode($list); + return json_decode($str,true); + } + + // 运费规则、起送规则、包邮规则 + public static function getRules() + { + $arr = self::getArr(); + $empty = []; + $emptyPointer = &$empty; + $ok = false; + foreach ($arr as $index => &$item) { + if ($item['parent_id'] == 1) { + $okCity = false; + $data = [ + 'id' => $item['id'], + 'name' => $item['name'] + ]; + $data['show'] = false; + $data['city'] = []; + $dataPointer = &$data['city']; + foreach ($arr as $key => $value) { + if ($value['parent_id'] == $index) { + $okCity = true; + $dataPointer[] = [ + 'id' => $value['id'], + 'name' => $value['name'], + 'show' => false + ]; + } + if ($okCity && $value['parent_id'] != $index) { + break; + } + } + array_push($emptyPointer, $data); + $ok = true; + } + if ($ok && $item['parent_id'] != 1) { + break; + } + } + + return $empty; + } + + // 微信获取地址 + public static function getWechatDistrict($province_name, $city_name, $county_name) + { + $arr = self::getArr(); + $ok = false; + $district = []; + $county = []; + $city = []; + $province = []; + foreach ($arr as $item) { + if ($item['name'] == $county_name && $item['level'] == 'district') { + $county = $item; + $city = $arr[$item['parent_id']]; + if (isset($arr[$county['parent_id']]) && $city['name'] == $city_name) { + $province = $arr[$city['parent_id']]; + if (isset($arr[$city['parent_id']]) && $province['name'] == $province_name) { + $ok = true; + break; + } + } + } + } + + if(!$ok){ + foreach ($arr as $item) { + if($item['name'] == $city_name && $item['level'] == 'city'){ + $city = $item; + if(isset($arr[$city['parent_id']]) && $arr[$city['parent_id']]['name']==$province_name){ + $province = $arr[$city['parent_id']]; + $ok = true; + break; + } + } + } + } + +// if (!$ok) { +// $diff_district = self::getDiffCityDistrict($city_name); +// $district = [ +// 'province' => [ +// 'id' => 3268, +// 'name' => '其他', +// ], +// 'city' => [ +// 'id' => 3269, +// 'name' => '其他', +// ], +// 'district' => [ +// 'id' => 3270, +// 'name' => '其他', +// ], +// ]; +// if ($diff_district) { +// $district = $diff_district; +// } +// return $district; +// } + + $district = [ + 'province' => [ + 'id' => isset($province['id']) ? $province['id'] : 3268, + 'name' => isset($province['name']) ? $province['name'] : '其他', + ], + 'city' => [ + 'id' => isset($city['id']) ? $city['id'] : 3269, + 'name' => isset($city['name']) ? $city['name'] : '其他', + ], + 'district' => [ + 'id' => isset($county['id']) ? $county['id'] : 3270 , + 'name' => isset($county['name']) ? $county['name'] : '其他' + ] + ]; + + return $district; + } +} diff --git a/common/models/DocPhaImgs.php b/common/models/DocPhaImgs.php new file mode 100644 index 0000000..569402b --- /dev/null +++ b/common/models/DocPhaImgs.php @@ -0,0 +1,8 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/DoctorArticle.php b/common/models/DoctorArticle.php new file mode 100644 index 0000000..4378307 --- /dev/null +++ b/common/models/DoctorArticle.php @@ -0,0 +1,28 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getCategories() + { + return $this->hasOne(Categories::class,['id'=>'cid']); + } +} \ No newline at end of file diff --git a/common/models/DoctorCommon.php b/common/models/DoctorCommon.php new file mode 100644 index 0000000..9055bbc --- /dev/null +++ b/common/models/DoctorCommon.php @@ -0,0 +1,20 @@ +hasOne(Drug::class,['id'=>'drug_id'])->select('id,drug_name,source,type,info,content,usage,function,specification,image,instruction'); + } + + public function getDrugStoreDrug(){ + return $this->hasOne(DrugStoreDrug::class,['drug_id'=>'drug_id'])->andWhere(['yii_drugstore_drug.status' => 2]); + } + public function getDrugStoreRelation() + { + return $this->hasOne(DrugStoreRelations::class,['drug_id'=>'drug_id', 'store_id'=>'store_id'])->andWhere(['yii_drug_store_relations.status' => 2]); + } + +} \ No newline at end of file diff --git a/common/models/DoctorIdentity.php b/common/models/DoctorIdentity.php new file mode 100644 index 0000000..6ea1bb3 --- /dev/null +++ b/common/models/DoctorIdentity.php @@ -0,0 +1,24 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + +} \ No newline at end of file diff --git a/common/models/DoctorInfo.php b/common/models/DoctorInfo.php new file mode 100644 index 0000000..c5f7061 --- /dev/null +++ b/common/models/DoctorInfo.php @@ -0,0 +1,83 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联职称 + public function getTitle() + { + return $this->hasOne(DoctorTitle::class,['id'=>'title_id']); + } + + //关联科室 + public function getDepart() + { + return $this->hasOne(Department::class,['id'=>'depart_id'])->select('id,name,pid'); + } + + //关联医院 + public function getHospital() + { + return $this->hasOne(Hospital::class,['id'=>'hospital_id']); + } + + //关联院区 + public function getYard() + { + return $this->hasOne(HospitalYard::class,['id'=>'yard_id']); + } + + //关联用户 + public function getUser() + { + return $this->hasOne(ServiceUser::class,['id'=>'su_id']); + } + + //关联服务 + public function getService() + { + return $this->hasOne(DoctorService::class,['su_id'=>'su_id']); + } + + //关联医生执业信息 + public function getDocPracticing() + { + return $this->hasOne(DoctorPracticing::class,['su_id'=>'su_id']); + } + + public function getServiceUser() + { + return $this->hasOne(ServiceUser::class,['id'=>'su_id']); + } + + + //关联门店信息 + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id'])->via('storeDoctor'); + } + + //关联门店医生信息 + public function getStoreDoctor() + { + return $this->hasOne(StoreDoctor::class,['su_id'=>'su_id']); + } + +} \ No newline at end of file diff --git a/common/models/DoctorNotice.php b/common/models/DoctorNotice.php new file mode 100644 index 0000000..5c8a273 --- /dev/null +++ b/common/models/DoctorNotice.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/DoctorPatient.php b/common/models/DoctorPatient.php new file mode 100644 index 0000000..d6497a3 --- /dev/null +++ b/common/models/DoctorPatient.php @@ -0,0 +1,76 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 科室 + */ + public function getTags() + { + + return $this->hasMany(DoctorTagIll::class, ['id' => 'ti_id']) + ->viaTable(UserPatientIll::tableName(), ['up_id' => 'id']); + } + + public function getHealth() + { + return $this->hasMany(UserPatientHealthInquiry::class, ['user_patient_id' => 'up_id']); + } + public static function inventory($params) + { + $su_id=\Yii::$app->user->id; + //统计时间范围 + if(!empty($params['min']) && !empty($params['max'])){ + $ti = strtotime($params['max'])+3600*24; + }else{ + $date_max = date('Y-m-d'); + $date_min = date('Y-m-d',strtotime("-31 day")); + } + //查询数据 + $where = ''; + $list=DoctorPatient::find()->where([ + 'su_id'=>$su_id + ])->with(['health'])->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + $inventory[$key]['name']= $value['name']; + $inventory[$key]['id_card'] = $value['id_card']; + $inventory[$key]['sex'] = $value['sex']; + $inventory[$key]['mobile'] = $value['mobile']; + $inventory[$key]['liver_function'] = $value['health'][0]['liver_function']; + $inventory[$key]['liver_index'] = $value['health'][0]['liver_index']; + $inventory[$key]['renal_function'] = $value['health'][0]['renal_function']; + $inventory[$key]['renal_index'] = $value['health'][0]['renal_index']; + $inventory[$key]['person_status'] = $value['health'][0]['person_status']; + $inventory[$key]['person_history'] = $value['health'][0]['person_history']; + $inventory[$key]['allergic_status'] = $value['health'][0]['allergic_status']; + $inventory[$key]['allergic_history'] = $value['health'][0]['allergic_history']; + $inventory[$key]['family_status'] = $value['health'][0]['family_status']; + $inventory[$key]['family_history'] = $value['health'][0]['family_history']; + } + }else{ + $inventory[0]['patient']= '无数据导出'; + } + return $inventory; + } +} diff --git a/common/models/DoctorPatientRemark.php b/common/models/DoctorPatientRemark.php new file mode 100644 index 0000000..34d2aad --- /dev/null +++ b/common/models/DoctorPatientRemark.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/DoctorPracticing.php b/common/models/DoctorPracticing.php new file mode 100644 index 0000000..5b3a028 --- /dev/null +++ b/common/models/DoctorPracticing.php @@ -0,0 +1,24 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + +} \ No newline at end of file diff --git a/common/models/DoctorService.php b/common/models/DoctorService.php new file mode 100644 index 0000000..d901742 --- /dev/null +++ b/common/models/DoctorService.php @@ -0,0 +1,24 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + +} \ No newline at end of file diff --git a/common/models/DoctorTagIll.php b/common/models/DoctorTagIll.php new file mode 100644 index 0000000..123c98b --- /dev/null +++ b/common/models/DoctorTagIll.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/DoctorTitle.php b/common/models/DoctorTitle.php new file mode 100644 index 0000000..1d70928 --- /dev/null +++ b/common/models/DoctorTitle.php @@ -0,0 +1,9 @@ +hasMany(DoctorCommon::class,['id'=>'drug_id'])->with(['su_id'=>\Yii::$app->user->identity->id]); + } + + public function getDrugStoreDrug() + { + return $this->hasOne(DrugStoreDrug::class,['drug_id'=>'id']); + } + public function getDrugStoreRelation() + { + return $this->hasOne(DrugStoreRelations::class,['drug_id'=>'id']); + } + + //关联门店 + public function getStore(){ + return $this->hasOne(Store::class,['id'=>'store_id']); + } + + //关联单位 + public function getUnit() + { + return $this->hasOne(WestUnit::class,['id'=>'unit_id']); + } + + + public function getDrugStoreRelationes() + { + return $this->hasOne(DrugStoreRelations::class,['drug_id'=>'id']); + } + //关联使用频率 + public function getDrugUseFrequency() + { + return $this->hasOne(DrugUseFrequency::class,['id'=>'frequency_id']); + } + + //关联 + public function getDrugUseType() + { + return $this->hasOne(DrugUseType::class,['id'=>'type_id']); + } + + //关联使用时间 + public function getDrugUseTime() + { + return $this->hasOne(DrugUseTime::class,['id'=>'time_id']); + } + + //关联煎法 + public function getDrugUseWay() + { + return $this->hasOne(DrugUseWay::class,['id'=>'decotion']); + } + + //导出药品 + public static function inventory($params) + { + $su_id=\Yii::$app->user->id; + //统计时间范围 + if (!empty($params['date_max']) && !empty($params['date_min'])) { + $params['date_max'] = strtotime($params['date_max']); + $params['date_min'] = strtotime($params['date_min']); + } + else{ + $date_max = date('Y-m-d'); + $date_min = date('Y-m-d',strtotime("-31 day")); + } + + $data = [ + 'and', + ['between', 'created_at', $params['date_min'], $params['date_max']], + ['type' => $params['type']], + ]; + //查询数据 + $list=Drug::find()->filterWhere($data)->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + + $inventory[$key]['id'] = $value['id']; + $inventory[$key]['drug_name'] = $value['drug_name']; + $inventory[$key]['pinyin_simple'] = $value['pinyin_simple']; + $inventory[$key]['source'] = $value['source']; + + if ($value['type']==1){ + $inventory[$key]['type']='中药'; + }elseif ($value['type']==2){ + $inventory[$key]['type']='西药'; + }elseif ($value['type']==3){ + $inventory[$key]['type']='颗粒配方'; + }elseif ($value['type']==4){ + $inventory[$key]['type']='中成药'; + }else{ + $inventory[$key]['type']='其他'; + } + $inventory[$key]['is_otc'] = $value['is_otc']; + $inventory[$key]['content'] = $value['content']; + $inventory[$key]['usage'] = $value['usage']; + $inventory[$key]['function'] = $value['function']; + $inventory[$key]['specification'] = $value['specification']; + $inventory[$key]['drug_number'] = $value['drug_number']; + $inventory[$key]['bar_code'] = $value['specification']; + $inventory[$key]['guozi_no'] = $value['guozi_no']; + $inventory[$key]['drug_alias'] = $value['drug_alias']; + if ($value['status']==1){ + $inventory[$key]['status']='草稿'; + }elseif ($value['status']==2){ + $inventory[$key]['status']='下架'; + }elseif ($value['status']==3){ + $inventory[$key]['status']='上架'; + }else{ + $inventory[$key]['status']='其他'; + } + } + + }else{ + $inventory[0]['prescription_no']= '无数据导出'; + } + return $inventory; + } +} \ No newline at end of file diff --git a/common/models/DrugCategories.php b/common/models/DrugCategories.php new file mode 100644 index 0000000..948a6bc --- /dev/null +++ b/common/models/DrugCategories.php @@ -0,0 +1,11 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/DrugStoreDrug.php b/common/models/DrugStoreDrug.php new file mode 100644 index 0000000..4553225 --- /dev/null +++ b/common/models/DrugStoreDrug.php @@ -0,0 +1,34 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联门店 + public function getStore() + { + return $this->hasOne(Store::class,['drugstore_id' => 'drugstore_id']); + } + + //关联基础商品 + public function getDrug() + { + return $this->hasOne(Drug::class,['id' => 'drug_id']); + } +} diff --git a/common/models/DrugStoreRelations.php b/common/models/DrugStoreRelations.php new file mode 100644 index 0000000..9f61817 --- /dev/null +++ b/common/models/DrugStoreRelations.php @@ -0,0 +1,23 @@ +hasOne(Drug::class,['id'=>'drug_id']); + } + + + //关联仓库 + public function getDrugStoreDrug() + { + return $this->hasOne(DrugStoreDrug::class,['drug_id'=>'drug_id']); + } +} diff --git a/common/models/DrugUseFrequency.php b/common/models/DrugUseFrequency.php new file mode 100644 index 0000000..f626867 --- /dev/null +++ b/common/models/DrugUseFrequency.php @@ -0,0 +1,8 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} diff --git a/common/models/ExpressCompanies.php b/common/models/ExpressCompanies.php new file mode 100644 index 0000000..3dd9910 --- /dev/null +++ b/common/models/ExpressCompanies.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/ExpressNos.php b/common/models/ExpressNos.php new file mode 100644 index 0000000..b38b3c3 --- /dev/null +++ b/common/models/ExpressNos.php @@ -0,0 +1,11 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + //关联基础信息-医生 + public function getDocInfo() + { + return $this->hasOne(DoctorInfo::className(),['su_id'=>'su_id']); + } + + //关联认证信息-医生 + public function getDocIdentity() + { + return $this->hasOne(DoctorIdentity::className(),['su_id'=>'su_id']); + } + //关联执业信息-医生 + public function getDocPracticing() + { + return $this->hasOne(DoctorPracticing::className(),['su_id'=>'su_id']); + } + + //关联服务信息-医生 + public function getDocService() + { + return $this->hasOne(DoctorService::className(),['su_id'=>'su_id']); + } + +} \ No newline at end of file diff --git a/common/models/FollowUser.php b/common/models/FollowUser.php new file mode 100644 index 0000000..69182df --- /dev/null +++ b/common/models/FollowUser.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/FreeDeliveryRules.php b/common/models/FreeDeliveryRules.php new file mode 100644 index 0000000..e977bd7 --- /dev/null +++ b/common/models/FreeDeliveryRules.php @@ -0,0 +1,74 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function decodeDetail() + { + $detail = json_decode($this->detail,true); + if (!isset($detail[0]['condition'])) { + $newItem['condition'] = $this->price; + $newItem['list'] = $detail; + $detail = [$newItem]; + } + return $detail; + } + + public function getTypeText() + { + switch ($this->type) { + case 1: + return '订单满额包邮'; + case 2: + return '订单满件包邮'; + case 3: + return '单商品满额包邮'; + case 4: + return '单商品满件包邮'; + default: + return ''; + } + } + // 设置默认包邮规则(一个商城仅有一个默认运费规则) + public static function setStatus($id = null) + { + $model = static::findOne([ + 'id' => $id, + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + ]); + if (!$model) { + throw new ApiException("包邮规则不存在"); + } else { + static::updateAll(['status' => 0], [ + 'mall_id' => \Yii::$app->mallId, + ]); + $model->status = 1; + if ($model->save()) { + return [ + ]; + } else { + throw new ApiException($model->errors[0]); + } + } + } +} diff --git a/common/models/FundWater.php b/common/models/FundWater.php new file mode 100644 index 0000000..d8e78df --- /dev/null +++ b/common/models/FundWater.php @@ -0,0 +1,113 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //挂号 + public function getRegister() + { + return $this->hasOne(Register::class,['id'=>'order_id']); + } + //产品订单 + public function getProductOrder() + { + return $this->hasOne(ProductOrder::class,['id'=>'order_id']); + } + + //诊所 + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } + + + //医生 + public function getDoctor() + { + return $this->hasOne(DoctorInfo::class,['su_id'=>'service_user_id']); + } + + //用户 + public function getUser() + { + return $this->hasOne(User::class,['id'=>'user_id']); + } + + //导出资金流水 + public static function inventory($params,$store_id) + { + $where = $andWhere = []; + //统计时间范围 + if (!empty($params['start_time']) && !empty($params['end_time'])) { + $start_time=strtotime($params['start_time']); + $end_time=strtotime($params['end_time']); + $andWhere = ['between', 'yii_fund_water.created_at', $start_time, $end_time]; + } + + if($store_id){ + $where['yii_fund_water.store_id'] = $store_id; + } + // $where['is_deleted'] = 0 + if (!empty($params['order_no'])) {//订单号 + $where['yii_fund_water.order_no'] = $params['order_no']; + } + if (!empty($params['refund_no'])) {//退款单号 + $where['yii_fund_water.refund_no'] = $params['refund_no']; + } + $name = $params['store']; + if($name){ + $where['yii_store.name'] = $name; + } + $doctor = $params['doctor']; + if($doctor){ + $where['yii_doctor_info.name'] = $doctor; + } + //查询数据 + $list=FundWater::find()->where($where)->andWhere($andWhere)->joinWith(['doctor','user','store'])->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + + //订单类型 + if ($value['order_type']==1){ + $inventory[$key]['order_type'] ='产品订单'; + }elseif ($value['order_type']==2){ + $inventory[$key]['order_type'] ='挂号订单'; + }elseif ($value['order_type']==3){ + $inventory[$key]['order_type'] ='问诊订单'; + }else{ + $inventory[$key]['order_type'] ='暂无'; + } + + $inventory[$key]['doctor'] = $value['doctor']['name']??'无'; + $inventory[$key]['patient'] = $value['user']['nickname']??'无'; + + $inventory[$key]['price'] = $value['price']??'无'; + $inventory[$key]['store'] = $value['store']['name']??'无';// + $inventory[$key]['created_at'] = date('Y-m-d H:i:s',$value['created_at']);//下单时间 + } + + }else{ + $inventory[0]['prescription_no']= '无数据导出'; + } + return $inventory; + } +} \ No newline at end of file diff --git a/common/models/GranularRepice.php b/common/models/GranularRepice.php new file mode 100644 index 0000000..1c94c9a --- /dev/null +++ b/common/models/GranularRepice.php @@ -0,0 +1,32 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + + /** + * 关联用量表 + */ + public function getUseNum(){ + return $this->hasMany(DrugUseNum::class,['id'=>'consumption']); + } + +} \ No newline at end of file diff --git a/common/models/HealthyNews.php b/common/models/HealthyNews.php new file mode 100644 index 0000000..23d69a8 --- /dev/null +++ b/common/models/HealthyNews.php @@ -0,0 +1,31 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联用户收藏 + public function getCollect() + { + return $this->hasOne(UserCollect::className(),['object_id'=>'id']) + ->where(['type'=>1,'user_id'=>\Yii::$app->user->identity->id]) + ->select('object_id,is_delete'); + } + +} diff --git a/common/models/Hospital.php b/common/models/Hospital.php new file mode 100644 index 0000000..152f0cd --- /dev/null +++ b/common/models/Hospital.php @@ -0,0 +1,32 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + //院区列表 + public function getYard(){ + // 一个医院对应多个院区,一对多的关系使用hasMany()关联 + return $this->hasMany(HospitalYard::class,['hospital_id'=>'id']); + } + + public function getDepartment() + { + return $this->hasOne(HospitalDepartment::className(),['department_id'=>'id']); + } +} \ No newline at end of file diff --git a/common/models/HospitalDepartmentIntro.php b/common/models/HospitalDepartmentIntro.php new file mode 100644 index 0000000..c1a3cf1 --- /dev/null +++ b/common/models/HospitalDepartmentIntro.php @@ -0,0 +1,49 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 获取科室信息 + * @return \yii\db\ActiveQuery + */ + public function getDepartment() + { + return $this->hasMany(HospitalDepartment::className(),['id'=>'department_id']); + } + + /** + * 获取分院信息 + * @return \yii\db\ActiveQuery + */ + public function getYard() + { + return $this->hasOne(HospitalYard::className(),['id'=>'yard_id'])->select('id,name'); + } + + /** + * 获取分院医生信息 + * @return \yii\db\ActiveQuery + */ + public function getDoctor() + { + return $this->hasMany(DoctorInfo::className(),['yard_id'=>'yard_id','depart_id'=>'department_id']); + } +} \ No newline at end of file diff --git a/common/models/HospitalYard.php b/common/models/HospitalYard.php new file mode 100644 index 0000000..7ceefa8 --- /dev/null +++ b/common/models/HospitalYard.php @@ -0,0 +1,32 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + + /** + * 科室 + */ + public function getDepartments(){ + //一个院区对应多个科室,一个科室对应多个院区 + return $this->hasMany(HospitalDepartment::class, ['id' => 'depart_id']) + ->viaTable(HospitalYardDepartment::tableName(), ['yard_id' => 'id']); + } +} \ No newline at end of file diff --git a/common/models/HospitalYardDepartment.php b/common/models/HospitalYardDepartment.php new file mode 100644 index 0000000..711f186 --- /dev/null +++ b/common/models/HospitalYardDepartment.php @@ -0,0 +1,8 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 获取分院信息 + * @return ActiveQuery + */ + public function getYard(): ActiveQuery + { + return $this->hasOne(HospitalYard::className(),['id'=>'yard_id'])->select('id,name,position,hospital_id'); + } +} diff --git a/common/models/ImMessage.php b/common/models/ImMessage.php new file mode 100644 index 0000000..a102403 --- /dev/null +++ b/common/models/ImMessage.php @@ -0,0 +1,62 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //发送消息 + public static function sendMessage($ims_id,$user_id,$service_id,$content,$type) + { + $imMessage = new ImMessage(); + $imMessage->ims_id = $ims_id; + $imMessage->user_id = $user_id; + $imMessage->service_id = $service_id; + $imMessage->content = $content; + $imMessage->type = $type; + $imMessage->saveOrFail(); + } + + //member下消息可以通过关联获取,service下的聊天用户不能通过关联,因为user_id可能是医生药师导医,service_id是客服 + //member下的消息可以通过关联获取,但是再次关联的info,需要区分,因为不仅跟医生,还会跟导医聊 + public function getUser() + { + return $this->hasOne(User::className(),['id'=>'user_id']); + } + + //关联用户 + public function getUserByServiceId() + { + return $this->hasOne(User::className(),['id'=>'service_id']); + } + + public function getServiceUser() + { + return $this->hasOne(ServiceUser::className(),['id'=>'service_id']); + } + + //关联服务人员 + public function getServiceUserByUserId() + { + return $this->hasOne(ServiceUser::className(),['id'=>'user_id']); + } + + public function getImSession() + { + return $this->hasOne(ImMessageSession::className(),['id'=>'ims_id']); + } +} diff --git a/common/models/ImMessageSession.php b/common/models/ImMessageSession.php new file mode 100644 index 0000000..d469ec6 --- /dev/null +++ b/common/models/ImMessageSession.php @@ -0,0 +1,98 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function attributes() + { + return array_merge(parent::attributes(), ['noread_count','last_time','last_id']); + } + + /** + * {@inheritdoc} + */ + public function rules() + { + $rules = parent::rules(); + $rules[] = [['noread_count'], 'safe']; + return $rules; + } + + public function attributeLabels() + { + return array_merge(parent::attributeLabels(), [ + 'noread_count' => '未读数量', + 'last_time' => '最新消息时间' + ]); + } + + public static function createSession($user_id,$service_id,$type) + { + $imMessageSession = new self(); + $imMessageSession->user_id = $user_id; + $imMessageSession->service_id = $service_id; + $imMessageSession->type = $type; + $imMessageSession->saveOrFail(); + return $imMessageSession; + } + + public function getSessionOrder() + { + return $this->hasOne(ImMessageSessionOrder::className(),['ims_id'=>'id']); + } + + //关联订单 + public function getOrder() + { + return $this->hasOne(Order::className(),['id'=>'order_id'])->via('sessionOrder'); + } + + //关联用户 + public function getUser() + { + return $this->hasOne(User::className(),['id'=>'user_id']); + } + + //关联用户 + public function getUserByServiceId() + { + return $this->hasOne(User::className(),['id'=>'service_id']); + } + + //关联服务人员 + public function getServiceUser() + { + return $this->hasOne(ServiceUser::className(),['id'=>'service_id']); + } + + //关联服务人员 + public function getServiceUserByUserId() + { + return $this->hasOne(ServiceUser::className(),['id'=>'user_id']); + } + + //关联消息 + public function getImMessage() + { + return $this->hasMany(ImMessage::className(),['ims_id'=>'id']); + } +} diff --git a/common/models/ImMessageSessionOrder.php b/common/models/ImMessageSessionOrder.php new file mode 100644 index 0000000..b2743b9 --- /dev/null +++ b/common/models/ImMessageSessionOrder.php @@ -0,0 +1,21 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/InquiryRefuseReason.php b/common/models/InquiryRefuseReason.php new file mode 100644 index 0000000..6616281 --- /dev/null +++ b/common/models/InquiryRefuseReason.php @@ -0,0 +1,24 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + +} \ No newline at end of file diff --git a/common/models/LeadInfo.php b/common/models/LeadInfo.php new file mode 100644 index 0000000..ce2d822 --- /dev/null +++ b/common/models/LeadInfo.php @@ -0,0 +1,126 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联职称 + public function getTitle() + { + return $this->hasOne(DoctorTitle::className(),['id'=>'title_id']); + } + + //关联科室 + public function getDepart() + { + return $this->hasOne(HospitalDepartment::className(),['id'=>'depart_id']); + } + + //关联医院 + public function getHospital() + { + return $this->hasOne(Hospital::className(), ['id' => 'hospital_id']); + } + + //关联院区 + public function getYard() + { + return $this->hasOne(HospitalYard::className(), ['id' => 'yard_id']); + } + + // 关联用户 + public function getUser() + { + return $this->hasOne(ServiceUser::className(), ['id' => 'su_id']); + } + + // 关联回话 + public function getImMessageSessions() + { + return $this->hasMany(ImMessageSession::className(), ['id' => 'service_id']); + } + + /** + * 获取空闲导医 + * + * @return array + */ + public static function getLastLeadUserId(): array + { + $wheres = [ + [ + 'su.role' => UserRoleEnum::LEADER, + 'su.status' => 2, + 'su.is_delete' => 0, + 'su.im_status' => 1, + 'ims.type' => 3, + 'ims.status' => 10, + ], + [ + 'su.role' => UserRoleEnum::LEADER, + 'su.status' => 2, + 'su.is_delete' => 0, + 'su.im_status' => 1, + 'ims.type' => 3, + 'ims.status' => 0, + ], + [ + 'su.role' => UserRoleEnum::LEADER, + 'su.status' => 2, + 'su.is_delete' => 0, + 'su.im_status' => 0, + 'ims.type' => 3, + 'ims.status' => 10, + ], + [ + 'su.role' => UserRoleEnum::LEADER, + 'su.status' => 2, + 'su.is_delete' => 0, + 'su.im_status' => 0, + 'ims.type' => 3, + 'ims.status' => 0, + ], + [ + 'su.role' => UserRoleEnum::LEADER, + 'su.status' => 2, + 'su.is_delete' => 0, + 'ims.type' => 3, + ], + ]; + foreach ($wheres as $where) { + $users = ServiceUser::find() + ->alias('su') + ->select(['su.id, count(ims.id) as count']) + ->leftJoin('yii_im_message_session as ims', 'su.id = ims.service_id') + ->where($where) + ->groupBy('su.id') + ->orderBy(['count' => SORT_ASC]) + ->asArray() + ->all(); + if (count($users)) { + return [ + 'id' => $users[0]['id'], + ]; + } + } + throw new Exception('当前无客服在线'); + } +} \ No newline at end of file diff --git a/common/models/Ledger.php b/common/models/Ledger.php new file mode 100644 index 0000000..ba96cbd --- /dev/null +++ b/common/models/Ledger.php @@ -0,0 +1,89 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //账户 + public function getCashAccount() + { + return $this->hasOne(CashAccount::class,['user_id'=>'user_id']); + } + + //产品订单 + public function getProductOrder() + { + return $this->hasOne(ProductOrder::class,['id'=>'order_id']); + } + //药品 + public function getDrug() + { + return $this->hasOne(Drug::class,['id'=>'drug_id']); + } + + //挂号 + public function getRegister() + { + return $this->hasOne(Register::class,['id'=>'order_id']); + } + + //导出结算记录 + public static function inventory($params,$store_id) + { + $where = $andWhere = []; + $where['status'] = [0,1]; + //统计时间范围 + if (!empty($params['start_time']) && !empty($params['end_time'])) { + $start_time=strtotime($params['start_time']); + $end_time=strtotime($params['end_time']); + $andWhere = ['between', 'created_at', $start_time, $end_time]; + } + + if($store_id){ + $where['user_id'] = $store_id; + } + + $list=Ledger::find()->select('id,order_id,sum(money) as total_money,order_type,status,created_at')->where($where)->andWhere($andWhere)->groupBy('order_id,order_type')->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + //订单类型 + if ($value['order_type']==1){ + $order = ProductOrder::find()->where(['id' => $value['order_id']])->one(); + $inventory[$key]['order_no'] =$order->order_no; + $inventory[$key]['order_type'] ='产品订单'; + }else{ + $order = Register::find()->where(['id' => $value['order_id']])->one(); + $inventory[$key]['order_no'] =$order->order_no; + $inventory[$key]['order_type'] ='挂号订单'; + } + $user = User::find()->where(['id' => $order->user_id])->one(); + $inventory[$key]['nickname'] = $user->nickname; + $inventory[$key]['money'] = $value['total_money']; + $inventory[$key]['status'] = $value['status'] == 0?'待结算':'已结算'; + $inventory[$key]['created_at'] = date('Y-m-d H:i:s',$value['created_at']);//下单时间 + } + + }else{ + $inventory[0]['prescription_no']= '无数据导出'; + } + return $inventory; + } +} diff --git a/common/models/LedgerLog.php b/common/models/LedgerLog.php new file mode 100644 index 0000000..d1029e7 --- /dev/null +++ b/common/models/LedgerLog.php @@ -0,0 +1,28 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + + public function getAdmin() + { + return $this->hasOne(Admin::class,['uid'=>'user_id']); + } +} diff --git a/common/models/Log.php b/common/models/Log.php new file mode 100644 index 0000000..a98fc9c --- /dev/null +++ b/common/models/Log.php @@ -0,0 +1,34 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public static function saveLog($admin_id,$type,$content) + { + $Log=new Log(); + $Log->admin_id=$admin_id; + $Log->type='同步互医'; + $Log->operate_time=date('Y-m-d H:i:s',time()); + $Log->content=$content; + $Log->mold=$type; + $Log->saveOrFail(); + } +} \ No newline at end of file diff --git a/common/models/Menu.php b/common/models/Menu.php new file mode 100644 index 0000000..191c09b --- /dev/null +++ b/common/models/Menu.php @@ -0,0 +1,9 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/Order.php b/common/models/Order.php new file mode 100644 index 0000000..47463e0 --- /dev/null +++ b/common/models/Order.php @@ -0,0 +1,146 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //接诊状态 + public static function accept_info($model) + { + $result = [ + 'status' => 0, + 'text' => '未知', + ]; + if($model->accept_status == OrderAcceptEnum::WAIT_ACCEPT){ + + $result['status'] = 1; + $result['text'] = '待接诊'; + $result['text_detail'] = '等待接诊中'; + + }elseif($model->accept_status == OrderAcceptEnum::ACCEPTING){ + + $result['status'] = 2; + $result['text'] = '咨询中'; + $result['text_detail'] = '正在接诊中'; + + }elseif($model->accept_status == OrderAcceptEnum::REFUSED || $model->accept_status == OrderAcceptEnum::OVER || $model->accept_status == OrderAcceptEnum::TIMEOUT_ACCEPT || $model->accept_status == OrderAcceptEnum::CANCEL){ + + $result['status'] = 3; + $result['text'] = '已结束'; + $result['text_detail'] = '问诊结束'; + + } + return $result; + } + + //订单状态 + public static function status_info($model) + { + $result = [ + 'status' => 0, + 'text' => '未知', + ]; + if($model->is_pay == 0 && $model->cancel_status == 0){ + //待支付 + + $result['status'] = OrderStatusEnum::WAIT_PAY; + $result['text'] = OrderStatusEnum::ARR[OrderStatusEnum::WAIT_PAY]; + + }elseif($model->is_pay == 1 && $model->cancel_status == 0 && $model->accept_status == OrderAcceptEnum::WAIT_ACCEPT){ + //待接诊 + + $result['status'] = OrderStatusEnum::WAIT_ACCEPT; + $result['text'] = OrderStatusEnum::ARR[OrderStatusEnum::WAIT_ACCEPT]; + + }elseif($model->is_pay == 1 && $model->cancel_status == 0 && $model->accept_status == OrderAcceptEnum::ACCEPTING){ + //咨询中 + + $result['status'] = OrderStatusEnum::ACCEPTING; + $result['text'] = OrderStatusEnum::ARR[OrderStatusEnum::ACCEPTING]; + + }elseif($model->is_pay == 1 && $model->cancel_status == 0 && $model->accept_status == OrderAcceptEnum::OVER && $model->is_comment == 0){ + //待评价 + + $result['status'] = OrderStatusEnum::WAIT_COMMENT; + $result['text'] = OrderStatusEnum::ARR[OrderStatusEnum::WAIT_COMMENT]; + + }elseif($model->is_pay == 1 && $model->cancel_status == 0 && $model->accept_status == OrderAcceptEnum::OVER && $model->is_comment == 1){ + //已完成 + + $result['status'] = OrderStatusEnum::COMPLETE; + $result['text'] = OrderStatusEnum::ARR[OrderStatusEnum::COMPLETE]; + + }elseif( $model->cancel_status == 1){ + //已取消 + + $result['status'] = OrderStatusEnum::CANCELED; + $result['text'] = OrderStatusEnum::ARR[OrderStatusEnum::CANCELED]; + + } + + return $result; + } + + //关联服务人员 + public function getServiceUser() + { + return $this->hasOne(ServiceUser::className(),['id'=>'su_id']); + } + + //关联医生信息 + public function getDocInfo() + { + return $this->hasOne(DoctorInfo::className(),['su_id'=>'su_id']); + } + + //关联问诊 + public function getInquiry() + { + return $this->hasOne(UserInquiry::className(),['id'=>'ui_id']); + } + + //关联用户 + public function getUser() + { + return $this->hasOne(User::className(),['id'=>'user_id']); + } + + //关联会话 + public function getSession() + { + return $this->hasOne(ImMessageSessionOrder::className(),['order_id'=>'id']); + } + + public function getVideo() + { + return $this->hasOne(OrderVideoInfo::className(), ['order_id' => 'id']); + } +} \ No newline at end of file diff --git a/common/models/OrderLog.php b/common/models/OrderLog.php new file mode 100644 index 0000000..2447e07 --- /dev/null +++ b/common/models/OrderLog.php @@ -0,0 +1,35 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 保存下单后的事件队列处理日志 + * @param $order_id + * @param $message + */ + public static function saveLog($order_id, $message) + { + $orderLog = new OrderLog(); + $orderLog->order_id = $order_id; + $orderLog->content = $message; + $orderLog->save(); + } +} diff --git a/common/models/OrderNumberChange.php b/common/models/OrderNumberChange.php new file mode 100644 index 0000000..3d2b0fb --- /dev/null +++ b/common/models/OrderNumberChange.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} diff --git a/common/models/OrderRefund.php b/common/models/OrderRefund.php new file mode 100644 index 0000000..5c98826 --- /dev/null +++ b/common/models/OrderRefund.php @@ -0,0 +1,26 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getOrder() + { + return $this->hasOne(Order::className(), ['id' => 'order_id']); + } +} \ No newline at end of file diff --git a/common/models/OrderVideoInfo.php b/common/models/OrderVideoInfo.php new file mode 100644 index 0000000..e23c2f7 --- /dev/null +++ b/common/models/OrderVideoInfo.php @@ -0,0 +1,27 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getOrder() + { + return $this->hasOne(Order::className(), ['id' => 'order_id']); + } +} \ No newline at end of file diff --git a/common/models/PatientVisitRecord.php b/common/models/PatientVisitRecord.php new file mode 100644 index 0000000..737406d --- /dev/null +++ b/common/models/PatientVisitRecord.php @@ -0,0 +1,29 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联医生信息 + public function getDocInfo() + { + return $this->hasOne(DoctorInfo::class,['su_id'=>'su_id']); + } +} \ No newline at end of file diff --git a/common/models/PaymentOrder.php b/common/models/PaymentOrder.php new file mode 100644 index 0000000..0034f2f --- /dev/null +++ b/common/models/PaymentOrder.php @@ -0,0 +1,21 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/PaymentPrescripOrder.php b/common/models/PaymentPrescripOrder.php new file mode 100644 index 0000000..9c06df9 --- /dev/null +++ b/common/models/PaymentPrescripOrder.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/PaymentPrescripRefund.php b/common/models/PaymentPrescripRefund.php new file mode 100644 index 0000000..40d24b4 --- /dev/null +++ b/common/models/PaymentPrescripRefund.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/PaymentProductOrder.php b/common/models/PaymentProductOrder.php new file mode 100644 index 0000000..30d5581 --- /dev/null +++ b/common/models/PaymentProductOrder.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/PaymentProductRefund.php b/common/models/PaymentProductRefund.php new file mode 100644 index 0000000..382b38f --- /dev/null +++ b/common/models/PaymentProductRefund.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/PaymentRefund.php b/common/models/PaymentRefund.php new file mode 100644 index 0000000..37b1f37 --- /dev/null +++ b/common/models/PaymentRefund.php @@ -0,0 +1,21 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/PaymentRegister.php b/common/models/PaymentRegister.php new file mode 100644 index 0000000..6454ed8 --- /dev/null +++ b/common/models/PaymentRegister.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/PaymentRegisterRefund.php b/common/models/PaymentRegisterRefund.php new file mode 100644 index 0000000..d5b8813 --- /dev/null +++ b/common/models/PaymentRegisterRefund.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/PharmacistIdentity.php b/common/models/PharmacistIdentity.php new file mode 100644 index 0000000..76ce0ac --- /dev/null +++ b/common/models/PharmacistIdentity.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/PharmacistPracticing.php b/common/models/PharmacistPracticing.php new file mode 100644 index 0000000..4c25ce6 --- /dev/null +++ b/common/models/PharmacistPracticing.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/common/models/PharmacistrInfo.php b/common/models/PharmacistrInfo.php new file mode 100644 index 0000000..843badf --- /dev/null +++ b/common/models/PharmacistrInfo.php @@ -0,0 +1,66 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + + public function getTitles() + { + return $this->hasOne(DoctorTitle::class,['id'=>'title_id']); + } + + public function getDepart() + { + return $this->hasOne(Department::class,['id'=>'depart_id']); + } + //关联医院 + public function getHospital() + { + return $this->hasMany(Hospital::class,['id'=>'hospital_id']); + } + + //关联院区 + public function getYardes() + { + return $this->hasMany(HospitalYard::class,['id'=>'yard_id']); + } + //关联执业 + public function getPractings() + { + return $this->hasOne(PharmacistPracticing::class,['su_id'=>'su_id']); + } + //关联身份认证 + public function getIdentity() + { + return $this->hasOne(PharmacistIdentity::class,['su_id'=>'su_id']); + } + + //关联用户 + public function getUser() + { + return $this->hasOne(ServiceUser::class,['id'=>'su_id']); + } + //关联门店 + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } +} \ No newline at end of file diff --git a/common/models/PhysicalPackage.php b/common/models/PhysicalPackage.php new file mode 100644 index 0000000..8ddf880 --- /dev/null +++ b/common/models/PhysicalPackage.php @@ -0,0 +1,32 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 分院关联 + * @return ActiveQuery + */ + public function getYardPhysical(): ActiveQuery + { + return $this->hasMany(HospitalYardPhysical::className(),['physical_id'=>'id']); + } +} diff --git a/common/models/PhysicalReserve.php b/common/models/PhysicalReserve.php new file mode 100644 index 0000000..f1e11c1 --- /dev/null +++ b/common/models/PhysicalReserve.php @@ -0,0 +1,50 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 分院关联 + * @return ActiveQuery + */ + public function getYard(): ActiveQuery + { + return $this->hasOne(HospitalYard::className(),['id'=>'yard_id']); + } + + /** + * 用户关联 + * @return ActiveQuery + */ + public function getUser(): ActiveQuery + { + return $this->hasOne(User::className(),['id'=>'user_id'])->select('id,mobile,nickname,idcard'); + } + + /** + * 体检套餐关联 + * @return ActiveQuery + */ + public function getPackage(): ActiveQuery + { + return $this->hasOne(PhysicalPackage::className(),['id'=>'physical_id']); + } +} diff --git a/common/models/PhysicalReserveTotal.php b/common/models/PhysicalReserveTotal.php new file mode 100644 index 0000000..014217a --- /dev/null +++ b/common/models/PhysicalReserveTotal.php @@ -0,0 +1,12 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + // public static function findIdentityByAccessToken($token, $type = null) + // { + // $platform = Platform::findOne(['token' => $token, 'status' => StatusEnum::ACTIVE]); + // if($platform){ + // return $platform->id; + // } + // return null; + // } + +} \ No newline at end of file diff --git a/common/models/PostageRules.php b/common/models/PostageRules.php new file mode 100644 index 0000000..6f39b1c --- /dev/null +++ b/common/models/PostageRules.php @@ -0,0 +1,60 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function decodeDetail() + { + $detail = json_decode($this->detail,true); + foreach ($detail as &$item) { + foreach ($item as &$value) { + if (is_numeric($value)) { + $value = floatval($value); + } + } + unset($value); + } + unset($item); + return $detail; + } + + public static function setStatus($id = null) + { + $model = static::findOne([ + 'id' => $id, + 'is_delete' => 0, + 'mall_id' => \Yii::$app->mallId, + ]); + if (!$model) { + throw new ApiException("运费规则不存在"); + } else { + PostageRules::updateAll(['status' => 0], [ + 'mall_id' => \Yii::$app->mallId, + ]); + $model->status = 1; + if ($model->save()) { + return []; + } else { + throw new ApiException($model->errors[0]); + } + } + } +} diff --git a/common/models/PrescripOrderLog.php b/common/models/PrescripOrderLog.php new file mode 100644 index 0000000..025e35c --- /dev/null +++ b/common/models/PrescripOrderLog.php @@ -0,0 +1,35 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 保存下单后的事件队列处理日志 + * @param $po_id + * @param $message + */ + public static function saveLog($po_id, $message) + { + $PrescripOrderLog = new PrescripOrderLog(); + $PrescripOrderLog->$po_id = $po_id; + $PrescripOrderLog->content = $message; + $PrescripOrderLog->save(); + } +} \ No newline at end of file diff --git a/common/models/PrescripOrderRefund.php b/common/models/PrescripOrderRefund.php new file mode 100644 index 0000000..d2892d9 --- /dev/null +++ b/common/models/PrescripOrderRefund.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/Prescription.php b/common/models/Prescription.php new file mode 100644 index 0000000..e3294d1 --- /dev/null +++ b/common/models/Prescription.php @@ -0,0 +1,143 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联用户 + public function getUser() + { + return $this->hasOne(User::class, ['id' => 'user_id']); + } + + //诊所 + public function getStore(){ + return $this->hasOne(Store::class, ['id' => 'store_id']); + } + //就诊人 + public function getPatients() + { + return $this->hasOne(UserPatient::class, ['id' => 'up_id']); + } + + + //就诊人 + public function getUserPatient() + { + return $this->hasOne(UserPatient::class, ['id' => 'up_id']); + } + + //医生 + public function getDoctorInfo() + { + return $this->hasOne(DoctorInfo::class, ['su_id' => 'su_id']); + } + + //登录用户 + public function getServiceUser() + { + return $this->hasOne(ServiceUser::class, ['id' => 'su_id']); + } + + //药师 + public function getPharmacistInfo() + { + return $this->hasOne(PharmacistrInfo::class, ['su_id' => 'pharmacist_id']); + } + + //挂号 + public function getRegister() + { + return $this->hasOne(Register::class, ['id' => 'register_id']); + } + + //导出处方 + public static function inventory($params,$store_id) + { + //统计时间范围 + if (!empty($params['start_time']) && !empty($params['end_time'])) { + $params['start_time'] = strtotime($params['start_time']); + $params['end_time'] = strtotime($params['end_time']); + } + else{ + $params['start_time'] = strtotime(date('Y-m-d')); + $params['end_time'] = strtotime(date('Y-m-d',strtotime("-31 day"))); + } + + $where = $andWhere = []; + if($store_id){ + $where['store_id'] = $store_id; + } + $where['is_deleted'] = 0; + $andWhere = ['between', 'yii_prescription.created_at', $params['start_time'], $params['end_time']]; + if($params['status']){ + $where['yii_prescription.status'] = $params['status']; + } + if (!empty($params['prescription_no'])) {//处方编号 + $where['yii_prescription.prescription_no'] = $params['prescription_no']; + } + $name = $params['name']; + if($name){ + $where['yii_user_patient.name'] = $name; + } + $doctor = $params['doctor']; + if($doctor){ + $where['yii_doctor_info.name'] = $doctor; + } + if (!empty($params['clinical_diagnose'])) {//临床诊断 + $where['yii_prescription.clinical_diagnose'] = $params['clinical_diagnose']; + } + if (!empty($params['is_dispense'])) {//是否配药 + $where['yii_prescription.is_dispense'] = $params['is_dispense']; + } + //查询数据 + $list=Prescription::find()->where($where)->andWhere($andWhere)->joinWith(['doctorInfo','userPatient'])->asArray()->all(); + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + + $inventory[$key]['prescription_no'] = $value['prescription_no']; + $inventory[$key]['doctor'] = $value['doctorInfo']['name']??'无'; + $inventory[$key]['patient'] = $value['userPatient']['name']??'无'; + + //订单状态 + if ($value['status']==0 ){ + $inventory[$key]['prescription_status'] ='待审核'; + }elseif ($value['status']==1){ + $inventory[$key]['prescription_status'] ='已通过'; + }elseif ($value['status']==2){ + $inventory[$key]['prescription_status'] ='未通过'; + }else{ + $inventory[$key]['prescription_status'] ='未知'; + } + + $inventory[$key]['total_pay_price'] = $value['total_pay_price']??'无'; + $inventory[$key]['is_dispense'] = $value['is_dispense']==0?'未取药':'已取药';//是否取药 + $inventory[$key]['created_at'] = date('Y-m-d H:i:s',$value['created_at']);//下单时间 + } + + }else{ + $inventory[0]['prescription_no']= '无数据导出'; + } + return $inventory; + } +} \ No newline at end of file diff --git a/common/models/PrescriptionChinese.php b/common/models/PrescriptionChinese.php new file mode 100644 index 0000000..3f1f95c --- /dev/null +++ b/common/models/PrescriptionChinese.php @@ -0,0 +1,42 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getPrescription(){ + return $this->hasOne(Prescription::class,['prescription_no'=>'prescription_no']); + } + + public function getPatients(){ + return $this->hasOne(UserPatient::class,['id'=>'up_id']); + } + + public function getDepart(){ + return $this->hasMany(DoctorInfo::class,['id'=>'su_id']); + } + + public function getDoctor(){ + return $this->hasOne(DoctorInfo::class,['su_id'=>'su_id']); + } + + public function getPharmacistInfo(){ + return $this->hasOne(PharmacistrInfo::class,['su_id'=>'pharmacist_id']); + } +} \ No newline at end of file diff --git a/common/models/PrescriptionGranular.php b/common/models/PrescriptionGranular.php new file mode 100644 index 0000000..3fc4e32 --- /dev/null +++ b/common/models/PrescriptionGranular.php @@ -0,0 +1,81 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getPrescription(){ + return $this->hasOne(Prescription::class,['prescription_no'=>'prescription_no']); + } + + public function getWestes(){ + return $this->hasOne(Drug::class,['id'=>'usage_dosage']); + } + public function getPrices(){ + + return $this->hasMany(Drug::class,['id'=>'drug_id']); + } + + public function getUsetime(){ + return $this->hasMany(DrugUseTime::class,['id'=>'time_id']); + } + public function getTypes(){ + + return $this->hasMany(DrugUseType::class,['id'=>'type_id']); + } + + public function getFrequency(){ + + return $this->hasMany(DrugUseFrequency::class,['id'=>'f_id']); + } + + /** + * 用户 + */ + public function getPatient(){ + return $this->hasMany(UserPatient::class,['id'=>'up_id']); + } + + /** + * 科室 + */ + public function getDepart(){ + return $this->hasMany(DoctorInfo::class,['id'=>'su_id']); + } + + /** + * 医生 + */ + public function getDoctor(){ + return $this->hasMany(DoctorInfo::class,['id'=>'su_id']); + } + + /** + * 就诊人 + */ + public function getPatients(){ + return $this->hasOne(UserPatient::class,['id'=>'up_id']); + } + + public function getPharmacistInfo(){ + return $this->hasOne(PharmacistrInfo::class,['su_id'=>'pharmacist_id']); + } + +} diff --git a/common/models/PrescriptionLog.php b/common/models/PrescriptionLog.php new file mode 100644 index 0000000..6a8fa29 --- /dev/null +++ b/common/models/PrescriptionLog.php @@ -0,0 +1,36 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 保存下单后的事件队列处理日志 + * @param $p_id + * @param $message + */ + public static function saveLog($p_id, $message) + { + $PrescriptionLog = new PrescriptionLog(); + $PrescriptionLog->p_id = $p_id; + $PrescriptionLog->content = $message; + $PrescriptionLog->save(); + } + +} \ No newline at end of file diff --git a/common/models/PrescriptionWest.php b/common/models/PrescriptionWest.php new file mode 100644 index 0000000..325f12b --- /dev/null +++ b/common/models/PrescriptionWest.php @@ -0,0 +1,80 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getPrescription(){ + return $this->hasOne(Prescription::class,['prescription_no'=>'prescription_no']); + } + public function getWestes(){ + return $this->hasOne(Drug::class,['id'=>'usage_dosage']); + } + public function getPrices(){ + + return $this->hasMany(Drug::class,['id'=>'drug_id']); + } + + public function getUsetime(){ + return $this->hasMany(DrugUseTime::class,['id'=>'time_id']); + } + public function getTypes(){ + + return $this->hasMany(DrugUseType::class,['id'=>'type_id']); + } + + public function getFrequency(){ + + return $this->hasMany(DrugUseFrequency::class,['id'=>'f_id']); + } + + /** + * 用户 + */ + public function getPatient(){ + return $this->hasMany(UserPatient::class,['id'=>'up_id']); + } + + /** + * 科室 + */ + public function getDepart(){ + return $this->hasMany(DoctorInfo::class,['id'=>'su_id']); + } + + /** + * 医生 + */ + public function getDoctor(){ + return $this->hasOne(DoctorInfo::class,['su_id'=>'su_id']); + } + + /** + * 就诊人 + */ + public function getPatients(){ + return $this->hasOne(UserPatient::class,['id'=>'up_id']); + } + + + public function getPharmacistInfo(){ + return $this->hasOne(PharmacistrInfo::class,['su_id'=>'pharmacist_id']); + } + +} diff --git a/common/models/ProcessRule.php b/common/models/ProcessRule.php new file mode 100644 index 0000000..cf78abd --- /dev/null +++ b/common/models/ProcessRule.php @@ -0,0 +1,27 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/ProcessRuleNote.php b/common/models/ProcessRuleNote.php new file mode 100644 index 0000000..be8cc91 --- /dev/null +++ b/common/models/ProcessRuleNote.php @@ -0,0 +1,27 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/ProductOrder.php b/common/models/ProductOrder.php new file mode 100644 index 0000000..c6614a5 --- /dev/null +++ b/common/models/ProductOrder.php @@ -0,0 +1,195 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联产品 + public function getOrderItems(){ + return $this->hasMany(ProductOrderItems::class, ['product_order_id' => 'id']); + } + //关联门店 + public function getStore() + { + return $this->hasOne(Store::class, ['id' => 'store_id']); + } + + //关联医生 + public function getDoctor() + { + return $this->hasOne(DoctorInfo::class, ['su_id' => 'su_id']); + } + + //关联快递单号 + public function getExpressNos() + { + return $this->hasOne(ExpressNos::class, ['id' => 'express_no_id']); + } + + //关联已通过审核的处方 + public function getApprovedPrescription(){ + return $this->hasOne(Prescription::class, ['id' => 'p_id'])->where(['yii_prescription.status' => 1]); + } + + //关联处方 + public function getPrescription() + { + return $this->hasOne(Prescription::class, ['id' => 'p_id']); + } + + //关联患者 + public function getUserPatient() + { + return $this->hasOne(UserPatient::class, ['id' => 'up_id']); + } + + //关联用户 + public function getUser() + { + return $this->hasOne(User::class, ['id' => 'user_id']); + } + + + // + public function getProductOrderRefund() + { + return $this->hasOne(ProductOrderRefund::class, ['order_id' => 'id']); + } + //get transaction_id + public static function getSHH($order_no=null) + { + return PaymentProductOrder::find()->where(['is_pay'=>1,'order_no'=>$order_no])->andWhere(['not', ['transaction_id' => null]])->one(); + } + //导出 + public static function inventory($params,$store_id) + { + + if($store_id){ + $where['store_id'] = $store_id; + } + $where = $andWhere = []; + //统计时间范围 + if (!empty($params['start_time']) && !empty($params['end_time'])) { + $start_time = strtotime($params['start_time']); + $end_time = strtotime($params['end_time']); + $andWhere = ['between', 'created_at', $start_time, $end_time]; + } + + if(isset($params['status']) && $params['status'] !== null && $params['status'] !== ""){ + if($params['status'] == 3){ + $where['status'] = [3,6,7]; + }else{ + $where['status'] = $params['status']; + } + } + if(isset($params['refund_status'])){ + $where['refund_status'] = $params['after_status']; + } +// return $data; + + //查询数据 + $list = ProductOrder::find()->where($where)->andWhere($andWhere)->with(['prescription', 'doctor','store'])->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if (!empty($list)) { + foreach ($list as $key => $value) { + $ProductOrder=self::getSHH($value['order_no']); + + $inventory[$key]['epl_order_no'] = "\t".$ProductOrder->transaction_id??'暂无';//易票联订单号 + $inventory[$key]['order_no'] = "\t" . $value['order_no'];//订单号 + $inventory[$key]['store'] = "\t" . $value['store']['name'];//诊所名称 + $content = $value['prescription']; + $item = []; + if ($content['prescription_type']==1 ||$content['prescription_type']==3){//中药 配方颗粒 + + $repice = json_decode($content['content'], true)['repice']; + foreach ($repice as $val) { + foreach (json_decode($val['content']) as $vv) { + $item['drug_name'] .= $vv->name . '|'; + $item['specification'] .= $vv->specification . '|' ?? '无' . '|'; + $item['source'] .= $vv->source . '|' ?? '无' . '|'; + $item['unit_price'] .= $vv->price . '|' ?? '无' . '|'; + } + } + } else {//西药 + + $repice = json_decode($content['content'], true)['repice']; + if(!empty($repice)){ + foreach ($repice as $val) { + $item['drug_name'] .= json_decode($val['content'], true)['drug_name'] . '|'; + $item['specification'] .= json_decode($val['content'], true)['specification'] . '|' ?? '无' . '|'; + $item['source'] .= json_decode($val['content'], true)['source'] . '|' ?? '无' . '|'; + $item['unit_price'] .= $val['total_price'] . '|' ?? '无' . '|'; + } + } + + } + + $inventory[$key]['drug_name'] = $item['drug_name']; + $inventory[$key]['specification'] = $item['specification'];//规格 + $inventory[$key]['source'] = $item['source'];//厂家 + $inventory[$key]['unit_price'] = $item['unit_price'];//单价 + + $inventory[$key]['process_price'] = $value['process_price']; + $inventory[$key]['treatement_price'] = $value['treatement_price']; + $inventory[$key]['items_price'] = $value['items_price']; + $inventory[$key]['market_price'] = $value['market_price']; + $inventory[$key]['total_price'] = $value['total_pay_price']; + $inventory[$key]['trans_expenses'] = $value['trans_expenses']; +// $inventory[$key]['drugstore'] = $value['drugStore']['name']; + $inventory[$key]['doctor'] = $value['doctor']['name']; + + //订单状态 + if ($value['status'] == 0) $inventory[$key]['status'] = '未支付'; + if ($value['status'] == 1) $inventory[$key]['status'] = '待发货'; + if ($value['status'] == 2) $inventory[$key]['status'] = '待收货'; + if ($value['status'] == 4) $inventory[$key]['status'] = '已退款'; + if ($value['status'] == 5) $inventory[$key]['status'] = '退款中'; + if ($value['status'] == 3 || $value['status'] == 6 || $value['status'] == 7) $inventory[$key]['status'] = '已完成'; + if ($value['status'] == 9) $inventory[$key]['status'] = '已取消'; + //售后 + if ($value['refund_status'] == 0) $inventory[$key]['after_status'] = '暂无'; + if ($value['refund_status'] == 1) $inventory[$key]['after_status'] = '申请退款'; + if ($value['refund_status'] == 2) $inventory[$key]['after_status'] = '同意退款'; + if ($value['refund_status'] == 3) $inventory[$key]['after_status'] = '已退款'; + if ($value['refund_status'] == 9) $inventory[$key]['after_status'] = '取消退款'; + + $inventory[$key]['created_at'] = date('Y-m-d H:i:s', $value['created_at']);//下单时间 + $inventory[$key]['accept_name'] = $value['express_name'];// json_decode($value['address'])->name; + $inventory[$key]['accept_tel'] = $value['express_mobile'];//json_decode($value['address'])->mobile; + $inventory[$key]['accept_address'] = $value['express_region'] . $value['express_address'];//json_decode($value['address'])->region; + //支付时间 + if ($value['pay_time']==0){ + $inventory[$key]['pay_time'] = '暂无'; + }else{ + $inventory[$key]['pay_time'] = date('Y-m-d H:i:s', $value['pay_time']); + } + } + } else { + $inventory[0]['product_order'] = '无数据导出'; + } + return $inventory; + } +} \ No newline at end of file diff --git a/common/models/ProductOrderItems.php b/common/models/ProductOrderItems.php new file mode 100644 index 0000000..f97fb89 --- /dev/null +++ b/common/models/ProductOrderItems.php @@ -0,0 +1,30 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + 'value' => new \yii\db\Expression('NOW()'), + ], + ]; + } + + public function getDrug(){ + return $this->hasOne(Drug::class,['id' => 'drug_id']); + } +} \ No newline at end of file diff --git a/common/models/ProductOrderLog.php b/common/models/ProductOrderLog.php new file mode 100644 index 0000000..34f1881 --- /dev/null +++ b/common/models/ProductOrderLog.php @@ -0,0 +1,36 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 保存下单后的事件队列处理日志 + * @param $p_id + * @param $message + */ + public static function saveLog($p_id, $message) + { + $ProductOrderLog = new ProductOrderLog(); + $ProductOrderLog->p_id = $p_id; + $ProductOrderLog->content = $message; + $ProductOrderLog->save(); + } + +} \ No newline at end of file diff --git a/common/models/ProductOrderRefund.php b/common/models/ProductOrderRefund.php new file mode 100644 index 0000000..cef9d54 --- /dev/null +++ b/common/models/ProductOrderRefund.php @@ -0,0 +1,27 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getOrder() + { + return $this->hasOne(ProductOrder::class,['id' => 'order_id']); + } +} \ No newline at end of file diff --git a/common/models/Reconciliation.php b/common/models/Reconciliation.php new file mode 100644 index 0000000..a2c4047 --- /dev/null +++ b/common/models/Reconciliation.php @@ -0,0 +1,82 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getDrugStoreDrug() + { + return $this->hasOne(DrugStoreDrug::class,['id'=>'drug_id']); + } + public function getDrug() + { + return $this->hasOne(Drug::class,['id'=>'drug_id']); + } + + public function getProductOrder() + { + return $this->hasOne(ProductOrder::class,['id'=>'order_id']); + } + //关联门店 + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } + + //导出对账单 + public static function inventory($params) + { + $su_id=\Yii::$app->user->id; + //统计时间范围 + if (!empty($params['date_max']) && !empty($params['date_min'])) { + $params['date_max'] = strtotime($params['date_max']); + $params['date_min'] = strtotime($params['date_min']); + } + else{ + $date_max = date('Y-m-d'); + $date_min = date('Y-m-d',strtotime("-31 day")); + } + + $data = [ + 'and', + ['between', 'created_at', $params['date_min'], $params['date_max']], + ['status' => $params['status']], + ]; + //查询数据 + $list=Reconciliation::find()->filterWhere($data)->with(['productOrder','drug','store'])->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + + $inventory[$key]['drug_name'] = $value['drug']['drug_name']; + $inventory[$key]['drug_number'] = $value['drug']['drug_number']??'无'; + $inventory[$key]['store'] = $value['store']['name']; + $inventory[$key]['number'] = $value['number']; + $inventory[$key]['total_buy_price'] = $value['total_buy_price']; + $inventory[$key]['total_price'] = $value['total_price']; + $inventory[$key]['pay_time'] = date('Y-m-d H:i:s',$value['pay_time'])??'暂无'; + } + + }else{ + $inventory[0]['prescription_no']= '无数据导出'; + } + return $inventory; + } +} \ No newline at end of file diff --git a/common/models/RefundAddress.php b/common/models/RefundAddress.php new file mode 100644 index 0000000..c845c73 --- /dev/null +++ b/common/models/RefundAddress.php @@ -0,0 +1,54 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + public function rules() + { + return [ + [['mall_id','address','address_detail','address_id'], 'required'], + [['mall_id', 'created_at', 'updated_at', 'is_delete'], 'integer'], + [['name'], 'string', 'max' => 65], + [['address', 'address_detail', 'mobile', 'remark'], 'string', 'max' => 255], + ]; + } + + public function beforeValidate() + { + $arr = DistrictArr::getArr(); + $area = $arr[$this->address_id]; + $city = $arr[$area['parent_id']]; + $province = $arr[$city['parent_id']]; + $this->address = json_encode([[$province['id'],$province['name']],[$city['id'],$city['name']],[$area['id'],$area['name']]]); + return parent::beforeValidate(); // TODO: Change the autogenerated stub + } + public function afterFind() + { + parent::afterFind(); // TODO: Change the autogenerated stub + if($this->address){ + $address = json_decode($this->address); + $this->full_address = $address[0][1].$address[1][1].$address[2][1].$this->address_detail; + $this->address_id =$address[2][0]; + } + } +} diff --git a/common/models/Region.php b/common/models/Region.php new file mode 100644 index 0000000..4240d02 --- /dev/null +++ b/common/models/Region.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/Register.php b/common/models/Register.php new file mode 100644 index 0000000..405110e --- /dev/null +++ b/common/models/Register.php @@ -0,0 +1,100 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + public function afterFind() + { + parent::afterFind(); + isset($this->created_at) && $this->created_at = date('Y-m-d H:i:s', $this->created_at); + isset($this->updated_at) && $this->updated_at = date('Y-m-d H:i:s', $this->updated_at); + } + //用户 + public function getUser(){ + return $this->hasOne(User::class,['id'=>'user_id']); + } + //门店 + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } + public function getDepart() + { + return $this->hasOne(Department::class,['id'=>'depart_id']); + } + public function getDoctor() + { + return $this->hasOne(DoctorInfo::class,['su_id'=>'service_user_id']); + } + //就诊人 + public function getPatient() + { + return $this->hasOne(UserPatient::class,['id'=>'user_patient_id']); + } + + public function getPrescription(){ + return $this->hasMany(Prescription::class, ['register_id' => 'id']); + } + //健康信息 + public function getHealthInquery() + { + return $this->hasOne(UserPatientHealthInquiry::class,['user_patient_id'=>'user_patient_id']); + } + //病历 + public function getCase() + { + return $this->hasOne(UserPatientCase::class,['register_id'=>'id']); + } + //导出 + public static function inventory($params) + { + $su_id=\Yii::$app->user->id; + //统计时间范围 + if(!empty($params['min']) && !empty($params['max'])){ + $ti = strtotime($params['max'])+3600*24; + }else{ + $date_max = date('Y-m-d'); + $date_min = date('Y-m-d',strtotime("-31 day")); + } + //查询数据 + $where = ''; + $map = "select user_patient_id, store_id, order_no, order_number, price,is_pay,refuse_reason from yii_register where service_user_id=$su_id"; + $list= Register::findBySql($map)->asArray()->all(); + + //把结果按照显示顺序存到返回的数组中 + if(!empty($list)){ + foreach ($list as $key => $value){ + $inventory[$key]['user_patient_id']= $value['user_patient_id']; + $inventory[$key]['store_id'] = $value['store_id']; + $inventory[$key]['order_no'] = $value['order_no']; + $inventory[$key]['order_number'] = $value['order_number']; + $inventory[$key]['price'] = $value['price']; + $inventory[$key]['is_pay'] = $value['is_pay']; + $inventory[$key]['refuse_reason'] = $value['refuse_reason']; + } + }else{ + $inventory[0]['register']= '无数据导出'; + } + return $inventory; + } +} \ No newline at end of file diff --git a/common/models/RegisterLog.php b/common/models/RegisterLog.php new file mode 100644 index 0000000..9a892fa --- /dev/null +++ b/common/models/RegisterLog.php @@ -0,0 +1,33 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public static function saveLog($id,$content) + { + $RegisterLog=new RegisterLog(); + $RegisterLog->register_id=$id; + $RegisterLog->content=$content; + $RegisterLog->created_at=time(); + $RegisterLog->updated_at=time(); + $RegisterLog->saveOrFail(); + } + +} \ No newline at end of file diff --git a/common/models/RegisterRefund.php b/common/models/RegisterRefund.php new file mode 100644 index 0000000..4a18b22 --- /dev/null +++ b/common/models/RegisterRefund.php @@ -0,0 +1,27 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getRegister() + { + return $this->hasOne(Register::class,['id'=>'register_id']); + } +} \ No newline at end of file diff --git a/common/models/ReplayTemplate.php b/common/models/ReplayTemplate.php new file mode 100644 index 0000000..e271119 --- /dev/null +++ b/common/models/ReplayTemplate.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/ReplayTemplateGroup.php b/common/models/ReplayTemplateGroup.php new file mode 100644 index 0000000..b1fd655 --- /dev/null +++ b/common/models/ReplayTemplateGroup.php @@ -0,0 +1,27 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getTemplates() + { + return $this->hasMany(ReplayTemplate::className(), ['group_id' => 'id']); + } +} \ No newline at end of file diff --git a/common/models/Role.php b/common/models/Role.php new file mode 100644 index 0000000..65aeb3e --- /dev/null +++ b/common/models/Role.php @@ -0,0 +1,25 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getAuthRole(){ + return $this->hasMany(AuthRole::class,['role_id'=>'id']); + } +} \ No newline at end of file diff --git a/common/models/RoleMenu.php b/common/models/RoleMenu.php new file mode 100644 index 0000000..3ce7296 --- /dev/null +++ b/common/models/RoleMenu.php @@ -0,0 +1,28 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/ServInfo.php b/common/models/ServInfo.php new file mode 100644 index 0000000..d02f604 --- /dev/null +++ b/common/models/ServInfo.php @@ -0,0 +1,47 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //关联职称 + public function getTitle() + { + return $this->hasOne(DoctorTitle::className(),['id'=>'title_id']); + } + + //关联科室 + public function getDepart() + { + return $this->hasOne(HospitalDepartment::className(),['id'=>'depart_id']); + } + + //关联医院 + public function getHospital() + { + return $this->hasOne(Hospital::className(),['id'=>'hospital_id']); + } + + //关联院区 + public function getYard() + { + return $this->hasOne(HospitalYard::className(),['id'=>'yard_id']); + } + +} \ No newline at end of file diff --git a/common/models/ServiceUser.php b/common/models/ServiceUser.php new file mode 100644 index 0000000..f27d991 --- /dev/null +++ b/common/models/ServiceUser.php @@ -0,0 +1,96 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 可覆盖 fields() 方法来增加、删除、重命名、重定义字段 + */ + public function fields() + { + $fields = parent::fields(); + // 删除一些包含敏感信息的字段 + unset($fields['password']); + return $fields; + } + + //关联基础信息-医生 + public function getDocInfo() + { + return $this->hasOne(DoctorInfo::className(),['su_id'=>'id']); + } + + //关联认证信息-医生 + public function getDocIdentity() + { + return $this->hasOne(DoctorIdentity::className(),['su_id'=>'id']); + } + + //关联执业信息-医生 + public function getDocPracticing() + { + return $this->hasOne(DoctorPracticing::className(),['su_id'=>'id']); + } + + //关联服务信息-医生 + public function getDocService() + { + return $this->hasOne(DoctorService::className(),['su_id'=>'id']); + } + + + //药师-关联基础信息 + public function getDrugInfo() + { + return $this->hasOne(PharmacistrInfo::className(),['su_id'=>'id']); + } + + //药师-关联认证信息 + public function getDrugIdentity() + { + return $this->hasOne(PharmacistIdentity::className(),['su_id'=>'id']); + } + + //药师-关联执业信息 + public function getDrugPracticing() + { + return $this->hasOne(PharmacistPracticing::className(),['su_id'=>'id']); + } + + //导医-关联基础信息 + public function getLeadInfo() + { + return $this->hasOne(LeadInfo::className(),['su_id'=>'id']); + } + + //客服-关联基础信息 + public function getServInfo() + { + return $this->hasOne(ServInfo::className(),['su_id'=>'id']); + } + + //关联门店 + public function getStore() + { + return $this->hasOne(StoreDoctor::className(),['su_id'=>'id']); + } + + +} \ No newline at end of file diff --git a/common/models/ServiceUserToken.php b/common/models/ServiceUserToken.php new file mode 100644 index 0000000..5ab3ec4 --- /dev/null +++ b/common/models/ServiceUserToken.php @@ -0,0 +1,64 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //登录检测token + public static function checkToken($token) + { + $pos = strrpos($token,'_'); + if(!$pos){ + return false; + } + $tokenInfo = self::find()->where([ + 'token' => $token + ])->one(); + if(!$tokenInfo || $tokenInfo->is_disable){ + return false; + } + $time = substr($token,$pos+1); + if($time + 30*24*60*60 < time()){ + return false; + } + return $tokenInfo; + } + + //创建token + public static function createToken($uid) + { + $token = \Yii::$app->security->generateRandomString().'_'.time(); + $model = new self(); + $model->su_id = $uid; + $model->token = $token; + if(!$model->save()){ + throw new Exception('登录失败'); + } + return $token; + } + + public static function disableToken($token) + { + $model = self::find()->where([ + 'token' => $token + ])->one(); + $model->is_disable = 1; + $model->save(); + } +} \ No newline at end of file diff --git a/common/models/Store.php b/common/models/Store.php new file mode 100644 index 0000000..62bc33d --- /dev/null +++ b/common/models/Store.php @@ -0,0 +1,62 @@ +TimestampBehavior::class, + 'attributes'=>[ + ActiveRecord::EVENT_BEFORE_INSERT=>['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE=>['updated_at'], + ] + ] + ]; + } + + //轮播图 + public function getNav(){ + return $this->hasMany(Nav::class, ['store_id' => 'id'])->andWhere(['is_delete' => 0])->orderBy('sort ASC,id ASC'); + } + //科室 + public function getDepartments(){ + //一个门店对应多个科室,一个科室对应多个门店 + return $this->hasMany(Department::class, ['id' => 'depart_id']) + ->viaTable(StoreDepartment::tableName(), ['store_id' => 'id']); + } + //关联仓库 + public function getDrugStore() + { + return $this->hasOne(DrugStore::class, ['id' => 'drugstore_id']); + } + + public function getChild() + { + return $this->hasMany(Department::class,['pid'=>'id']); + } + + public function getReconciliation() + { + return $this->hasMany(Reconciliation::class,['store_id'=>'id']); + } + + public function getAdmin() + { + return $this->hasOne(Admin::class,['uid'=>'uid']); + } + + public function getProvince() + { + return $this->hasOne(Region::class,['id'=>'province_id']); + } + public function getCity() + { + return $this->hasOne(Region::class,['id'=>'city_id']); + } +} \ No newline at end of file diff --git a/common/models/StoreDepartment.php b/common/models/StoreDepartment.php new file mode 100644 index 0000000..3bb7a40 --- /dev/null +++ b/common/models/StoreDepartment.php @@ -0,0 +1,22 @@ +TimestampBehavior::class, + 'attributes'=>[ + ActiveRecord::EVENT_BEFORE_INSERT=>['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE=>['updated_at'], + ] + ] + ]; + } +} \ No newline at end of file diff --git a/common/models/StoreDoctor.php b/common/models/StoreDoctor.php new file mode 100644 index 0000000..ca2976e --- /dev/null +++ b/common/models/StoreDoctor.php @@ -0,0 +1,34 @@ +TimestampBehavior::class, + 'attributes'=>[ + ActiveRecord::EVENT_BEFORE_INSERT=>['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE=>['updated_at'], + ] + ] + ]; + } + + + //关联服务端用户 + public function getServiceUser() + { + return $this->hasOne(ServiceUser::class,['id'=>'su_id']); + } + + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } +} \ No newline at end of file diff --git a/common/models/StoreUser.php b/common/models/StoreUser.php new file mode 100644 index 0000000..b2e9eaf --- /dev/null +++ b/common/models/StoreUser.php @@ -0,0 +1,38 @@ +TimestampBehavior::class, + 'attributes'=>[ + ActiveRecord::EVENT_BEFORE_INSERT=>['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE=>['updated_at'], + ] + ] + ]; + } + + //关联用户端用户 + public function getUser() + { + return $this->hasOne(User::class,['id'=>'user_id']); + } + + //关联门店 + public function getStore() + { + return $this->hasOne(Store::class,['id'=>'store_id']); + } + + public function getNav(){ + return $this->hasMany(Nav::class,['store_id'=>'store_id'])->andWhere(['id_delete' => 0])->orderBy('sort ASC,id ASC'); + } +} \ No newline at end of file diff --git a/common/models/SubAccountMenu.php b/common/models/SubAccountMenu.php new file mode 100644 index 0000000..1ec3336 --- /dev/null +++ b/common/models/SubAccountMenu.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} diff --git a/common/models/SystemConfig.php b/common/models/SystemConfig.php new file mode 100644 index 0000000..a294145 --- /dev/null +++ b/common/models/SystemConfig.php @@ -0,0 +1,24 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/SystemNotice.php b/common/models/SystemNotice.php new file mode 100644 index 0000000..f401b64 --- /dev/null +++ b/common/models/SystemNotice.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/User.php b/common/models/User.php new file mode 100644 index 0000000..4ffd586 --- /dev/null +++ b/common/models/User.php @@ -0,0 +1,59 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + /** + * 可覆盖 fields() 方法来增加、删除、重命名、重定义字段 + */ + public function fields() + { + $fields = parent::fields(); + // 删除一些包含敏感信息的字段 + unset($fields['session_key']); + return $fields; + } + + // 关联评论 + public function getComment(){ + return $this->hasMany(UserComment::className(),['u_id'=>'id']); + } + + /** + * 亲属 + */ + public function getAllRelative(){ + return $this->hasMany(UserRelative::className(),['u_id'=>'id']); + } + + /** + * 收货地址 + */ + public function getAddress() + { + return $this->hasMany(Address::className(),['user_id'=>'id']); + } + /** + * 收货地址 + */ + public function getUserPatient() + { + return $this->hasMany(UserPatient::className(),['user_id'=>'id']); + } +} \ No newline at end of file diff --git a/common/models/UserCollect.php b/common/models/UserCollect.php new file mode 100644 index 0000000..5572ec6 --- /dev/null +++ b/common/models/UserCollect.php @@ -0,0 +1,23 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + +} diff --git a/common/models/UserComment.php b/common/models/UserComment.php new file mode 100644 index 0000000..64bee47 --- /dev/null +++ b/common/models/UserComment.php @@ -0,0 +1,42 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + // 关联用户 + public function getUser() + { + return $this->hasOne(User::className(),['id'=>'user_id']); + } + + // 关联患者 + public function getUserPatient() + { + return $this->hasOne(UserPatient::className(),['id'=>'u_id']); + } + + public function afterFind() + { + parent::afterFind(); + isset($this->created_at) && $this->created_at = date('Y-m-d', $this->created_at); + isset($this->updated_at) && $this->updated_at = date('Y-m-d', $this->updated_at); + } +} \ No newline at end of file diff --git a/common/models/UserInquiry.php b/common/models/UserInquiry.php new file mode 100644 index 0000000..7e9c0e0 --- /dev/null +++ b/common/models/UserInquiry.php @@ -0,0 +1,21 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/UserPatient.php b/common/models/UserPatient.php new file mode 100644 index 0000000..dfbd9e1 --- /dev/null +++ b/common/models/UserPatient.php @@ -0,0 +1,69 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + //就诊人问诊健康信息 + public function getHealthInquiry() + { + return $this->hasOne(UserPatientHealthInquiry::className(),['up_id'=>'id'])->andWhere([ + 'is_delete' => 0 + ]); + } + + //中药处方 + public function getChinPrescrip() + { + return $this->hasOne(PrescriptionChinese::class,['up_id'=>'id']); + } + //西药处方 + public function getWestPrescrip() + { + return $this->hasOne(PrescriptionWest::class,['up_id'=>'id']); + } + + //处方 + public function getPrescrip() + { + return $this->hasOne(Prescription::class,['up_id'=>'id']); + } + + // 用户 + public function getUser() + { + return $this->hasOne(User::class,['user_id'=>'id']); + } + // 挂号 + public function getRegister() + { + return $this->hasOne(Register::class,['user_patient_id'=>'id']); + } + + // 病历 + public function getCase() + { + return $this->hasMany(UserPatientCase::class,['user_patient_id'=>'id']); + } + + //健康信息 + public function getHealth() + { + return $this->hasOne(UserPatientHealthInquiry::class,['user_patient_id'=>'id']); + } +} \ No newline at end of file diff --git a/common/models/UserPatientCase.php b/common/models/UserPatientCase.php new file mode 100644 index 0000000..3660b5f --- /dev/null +++ b/common/models/UserPatientCase.php @@ -0,0 +1,33 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function afterFind() + { + parent::afterFind(); + isset($this->created_at) && $this->created_at = date('Y-m-d H:i:s', $this->created_at); + isset($this->updated_at) && $this->updated_at = date('Y-m-d H:i:s', $this->updated_at); + } + public function getUserPatient() + { + return $this->hasMany(UserPatient::className(),['id'=>'user_patient_id']); + } +} \ No newline at end of file diff --git a/common/models/UserPatientHealthInquiry.php b/common/models/UserPatientHealthInquiry.php new file mode 100644 index 0000000..501b0ea --- /dev/null +++ b/common/models/UserPatientHealthInquiry.php @@ -0,0 +1,21 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/UserPatientIll.php b/common/models/UserPatientIll.php new file mode 100644 index 0000000..7f65a17 --- /dev/null +++ b/common/models/UserPatientIll.php @@ -0,0 +1,30 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + // 关联就诊人 + public function getUserPatient() + { + return $this->hasOne(UserPatient::class,['id'=>'up_id'])->andWhere([ + 'is_delete' => 0 + ]); + } +} \ No newline at end of file diff --git a/common/models/UserPatientRecord.php b/common/models/UserPatientRecord.php new file mode 100644 index 0000000..2243c7e --- /dev/null +++ b/common/models/UserPatientRecord.php @@ -0,0 +1,22 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/common/models/UserRelationship.php b/common/models/UserRelationship.php new file mode 100644 index 0000000..1650880 --- /dev/null +++ b/common/models/UserRelationship.php @@ -0,0 +1,10 @@ +hasMany(UserRelationship::className(),['id'=>'relative']); + } +} \ No newline at end of file diff --git a/common/models/WestRepice.php b/common/models/WestRepice.php new file mode 100644 index 0000000..640a743 --- /dev/null +++ b/common/models/WestRepice.php @@ -0,0 +1,43 @@ + TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + + public function getUsetime(){ + return $this->hasOne(DrugUseTime::class,['id'=>'time_id']); + } + + + public function getWestUnit(){ + return $this->hasOne(WestUnit::class,['id'=>'wu_id']); + } + + public function getUsetype(){ + + return $this->hasOne(DrugUseType::class,['id'=>'type_id']); + } + + public function getFrequency(){ + + return $this->hasOne(DrugUseFrequency::class,['id'=>'f_id']); + } +} \ No newline at end of file diff --git a/common/models/WestUnit.php b/common/models/WestUnit.php new file mode 100644 index 0000000..07b2f02 --- /dev/null +++ b/common/models/WestUnit.php @@ -0,0 +1,8 @@ + 150], + [['mobile'], 'string', 'max' => 20], + [['region', 'province','detail_address'], 'string', 'max' => 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'name' => 'Name', + 'mobile' => 'Mobile', + 'province' => 'Province', + 'city' => 'city', + 'area' => 'area', + 'region' => 'Region', + 'detail_address' => 'Detail Address', + 'is_default' => 'Is Default', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/Admin.php b/common/modelsgii/Admin.php new file mode 100644 index 0000000..9c6b9d8 --- /dev/null +++ b/common/modelsgii/Admin.php @@ -0,0 +1,79 @@ + 16], + [['password'], 'string', 'max' => 60], + [['salt', 'email'], 'string', 'max' => 32], + [['mobile'], 'string', 'max' => 15], + [['code'], 'string', 'max' => 30], + [['mobile','code'], 'unique'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'uid' => 'Uid', + 'username' => 'Username', + 'password' => 'Password', + 'role' => 'Role', + 'mall_id' => 'Mall ID', + 'salt' => 'Salt', + 'email' => 'Email', + 'mobile' => 'Mobile', + 'reg_time' => 'Reg Time', + 'reg_ip' => 'Reg Ip', + 'last_login_time' => 'Last register Time', + 'last_login_ip' => 'Last register Ip', + 'update_time' => 'Update Time', + 'is_sub' => 'Is Sub', + 'is_delete' => 'Is Delete', + 'status' => 'Status', + ]; + } +} diff --git a/common/modelsgii/AdminAccessToken.php b/common/modelsgii/AdminAccessToken.php new file mode 100644 index 0000000..9ea7756 --- /dev/null +++ b/common/modelsgii/AdminAccessToken.php @@ -0,0 +1,58 @@ + 60], + [['group'], 'string', 'max' => 100], + [['access_token'], 'unique'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'access_token' => 'Access Token', + 'admin_id' => 'Admin ID', + 'group' => 'Group', + 'status' => 'Status', + 'expired_at' => 'Expired At', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Attachment.php b/common/modelsgii/Attachment.php new file mode 100644 index 0000000..0508a98 --- /dev/null +++ b/common/modelsgii/Attachment.php @@ -0,0 +1,74 @@ + 128], + [['url', 'thumb_url'], 'string', 'max' => 2080], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'storage_id' => 'Storage ID', + 'attachment_group_id' => 'Attachment Group ID', + 'user_id' => 'User ID', + 'mall_id' => 'Mall ID', + 'mch_id' => '多商户id', + 'name' => 'Name', + 'size' => '大小:字节', + 'url' => 'Url', + 'thumb_url' => 'Thumb Url', + 'type' => '类型:1=图片,2=视频', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'deleted_at' => 'Deleted At', + 'is_delete' => 'Is Delete', + 'is_recycle' => '是否加入回收站 0.否|1.是', + ]; + } +} diff --git a/common/modelsgii/AttachmentGroup.php b/common/modelsgii/AttachmentGroup.php new file mode 100644 index 0000000..f43af4d --- /dev/null +++ b/common/modelsgii/AttachmentGroup.php @@ -0,0 +1,61 @@ + 64], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'mall_id' => 'Mall ID', + 'mch_id' => 'Mch ID', + 'name' => 'Name', + 'is_delete' => 'Is Delete', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'deleted_at' => 'Deleted At', + 'is_recycle' => '是否加入回收站 0.否|1.是', + 'type' => '0 图片 1商品', + ]; + } +} diff --git a/common/modelsgii/AuthItem.php b/common/modelsgii/AuthItem.php new file mode 100644 index 0000000..eb33294 --- /dev/null +++ b/common/modelsgii/AuthItem.php @@ -0,0 +1,102 @@ + 64], + [['name'], 'unique'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'name' => 'Name', + 'type' => 'Type', + 'description' => 'Description', + 'rule_name' => 'Rule Name', + 'data' => 'Data', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } + + /** + * Gets query for [[AuthItemChildren]]. + * + * @return \yii\db\ActiveQuery + */ + public function getAuthItemChildren() + { + return $this->hasMany(AuthItemChild::class, ['parent' => 'name']); + } + + /** + * Gets query for [[AuthItemChildren0]]. + * + * @return \yii\db\ActiveQuery + */ + public function getAuthItemChildren0() + { + return $this->hasMany(AuthItemChild::class, ['child' => 'name']); + } + + /** + * Gets query for [[Children]]. + * + * @return \yii\db\ActiveQuery + */ + public function getChildren() + { + return $this->hasMany(AuthItem::class, ['name' => 'child'])->viaTable('yii_auth_item_child', ['parent' => 'name']); + } + + /** + * Gets query for [[Parents]]. + * + * @return \yii\db\ActiveQuery + */ + public function getParents() + { + return $this->hasMany(AuthItem::class, ['name' => 'parent'])->viaTable('yii_auth_item_child', ['child' => 'name']); + } +} diff --git a/common/modelsgii/AuthItemChild.php b/common/modelsgii/AuthItemChild.php new file mode 100644 index 0000000..62c94b4 --- /dev/null +++ b/common/modelsgii/AuthItemChild.php @@ -0,0 +1,70 @@ + 64], + [['parent', 'child'], 'unique', 'targetAttribute' => ['parent', 'child']], + [['parent'], 'exist', 'skipOnError' => true, 'targetClass' => AuthItem::class, 'targetAttribute' => ['parent' => 'name']], + [['child'], 'exist', 'skipOnError' => true, 'targetClass' => AuthItem::class, 'targetAttribute' => ['child' => 'name']], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'parent' => 'Parent', + 'child' => 'Child', + ]; + } + + /** + * Gets query for [[Child0]]. + * + * @return \yii\db\ActiveQuery + */ + public function getChild0() + { + return $this->hasOne(AuthItem::class, ['name' => 'child']); + } + + /** + * Gets query for [[Parent0]]. + * + * @return \yii\db\ActiveQuery + */ + public function getParent0() + { + return $this->hasOne(AuthItem::class, ['name' => 'parent']); + } +} diff --git a/common/modelsgii/AuthRole.php b/common/modelsgii/AuthRole.php new file mode 100644 index 0000000..5a50cb2 --- /dev/null +++ b/common/modelsgii/AuthRole.php @@ -0,0 +1,48 @@ + 'ID', + 'role_id' => 'Role ID', + 'rule_id' => 'Rule Id', + 'status' => 'Status', + ]; + } +} diff --git a/common/modelsgii/AuthRule.php b/common/modelsgii/AuthRule.php new file mode 100644 index 0000000..67a21b2 --- /dev/null +++ b/common/modelsgii/AuthRule.php @@ -0,0 +1,61 @@ + 30], + [['path', 'component', 'redirect', 'icon', 'api_url'], 'string', 'max' => 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'pid' => 'Pid', + 'title' => 'Title', + 'path' => 'Path', + 'component' => 'Component', + 'redirect' => 'Redirect', + 'icon' => 'Icon', + 'api_url' => 'Api Url', + 'status' => 'Status', + ]; + } +} diff --git a/common/modelsgii/BaseConfig.php b/common/modelsgii/BaseConfig.php new file mode 100644 index 0000000..317d671 --- /dev/null +++ b/common/modelsgii/BaseConfig.php @@ -0,0 +1,60 @@ + 'ID', + 'store_id' => '门店ID', + 'type' => '类型', + 'end' => '区分端1用户端2服务端', + 'desc' => '描述', + 'content' => '内容', + 'chang_at' => '变更时间', + 'status' => '是否删除0否1是', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + ]; + } +} diff --git a/common/modelsgii/Callback.php b/common/modelsgii/Callback.php new file mode 100644 index 0000000..8a530a3 --- /dev/null +++ b/common/modelsgii/Callback.php @@ -0,0 +1,55 @@ + 50], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'content' => '回调内容', + 'type' => 'order下单回调,refund退款回调', + 'status' => '是否处理成功,1是成功', + 'message' => '失败原因', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/CashAccount.php b/common/modelsgii/CashAccount.php new file mode 100644 index 0000000..c1e8dbc --- /dev/null +++ b/common/modelsgii/CashAccount.php @@ -0,0 +1,64 @@ + 'ID', + 'user_id' => 'User ID', + 'able_cash' => 'Able Cash', + 'frozen_cash' => 'Frozen Cash', + 'withdrawn_cash' => 'Withdrawn Cash', + 'total_cash' => 'Total Cash', + 'wait_cash' => 'Wait Cash', + 'user_type' => 'User Type', + 'last_apply_time' => 'Last Apply Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/CashApply.php b/common/modelsgii/CashApply.php new file mode 100644 index 0000000..2c2a24a --- /dev/null +++ b/common/modelsgii/CashApply.php @@ -0,0 +1,67 @@ + 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'apply_cash' => 'Apply Cash', + 'true_cash' => 'True Cash', + 'charge_cash' => 'Charge Cash', + 'check_id' => 'Check ID', + 'check_status' => 'Check Status', + 'check_result' => 'Check Result', + 'check_time' => 'Check Time', + 'apply_time' => 'Apply Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Categories.php b/common/modelsgii/Categories.php new file mode 100644 index 0000000..d1b610a --- /dev/null +++ b/common/modelsgii/Categories.php @@ -0,0 +1,52 @@ + 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'level' => 'Level', + 'pid' => 'Pid', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ChineseMedicine.php b/common/modelsgii/ChineseMedicine.php new file mode 100644 index 0000000..a56a5e5 --- /dev/null +++ b/common/modelsgii/ChineseMedicine.php @@ -0,0 +1,62 @@ + 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'drug_id' => '药品ID', + 'name' => '名字', + 'number' => '数量', + 'order' => '先下后下', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } + + public function getUnit(){ + return $this->hasOne(WestUnit::class,['id' => 'unit'])->select('id,name'); + } + + public function getUseWay(){ + return $this->hasOne(DrugUseWay::class,['id' => 'order'])->select('id,name'); + } +} diff --git a/common/modelsgii/ChineseRepice.php b/common/modelsgii/ChineseRepice.php new file mode 100644 index 0000000..a53cd4d --- /dev/null +++ b/common/modelsgii/ChineseRepice.php @@ -0,0 +1,71 @@ + 500], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'content' => 'Content', + 'deployment' => 'Deployment', + 'dosage' => 'Dosage', + 'consumption' => 'Consumption', + 'usage' => 'Usage', + 'volume' => 'Volume', + 'is_deepfry' => 'Is Deepfry', + 'cm_id' => 'Cm ID', + 'drug_ids' => '药品ids', + 'total_price' => 'Total Price', + 'remark' => 'Remark', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Config.php b/common/modelsgii/Config.php new file mode 100644 index 0000000..9e5c35d --- /dev/null +++ b/common/modelsgii/Config.php @@ -0,0 +1,70 @@ +4,'max' => 30], + [['title'], 'string','min'=>4,'max' => 50], + [['extra'], 'string', 'max' => 255], + [['remark'], 'string', 'max' => 100], + [['name'], 'unique'], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => '配置标识', + 'type' => '配置类型', + 'title' => '配置说明', + 'group' => '分组', + 'extra' => '扩展', + 'remark' => '说明文字', + 'create_time' => '创建时间', + 'update_time' => '更新时间', + 'status' => '状态', + 'value' => '配置值', + 'sort' => '排序', + ]; + } +} diff --git a/common/modelsgii/Department.php b/common/modelsgii/Department.php new file mode 100644 index 0000000..f19c937 --- /dev/null +++ b/common/modelsgii/Department.php @@ -0,0 +1,55 @@ + 50], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'pid' => 'Pid', + 'level' => 'Level', + 'feature' => 'Feature', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DiagnoseCommon.php b/common/modelsgii/DiagnoseCommon.php new file mode 100644 index 0000000..b250520 --- /dev/null +++ b/common/modelsgii/DiagnoseCommon.php @@ -0,0 +1,50 @@ + 'ID', + 'su_id' => 'Su ID', + 'content' => '医嘱内容', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Disease.php b/common/modelsgii/Disease.php new file mode 100644 index 0000000..958293a --- /dev/null +++ b/common/modelsgii/Disease.php @@ -0,0 +1,53 @@ + 50], + [['diagnose_code','major_number','ref_number'],'string'] + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DiseaseCommon.php b/common/modelsgii/DiseaseCommon.php new file mode 100644 index 0000000..1468cb6 --- /dev/null +++ b/common/modelsgii/DiseaseCommon.php @@ -0,0 +1,49 @@ + 'ID', + 'su_id' => 'Su ID', + 'disease_id' => 'Disease ID', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DocPhaImgs.php b/common/modelsgii/DocPhaImgs.php new file mode 100644 index 0000000..4d62dcc --- /dev/null +++ b/common/modelsgii/DocPhaImgs.php @@ -0,0 +1,62 @@ + 160], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'id_image' => '身份证照片', + 'work_license' => '工作照', + 'qualification' => '工作资格证书', + 'practicing_certificate' => '执业证书', + 'title_certificate' => '职称证书', + 'su_id' => '用户id', + 'audit_status' => '0未审核,1已审核', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorApply.php b/common/modelsgii/DoctorApply.php new file mode 100644 index 0000000..e6dbd76 --- /dev/null +++ b/common/modelsgii/DoctorApply.php @@ -0,0 +1,53 @@ + 'ID', + 'service_user_id' => 'Service User ID', + 'status' => 'Status', + 'is_delete' => 'Is Delete', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorArticle.php b/common/modelsgii/DoctorArticle.php new file mode 100644 index 0000000..8d66019 --- /dev/null +++ b/common/modelsgii/DoctorArticle.php @@ -0,0 +1,71 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'type' => 'Type', + 'cid' => 'Cid', + 'su_id' => '医生ID', + 'cover' => '封面', + 'title' => '标题', + 'intro' => '简介', + 'content' => '内容', + 'read_num' => '阅读量', + 'collection' => 'Collection', + 'is_draft' => '是否草稿', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/DoctorCommon.php b/common/modelsgii/DoctorCommon.php new file mode 100644 index 0000000..7c87303 --- /dev/null +++ b/common/modelsgii/DoctorCommon.php @@ -0,0 +1,50 @@ + 'ID', + 'su_id' => 'Su ID', + 'drug_id' => 'Drug ID', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorIdentity.php b/common/modelsgii/DoctorIdentity.php new file mode 100644 index 0000000..b804069 --- /dev/null +++ b/common/modelsgii/DoctorIdentity.php @@ -0,0 +1,59 @@ + 'ID', + 'su_id' => '关联医生', + 'card_up' => '身份证正面', + 'card_down' => '身份证反面', + 'work_avator' => '工作照', + 'sign_type' => '签章类型1电子2手写', + 'sign_image' => '签章图片', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorInfo.php b/common/modelsgii/DoctorInfo.php new file mode 100644 index 0000000..3237a41 --- /dev/null +++ b/common/modelsgii/DoctorInfo.php @@ -0,0 +1,94 @@ + 255], + [['name'], 'string', 'max' => 50], + [['mobile'], 'string', 'max' => 30], + [['idcard'], 'string', 'max' => 20], + [['store_id'], 'string', 'max' => 100], + [['good_at', 'intro', 'qr_code'], 'string', 'max' => 500], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => 'Su ID', + 'avatar' => 'Avatar', + 'name' => 'Name', + 'mobile' => 'Mobile', + 'idcard' => 'Idcard', + 'store_id' => 'Store ID', + 'hospital_id' => 'Hospital ID', + 'yard_id' => 'Yard ID', + 'depart_id' => 'Depart ID', + 'title_id' => 'Title ID', + 'identity' => 'Identity', + 'good_at' => 'Good At', + 'intro' => 'Intro', + 'qr_code' => 'Qr Code', + 'star' => 'Star', + 'average_response' => 'Average Response', + 'inquiries' => 'Inquiries', + 'applause_rate' => 'Applause Rate', + 'reception_rate' => 'Reception Rate', + 'grade' => 'Grade', + 'radio' => 'Radio', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorNotice.php b/common/modelsgii/DoctorNotice.php new file mode 100644 index 0000000..5264573 --- /dev/null +++ b/common/modelsgii/DoctorNotice.php @@ -0,0 +1,57 @@ + 'ID', + 'su_id' => '医生id', + 'close_notice' => '停诊公告 0关闭1开启', + 'content' => '公告内容', + 'start_time' => 'Start Time', + 'end_time' => 'End Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorPatient.php b/common/modelsgii/DoctorPatient.php new file mode 100644 index 0000000..b79f4d9 --- /dev/null +++ b/common/modelsgii/DoctorPatient.php @@ -0,0 +1,62 @@ + 'ID', + 'user_id' => '用户ID', + 'su_id' => '医生ID', + 'up_id' => '患者ID', + 'name' => '真实姓名', + 'avatar' => '头像', + 'id_card' => '身份证', + 'sex' => '0默认1男2女', + 'mobile' => '手机号', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + ]; + } +} diff --git a/common/modelsgii/DoctorPatientRemark.php b/common/modelsgii/DoctorPatientRemark.php new file mode 100644 index 0000000..686379a --- /dev/null +++ b/common/modelsgii/DoctorPatientRemark.php @@ -0,0 +1,53 @@ + 'ID', + 'su_id' => 'Su ID', + 'up_id' => 'Up ID', + 'remark' => '备注', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorPracticing.php b/common/modelsgii/DoctorPracticing.php new file mode 100644 index 0000000..0cdb8b5 --- /dev/null +++ b/common/modelsgii/DoctorPracticing.php @@ -0,0 +1,55 @@ + 'ID', + 'su_id' => '关联医生', + 'qualification' => '医师资格证书', + 'practicing' => '医师执业证书', + 'title' => '职称证书', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorService.php b/common/modelsgii/DoctorService.php new file mode 100644 index 0000000..fdf3a85 --- /dev/null +++ b/common/modelsgii/DoctorService.php @@ -0,0 +1,53 @@ + 'ID', + 'su_id' => '关联服务用户id', + 'register_status' => '是否开通挂号', + 'register_price' => '挂号金额', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorTagIll.php b/common/modelsgii/DoctorTagIll.php new file mode 100644 index 0000000..8234103 --- /dev/null +++ b/common/modelsgii/DoctorTagIll.php @@ -0,0 +1,53 @@ + 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => '医生id', + 'name' => 'Name', + 'is_default' => '是否默认 0否1是', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DoctorTitle.php b/common/modelsgii/DoctorTitle.php new file mode 100644 index 0000000..59310a2 --- /dev/null +++ b/common/modelsgii/DoctorTitle.php @@ -0,0 +1,49 @@ + 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => '职称', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Drug.php b/common/modelsgii/Drug.php new file mode 100644 index 0000000..22ee988 --- /dev/null +++ b/common/modelsgii/Drug.php @@ -0,0 +1,107 @@ + 100], + [['pinyin_simple'], 'string', 'max' => 50], + [['type'], 'string', 'max' => 20], + [['small_info'], 'string', 'max' => 150], + [['function'], 'string', 'max' => 500], + [['specification'], 'string', 'max' => 30], + [['bar_code','usage'], 'string', 'max' => 300], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'drug_name' => 'Drug Name', + 'pinyin_simple' => '拼音首拼', + 'source' => 'Source', + 'type' => 'Type', + 'is_otc' => 'Is Otc', + 'category_first' => 'Category First', + 'category_second' => 'Category Second', + 'small_info' => 'Small Info', + 'info' => 'Info', + 'content' => 'Content', + 'usage' => 'Usage', + 'function' => 'Function', + 'specification' => 'Specification', + 'image' => 'Image', + 'time_id' => 'Time ID', + 'type_id' => 'Type ID', + 'frequency_id' => 'Frequency ID', + 'unit_id' => 'Unit ID', + 'number' => 'Number', + 'status' => 'Status', + 'drug_number' => 'Drug Number', + 'bar_code' => 'Bar Code', + 'guozi_no' => 'Guozi No', + 'drug_alias' => 'Drug Alias', + 'place' => 'Place', + 'decotion' => 'Decotion', + 'instruction' => '说明书', + 'updated_at' => 'Updated At', + 'created_at' => 'Created At', + ]; + } +} diff --git a/common/modelsgii/DrugCategories.php b/common/modelsgii/DrugCategories.php new file mode 100644 index 0000000..acf3fa1 --- /dev/null +++ b/common/modelsgii/DrugCategories.php @@ -0,0 +1,58 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'level' => 'Level', + 'parent_id' => 'Parent ID', + 'category_name' => 'Category Name', + 'sort' => 'Sort', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'deleted_at' => 'Deleted At', + ]; + } +} diff --git a/common/modelsgii/DrugDosage.php b/common/modelsgii/DrugDosage.php new file mode 100644 index 0000000..a7e5e37 --- /dev/null +++ b/common/modelsgii/DrugDosage.php @@ -0,0 +1,47 @@ + 'ID', + 'num' => 'Num', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DrugStoreDrug.php b/common/modelsgii/DrugStoreDrug.php new file mode 100644 index 0000000..63fffc0 --- /dev/null +++ b/common/modelsgii/DrugStoreDrug.php @@ -0,0 +1,59 @@ + 'ID', + 'drugstore_id' => 'Drugstore ID', + 'drug_id' => 'Drug ID', + 'type' => 'Type', + 'price' => 'Price', + 'stock' => 'Stock', + 'frozen_number' => 'Frozen Number', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DrugStoreRelations.php b/common/modelsgii/DrugStoreRelations.php new file mode 100644 index 0000000..29516d5 --- /dev/null +++ b/common/modelsgii/DrugStoreRelations.php @@ -0,0 +1,61 @@ + 'ID', + 'drug_id' => 'Drug ID', + 'store_id' => 'Store ID', + 'status' => 'Status', + 'is_forbid' => 'Is Forbid', + 'base_sales_volume' => 'Base Sales Volume', + 'true_sales_volume' => 'True Sales Volume', + 'total_sales_volume' => 'Total Sales Volume', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DrugUseFrequency.php b/common/modelsgii/DrugUseFrequency.php new file mode 100644 index 0000000..b62b3c1 --- /dev/null +++ b/common/modelsgii/DrugUseFrequency.php @@ -0,0 +1,49 @@ + 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DrugUseNum.php b/common/modelsgii/DrugUseNum.php new file mode 100644 index 0000000..925ab1c --- /dev/null +++ b/common/modelsgii/DrugUseNum.php @@ -0,0 +1,49 @@ + 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DrugUseTime.php b/common/modelsgii/DrugUseTime.php new file mode 100644 index 0000000..3446970 --- /dev/null +++ b/common/modelsgii/DrugUseTime.php @@ -0,0 +1,49 @@ + 20], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DrugUseType.php b/common/modelsgii/DrugUseType.php new file mode 100644 index 0000000..216e5bd --- /dev/null +++ b/common/modelsgii/DrugUseType.php @@ -0,0 +1,49 @@ + 20], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/DrugUseWay.php b/common/modelsgii/DrugUseWay.php new file mode 100644 index 0000000..ea398fb --- /dev/null +++ b/common/modelsgii/DrugUseWay.php @@ -0,0 +1,49 @@ + 20], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Drugstore.php b/common/modelsgii/Drugstore.php new file mode 100644 index 0000000..e5d816a --- /dev/null +++ b/common/modelsgii/Drugstore.php @@ -0,0 +1,51 @@ + 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'position' => 'Position', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ExamineLog.php b/common/modelsgii/ExamineLog.php new file mode 100644 index 0000000..e39f7bd --- /dev/null +++ b/common/modelsgii/ExamineLog.php @@ -0,0 +1,55 @@ + 'ID', + 'prescription_id' => '处方id', + 'pharmacist_id' => '药师id', + 'examine_status' => '审核状态', + 'reject_reason' => '拒绝原因', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ExpressCompanies.php b/common/modelsgii/ExpressCompanies.php new file mode 100644 index 0000000..8a92851 --- /dev/null +++ b/common/modelsgii/ExpressCompanies.php @@ -0,0 +1,59 @@ + 100], + [['code', 'type'], 'string', 'max' => 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'code' => 'Code', + 'type' => 'Type', + 'sort' => 'Sort', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'deleted_at' => 'Deleted At', + ]; + } +} diff --git a/common/modelsgii/ExpressDetails.php b/common/modelsgii/ExpressDetails.php new file mode 100644 index 0000000..91803a7 --- /dev/null +++ b/common/modelsgii/ExpressDetails.php @@ -0,0 +1,57 @@ + 'ID', + 'express_no_id' => 'Express No Id', + 'detail_at' => 'Mobile', + 'detail' => 'State', + 'status' => 'Status', + 'deleted_at' => 'Deleted At', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ExpressNos.php b/common/modelsgii/ExpressNos.php new file mode 100644 index 0000000..4442996 --- /dev/null +++ b/common/modelsgii/ExpressNos.php @@ -0,0 +1,63 @@ + 100], + [['express_company_code'], 'string', 'max' => 30], + [['express_no'], 'string', 'max' => 50], + [['mobile'], 'string', 'max' => 20], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'express_company_name' => 'Express Company Name', + 'express_company_code' => 'Express Company Code', + 'express_no' => 'Express No', + 'mobile' => 'Mobile', + 'state' => 'State', + 'sync_at' => 'Sync At', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/FollowDoctor.php b/common/modelsgii/FollowDoctor.php new file mode 100644 index 0000000..a53dc9c --- /dev/null +++ b/common/modelsgii/FollowDoctor.php @@ -0,0 +1,50 @@ + 'ID', + 'user_id' => 'User ID', + 'su_id' => 'Su ID', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/FollowUser.php b/common/modelsgii/FollowUser.php new file mode 100644 index 0000000..b770d61 --- /dev/null +++ b/common/modelsgii/FollowUser.php @@ -0,0 +1,50 @@ + 'ID', + 'su_id' => 'Su ID', + 'user_id' => 'User ID', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/FundWater.php b/common/modelsgii/FundWater.php new file mode 100644 index 0000000..7ee412e --- /dev/null +++ b/common/modelsgii/FundWater.php @@ -0,0 +1,68 @@ + 20], + [['order_no', 'refund_no'], 'string', 'max' => 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'store_id' => 'Store ID', + 'order_id' => 'Order ID', + 'order_type' => 'Order Type', + 'user_id' => 'User ID', + 'service_user_id' => 'Service User ID', + 'type' => 'Type', + 'price' => 'Price', + 'order_no' => 'Order No', + 'refund_no' => 'Refund No', + 'pay_type' => 'Pay Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/GranularMedicine.php b/common/modelsgii/GranularMedicine.php new file mode 100644 index 0000000..4b2c9ca --- /dev/null +++ b/common/modelsgii/GranularMedicine.php @@ -0,0 +1,63 @@ + 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'drug_id' => '药品ID', + 'name' => '名字', + 'number' => '数量', + 'order' => '1先下 2后下', + 'price' => '价格', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } + + public function getUnit(){ + return $this->hasOne(WestUnit::class,['id' => 'unit']); + } + + public function getUseWay(){ + return $this->hasOne(DrugUseWay::class,['id' => 'order']); + } +} diff --git a/common/modelsgii/GranularRepice.php b/common/modelsgii/GranularRepice.php new file mode 100644 index 0000000..b72f14e --- /dev/null +++ b/common/modelsgii/GranularRepice.php @@ -0,0 +1,69 @@ + 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'content' => 'Content', + 'deployment' => 'Deployment', + 'dosage' => 'Dosage', + 'consumption' => 'Consumption', + 'usage' => 'Usage', + 'volume' => 'Volume', + 'is_deepfry' => 'Is Deepfry', + 'gm_id' => 'Gm ID', + 'total_price' => 'Total Price', + 'remark' => 'Remark', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/HealthyNews.php b/common/modelsgii/HealthyNews.php new file mode 100644 index 0000000..dc5fa37 --- /dev/null +++ b/common/modelsgii/HealthyNews.php @@ -0,0 +1,58 @@ + 'ID', + 'author' => '作者', + 'title' => '标题', + 'image' => '图片', + 'intro' => '介绍', + 'content' => '详情', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Hospital.php b/common/modelsgii/Hospital.php new file mode 100644 index 0000000..6335f76 --- /dev/null +++ b/common/modelsgii/Hospital.php @@ -0,0 +1,52 @@ + 50], + [['position'], 'string', 'max' => 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => '医院名称', + 'position' => '位置', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/HospitalDepartmentIntro.php b/common/modelsgii/HospitalDepartmentIntro.php new file mode 100644 index 0000000..96a1571 --- /dev/null +++ b/common/modelsgii/HospitalDepartmentIntro.php @@ -0,0 +1,60 @@ + "string", 'yard_id' => "string", 'department_id' => "string", 'image' => "string", 'intro' => "string", 'content' => "string", 'created_at' => "string", 'updated_at' => "string"])] + public function attributeLabels(): array + { + return [ + 'id' => 'ID', + 'yard_id' => '医院id', + 'department_id' => '科室id', + 'image' => '科室图片', + 'intro' => '介绍', + 'content' => '详情', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/HospitalYard.php b/common/modelsgii/HospitalYard.php new file mode 100644 index 0000000..4347979 --- /dev/null +++ b/common/modelsgii/HospitalYard.php @@ -0,0 +1,54 @@ + 100], + [['position'], 'string', 'max' => 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => '院区名称', + 'position' => '院区位置', + 'hospital_id' => '医院id', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/HospitalYardDepartment.php b/common/modelsgii/HospitalYardDepartment.php new file mode 100644 index 0000000..2d42038 --- /dev/null +++ b/common/modelsgii/HospitalYardDepartment.php @@ -0,0 +1,50 @@ + 'ID', + 'yard_id' => '院区id', + 'depart_id' => '科室id', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/HospitalYardPhysical.php b/common/modelsgii/HospitalYardPhysical.php new file mode 100644 index 0000000..d348d8b --- /dev/null +++ b/common/modelsgii/HospitalYardPhysical.php @@ -0,0 +1,51 @@ + 'ID', + 'yard_id' => '医院id', + 'physical_id' => '体检套餐id', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ImBind.php b/common/modelsgii/ImBind.php new file mode 100644 index 0000000..fd2611a --- /dev/null +++ b/common/modelsgii/ImBind.php @@ -0,0 +1,50 @@ + 'ID', + 'user_id' => '用户id', + 'client_id' => '客户端id', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ImMessage.php b/common/modelsgii/ImMessage.php new file mode 100644 index 0000000..b5ea936 --- /dev/null +++ b/common/modelsgii/ImMessage.php @@ -0,0 +1,61 @@ + 'ID', + 'ims_id' => 'Ims ID', + 'user_id' => 'User ID', + 'service_id' => 'Service ID', + 'content' => 'Content', + 'read_status' => 'Read Status', + 'type' => 'Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/ImMessageSession.php b/common/modelsgii/ImMessageSession.php new file mode 100644 index 0000000..64ae72d --- /dev/null +++ b/common/modelsgii/ImMessageSession.php @@ -0,0 +1,58 @@ + 'ID', + 'user_id' => 'User ID', + 'service_id' => 'Service ID', + 'type' => 'Type', + 'status' => 'Status', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + 'in_time' => 'In Time', + ]; + } +} diff --git a/common/modelsgii/ImMessageSessionOrder.php b/common/modelsgii/ImMessageSessionOrder.php new file mode 100644 index 0000000..707389c --- /dev/null +++ b/common/modelsgii/ImMessageSessionOrder.php @@ -0,0 +1,50 @@ + 'ID', + 'ims_id' => 'Ims ID', + 'order_id' => 'Order ID', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/InquiryRefuseReason.php b/common/modelsgii/InquiryRefuseReason.php new file mode 100644 index 0000000..c7b1022 --- /dev/null +++ b/common/modelsgii/InquiryRefuseReason.php @@ -0,0 +1,52 @@ + 50], + [['reason_message'], 'string', 'max' => 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'reason' => 'Reason', + 'reason_message' => 'Reason Message', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/LeadInfo.php b/common/modelsgii/LeadInfo.php new file mode 100644 index 0000000..e71844d --- /dev/null +++ b/common/modelsgii/LeadInfo.php @@ -0,0 +1,68 @@ + 50], + [['avatar', 'card_up', 'card_down'], 'string', 'max' => 255], + [['mobile'], 'string', 'max' => 30], + [['idcard'], 'string', 'max' => 20], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => 'Su ID', + 'name' => 'Name', + 'avatar' => 'Avatar', + 'mobile' => 'Mobile', + 'idcard' => 'Idcard', + 'hospital_id' => 'Hospital ID', + 'depart_id' => 'Depart ID', + 'card_up' => 'Card Up', + 'card_down' => 'Card Down', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Ledger.php b/common/modelsgii/Ledger.php new file mode 100644 index 0000000..d6371e2 --- /dev/null +++ b/common/modelsgii/Ledger.php @@ -0,0 +1,67 @@ + 'ID', + 'order_id' => 'Order ID', + 'user_id' => 'User ID', + 'user_type' => 'User Type', + 'order_type' => 'order Type', + 'fee_type' => 'fee Type', + 'su_id' => 'Su ID', + 'drugstore_id' => 'Drugstore ID', + 'drug_id' => 'Drug ID', + 'money' => 'Money', + 'status' => 'Status', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/LedgerLog.php b/common/modelsgii/LedgerLog.php new file mode 100644 index 0000000..9eb8166 --- /dev/null +++ b/common/modelsgii/LedgerLog.php @@ -0,0 +1,64 @@ + 'ID', + 'order_id' => 'Order ID', + 'user_id' => 'User ID', + 'user_type' => 'User Type', + 'order_type' => 'order Type', + 'fee_type' => 'fee Type', + 'type' => 'Type', + 'amount' => 'Amount', + 'content' => 'Content', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Log.php b/common/modelsgii/Log.php new file mode 100644 index 0000000..7a20850 --- /dev/null +++ b/common/modelsgii/Log.php @@ -0,0 +1,58 @@ + 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'admin_id' => 'Admin ID', + 'type' => 'Type', + 'operate_time' => 'Operate Time', + 'content' => 'Content', + 'mold' => 'Mold', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/MedicalAdvice.php b/common/modelsgii/MedicalAdvice.php new file mode 100644 index 0000000..7c326d3 --- /dev/null +++ b/common/modelsgii/MedicalAdvice.php @@ -0,0 +1,58 @@ + 30], + [['idcard'], 'string', 'max' => 11], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => 'Su ID', + 'username' => '用户名称', + 'idcard' => '身份证号码', + 'hospital_id' => '医院id', + 'department_id' => '科室id', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Menu.php b/common/modelsgii/Menu.php new file mode 100644 index 0000000..c111d3e --- /dev/null +++ b/common/modelsgii/Menu.php @@ -0,0 +1,63 @@ + 50], + [['redirect'], 'string', 'max' => 255], + [['menuUrl'], 'unique'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'menuUrl' => '菜单地址', + 'menuName' => '菜单名称', + 'parentPath' => '上级路由', + 'routeName' => '路由name', + 'redirect' => '是否隐藏', + 'icon' => '菜单图标', + 'sort' => 'Sort', + 'cacheable' => '是否缓存', + 'hidden' => '是否隐藏', + 'affix' => '是否固定标题栏', + ]; + } +} diff --git a/common/modelsgii/Nav.php b/common/modelsgii/Nav.php new file mode 100644 index 0000000..63c9077 --- /dev/null +++ b/common/modelsgii/Nav.php @@ -0,0 +1,65 @@ + 500], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'pic' => 'Pic', + 'external_link' => 'External Link', + 'is_home' => 'Is Home', + 'home_time' => 'Home Time', + 'type' => 'Type', + 'sort' => 'Sort', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/Order.php b/common/modelsgii/Order.php new file mode 100644 index 0000000..e3765c4 --- /dev/null +++ b/common/modelsgii/Order.php @@ -0,0 +1,104 @@ + 50], + [['cancel_remark'], 'string', 'max' => 100], + [['refuse_reason'], 'string', 'max' => 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'su_id' => 'Su ID', + 'ui_id' => 'Ui ID', + 'type' => 'Type', + 'image_limit_status' => 'Image Limit Status', + 'image_limit_number' => 'Image Limit Number', + 'left_number' => 'Left Number', + 'order_no' => 'Order No', + 'total_pay_price' => 'Total Pay Price', + 'is_pay' => 'Is Pay', + 'pay_time' => 'Pay Time', + 'pay_type' => 'Pay Type', + 'cancel_status' => 'Cancel Status', + 'cancel_time' => 'Cancel Time', + 'cancel_remark' => 'Cancel Remark', + 'auto_cancel_time' => 'Auto Cancel Time', + 'auto_refund_time' => 'Auto Refund Time', + 'auto_over_time' => 'Auto Over Time', + 'over_time' => 'Over Time', + 'accept_status' => 'Accept Status', + 'accept_time' => 'Accept Time', + 'refuse_reason' => 'Refuse Reason', + 'refuse_time' => 'Refuse Time', + 'is_comment' => 'Is Comment', + 'refund_status' => 'Refund Status', + 'refund_time' => 'Refund Time', + 'comment_time' => 'Comment Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/OrderLog.php b/common/modelsgii/OrderLog.php new file mode 100644 index 0000000..15981a6 --- /dev/null +++ b/common/modelsgii/OrderLog.php @@ -0,0 +1,51 @@ + 500], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'order_id' => 'Order ID', + 'content' => 'Content', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/OrderNumberChange.php b/common/modelsgii/OrderNumberChange.php new file mode 100644 index 0000000..64e3e75 --- /dev/null +++ b/common/modelsgii/OrderNumberChange.php @@ -0,0 +1,52 @@ + 'ID', + 'order_id' => 'Order ID', + 'number' => 'Number', + 'type' => 'Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/OrderRefund.php b/common/modelsgii/OrderRefund.php new file mode 100644 index 0000000..d69925a --- /dev/null +++ b/common/modelsgii/OrderRefund.php @@ -0,0 +1,62 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => '关联用户', + 'order_id' => '关联订单', + 'refund_no' => '退款单号', + 'refund_price' => '退款金额', + 'remark' => '用户退款备注、说明', + 'is_refund' => '是否打款0是未打款1成功-1失败', + 'refund_time' => '打款时间', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/OrderVideoInfo.php b/common/modelsgii/OrderVideoInfo.php new file mode 100644 index 0000000..1732dd1 --- /dev/null +++ b/common/modelsgii/OrderVideoInfo.php @@ -0,0 +1,71 @@ + 'ID', + 'order_id' => '订单ID', + 'user_id' => '用户ID', + 'su_id' => '医生ID', + 'is_limit' => '是否限制通话时长(1限制2不限制)', + 'order_limit_minutes' => '订单限制总时长', + 'left_minutes' => '剩余总时长', + 'start_at' => '订单开始时间', + 'end_at' => '订单结束时间', + 'last_start_left_minutes' => '上次开始剩余时长', + 'last_start_at' => '上次一次开始时间', + 'last_limit_at' => '最后一次扣除时间', + 'info' => '明细信息', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + ]; + } +} diff --git a/common/modelsgii/OtherInfo.php b/common/modelsgii/OtherInfo.php new file mode 100644 index 0000000..621f725 --- /dev/null +++ b/common/modelsgii/OtherInfo.php @@ -0,0 +1,57 @@ + 'ID', + 'hospital_id' => 'Hospital ID', + 'service' => 'Service', + 'privacy' => 'Privacy', + 'qualifications' => 'Qualifications', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/Page.php b/common/modelsgii/Page.php new file mode 100644 index 0000000..bfa851b --- /dev/null +++ b/common/modelsgii/Page.php @@ -0,0 +1,57 @@ + 30], + [['title'], 'string', 'max' => 100], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'title' => 'Title', + 'content' => 'Content', + 'create_time' => 'Create Time', + 'update_time' => 'Update Time', + 'status' => 'Status', + ]; + } +} diff --git a/common/modelsgii/PatientVisitRecord.php b/common/modelsgii/PatientVisitRecord.php new file mode 100644 index 0000000..1841428 --- /dev/null +++ b/common/modelsgii/PatientVisitRecord.php @@ -0,0 +1,58 @@ + 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => '医生id', + 'up_id' => '就诊人id', + 'main_suit' => '主诉', + 'diagnose' => '诊断', + 'is_selection'=>'是否设置精选0否1是', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PayConfig.php b/common/modelsgii/PayConfig.php new file mode 100644 index 0000000..e7cfc92 --- /dev/null +++ b/common/modelsgii/PayConfig.php @@ -0,0 +1,57 @@ + 32], + [['name'], 'unique'], + [['pay_type'], 'unique'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'pay_type' => 'Pay Type', + 'status' => 'Status', + 'current_use' => 'Current Use', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentOrder.php b/common/modelsgii/PaymentOrder.php new file mode 100644 index 0000000..655dfdb --- /dev/null +++ b/common/modelsgii/PaymentOrder.php @@ -0,0 +1,60 @@ + 255], + [['order_no'], 'string', 'max' => 32], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'transaction_id' => 'Transaction ID', + 'order_no' => 'Order No', + 'pay_order_no' => '发起支付的order_no', + 'amount' => 'Amount', + 'is_pay' => '支付状态:0=未支付,1=已支付', + 'pay_type' => '支付方式:1=微信支付', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentPrescripOrder.php b/common/modelsgii/PaymentPrescripOrder.php new file mode 100644 index 0000000..b51f5dd --- /dev/null +++ b/common/modelsgii/PaymentPrescripOrder.php @@ -0,0 +1,60 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'transaction_id' => 'Transaction ID', + 'order_no' => 'Order No', + 'pay_order_no' => 'Pay Order No', + 'amount' => 'Amount', + 'is_pay' => 'Is Pay', + 'pay_type' => 'Pay Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentPrescripRefund.php b/common/modelsgii/PaymentPrescripRefund.php new file mode 100644 index 0000000..ba4e979 --- /dev/null +++ b/common/modelsgii/PaymentPrescripRefund.php @@ -0,0 +1,57 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'refund_no' => 'Refund No', + 'amount' => 'Amount', + 'is_pay' => 'Is Pay', + 'pay_type' => 'Pay Type', + 'out_trade_no' => 'Out Trade No', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentProductOrder.php b/common/modelsgii/PaymentProductOrder.php new file mode 100644 index 0000000..c8a15d6 --- /dev/null +++ b/common/modelsgii/PaymentProductOrder.php @@ -0,0 +1,60 @@ + 255], + [['order_no'], 'string', 'max' => 32], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'transaction_id' => 'Transaction ID', + 'order_no' => 'Order No', + 'pay_order_no' => 'Pay Order No', + 'amount' => 'Amount', + 'is_pay' => 'Is Pay', + 'pay_type' => 'Pay Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentProductRefund.php b/common/modelsgii/PaymentProductRefund.php new file mode 100644 index 0000000..5572c7c --- /dev/null +++ b/common/modelsgii/PaymentProductRefund.php @@ -0,0 +1,57 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'refund_no' => 'Refund No', + 'amount' => 'Amount', + 'is_pay' => 'Is Pay', + 'pay_type' => 'Pay Type', + 'out_order_no' => 'Out Order No', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentRefund.php b/common/modelsgii/PaymentRefund.php new file mode 100644 index 0000000..8ebb918 --- /dev/null +++ b/common/modelsgii/PaymentRefund.php @@ -0,0 +1,57 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'refund_no' => '退款单号', + 'amount' => '退款金额', + 'is_pay' => '支付状态 0--未支付|1--已支付', + 'pay_type' => '支付方式:1=微信支付', + 'out_trade_no' => '支付单号', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentRegister.php b/common/modelsgii/PaymentRegister.php new file mode 100644 index 0000000..e896079 --- /dev/null +++ b/common/modelsgii/PaymentRegister.php @@ -0,0 +1,61 @@ + 255], + [['order_no', 'pay_order_no'], 'string', 'max' => 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'transaction_id' => 'Transaction ID', + 'order_no' => 'Order No', + 'pay_order_no' => 'Pay Order No', + 'amount' => 'Amount', + 'is_pay' => 'Is Pay', + 'pay_type' => 'Pay Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PaymentRegisterRefund.php b/common/modelsgii/PaymentRegisterRefund.php new file mode 100644 index 0000000..c3f3db2 --- /dev/null +++ b/common/modelsgii/PaymentRegisterRefund.php @@ -0,0 +1,58 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'refund_no' => 'Refund No', + 'amount' => 'Amount', + 'is_pay' => 'Is Pay', + 'pay_type' => 'Pay Type', + 'out_trade_no' => 'Out Trade No', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Pharmacist.php b/common/modelsgii/Pharmacist.php new file mode 100644 index 0000000..0b54841 --- /dev/null +++ b/common/modelsgii/Pharmacist.php @@ -0,0 +1,57 @@ + 30], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'username' => 'Username', + 'hospital_id' => '医院id', + 'department_id' => '科室id', + 'title_id' => '职称id', + 'signature_style' => '签章样式 1电子签章,2手写签名', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PharmacistIdentity.php b/common/modelsgii/PharmacistIdentity.php new file mode 100644 index 0000000..cf39458 --- /dev/null +++ b/common/modelsgii/PharmacistIdentity.php @@ -0,0 +1,57 @@ + 'ID', + 'su_id' => '关联医生', + 'card_up' => '身份证正面', + 'card_down' => '身份证反面', + 'sign_type' => '签章类型1电子2手写', + 'sign_image' => '签章图片', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PharmacistInfo.php b/common/modelsgii/PharmacistInfo.php new file mode 100644 index 0000000..e79db51 --- /dev/null +++ b/common/modelsgii/PharmacistInfo.php @@ -0,0 +1,68 @@ + 50], + [['avatar'], 'string', 'max' => 255], + [['idcard'], 'string', 'max' => 20], + ['store_id','string'] + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => 'Su ID', + 'name' => 'Name', + 'avatar' => 'Avatar', + 'mobile' => 'Mobile', + 'idcard' => 'Idcard', + 'store_id' => 'Store ID', + 'depart_id' => 'Depart ID', + 'title_id' => 'Title ID', + 'type' => 'Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PharmacistPracticing.php b/common/modelsgii/PharmacistPracticing.php new file mode 100644 index 0000000..49a409a --- /dev/null +++ b/common/modelsgii/PharmacistPracticing.php @@ -0,0 +1,55 @@ + 'ID', + 'su_id' => '关联医生', + 'qualification' => '资格证书', + 'practicing' => '执业证书', + 'title' => '职称证书', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PhysicalPackage.php b/common/modelsgii/PhysicalPackage.php new file mode 100644 index 0000000..cf856a5 --- /dev/null +++ b/common/modelsgii/PhysicalPackage.php @@ -0,0 +1,61 @@ + 'ID', + 'name' => '标题', + 'image' => '图片', + 'price' => '价格', + 'intro' => '介绍', + 'content' => '项目详情', + 'service' => '服务须知', + 'type' => '类型', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PhysicalReserve.php b/common/modelsgii/PhysicalReserve.php new file mode 100644 index 0000000..0f40e83 --- /dev/null +++ b/common/modelsgii/PhysicalReserve.php @@ -0,0 +1,60 @@ + 'ID', + 'user_id' => '用户id', + 'yard_id' => '分院id', + 'physical_id' => '体检套餐id', + 'day' => '预约时间', + 'status' => '预约状态', + 'way' => '获取报告的方式', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PhysicalReserveTotal.php b/common/modelsgii/PhysicalReserveTotal.php new file mode 100644 index 0000000..ff802bc --- /dev/null +++ b/common/modelsgii/PhysicalReserveTotal.php @@ -0,0 +1,54 @@ + "string", 'yard_id' => "string", 'physical_id' => "string", 'day' => "string", 'num' => "string"])] + public function attributeLabels(): array + { + return [ + 'id' => 'ID', + 'yard_id' => '医院id', + 'physical_id' => '体检套餐id', + 'day' => '预约天', + 'num' => '已预约总数', + ]; + } +} diff --git a/common/modelsgii/Platform.php b/common/modelsgii/Platform.php new file mode 100644 index 0000000..7a8c15d --- /dev/null +++ b/common/modelsgii/Platform.php @@ -0,0 +1,53 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'token' => 'Token', + 'status' => 'Status', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At' + ]; + } +} diff --git a/common/modelsgii/PrescripOrderLog.php b/common/modelsgii/PrescripOrderLog.php new file mode 100644 index 0000000..b7dc9d6 --- /dev/null +++ b/common/modelsgii/PrescripOrderLog.php @@ -0,0 +1,50 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'po_id' => 'Po ID', + 'content' => 'Content', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PrescripOrderRefund.php b/common/modelsgii/PrescripOrderRefund.php new file mode 100644 index 0000000..cd9e45d --- /dev/null +++ b/common/modelsgii/PrescripOrderRefund.php @@ -0,0 +1,62 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'po_id' => 'Po ID', + 'refund_no' => 'Refund No', + 'refund_price' => 'Refund Price', + 'refund_time' => 'Refund Time', + 'remark' => 'Remark', + 'is_refund' => 'Is Refund', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Prescription.php b/common/modelsgii/Prescription.php new file mode 100644 index 0000000..18b542d --- /dev/null +++ b/common/modelsgii/Prescription.php @@ -0,0 +1,105 @@ + 255], + [['doctor_order'], 'string', 'max' => 200], + [['cr_ids', 'wr_ids', 'gr_ids'], 'string', 'max' => 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'prescription_no' => 'Prescription No', + 'content' => '处方快照', + 'su_id' => 'Su ID', + 'prescription_type' => '处方类型', + 'store_id' => '门店ID', + 'user_id' => 'User ID', + 'up_id' => 'Up ID', + 'status' => 'Status', + 'category' => 'Category', + 'doctor_order' => 'Doctor Order', + 'clinical_diagnose' => 'Clinical Diagnose', + 'first_view' => 'First View', + 'first_time' => 'First Time', + 'again_view' => 'Again View', + 'again_time' => 'Again Time', + 'type' => 'Type', + 'cr_ids' => 'Cr Ids', + 'wr_ids' => 'Wr Ids', + 'gr_ids' => 'Gr Ids', + 'order_type' => 'Order Type', + 'total_pay_price' => 'Total Pay Price', + 'is_pay' => 'Is Pay', + 'pay_time' => 'Pay Time', + 'pay_type' => 'Pay Type', + 'cancel_status' => 'Cancel Status', + 'cancel_time' => 'Cancel Time', + 'cancel_remark' => 'Cancel Remark', + 'refund_status' => 'Refund Status', + 'refund_time' => 'Refund Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PrescriptionChinese.php b/common/modelsgii/PrescriptionChinese.php new file mode 100644 index 0000000..b30fd3a --- /dev/null +++ b/common/modelsgii/PrescriptionChinese.php @@ -0,0 +1,92 @@ + 50], + [['clinical_diagnose', 'cr_ids'], 'string', 'max' => 100], + [['doctor_order'], 'string', 'max' => 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'su_id' => 'Su ID', + 'prescription_no' => 'Prescription No', + 'content' => 'Content', + 'clinical_diagnose' => 'Clinical Diagnose', + 'user_id' => 'User ID', + 'up_id' => 'Up ID', + 'store_id' => 'Store ID', + 'status' => 'Status', + 'category' => 'Category', + 'doctor_order' => 'Doctor Order', + 'doctor_sign' => 'Doctor Sign', + 'pharmacist_id' => 'Pharmacist ID', + 'pharmacist_sign' => 'Pharmacist Sign', + 'pharmacist_view_time' => 'Pharmacist View Time', + 'first_view' => 'First View', + 'first_time' => 'First Time', + 'again_view' => 'Again View', + 'again_time' => 'Again Time', + 'type' => 'Type', + 'cr_ids' => 'Cr Ids', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PrescriptionGranular.php b/common/modelsgii/PrescriptionGranular.php new file mode 100644 index 0000000..efb51e3 --- /dev/null +++ b/common/modelsgii/PrescriptionGranular.php @@ -0,0 +1,92 @@ + 50], + [['clinical_diagnose', 'gr_ids'], 'string', 'max' => 100], + [['doctor_order'], 'string', 'max' => 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'su_id' => 'Su ID', + 'prescription_no' => 'Prescription No', + 'content' => 'Content', + 'clinical_diagnose' => 'Clinical Diagnose', + 'user_id' => 'User ID', + 'up_id' => 'Up ID', + 'store_id' => 'Store ID', + 'status' => 'Status', + 'category' => 'Category', + 'doctor_order' => 'Doctor Order', + 'doctor_sign' => 'Doctor Sign', + 'pharmacist_id' => 'Pharmacist ID', + 'pharmacist_sign' => 'Pharmacist Sign', + 'pharmacist_view_time' => 'Pharmacist View Time', + 'first_view' => 'First View', + 'first_time' => 'First Time', + 'again_view' => 'Again View', + 'again_time' => 'Again Time', + 'type' => 'Type', + 'gr_ids' => 'Gr Ids', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PrescriptionLog.php b/common/modelsgii/PrescriptionLog.php new file mode 100644 index 0000000..a27b47d --- /dev/null +++ b/common/modelsgii/PrescriptionLog.php @@ -0,0 +1,51 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'p_id' => 'P ID', + 'content' => 'Content', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/PrescriptionWest.php b/common/modelsgii/PrescriptionWest.php new file mode 100644 index 0000000..7967463 --- /dev/null +++ b/common/modelsgii/PrescriptionWest.php @@ -0,0 +1,92 @@ + 50], + [['doctor_order'], 'string', 'max' => 200], + [['clinical_diagnose'], 'string', 'max' => 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'store_id' => 'Store ID', + 'su_id' => 'Su ID', + 'user_id' => 'User ID', + 'up_id' => 'Up ID', + 'doctor_order' => 'Doctor Order', + 'prescription_no' => 'Prescription No', + 'content' => 'Content', + 'clinical_diagnose' => 'Clinical Diagnose', + 'status' => 'Status', + 'category' => 'Category', + 'doctor_sign' => 'Doctor Sign', + 'pharmacist_sign' => 'Pharmacist Sign', + 'pharmacist_id' => 'Pharmacist ID', + 'pharmacist_view_time' => 'Pharmacist View Time', + 'first_view' => 'First View', + 'first_time' => 'First Time', + 'again_view' => 'Again View', + 'again_time' => 'Again Time', + 'wr_ids' => 'Wr Ids', + 'type' => 'Type', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ProcessRule.php b/common/modelsgii/ProcessRule.php new file mode 100644 index 0000000..6e453aa --- /dev/null +++ b/common/modelsgii/ProcessRule.php @@ -0,0 +1,62 @@ + 50], + [['name'], 'unique'], + [['calc_method'],'in','range' => [1,2,3]], + ['price','double'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'pid' => 'Pid', + 'name' => 'Name', + 'calc_method' => 'calc_method', + 'price' => 'price', + 'unit' => 'unit', + 'created_at' => '创建时间', + ]; + } +} diff --git a/common/modelsgii/ProcessRuleNote.php b/common/modelsgii/ProcessRuleNote.php new file mode 100644 index 0000000..39f6b8c --- /dev/null +++ b/common/modelsgii/ProcessRuleNote.php @@ -0,0 +1,53 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'rule_id' => 'rule id', + 'note' => '备注', + 'created_at' => '创建时间', + ]; + } +} diff --git a/common/modelsgii/ProductOrder.php b/common/modelsgii/ProductOrder.php new file mode 100644 index 0000000..784ee6f --- /dev/null +++ b/common/modelsgii/ProductOrder.php @@ -0,0 +1,80 @@ + 50], + [['cancel_remark'], 'string', 'max' => 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => 'Su ID', + 'user_id' => 'User ID', + 'up_id' => 'Up ID', + 'order_no' => 'Order No', + 'p_id' => 'P ID', + 'type' => 'Type', + 'is_pay' => 'Is Pay', + 'total_pay_price' => 'Total Pay Price', + 'pay_time' => 'Pay Time', + 'cancel_status' => 'Cancel Status', + 'cancel_time' => 'Cancel Time', + 'cancel_remark' => 'Cancel Remark', + 'refund_status' => 'Refund Status', + 'refund_time' => 'Refund Time', + 'status' => 'Status', + 'sync_order_no' => '互医的订单号', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ProductOrderItems.php b/common/modelsgii/ProductOrderItems.php new file mode 100644 index 0000000..fe9754d --- /dev/null +++ b/common/modelsgii/ProductOrderItems.php @@ -0,0 +1,44 @@ + 'id', + 'product_order_id' => 'product_order_id', + 'drug_id' => 'drug_id', + 'drug_image' => 'drug_image', + 'number' => 'number', + 'price' => 'price', + 'drug_name' => 'drug_name', + 'small_info' => 'small_info', + 'created_at' => 'created_at', + 'updated_at' => 'updated_at', + ]; + } +} diff --git a/common/modelsgii/ProductOrderLog.php b/common/modelsgii/ProductOrderLog.php new file mode 100644 index 0000000..62579f4 --- /dev/null +++ b/common/modelsgii/ProductOrderLog.php @@ -0,0 +1,51 @@ + 'ID', + 'p_id' => 'P ID', + 'content' => 'Content', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ProductOrderRefund.php b/common/modelsgii/ProductOrderRefund.php new file mode 100644 index 0000000..a5e9b36 --- /dev/null +++ b/common/modelsgii/ProductOrderRefund.php @@ -0,0 +1,64 @@ + 255], + ['check_result', 'string', 'max' => 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'order_id' => 'Order ID', + 'refund_no' => 'Refund No', + 'refund_price' => 'Refund Price', + 'remark' => 'Remark', + 'is_refund' => 'Is Refund', + 'refund_time' => 'Refund Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Reconciliation.php b/common/modelsgii/Reconciliation.php new file mode 100644 index 0000000..5045461 --- /dev/null +++ b/common/modelsgii/Reconciliation.php @@ -0,0 +1,65 @@ + 'ID', + 'store_id' => 'Store ID', + 'order_id' => 'Order ID', + 'drug_id' => 'Drug ID', + 'drug_type' => 'Drug Type', + 'number' => 'Number', + 'pay_time' => 'Pay Time', + 'total_buy_price' => 'Total Buy Price', + 'total_price' => 'Total Price', + 'status' => 'Status', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} \ No newline at end of file diff --git a/common/modelsgii/RefundReason.php b/common/modelsgii/RefundReason.php new file mode 100644 index 0000000..ced7a5b --- /dev/null +++ b/common/modelsgii/RefundReason.php @@ -0,0 +1,49 @@ + 50], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'reason' => 'Reason', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Region.php b/common/modelsgii/Region.php new file mode 100644 index 0000000..fd393a8 --- /dev/null +++ b/common/modelsgii/Region.php @@ -0,0 +1,55 @@ + 200], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'pid' => 'Pid', + 'level' => 'Level', + 'express_fee' => 'Express Fee', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Register.php b/common/modelsgii/Register.php new file mode 100644 index 0000000..fe3870f --- /dev/null +++ b/common/modelsgii/Register.php @@ -0,0 +1,84 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'service_user_id' => 'Service User ID', + 'user_patient_id' => 'User Patient ID', + 'store_id' => 'Store ID', + 'order_no' => 'Order No', + 'depart_id' => 'Depart ID', + 'order_number' => 'Order Number', + 'price' => 'Price', + 'is_pay' => 'Is Pay', + 'status' => 'Status', + 'refuse_reason' => 'Refuse Reason', + 'pay_type' => 'Pay Type', + 'pay_time' => 'Pay Time', + 'is_cancel' => 'Is Cancel', + 'cancel_time' => 'Cancel Time', + 'refund_status' => 'Refund Status', + 'refund_time' => 'Refund Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/RegisterLog.php b/common/modelsgii/RegisterLog.php new file mode 100644 index 0000000..51a35d7 --- /dev/null +++ b/common/modelsgii/RegisterLog.php @@ -0,0 +1,51 @@ + 'ID', + 'register_id' => 'Register ID', + 'content' => 'Content', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/RegisterRefund.php b/common/modelsgii/RegisterRefund.php new file mode 100644 index 0000000..e24d7f1 --- /dev/null +++ b/common/modelsgii/RegisterRefund.php @@ -0,0 +1,63 @@ + 200], + [['remark'], 'string', 'max' => 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'register_id' => 'Register ID', + 'refund_no' => 'Refund No', + 'refund_price' => 'refund Price', + 'remark' => 'Remark', + 'is_refund' => 'Is Refund', + 'refund_time' => 'Refund Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ReplayTemplate.php b/common/modelsgii/ReplayTemplate.php new file mode 100644 index 0000000..82cae3c --- /dev/null +++ b/common/modelsgii/ReplayTemplate.php @@ -0,0 +1,55 @@ + 'ID', + 'su_id' => '人员ID', + 'group_id' => '分组ID', + 'content' => '内容', + 'sort' => '排序', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + ]; + } +} diff --git a/common/modelsgii/ReplayTemplateGroup.php b/common/modelsgii/ReplayTemplateGroup.php new file mode 100644 index 0000000..9f7b1f0 --- /dev/null +++ b/common/modelsgii/ReplayTemplateGroup.php @@ -0,0 +1,54 @@ + 'ID', + 'su_id' => '人员ID', + 'group_name' => '分组名', + 'sort' => '排序', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + ]; + } +} diff --git a/common/modelsgii/Role.php b/common/modelsgii/Role.php new file mode 100644 index 0000000..0664625 --- /dev/null +++ b/common/modelsgii/Role.php @@ -0,0 +1,54 @@ + 50], + [['description'], 'string', 'max' => 255], + [['name'], 'unique'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'role_code' => 'Role Code', + 'description' => 'Description', + 'created_at' => '创建时间', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/RoleMenu.php b/common/modelsgii/RoleMenu.php new file mode 100644 index 0000000..debf4fb --- /dev/null +++ b/common/modelsgii/RoleMenu.php @@ -0,0 +1,50 @@ + 50], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'role_id' => 'Role ID', + 'menuUrl' => 'Menu Url', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ServInfo.php b/common/modelsgii/ServInfo.php new file mode 100644 index 0000000..815e1d8 --- /dev/null +++ b/common/modelsgii/ServInfo.php @@ -0,0 +1,68 @@ + 50], + [['avatar', 'card_up', 'card_down'], 'string', 'max' => 255], + [['mobile'], 'string', 'max' => 30], + [['idcard'], 'string', 'max' => 20], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => 'Su ID', + 'name' => 'Name', + 'avatar' => 'Avatar', + 'mobile' => 'Mobile', + 'idcard' => 'Idcard', + 'hospital_id' => 'Hospital ID', + 'depart_id' => 'Depart ID', + 'card_up' => 'Card Up', + 'card_down' => 'Card Down', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/ServiceUser.php b/common/modelsgii/ServiceUser.php new file mode 100644 index 0000000..61977ef --- /dev/null +++ b/common/modelsgii/ServiceUser.php @@ -0,0 +1,62 @@ + 20], + [['nickname'], 'string', 'max' => 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'mobile' => 'Mobile', + 'nickname' => 'Nickname', + 'role' => 'Role', + 'status' => 'Status', + 'im_status' => 'Im Status', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } + + +} diff --git a/common/modelsgii/ServiceUserToken.php b/common/modelsgii/ServiceUserToken.php new file mode 100644 index 0000000..8630445 --- /dev/null +++ b/common/modelsgii/ServiceUserToken.php @@ -0,0 +1,53 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'su_id' => '服务端用户id', + 'token' => '用户token', + 'is_disable' => '是否禁用,主动退出后=1', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/Store.php b/common/modelsgii/Store.php new file mode 100644 index 0000000..46fda67 --- /dev/null +++ b/common/modelsgii/Store.php @@ -0,0 +1,90 @@ + 100], + [['position', 'pic'], 'string', 'max' => 255], + [['mobile'], 'string', 'max' => 20], + [['code'], 'string', 'max' => 30], + [['qr_code','z_buy_percent','z_sale_percent','g_bug_percent','g_sale_percent','store_set_sale_z','store_set_sale_g','shouzimu','bank_no','bank_name','bank_card','bank_user_name','start_time','end_time'], 'string'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'erp_id' => 'Erp_Id', + 'name' => '名字', + 'position' => '位置', + 'pic' => 'Pic', + 'contact' => '联系人', + 'mobile' => '联系电话', + 'code' => '推广码', + 'qr_code' => '门店码', + 'start_time' => '开始营业时间', + 'end_time' => '结束营业时间', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => '是否删除', + ]; + } +} diff --git a/common/modelsgii/StoreDepartment.php b/common/modelsgii/StoreDepartment.php new file mode 100644 index 0000000..150ea1d --- /dev/null +++ b/common/modelsgii/StoreDepartment.php @@ -0,0 +1,50 @@ + 'ID', + 'store_id' => 'Store ID', + 'depart_id' => 'Depart ID', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/StoreDoctor.php b/common/modelsgii/StoreDoctor.php new file mode 100644 index 0000000..ebe365d --- /dev/null +++ b/common/modelsgii/StoreDoctor.php @@ -0,0 +1,56 @@ + 'ID', + 'store_id' => 'Store ID', + 'su_id' => 'Su ID', + 'is_online' => 'Is Online', + 'last_login_time' => 'Last Login Time', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/StoreUser.php b/common/modelsgii/StoreUser.php new file mode 100644 index 0000000..c0e3099 --- /dev/null +++ b/common/modelsgii/StoreUser.php @@ -0,0 +1,56 @@ + 'ID', + 'store_id' => 'Store ID', + 'user_id' => 'User ID', + 'is_online' => '当前在线', + 'last_login_time' => '最近登录时间', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/SubAccountMenu.php b/common/modelsgii/SubAccountMenu.php new file mode 100644 index 0000000..ea88b27 --- /dev/null +++ b/common/modelsgii/SubAccountMenu.php @@ -0,0 +1,50 @@ + 50], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'admin_id' => 'Admin ID', + 'menuUrl' => 'Menu Url', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/SystemConfig.php b/common/modelsgii/SystemConfig.php new file mode 100644 index 0000000..e1df97f --- /dev/null +++ b/common/modelsgii/SystemConfig.php @@ -0,0 +1,53 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'type' => 'Type', + 'value' => 'Value', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/SystemNotice.php b/common/modelsgii/SystemNotice.php new file mode 100644 index 0000000..67a89db --- /dev/null +++ b/common/modelsgii/SystemNotice.php @@ -0,0 +1,66 @@ + 'ID', + 'data' => 'Data', + 'store_id' => '门店ID', + 'content' => '通知内容', + 'url' => '链接', + 'url_type' => '链接类型', + 'base_type' => '通知类型1订单取消通知2接诊通知3拒诊通知4温馨提示', + 'scene_type' => '场景类型:1用户端,2服务端(角色)', + 'user_role' => '通知用户类型', + 'user_id' => '用户id', + 'notice_at' => '通知时间', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + ]; + } +} diff --git a/common/modelsgii/User.php b/common/modelsgii/User.php new file mode 100644 index 0000000..5a380d6 --- /dev/null +++ b/common/modelsgii/User.php @@ -0,0 +1,85 @@ + 100], + [['session_key', 'password', 'avatarurl'], 'string', 'max' => 255], + [['mobile', 'idcard'], 'string', 'max' => 20], + [['nickname', 'country', 'province', 'city'], 'string', 'max' => 50], + [['openid'], 'unique'], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'openid' => 'Openid', + 'session_key' => 'Session Key', + 'unionid' => 'Unionid', + 'mobile' => 'Mobile', + 'password' => 'Password', + 'nickname' => 'Nickname', + 'gender' => 'Gender', + 'country' => 'Country', + 'province' => 'Province', + 'city' => 'City', + 'avatarurl' => 'Avatarurl', + 'token' => 'Token', + 'idcard' => 'Idcard', + 'age' => 'Age', + 'status' => 'Status', + 'current_store_id' => 'cCurrent Store Id', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/UserCollect.php b/common/modelsgii/UserCollect.php new file mode 100644 index 0000000..728ea0a --- /dev/null +++ b/common/modelsgii/UserCollect.php @@ -0,0 +1,58 @@ + "string", 'user_id' => "string", 'object_id' => "string", 'type' => "string", 'is_delete' => "string", 'created_at' => "string", 'updated_at' => "string"])] + public function attributeLabels(): array + { + return [ + 'id' => 'ID', + 'user_id' => '用户id', + 'object_id' => '收藏对象id', + 'type' => '类型', + 'is_delete' => '是否取消收藏', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/UserComment.php b/common/modelsgii/UserComment.php new file mode 100644 index 0000000..77e8875 --- /dev/null +++ b/common/modelsgii/UserComment.php @@ -0,0 +1,59 @@ + 'ID', + 'order_id' => '订单', + 'user_id' => '用户', + 'u_id' => '患者id', + 'su_id' => '医生id', + 'score' => '评分1很差2较差3好4很好5非常好', + 'comment' => '评论', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/UserInquiry.php b/common/modelsgii/UserInquiry.php new file mode 100644 index 0000000..bfa025e --- /dev/null +++ b/common/modelsgii/UserInquiry.php @@ -0,0 +1,82 @@ + 500], + [['visit_desc'], 'string', 'max' => 255], + [['person_history', 'allergic_history', 'family_history'], 'string', 'max' => 1000], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => 'User ID', + 'su_id' => 'Su ID', + 'up_id' => 'Up ID', + 'desc' => 'Desc', + 'images' => 'Images', + 'is_visit' => 'Is Visit', + 'visit_desc' => 'Visit Desc', + 'patient_data' => 'Patient Data', + 'liver_function' => 'Liver Function', + 'renal_function' => 'Renal Function', + 'person_status' => 'Person Status', + 'person_history' => 'Person History', + 'allergic_status' => 'Allergic Status', + 'allergic_history' => 'Allergic History', + 'family_status' => 'Family Status', + 'family_history' => 'Family History', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/UserPatient.php b/common/modelsgii/UserPatient.php new file mode 100644 index 0000000..ddc1325 --- /dev/null +++ b/common/modelsgii/UserPatient.php @@ -0,0 +1,68 @@ + 50], + [['mobile'], 'string', 'max' => 20], + ['avatar', 'string'] + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_id' => '关联用户', + 'avatar' => '头像', + 'name' => '真实姓名', + 'id_card' => '身份证', + 'sex' => '0默认1男2女', + 'relation' => '关系,0本人1丈夫2妻子3爸爸4妈妈5儿子6女儿7其他', + 'mobile' => '手机号', + 'is_default' => '是否默认就诊人', + 'is_delete' => '是否删除', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/UserPatientCase.php b/common/modelsgii/UserPatientCase.php new file mode 100644 index 0000000..a93dc4b --- /dev/null +++ b/common/modelsgii/UserPatientCase.php @@ -0,0 +1,80 @@ + 500], + [['idea'], 'string', 'max' => 100], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'store_id' => 'Store ID', + 'service_user_id' => 'Service User ID', + 'user_patient_id' => 'User Patient ID', + 'register_id' => 'Register ID', + 'hight' => 'Hight', + 'weight' => 'Weight', + 'temperature' => 'Temperature', + 'blood' => 'Blood', + 'main_suit' => 'Main Suit', + 'family' => 'Family', + 'now_history' => 'Now History', + 'popular' => 'Popular', + 'history' => 'History', + 'allergic' => 'Allergic', + 'idea' => 'Idea', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'is_delete' => 'Is Delete', + ]; + } +} diff --git a/common/modelsgii/UserPatientHealthInquiry.php b/common/modelsgii/UserPatientHealthInquiry.php new file mode 100644 index 0000000..42014c1 --- /dev/null +++ b/common/modelsgii/UserPatientHealthInquiry.php @@ -0,0 +1,71 @@ + 1000], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'user_patient_id' => '关联就诊人', + 'liver_function' => '肝功能0正常1异常', + 'liver_index' => '肝功能指标', + 'renal_function' => '肾功能0正常1异常', + 'renal_index' => '肾功能指标', + 'person_status' => '既往史0无1有', + 'person_history' => '既往史', + 'allergic_status' => '过敏史0无1有', + 'allergic_history' => '过敏史', + 'family_status' => '家庭遗传史0无1有', + 'family_history' => '家庭遗传史', + 'is_delete' => 'Is Delete', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/UserPatientIll.php b/common/modelsgii/UserPatientIll.php new file mode 100644 index 0000000..6ce8637 --- /dev/null +++ b/common/modelsgii/UserPatientIll.php @@ -0,0 +1,52 @@ + 'ID', + 'su_id' => '医生id', + 'up_id' => '关联就诊人id', + 'ti_id' => '关联疾病id', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/UserPatientRecord.php b/common/modelsgii/UserPatientRecord.php new file mode 100644 index 0000000..5052e55 --- /dev/null +++ b/common/modelsgii/UserPatientRecord.php @@ -0,0 +1,58 @@ + 255], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'up_id' => 'Up ID', + 'height' => 'Height', + 'weight' => 'Weight', + 'region' => 'Region', + 'address' => 'Address', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/WestRecipe.php b/common/modelsgii/WestRecipe.php new file mode 100644 index 0000000..638ff2c --- /dev/null +++ b/common/modelsgii/WestRecipe.php @@ -0,0 +1,64 @@ + 'ID', + 'content' => 'Content', + 'number' => '药品数量', + 'instruction' => '说明书', + 'time_id' => 'Time ID', + 'type_id' => 'Type ID', + 'wu_id' => '单位 ID', + 'grain_number' => '每天几粒', + 'available_days' => '可用天数', + 'f_id' => '频率', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/modelsgii/WestUnit.php b/common/modelsgii/WestUnit.php new file mode 100644 index 0000000..95054fd --- /dev/null +++ b/common/modelsgii/WestUnit.php @@ -0,0 +1,49 @@ + 20], + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + ]; + } +} diff --git a/common/services/EplPayService.php b/common/services/EplPayService.php new file mode 100644 index 0000000..a45b987 --- /dev/null +++ b/common/services/EplPayService.php @@ -0,0 +1,246 @@ +params['eplpay']; + if(!$eplConfig['customerCode'] || !$eplConfig['url']){ + throw new Exception('缺少易票联相关配置'); + } + $this->eplConfig = $eplConfig; + $this->wechatConfig = \Yii::$app->params['wechat']; + } + + + public static function getInstance($module = null) + { + if(empty(self::$instance)){ + self::$instance = new self($module); + } + return self::$instance; + } + + // 微信小程序支付 + public function WxJsapiPayment($params){ + $url = $this->eplConfig['url'].'/api/txs/pay/WxJSAPIPayment'; + $param = [ + 'outTradeNo' => $params['order_no'], + 'customerCode' => $this->eplConfig['customerCode'], + 'appId' => $this->wechatConfig['app_id'], + 'openId' => $params['openId'], + 'orderInfo' => $params['orderInfo'], + 'payAmount' => bcmul($params['total_pay_price'], 100, 0), + 'payCurrency' => 'CNY', + 'payMethod' => 35, + 'notifyUrl' => $this->eplConfig['pay_notify_url'], + 'transactionStartTime' => date('YmdHis'), + 'areaInfo' => '330102', + 'nonceStr' => FuncHelper::uuid(), + 'version' => '3.0' + ]; + $sign = $this->sign(Json::encode($param)); + $result = $this->http_post_json($url,Json::encode($param),$sign); + if(!$result || $result[0] != 200){ + throw new Exception('获取支付参数失败'); + } + return Json::decode($result[1]); + } + + //查询支付结果 + public function queryPayment($params){ + $url = $this->eplConfig['url'].'/api/txs/pay/PaymentQuery'; + $param = [ + 'outTradeNo' => $params['pay_order_no'], + 'customerCode' => $this->eplConfig['customerCode'], + 'nonceStr' => FuncHelper::uuid() + ]; + $sign = $this->sign(Json::encode($param)); + $result = $this->http_post_json($url,Json::encode($param),$sign); + if(!$result || $result[0] != 200){ + throw new Exception('查询支付结果失败'); + } + return Json::decode($result[1]); + } + + // 退款 + public function refund($params){ + $url = $this->eplConfig['url'].'/api/txs/pay/Refund/V2'; + $param = [ + 'outRefundNo' => $params['refund_no'], + 'customerCode' => $this->eplConfig['customerCode'], + 'transactionNo' => $params['transaction_id'], + 'amount' => bcmul($params['total_pay_price'], 100, 0), + 'refundAmount' => bcmul($params['refund_price'], 100, 0), + 'notifyUrl' => $this->eplConfig['refund_notify_url'], + 'transactionStartTime' => date('YmdHis'), + 'nonceStr' => FuncHelper::uuid(), + 'version' => '3.0' + ]; + $sign = $this->sign(Json::encode($param)); + $result = $this->http_post_json($url,Json::encode($param),$sign); + if(!$result || $result[0] != 200){ + throw new Exception('退款失败'); + } + return Json::decode($result[1]); + } + + //查询退款结果 + public function queryRefund($params){ + $url = $this->eplConfig['url'].'/api/txs-query/refundOrderQuery'; + $param = [ + 'outRefundNo' => $params['refund_no'], + 'customerCode' => $this->eplConfig['customerCode'], + 'nonceStr' => FuncHelper::uuid() + ]; + $sign = $this->sign(Json::encode($param)); + $result = $this->http_post_json($url,Json::encode($param),$sign); + if(!$result || $result[0] != 200){ + throw new Exception('查询退款结果失败'); + } + return Json::decode($result[1]); + } + + //单笔提现 + public function withDraw($params){ + $url = $this->eplConfig['url'].'/api/txs/pay/withdrawalToCard'; + $param = [ + 'outTradeNo' => $params['order_no'], + 'customerCode' => $this->eplConfig['customerCode'], + 'amount' => bcmul($params['apply_cash'], 100, 0), + 'arrivalType' => 0,// 到账类型 0当日 1次日 最大99 + 'procedureType' => 'inner', //inner内扣 outer外扣 + 'bankUserName' => $this->public_encrypt($params['bank_user_name']), //开户人姓名 + 'bankCardNo' => $this->public_encrypt($params['bank_card']), //银行卡号 + 'bankName' => $params['bank_name'],// 银行名称 + 'bankAccountType' => $params['bank_account_type'], //1对公 2对私 5存折 + 'notifyUrl' => $this->eplConfig['withdraw_notify_url'], + 'payCurrency' => 'CNY', + 'nonceStr' => FuncHelper::uuid() + ]; + if($params['bank_account_type'] != '2' || substr($params['bank_card'],0,2) != '62'){ + $param['bankNo'] = $params['bank_no']; + } + + $sign = $this->sign(Json::encode($param)); + $result = $this->http_post_json($url,Json::encode($param),$sign); + if(!$result || $result[0] != 200){ + throw new Exception('提现失败'); + } + return Json::decode($result[1]); + } + + //查询提现结果 + public function queryWithdraw($params){ + $url = $this->eplConfig['url'].'/api/txs/pay/withdrawalToCardQuery'; + $param = [ + 'outTradeNo' => $params['withdraw_order_no'], + 'customerCode' => $this->eplConfig['customerCode'], + 'nonceStr' => FuncHelper::uuid() + ]; + $sign = $this->sign(Json::encode($param)); + $result = $this->http_post_json($url,Json::encode($param),$sign); + if(!$result || $result[0] != 200){ + throw new Exception('查询提现结果失败'); + } + return Json::decode($result[1]); + } + + protected function sign($data) { + $certs = []; + openssl_pkcs12_read(file_get_contents($this->eplConfig['rsaPrivateKeyFilePath']), $certs, $this->eplConfig['password']); //其中password为你的证书密码 + + if(!$certs){ + throw new Exception('请检查RSA私钥配置'); + } + + openssl_sign($data, $sign, $certs['pkey'], OPENSSL_ALGO_SHA256); + + $sign = base64_encode($sign); + return $sign; + } + + protected function http_post_json($url, $jsonStr, $sign) + { + $ch = curl_init(); + $headers = array( + 'Content-Type: application/json; charset=utf-8', + 'Content-Length: ' . strlen($jsonStr), + 'x-efps-sign-no:'.$this->eplConfig['signNo'], + 'x-efps-sign-type:SHA256withRSA', + 'x-efps-sign:'.$sign, + 'x-efps-timestamp:'.date('YmdHis'), + ); + 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_SSL_VERIFYPEER, false); // 跳过检查 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 跳过检查 + //curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + $response = curl_exec($ch); + + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + return [$httpCode, $response]; + } + + // 公钥加密 + protected function public_encrypt($data) + { + //读取公钥文件 + $pubKey = file_get_contents($this->eplConfig['publicKeyFilePath']); + + $res = openssl_get_publickey($pubKey); + + if(!$res){ + throw new Exception('RSA公钥错误。请检查公钥文件格式是否正确'); + } + + $crypttext = ""; + + openssl_public_encrypt($data,$crypttext, $res ); + + if(!$this->checkEmpty($this->eplConfig['publicKeyFilePath'])) { + //释放资源 + if (PHP_VERSION_ID < 80000) { + openssl_free_key($res); + } + } + + return(base64_encode($crypttext)); + } + + /** + * 校验$value是否非空 + * if not set ,return true; + * if is null , return true; + **/ + protected function checkEmpty($value) { + if (!isset($value)) + return true; + if ($value === null) + return true; + if (trim($value) === "") + return true; + + return false; + } + +} diff --git a/common/services/ExportService.php b/common/services/ExportService.php new file mode 100644 index 0000000..819eb30 --- /dev/null +++ b/common/services/ExportService.php @@ -0,0 +1,74 @@ +request->post(); + + $data = $class->inventory($params); + //设置导出的文件名 + $fileName = iconv('utf-8', 'gbk', "$Name" . date("Y-m-d")); + header('Content-Type: application/vnd.ms-excel'); + //指明导出的格式 + header('Content-Disposition: attachment;filename="' . $fileName . '.xsl"'); + header('Cache-Control: max-age=0'); + //打开PHP文件句柄,php://output 表示直接输出到浏览器 + $fp = fopen('php://output', 'a'); + //输出Excel列名信息 + foreach ($headlist as $key => $value) { + //CSV的Excel支持GBK编码,一定要转换,否则乱码 + $headlist[$key] = $value; + } + //将数据通过fputcsv写到文件句柄 + fputcsv($fp, $headlist); + //每隔$limit行,刷新一下输出buffer,不要太大,也不要太小 + $limit = 100000; + //逐行取出数据,不浪费内存 + + foreach ($data as $k => $v) { + //刷新一下输出buffer,防止由于数据过多造成问题 + if ($k % $limit == 0 && $k != 0) { + ob_flush(); + flush(); + } + $row = $data[$k]; + foreach ($row as $key => $value) { + $row[$key] = $value; + } + fputcsv($fp, $row); + } + } + + public static function ExportByCors($parameter) + { + ini_set("memory_limit", "2048M"); + set_time_limit(0); + if (is_array($parameter)) { + $filename = date('Y-m-d_H-i-s') . '.csv'; +// header('Content-Type: application/vnd.ms-excel'); + header('Content-Type: application/json'); + header('Access-control-Allow-Origin:*'); + header("Content-Disposition: attachment;filename=$filename"); + header('Cache-Control: max-age=0'); + $fp = fopen('php://output', 'w'); + fwrite($fp,chr(0xEF).chr(0xBB).chr(0xBF)); + if ( ! empty($parameter['header']) && is_array($parameter['header'])) { + fputcsv($fp, $parameter['header']); + } + if (isset($parameter['data'])) { + foreach ($parameter['data'] as $row) { + fputcsv($fp, $row); + } + exit(); + } + return true; + } + // throw new \yii\web\HttpException(500, "Not a valid parameter!"); + + } +} \ No newline at end of file diff --git a/common/services/ExpressService.php b/common/services/ExpressService.php new file mode 100644 index 0000000..f669b3d --- /dev/null +++ b/common/services/ExpressService.php @@ -0,0 +1,38 @@ +where(['id' => $order_id])->one(); + if(!$productOrder){ + throw new Exception('产品订单不存在'); + } + $express = ExpressNos::find()->select('express_company_name,express_company_code,express_no,mobile,state')->where(['id' => $productOrder->express_no_id])->asArray()->one(); + if($express){ + $detail = ExpressDetails::find()->select('status,detail_at,detail')->where(['express_no_id' => $productOrder->express_no_id])->orderBy('detail_at DESC')->asArray()->all(); + $express['detail'] = $detail; + }else{ + $express = []; + } + return [ + 'address' => [ + "express_name" => $productOrder->express_name, + "express_mobile" => $productOrder->express_mobile, + "express_region" => $productOrder->express_region, + "express_address" => $productOrder->express_address, + "express_no_id" => $productOrder->express_no_id + ], + 'express' => $express + ]; + } + +} \ No newline at end of file diff --git a/common/services/ImService.php b/common/services/ImService.php new file mode 100644 index 0000000..abe7835 --- /dev/null +++ b/common/services/ImService.php @@ -0,0 +1,87 @@ +params['im']; + if(!$config['url'] || !$config['token']){ + throw new Exception('缺少im相关配置'); + } + $this->config = $config; + } + + private function __clone() + { + + } + + public static function getInstance() + { + if(empty(self::$instance)){ + self::$instance = new self(); + } + return self::$instance; + } + + /** + * Get a fresh instance of the Guzzle HTTP client. + * + * @return \GuzzleHttp\Client + */ + protected function getHttpClient() + { + return new Client(['http_errors' => false]); + } + + //消息发送 接收人,接收角色,会话id,消息内容 + public function sendToUid($to_id,$to_role,$message) + { + //会话id组合到message + $data = [ + 'FromId' => 0, + 'ToId' => $to_id, + 'ToType' => $to_role, + 'Msg' => $message, + 'Broadcast' => $to_id ? false : true, + ]; + $params = [ + 'headers' => ['token' => $this->config['token']], + 'json' => $data, + ]; + $response = $this->getHttpClient()->post($this->config['url'].'/sendMsg', $params); + + $result = json_decode($response->getBody()->getContents(), true); + \Yii::error($data); + \Yii::error($result); + //根据是否发送成功进行模板消息的发送 + } + + public function updateImStatus($userId,$imStatus,$userType) + { + // + $data = [ + 'userId' => intval($userId), + 'imStatus' => intval($imStatus), + 'userType' => $userType, + ]; + $params = [ + 'headers' => ['token' => $this->config['token']], + 'json' => $data, + ]; + $response = $this->getHttpClient()->post($this->config['url'].'/updateImStatus', $params); + + $result = json_decode($response->getBody()->getContents(), true); + + } + + + +} diff --git a/common/services/JacErpService.php b/common/services/JacErpService.php new file mode 100644 index 0000000..49ef79b --- /dev/null +++ b/common/services/JacErpService.php @@ -0,0 +1,66 @@ + false]; + + private function __clone() + { + + } + + private function __construct($userid) + { + $config = \Yii::$app->params['jac_erp']; + + // ... 在应用配置之前初始化 + if(!$config['secret']){ + throw new \Exception('江奥川ERP参数配置错误'); + } + if($userid){ + $config['userid'] = $userid; + } + + $this->config = $config; + } + + + public static function getInstance($userid) + { + if(empty(self::$instance)){ + self::$instance = new self($userid); + } + return self::$instance; + } + + + public function syncOrder($params){ + \Yii::info(__METHOD__."——同步订单至江奥川erp接口地址: ".$this->config['url'].'/tis-server/api/addTisApplyMaster'); + $url = $this->config['url'].'/tis-server/api/addTisApplyMaster'; + $params['hospital_code'] = $this->config['userid']; + $params['apply_no'] = time().rand(100,999); + + $response = (new Client(['http_errors' => false]))->post( + $url, + [ + 'headers' => ['Content-Type' => 'application/json', 'userid' => $this->config['userid'], 'secret' => $this->config['secret']], + \GuzzleHttp\RequestOptions::JSON =>$params + ] + ); + $result = json_decode($response->getBody(),true); + if ($result['code']) { + throw new Exception($result['message']); + } + return true; + } + +} diff --git a/common/services/PlatformService.php b/common/services/PlatformService.php new file mode 100644 index 0000000..4f722c7 --- /dev/null +++ b/common/services/PlatformService.php @@ -0,0 +1,115 @@ + false]; + + public function __construct($config = []) + { + $this->url = \Yii::$app->params['platform']['url']; + $this->token = \Yii::$app->params['platform']['token']; + if(!$this->url || !$this->token){ + throw new Exception('平台配置错误'); + } + } + + /** + * Get a fresh instance of the Guzzle HTTP client. + * + * @return \GuzzleHttp\Client + */ + protected function getHttpClient() + { + return new Client(self::$guzzleOptions); + } + + // 用户登录 + public function userLogin($data){ + $response = (new Client(['http_errors' => false, 'verify' => false]))->post($this->url."/platform/v1/user/login", [ + 'headers' => ['Authorization' =>"Bearer ".$this->token], + 'form_params' => [ + 'user_id' => $data['user_id'], + 'openid' => $data['openid'], + 'session_key' => $data['session_key'], + 'mobile' => $data['mobile'] ?? '', + 'nickname' => $data['nickname'] ?? '微信用户', + 'avatarurl' => $data['avatarurl'] ?? '', + 'platform_store_id' => $data['store_id'] + ], + ]); + $result = json_decode($response->getBody(),true); + if ($result['errcode'] == -1) { + throw new Exception($result['msg']); + } + return ['token' => $result['data']['token']]; + } + + + // 订单支付、取消或退款 + public function updateOrder($data){ + $response = (new Client(['http_errors' => false, 'verify' => false]))->post($this->url."/platform/v1/sync/product-order", [ + 'headers' => ['Authorization' =>"Bearer ".$this->token], + 'form_params' => [ + 'platform_store_id' => $data['store_id'], + 'order_no' => $data['order_no'], + 'status' => $data['status'], + ], + ]); + $result = json_decode($response->getBody(),true); + if ($result['errcode'] == -1) { + throw new Exception($result['msg']); + } + return true; + } + + public function forwardNotify($data, $type = 'pay'){ + $response = (new Client(['http_errors' => false, 'verify' => false]))->post($this->url."/platform/v1/order/notify", [ + 'headers' => ['Authorization' =>"Bearer ".$this->token], + 'json' => Json::encode([ + 'type' => $type, + 'notify' => $data + ]), + ]); + $result = json_decode($response->getBody(),true); + if ($result['errcode'] == -1) { + throw new Exception($result['msg']); + } + return true; + } + + public function syncDrug($data){ + $response = (new Client(['http_errors' => false, 'verify' => false]))->post($this->url."/platform/v1/sync/drug", [ + 'headers' => ['Authorization' =>"Bearer ".$this->token], + 'form_params' =>$data, + ]); + $result = json_decode($response->getBody(),true); + if ($result['errcode'] == -1) { + return false; + } + return true; + } + + //问诊信息 + // public function consultInfo($orderNo){ + // $response = $this->getHttpClient()->post($this->url."/platform/v1/order/info", [ + // 'headers' => ['Authorization' =>"Bearer ".$this->token], + // 'form_params' => [ + // 'order_no' => $orderNo + // ], + // ]); + // $result = json_decode($response->getBody(),true); + // if ($result['errcode'] == -1) { + // throw new Exception($result['msg']); + // } + // return $result; + // } + +} diff --git a/common/services/PrescriptionService.php b/common/services/PrescriptionService.php new file mode 100644 index 0000000..53bd89e --- /dev/null +++ b/common/services/PrescriptionService.php @@ -0,0 +1,64 @@ +select('id,store_id,prescription_no,online_prescription_no,is_online,prescription_type,type,is_dispense,valid_hours,content,doctor_order,status,pharmacist_id,su_id,process_rule_id,process_rule,process_rule_note,doctor_second_sign')->where([ + 'prescription_no' => $prescriptionNo + ])->with('pharmacistInfo')->asArray()->one(); + } else { + $prescription = Prescription::find()->select('id,store_id,prescription_no,online_prescription_no,is_online,prescription_type,type,is_dispense,valid_hours,content,doctor_order,status,pharmacist_id,su_id,process_rule_id,process_rule,process_rule_note,doctor_second_sign')->where([ + 'id' => $presciptionId + ])->with('pharmacistInfo')->asArray()->one(); + } + if(!$prescription){ + throw new Exception('处方不存在'); + } + $store = Store::find()->select('name, offical_seal')->where(['id' => $prescription['store_id']])->one(); + if(!$store) throw new Exception('门店不存在'); + $productOrder = ProductOrder::find()->where(['p_id' => $prescription['id']])->one(); + $content = Json::decode($prescription['content']); + foreach($content['repice'] as $k=>$v){ + $content['repice'][$k]['content'] = Json::decode($v['content']); + } + $prescription['content'] = $content; + $prescription['doctor_order'] = explode('|',$prescription['doctor_order']); + $prescription['is_pay'] = $productOrder->is_pay; + $prescription['cancel_status'] = $productOrder->cancel_status; + $prescription['refund_status'] = $productOrder->refund_status; + $prescription['store'] = $store; + + $DoctorIdentity= DoctorIdentity::find()->where(['su_id'=>$prescription['su_id']])->asArray()->one(); + $PharmacistIdentity= PharmacistIdentity::find()->where(['su_id'=>$prescription['pharmacist_id']])->asArray()->one(); + $prescription['doctor_sign_image']=$DoctorIdentity['sign_image']; + $prescription['doctor_sign_type']=$DoctorIdentity['sign_type']; + $prescription['Pharmacist_sign_image']=$PharmacistIdentity['sign_image']; + $prescription['Pharmacist_sign_type']=$PharmacistIdentity['sign_type']; + + return $prescription; + } + +} \ No newline at end of file diff --git a/common/services/SmsService.php b/common/services/SmsService.php new file mode 100644 index 0000000..018b23a --- /dev/null +++ b/common/services/SmsService.php @@ -0,0 +1,144 @@ +sms = [ + "status" => "1", //是否开启 + "access_key_id" => "LTAI5tSePVz6X1EXi6tBHzVg", + "access_key_secret" => "ppd5xa2o8b9oKalOiUqQFnYLYq4xlX", + "sign_name" => "萧康医药", //签名 + "captcha" => [ //验证码格式设置 + //'template_code' => 'SMS_274460204', // 模板code + "template_id" => "SMS_275060336", // 模板id + "template_variable" => "code", //模板变量 + ], + "doctor" => [ + "register" => [ //挂号订单提醒 + "template_id" => "SMS_462205458", + "template_variable" => "" + ], + "prescription_pass" => [ + "template_id" => "SMS_462260412", + "template_variable" => "order" + ], + "prescription_refuse" => [ + "template_id" => "SMS_462230433", + "template_variable" => [ + "order", + "cause" + ] + ] + ], + "pharmacist" => [ + "wait_approval" => [ + "template_id" => "SMS_462255406", + "template_variable" => "" + ] + ] + ]; + + $this->config = [ + // HTTP 请求的超时时间(秒) + 'timeout' => 5.0, + + // 默认发送配置 + 'default' => [ + // 网关调用策略,默认:顺序调用 + 'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class, + + // 默认可用的发送网关 + 'gateways' => [ + 'aliyun', + ], + ], + // 可用的网关配置 + 'gateways' => [ + 'errorlog' => [ + 'file' => '/tmp/easy-sms.log', + ], + 'aliyun' => [ + 'access_key_id' => $this->sms['access_key_id'], + 'access_key_secret' => $this->sms['access_key_secret'], + 'sign_name' => $this->sms['sign_name'], + ], + ], + ]; + $this->easySms = new EasySms($this->config); + } + + public function send($mobile, $message) + { + try { + $this->easySms->send($mobile, $message); + return true; + } catch (NoGatewayAvailableException $exception) { + $es = $exception->getExceptions(); + foreach ($es as $e) { + /** @var GatewayErrorException $e */ + if (isset($e->raw) && isset($e->raw['Code']) && $e->raw['Code'] == 'isv.MOBILE_NUMBER_ILLEGAL') { + throw new GatewayErrorException("无效的号码 {$mobile}", $e->getCode(), $e->raw); + } + if ($e instanceof ClientException) { + $result = json_decode($e->getResponse()->getBody()->getContents(), true); + if ($result && is_array($result) && isset($result['Message']) && isset($result['Code'])) { + if ($result['Code'] == 'InvalidAccessKeyId.NotFound') { + throw new GatewayErrorException("无效的AccessKeyId", $e->getCode(), $result); + } + if ($result['Code'] == 'SignatureDoesNotMatch') { + throw new GatewayErrorException( + "Signature不匹配,请检查AccessKeySecret是否正确", + $e->getCode(), + $result + ); + } + + throw new GatewayErrorException($result['Message'], $e->getCode(), $result); + } + } + throw $e; + } + } + } + + + public function sendCaptcha($mobile, $captcha) + { + // $captcha = (string)mt_rand(100000, 999999); + $message = new CaptchaMessage($captcha, $this->sms['captcha']); + return $this->send($mobile, $message); + } + + public function sendRegister($mobile){ + $message = new RegisterMessage($this->sms['doctor']['register']); + return $this->send($mobile, $message); + } + + public function sendWaitApproval($mobile){ + $message = new WaitApprovalMessage($this->sms['pharmacist']['wait_approval']); + return $this->send($mobile, $message); + } + + public function sendPrescriptionPass($mobile,$prescription_no){ + $message = new PrescriptionPassMessage($prescription_no, $this->sms['doctor']['prescription_pass']); + return $this->send($mobile, $message); + } + + public function sendPrescriptionRefuse($mobile,$prescription){ + $message = new PrescriptionRefuseMessage($prescription,$this->sms['doctor']['prescription_refuse']); + return $this->send($mobile, $message); + } +} diff --git a/common/services/UploadService.php b/common/services/UploadService.php new file mode 100644 index 0000000..c489ac5 --- /dev/null +++ b/common/services/UploadService.php @@ -0,0 +1,250 @@ + false]; + + public function __construct() + { + $this->storage = \Yii::$app->params['upload']; + } + + /** + * Get a fresh instance of the Guzzle HTTP client. + * + * @return \GuzzleHttp\Client + */ + protected function getHttpClient() + { + return new Client(self::$guzzleOptions); + } + + public function index($name) + { + $file = UploadedFile::getInstanceByName($name); + + + $this->file = $file; + + $this->validateSize(); + + $this->saveFileFolder = '/uploads/' . date('Ymd'); + $this->saveFileName = md5_file($this->file->tempName) . '.' . $this->file->getExtension(); + + switch($this->storage['type']){ + case 'alioss': + $this->saveToAliOss(); + break; + default: + $this->saveToLocal(); + break; + } + return $this->url; + } + + public function validateSize() + { + $supportExt = array_merge($this->docExt, $this->imageExt, $this->videoExt); + if (!in_array($this->file->extension, $supportExt)) { + throw new Exception('不支持的文件类型: ' . $this->file->extension); + } + + if (in_array($this->file->extension, $this->imageExt)) { + if ($this->storage['image_limit'] && $this->file->size > $this->storage['image_limit'] * 1024 * 1024) { + throw new Exception('图片大小超出限制,当前大小为: ' + . (round($this->file->size / 1024 / 1024, 4)) . 'MB,最大限制为:' + . $this->storage['image_limit'] . 'MB'); + } + } + + if (in_array($this->file->extension, $this->videoExt)) { + if ($this->storage['video_limit'] && $this->file->size > $this->storage['video_limit'] * 1024 * 1024) { + throw new Exception('视频大小超出限制,当前大小为: ' + . (round($this->file->size / 1024 / 1024, 4)) . 'MB,最大限制为:' + . $this->storage['video_limit'] . 'MB'); + } + } + } + + private function saveToLocal() + { + $saveFile = $this->storage['path'] . $this->saveFileFolder . '/' . $this->saveFileName; + $dir = dirname($saveFile); + FuncHelper::make_dir($dir); + + if(move_uploaded_file($this->file->tempName,$saveFile)){ + $this->url = $this->storage['url'] . $this->saveFileFolder . '/' . $this->saveFileName; + }else{ + throw new Exception('上传图片失败'); + } + } + + public function saveToAliOss() + { + try { + $config = $this->storage['alioss']; + + $isCName = (!empty($config['is_cname']) && $config['is_cname'] == 1) ? true : false; + $client = new OssClient($config['access_key'], $config['secret_key'], $config['domain'], $isCName); + + $object = trim($this->saveFileFolder . '/' . $this->saveFileName, '/'); + $client->uploadFile($config['bucket'], $object, $this->file->tempName); + if (!$isCName) { + $endpointNameStart = mb_stripos($config['domain'], '://') + 3; + $urlPrefix = mb_substr($config['domain'], 0, $endpointNameStart) + . $config['bucket'] + . '.' + . mb_substr($config['domain'], $endpointNameStart); + } else { + $urlPrefix = $config['domain']; + } + $this->url = $urlPrefix . $this->saveFileFolder . '/' . $this->saveFileName; + + } catch (OssException $e) { + throw new Exception($e->getMessage()); + } + } + + public function saveFile($file_path) + { + $this->saveFileFolder = '/uploads/' . date('Ymd'); + $this->saveFileName = md5_file($file_path) . '.' . strtolower(pathinfo($file_path, PATHINFO_EXTENSION)); + try { + $config = $this->storage['alioss']; + + $isCName = (!empty($config['is_cname']) && $config['is_cname'] == 1) ? true : false; + $client = new OssClient($config['access_key'], $config['secret_key'], $config['domain'], $isCName); + + $object = trim($this->saveFileFolder . '/' . $this->saveFileName, '/'); + $client->uploadFile($config['bucket'], $object,$file_path); + if (!$isCName) { + $endpointNameStart = mb_stripos($config['domain'], '://') + 3; + $urlPrefix = mb_substr($config['domain'], 0, $endpointNameStart) + . $config['bucket'] + . '.' + . mb_substr($config['domain'], $endpointNameStart); + } else { + $urlPrefix = $config['domain']; + } + $this->url = $urlPrefix . $this->saveFileFolder . '/' . $this->saveFileName; + + unlink($file_path); + return $this->url; + } catch (OssException $e) { + unlink($file_path); + throw new Exception($e->getMessage()); + } + } + + /** + * 阿里云直传 + */ + public function redirectFile($data) + { + $config = $this->storage['alioss']; + $callbackUrl = $data['callbackUrl']; + + $dir = $data['dir']; + $key = $config['secret_key']; + $id = $config['access_key']; + $host = $config['domain']; + + $callback_param = array( + 'callbackUrl' => $callbackUrl, + 'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}', + 'callbackBodyType' => "application/x-www-form-urlencoded" + ); + $callback_string = json_encode($callback_param); + $base64_callback_body = base64_encode($callback_string); + + $now = time(); + $expire = 30; //设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问。 + $end = $now + $expire; + + $expiration = $this->gmt_iso8601($end); + + //最大文件大小.用户可以自己设置 +// $condition = array(0 => 'content-length-range', 1 => 0, 2 => 1048576000); +// $conditions[] = $condition; + + // 表示用户上传的数据,必须是以$dir开始,不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录。 + $start = array(0 => 'starts-with', 1 => '$key', 2 => $dir); + $conditions[] = $start; + + $arr = array('expiration' => $expiration, 'conditions' => $conditions); + $policy = json_encode($arr); + $base64_policy = base64_encode($policy); + + $string_to_sign = $base64_policy; + $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true)); + + $response = array(); + $response['accessid'] = $id; + $response['host'] = $host; + $response['policy'] = $base64_policy; + $response['signature'] = $signature; + $response['expire'] = $end; + $response['callback'] = $base64_callback_body; + $response['dir'] = $dir; // 这个参数是设置用户上传文件时指定的前缀。 + $response['savename'] = md5(time().mt_rand(100,999)); + + return $response; + } + + public function gmt_iso8601($time) + { + return str_replace('+00:00', '.000Z', gmdate('c', $time)); + } + + /** + * 获取直传回调公钥 + */ + public function getPublicKey($pubKeyUrlBase64) + { + try { + $pubKeyUrl = base64_decode($pubKeyUrlBase64); + $response = $this->getHttpClient()->get($pubKeyUrl); + $body = $response->getBody(); + $buffer = $body->getContents(); + return $buffer; + }catch (\Exception $exception){ + return ""; + } + } + + /** + * 处理下返回,域名前缀 + */ + public function getBody($body) + { + $config = $this->storage['alioss']; + + parse_str($body,$body_arr); + $isCName = (!empty($config['is_cname']) && $config['is_cname'] == 1) ? true : false; + + if (!$isCName) { + $endpointNameStart = mb_stripos($config['domain'], '://') + 3; + $urlPrefix = mb_substr($config['domain'], 0, $endpointNameStart) + . $config['bucket'] + . '.' + . mb_substr($config['domain'], $endpointNameStart); + } else { + $urlPrefix = $config['domain']; + } + $body_arr['filename'] = $urlPrefix . '/' . $body_arr['filename']; + return $body_arr; + } + +} \ No newline at end of file diff --git a/common/services/WeappService.php b/common/services/WeappService.php new file mode 100644 index 0000000..168a729 --- /dev/null +++ b/common/services/WeappService.php @@ -0,0 +1,136 @@ + false]; + + public $base_url = "https://api.weixin.qq.com"; + + public function __construct($config = []) + { + if(!\Yii::$app->params['wechat']['app_id'] || !\Yii::$app->params['wechat']['app_secret']){ + throw new Exception('请设置后台小程序配置'); + } + $this->appid = \Yii::$app->params['wechat']['app_id']; + $this->secret = \Yii::$app->params['wechat']['app_secret']; + } + + /** + * Get a fresh instance of the Guzzle HTTP client. + * + * @return \GuzzleHttp\Client + */ + protected function getHttpClient() + { + return new Client(self::$guzzleOptions); + } + + /** + * 小程序登录 + * @param $code + * @return mixed + * @throws Exception + */ + public function login($code) + { + $response = $this->getHttpClient()->get($this->base_url.'/sns/jscode2session', [ + 'query' => array_filter([ + 'appid' => $this->appid, + 'secret' => $this->secret, + 'js_code' => $code, + 'grant_type' => 'authorization_code' + ]), + ]); + $result = json_decode($response->getBody(), true); + if(isset($result['errcode'])){ + throw new Exception($result['errmsg']); + } + return $result; + } + /** + * 获取后台接口access_token + */ + public function getAccessToken() + { + $key = 'wechat.common.access_token.'.$this->appid; + $cache = \Yii::$app->cache; + + $access_token = $cache->get($key); + if($access_token == false){ + //app.huiliaoyaofang.com + //job过来的没有HTTP_HOST; +// if(!isset($_SERVER['HTTP_HOST']) || $_SERVER['HTTP_HOST']!=='app.huiliaoyaofang.com'){ +// $response = $this->getHttpClient()->get('https://app.huiliaoyaofang.com/api/v1/noauth/token'); +// $result = json_decode($response->getBody(), true); +// $access_token = $result['data']['token']; +// }else{ + if(!isset($_SERVER['HTTP_HOST']) || $_SERVER['HTTP_HOST']=='hy.api.ctkj88.com') { + $response = $this->getHttpClient()->get('http://hy.api.ctkj88.com/service/v1/user/token'); + $result = json_decode($response->getBody(), true); + $access_token = $result['data']['token']; + }else{ + $response = $this->getHttpClient()->get($this->base_url.'/cgi-bin/token', [ + 'query' => array_filter([ + 'appid' => $this->appid, + 'secret' => $this->secret, + 'grant_type' => 'client_credential' + ]), + ]); + $result = json_decode($response->getBody(), true); + if(isset($result['errcode'])){ + throw new Exception($result['errmsg']); + } + $access_token = $result['access_token']; + $cache->set($key,$access_token,$result['expires_in']-30*60); + } + } + return $access_token; + } + /** + * 获取小程序码 + * @param $scene + * @return mixed + * @throws Exception + */ + public function getQrcode($scene,$page='',$type='base64') + { + $data['scene'] = $scene; + if($page){ + $data['page'] = $page; + } + + $params = [ + 'json' => $data, + ]; + + $response = $this->getHttpClient()->post($this->base_url.'/wxa/getwxacodeunlimit?access_token='.$this->getAccessToken(),$params); + + $body = $response->getBody(); + //\Yii::$app->response->format = \yii\web\Response::FORMAT_RAW; + try { + $buffer = $body->getContents(); + if($type=='base64'){ + $type = getimagesizefromstring($buffer)['mime']; //获取二进制流图片格式 + $base64String = 'data:' . $type . ';base64,' . chunk_split(base64_encode($buffer)); +// header('Content-Type: '.getimagesizefromstring($buffer)['mime']); + return $base64String; + }else{ + return $buffer; + } + }catch (\Exception $exception){ + \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; + $result = json_decode($response->getBody(), true); + if(isset($result['errcode'])){ + throw new Exception($result['errmsg']); + } + } + } + +} \ No newline at end of file diff --git a/common/services/WechatService.php b/common/services/WechatService.php new file mode 100644 index 0000000..097270a --- /dev/null +++ b/common/services/WechatService.php @@ -0,0 +1,100 @@ +params['wechat']; + // } + + // ... 在应用配置之前初始化 + if(!$config['app_id'] || !$config['app_secret'] || !$config['merchant_id'] || !$config['merchant_key'] || !$config['apiclient_cert'] || !$config['apiclient_key']){ + throw new \Exception('请设置支付配置'); + } + if ($config['apiclient_cert'] && $config['apiclient_key']) { + list($sslCer, $sslKey) = $this->generatePem($config['apiclient_cert'], $config['apiclient_key']); + } + + $app_id = $config['app_id']; + $app_secret = $config['app_secret']; + $mch_id = $config['merchant_id']; + $key = $config['merchant_key']; + $cert_path = $sslCer; + $key_path = $sslKey; + + $config = [ + 'app_id' => $app_id, + 'secret' => $app_secret, + + // 下面为可选项 + // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名 + 'response_type' => 'array', + + 'log' => [ + 'level' => 'debug', + 'file' => \Yii::getAlias('@member').'/runtime/wechat.log', + ], + + //支付参数 + 'mch_id' => $mch_id, + 'key' => $key, // API v2 密钥 (注意: 是v2密钥 是v2密钥 是v2密钥) + + // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书) + 'cert_path' => $cert_path, // XXX: 绝对路径!!!! + 'key_path' => $key_path, // XXX: 绝对路径!!!! + ]; + \Yii::error('支付参数:'.json_encode($config)); + $this->wechat = Factory::officialAccount($config);//公众号 + $this->app = Factory::miniProgram($config);//小程序 + $this->payment = Factory::payment($config);//支付 + } + + + public static function getInstance($module = null) + { + if(empty(self::$instance)){ + self::$instance = new self($module); + } + return self::$instance; + } + + /** + * @param $cert_pem + * @param $key_pem + */ + private function generatePem($cert_pem, $key_pem) + { + $pemDir = \Yii::$app->runtimePath . '/pem'; + FuncHelper::make_dir($pemDir); + $certPemFile = $pemDir . '/' . md5($cert_pem); + if (!file_exists($certPemFile)) { + file_put_contents($certPemFile, $cert_pem); + } + $keyPemFile = $pemDir . '/' . md5($key_pem); + if (!file_exists($keyPemFile)) { + file_put_contents($keyPemFile, $key_pem); + } + return [$certPemFile, $keyPemFile]; + } +} diff --git a/common/tests/_bootstrap.php b/common/tests/_bootstrap.php new file mode 100644 index 0000000..9915cc3 --- /dev/null +++ b/common/tests/_bootstrap.php @@ -0,0 +1,9 @@ + 'bayer.hudson', + 'auth_key' => 'HP187Mvq7Mmm3CTU80dLkGmni_FUH_lR', + //password_0 + 'password_hash' => '$2y$13$EjaPFBnZOQsHdGuHI.xvhuDp1fHpo8hKRSk6yshqa9c5EG8s3C3lO', + 'password_reset_token' => 'ExzkCOaYc1L8IOBs4wdTGGbgNiG3Wz1I_1402312317', + 'created_at' => '1402312317', + 'updated_at' => '1402312317', + 'email' => 'nicole.paucek@schultz.info', + ], +]; diff --git a/common/tests/_output/.gitignore b/common/tests/_output/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/common/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/common/tests/_support/.gitignore b/common/tests/_support/.gitignore new file mode 100644 index 0000000..36e264c --- /dev/null +++ b/common/tests/_support/.gitignore @@ -0,0 +1 @@ +_generated diff --git a/common/tests/_support/UnitTester.php b/common/tests/_support/UnitTester.php new file mode 100644 index 0000000..a0cc7a7 --- /dev/null +++ b/common/tests/_support/UnitTester.php @@ -0,0 +1,26 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]; + } + + public function testLoginNoUser() + { + $model = new LoginForm([ + 'username' => 'not_existing_username', + 'password' => 'not_existing_password', + ]); + + verify($model->login())->false(); + verify(Yii::$app->user->isGuest)->true(); + } + + public function testLoginWrongPassword() + { + $model = new LoginForm([ + 'username' => 'bayer.hudson', + 'password' => 'wrong_password', + ]); + + verify($model->login())->false(); + verify( $model->errors)->arrayHasKey('password'); + verify(Yii::$app->user->isGuest)->true(); + } + + public function testLoginCorrect() + { + $model = new LoginForm([ + 'username' => 'bayer.hudson', + 'password' => 'password_0', + ]); + + verify($model->login())->true(); + verify($model->errors)->arrayHasNotKey('password'); + verify(Yii::$app->user->isGuest)->false(); + } +} diff --git a/common/validators/MobieValidator.php b/common/validators/MobieValidator.php new file mode 100644 index 0000000..5528fb1 --- /dev/null +++ b/common/validators/MobieValidator.php @@ -0,0 +1,29 @@ +_pattern, $value, $arr)) { + $valid = true; + } + return $valid ? null : [$this->_message, []]; + } + + public function validateAttribute($model, $attribute) + { + $valid = false; + if (preg_match($this->_pattern, $model->$attribute, $arr)) { + $valid = true; + } + $valid ?: $this->addError($model, $attribute, $this->_message); + } +} diff --git a/common/validators/MobileValidator.php b/common/validators/MobileValidator.php new file mode 100644 index 0000000..9b5b9fb --- /dev/null +++ b/common/validators/MobileValidator.php @@ -0,0 +1,35 @@ +_pattern, $value, $arr)) { + $valid = true; + } + return $valid ? null : [$this->_message, []]; + } + + public function validateAttribute($model, $attribute) + { + $valid = false; + if (preg_match($this->_pattern, $model->$attribute, $arr)) { + $valid = true; + } + $valid ?: $this->addError($model, $attribute, $this->_message); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..492a664 --- /dev/null +++ b/composer.json @@ -0,0 +1,74 @@ +{ + "name": "yiisoft/yii2-app-advanced", + "description": "Yii 2 Advanced Project Template", + "keywords": ["yii2", "framework", "advanced", "project template"], + "homepage": "https://www.yiiframework.com/", + "type": "project", + "license": "BSD-3-Clause", + "support": { + "issues": "https://github.com/yiisoft/yii2/issues?state=open", + "forum": "https://www.yiiframework.com/forum/", + "wiki": "https://www.yiiframework.com/wiki/", + "irc": "irc://irc.freenode.net/yii", + "source": "https://github.com/yiisoft/yii2" + }, + "minimum-stability": "dev", + "require": { + "php": ">=7.4.0", + "ext-json": "*", + "yiisoft/yii2": "~2.0.45", + "yiisoft/yii2-bootstrap5": "~2.0.2", + "yiisoft/yii2-symfonymailer": "~2.0.3", + "aliyuncs/oss-sdk-php": "dev-master", + "overtrue/wechat": "5.*", + "jiang704593835/yii2-doc": "dev-master", + "yiisoft/yii2-queue": "2.x-dev", + "endroid/qr-code": "4.*", + "yiithings/yii2-dotenv": "*", + "tencent/tls-sig-api-v2": "1.*", + "nesbot/carbon": "2.*", + "yiisoft/log-target-file": "1.0.4", + "linslin/yii2-curl": "*", + "overtrue/easy-sms": "dev-master", + "yiisoft/yii2-redis": "2.0.x-dev", + "phpoffice/phpexcel": "*", + "moonlandsoft/yii2-phpexcel": "2.*" + }, + "require-dev": { + "yiisoft/yii2-debug": "~2.1.0", + "yiisoft/yii2-gii": "~2.2.0", + "yiisoft/yii2-faker": "~2.0.0", + "phpunit/phpunit": "~9.5.0", + "codeception/codeception": "^5.0.0 || ^4.0", + "codeception/lib-innerbrowser": "^3.0 || ^1.1", + "codeception/module-asserts": "^3.0 || ^1.1", + "codeception/module-yii2": "^1.1", + "codeception/module-filesystem": "^3.0 || ^1.1", + "codeception/verify": "^2.2", + "symfony/browser-kit": "^6.0 || >=2.7 <=4.2.4", + "overtrue/pinyin": "4.1.0" + }, + "autoload-dev": { + "psr-4": { + "common\\tests\\": ["common/tests/", "common/tests/_support"], + "admin\\tests\\": ["admin/tests/", "admin/tests/_support"], + "app\\tests\\": ["app/tests/", "app/tests/_support"] + } + }, + "config": { + "allow-plugins": { + "yiisoft/yii2-composer": true, + "easywechat-composer/easywechat-composer": true + }, + "process-timeout": 1800, + "fxp-asset": { + "enabled": false + } + }, + "repositories": [ + { + "type": "composer", + "url": "https://asset-packagist.org" + } + ] +} diff --git a/console/config/.gitignore b/console/config/.gitignore new file mode 100644 index 0000000..42799dd --- /dev/null +++ b/console/config/.gitignore @@ -0,0 +1,3 @@ +main-local.php +params-local.php +test-local.php diff --git a/console/config/bootstrap.php b/console/config/bootstrap.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/console/config/bootstrap.php @@ -0,0 +1 @@ + 'app-console', + 'basePath' => dirname(__DIR__), + 'bootstrap' => ['log'], + 'controllerNamespace' => 'console\controllers', + 'aliases' => [ + '@bower' => '@vendor/bower-asset', + '@npm' => '@vendor/npm-asset', + ], + 'controllerMap' => [ + 'fixture' => [ + 'class' => \yii\console\controllers\FixtureController::class, + 'namespace' => 'common\fixtures', + ], + ], + 'components' => [ + // 'log' => [ + // 'targets' => [ + // [ + // 'class' => \yii\log\FileTarget::class, + // 'levels' => ['error', 'warning'], + // ], + // ], + // ], + ], + 'params' => $params, +]; diff --git a/console/config/params.php b/console/config/params.php new file mode 100644 index 0000000..6ebf279 --- /dev/null +++ b/console/config/params.php @@ -0,0 +1,5 @@ + 'admin@example.com', +]; diff --git a/console/config/test.php b/console/config/test.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/console/config/test.php @@ -0,0 +1,4 @@ +where(['role' => 0])->count(); + if ($count===0) { + $model = new Admin(); + $model->username = StringHelper::random(6); + $model->generateAuthKey(); + $password_hash = StringHelper::random(10); + $model->setPassword($password_hash); + if ($model->save()) { + Console::output('username; ' . $model->username); + Console::output('password; ' . $password_hash); + exit(); + } + + Console::stdout('Password initialization failed'); + exit(); + } + + Console::stdout('已经有超管账号'); + exit(); + } +} \ No newline at end of file diff --git a/console/controllers/TestController.php b/console/controllers/TestController.php new file mode 100644 index 0000000..a7c49bf --- /dev/null +++ b/console/controllers/TestController.php @@ -0,0 +1,24 @@ +queue->delay(0)->push(new OrderPayImJob([ +// 'orderId' => 10, +// ])); + + + $job = new OrderPayImJob(); + $job->exec(114); + } +} diff --git a/console/migrations/m130524_201442_init.php b/console/migrations/m130524_201442_init.php new file mode 100644 index 0000000..ceddf02 --- /dev/null +++ b/console/migrations/m130524_201442_init.php @@ -0,0 +1,33 @@ +db->driverName === 'mysql') { + // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; + } + + $this->createTable('{{%user}}', [ + 'id' => $this->primaryKey(), + 'username' => $this->string()->notNull()->unique(), + 'auth_key' => $this->string(32)->notNull(), + 'password_hash' => $this->string()->notNull(), + 'password_reset_token' => $this->string()->unique(), + 'email' => $this->string()->notNull()->unique(), + + 'status' => $this->smallInteger()->notNull()->defaultValue(10), + 'created_at' => $this->integer()->notNull(), + 'updated_at' => $this->integer()->notNull(), + ], $tableOptions); + } + + public function down() + { + $this->dropTable('{{%user}}'); + } +} \ No newline at end of file diff --git a/console/migrations/m190124_110200_add_verification_token_column_to_user_table.php b/console/migrations/m190124_110200_add_verification_token_column_to_user_table.php new file mode 100644 index 0000000..2ccaa4e --- /dev/null +++ b/console/migrations/m190124_110200_add_verification_token_column_to_user_table.php @@ -0,0 +1,16 @@ +addColumn('{{%user}}', 'verification_token', $this->string()->defaultValue(null)); + } + + public function down() + { + $this->dropColumn('{{%user}}', 'verification_token'); + } +} \ No newline at end of file diff --git a/console/migrations/m221104_020506_init2.php b/console/migrations/m221104_020506_init2.php new file mode 100644 index 0000000..b3b25c3 --- /dev/null +++ b/console/migrations/m221104_020506_init2.php @@ -0,0 +1,183 @@ +createTable('{{%admin}}', [ + 'id' => $this->primaryKey(), + 'username' => $this->char(16)->notNull()->comment('用户名'), + 'password' => $this->char(60)->notNull()->comment('密码'), + 'role' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('角色1为官方管理'), + 'mall_id' => $this->integer(11)->notNull()->defaultValue(0)->comment('商城ID'), + 'salt' => $this->char(32)->notNull()->comment('密码干扰字符'), + 'email' => $this->char(32)->notNull()->defaultValue('')->comment('用户邮箱'), + 'mobile' => $this->char(15)->notNull()->defaultValue('')->comment('用户手机'), + 'reg_time' => $this->integer(11)->notNull()->defaultValue(0)->comment('注册时间'), + 'reg_ip' => $this->bigInteger(20)->notNull()->defaultValue(0)->comment('注册IP'), + 'last_login_time' => $this->integer(11)->notNull()->defaultValue(0)->comment('最后登录时间'), + 'last_login_ip' => $this->bigInteger(20)->notNull()->defaultValue(0)->comment('最后登录IP'), + 'update_time' => $this->integer(11)->notNull()->defaultValue(0)->comment('更新时间'), + 'is_sub' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('是否子账号'), + 'is_delete' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('是否删除'), + 'status' => $this->tinyInteger(1)->notNull()->defaultValue(1)->comment('用户状态 1正常 0禁用'), + ]); + + $this->createTable('{{%admin_access_token}}', [ + 'id' => $this->primaryKey(), + 'access_token' => $this->string(60)->notNull()->comment('授权令牌'), + 'admin_id' => $this->integer(11)->notNull()->defaultValue(0)->comment('admin用户id'), + 'group' => $this->string(100)->notNull()->defaultValue('')->comment('组别'), + 'status' => $this->tinyInteger(1)->notNull()->defaultValue(1)->comment('状态[-1:删除;0:禁用;1启用]'), + 'expired_at' => $this->integer(11)->notNull()->defaultValue(0)->comment('过期时间'), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0)->comment('创建时间'), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0)->comment('修改时间'), + ]); + + $this->createTable('{{%attachment_group}}', [ + 'id' => $this->primaryKey(), + 'mall_id' => $this->integer(11)->notNull()->defaultValue(0), + 'name' => $this->string(64)->notNull()->defaultValue('')->comment('组别'), + 'is_delete' => $this->tinyInteger(1)->notNull()->defaultValue(0), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0), + 'deleted_at' => $this->integer(11)->notNull()->defaultValue(0), + 'is_recycle' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('是否加入回收站 0.否|1.是'), + 'type' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('0 图片 1商品'), + ]); + + $this->createTable('{{%attachment}}', [ + 'id' => $this->primaryKey(), + 'storage_id' => $this->integer(11)->notNull(), + 'attachment_group_id' => $this->integer(11)->notNull()->defaultValue(0), + 'user_id' => $this->integer(11)->notNull(), + 'mall_id' => $this->integer(11)->notNull()->defaultValue(0), + 'name' => $this->string(128)->notNull(), + 'size' => $this->integer(11)->notNull()->comment('大小:字节'), + 'url' => $this->string(2080)->notNull(), + 'thumb_url' => $this->string(2080)->notNull()->defaultValue(''), + 'type' => $this->tinyInteger(2)->notNull()->comment('类型:1=图片,2=视频'), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0), + 'deleted_at' => $this->integer(11)->notNull()->defaultValue(0), + 'is_delete' => $this->tinyInteger(2)->notNull()->defaultValue(0), + 'is_recycle' => $this->tinyInteger(2)->notNull()->defaultValue(0)->comment('是否加入回收站 0.否|1.是'), + ]); + + $this->createTable('{{%role}}', [ + 'id' => $this->primaryKey(), + 'name' => $this->string(50), + 'role_code' => $this->string(50), + 'description' => $this->string(255), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0), + ]); + + $this->createTable('{{%role_menu}}', [ + 'id' => $this->primaryKey(), + 'role_id' => $this->integer(11), + 'menuUrl' => $this->string(50), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0), + ]); + + $this->createTable('{{%menu}}', [ +// 'id' => $this->primaryKey(), + 'menuUrl' => $this->string(50)->notNull()->defaultValue('')->comment('菜单地址'), + 'menuName' => $this->string(50)->notNull()->defaultValue('')->comment('菜单名称'), + 'parentPath' => $this->string(50)->notNull()->defaultValue('')->comment('上级路由'), + 'routeName' => $this->string(50)->notNull()->defaultValue('')->comment('路由name'), + 'redirect' => $this->string(255)->notNull()->defaultValue(''), + 'icon' => $this->string(50)->defaultValue('')->comment('菜单图标'), + 'sort' => $this->integer(11)->notNull()->defaultValue(0), + 'cacheable' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('是否缓存'), + 'hidden' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('是否隐藏'), + 'affix' => $this->tinyInteger(1)->notNull()->defaultValue(0)->comment('是否固定标题栏'), + ]); + + $this->addPrimaryKey('menuUrl','{{%menu}}','menuUrl'); + + $this->createTable('{{%sub_account_menu}}', [ + 'id' => $this->primaryKey(), + 'admin_id' => $this->integer(11), + 'menuUrl' => $this->string(50), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0), + ]); + + $this->createTable('{{%config}}', [ + 'id' => $this->primaryKey(), + 'name' => $this->string(30)->notNull()->defaultValue('')->comment('配置名称'), + 'title' => $this->string(50)->notNull()->defaultValue('')->comment('配置标题'), + 'group' => $this->tinyInteger(3)->notNull()->defaultValue(0)->comment('配置分组'), + 'type' => $this->tinyInteger(3)->notNull()->defaultValue(0)->comment('配置类型'), + 'value' => $this->text()->comment('配置值'), + 'extra' => $this->string(255)->comment('配置值'), + 'remark' => $this->string(100)->comment('配置说明'), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0), + 'sort' => $this->integer(11)->notNull()->defaultValue(0), + 'status' => $this->tinyInteger(2)->notNull()->defaultValue(1), + ]); + + $this->dropTable('{{%user}}'); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + $this->dropTable('{{%admin}}'); + $this->dropTable('{{%admin_access_token}}'); + $this->dropTable('{{%attachment_group}}'); + $this->dropTable('{{%attachment}}'); + $this->dropTable('{{%role}}'); + $this->dropTable('{{%role_menu}}'); + $this->dropTable('{{%menu}}'); + $this->dropTable('{{%sub_account_menu}}'); + $this->dropTable('{{%config}}'); + + $tableOptions = null; + if ($this->db->driverName === 'mysql') { + // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; + } + $this->createTable('{{%user}}', [ + 'id' => $this->primaryKey(), + 'username' => $this->string()->notNull()->unique(), + 'auth_key' => $this->string(32)->notNull(), + 'password_hash' => $this->string()->notNull(), + 'password_reset_token' => $this->string()->unique(), + 'email' => $this->string()->notNull()->unique(), + + 'status' => $this->smallInteger()->notNull()->defaultValue(10), + 'created_at' => $this->integer()->notNull(), + 'updated_at' => $this->integer()->notNull(), + 'verification_token' => $this->string()->defaultValue(null) + ], $tableOptions); + } + + /* + // Use up()/down() to run migration code without a transaction. + public function up() + { + + } + + public function down() + { + echo "m221104_020506_init2 cannot be reverted.\n"; + + return false; + } + */ +} \ No newline at end of file diff --git a/console/migrations/m230520_025427_create_tablename_categories.php b/console/migrations/m230520_025427_create_tablename_categories.php new file mode 100644 index 0000000..cfe5a7e --- /dev/null +++ b/console/migrations/m230520_025427_create_tablename_categories.php @@ -0,0 +1,59 @@ +db->driverName === 'mysql') { + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB'; + } + + //创建一个表 + $this->createTable('{{yii_categories}}', [ + 'id' => $this->primaryKey(), + 'name' => $this->string(200)->notNull()->defaultValue('')->comment('分类'), + 'level' => $this->tinyInteger(2)->notNull()->defaultValue(0)->comment('级别'), + 'pid' => $this->tinyInteger(2)->notNull()->defaultValue(0)->comment('父级id'), + 'created_at' => $this->integer(11)->notNull()->defaultValue(0)->comment('创建时间'), + 'updated_at' => $this->integer(11)->notNull()->defaultValue(0)->comment('修改时间'), + ], $tableOptions); + + //增加或者修改一个表备注 + $this->addCommentOnTable('{{yii_categories}}', '分类表'); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + echo "m230520_025427_create_tablename_categories cannot be reverted.\n"; + + return false; + } + + /* + // Use up()/down() to run migration code without a transaction. + public function up() + { + + } + + public function down() + { + echo "m230520_025427_create_tablename_categories cannot be reverted.\n"; + + return false; + } + */ +} diff --git a/console/models/.gitkeep b/console/models/.gitkeep new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/console/models/.gitkeep @@ -0,0 +1 @@ +* diff --git a/environments/dev/admin/config/codeception-local.php b/environments/dev/admin/config/codeception-local.php new file mode 100644 index 0000000..2d875dd --- /dev/null +++ b/environments/dev/admin/config/codeception-local.php @@ -0,0 +1,11 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => \yii\debug\Module::class, + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => \yii\gii\Module::class, + ]; +} + +return $config; diff --git a/environments/dev/admin/config/params-local.php b/environments/dev/admin/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/dev/admin/config/params-local.php @@ -0,0 +1,4 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], + ] +); diff --git a/environments/dev/common/config/main-local.php b/environments/dev/common/config/main-local.php new file mode 100644 index 0000000..80d6839 --- /dev/null +++ b/environments/dev/common/config/main-local.php @@ -0,0 +1,44 @@ + [ + 'db' => [ + 'class' => \yii\db\Connection::class, + 'dsn' => 'mysql:host=116.62.5.141;dbname=xiaokang', + 'username' => 'xiaokang', + 'password' => 'rY2csjsDW6n4MzLY', + 'charset' => 'utf8mb4', + 'tablePrefix' => 'yii_', + ], + 'mailer' => [ + 'class' => \yii\symfonymailer\Mailer::class, + 'viewPath' => '@common/mail', + // send all mails to a file by default. + 'useFileTransport' => true, + // You have to set + // + // 'useFileTransport' => false, + // + // and configure a transport for the mailer to send real emails. + // + // SMTP server example: + // 'transport' => [ + // 'scheme' => 'smtps', + // 'host' => '', + // 'username' => '', + // 'password' => '', + // 'port' => 465, + // 'dsn' => 'native://default', + // ], + // + // DSN example: + // 'transport' => [ + // 'dsn' => 'smtp://user:pass@smtp.example.com:25', + // ], + // + // See: https://symfony.com/doc/current/mailer.html#using-built-in-transports + // Or if you use a 3rd party service, see: + // https://symfony.com/doc/current/mailer.html#using-a-3rd-party-transport + ], + ], +]; diff --git a/environments/dev/common/config/params-local.php b/environments/dev/common/config/params-local.php new file mode 100644 index 0000000..14e6006 --- /dev/null +++ b/environments/dev/common/config/params-local.php @@ -0,0 +1,91 @@ + [ + 'over_time' => 300,//秒,自动取消时间 + 'refund_time' => 600,//秒,医生未接诊超时自动退款 + 'accept_over_time' => 1800,//秒,医生接诊后自动结束时间 + ], + 'im' => [ + 'url' => 'wss://wss.ctkj88.com/ws', + 'token' => 'tokenwebffff333', + ], + 'wechat' => [ + 'app_id' => 'wx1eb90a487ca945d2', + 'app_secret' => 'bfc4ed01e02602f2d2692cf588e66426', + 'merchant_id' => '1640496313', + 'merchant_key' => 'x80e509acd6319904b16d89fd331a988', + 'apiclient_cert' => '-----BEGIN CERTIFICATE----- +MIIEITCCAwmgAwIBAgIUX2WR15TWy6hCUBijincsyUDCdncwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjMwMzI3MDUyNzIxWhcNMjgwMzI1MDUyNzIxWjB7MRMwEQYDVQQDDAox +NjQwNDk2MzEzMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM +Hua1meaxn+iQp+W6t+WMu+iNr+aciemZkOWFrOWPuDELMAkGA1UEBgwCQ04xETAP +BgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +0Sp54iPzSy4+hPvlFIIl1rbqPb8JN+onIbj9dVQZBnOXgLBQILcfLuxLQchiZ1Xt +M85M/ddqEfaggBe1HvGs9INW6u6kvMzLo8QR39CduPBAjBNxE6+VBFXIIKsmr7qd +iv5ixDC1F5dhtcvXQ7VCM+PKtZlbEHdSlGSJmoFGDgqn5TAjlZ1nnhAtx2PJ4SpJ +GjmsGIHoPv1O4eCxbvBb3mMfV9KgCPs/H1VS9MFal8EN2X11O/rhRwQaApgYqxDZ +Ifc1PerKuzrYMtBXM05ugxQt1kLACPrg/P1eUro/8uOwGKoyOSfG8AIdUGGABiDY +zpqojvyJ9gHN9++uRCeWOQIDAQABo4G5MIG2MAkGA1UdEwQCMAAwCwYDVR0PBAQD +AgP4MIGbBgNVHR8EgZMwgZAwgY2ggYqggYeGgYRodHRwOi8vZXZjYS5pdHJ1cy5j +b20uY24vcHVibGljL2l0cnVzY3JsP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3 +NTQ5ODQ2QzAxQzNFOEVCRDImc2c9SEFDQzQ3MUI2NTQyMkUxMkIyN0E5RDMzQTg3 +QUQxQ0RGNTkyNkUxNDAzNzEwDQYJKoZIhvcNAQELBQADggEBAGWtcwXxbktlmT1l +9xwagnDLIzgzSbED13MRY/1lX5iBhX5JQ2W7goDb5QPomZ4ETNkE2jeqSU7yTb1v +xzwXITGLHXaepfAC6QG96WE9iVW4CwkrBKlLae2Eo+6v3FmCeFgBUZawg2QZO5Wr +9GDu61PxQ6do9ra0iU9HR7tLWJth4dX/1RekO5wJ50bneeSf2bERrO9E7OwpUk56 +0SFSnZSm9hi25T3z856GKtQnNwgukxMbucYHh4wgcGLfjxUz7XgzeimnFNM2Dl1C +i7HrN4HpP4M4MmyUaxUE+4py0jBz8EDQUmwN+b/AsyfbtE3uumXvvTDjXfP5Dg6Y +RvVASc0= +-----END CERTIFICATE-----', + 'apiclient_key' => '-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRKnniI/NLLj6E +++UUgiXWtuo9vwk36ichuP11VBkGc5eAsFAgtx8u7EtByGJnVe0zzkz912oR9qCA +F7Ue8az0g1bq7qS8zMujxBHf0J248ECME3ETr5UEVcggqyavup2K/mLEMLUXl2G1 +y9dDtUIz48q1mVsQd1KUZImagUYOCqflMCOVnWeeEC3HY8nhKkkaOawYgeg+/U7h +4LFu8FveYx9X0qAI+z8fVVL0wVqXwQ3ZfXU7+uFHBBoCmBirENkh9zU96sq7Otgy +0FczTm6DFC3WQsAI+uD8/V5Suj/y47AYqjI5J8bwAh1QYYAGINjOmqiO/In2Ac33 +765EJ5Y5AgMBAAECggEAdTKYooZEPx7FNxwxCmG2M+2/qCNPVf4kOPf/RGt/ria8 +gAXKj9orZc5OiKhvwrjZtMpmR2EY9MG8wqkF+jWuFD83R2G5+nPBspwc68xnY4Vy +lUobdM1P8OLjxLJBdftZZNUOoCEuhu5yeDuj/TMlyg9buI8aAErrgWwn0eOXTivU +GhVTSYf6bW3CpBZ3fxNO8KYYJyjU4tH8Ow8xYNLZRE4SFvzZmtHm20OtgUZN/aI6 +BjnOZLWpxU0Q4tdtZu5LCC3gF4Gj95lLY9GarPV2R00vnxyJyqQf29IJCWv4gD/M +DF7Y+RGR71m7hNEtKnZSeq8rWBWkgd23k6hEPX8ugQKBgQD7feaNQisVsH95zhYB +Y3BrMu0Mm1LThTwqZ73rHbpGaiLoXE2EKbcYGvwrqoZWn3echCWWOK80Q/EXx9EO +VqFbrb9/dovjKQAyivQnaBY1yDDwm9Of9sLeWRnh6+/im4AjhuP5ZDJcoYlWPfeS +dcpHcnK9NWzmW/pZS0zwH5HukQKBgQDU6ldqgtuYxPgOCiAS8yXuhhpDKe/+4uh2 +GVVyhty8kQptT5bsgpkBMEPQu3hATvuYMHVSRNWMLvtYnvSh1rMrZXIYKiwprFXi +gIbqPEEdla8/ERBs3inMhyORoGOMtgnmkfaYQhfwI4QLYbdxrtlVGTC1zpsBZHyN +gRJtO8TRKQKBgF7Lmx69xT28tKA2FUdasyJFJOMunO7L9tzJE+ZO40rtcNEDEdjy +XGiCq3DOKyr1mwFtMjnIjgn2Xicnk16DOvkyqc8i4SGz77YdeGBuNIj7N69KHV/b +hKKJFV96LobNNGSv0LjNksolvX27h9k1+xQpSKSXQcAnBVupLYwJallxAoGBAJXC +U0Re0Lku6k9tvcu2bRrOBpDxYZbF4b6X6StKQt77ofrrPXwUDCzy1vBtvJJ3O657 +fzojopUcwrw96lIfYx0GGO94UmHpjutnff4p7Z8ylvZkOUpqJbpv34vh5cOmk2Yz +iuDjtFS7lngu/kofM00RD9sBfLPJC3a4r85XeQOpAoGBANkWq6FHRYjVISdz9Olc +yieXIKzTFemVO+SZXN715HrE83wVhTmkl6+4p/C+nxeVWlAuZ8nrRCZd9+3vzqv4 +6WcLGHkclmjGv3PeatZ8vCoqZq70nsxD1sCngWMSBqQlswC2C+em/4pL4An+fWOq +JJvBfLfudYNUjUCyW3gAcOIJ +-----END PRIVATE KEY-----' + ], + /* 上传文件 */ + 'upload' => [ + 'type' => 'alioss', // local,alioss + 'image_limit' => 20,//单位M,0不限制 + 'video_limit' => 50,//单位M,0不限制 + 'local_url' => '', + 'local_path' => '', // 服务器解析到/web/目录时,上传到这里 + 'alioss' => [ + 'access_key' => 'LTAINrYfGdUKadD0', + 'secret_key' => '4mv4Uhlc6kQuY7OfaHI3tWMUcSnJlo', + 'bucket' => 'yanydy', //bucket + 'is_cname' => 0, //自定义域名,1使用,0不使用 + 'domain' => 'https://oss-cn-hangzhou.aliyuncs.com', //Endpoint或自定义域名,http://mydomain.com + ] + ], + 'platform' => [ + 'token' => '1234567890', + 'url' => 'https://hy.api.ctkj88.com' + ] +]; diff --git a/environments/dev/common/config/test-local.php b/environments/dev/common/config/test-local.php new file mode 100644 index 0000000..a010219 --- /dev/null +++ b/environments/dev/common/config/test-local.php @@ -0,0 +1,9 @@ + [ + 'db' => [ + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced_test', + ], + ], +]; diff --git a/environments/dev/console/config/main-local.php b/environments/dev/console/config/main-local.php new file mode 100644 index 0000000..a3246e0 --- /dev/null +++ b/environments/dev/console/config/main-local.php @@ -0,0 +1,8 @@ + ['gii'], + 'modules' => [ + 'gii' => 'yii\gii\Module', + ], +]; diff --git a/environments/dev/console/config/params-local.php b/environments/dev/console/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/dev/console/config/params-local.php @@ -0,0 +1,4 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => \yii\debug\Module::class, + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => \yii\gii\Module::class, + ]; +} + +return $config; diff --git a/environments/dev/member/config/params-local.php b/environments/dev/member/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/dev/member/config/params-local.php @@ -0,0 +1,4 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => \yii\debug\Module::class, + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => \yii\gii\Module::class, + ]; +} + +return $config; diff --git a/environments/dev/service/config/params-local.php b/environments/dev/service/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/dev/service/config/params-local.php @@ -0,0 +1,4 @@ +run(); diff --git a/environments/dev/web/admin/index.php b/environments/dev/web/admin/index.php new file mode 100644 index 0000000..2c61948 --- /dev/null +++ b/environments/dev/web/admin/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/dev/web/admin/robots.txt b/environments/dev/web/admin/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/environments/dev/web/admin/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/environments/dev/web/member/index-test.php b/environments/dev/web/member/index-test.php new file mode 100644 index 0000000..c435941 --- /dev/null +++ b/environments/dev/web/member/index-test.php @@ -0,0 +1,29 @@ +run(); diff --git a/environments/dev/web/member/index.php b/environments/dev/web/member/index.php new file mode 100644 index 0000000..3ae0678 --- /dev/null +++ b/environments/dev/web/member/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/dev/web/member/robots.txt b/environments/dev/web/member/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/environments/dev/web/member/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/environments/dev/web/service/index-test.php b/environments/dev/web/service/index-test.php new file mode 100644 index 0000000..aee31f8 --- /dev/null +++ b/environments/dev/web/service/index-test.php @@ -0,0 +1,29 @@ +run(); diff --git a/environments/dev/web/service/index.php b/environments/dev/web/service/index.php new file mode 100644 index 0000000..72671e6 --- /dev/null +++ b/environments/dev/web/service/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/dev/web/service/robots.txt b/environments/dev/web/service/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/environments/dev/web/service/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/environments/dev/yii b/environments/dev/yii new file mode 100644 index 0000000..00e939d --- /dev/null +++ b/environments/dev/yii @@ -0,0 +1,24 @@ +#!/usr/bin/env php +run(); +exit($exitCode); diff --git a/environments/index.php b/environments/index.php new file mode 100644 index 0000000..0125132 --- /dev/null +++ b/environments/index.php @@ -0,0 +1,76 @@ + [ + * 'path' => 'directory storing the local files', + * 'skipFiles' => [ + * // list of files that should only be copied once and skipped if they already exist + * ], + * 'setWritable' => [ + * // list of directories that should be set writable + * ], + * 'setExecutable' => [ + * // list of files that should be set executable + * ], + * 'setCookieValidationKey' => [ + * // list of config files that need to be inserted with automatically generated cookie validation keys + * ], + * 'createSymlink' => [ + * // list of symlinks to be created. Keys are symlinks, and values are the targets. + * ], + * ], + * ]; + * ``` + */ +return [ + 'Development' => [ + 'path' => 'dev', + 'setWritable' => [ + 'admin/runtime', + 'console/runtime', + 'member/runtime', + 'service/runtime', + + 'web/admin/assets', + 'web/member/assets', + 'web/service/assets', + ], + 'setExecutable' => [ + 'yii', + 'yii_test', + ], + 'setCookieValidationKey' => [ + 'admin/config/main-local.php', + 'common/config/codeception-local.php', + 'member/config/main-local.php', + 'service/config/main-local.php', + ], + ], + 'Production' => [ + 'path' => 'prod', + 'setWritable' => [ + 'admin/runtime', + 'console/runtime', + 'member/runtime', + 'service/runtime', + + 'web/admin/assets', + 'web/member/assets', + 'web/service/assets', + ], + 'setExecutable' => [ + 'yii', + ], + 'setCookieValidationKey' => [ + 'admin/config/main-local.php', + 'member/config/main-local.php', + 'service/config/main-local.php', + ], + ], +]; diff --git a/environments/prod/admin/config/main-local.php b/environments/prod/admin/config/main-local.php new file mode 100644 index 0000000..babe4a4 --- /dev/null +++ b/environments/prod/admin/config/main-local.php @@ -0,0 +1,10 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; diff --git a/environments/prod/admin/config/params-local.php b/environments/prod/admin/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/prod/admin/config/params-local.php @@ -0,0 +1,4 @@ + [ + 'db' => [ + 'class' => \yii\db\Connection::class, + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', + ], + 'mailer' => [ + 'class' => \yii\symfonymailer\Mailer::class, + 'viewPath' => '@common/mail', + ], + ], +]; diff --git a/environments/prod/common/config/params-local.php b/environments/prod/common/config/params-local.php new file mode 100644 index 0000000..cb1e77a --- /dev/null +++ b/environments/prod/common/config/params-local.php @@ -0,0 +1,91 @@ + [ + 'over_time' => 60,//秒,自动取消时间 + 'refund_time' => 120,//秒,医生未接诊超时自动退款 + 'accept_over_time' => 600,//秒,医生接诊后自动结束时间 + ], + 'im' => [ + 'url' => 'wss://wss.ctkj88.com/ws', + 'token' => 'tokenwebffff333', + ], + 'wechat' => [ + 'app_id' => 'wx1eb90a487ca945d2', + 'app_secret' => 'bfc4ed01e02602f2d2692cf588e66426', + 'merchant_id' => '1640496313', + 'merchant_key' => 'x80e509acd6319904b16d89fd331a988', + 'apiclient_cert' => '-----BEGIN CERTIFICATE----- +MIIEITCCAwmgAwIBAgIUX2WR15TWy6hCUBijincsyUDCdncwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjMwMzI3MDUyNzIxWhcNMjgwMzI1MDUyNzIxWjB7MRMwEQYDVQQDDAox +NjQwNDk2MzEzMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM +Hua1meaxn+iQp+W6t+WMu+iNr+aciemZkOWFrOWPuDELMAkGA1UEBgwCQ04xETAP +BgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +0Sp54iPzSy4+hPvlFIIl1rbqPb8JN+onIbj9dVQZBnOXgLBQILcfLuxLQchiZ1Xt +M85M/ddqEfaggBe1HvGs9INW6u6kvMzLo8QR39CduPBAjBNxE6+VBFXIIKsmr7qd +iv5ixDC1F5dhtcvXQ7VCM+PKtZlbEHdSlGSJmoFGDgqn5TAjlZ1nnhAtx2PJ4SpJ +GjmsGIHoPv1O4eCxbvBb3mMfV9KgCPs/H1VS9MFal8EN2X11O/rhRwQaApgYqxDZ +Ifc1PerKuzrYMtBXM05ugxQt1kLACPrg/P1eUro/8uOwGKoyOSfG8AIdUGGABiDY +zpqojvyJ9gHN9++uRCeWOQIDAQABo4G5MIG2MAkGA1UdEwQCMAAwCwYDVR0PBAQD +AgP4MIGbBgNVHR8EgZMwgZAwgY2ggYqggYeGgYRodHRwOi8vZXZjYS5pdHJ1cy5j +b20uY24vcHVibGljL2l0cnVzY3JsP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3 +NTQ5ODQ2QzAxQzNFOEVCRDImc2c9SEFDQzQ3MUI2NTQyMkUxMkIyN0E5RDMzQTg3 +QUQxQ0RGNTkyNkUxNDAzNzEwDQYJKoZIhvcNAQELBQADggEBAGWtcwXxbktlmT1l +9xwagnDLIzgzSbED13MRY/1lX5iBhX5JQ2W7goDb5QPomZ4ETNkE2jeqSU7yTb1v +xzwXITGLHXaepfAC6QG96WE9iVW4CwkrBKlLae2Eo+6v3FmCeFgBUZawg2QZO5Wr +9GDu61PxQ6do9ra0iU9HR7tLWJth4dX/1RekO5wJ50bneeSf2bERrO9E7OwpUk56 +0SFSnZSm9hi25T3z856GKtQnNwgukxMbucYHh4wgcGLfjxUz7XgzeimnFNM2Dl1C +i7HrN4HpP4M4MmyUaxUE+4py0jBz8EDQUmwN+b/AsyfbtE3uumXvvTDjXfP5Dg6Y +RvVASc0= +-----END CERTIFICATE-----', + 'apiclient_key' => '-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRKnniI/NLLj6E +++UUgiXWtuo9vwk36ichuP11VBkGc5eAsFAgtx8u7EtByGJnVe0zzkz912oR9qCA +F7Ue8az0g1bq7qS8zMujxBHf0J248ECME3ETr5UEVcggqyavup2K/mLEMLUXl2G1 +y9dDtUIz48q1mVsQd1KUZImagUYOCqflMCOVnWeeEC3HY8nhKkkaOawYgeg+/U7h +4LFu8FveYx9X0qAI+z8fVVL0wVqXwQ3ZfXU7+uFHBBoCmBirENkh9zU96sq7Otgy +0FczTm6DFC3WQsAI+uD8/V5Suj/y47AYqjI5J8bwAh1QYYAGINjOmqiO/In2Ac33 +765EJ5Y5AgMBAAECggEAdTKYooZEPx7FNxwxCmG2M+2/qCNPVf4kOPf/RGt/ria8 +gAXKj9orZc5OiKhvwrjZtMpmR2EY9MG8wqkF+jWuFD83R2G5+nPBspwc68xnY4Vy +lUobdM1P8OLjxLJBdftZZNUOoCEuhu5yeDuj/TMlyg9buI8aAErrgWwn0eOXTivU +GhVTSYf6bW3CpBZ3fxNO8KYYJyjU4tH8Ow8xYNLZRE4SFvzZmtHm20OtgUZN/aI6 +BjnOZLWpxU0Q4tdtZu5LCC3gF4Gj95lLY9GarPV2R00vnxyJyqQf29IJCWv4gD/M +DF7Y+RGR71m7hNEtKnZSeq8rWBWkgd23k6hEPX8ugQKBgQD7feaNQisVsH95zhYB +Y3BrMu0Mm1LThTwqZ73rHbpGaiLoXE2EKbcYGvwrqoZWn3echCWWOK80Q/EXx9EO +VqFbrb9/dovjKQAyivQnaBY1yDDwm9Of9sLeWRnh6+/im4AjhuP5ZDJcoYlWPfeS +dcpHcnK9NWzmW/pZS0zwH5HukQKBgQDU6ldqgtuYxPgOCiAS8yXuhhpDKe/+4uh2 +GVVyhty8kQptT5bsgpkBMEPQu3hATvuYMHVSRNWMLvtYnvSh1rMrZXIYKiwprFXi +gIbqPEEdla8/ERBs3inMhyORoGOMtgnmkfaYQhfwI4QLYbdxrtlVGTC1zpsBZHyN +gRJtO8TRKQKBgF7Lmx69xT28tKA2FUdasyJFJOMunO7L9tzJE+ZO40rtcNEDEdjy +XGiCq3DOKyr1mwFtMjnIjgn2Xicnk16DOvkyqc8i4SGz77YdeGBuNIj7N69KHV/b +hKKJFV96LobNNGSv0LjNksolvX27h9k1+xQpSKSXQcAnBVupLYwJallxAoGBAJXC +U0Re0Lku6k9tvcu2bRrOBpDxYZbF4b6X6StKQt77ofrrPXwUDCzy1vBtvJJ3O657 +fzojopUcwrw96lIfYx0GGO94UmHpjutnff4p7Z8ylvZkOUpqJbpv34vh5cOmk2Yz +iuDjtFS7lngu/kofM00RD9sBfLPJC3a4r85XeQOpAoGBANkWq6FHRYjVISdz9Olc +yieXIKzTFemVO+SZXN715HrE83wVhTmkl6+4p/C+nxeVWlAuZ8nrRCZd9+3vzqv4 +6WcLGHkclmjGv3PeatZ8vCoqZq70nsxD1sCngWMSBqQlswC2C+em/4pL4An+fWOq +JJvBfLfudYNUjUCyW3gAcOIJ +-----END PRIVATE KEY-----' + ], + /* 上传文件 */ + 'upload' => [ + 'type' => 'alioss', // local,alioss + 'image_limit' => 20,//单位M,0不限制 + 'video_limit' => 50,//单位M,0不限制 + 'local_url' => '', + 'local_path' => '', // 服务器解析到/web/目录时,上传到这里 + 'alioss' => [ + 'access_key' => 'LTAINrYfGdUKadD0', + 'secret_key' => '4mv4Uhlc6kQuY7OfaHI3tWMUcSnJlo', + 'bucket' => 'yanydy', //bucket + 'is_cname' => 0, //自定义域名,1使用,0不使用 + 'domain' => 'https://oss-cn-hangzhou.aliyuncs.com', //Endpoint或自定义域名,http://mydomain.com + ] + ], + 'platform' => [ + 'token' => '1234567890', + 'url' => 'https://hy.api.ctkj88.com' + ] +]; diff --git a/environments/prod/console/config/main-local.php b/environments/prod/console/config/main-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/prod/console/config/main-local.php @@ -0,0 +1,4 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; diff --git a/environments/prod/member/config/params-local.php b/environments/prod/member/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/prod/member/config/params-local.php @@ -0,0 +1,4 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; diff --git a/environments/prod/service/config/params-local.php b/environments/prod/service/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/environments/prod/service/config/params-local.php @@ -0,0 +1,4 @@ +run(); diff --git a/environments/prod/web/admin/robots.txt b/environments/prod/web/admin/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/environments/prod/web/admin/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/environments/prod/web/member/index.php b/environments/prod/web/member/index.php new file mode 100644 index 0000000..b75da57 --- /dev/null +++ b/environments/prod/web/member/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/prod/web/member/robots.txt b/environments/prod/web/member/robots.txt new file mode 100644 index 0000000..14267e9 --- /dev/null +++ b/environments/prod/web/member/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / \ No newline at end of file diff --git a/environments/prod/web/service/index.php b/environments/prod/web/service/index.php new file mode 100644 index 0000000..042f7bd --- /dev/null +++ b/environments/prod/web/service/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/prod/web/service/robots.txt b/environments/prod/web/service/robots.txt new file mode 100644 index 0000000..14267e9 --- /dev/null +++ b/environments/prod/web/service/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / \ No newline at end of file diff --git a/environments/prod/yii b/environments/prod/yii new file mode 100644 index 0000000..293565e --- /dev/null +++ b/environments/prod/yii @@ -0,0 +1,24 @@ +#!/usr/bin/env php +run(); +exit($exitCode); diff --git a/init b/init new file mode 100644 index 0000000..cf472c9 --- /dev/null +++ b/init @@ -0,0 +1,356 @@ +#!/usr/bin/env php + $name) { + echo " [$i] $name\n"; + } + echo "\n Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] '; + $answer = trim(fgets(STDIN)); + + if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) { + echo "\n Quit initialization.\n"; + exit(0); + } + + if (isset($envNames[$answer])) { + $envName = $envNames[$answer]; + } +} else { + $envName = $params['env']; +} + +if (!in_array($envName, $envNames, true)) { + $envsList = implode(', ', $envNames); + echo "\n $envName is not a valid environment. Try one of the following: $envsList. \n"; + exit(2); +} + +$env = $envs[$envName]; + +if (empty($params['env'])) { + echo "\n Initialize the application under '{$envNames[$answer]}' environment? [yes|no] "; + $answer = trim(fgets(STDIN)); + if (strncasecmp($answer, 'y', 1)) { + echo "\n Quit initialization.\n"; + exit(0); + } +} + +$rootPath = "$root/environments/{$env['path']}"; +if (!is_dir($rootPath)) { + printError("$rootPath directory does not exist. Check path in $envName environment."); + exit(3); +} + +echo "\n Start initialization ...\n\n"; + +$files = getFileList($rootPath); +if (isset($env['skipFiles'])) { + $skipFiles = $env['skipFiles']; + array_walk($skipFiles, function(&$value) use($env, $root) { $value = "$root/$value"; }); + $files = array_diff($files, array_intersect_key($env['skipFiles'], array_filter($skipFiles, 'file_exists'))); +} +$all = false; +foreach ($files as $file) { + if (!copyFile($root, "environments/{$env['path']}/$file", $file, $all, $params)) { + break; + } +} + +$filesToRemove = []; +$skipFiles = !empty($env['skipFiles']) ? $env['skipFiles'] : []; +foreach(array_column($envs, 'path') as $envPath) { + if ($env['path'] === $envPath) continue; + + $filesToRemove = + array_merge( + $filesToRemove, + array_diff(getFileList("$root/environments/{$envPath}"), $files, $filesToRemove, $skipFiles) + ); +} +$filesToRemove = array_filter($filesToRemove, 'file_exists'); +if ($filesToRemove) { + echo "\n Remove files from other environments ...\n\n"; + + $all = false; + foreach ($filesToRemove as $file) { + if (!removeFile($root, $file, $all, $params)) { + break; + } + } + echo "\n"; +} + +$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink']; +foreach ($callbacks as $callback) { + if (!empty($env[$callback])) { + $callback($root, $env[$callback]); + } +} + +echo "\n ... initialization completed.\n\n"; + +function getFileList($root, $basePath = '') +{ + $files = []; + $handle = opendir($root); + while (($path = readdir($handle)) !== false) { + if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') { + continue; + } + $fullPath = "$root/$path"; + $relativePath = $basePath === '' ? $path : "$basePath/$path"; + if (is_dir($fullPath)) { + $files = array_merge($files, getFileList($fullPath, $relativePath)); + } else { + $files[] = $relativePath; + } + } + closedir($handle); + return $files; +} + +function copyFile($root, $source, $target, &$all, $params) +{ + if (!is_file($root . '/' . $source)) { + echo " skip $target ($source not exist)\n"; + return true; + } + if (is_file($root . '/' . $target)) { + if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) { + echo " unchanged $target\n"; + return true; + } + if ($all) { + echo " overwrite $target\n"; + } else { + echo " exist $target\n"; + echo " ...overwrite? [Yes|No|All|Quit] "; + + + $answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN)); + if (!strncasecmp($answer, 'q', 1)) { + return false; + } else { + if (!strncasecmp($answer, 'y', 1)) { + echo " overwrite $target\n"; + } else { + if (!strncasecmp($answer, 'a', 1)) { + echo " overwrite $target\n"; + $all = true; + } else { + echo " skip $target\n"; + return true; + } + } + } + } + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source)); + return true; + } + echo " generate $target\n"; + @mkdir(dirname($root . '/' . $target), 0777, true); + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source)); + return true; +} + +function removeFile($root, $target, &$all, $params) +{ + if (is_file($root . '/' . $target)) { + if ($all) { + echo " delete $target\n"; + } else { + echo " delete $target\n"; + echo " ...confirm? [Yes|No|All|Quit] "; + + $answer = !empty($params['delete']) ? $params['delete'] : trim(fgets(STDIN)); + if (!strncasecmp($answer, 'q', 1)) { + return false; + } else { + if (!strncasecmp($answer, 'y', 1)) { + echo " delete $target\n"; + } else { + if (!strncasecmp($answer, 'a', 1)) { + echo " delete $target\n"; + $all = true; + } else { + echo " skip $target\n"; + return true; + } + } + } + } + return unlink($root . '/' . $target); + } + + return true; +} + +function getParams() +{ + $rawParams = []; + if (isset($_SERVER['argv'])) { + $rawParams = $_SERVER['argv']; + array_shift($rawParams); + } + + $params = []; + foreach ($rawParams as $param) { + if (preg_match('/^--([\w-]*\w)(=(.*))?$/', $param, $matches)) { + $name = $matches[1]; + $params[$name] = isset($matches[3]) ? $matches[3] : true; + } else { + $params[] = $param; + } + } + return $params; +} + +function setWritable($root, $paths) +{ + foreach ($paths as $writable) { + if (is_dir("$root/$writable")) { + if (@chmod("$root/$writable", 0777)) { + echo " chmod 0777 $writable\n"; + } else { + printError("Operation chmod not permitted for directory $writable."); + } + } else { + printError("Directory $writable does not exist."); + } + } +} + +function setExecutable($root, $paths) +{ + foreach ($paths as $executable) { + if (file_exists("$root/$executable")) { + if (@chmod("$root/$executable", 0755)) { + echo " chmod 0755 $executable\n"; + } else { + printError("Operation chmod not permitted for $executable."); + } + } else { + printError("$executable does not exist."); + } + } +} + +function setCookieValidationKey($root, $paths) +{ + foreach ($paths as $file) { + echo " generate cookie validation key in $file\n"; + $file = $root . '/' . $file; + $length = 32; + $bytes = openssl_random_pseudo_bytes($length); + $key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.'); + $content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file)); + file_put_contents($file, $content); + } +} + +function createSymlink($root, $links) +{ + foreach ($links as $link => $target) { + //first removing folders to avoid errors if the folder already exists + @rmdir($root . "/" . $link); + //next removing existing symlink in order to update the target + if (is_link($root . "/" . $link)) { + @unlink($root . "/" . $link); + } + if (@symlink($root . "/" . $target, $root . "/" . $link)) { + echo " symlink $root/$target $root/$link\n"; + } else { + printError("Cannot create symlink $root/$target $root/$link."); + } + } +} + +/** + * Prints error message. + * @param string $message message + */ +function printError($message) +{ + echo "\n " . formatMessage("Error. $message", ['fg-red']) . " \n"; +} + +/** + * Returns true if the stream supports colorization. ANSI colors are disabled if not supported by the stream. + * + * - windows without ansicon + * - not tty consoles + * + * @return boolean true if the stream supports ANSI colors, otherwise false. + */ +function ansiColorsSupported() +{ + return DIRECTORY_SEPARATOR === '\\' + ? getenv('ANSICON') !== false || getenv('ConEmuANSI') === 'ON' + : function_exists('posix_isatty') && @posix_isatty(STDOUT); +} + +/** + * Get ANSI code of style. + * @param string $name style name + * @return integer ANSI code of style. + */ +function getStyleCode($name) +{ + $styles = [ + 'bold' => 1, + 'fg-black' => 30, + 'fg-red' => 31, + 'fg-green' => 32, + 'fg-yellow' => 33, + 'fg-blue' => 34, + 'fg-magenta' => 35, + 'fg-cyan' => 36, + 'fg-white' => 37, + 'bg-black' => 40, + 'bg-red' => 41, + 'bg-green' => 42, + 'bg-yellow' => 43, + 'bg-blue' => 44, + 'bg-magenta' => 45, + 'bg-cyan' => 46, + 'bg-white' => 47, + ]; + return $styles[$name]; +} + +/** + * Formats message using styles if STDOUT supports it. + * @param string $message message + * @param string[] $styles styles + * @return string formatted message. + */ +function formatMessage($message, $styles) +{ + if (empty($styles) || !ansiColorsSupported()) { + return $message; + } + + return sprintf("\x1b[%sm", implode(';', array_map('getStyleCode', $styles))) . $message . "\x1b[0m"; +} diff --git a/init.bat b/init.bat new file mode 100644 index 0000000..1b92c19 --- /dev/null +++ b/init.bat @@ -0,0 +1,15 @@ +@echo off + +rem ------------------------------------------------------------- +rem Yii command line init script for Windows. +rem ------------------------------------------------------------- + +@setlocal + +set YII_PATH=%~dp0 + +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe + +"%PHP_COMMAND%" "%YII_PATH%init" %* + +@endlocal diff --git a/member/Dockerfile b/member/Dockerfile new file mode 100644 index 0000000..a0487d2 --- /dev/null +++ b/member/Dockerfile @@ -0,0 +1,4 @@ +FROM yiisoftware/yii2-php:8.1-apache + +# Change document root for Apache +RUN sed -i -e 's|/app/web|/app/frontend/web|g' /etc/apache2/sites-available/000-default.conf diff --git a/member/behaviors/MallBehavior.php b/member/behaviors/MallBehavior.php new file mode 100644 index 0000000..7f33fdd --- /dev/null +++ b/member/behaviors/MallBehavior.php @@ -0,0 +1,21 @@ +request->post('store_id')??\Yii::$app->request->get('store_id'); + if(!$store_id && $action->id !='login'&& $action->id !='phone-number'&& $action->id !='send-code' && $action->id !='config'){ + throw new Exception('缺少store_id参数'); + } + $store=$store_id??11001; + \Yii::$app->store = $store; + + return true; + } +} \ No newline at end of file diff --git a/member/codeception.yml b/member/codeception.yml new file mode 100644 index 0000000..5d3ed5d --- /dev/null +++ b/member/codeception.yml @@ -0,0 +1,15 @@ +namespace: frontend\tests +actor_suffix: Tester +paths: + tests: tests + output: tests/_output + data: tests/_data + support: tests/_support +bootstrap: _bootstrap.php +settings: + colors: true + memory_limit: 1024M +modules: + config: + Yii2: + configFile: 'config/codeception-local.php' diff --git a/member/config/.gitignore b/member/config/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/member/config/bootstrap.php b/member/config/bootstrap.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/member/config/bootstrap.php @@ -0,0 +1 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => 'aXQWwoTfWr8mqaC7JtTehd1uIPMOZtVZ', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => \yii\debug\Module::class, + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => \yii\gii\Module::class, + ]; +} + +return $config; diff --git a/member/config/main.php b/member/config/main.php new file mode 100644 index 0000000..f6179d4 --- /dev/null +++ b/member/config/main.php @@ -0,0 +1,67 @@ + 'app-frontend', + 'basePath' => dirname(__DIR__), + 'bootstrap' => ['log'], + 'controllerNamespace' => 'member\controllers', + 'modules' => [ + 'v1' => [ + 'class' => 'member\modules\v1\Module', + ], + 'doc'=>[ + 'class' => 'cfd\doc\Module', + 'modelsMap'=>[ + '\common\models\\', + '\common\modelsgii\\', + ] + ], + ], + 'components' => [ + 'request' => [ + 'csrfParam' => '_csrf-frontend', + ], + 'response' => [ + 'class' => 'yii\web\Response', + 'format' => \yii\web\Response::FORMAT_JSON, + 'formatters' => [ + \yii\web\Response::FORMAT_JSON => [ + 'class' => 'common\foundation\JsonResponseFormatter', + 'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode + 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, + ], + ], + ], + 'user' => [ + 'identityClass' => 'member\models\User', + 'enableAutoLogin' => true, + 'enableSession'=>false, +// 'identityCookie' => ['name' => '_identity-app', 'httpOnly' => true], + ], + // 'log' => [ + // 'traceLevel' => YII_DEBUG ? 3 : 0, + // 'targets' => [ + // [ + // 'class' => \yii\log\FileTarget::class, + // 'levels' => ['error', 'warning'], + // ], + // ], + // ], +// 'errorHandler' => [ +// 'errorAction' => 'site/error', +// ], + 'urlManager' => [ + 'enablePrettyUrl' => true, + 'showScriptName' => false, + 'rules' => [ + ], + ], + ], + 'params' => $params, +]; diff --git a/member/config/params-local.php b/member/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/member/config/params-local.php @@ -0,0 +1,4 @@ + 'admin@example.com', +]; diff --git a/member/config/test-local.php b/member/config/test-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/member/config/test-local.php @@ -0,0 +1,4 @@ + 'app-frontend-tests', + 'components' => [ + 'assetManager' => [ + 'basePath' => __DIR__ . '/../web/assets', + ], + 'urlManager' => [ + 'showScriptName' => true, + ], + 'request' => [ + 'cookieValidationKey' => 'test', + ], + 'mailer' => [ + 'messageClass' => \yii\symfonymailer\Message::class + ] + ], +]; diff --git a/member/models/User.php b/member/models/User.php new file mode 100644 index 0000000..27d2bd8 --- /dev/null +++ b/member/models/User.php @@ -0,0 +1,80 @@ + $id]); + } + + public static function findIdentityByAccessToken($token, $type = null) + { + $pos = strrpos($token,'_'); + if(!$pos){ + return false; + } + $user = static::find()->where(['token' => $token])->one(); + if(!$user){ + return false; + } + $time = substr($token,$pos+1); + if($time + 30*24*60*60 < time()){ + return false; + } + return $user; + } + + public function getId() + { + return $this->id; + } + + /** + * --------------------------------------- + * 获取密码干扰字符串 + * @return string + * --------------------------------------- + */ + public function getAuthKey() + { + return $this->salt; + } + + /** + * --------------------------------------- + * 验证 + * @param string $authKey + * @return bool + * --------------------------------------- + */ + public function validateAuthKey($authKey) + { + return $this->getAuthKey() === $authKey; + } + + /** + * 验证密码 + * + * @param string $password password to validate + * @return boolean if password provided is valid for current user + */ + public function validatePassword($password) + { + return Yii::$app->security->validatePassword($password, $this->password); + } + + /** + * 设置加密后的密码 + * + * @param string $password + */ + public function setPassword($password) + { + $this->password = Yii::$app->security->generatePasswordHash($password); + } +} diff --git a/member/models/forms/AddressForm.php b/member/models/forms/AddressForm.php new file mode 100644 index 0000000..9846d22 --- /dev/null +++ b/member/models/forms/AddressForm.php @@ -0,0 +1,127 @@ +validate()){ + throw new Exception($this->getErrorMsg()); + } + + $address=new Address(); + $address->name=$this->name; + $address->user_id=\Yii::$app->user->identity->getId(); + $address->mobile=$this->mobile; + $address->province=$this->province; + $address->city=$this->city; + $address->area=$this->area; + $address->region=$this->region; + $address->detail_address=$this->detail_address; + $address->save(); + + } + + public function edit($post) + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $address=Address::find()->where([ + 'id'=>$post['id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + 'is_delete'=>0, + ])->one(); + if (!$address)throw new Exception('暂无该收货地址'); + + if($this->province && $this->province != $address->province){ + $address->province = $this->province; + $address->city=$this->city; + $address->area=$this->area; + } + $address->name = $this->name; + $address->mobile = $this->mobile; + $address->region = $this->region; + $address->detail_address = $this->detail_address; + $address->save(); + } + + + public function UpdateDefault($post) + { + $address=Address::find()->where([ + 'id'=>$post['id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + 'is_delete'=>0, + ])->one(); + if (!$address)throw new Exception('暂无该收货地址'); + + $t=\Yii::$app->db->beginTransaction(); + try { + Address::updateAll([ + 'is_default'=>0, + ],[ + 'user_id'=>\Yii::$app->user->identity->getId(), + 'is_delete'=>0, + ]); + \Yii::$app->db->createCommand()->update('yii_address',[ + 'is_default'=>1, + ],[ + 'id'=>$post['id'], + 'is_delete'=>0, + ])->execute(); + $t->commit(); + } + catch (\Exception $e){ + $t->rollBack(); + throw new $e; + } + + } + public function del($post) + { + $address=Address::find()->where([ + 'id'=>$post['id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + 'is_delete'=>0, + ])->one(); + if (!$address)throw new Exception('暂无该收货地址'); + + Address::updateAll([ + 'is_delete'=>1, + ],[ + 'id'=>$post['id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + ]); + + } +} \ No newline at end of file diff --git a/member/models/forms/AskForm.php b/member/models/forms/AskForm.php new file mode 100644 index 0000000..1eb49db --- /dev/null +++ b/member/models/forms/AskForm.php @@ -0,0 +1,293 @@ + [10, 255]], + ['images', 'checkImages'], + ['patient_id','checkPatient'], + ['is_visit','default','value'=> 0], + ['visit_desc','required','when'=>function($model){ + return $model->is_visit == 1; + }], + ['visit_desc','default','value'=>''], + + [['liver_function', 'renal_function', 'allergic_status', 'person_status','family_status'], 'default', 'value' => 0], + [['allergic_history', 'person_history', 'family_history'], 'default', 'value' => '[]'], + + ['allergic_history','required','when'=>function($model){ + return $model->allergic_status == 1; + }], + ['person_history','required','when'=>function($model){ + return $model->person_status == 1; + }], + ['family_history','required','when'=>function($model){ + return $model->family_status == 1; + }], + ]; + } + + public function checkImages($attribute, $params) + { + $images = json_decode($this->images,true); + if(empty($images)){ + $this->addError($attribute, '检查报告或患处图片不能为空'); + } + } + + public function checkPatient($attribute, $params) + { + $patient = UserPatient::find()->where([ + 'id' => $this->patient_id, + 'user_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0, + ])->one(); + if(!$patient){ + $this->addError($attribute, '患者不存在'); + } + $this->patient_data = ArrayHelper::toArray($patient,[ + UserPatient::class => [ + 'id','name','id_card','sex','relation','mobile','is_default','avatar' +// 'age' => function($model){ +// return FuncHelper::getAgeFromIdNo($model->id_card); +// }, + ] + ]); + } + + public function attributeLabels() + { + return [ + 'desc' => '病情', + 'images' => '报告或患者图片', + 'patient_id' => '就诊人', + 'is_visit' => '是否就诊过', + 'visit_desc' => '实体医院就诊确诊病例名称', + 'liver_function' => '肝功能', + 'renal_function' => '肾功能', + 'allergic_history' => '过敏史', + 'person_history' => '个人病史', + 'family_history' => '家庭病史', + ]; + } + + public function save() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + + //咨询的医生 + $doctor = ServiceUser::find()->where([ + 'id' => $this->doctor_id, + 'is_delete' => 0, + 'status' => UserStatusEnum::OK + ])->with('docService')->one(); + if(!$doctor){ + throw new Exception('医生不存在'); + } + if(!$doctor->docService->image_limit_status){ + throw new Exception('医生未开通图文问诊服务'); + } + $t = \Yii::$app->db->beginTransaction(); + try { + $UserInquiry = new UserInquiry(); + $UserInquiry->attributes = $this->attributes; + $UserInquiry->su_id = $this->doctor_id; + $UserInquiry->user_id = \Yii::$app->user->identity->id; + $UserInquiry->patient_data = json_encode($this->patient_data); + $UserInquiry->saveOrFail(); + + $order = new Order(); + $order->user_id = \Yii::$app->user->identity->id; + $order->su_id = $this->doctor_id; + $order->up_id=$this->patient_id; + $order->type = $this->type; + $order->ui_id = $UserInquiry->id; + $order->order_no = FuncHelper::generate_order_no('SN'); + $order->total_pay_price = $doctor->docService->register_price; + $order->saveOrFail(); + + $event = new OrderEvent();//触发订单创建事件 + $event->order = $order; + $event->sender = $this; + \Yii::$app->trigger(Order::EVENT_CREATED, $event); + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + return ['order_id' => $order->id]; + } + + public function saves() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + + //咨询的医生 + $doctor = ServiceUser::find()->where([ + 'id' => $this->doctor_id, + 'is_delete' => 0, + 'status' => UserStatusEnum::OK + ])->with('docService')->one(); + if(!$doctor){ + throw new Exception('医生不存在'); + } + switch ($this->type){ + case 1: + if(!$doctor->docService->image_limit_status){ + throw new Exception('医生未开通图文问诊服务'); + } + $t = \Yii::$app->db->beginTransaction(); + try { + $UserInquiry = new UserInquiry(); + $UserInquiry->attributes = $this->attributes; + $UserInquiry->su_id = $this->doctor_id; + $UserInquiry->up_id=$this->patient_id; + $UserInquiry->store_id=$this->store_id; + $UserInquiry->user_id = \Yii::$app->user->identity->id; + $UserInquiry->patient_data = json_encode($this->patient_data); + $UserInquiry->saveOrFail(); + //医生患者 + $DoctorPatient=new DoctorPatient(); + $DoctorPatient->user_id=\Yii::$app->user->identity->id; + $DoctorPatient->su_id=$this->doctor_id; + $DoctorPatient->up_id=$this->patient_id; + $data=$this->patient_data; + $DoctorPatient->name=$data['name']; + $DoctorPatient->avatar=$data['avatar']??''; + $DoctorPatient->id_card=$data['id_card']; + $DoctorPatient->sex=$data['sex']; + $DoctorPatient->saveOrFail(); + + + //创建订单 + $order = new Order(); + $order->user_id = \Yii::$app->user->identity->id; + $order->su_id = $this->doctor_id; + $order->up_id=$this->patient_id; + $order->type = $this->type; + $order->ui_id = $UserInquiry->id; + $order->store_id=$this->store_id; + $order->order_no = FuncHelper::generate_order_no('SN'); + $order->total_pay_price = $doctor->docService->register_price; + $order->saveOrFail(); + + $event = new OrderEvent();//触发订单创建事件 + $event->order = $order; + $event->sender = $this; + \Yii::$app->trigger(Order::EVENT_CREATED, $event); + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + return ['order_id' => $order->id]; + + case 2: + if(!$doctor->docService->video_limit_status){ + throw new Exception('医生未开通视频问诊服务'); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $UserInquiry = new UserInquiry(); + $UserInquiry->attributes = $this->attributes; + $UserInquiry->su_id = $this->doctor_id; + $UserInquiry->up_id=$this->patient_id; + $UserInquiry->user_id = \Yii::$app->user->identity->id; + $UserInquiry->store_id = $this->store_id; + $UserInquiry->patient_data = json_encode($this->patient_data); + $UserInquiry->saveOrFail(); + //创建订单 + $order = new Order(); + $order->user_id = \Yii::$app->user->identity->id; + $order->su_id = $this->doctor_id; + $order->up_id=$this->patient_id; + $order->type = $this->type; + $order->ui_id = $UserInquiry->id; + $order->store_id=$this->store_id; + $order->order_no = FuncHelper::generate_order_no('SN'); + $order->saveOrFail(); + + //医生患者 + $DoctorPatient=new DoctorPatient(); + $DoctorPatient->user_id=\Yii::$app->user->identity->id; + $DoctorPatient->su_id=$this->doctor_id; + $DoctorPatient->up_id=$this->patient_id; + $data=$this->patient_data; + $DoctorPatient->name=$data['name']; + $DoctorPatient->avatar=$data['avatar']??''; + $DoctorPatient->id_card=$data['id_card']; + $DoctorPatient->sex=$data['sex']; + $DoctorPatient->saveOrFail(); + + + //创建视频问诊视频通话信息 + $OrderVideoInfo=new OrderVideoInfo(); + $OrderVideoInfo->order_id=$order->id; + $OrderVideoInfo->user_id=\Yii::$app->user->identity->getId(); + $OrderVideoInfo->su_id=$this->doctor_id; + $OrderVideoInfo->is_limit=1; + $OrderVideoInfo->order_limit_minutes=10; + $OrderVideoInfo->left_minutes=10; + $OrderVideoInfo->saveOrFail(); + + $event = new OrderEvent();//触发订单创建事件 + $event->order = $order; + $event->sender = $this; + \Yii::$app->trigger(Order::EVENT_CREATED, $event); + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + + return ['order_id' => $order->id]; + } + } +} diff --git a/member/models/forms/CommentForm.php b/member/models/forms/CommentForm.php new file mode 100644 index 0000000..7a3d05d --- /dev/null +++ b/member/models/forms/CommentForm.php @@ -0,0 +1,59 @@ +where([ + 'id'=>$id, + 'su_id'=>$this->su_id, + 'u_id'=>$this->u_id + ])->one(); + + if (!$userComment) throw new Exception('评价不存在'); + + $userComment->delete(); + + } + + public function edit($id) + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg($this)); + } + $userComment=UserComment::find()->where([ + 'id'=>$id, + 'su_id'=>$this->su_id, + 'u_id'=>$this->u_id + ])->one(); + + if (!$userComment) throw new Exception('评价不存在'); + + UserComment::updateAll(['score'=>$this->score,'comment'=>$this->comment],['id'=>$id,'su_id'=>$this->su_id, + 'u_id'=>$this->u_id]); + + } + +} \ No newline at end of file diff --git a/member/models/forms/FollowForm.php b/member/models/forms/FollowForm.php new file mode 100644 index 0000000..7c00c72 --- /dev/null +++ b/member/models/forms/FollowForm.php @@ -0,0 +1,67 @@ +validate()){ + throw new Exception($this->getErrorMsg()); + } + $su_ids = FollowDoctor::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + ])->select('su_id')->column(); + + if (in_array($this->su_id ,$su_ids)) { + throw new Exception('已关注该医生'); + } + + $FollowDoctor=new FollowDoctor(); + $FollowDoctor->attributes=$this->attributes; + $FollowDoctor->user_id=\Yii::$app->user->identity->id; + $FollowDoctor->saveOrFail(); + } + + public function cancel() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $su_ids = FollowDoctor::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + ])->select('su_id')->column(); + + if (!in_array($this->su_id ,$su_ids)) { + throw new Exception('你还没有关注该医生'); + } + + \Yii::$app->db->createCommand()->delete('yii_follow_doctor', ['user_id' => \Yii::$app->user->identity->id, 'su_id' => $this->su_id])->execute(); + + } + + + public function attributeLabels() + { + return [ + 'su_id' => '医生id', + ]; + } + +} \ No newline at end of file diff --git a/member/models/forms/HealthForm.php b/member/models/forms/HealthForm.php new file mode 100644 index 0000000..93ec637 --- /dev/null +++ b/member/models/forms/HealthForm.php @@ -0,0 +1,134 @@ +0], + + [['family_history','allergic_history','person_history','liver_index','renal_index'],'default','value'=>[]], + + ['family_history','required','when'=>function($model){ + return $model->family_status==1; + }], + ['allergic_history','required','when'=>function($model){ + return $model->allergic_status==1; + }], + ['person_history','required','when'=>function($model){ + return $model->person_status==1; + }], + ['liver_index','required','when'=>function($model){ + return $model->liver_function==1; + }], + ['renal_index','required','when'=>function($model){ + return $model->renal_function==1; + }], + ]; + } + + public function save() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $UserPatient=UserPatient::find()->where([ + 'id'=>$this->user_patient_id, + 'user_id'=>\Yii::$app->user->identity->getId(), + 'is_delete'=>0 + ])->one(); + + if (!$UserPatient){ + throw new Exception('患者不存在'); + } + + $UserPatientHealthInquiry= UserPatientHealthInquiry::find()->where([ + 'user_patient_id'=>$this->user_patient_id, + 'is_delete'=>0 + ])->one(); + + if (!$UserPatientHealthInquiry){ + $UserPatientHealthInquiry=new UserPatientHealthInquiry(); + } + + $UserPatientHealthInquiry->attributes=$this->attributes; + $UserPatientHealthInquiry->saveOrFail(); + return ['保存成功']; + } + + + public function del() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $UserPatient=UserPatient::find()->where([ + 'id'=>$this->user_patient_id, + 'user_id'=>\Yii::$app->user->identity->getId(), + 'is_delete'=>0 + ])->one(); + + if (!$UserPatient){ + throw new Exception('患者不存在'); + } + $UserPatientHealthInquiry= UserPatientHealthInquiry::find()->where([ + 'user_patient_id'=>$this->user_patient_id, + 'is_delete'=>0 + ])->one(); + + if (!$UserPatientHealthInquiry){ + throw new Exception('健康信息不存在'); + } + $UserPatientHealthInquiry->is_delete=1; + $UserPatientHealthInquiry->update(); + return ['删除成功']; + } + + public function info() + { + $user_id= \Yii::$app->user->identity->getId(); + + $patient = \common\models\UserPatient::findOne([ + 'id' => $this->user_patient_id, + 'user_id' =>$user_id, + 'is_delete' => 0 + ]); + if (!$patient) { + throw new \yii\base\Exception('就诊人不存在'); + } + $UserPatientHealthInquiry= UserPatientHealthInquiry::find()->where([ + 'user_patient_id'=>$this->user_patient_id, + 'is_delete'=>0 + ])->one(); + + if (!$UserPatientHealthInquiry){ + throw new Exception('健康信息不存在'); + } + return $UserPatientHealthInquiry; + } +} \ No newline at end of file diff --git a/member/models/forms/LoginForm.php b/member/models/forms/LoginForm.php new file mode 100644 index 0000000..049c714 --- /dev/null +++ b/member/models/forms/LoginForm.php @@ -0,0 +1,336 @@ + '状态', + 'code' => '微信code', + 'iv' => 'iv', + 'encryptedData' => 'encryptedData', + 'mobile' => '手机号', + 'smsCode' => '验证码', + ]; + } + + public function userlogin() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + switch ($this->status) { + case 1;//微信一键登录 + if (!$this->code) { + throw new \yii\db\Exception('code不能为空'); + } + return $this->login(); + + case 3://手机号登录 + if (!$this->mobile) { + throw new \yii\db\Exception('mobile不能为空'); + } + + if (!$this->smsCode) throw new \yii\db\Exception('验证码不能为空'); + + return $this->phoneLogin(); + case 4://手机号注册 + if (!$this->mobile) throw new \yii\db\Exception('mobile不能为空'); + + if (!$this->smsCode) throw new \yii\db\Exception('验证码不能为空'); + + return $this->PhoneRegister(); + case 5://开发登录 + if (!YII_DEBUG) { + die(); + } + $user = User::findOne(['mobile' => $this->mobile]); + if (!$user) { + throw new \yii\db\Exception('用户不存在'); + } + $t = Yii::$app->db->beginTransaction(); + try { + $user->mobile = $this->mobile; + $user->nickname = $user->nickname ?? '微信用户'; + $token = Yii::$app->security->generateRandomString() . '_' . time(); + $user->token = $token; + $user->saveOrFail(); + + $storeUser = StoreUser::find()->where([ + 'user_id' => $user->id, + 'store_id' => Yii::$app->store, + ])->one(); + + if (!$storeUser) { + //用户关联门店 + $StoreUser = new StoreUser(); + $StoreUser->store_id = Yii::$app->store; + $StoreUser->user_id = $user->id; + $StoreUser->is_online = 1; + $StoreUser->last_login_time = time(); + $StoreUser->saveOrFail(); + } else { + StoreUser::updateAll(['last_login_time' => time()], [ + 'user_id' => $user->id, + 'store_id' => Yii::$app->store, + 'is_delete' => 0 + ]); + } + + $t->commit(); + return [ + 'token' => $token, + 'data' => $storeUser, + ]; + } catch (\Exception $e) { + $t->rollBack(); + throw new \yii\db\Exception($e->getMessage()); + } + break; + } + } + + /** + * 微信登录 + */ + public function login() + { + $transaction = Yii::$app->db->beginTransaction(); + try { + $login = WechatService::getInstance()->app->auth->session($this->code); + if (isset($login['errmsg'])) { + throw new Exception($login['errmsg']); + } + + $user = User::find()->where(['openid' => $login['openid'], 'is_delete' => 0])->one(); + + if (!$user) { + $user = new User(); + } + + + $user->openid = $login['openid']; + $user->session_key = $login['session_key']; + $user->unionid = isset($login['unionid']) ? $login['unionid'] : ''; + $token = Yii::$app->security->generateRandomString() . '_' . time(); + $user->token = $token; + $user->nickname = $user['nickname'] ?? '微信用户'; + $user->current_store_id = Yii::$app->store;//当前门店 + $user->saveOrFail(); + + $storeUser = StoreUser::find()->where([ + 'user_id' => $user->id, + 'store_id' => Yii::$app->store, + ])->one(); + if (!$storeUser) { + //用户关联门店 + $StoreUser = new StoreUser(); + $StoreUser->store_id = Yii::$app->store; + $StoreUser->user_id = $user->id; + $StoreUser->is_online = 1; + $StoreUser->last_login_time = time(); + $StoreUser->saveOrFail(); + } else { + StoreUser::updateAll(['last_login_time' => time()], [ + 'user_id' => $user->id, + 'store_id' => Yii::$app->store, + 'is_delete' => 0 + ]); + } + + $transaction->commit(); + } catch (Exception $exception) { + $transaction->rollBack(); + throw new Exception('登录失败:' . $exception->getMessage() . ' APPID:' . WechatService::getInstance()->app->getConfig()['app_id']); + } + + $StoreUser = StoreUser::find()->where([ + 'user_id' => $user->id, + ])->with(['user'])->orderBy(['last_login_time' => SORT_DESC]) + ->asArray()->one(); + return [ + 'token' => $token, + 'data' => $StoreUser, + 'platform_token' => "Bearer ".Yii::$app->params['platform']['token'], + 'user_id' => $user->id + ]; + } + + + + /** + * 手机号登录 + */ + public function phoneLogin() + { + $cache = Yii::$app->cache; + + if ($cache->get('login_sms_code_' . $this->mobile)) { + if ($cache->get('login_sms_code_' . $this->mobile) != $this->smsCode) { + throw new Exception('手机验证码错误'); + } + + $t = Yii::$app->db->beginTransaction(); + try { + $user = User::findOne(['mobile' => $this->mobile]); + if (!$user) { + throw new \yii\db\Exception('您还没有注册,请先注册'); + } + $user->mobile = $this->mobile; + $user->nickname = $user->nickname ?? '微信用户'; + $token = Yii::$app->security->generateRandomString() . '_' . time(); + $user->token = $token; + $user->saveOrFail(); + + $storeUser = StoreUser::find()->where([ + 'user_id' => $user->id, + 'store_id' => Yii::$app->store, + ])->one(); + if (!$storeUser) { + //用户关联门店 + $StoreUser = new StoreUser(); + $StoreUser->store_id = Yii::$app->store; + $StoreUser->user_id = $user->id; + $StoreUser->is_online = 1; + $StoreUser->last_login_time = time(); + $StoreUser->saveOrFail(); + } else { + StoreUser::updateAll(['last_login_time' => time()], [ + 'user_id' => $user->id, + 'store_id' => Yii::$app->store, + 'is_delete' => 0 + ]); + } + + $t->commit(); + return [ + 'token' => $token, + 'data' => $storeUser, + 'platform_token' => "Bearer ".Yii::$app->params['platform']['token'], + 'user_id' => $user->id + ]; + } catch (\Exception $e) { + $t->rollBack(); + throw new \yii\db\Exception($e->getMessage()); + } + } else { + throw new Exception('验证码已过期,请从新获取验证码'); + } + } + + /** + * 手机号注册 + */ + public function PhoneRegister() + { + $cache = Yii::$app->cache; + + if ($cache->get('login_sms_code_' . $this->mobile)) { + if ($cache->get('login_sms_code_' . $this->mobile) != $this->smsCode) { + throw new Exception('手机验证码错误'); + } + + try { + $t = Yii::$app->db->beginTransaction(); + $user = User::findOne(['mobile' => $this->mobile]); + if ($user) { + throw new \yii\db\Exception('您已注册,请登录'); + } + + $addUsers = new User(); + $addUsers->mobile = $this->mobile; + $addUsers->nickname = $user->nickname ?? '微信用户'; + $addUsers->avatarurl = $user->avatarurl ?? 'https://tenfei03.cfp.cn/creative/vcg/veer/1600water/veer-105516317.jpg'; + $token = Yii::$app->security->generateRandomString() . '_' . time(); + $addUsers->token = $token; + $addUsers->saveOrFail(); + + //用户门店 + $storeUser = StoreUser::find()->where([ + 'user_id' => $addUsers->id, + 'store_id' => Yii::$app->store, + ])->one(); + if (!$storeUser) { + //用户关联门店 + $StoreUser = new StoreUser(); + $StoreUser->store_id = Yii::$app->store; + $StoreUser->user_id = $addUsers->id; + $StoreUser->is_online = 1; + $StoreUser->last_login_time = time(); + $StoreUser->saveOrFail(); + } else { + //更新登录时间 + StoreUser::updateAll(['last_login_time' => time()], [ + 'user_id' => $addUsers->id, + 'store_id' => Yii::$app->store, + 'is_delete' => 0 + ]); + } + + // $response = (new Client(['http_errors' => false]))->post(\Yii::$app->params['platform']['url']."/platform/v1/sync/user", [ + // 'headers' => ['Authorization' =>"Bearer ".\Yii::$app->params['platform']['token']], + // 'form_params' => [ + // 'id' => $addUsers->id, + // 'mobile' => $this->mobile, + // 'nickname' => '微信用户', + // 'avatarurl' => $addUsers->avatarurl + // ], + // ]); + // $result = json_decode($response->getBody(),true); + // if ($result['errcode'] != 0) { + // throw new Exception($result['msg']); + // } + + $t->commit(); + return [ + 'StoreUser' => $StoreUser, + 'addUsers' => $addUsers, + 'platform_token' => "Bearer ".Yii::$app->params['platform']['token'], + ]; + } catch (\Exception $e) { + $t->rollBack(); + throw new \yii\db\Exception($e->getMessage()); + } + } else { + throw new Exception('验证码已过期,请从新获取验证码'); + } + } +} \ No newline at end of file diff --git a/member/models/forms/OrderSubmitResultForm.php b/member/models/forms/OrderSubmitResultForm.php new file mode 100644 index 0000000..0f4b16f --- /dev/null +++ b/member/models/forms/OrderSubmitResultForm.php @@ -0,0 +1,138 @@ +where([ + 'id' => $order_id, + 'user_id' => \Yii::$app->user->identity->id, + ])->one(); + if (!$order) { + throw new Exception("订单不存在"); + } + if($order->is_pay){ + throw new Exception("订单已支付"); + } + + $pay_order_no = FuncHelper::generate_order_no('PY'); + $total_fee = $order['total_pay_price']; + + $paymentOrder = new PaymentOrder(); + $paymentOrder->order_no = $order->order_no; + $paymentOrder->pay_order_no = $pay_order_no; + $paymentOrder->amount = $order->total_pay_price; + $paymentOrder->saveOrFail(); + + if(bccomp($total_fee,0,2) <= 0){ //无需支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $this->paid(['order_no' => $order->order_no]); + $t->commit(); + }catch (Exception $exception){ + $t->rollback(); + throw $exception; + } + return [ + 'is_paid' => 1, + 'order_id' => $order['id'], + ]; + } + + $result = WechatService::getInstance()->payment->order->unify([ + 'body' => '订单号:'.$order['order_no'], + 'out_trade_no' => $pay_order_no, + 'total_fee' => bcmul($total_fee,100,0), // 单位:分 + 'notify_url' => \Yii::$app->request->hostInfo.'/member/v1/callback/notify', + 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 + 'openid' => \Yii::$app->user->identity->openid, + ]); + + /** + * array (size=9) + 'return_code' => string 'SUCCESS' (length=7) + 'return_msg' => string 'OK' (length=2) + 'result_code' => string 'SUCCESS' (length=7) + 'mch_id' => string '1613782197' (length=10) + 'appid' => string 'wx80c3e46b0791970f' (length=18) + 'nonce_str' => string '4Dgv26sAHXYFvsT4' (length=16) + 'sign' => string '1FB6605C15426426C6299AC6225F3188' (length=32) + 'prepay_id' => string 'wx08185934425439f262fcd8f03d80d80000' (length=36) + 'trade_type' => string 'JSAPI' (length=5) + */ + + if(!isset($result['return_code']) || $result['return_code'] != 'SUCCESS'){ + throw new Exception('支付失败,失败原因:'.$result['return_msg']); + } + if(!isset($result['result_code']) || $result['result_code'] != 'SUCCESS'){ + throw new Exception('支付失败,错误原因:'.ArrayHelper::getValue($result,'err_code_des','未知')); + } + $config = WechatService::getInstance()->payment->jssdk->sdkConfig($result['prepay_id']); // 返回数组 + $config['is_paid'] = 0; + $config['order_id'] = $order['id']; + return $config; + } + + public function paid($data) + { + $transaction_id = isset($data['transaction_id']) ? $data['transaction_id'] : ''; + $order = Order::findOne(['order_no'=>$data['order_no']]); + if(!$order){ + throw new Exception('订单不存在'); + } + $payment_order = PaymentOrder::find()->where([ + 'order_no' => $data['order_no'], + ])->orderBy(['id'=>SORT_DESC])->one(); + if(!$payment_order){ + throw new Exception('支付订单不存在'); + } + + if($order->is_pay && $payment_order->is_pay){ + return true; + } + + if($order->is_pay == 1){ + return true; + } + $order->is_pay = 1; + $order->pay_time = time(); + $order->pay_type = isset($data['pay_type']) ? $data['pay_type'] : 0; + $order->accept_status = OrderAcceptEnum::WAIT_ACCEPT; + $order->saveOrFail(); + + $payment_order->transaction_id = $transaction_id; + $payment_order->is_pay = 1; + $payment_order->pay_type = $order->pay_type; + $payment_order->saveOrFail(); + + $event = new OrderEvent(); + $event->order = $order; + $event->sender = $this; + \Yii::$app->trigger(Order::EVENT_PAYED, $event); + return true; + } +} diff --git a/member/models/forms/PatientForm.php b/member/models/forms/PatientForm.php new file mode 100644 index 0000000..1606d23 --- /dev/null +++ b/member/models/forms/PatientForm.php @@ -0,0 +1,282 @@ + 0], + ['up_id', 'integer'], + [['name', 'id_card', 'age', 'sex', 'relation', 'mobile'], 'required'], + [['is_default'], 'default', 'value' => 0], + ['mobile', 'match', 'pattern' => '/^\d{11}$/i'], + ['id_card', 'match', 'pattern' => '/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/i'], + ['id_card','checkCard'], + [['family_status', 'allergic_status', 'person_status', 'liver_function', 'renal_function'], 'default', 'value' => 0], + + [['family_history', 'allergic_history', 'person_history', 'liver_index', 'renal_index'], 'default', 'value' => ''], + + ['family_history', 'required', 'when' => function ($model) { + return $model->family_status == 1; + }], + ['allergic_history', 'required', 'when' => function ($model) { + return $model->allergic_status ==1; + }], + ['person_history', 'required', 'when' => function ($model) { + return $model->person_status == 1; + }], +// ['liver_index', 'required', 'when' => function ($model) { +// return $model->liver_function == 1; +// }], +// ['renal_index', 'required', 'when' => function ($model) { +// return $model->renal_function == 1; +// }], + ]; + } + +// public function checkUnique($attribute, $params) +// { +// $exist = UserPatient::find()->where([ +// 'user_id' => \Yii::$app->user->id, +// 'is_delete' => 0 +// ])->andWhere(['<>', 'id', $this->id])->andWhere([ +// 'or', +// ['name' => $this->name], +// ['id_card' => $this->id_card], +// ])->one(); +// if ($exist) { +// $this->addError($attribute, '就诊人姓名或身份证已存在'); +// } +// +// if ($this->relation == 0) { +// $exist = UserPatient::find()->where([ +// 'user_id' => \Yii::$app->user->id, +// 'is_delete' => 0 +// ])->andWhere(['<>', 'id', $this->id])->andWhere([ +// 'relation' => $this->relation,//本人 +// ])->one(); +// if ($exist) { +// $this->addError($attribute, '本人的信息已存在,请选择其他关系'); +// } +// } +// } + + public function checkCard($attribute, $params) + { + $response = (new Client(['http_errors' => false]))->post("https://eid.shumaidata.com/eid/check", [ + 'headers' => ['Authorization' => "APPCODE f98bba3251714c759f5bd29d00e1c46e"], + 'query' => [ + 'idcard' => $this->id_card, + 'name' => $this->name + ], + ]); + $result = json_decode($response->getBody(), true); + if (!($result['code'] == 0 && $result['result']['res'] == 1)) { + $this->addError($attribute, '身份证名字不匹配'); + } + } + + public function attributeLabels() + { + return [ + 'name' => '姓名', + 'id_card' => '身份证号', + 'age' => '年龄', + 'sex' => '性别', + 'relation' => '与本人关系', + 'mobile' => '手机号', + 'liver_function' => '肝功能', + 'renal_function' => '肾功能', + 'allergic_history' => '过敏史', + 'person_history' => '个人病史', + 'family_history' => '家庭病史', + ]; + } + + public function save() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + $user_id = \Yii::$app->user->identity->id; + //修改 + if ($this->id) { + $patient = UserPatient::findOne([ + 'id' => $this->id, + 'user_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ]); + if (!$patient) { + throw new Exception('就诊人不存在'); + } + } else {//新增 + $patient = new UserPatient(); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + if ($this->is_default) { + UserPatient::updateAll(['is_default' => 0], ['user_id' => $user_id]); + } + $patient->user_id = \Yii::$app->user->id; + $patient->attributes = $this->attributes; + $patient->saveOrFail(); + + $UserPatientHealthInquiry = UserPatientHealthInquiry::find()->where([ + 'user_patient_id' => $patient->id, + 'is_delete' => 0 + ])->one(); + if (!$UserPatientHealthInquiry) {//新增 + $UserPatientHealthInquiry = new UserPatientHealthInquiry(); + } + $UserPatientHealthInquiry->user_patient_id = $patient->attributes['id']; + $UserPatientHealthInquiry->family_status = $this->family_status; + $UserPatientHealthInquiry->allergic_status = $this->allergic_status; + $UserPatientHealthInquiry->person_status = $this->person_status; + $UserPatientHealthInquiry->liver_function = $this->liver_function; + $UserPatientHealthInquiry->renal_function = $this->renal_function; + $UserPatientHealthInquiry->family_history = $this->family_history; + $UserPatientHealthInquiry->allergic_history = $this->allergic_history; + $UserPatientHealthInquiry->person_history = $this->person_history; + $UserPatientHealthInquiry->liver_index = $this->liver_index; + $UserPatientHealthInquiry->renal_index = $this->renal_index; + + $UserPatientHealthInquiry->saveOrFail(); + +// $params = [ +// 'user_id' => \Yii::$app->user->id, +// 'avatar' => '', +// 'name' => $this->name, +// 'id_card' => $this->id_card, +// 'age' => $this->age, +// 'sex' => $this->sex, +// 'relation' => $this->relation, +// 'mobile' => $this->mobile, +// 'is_default' => $this->is_default, +// 'is_delete' =>0, +// 'userPatientHealthInquiry'=>json_encode($UserPatientHealthInquiry,true), +// 'user_patient_id' => $patient->id, +// 'family_status' => $this->family_status, +// 'allergic_status' => $this->allergic_status, +// 'person_status' => $this->person_status, +// 'liver_function' => $this->liver_function, +// 'renal_function' => $this->renal_function, +// 'family_history' => $this->family_history, +// 'allergic_history' => $this->allergic_history, +// 'person_history' => $this->person_history, +// 'liver_index' => $this->liver_index, +// 'renal_index' => $this->renal_index, +// ]; +// $curl = new Curl(); +// $url = 'http://hy.api.ctkj88.com/platform/v1/sync/patient'; +// $response = $curl->setPostParams($params) +// ->setHeaders([ +// 'multipart/form-data' => 'application/json', +// 'Authorization' => 'Bearer 1234567890', +// ])->post($url); +// +// $response=json_decode($response,true); +// if ($response['errcode']==-1){ +// return [$response['msg']]; +// } + + + $t->commit(); + return ['添加或编辑成功']; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + public function del() + { + $user_id = \Yii::$app->user->identity->getId(); + + $patient = UserPatient::findOne([ + 'id' => $this->id, + 'user_id' => $user_id, + 'is_delete' => 0 + ]); + if (!$patient) { + throw new Exception('就诊人不存在'); + } + + // $curl = new Curl(); + // $params = [ + // 'user_id'=>$user_id, + // 'id_card'=>$patient['id_card'], + // ]; + + // $response = (new Client(['http_errors' => false]))->post("https://hy.api.ctkj88.com/platform/v1/sync/patient-delete", [ + // 'headers' => ['Authorization' =>"Bearer 1234567890"], + // 'form_params' => [ + // 'user_id'=>$user_id, + // 'id_card'=>$patient['id_card'], + // ], + // ]); + // $result = json_decode($response->getBody(),true); + // if ($result['errcode'] == -1) { + // throw new Exception($result['msg']); + // } + + //删除萧康就诊人 + $patient->delete(); + } + + //切换就诊人 + public function change() + { + $patient = UserPatient::findOne([ + 'id' => $this->up_id, + 'user_id' => \Yii::$app->user->id, + 'is_delete' => 0 + ]); + if (!$patient) { + throw new Exception('就诊人不存在'); + }else{ + UserPatient::updateAll(['is_default'=>0], + ['user_id' => \Yii::$app->user->id, 'is_delete' => 0]); + } + + UserPatient::updateAll(['is_default'=>1], + ['id' => $this->up_id,'user_id' => \Yii::$app->user->id, 'is_delete' => 0]); + return ['切换成功']; + } +} \ No newline at end of file diff --git a/member/models/forms/PayForm.php b/member/models/forms/PayForm.php new file mode 100644 index 0000000..0e14ff7 --- /dev/null +++ b/member/models/forms/PayForm.php @@ -0,0 +1,56 @@ + 255], + ]; + } + + public function GoPutRecord() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $is_record=UserPatientRecord::find()->where(['up_id'=>$this->up_id])->one(); + if ($is_record){ + throw new Exception('您已建过档'); + } + $UserPatientRecord=new UserPatientRecord(); + $UserPatientRecord->attributes=$this->attributes; + + $UserPatientRecord->saveOrFail(); + + return ['建档成功,病案号为'.$UserPatientRecord->id]; + } + + public function attributeLabels() + { + return [ + 'up_id'=>'就诊人id', + 'height' => 'Height', + 'weight' => 'Weight', + 'region' => 'Region', + 'address' => 'Address', + ]; + } +} \ No newline at end of file diff --git a/member/models/forms/PhysicalForm.php b/member/models/forms/PhysicalForm.php new file mode 100644 index 0000000..c83b0f1 --- /dev/null +++ b/member/models/forms/PhysicalForm.php @@ -0,0 +1,163 @@ + 1], + [['page_size'], 'default', 'value' => 20], + [['sort'], 'default', 'value' => 'default'], + [['sort_type'], 'default', 'value' => 'desc'], + ]; + } + + /** + * 体检套餐列表 + * @throws Exception + */ + public function getPhysicalPackageList(): array + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg($this)); + } + $package_query = PhysicalPackage::find(); + + //综合排序 + if($this->all){ + $package_query->orderBy([ + 'id'=>SORT_ASC + ]); + } + + //按照套餐类型排序 + if($this->type){ + $package_query->orderBy([ + 'type'=>SORT_ASC + ]); + } + + $field = [ + PhysicalPackage::class => [ + 'id','name','image','price','intro','content','service','type' + ] + ]; + + $pagination['page'] = (int)$this->page; + $data = new ActiveDataProvider([ + 'query'=>$package_query->asArray(), + 'pagination'=>[ + 'defaultPageSize'=>(int)$this->page_size, + 'params'=>$pagination + ] + ]); + return [ + 'data' => $data, + 'field' => $field + ]; + } + + /** + * 体检套餐详情 + * @return array + */ + public function getPhysicalPackage(): array + { + // 套餐详情 + $data['package'] = PhysicalPackage::find()->with(['yardPhysical' => function($query) { + if(isset($this->yard_id)){ + $query->where(['yard_id'=>$this->yard_id]); + } + $query->select('yard_id,physical_id')->with('yard'); + }])->where([ + 'id' => $this->id + ])->asArray()->one(); + + // 预约时间 近一月 + $reserve_done = [];//已预约数 + $reserve = PhysicalReserveTotal::find()->where(['>=','day',date('Y-m-d')])->all(); + foreach($reserve as $item){ + $reserve_done[$item->day] = $item->num; + } + + $reserve_date = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]; + foreach($reserve_date as $day){ + $date = date('Y-m-d',strtotime('+'.$day.' day')); + if(isset($reserve_done[$date])){ + //如果有预约是日期 做减法 + $data['reserve'][$date] = $this->reserve_total - $reserve_done[$date]; + }else{ + $data['reserve'][$date] = $this->reserve_total; + } + } + + return $data; + } + + /** + * 体检套餐预约 + * @return array + */ + public function setPhysicalReserve(): array + { + $user_reserve = PhysicalReserve::findone([ + 'user_id' => \Yii::$app->user->identity->id, + 'yard_id' => $this->yard_id, + 'physical_id' => $this->physical_id, + 'day' => $this->day + ]); + + if(isset($user_reserve) && $user_reserve->status !=2){//已经预约,不可以重复预约 + return ['success' => 0, 'msg'=>'您已经预约过,请误重复预约']; + }else{ + $user_reserve = new PhysicalReserve(); + $user_reserve->user_id = \Yii::$app->user->id; + $user_reserve->yard_id = $this->yard_id; + $user_reserve->physical_id = $this->physical_id; + $user_reserve->day = $this->day; + $user_reserve->status = 0; + $user_reserve->way = isset($this->way) ? $this->way : 0; + $res = $user_reserve->save(); + } + + return ['success' => $res, 'msg'=>'您预约成功,请尽快支付']; + } + + /** + * 挂号详情 + * @return array + */ + public function getReserveDetail(): array + { + return PhysicalReserve::find()->with(['yard','user','package'])->where([ + 'id' => $this->id + ])->asArray()->one(); + } +} diff --git a/member/models/forms/PrescripOrderSubmitForm.php b/member/models/forms/PrescripOrderSubmitForm.php new file mode 100644 index 0000000..b5d3618 --- /dev/null +++ b/member/models/forms/PrescripOrderSubmitForm.php @@ -0,0 +1,176 @@ +where([ + 'id' => $order_id, + ])->one(); + + if (!$prescription ) { + throw new Exception("订单不存在"); + } + + if($prescription->is_pay){ + throw new Exception("订单已支付"); + } + + $pay_order_no = FuncHelper::generate_order_no('PY'); + $total_fee = $prescription['total_pay_price']; + + $paymentPrescripOrder = new PaymentPrescripOrder(); + $paymentPrescripOrder->order_no = $prescription->prescription_no; + $paymentPrescripOrder->pay_order_no = $pay_order_no; + $paymentPrescripOrder->amount = $prescription->total_pay_price; + $paymentPrescripOrder->saveOrFail(); + + if(bccomp($total_fee,0,2) <= 0){ //无需支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $this->paid(['order_no' => $prescription->prescription_no]); + $t->commit(); + }catch (Exception $exception){ + $t->rollback(); + throw $exception; + } + return [ + 'is_paid' => 1, + 'order_id' => $prescription['id'], + ]; + } + $result = WechatService::getInstance()->payment->order->unify([ + 'body' => '订单号:'.$prescription['prescription_no'], + 'out_trade_no' => $pay_order_no, + 'total_fee' => bcmul($total_fee,100,0), // 单位:分 + 'notify_url' => \Yii::$app->request->hostInfo.'/member/v1/callback/notify', + 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 + 'openid' => \Yii::$app->user->identity->openid, + ]); + + /** + * array (size=9) + 'return_code' => string 'SUCCESS' (length=7) + 'return_msg' => string 'OK' (length=2) + 'result_code' => string 'SUCCESS' (length=7) + 'mch_id' => string '1613782197' (length=10) + 'appid' => string 'wx80c3e46b0791970f' (length=18) + 'nonce_str' => string '4Dgv26sAHXYFvsT4' (length=16) + 'sign' => string '1FB6605C15426426C6299AC6225F3188' (length=32) + 'prepay_id' => string 'wx08185934425439f262fcd8f03d80d80000' (length=36) + 'trade_type' => string 'JSAPI' (length=5) + */ + + if(!isset($result['return_code']) || $result['return_code'] != 'SUCCESS'){ + throw new Exception('支付失败,失败原因:'.$result['return_msg']); + } + if(!isset($result['result_code']) || $result['result_code'] != 'SUCCESS'){ + throw new Exception('支付失败,错误原因:'.ArrayHelper::getValue($result,'err_code_des','未知')); + } + $config = WechatService::getInstance()->payment->jssdk->sdkConfig($result['prepay_id']); // 返回数组 + $config['is_paid'] = 0; + $config['order_id'] = $prescription['id']; + return $config; + } + + public function paid($data) + { + $transaction_id = isset($data['transaction_id']) ? $data['transaction_id'] : ''; + $prescription = Prescription::findOne(['prescription_no'=>$data['prescription_no']]); + if(!$prescription){ + throw new Exception('处方订单不存在'); + } + $paymentPrescrip_Order = PaymentPrescripOrder::find()->where([ + 'order_no' => $data['prescription_no'], + ])->orderBy(['id'=>SORT_DESC])->one(); + if(!$paymentPrescrip_Order){ + throw new Exception('支付订单不存在'); + } + + if($prescription->is_pay && $paymentPrescrip_Order->is_pay){ + return true; + } + + if($prescription->is_pay == 1){ + return true; + } + $prescription->is_pay = 1; + $prescription->pay_time = time(); + $prescription->pay_type = isset($data['pay_type']) ? $data['pay_type'] : 0; + $prescription->accept_status = OrderAcceptEnum::WAIT_ACCEPT; + $prescription->saveOrFail(); + + $paymentPrescrip_Order->transaction_id = $transaction_id; + $paymentPrescrip_Order->is_pay = 1; + $paymentPrescrip_Order->pay_type = $prescription->pay_type; + $paymentPrescrip_Order->saveOrFail(); + + + PrescripOrderLog::saveLog($prescription->id,'触发处方订单支付事件'); + $event = new OrderEvent(); + $event->order = $prescription; + $event->sender = $this; + \Yii::$app->trigger(Prescription::EVENT_PAYED, $event); + return true; + } + + //预览 + public function Preview($id) + { + $p_id = ProductOrder::find()->select('p_id')->where([ + 'id' => $id, + ])->column(); + + $prescription = Prescription::find()->select('cr_ids,wr_ids')->where(['id' => $p_id])->one(); + + $wr_ids = explode(',', $prescription['wr_ids']); + $cr_ids = explode(',', $prescription['cr_ids']); + $west = WestRepice::find()->select('content,number,total_price')->where([ + 'in', 'id', $wr_ids + ])->asArray()->all(); + $chinese = ChineseRepice::find()->select('content,total_price')->where([ + 'in', 'id', $cr_ids + ])->asArray()->all(); + + foreach ($west as $value) { + $number += $value['number']; + $price += $value['total_price']; + } + + foreach ($chinese as $val) { + $number += $val['number']; + $prices += $val['total_price']; + } + + if (!empty($price)) { + ProductOrder::updateAll(['total_pay_price' => $price], ['id' => $id]); + } + if (!empty($prices)) { + ProductOrder::updateAll(['total_pay_price' => $prices], ['id' =>$id]); + } + } +} \ No newline at end of file diff --git a/member/models/forms/ProductOrderSubmitForm.php b/member/models/forms/ProductOrderSubmitForm.php new file mode 100644 index 0000000..2f8490d --- /dev/null +++ b/member/models/forms/ProductOrderSubmitForm.php @@ -0,0 +1,277 @@ +where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->getId(), + ])->one(); + if (!$ProductOrder) { + throw new Exception("订单不存在"); + } + if($ProductOrder->is_pay){ + throw new Exception("订单已支付"); + } + + if(!$ProductOrder['delivery_method'] && !$ProductOrder->address_id){ + throw new Exception("快递配送请选择收货地址"); + } + + switch ($ProductOrder->type) { + case 0:case 1: // 微信支付 + $config = $this->getWechatPayConfig($ProductOrder); + break; + case 2: //易票联支付 + $config = $this->getEplPayConfig($ProductOrder); + break; + default: + throw new Exception('支付方式设置错误,请联系医生或客服'); + break; + } + return $config; + } + + + //获取微信小程序支付配置 + public function getWechatPayConfig($productOrder){ + $pay_order_no = FuncHelper::generate_order_no('PY'); + $total_fee = $productOrder['total_pay_price']; + + $paymentProductOrder = new PaymentProductOrder(); + $paymentProductOrder->order_no = $productOrder->order_no; + $paymentProductOrder->pay_order_no = $pay_order_no; + $paymentProductOrder->amount = $productOrder->total_pay_price; + $paymentProductOrder->saveOrFail(); + + if(bccomp($total_fee,0,2) <= 0){ //无需支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $this->paid(['order_no' => $productOrder->order_no]); + $t->commit(); + }catch (Exception $exception){ + $t->rollback(); + throw $exception; + } + return [ + 'is_paid' => 1, + 'order_id' => $productOrder['id'], + ]; + } + $result = WechatService::getInstance()->payment->order->unify([ + 'body' => '订单号:'.$productOrder['order_no'], + 'out_trade_no' => $pay_order_no, + 'total_fee' => bcmul($total_fee,100,0), // 单位:分 + 'notify_url' => \Yii::$app->request->hostInfo.'/member/v1/callback/notify', + 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 + 'openid' => \Yii::$app->user->identity->openid, + ]); + + /** + * array (size=9) + 'return_code' => string 'SUCCESS' (length=7) + 'return_msg' => string 'OK' (length=2) + 'result_code' => string 'SUCCESS' (length=7) + 'mch_id' => string '1613782197' (length=10) + 'appid' => string 'wx80c3e46b0791970f' (length=18) + 'nonce_str' => string '4Dgv26sAHXYFvsT4' (length=16) + 'sign' => string '1FB6605C15426426C6299AC6225F3188' (length=32) + 'prepay_id' => string 'wx08185934425439f262fcd8f03d80d80000' (length=36) + 'trade_type' => string 'JSAPI' (length=5) + */ + + if(!isset($result['return_code']) || $result['return_code'] != 'SUCCESS'){ + throw new Exception('支付失败,失败原因:'.$result['return_msg']); + } + if(!isset($result['result_code']) || $result['result_code'] != 'SUCCESS'){ + throw new Exception('支付失败,错误原因:'.ArrayHelper::getValue($result,'err_code_des','未知')); + } + $config = WechatService::getInstance()->payment->jssdk->sdkConfig($result['prepay_id']); // 返回数组 + $config['is_paid'] = 0; + $config['order_id'] = $productOrder['id']; + return $config; + } + + //获取易票联支付配置 + public function getEplPayConfig($productOrder){ + $pay_order_no = FuncHelper::generate_order_no('PY'); + $total_fee = $productOrder['total_pay_price']; + + $paymentProductOrder = new PaymentProductOrder(); + $paymentProductOrder->pay_type = 2; + $paymentProductOrder->order_no = $productOrder['order_no']; + $paymentProductOrder->pay_order_no = $pay_order_no; + $paymentProductOrder->amount = $productOrder['total_pay_price']; + $paymentProductOrder->saveOrFail(); + + if(bccomp($total_fee,0,2) <= 0){ //无需支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $this->paid(['order_no' => $productOrder->order_no]); + $t->commit(); + }catch (Exception $exception){ + $t->rollback(); + throw $exception; + } + return [ + 'is_paid' => 1, + 'order_id' => $productOrder['id'], + ]; + } + $productOrderItems = ProductOrderItems::find()->where(['product_order_id' => $productOrder->id])->all(); + $orderInfo = []; + $goods = []; + foreach($productOrderItems as $v){ + $good = []; + $good['name'] = $v['drug_name']; + $good['number'] = $v['number']; + $good['amount'] = bcmul(round($v['price'] * $v['number'], 2), 100,0); + $goods[] = $good; + } + if($productOrder->decoct_price){ + $good = [ + 'name' => '代煎费用', + 'number' => 1, + 'amount' => $productOrder->decoct_price + ]; + } + if($productOrder->trans_expenses){ + $good = [ + 'name' => '快递费用', + 'number' => 1, + 'amount' => $productOrder->trans_expenses + ]; + } + $orderInfo['Id'] = $productOrder['order_no']; + $orderInfo['businessType'] = '100007'; + $orderInfo['goodsList'] = $goods; + $eplResult = EplPayService::getInstance()->WxJsapiPayment([ + 'order_no' => $pay_order_no, + 'openId' => \Yii::$app->user->identity->openid, + 'orderInfo' => $orderInfo, + 'total_pay_price' => $productOrder['total_pay_price'], + ]); + if(!isset($eplResult['returnCode']) || $eplResult['returnCode'] != '0000'){ + throw new Exception($eplResult['returnMsg']); + } + $config = $eplResult['wxJsapiParam']; + $config['timestamp'] = $config['timeStamp']; + $config['is_paid'] = 0; + $config['order_id'] = $productOrder['id']; + return $config; + } + + //已支付操作 + public function paid($data) + { + $transaction_id = isset($data['transaction_id']) ? $data['transaction_id'] : ''; + $t = \Yii::$app->db->beginTransaction(); + try { + $ProductOrder = ProductOrder::find()->where(['order_no'=>$data['order_no']])->with('prescription')->one(); + if(!$ProductOrder){ + throw new Exception('产品订单不存在'); + } + $paymentProduct_Order = PaymentProductOrder::find()->where([ + 'pay_order_no' => $data['pay_order_no'], + ])->orderBy(['id'=>SORT_DESC])->one(); + if(!$paymentProduct_Order){ + throw new Exception('支付订单不存在'); + } + + if($ProductOrder->is_pay && $paymentProduct_Order->is_pay){ + return true; + } + + if($ProductOrder->is_pay == 1){ + return true; + } + + if($ProductOrder->is_online != 1){ + $Prescription = $ProductOrder->prescription; + $Prescription->is_pay = 1; + $Prescription->pay_time = time(); + $Prescription->saveOrFail(); + + //中药处方订单同步江奥川erp + if($Prescription->prescription_type == 1 && $Prescription->status== 1){ + //触发订单支付事件,同步江奥川ERP + $event = new ProductOrderEvent(); + $event->order = $ProductOrder; + $event->sender = $this; + \Yii::$app->trigger(ProductOrder::EVENT_PAYED, $event); + } + } + + $ProductOrder->is_pay = 1; + $ProductOrder->status = ProductOrderEnum::WAIT_SEND; + $ProductOrder->pay_time = time(); + $ProductOrder->type = isset($data['pay_type']) ? $data['pay_type'] : 0; + $ProductOrder->saveOrFail(); + + $paymentProduct_Order->transaction_id = $transaction_id; + $paymentProduct_Order->is_pay = 1; + $paymentProduct_Order->pay_type = $ProductOrder->type; + $paymentProduct_Order->saveOrFail(); + + // 订单支付进行分账 + \Yii::$app->queue->delay(0)->push(new ProductOrderPaidJob([ + 'orderId' => $ProductOrder->id, + ])); + + if($ProductOrder->order_type ==1 && $ProductOrder->p_id){//线下挂号处方订单 + $prescription = Prescription::find()->where(['id' => $ProductOrder->p_id])->one(); + //发送处方已支付通知 + $systemNotice = new SystemNotice(); + $systemNotice->data = $prescription->id; + $systemNotice->store_id = $prescription->store_id; + $systemNotice->content = '您开具的处方,编号:'.$prescription->prescription_no.' 患者已取药!'; + $systemNotice->base_type = 4;//处方通知 + $systemNotice->scene_type = 2; + $systemNotice->user_id = $prescription->user_id; + $systemNotice->notice_at = date('Y-m-d H:i:s',time()); + $systemNotice->saveOrFail(); + } + + + if($ProductOrder->is_online){ //平台订单状态同步 + \Yii::$app->queue->delay(0)->push(new ProductOrderSyncPlatformJob([ + 'orderId' => $ProductOrder->id, + 'status' => 1 + ])); + } + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + throw $e; + } + return $ProductOrder; + } +} \ No newline at end of file diff --git a/member/models/forms/RegisterForm.php b/member/models/forms/RegisterForm.php new file mode 100644 index 0000000..081a16b --- /dev/null +++ b/member/models/forms/RegisterForm.php @@ -0,0 +1,190 @@ +validate()) { + throw new Exception($this->getErrorMsg()); + } + + $UserPatient = UserPatient::find()->where([ + 'user_id' => \Yii::$app->user->id, + 'id' => $this->user_patient_id + ])->one(); + if (!$UserPatient) { + throw new Exception('就诊人不存在'); + } + + $today = strtotime(date('Y-m-d', time())); + $end = $today + 60 * 60 * 24; + $order_number = Register::find()->where([ + 'store_id' => $this->store_id, + 'service_user_id' => $this->service_user_id + ])->andWhere([ + 'between', 'created_at', $today, $end + ])->select('order_number')->orderBy(['order_number' => SORT_DESC])->one(); + + $StoreDoctor=StoreDoctor::find()->where([ + 'store_id'=>\Yii::$app->store, + 'su_id'=>$this->service_user_id + ])->one(); + if (!$StoreDoctor) throw new Exception('门店没有该医生'); + + $ServiceUser=ServiceUser::find()->where([ + 'id'=>$this->service_user_id, + 'is_delete'=>0 + ])->one(); + if (!$StoreDoctor) throw new Exception('该医生不存在'); + if ($ServiceUser->docService->register_status==0) throw new Exception('该医生没开通挂号服务'); + + $is_doctorPatient=DoctorPatient::find()->where([ + 'up_id' => $this->user_patient_id, + 'su_id' => $this->service_user_id, + 'user_id' => \Yii::$app->user->id, + ])->one(); + //添加患者 + if (!$is_doctorPatient){ + //医生患者 + $DoctorPatient=new DoctorPatient(); + $DoctorPatient->user_id=\Yii::$app->user->id; + $DoctorPatient->su_id=$this->service_user_id; + $DoctorPatient->up_id=$this->user_patient_id; + $DoctorPatient->name=$UserPatient->name; + $DoctorPatient->avatar=$UserPatient->avatar??''; + $DoctorPatient->id_card=$UserPatient->id_card; + $DoctorPatient->sex=$UserPatient->sex; + $DoctorPatient->mobile=$UserPatient->mobile; + $DoctorPatient->saveOrFail(); + } + + $Register = Register::find()->where([ + 'user_id' => \Yii::$app->user->id, + 'user_patient_id' => $this->user_patient_id, + 'store_id' => $this->store_id, + 'service_user_id' => $this->service_user_id, + ])->andWhere([ + 'in','status',[0,1] //未支付 待接诊 + ])->andWhere(['between','created_at',$today,$end])->one(); + + if($Register){ + return [ + 'isHas' => 1, + 'register_id' => $Register->id + ]; + } + // if ($Register) throw new Exception('您今天已经在该医生处挂过号,请勿重复挂号'); + + //获取支付方式配置 + $payConfig = PayConfig::findOne(['status' => 1, 'current_use' => 1]); + + $t = \Yii::$app->db->beginTransaction(); + try { + $UserRegister = new Register(); + $UserRegister->user_id = \Yii::$app->user->id; + $UserRegister->store_id = \Yii::$app->store; + $UserRegister->order_no = FuncHelper::generate_order_no('SN'); + $UserRegister->user_patient_id = $this->user_patient_id; + $UserRegister->service_user_id = $this->service_user_id; + $UserRegister->depart_id = $ServiceUser->docInfo->depart_id; + $UserRegister->order_number = ($order_number['order_number']??0 ) + 1; + $UserRegister->price = $ServiceUser->docService->register_price; + $UserRegister->pay_type = $payConfig->pay_type??2;//1微信 2易票联 + $UserRegister->saveOrFail(); + + $event = new RegisterEvent();//触发订单创建事件 + $event->register = $UserRegister; + \Yii::$app->trigger(Register::EVENT_CREATED, $event); + + $t->commit(); + } catch (\Exception $E) { + $t->rollBack(); + throw new Exception($E->getMessage()); + } + return ['isHas' => 0,'register_id' => $UserRegister->id]; + } + + + public function info() + { + $ServiceUser = ServiceUser::find()->where([ + 'id' => $this->service_user_id, + 'role' => UserRoleEnum::DOCTOR, + 'status' => UserStatusEnum::OK, + 'is_delete' => 0 + ])->one(); + + if (!$ServiceUser) throw new Exception('医生不存在'); + \Yii::$app->response->headers->set("Content-type:text/html;charset=utf-8"); + $today = strtotime(date('Y-m-d', time())); + $end = $today + 60 * 60 * 24; + $count = Register::find()->where([ + 'service_user_id' => $this->service_user_id + ])->andWhere([ + 'between', 'created_at', $today, $end + ])->count(); + $left_number = $ServiceUser->docInfo->register_num - $count; + + return [ + 'time' => date('Y-m-d'), + 'register_price' => $ServiceUser->docService->register_price . '元/次', + 'left_num' => $left_number, + 'register_num' => $ServiceUser->docInfo->register_num + ]; + } + + /** + * 取消挂号 + */ + public function cancel() + { + $Register = Register::find()->where([ + 'id'=>$this->register_id, + 'user_id' => \Yii::$app->user->id, + 'is_delete' => 0, + ])->one(); + if (!$Register) throw new Exception('该挂号不存在'); + + Register::updateAll([ + 'is_delete' => 1, + 'status'=>RegisterEnum::CANCEL + ],[ + 'id'=>$this->register_id, + 'user_id' => \Yii::$app->user->id, + ]); + + return ['取消成功']; + } + +} \ No newline at end of file diff --git a/member/models/forms/RegisterSubmitForm.php b/member/models/forms/RegisterSubmitForm.php new file mode 100644 index 0000000..b49e2e2 --- /dev/null +++ b/member/models/forms/RegisterSubmitForm.php @@ -0,0 +1,257 @@ +where([ + 'id' => $register_id, + 'user_id'=> \Yii::$app->user->id, + ])->one(); + + $today = strtotime(date('Y-m-d', time())); + $end = $today + 60 * 60 * 24; + $number=Register::find()->where([ + 'store_id' => $Register->store_id, + 'user_id'=> \Yii::$app->user->id, + 'user_patient_id'=>$Register->user_patient_id, + 'service_user_id'=>$Register->service_user_id, + 'status' => 1 + ])->andWhere([ + 'between', 'created_at', $today, $end + ])->count(); + if ($number>=1){ + throw new \yii\base\Exception("您今天在该医生处还有待接诊挂号,请勿重复挂号"); + } + if (!$Register) { + throw new \yii\base\Exception("订单不存在"); + } + if($Register->is_pay){ + throw new Exception("订单已支付"); + } + + switch ($Register->pay_type) { + case 0:case 1: // 微信支付 + $config = $this->getWechatPayConfig($Register); + break; + case 2: //易票联支付 + $config = $this->getEplPayConfig($Register); + break; + default: + throw new Exception('支付方式设置错误,请联系医生或客服'); + break; + } + return $config; + + + } + + + //获取微信小程序支付配置 + public function getWechatPayConfig($Register){ + $pay_order_no = FuncHelper::generate_order_no('PY'); + $total_fee = $Register['price']; + + $PaymentRegister = new PaymentRegister(); + $PaymentRegister->order_no = $Register->order_no; + $PaymentRegister->pay_order_no = $pay_order_no; + $PaymentRegister->amount = $Register->price; + $PaymentRegister->saveOrFail(); + + + if(bccomp($total_fee,0,2) <= 0){ //无需支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $this->paid(['order_no' => $Register->order_no]); + $t->commit(); + }catch (Exception $exception){ + $t->rollback(); + throw $exception; + } + + return [ + 'is_paid' => 1, + 'register_id' => $Register['id'], + ]; + } + + $result = WechatService::getInstance()->payment->order->unify([ + 'body' => '订单号:'.$Register['order_no'], + 'out_trade_no' => $pay_order_no, + 'total_fee' => bcmul($total_fee,100,0), // 单位:分 + 'notify_url' => \Yii::$app->request->hostInfo.'/member/v1/callback/notify', + 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 + 'openid' => \Yii::$app->user->identity->openid, + ]); + + /** + * array (size=9) + 'return_code' => string 'SUCCESS' (length=7) + 'return_msg' => string 'OK' (length=2) + 'result_code' => string 'SUCCESS' (length=7) + 'mch_id' => string '1613782197' (length=10) + 'appid' => string 'wx80c3e46b0791970f' (length=18) + 'nonce_str' => string '4Dgv26sAHXYFvsT4' (length=16) + 'sign' => string '1FB6605C15426426C6299AC6225F3188' (length=32) + 'prepay_id' => string 'wx08185934425439f262fcd8f03d80d80000' (length=36) + 'trade_type' => string 'JSAPI' (length=5) + */ + + if(!isset($result['return_code']) || $result['return_code'] != 'SUCCESS'){ + throw new Exception('支付失败,失败原因:'.$result['return_msg']); + } + if(!isset($result['result_code']) || $result['result_code'] != 'SUCCESS'){ + throw new Exception('支付失败,错误原因:'.ArrayHelper::getValue($result,'err_code_des','未知')); + } + $config = WechatService::getInstance()->payment->jssdk->sdkConfig($result['prepay_id']); // 返回数组 + $config['is_paid'] = 0; + $config['register_id'] = $Register['id']; + return $config; + } + + //获取易票联支付配置 + public function getEplPayConfig($Register){ + $pay_order_no = FuncHelper::generate_order_no('PY'); + $total_fee = $Register['price']; + + $PaymentRegister = new PaymentRegister(); + $PaymentRegister->order_no = $Register->order_no; + $PaymentRegister->pay_order_no = $pay_order_no; + $PaymentRegister->amount = $Register->price; + $PaymentRegister->saveOrFail(); + + + if(bccomp($total_fee,0,2) <= 0){ //无需支付 + $t = \Yii::$app->db->beginTransaction(); + try { + $this->paid(['order_no' => $Register->order_no]); + $t->commit(); + }catch (Exception $exception){ + $t->rollback(); + throw $exception; + } + + return [ + 'is_paid' => 1, + 'register_id' => $Register['id'], + ]; + } + + $orderInfo['Id'] = $Register->order_no; + $orderInfo['businessType'] = '100007'; + $orderInfo['goodsList'] = [ + [ + 'name' => '挂号订单', + 'number' => 1, + 'amount' => bcmul($total_fee , 100,0), + ] + ]; + $eplResult = EplPayService::getInstance()->WxJsapiPayment([ + 'order_no' => $pay_order_no, + 'openId' => \Yii::$app->user->identity->openid, + 'orderInfo' => $orderInfo, + 'total_pay_price' => $total_fee, + ]); + if(!isset($eplResult['returnCode']) || $eplResult['returnCode'] != '0000'){ + throw new Exception($eplResult['returnMsg']); + } + $config = $eplResult['wxJsapiParam']; + $config['timestamp'] = $config['timeStamp']; + $config['is_paid'] = 0; + $config['register_id'] = $Register['id']; + return $config; + } + + + public function paid($data) + { + $transaction_id = isset($data['transaction_id']) ? $data['transaction_id'] : ''; + $Register = Register::findOne(['order_no'=>$data['order_no']]); + if(!$Register){ + throw new Exception('挂号订单不存在'); + } + + $PaymentRegister = PaymentRegister::find()->where([ + 'order_no' => $data['order_no'], + ])->orderBy(['id'=>SORT_DESC])->one(); + if(!$PaymentRegister){ + throw new Exception('支付订单不存在'); + } + + if($Register->is_pay && $PaymentRegister->is_pay){ + return true; + } + + if($Register->is_pay == 1){ + return true; + } + $t = \Yii::$app->db->beginTransaction(); + try { + $Register->is_pay = 1; + $Register->pay_time = time(); + $Register->pay_type = isset($data['pay_type']) ? $data['pay_type'] : 0; + $Register->status=1; + $Register->created_at=strtotime($Register->created_at); + $Register->updated_at=strtotime($Register->updated_at); + $Register->saveOrFail(); + + $PaymentRegister->transaction_id = $transaction_id; + $PaymentRegister->is_pay = 1; + $PaymentRegister->pay_type = $Register->pay_type; + $PaymentRegister->saveOrFail(); + + //发送挂号成功系统通知 + $systemNotice = new SystemNotice(); + $systemNotice->data = $Register->user_patient_id.','.$Register->id; + $systemNotice->store_id = $Register->store_id; + $systemNotice->content = '您有新的挂号订单,请及时接诊!'; + $systemNotice->base_type = 2;//挂号通知 + $systemNotice->scene_type = 2; + $systemNotice->user_id = $Register->service_user_id; + $systemNotice->notice_at = date('Y-m-d H:i:s',time()); + $systemNotice->saveOrFail(); + + //发送短信通知医生接诊 + \Yii::$app->queue->delay(0)->push(new RegisterMessageJob([ + 'orderId' => $Register->id, + ])); + + + + RegisterLog::saveLog($Register->id,'触发挂号支付事件'); + $event = new RegisterEvent(); + $event->register = $Register; + $event->sender = $this; + \Yii::$app->trigger(Register::EVENT_PAYED, $event); + + + // 订单支付进行分账 + // \Yii::$app->queue->delay(0)->push(new RegisterPaidJob([ + // 'orderId' => $Register->id, + // ])); + + $t->commit(); + return $Register; + }catch (\Exception $exception){ + $t->rollBack(); + throw new Exception($exception->getMessage()); + } + } + +} \ No newline at end of file diff --git a/member/models/forms/UpdatePassForm.php b/member/models/forms/UpdatePassForm.php new file mode 100644 index 0000000..b98b0a2 --- /dev/null +++ b/member/models/forms/UpdatePassForm.php @@ -0,0 +1,60 @@ + '旧密码', + 'new_pass' => '新密码', + ]; + } + public function validatePassword($attribute, $params) + { + /* @var User $user */ + $user = \Yii::$app->user->identity; + + if(!$user->validatePassword($this->old_pass)){ + $this->addError($attribute, '旧密码错误'); + } + } + + public function updatePassword() + { + if (!$this->validate()){ + throw new \yii\db\Exception($this->getErrorMsg()); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + /* @var User $user */ + $user = \Yii::$app->user->identity; + $user->setPassword($this->new_pass); + $user->saveOrFail(); + + $t->commit(); + return []; + } catch (Exception $e) { + $t->rollBack(); + throw $e; + } + } +} \ No newline at end of file diff --git a/member/models/search/ImSessionSearch.php b/member/models/search/ImSessionSearch.php new file mode 100644 index 0000000..c3b60d6 --- /dev/null +++ b/member/models/search/ImSessionSearch.php @@ -0,0 +1,35 @@ + '未读数量', + 'last_time' => '最新消息时间' + ]); + } +} diff --git a/member/modules/v1/Module.php b/member/modules/v1/Module.php new file mode 100644 index 0000000..99a00f8 --- /dev/null +++ b/member/modules/v1/Module.php @@ -0,0 +1,24 @@ + $uploadService->index($name)]; + } +} diff --git a/member/modules/v1/controllers/CallbackController.php b/member/modules/v1/controllers/CallbackController.php new file mode 100644 index 0000000..ad6f25e --- /dev/null +++ b/member/modules/v1/controllers/CallbackController.php @@ -0,0 +1,604 @@ +response->format = Response::FORMAT_RAW; + Yii::$app->response->formatters = []; + + $response = WechatService::getInstance()->payment->handlePaidNotify(function ($notify, $fail) { + /** + * {"appid":"wx36bbb299d88c6127","bank_type":"ZJRCUB_DEBIT","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1496340382","nonce_str":"637ed1617f5f3","openid":"o88xX5Z-mpVWWV-yw2X6MefDIUqE","out_trade_no":"PY20221124100521434224","result_code":"SUCCESS","return_code":"SUCCESS","sign":"FAB5D4E3AD785DBF7D6FB1FE0E1A897E","time_end":"20221124100606","total_fee":"1","trade_type":"JSAPI","transaction_id":"4200001675202211242752421487"} + */ + //记录回调信息 + $callback = new Callback(); + $callback->content = json_encode($notify); + $callback->type = 'order'; + $callback->save(); + + if ($notify['return_code'] == 'SUCCESS' && $notify['result_code'] == 'SUCCESS') { + $t = \Yii::$app->db->beginTransaction(); + try { + $out_trade_no = $notify['out_trade_no']; + $paymentProductOrder = PaymentProductOrder::find()->where([ + 'pay_order_no' => $out_trade_no + ])->one(); + if ($paymentProductOrder) { + $data['order_no'] = $paymentProductOrder->order_no; + $data['transaction_id'] = $notify['transaction_id']; + $data['pay_order_no'] = $out_trade_no; + $data['pay_type'] = 1; + $productOrderPayForm = new ProductOrderSubmitForm(); + $order = $productOrderPayForm->paid($data); + $order_type = 1; + } else { + $PaymentRegister = PaymentRegister::find()->where([ + 'pay_order_no' => $out_trade_no + ])->one(); + if (!$PaymentRegister) { + throw new Exception('订单不存在'); + } + $data['order_no'] = $PaymentRegister->order_no; + $data['transaction_id'] = $notify['transaction_id']; + $data['pay_type'] = 1; + $RegisterSubmitForm = new RegisterSubmitForm(); + $order = $RegisterSubmitForm->paid($data); + $order_type = 2; + } + + // 增加流水记录 + $fundWater = new FundWater(); + $fundWater->store_id = $order->store_id; // 入账 + $fundWater->type = 'enter'; // 入账 + $fundWater->order_type = $order_type; + $fundWater->order_id = $order->id; + $fundWater->user_id = $order->user_id; + $fundWater->service_user_id = $order_type == 1 ? $order->su_id : $order->service_user_id; + $fundWater->order_no = $order->order_no; + $fundWater->price = $order_type == 1 ? $order->total_pay_price : $order->price; + $fundWater->pay_type = 1; //微信 + $fundWater->saveOrFail(); + + //回调处理成功 + $callback->status = 1; + $callback->save(); + $t->commit(); + return true; + } catch (\Exception $exception) { + $t->rollBack(); + $callback->message = $exception->getMessage(); + $callback->save(); + return $fail('通信失败,请稍后再通知我'); + } + + } + }); +// $response = unserialize('O:41:"Symfony\\Component\\HttpFoundation\\Response":6:{s:7:"headers";O:50:"Symfony\\Component\\HttpFoundation\\ResponseHeaderBag":5:{s:23:"' . "\0" . '*' . "\0" . 'computedCacheControl";a:1:{s:8:"no-cache";b:1;}s:10:"' . "\0" . '*' . "\0" . 'cookies";a:0:{}s:14:"' . "\0" . '*' . "\0" . 'headerNames";a:2:{s:13:"cache-control";s:13:"Cache-Control";s:4:"date";s:4:"Date";}s:10:"' . "\0" . '*' . "\0" . 'headers";a:2:{s:13:"cache-control";a:1:{i:0;s:8:"no-cache";}s:4:"date";a:1:{i:0;s:29:"Wed, 09 Mar 2022 02:19:18 GMT";}}s:15:"' . "\0" . '*' . "\0" . 'cacheControl";a:0:{}}s:10:"' . "\0" . '*' . "\0" . 'content";s:96:"";s:10:"' . "\0" . '*' . "\0" . 'version";s:3:"1.0";s:13:"' . "\0" . '*' . "\0" . 'statusCode";i:200;s:13:"' . "\0" . '*' . "\0" . 'statusText";s:2:"OK";s:10:"' . "\0" . '*' . "\0" . 'charset";N;}'); + return $response; + } + + /** + * 退款回调 + */ + public function actionRefundNotify() + { + Yii::$app->response->format = Response::FORMAT_RAW; + Yii::$app->response->formatters = []; + + + $response = WechatService::getInstance()->payment->handleRefundedNotify(function ($message, $reqInfo, $fail) { + // 其中 $message['req_info'] 获取到的是加密信息 + // $reqInfo 为 message['req_info'] 解密后的信息 + // 你的业务逻辑... + + /** + * {"cash_refund_fee":"1","out_refund_no":"RF20221124103051025400","out_trade_no":"PY20221124100521434224","refund_account":"REFUND_SOURCE_RECHARGE_FUNDS","refund_fee":"1","refund_id":"50300503882022112427569050043","refund_recv_accout":"\u6d59\u6c5f\u519c\u4fe1\u501f\u8bb0\u53617865","refund_request_source":"API","refund_status":"SUCCESS","settlement_refund_fee":"1","settlement_total_fee":"1","success_time":"2022-11-24 10:31:00","total_fee":"1","transaction_id":"4200001675202211242752421487"} + */ + + //记录回调信息 + $callback = new Callback(); + $callback->content = json_encode($reqInfo); + $callback->type = 'refund'; + $callback->save(); + + $t = \Yii::$app->db->beginTransaction(); + try { + $transaction_id = $reqInfo['transaction_id']; + $out_refund_no = $reqInfo['out_refund_no']; + + $paymentProductOrder = PaymentProductOrder::find()->where([ + 'transaction_id' => $transaction_id, + ])->one(); + if ($paymentProductOrder) { + if ($paymentProductOrder->is_pay != 1) { + throw new Exception('支付订单不存在'); + } + $order = ProductOrder::find()->where([ + 'order_no' => $paymentProductOrder->order_no, + ])->with('prescription')->one(); + if (!$order || $order->is_pay != 1) { + throw new Exception('订单不存在'); + } + $order_type = 1; + $refund = ProductOrderRefund::find()->where(['refund_no' => $out_refund_no])->one();//退款订单 + $payment_refund = PaymentProductRefund::find()->where(['refund_no' => $out_refund_no])->one(); + } else { + $PaymentRegister = PaymentRegister::find()->where([ + 'transaction_id' => $transaction_id + ])->one(); + if (!$PaymentRegister || $PaymentRegister->is_pay != 1) { + throw new \yii\db\Exception('支付订单不存在'); + } + + $order = Register::find()->where([ + 'order_no' => $PaymentRegister->order_no, + ])->one(); + if (!$order || $order->is_pay != 1) { + throw new Exception('订单不存在'); + } + $order_type = 2; + $refund = RegisterRefund::find()->where(['refund_no' => $out_refund_no])->one();//退款订单 + $payment_refund = PaymentRegisterRefund::find()->where(['refund_no' => $out_refund_no])->one(); + } + + if (!$refund || !$payment_refund) { + throw new Exception('退款订单不存在'); + } + if ($reqInfo['refund_status'] == 'SUCCESS') { + if ($order_type == 1) { + $order->refund_status = 3;//已退款 + $order->status = ProductOrderEnum::REFUND;//已退款 + $order->refund_time = time(); + $order->save(); + + if ($order->is_online) { //平台订单状态同步 + \Yii::$app->queue->delay(0)->push(new ProductOrderSyncPlatformJob([ + 'orderId' => $order->id, + 'status' => 3 + ])); + } + } + + $refund->is_refund = 1; + $refund->refund_time = date('Y-m-d H:i:s', strtotime($reqInfo['success_time'])); + $refund->save(); + + $payment_refund->is_pay = 1; + $payment_refund->pay_type = 1; + $payment_refund->save(); + + } else { + $refund->is_refund = -1; + $refund->save(); + + $payment_refund->is_pay = -1; + $payment_refund->save(); + } + + // 增加流水记录 + $fundWater = new FundWater();//出账 + $fundWater->store_id = $order->store_id; + $fundWater->order_type = $order_type; + $fundWater->type = 'refund'; // 出账 + $fundWater->order_id = $order->id; + $fundWater->user_id = $order->user_id; + $fundWater->service_user_id = $order_type == 1 ? $order->su_id : $order->service_user_id; + $fundWater->refund_no = $refund->refund_no; + $fundWater->price = $order_type == 1 ? $order->total_pay_price : $order->price; + $fundWater->pay_type = 1; //微信 + $fundWater->saveOrFail(); + + $callback->status = 1; + $callback->save(); + $t->commit(); + + return true; // 返回 true 告诉微信“我已处理完成” + // 或返回错误原因 $fail('参数格式校验错误'); + } catch (\Exception $exception) { + $t->rollBack(); + $callback->message = $exception->getMessage(); + $callback->save(); + $fail($exception->getMessage()); + } + }); + return $response; + } + + + /** + * 阿里oss直传回调 + */ + public function actionUploadNotify() + { + // 1.获取OSS的签名header和公钥url header + $headers = Yii::$app->request->getHeaders(); + + $authorizationBase64 = ""; + $pubKeyUrlBase64 = ""; + if (isset($headers['authorization'])) { + $authorizationBase64 = $headers['authorization']; + } else { + if (isset($_SERVER['HTTP_AUTHORIZATION'])) { + $authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION']; + } + } + if (isset($headers['x-oss-pub-key-url'])) { + $pubKeyUrlBase64 = $headers['x-oss-pub-key-url']; + } else { + if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL'])) { + $pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL']; + } + } + if ($authorizationBase64 == '' || $pubKeyUrlBase64 == '') { + throw new Exception('参数异常'); + } + + // 2.获取OSS的签名 + $authorization = base64_decode($authorizationBase64); + + // 4.获取回调body + $body = file_get_contents('php://input'); + + // 5.拼接待签名字符串 + $authStr = ''; + $path = $_SERVER['REQUEST_URI']; + $pos = strpos($path, '?'); + if ($pos === false) { + $authStr = urldecode($path) . "\n" . $body; + } else { + $authStr = urldecode(substr($path, 0, $pos)) . substr($path, $pos, strlen($path) - $pos) . "\n" . $body; + } + + // 3.获取公钥 + $pubKey = (new UploadService())->getPublicKey($pubKeyUrlBase64); + if ($pubKey == "") { + throw new Exception('公钥异常'); + } + + // 6.验证签名 + $ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5); + if (!$ok) { + throw new Exception('签名异常'); + } + + $data = (new UploadService())->getBody($body); + return $data; + } + + // 互医订单同步 + public function actionPlatformNotify() + { + Yii::$app->response->format = Response::FORMAT_RAW; + + $content = file_get_contents('php://input'); + $callback = new Callback(); + $callback->content = $content; + $callback->type = 'platform_notify'; + $callback->save(); + + $t = \Yii::$app->db->beginTransaction(); + try { + $data = json_decode($content, true); + $config = \Yii::$app->params; + + switch ($data['type']) { + case 'order_create'://订单创建 + $sign = md5($data['order']['order_no'] . $data['time'] . $config['platform']['token'] . $data['type']); + if ($sign != $data['sign']) { + throw new Exception('sign不匹配'); + } + $isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one(); + if ($isExist) { + throw new Exception('产品订单已存在'); + } + + $userPatient = UserPatient::findOne([ + 'user_id' => $data['order']['user_id'], + 'id_card' => $data['order']['patient']['id_card'], + 'is_delete' => 0 + ]); + + $storeUser = StoreUser::find()->where([ + 'user_id' => $data['order']['user_id'], + 'is_online' => 1 + ])->one(); + + $repice = $data['order']['recipe']; + $prescription_type = $data['order']['prescription_type']; + $priceTotal = $data['order']['total_price']; + foreach ($data['order']['goods'] as $v) { + $drug = Drug::find()->alias('d')->where(['d.id' => $v['id']])->joinWith('drugStoreDrug')->one(); + if (!$drug) { + throw new Exception('基础药品不存在:' . $v['id']); + } + } + + $is_decoct = $data['order']['decoct']; + $process_price = 0; + $dosage = $data['order']['dosage']; + $process_rule_id = 0; + $process_rule = ''; + $process_rule_note = ''; + if ($prescription_type == 1 || $prescription_type == 3) { //中药 + $ids = array_column($data['order']['goods'], 'id'); + $medicine = ChineseMedicine::find()->select('id,drug_id,name,order,unit,number,price,drug_number,buy_price')->with(['unit', 'useWay'])->where(['in', 'id', $ids])->asArray()->all(); +// $price = 0; +// $totalNum = 0; +// foreach ($medicine as $value){ +// $drugNumber = (int) $value['number'] * (int) $dosage; +// $totalNum += $drugNumber; +// $price+=$value['number'] * $value['price'] * $dosage; +// } + if ($is_decoct == 1) { + $process_rule_id = 6; + $processRule = ProcessRule::find()->where(['id' => 6])->one(); + $process_rule = '加工方式:汤剂-浓煎-' . $data['order']['volume'] . ',' . $processRule->price . '元/,共' . $dosage . '贴'; + $process_price = $processRule->price * $dosage; + $priceTotal += $process_price; + } + } + if ($prescription_type == 1) { + $prescription_no = 'ZY' . rand(111111, 999999) . time(); + } elseif ($prescription_type == 2) { + $prescription_no = 'XY' . rand(111111, 999999) . time(); + } else { + $prescription_no = 'GY' . rand(111111, 999999) . time(); + } + + $prescription_content['prescription_no'] = $prescription_no; + $prescription_content['repice'] = $data['order']['recipe']; + $prescription_content['created_at'] = date('Y-m-d', time()); + $prescription_content['doctor_order'] = $data['order']['doctor_order']; + $prescription_content['clinical_diagnose'] = $data['order']['clinical_diagnose']; + $prescription_content['category'] = '自费'; + $prescription_content['patient'] = $userPatient; + $prescription_content['patient']['age'] = FuncHelper::getAgeFromIdNo($userPatient->id_card); + $prescription_content['doctor'] = DoctorInfo::find()->select('su_id,name,depart_id,title_id')->where(['su_id' => $data['order']['doctor_id']])->with(['depart', 'title'])->asArray()->one(); + $prescription_content['total_pay_price'] = $priceTotal; + + $prescription = new Prescription(); + $prescription->store_id = $storeUser->store_id ?? 11001; + $prescription->register_id = 0; + $prescription->prescription_no = $prescription_no; + $prescription->online_prescription_no = $data['order']['prescription_no']; + $prescription->su_id = $data['order']['doctor_id']; + $prescription->user_id = $userPatient->user_id; + $prescription->up_id = $userPatient->id; + $prescription->status = 0; + $prescription->type = 1;//普通方 + $prescription->is_online = 1; + $prescription->content = Json::encode($prescription_content); + $prescription->prescription_type = $prescription_type; + $prescription->category = 1; + $prescription->process_rule_id = $process_rule_id; + $prescription->process_rule = $process_rule; + $prescription->process_rule_note = $process_rule_note; + $over_time = \Yii::$app->params['prescription']['over_time']; + $doctor_order = []; + if (date('H') >= 16) { + $doctor_order[] = '该处方有效期延长为三天内有效'; + $over_time = 72 * 3600; + } + if ($repice[0]['dosage'] > 7) { + $doctor_order[] = '患者需长期使用此药,开具超七天用量'; + } + $doctor_order[] = $data['order']['doctor_order']; + $prescription->valid_hours = $over_time / 3600; + $prescription->doctor_order = implode('|', $doctor_order); + $prescription->clinical_diagnose = $data['order']['clinical_diagnose']; + $prescription->total_pay_price = $priceTotal; + $prescription->saveOrFail(); + + + //获取支付方式配置 + $payConfig = PayConfig::findOne(['status' => 1, 'current_use' => 1]); + + $productOrder = new ProductOrder(); + $productOrder->store_id = $storeUser->store_id ?? 11001; + $productOrder->is_online = 1; + $productOrder->online_prescription_status = 0; + $productOrder->dosage = isset($data['order']['dosage']) ? $data['order']['dosage'] : 0; + $productOrder->su_id = $data['order']['doctor_id']; + $productOrder->user_id = $data['order']['user_id']; + $productOrder->up_id = $userPatient->id ?? 0; + $productOrder->order_no = Carbon::now()->format('YmdHis') . rand(10000, 99999) . rand(10000, 99999); + $productOrder->sync_order_no = $data['order']['order_no']; + $productOrder->order_type = 2; //商城订单 + $productOrder->prescription_type = $data['order']['prescription_type']; + $productOrder->p_id = $prescription->id; + $productOrder->status = 0; + $productOrder->items_price = $data['order']['total_price']; + $productOrder->process_price = $process_price; + $productOrder->trans_expenses = 0; + $productOrder->type = $payConfig->pay_type ?? 2;//1微信 2易票联 + $totalPayPrice = $priceTotal; + + $userAddress = Address::find()->select('id,name,mobile,province,region,detail_address')->where(['user_id' => $data['order']['user_id']])->orderBy('is_default DESC')->asArray()->all(); + if ($userAddress) { + $productOrder->address_id = $userAddress[0]['id']; + $productOrder->address = Json::encode($userAddress[0]); + $productOrder->express_name = $userAddress[0]['name']; + $productOrder->express_mobile = $userAddress[0]['mobile']; + $productOrder->express_region = $userAddress[0]['region']; + $productOrder->express_address = $userAddress[0]['detail_address']; + $region = Region::find()->where(['name' => $userAddress[0]['province']])->one(); + $productOrder->trans_expenses = $region->express_fee; + $totalPayPrice = $totalPayPrice + $region->express_fee; + } + $productOrder->total_pay_price = $totalPayPrice; + $productOrder->saveOrFail(); + + $market_price = '0'; + foreach ($data['order']['goods'] as $v) { + $drug = Drug::find()->alias('d')->where(['d.id' => $v['id']])->joinWith('drugStoreDrug')->one(); + if (!$drug) { + throw new Exception('基础药品不存在:' . $v['id']); + } + $item = new ProductOrderItems(); + $item->product_order_id = $productOrder->id; + $item->drug_id = $drug->id; + $item->drug_image = $drug->image; + $item->number = $v['number']; + $item->type = $drug->type; + $item->drug_no = $drug->drug_number; + $item->price = $drug->drugStoreDrug->price; + $item->buy_price = $drug->drugStoreDrug->market_price; + $item->drug_name = $drug->drug_name; + $item->small_info = $drug->small_info; + $item->saveOrFail(); + + $itemMarketPrice = bcmul($v['number'],$drug->drugStoreDrug->market_price,2); + $market_price = bcadd($market_price,$itemMarketPrice,2); + + } + + $productOrder->market_price = $market_price; + $productOrder->saveOrFail(); + + + //生成系统消息 + $SystemNotice = new SystemNotice(); + $SystemNotice->store_id = $storeUser->store_id ?? 11001; + $SystemNotice->content = '您有一条在线问诊流转处方,请及时处理'; + $SystemNotice->data = $prescription->id; + $SystemNotice->base_type = SystemNoticeTypeEnum::ONLINE_PRESCRIPTION; + $SystemNotice->scene_type = 2;//用户端 + $SystemNotice->user_id = $data['order']['doctor_id']; + $SystemNotice->notice_at = date('Y-m-d H:i:s', time()); + $SystemNotice->saveOrFail(); + + //触发订单创建事件 + $event = new ProductOrderEvent(); + $event->order = $productOrder; + $event->sender = $this; + \Yii::$app->trigger(ProductOrder::EVENT_CREATED, $event); + + break; + case 'prescription_pass'://处方通过 + $sign = md5($data['order']['order_no'] . $data['time'] . $config['platform']['token'] . $data['type']); + if ($sign != $data['sign']) { + throw new Exception('sign不匹配'); + } + $isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one(); + if (!$isExist) { + throw new Exception('产品订单不存在'); + } + $isExist->online_prescription_status = 1; + $isExist->save(); + break; + case 'prescription_refuse'://处方拒绝 + $sign = md5($data['order']['order_no'] . $data['time'] . $config['platform']['token'] . $data['type']); + if ($sign != $data['sign']) { + throw new Exception('sign不匹配'); + } + $isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one(); + if (!$isExist) { + throw new Exception('产品订单不存在'); + } + $isExist->online_prescription_status = 2; + $isExist->save(); + //未付款订单取消/已付款订单退款 + // 判断订单是否已付款且待发货,是则进行退款操作 + + if ($isExist->cancel_status == 0 && $isExist->refund_status == 0 && $isExist->status == 1 && $isExist->is_pay == 1) { + // 自动退款 + $ProductRefundForm = new ProductRefundForm(); + $ProductRefundForm->refund([ + 'order_id' => $isExist->id, + 'user_id' => $isExist->user_id + ]); + } else { + // 订单取消 + $ProductCancelForm = new ProductCancelForm(); + $ProductCancelForm->cancel([ + 'order_id' => $isExist->id, + 'user_id' => $isExist->user_id + ], '处方未通过审核,订单取消'); + } + + break; + case 'doctor_approved': + $sign = md5($data['su_id'] . $data['time'] . $config['platform']['token'] . $data['type']); + if ($sign != $data['sign']) { + throw new Exception('sign不匹配'); + } + $isExist = DoctorInfo::find()->where(['su_id' => $data['su_id']])->one(); + if (!$isExist) { + throw new Exception('医生不存在'); + } + $isExist->is_sync = 2; + $isExist->save(); + break; + default: + throw new Exception('错误的回调类型'); + break; + } + + $callback->status = 1; + $callback->save(); + $t->commit(); + return true; + } catch (Exception $e) { + $t->rollBack(); + $callback->message = $e->getMessage(); + $callback->save(); + Yii::$app->response->setStatusCode('400'); + return false; + } + } + +} \ No newline at end of file diff --git a/member/modules/v1/controllers/DoctorController.php b/member/modules/v1/controllers/DoctorController.php new file mode 100644 index 0000000..7b5b5f8 --- /dev/null +++ b/member/modules/v1/controllers/DoctorController.php @@ -0,0 +1,454 @@ +where([ + 'pid' => 0, + ])->with('child')->asArray()->all(); + + return $list; + } + + /** + * @doc-name 医生列表 + * @doc-param string keyword 关键词 / optional + * @doc-param json depart_id 科室id,多选["科室id1","科室id2"] [] optional + * @doc-param json title_id 职称,多选["id1","id2"] [] optional + * @doc-param int sort 1综合排序2问诊量3接诊率4综合评分 1 optional + * @doc-param int page 页码 1 optional + * @doc-param int page_size 每页条数 20 optional + * @doc-return mixed @List{ServiceUser{id,avatar-string-医生头像,name-string-医生姓名,depart-string-医生科室,store-string-门店,title-string-职称,good_at-string-擅长,accept_percent-string-接诊率,inquiry_num-int-问诊量,overall_score-int-综合评分,@Service{DoctorService{register_status,register_price}}}} 医生列表 + * @doc-return mixed @Pagination{total_count-int-总数量,page_count-int-总页数,current_page-int-当前页,per_page-int-每页条数} 分页数据 + */ + public function actionAllList() + { + $post = \Yii::$app->request->post(); + $keyword = $post['keyword']; + $store_id = \Yii::$app->store; + $su_id = StoreDoctor::find()->select('su_id')->where([ + 'store_id' => $store_id, + 'is_delete' => 0 + ])->column() ; + + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::OK, + 'su.is_delete' => 0 + ])->andWhere([ + 'in', 'su.id', $su_id + ]); + + $depart_arr = json_decode(ArrayHelper::getValue($post, 'depart_id', "[]"), true); + $title_arr = json_decode(ArrayHelper::getValue($post, 'title_id', "[]"), true); +// $sort = ArrayHelper::getValue($post, 'sort', 0); + + $departs = Department::find()->select('id,name')->where(['<>', 'id', 0])->asArray()->all(); + $id = 0; + foreach ($departs as $v) { + if (in_array($keyword, $v) == true) { + $id = $v['id']; + } + } + + $query->joinWith(['docInfo' => function ($q) use ($id, $keyword, $depart_arr, $title_arr) { + $q->alias('i'); + //搜索框搜索姓名和科室 + if (!empty($keyword)) { + $q->andWhere([ + 'or', + ['like', 'i.name', $keyword], + ['i.depart_id' => $id] + ]); + } + //科室搜索 + if (!empty($depart_arr)) { + $q->andWhere([ + 'i.depart_id' => $depart_arr + ]); + } + //职称搜索 + if (!empty($title_arr)) { + $q->andWhere([ + 'i.title_id' => $title_arr + ]); + } + }]); + + $query->joinWith(['docIdentity' => function ($q) { + $q->alias('it'); + }]); + + if (!empty($post['sort'])){ + switch ($post['sort']) { + case 1://综合排序 + $query->orderBy('i.id desc'); + break; + case 2://问诊量 + $query->orderBy('i.inquiries desc'); + break; + case 3://接诊率 + $query->orderBy('i.reception_rate desc'); + break; + case 4://综合评分 + $query->orderBy('i.grade desc'); + break; + default: + return ['参数错误']; + } + } + + $this->field = [ + ServiceUser::class => [ + 'id', + 'avatar' => 'docIdentity.work_avator', + 'name' => 'docInfo.name', + 'depart' => 'docInfo.depart.name', + 'store' => function () use($store_id){ + $store = Store::findOne(['id' => $store_id]); + return $store->name; + }, + 'title' => 'docInfo.title.name', + 'good_at' => 'docInfo.good_at', + 'accept_percent' => function ($model) { + $accept_num = Order::find()->where([ + 'su_id' => $model->id, + 'is_pay' => 1, + 'accept_status' => [OrderAcceptEnum::ACCEPTING, OrderAcceptEnum::OVER], + ])->count(); + $all_num = Order::find()->where([ + 'su_id' => $model->id, + 'is_pay' => 1, + 'accept_status' => [OrderAcceptEnum::TIMEOUT_ACCEPT, OrderAcceptEnum::REFUSED, OrderAcceptEnum::ACCEPTING, OrderAcceptEnum::OVER], + ])->count(); + $accept_percent= $all_num == 0 ? 100 : round(($accept_num / $all_num) * 100, 2) ; + + $DoctorInfo= DoctorInfo::find()->where([ + 'su_id'=>$model->id + ])->one(); + + if ($DoctorInfo){ + $DoctorInfo->su_id=$model->id; + $DoctorInfo->reception_rate=$accept_percent; + $DoctorInfo->saveOrFail(); + } + return $accept_percent; + }, + 'inquiry_num' => function($model){ + $count=Register::find()->where([ + 'service_user_id' => $model->id, + 'is_pay' => 1, + 'is_cancel'=>0 + ])->count(); + $DoctorInfo= DoctorInfo::find()->where([ + 'su_id'=>$model->id + ])->one(); + if ($DoctorInfo){ + $DoctorInfo->inquiries=$count; + $DoctorInfo->saveOrFail(); + } + return $count; + }, + 'overall_score' => function($m){ + $score= UserComment::find()->select('score')->where([ + 'su_id'=>$m->id + ])->column(); + $allnum=UserComment::find()->where([ + 'su_id'=>$m->id + ])->count(); + $sum_score=array_sum($score); + $overall_score= $allnum == 0 ? '5' : round(($sum_score / $allnum) , 2) ; + $DoctorInfo= DoctorInfo::find()->where([ + 'su_id'=>$m->id + ])->one(); + if ($DoctorInfo){ + $DoctorInfo->su_id=$m->id; + $DoctorInfo->grade=$overall_score; + $DoctorInfo->saveOrFail(); + } + return $overall_score; + }, + 'service' => 'docService' + ], + DoctorService::class => [ + 'register_status', 'register_price' + ] + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 医生详情 + * @doc-param int doctor_id 医生id + * @doc-return mixed ServiceUser{id,avatar-string-医生头像,name-string-医生姓名,depart-string-医生科室,store-string-门店,title-string-职称,good_at-string-擅长,intro-string-简介,accept_percent-string-接诊率,inquiry_num-int-问诊量,overall_score-float-综合评分,status-int-状态1为关注其他返回均为未关注,@Service{DoctorService{*}}} 医生详情 + */ + public function actionDetail() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['doctor_id', 'required'] + ]); + $store_id = \Yii::$app->store; + $su_id = StoreDoctor::find()->select('su_id')->where([ + 'store_id' => $store_id, + 'su_id'=>$post['doctor_id'], + 'is_delete' => 0 + ])->column() ; + + $doctor = ServiceUser::find()->alias('su')->where([ + 'su.id' => $su_id, + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::OK, + 'id' => $post['doctor_id'], + 'is_delete' => 0 + ])->with('docService')->one(); + if (!$doctor) throw new Exception('医生不存在'); + + return ArrayHelper::toArray($doctor, [ + ServiceUser::class => [ + 'id', + 'avator' => 'docIdentity.work_avator', + 'name' => 'docInfo.name', + 'depart' => 'docInfo.depart.name', + 'store' => function () use($store_id){ + $store = Store::findOne(['id' => $store_id]); + return $store->name; + }, + 'title' => 'docInfo.title.name', + 'good_at' => 'docInfo.good_at', + 'intro' => 'docInfo.intro', + 'accept_percent' => function ($model) { + $accept_num = Order::find()->where([ + 'su_id' => $model->id, + 'is_pay' => 1, + 'accept_status' => [OrderAcceptEnum::ACCEPTING, OrderAcceptEnum::OVER], + ])->count(); + $all_num = Order::find()->where([ + 'su_id' => $model->id, + 'is_pay' => 1, + 'accept_status' => [OrderAcceptEnum::TIMEOUT_ACCEPT, OrderAcceptEnum::REFUSED, OrderAcceptEnum::ACCEPTING, OrderAcceptEnum::OVER], + ])->count(); + return $all_num == 0 ? '100%' : round(($accept_num / $all_num) * 100, 2) . '%'; + }, + 'inquiry_num' => function ($model) { + $count=Register::find()->where([ + 'service_user_id' => $model->id, + 'is_pay' => 1, + 'is_cancel'=>0 + ])->count(); + $DoctorInfo= DoctorInfo::find()->where([ + 'su_id'=>$model->id + ])->one(); + if ($DoctorInfo){ + $DoctorInfo->inquiries=$count; + $DoctorInfo->saveOrFail(); + } + return $count; + }, + 'overall_score' => function($m){ + $score= UserComment::find()->select('score')->where([ + 'su_id'=>$m->id + ])->column(); + $allnum=UserComment::find()->where([ + 'su_id'=>$m->id + ])->count(); + $sum_score=array_sum($score); + return $allnum == 0 ? '5' : round(($sum_score / $allnum) , 2) ; + }, + 'service' => 'docService', + 'status' => function ($model) { + $status = FollowDoctor::find()->select('status') + ->where([ + 'su_id' => $model->id, + 'user_id' => \Yii::$app->user->identity->id + ])->column(); + if (empty($status)) { + return 0;//未关注 + } + return $status; + }, + ], + ]); + } + + /** + * @doc-name 患者评论的顶部 + * @doc-param int su_id 医生id + * @doc-return int all_num 全部 + * @doc-return int high_score 高分 + * @doc-return int low_score 低分 + * @doc-return string patient_score 患者评分 + */ + public function actionTop() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['su_id', 'required'] + ]); + + $doctor = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::OK, + 'id' => $post['su_id'], + 'is_delete' => 0 + ])->all(); + if (!$doctor) throw new \yii\db\Exception('医生不存在'); + + $all_num = UserComment::find()->where([ + 'su_id' => $post['su_id'] + ])->count(); + $high_score = UserComment::find()->where([ + '>=', 'score', 4, + ])->andWhere(['su_id' => $post['su_id']])->count(); + $low_score = UserComment::find()->where([ + '<=', 'score', 3, + ])->andWhere(['su_id' => $post['su_id']])->count(); + + return [ + 'all_num' => $all_num, + 'high_score' => $high_score, + 'low_score' => $low_score, + 'patient_score' => '5.0', + ]; + } + + /** + * @doc-name 评价列表 + * @doc-param int keyword 筛选1全部2高分3低分 + * @doc-param int su_id 医生id + * @doc-return mixed @List{id-int-评论id,comment-string-评论,score-int-评分,created_at-int-发布时间,nickname-string-昵称,avatarurl-string-头像} 评价信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-页数,pageSize-int-每页数据} 分页信息 + */ + public function actionCommentList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['su_id', 'required'] + ]); + + $doctor = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::OK, + 'id' => $post['su_id'], + 'is_delete' => 0 + ])->all(); + if (!$doctor) throw new \yii\db\Exception('医生不存在'); + + $query = UserComment::find()->where([ + 'su_id' => $post['su_id'] + ]); + + switch ($post['keyword']) { + case 1://全部 + $query->all(); + break; + case 2: + $query->andWhere(['>=', 'score', 4,]); + break; + case 3://低分 + $query->andWhere(['<=', 'score', 3,]); + break; + } + $this->field = [ + UserComment::class => [ + 'id', 'score', 'comment', 'created_at', + 'avator'=>function($u){ + return $u->userPatient->avatar??'https://tenfei03.cfp.cn/creative/vcg/veer/1600water/veer-105516317.jpg'; + }, + 'nickname'=>function($m){ + return StringHelper::string_hide_cut($m->userPatient->name); + }, + ], + ]; + return $this->create($query, $post); + } + + + /** + * @doc-name 医生文章列表 + * @doc-param int id 医生id + * @doc-return mixed @List{id-int-文章id,cover-string-封面,title-string-标题,created_at-int-发布时间} 文章信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionArticleList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $query = DoctorArticle::find()->where([ + 'su_id' => $post['id'], + 'is_draft' => 0, + 'is_delete' => 0, + ]); + $this->field = [ + DoctorArticle::class => [ + 'id', 'title', 'created_at', + 'cover' => function ($model) { + if (empty($model->cover)) { + return 'https://yanydy.oss-cn-hangzhou.aliyuncs.com/uploads/20221130/e52920ceb880e422de5f8b040daa03ab.jpg'; + } + return $model->cover; + } + ] + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 问诊记录列表 + * @doc-param string keyword 搜索疾病或症状 / optional + * @doc-param int id 医生id + * @doc-return mixed @List{type-int-0用户问1医生回复} + */ + public function actionAskList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $query= ImMessage::find()->where([ + 'service_id'=>$post['id'], + 'is_delete'=>0 + ])->addSelect('content,type')->groupBy('ims_id')->orderBy('id desc'); + $this->field=[ + 'id','content','type' + ]; + return $this->create($query,$post); + } + + +} diff --git a/member/modules/v1/controllers/EplpayCallbackController.php b/member/modules/v1/controllers/EplpayCallbackController.php new file mode 100644 index 0000000..b90fb10 --- /dev/null +++ b/member/modules/v1/controllers/EplpayCallbackController.php @@ -0,0 +1,350 @@ +response->format = Response::FORMAT_RAW; + + $content = file_get_contents('php://input'); + $callback = new Callback(); + $callback->content = $content; + $callback->type = 'eplpay_order'; + $callback->save(); + + $data = json_decode($content, true); + if(!isset($data['payState']) || $data['payState'] == '01'){ //支付失败 + return Json::encode([ + 'returnCode' => '0001', + 'returnMsg' => '支付失败' + ]); + } + $t = \Yii::$app->db->beginTransaction(); + try { + $out_trade_no = $data['outTradeNo']; + $paymentProductOrder = PaymentProductOrder::find()->where([ + 'pay_order_no' => $out_trade_no + ])->one(); + if($paymentProductOrder){ // 产品订单 + $data['pay_order_no'] = $out_trade_no; + $data['order_no'] = $paymentProductOrder->order_no; + $data['transaction_id'] =$data['transactionNo']; + $data['pay_type'] = 2; + $productOrderPayForm = new ProductOrderSubmitForm(); + $order = $productOrderPayForm->paid($data); + $order_type=1; + } else { // 挂号订单 + $PaymentRegister=PaymentRegister::find()->where([ + 'pay_order_no' => $out_trade_no + ])->one(); + if (!$PaymentRegister){ + throw new Exception('订单不存在'); + } + $data['order_no']= $PaymentRegister->order_no; + $data['transaction_id'] =$data['transactionNo']; + $data['pay_type'] = 2; + $RegisterSubmitForm = new RegisterSubmitForm(); + $order = $RegisterSubmitForm->paid($data); + $order_type=2; + } + + // 增加流水记录 + $fundWater = new FundWater(); + $fundWater->store_id = $order->store_id; // 入账 + $fundWater->type = 'enter'; // 入账 + $fundWater->order_type = $order_type; + $fundWater->order_id = $order->id; + $fundWater->user_id = $order->user_id; + $fundWater->service_user_id = $order_type==1?$order->su_id:$order->service_user_id; + $fundWater->order_no = $order->order_no; + $fundWater->price = $order_type==1 ? $order->total_pay_price : $order->price; + $fundWater->pay_type = 2; //易票联 + $fundWater->saveOrFail(); + + $callback->status = 1; + $callback->save(); + $t->commit(); + } catch (Exception $e){ + $t->rollBack(); + $callback->message = $e->getMessage(); + $callback->save(); + return Json::encode([ + 'returnCode' => '0001', + 'returnMsg' => '通信失败' + ]); + } + return Json::encode([ + 'returnCode' => '0000', + 'returnMsg' => '通信成功' + ]); + } + + /** + * 退款回调 + */ + public function actionRefundNotify() + { + Yii::$app->response->format = Response::FORMAT_RAW; + + $content = file_get_contents('php://input'); + $callback = new Callback(); + $callback->content = $content; + $callback->type = 'eplpay_refund'; + $callback->save(); + + $data = json_decode($content, true); + + $t = \Yii::$app->db->beginTransaction(); + try { + $out_trade_no = $data['outTradeNo']; + $out_refund_no = $data['outRefundNo']; + + $paymentProductOrder = PaymentProductOrder::find()->where([ + 'pay_order_no' => $out_trade_no, + ])->one(); + if ($paymentProductOrder){//产品订单 + if ($paymentProductOrder->is_pay!=1){ + throw new Exception('支付订单不存在'); + } + $order = ProductOrder::find()->where([ + 'order_no' => $paymentProductOrder->order_no, + ])->one(); + if(!$order || $order->is_pay!=1){ + throw new Exception('订单不存在'); + } + $order_type = 1; + $refund = ProductOrderRefund::find()->where(['refund_no'=>$out_refund_no])->one();//退款订单 + $payment_refund = PaymentProductRefund::find()->where(['refund_no'=>$out_refund_no])->one(); + } else { //挂号订单 + $PaymentRegister=PaymentRegister::find()->where([ + 'pay_order_no' => $out_trade_no + ])->one(); + if (!$PaymentRegister || $PaymentRegister->is_pay!=1){ + throw new \yii\db\Exception('支付订单不存在'); + } + + $order = Register::find()->where([ + 'order_no' => $PaymentRegister->order_no, + ])->one(); + if(!$order || $order->is_pay!=1){ + throw new Exception('订单不存在'); + } + $order_type = 2; + $refund= RegisterRefund::find()->where(['refund_no'=>$out_refund_no])->one();//退款订单 + $payment_refund= PaymentRegisterRefund::find()->where(['refund_no'=>$out_refund_no])->one(); + } + + if(!$refund || !$payment_refund){ + throw new Exception('退款订单不存在'); + } + + if(isset($data['payState']) && $data['payState'] == '00'){ + if ($order_type == 1){ //产品订单 + $order->refund_status =3;//已退款 + $order->status = ProductOrderEnum::REFUND;//已退款 + $order->refund_time = time(); + $order->save(); + + if($order->order_type ==1){//处方订单 + $prescription = $order->prescription; + $prescription->refund_status = 2;//已退款 + $prescription->save(); + + //药品库存回滚 + $DrugRollBackForm = new DrugRollBackForm(); + $DrugRollBackForm->rollBack($order->p_id); + }else{ + //药品库存回滚 + $DrugRollBackForm = new DrugRollBackForm(); + $DrugRollBackForm->rollBack($order->id, $order->order_type); + } + + // 退款分账结算更新 + \Yii::$app->queue->delay(0)->push(new ProductOrderRefundJob([ + 'orderId' => $order->id + ])); + + if($order->is_online){ //平台订单状态同步 + \Yii::$app->queue->delay(0)->push(new ProductOrderSyncPlatformJob([ + 'orderId' => $order->id, + 'status' => 3 + ])); + } + }else{ + //分账状态更新 + $ledgerForm = new LedgerForm(); + $ledgerForm->order_id = $order->id; + $ledgerForm->status = 2; + $ledgerForm->update('register'); + } + $refund->is_refund = 1; + $refund->refund_time = date('Y-m-d H:i:s', strtotime($data['payTime'])); + $refund->save(); + + $payment_refund->is_pay = 1; + $payment_refund->pay_type = 1; + $payment_refund->save(); + + // 增加流水记录 + $fundWater = new FundWater(); + $fundWater->store_id = $order->store_id; // 门店 + $fundWater->type = 'refund'; // 出账 + $fundWater->order_type = 1; // 产品订单 + $fundWater->order_id = $order->id; + $fundWater->user_id = $order->user_id; + $fundWater->service_user_id = $order_type==1?$order->su_id:$order->service_user_id; + $fundWater->refund_no = $refund->refund_no; + $fundWater->price = $order_type==1 ? $order->total_pay_price : $order->price; + $fundWater->pay_type = 2; //易票联 + $fundWater->saveOrFail(); + + } else {//退款失败 + if($order_type == 1 && $order->is_send != 1){ + $order->status = ProductOrderEnum::WAIT_SEND;//待发货 + } + $order->refund_status = 0; + $order->refund_time = 0; + $order->save(); + + $refund->fail_reason = '退款失败'; + $refund->is_refund = -1; + $refund->save(); + + $payment_refund->is_pay = -1; + $payment_refund->save(); + } + + $callback->status = 1; + $callback->save(); + $t->commit(); + }catch (\Exception $exception){ + $t->rollBack(); + $callback->message = $exception->getMessage(); + $callback->save(); + return Json::encode([ + 'returnCode' => '0001', + 'returnMsg' => '通信失败' + ]); + } + return Json::encode([ + 'returnCode' => '0000', + 'returnMsg' => '通信成功' + ]); + } + + + /** + * 提现回调 + */ + public function actionWithdrawNotify() + { + Yii::$app->response->format = Response::FORMAT_RAW; + + $content = file_get_contents('php://input'); + $callback = new Callback(); + $callback->content = $content; + $callback->type = 'eplpay_withdraw'; + $callback->save(); + + $data = json_decode($content, true); + $out_trade_no = $data['outTradeNo']; + + $t = \Yii::$app->db->beginTransaction(); + try { + $applyOrder = CashApply::findOne(['order_no' => $out_trade_no,'check_status' => 2]); //已审核通过的提现申请 + if(!$applyOrder){ + throw new Exception('提现申请不存在'); + } + $CashAccount = CashAccount::findOne([ + 'user_type' => $applyOrder->user_type, + 'user_id' => $applyOrder->user_id + ]); + if(!$CashAccount){ + throw new Exception('分账账号不存在'); + } + if(!isset($data['payState']) || $data['payState'] == '01'){ //提现失败 + // $applyOrder->check_staus = 4; + // $applyOrder->check_result = '提现失败'; + // $applyOrder->check_time = date('Y-m-d H:i:s'); + $applyOrder->dakuan_status = -1; + $applyOrder->saveOrFail(); + + $CashAccount->able_cash = $CashAccount->able_cash + $applyOrder->apply_cash; + $CashAccount->frozen_cash -= $applyOrder->apply_cash; + $CashAccount->saveOrFail(); + } else { + $applyOrder->dakuan_status = 1; + $applyOrder->dakuan_time = date('Y-m-d H:i:s'); + $applyOrder->saveOrFail(); + + $CashAccount->frozen_cash -= $applyOrder->apply_cash; + $CashAccount->withdrawn_cash += $applyOrder->apply_cash; + $CashAccount->charge_cash += $applyOrder->charge_cash; + $CashAccount->saveOrFail(); + + // 增加流水记录 + $fundWater = new FundWater(); + $fundWater->type = 'withdraw'; // 提现 + $fundWater->order_type = 3; // 分账提现 + $fundWater->order_id = $applyOrder->id; + $fundWater->user_id = $applyOrder->user_id; + $fundWater->user_type = $applyOrder->user_type; + $fundWater->price = $applyOrder->apply_cash; + $fundWater->pay_type = 2; //易票联 + $fundWater->saveOrFail(); + } + $callback->status = 1; + $callback->save(); + $t->commit(); + } catch (Exception $e){ + $t->rollBack(); + $callback->message = $e->getMessage(); + $callback->save(); + return Json::encode([ + 'returnCode' => '0001', + 'returnMsg' => '通信失败' + ]); + } + return Json::encode([ + 'returnCode' => '0000', + 'returnMsg' => '通信成功' + ]); + } + + + +} diff --git a/member/modules/v1/controllers/ImController.php b/member/modules/v1/controllers/ImController.php new file mode 100644 index 0000000..14ba772 --- /dev/null +++ b/member/modules/v1/controllers/ImController.php @@ -0,0 +1,472 @@ +where([ + 'user_id' => \Yii::$app->user->identity->id, + 'type' => ImSessionTypeEnum::USER_LEAD, + 'is_delete' => 0 + ])->with('serviceUser')->orderBy('id desc')->one(); + $leadSessions = $leadSessions ? ArrayHelper::toArray($leadSessions,[ + ImMessageSession::class => [ + 'id', + 'type', + 'name' => function(){ + return '导医消息'; + }, + 'avatar' => 'serviceUser.leadInfo.avatar', + 'noread_count' => function($model){ + $count = ImMessage::find()->where([ + 'ims_id' => $model->id, + 'read_status' => 0, + 'type' => ImMessageSendTypeEnum::SERVICE_SEND, + 'is_delete' => 0 + ])->count(); + return $count; + }, + 'last' => function($model){ + $message = ImMessage::find()->where([ + 'ims_id' => $model->id, + 'is_delete' => 0, + ])->orderBy('id desc')->one(); + if($message){ + return [ + 'created_at' => $message['created_at'], + 'created_at_format' => FuncHelper::time_tran($message['created_at']), + 'content' => $message['content'], + ]; + }else{ + return []; + } + } + ] + ]) : []; + + + //最新的消息排在最上边,不管是谁发送的,不管已读未读 + $last = ImMessage::find()->where([ + 'is_delete' => 0, + ])->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc'); + + $docSessions = ImMessageSession::find()->alias('ims')->select([ + 'ims.*', + ])->addSelect('l.id as last_id,l.created_at as last_time')->where([ + 'ims.user_id' => \Yii::$app->user->identity->id, + 'ims.type' => UserRoleEnum::DOCTOR, + 'ims.is_delete' => 0 + ])->joinWith(['order' => function($q){ + $q->alias('o')->andWhere(['<>','o.accept_status',OrderAcceptEnum::NO]); + + }])->leftJoin('(' . $last->createCommand()->getRawSql() . ') l', 'ims.id = l.ims_id') + ->with('serviceUser') + ->orderBy('l.created_at desc,ims.id desc') + ->all(); + + $docSessions = count($docSessions) > 0 ? ArrayHelper::toArray($docSessions,[ + ImMessageSession::class => [ + 'id', + 'type', + 'name' => 'serviceUser.docInfo.name', + 'avatar' => 'serviceUser.docInfo.avatar', + 'depart' => 'serviceUser.docInfo.depart.name', + 'noread_count' => function($model){ + $count = ImMessage::find()->where([ + 'ims_id' => $model->id, + 'read_status' => 0, + 'type' => ImMessageSendTypeEnum::SERVICE_SEND, + 'is_delete' => 0 + ])->count(); + return $count; + }, + 'last' => function($model){ + $message = ImMessage::findOne($model->last_id); + if($message){ + return [ + 'created_at' => $model->last_time, + 'created_at_format' => FuncHelper::time_tran($model->last_time), + 'content' => $message->content + ]; + }else{ + return []; + } + } + ] + ]) : []; + + return [ + 'lead' => $leadSessions, + 'doc' => $docSessions + ]; + } + + /** + * @doc-name 清除未读 + */ + public function actionClearNoRead() + { + $t=\Yii::$app->db->beginTransaction(); + try { + ImMessage::updateAll(['read_status'=>1],[ + 'user_id' => \Yii::$app->user->identity->id, + 'type' => ImMessageSendTypeEnum::SERVICE_SEND, + 'read_status' => 0, + 'is_delete' => 0 + ]); + SystemNotice::updateAll(['read_status'=>1],[ + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' =>SystemNoticeTypeEnum::REMINDER, + 'scene_type' => 1, + 'read_status' => 0, + ]); + $t->commit(); + + return ['清除成功']; + }catch (\Exception $e){ + $t->rollBack(); + throw $e; + } + + } + + /** + * @doc-name 会话消息记录 + * @doc-param int ims_id 会话id + * @doc-param int page 页码 1 optional + * @doc-param int page_size 每页条数 20 optional + * @doc-return mixed @Session{ImMessageSession{*,@User-mixed-用户信息{name-string-名称,avatar-string-头像},@ServiceUser-mixed-服务人员信息{name-string-名称,avator-string-头像}}} 会话信息 + * @doc-return mixed @List{ImMessage{*,@User-mixed-用户信息{name-string-名称,avatar-string-头像},@ServiceUser-mixed-服务人员信息{name-string-名称,avator-string-头像}}} 消息记录 + * @doc-return mixed @Pagination{total_count-int-总数量,page_count-int-总页数,current_page-int-当前页,per_page-int-每页条数} 分页数据 + */ + public function actionMessageList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['ims_id','required'] + ]); + + $imMessageSession = ImMessageSession::find()->with('user','serviceUser')->where([ + 'id' => $post['ims_id'], + 'user_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->with('order')->one(); + $session = $imMessageSession ? ArrayHelper::toArray($imMessageSession,[ + ImMessageSession::class => [ + 'id','user_id','service_id','type','status','created_at', + 'user','order', + 'serviceUser' => function($model){ + switch($model->type) { + case ImSessionTypeEnum::USER_USER: + $serviceUser = User::findOne($model->service_id); + return [ + 'name' => $serviceUser->nickname, + 'avatar' => $serviceUser->avatarurl, + ]; + break; + case ImSessionTypeEnum::USER_DOC: + $serviceUser = ServiceUser::find()->where([ + 'id' => $model->service_id + ])->with('docInfo')->one(); + return [ + 'name' => $serviceUser->docInfo->name, + 'avatar' => $serviceUser->docInfo->avatar, + ]; + + case ImSessionTypeEnum::USER_LEAD: + $serviceUser = ServiceUser::find()->where([ + 'id' => $model->service_id + ])->with('leadInfo')->one(); + return [ + 'name' => $serviceUser->leadInfo->name, + 'avatar' => $serviceUser->leadInfo->avatar, + ]; + + case ImSessionTypeEnum::DOC_SERV: + case ImSessionTypeEnum::DRUG_SERV: + case ImSessionTypeEnum::LEAD_SERV: + //这三种情况member下暂时不会有 + break; + } + }, + ], + User::class => [ + 'name'=>'nickname','avatar'=>'avatarurl' + ], + Order::class => [ + 'id', + 'auto_over_time', + 'image_limit_status', + 'left_number', + 'status' => function($model){ + return Order::status_info($model); + }, + 'accept_status' => function($model){ + return Order::accept_info($model); + }, + ] + ]) : []; + $this->extend_result['session'] = $session; + + $query = ImMessage::find()->where([ + 'ims_id' => $post['ims_id'], + 'user_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->with('user','imSession')->orderBy('id desc'); + + $this->field = [ + ImMessage::class => [ + 'id','user_id','service_id','content','read_status','type','created_at', + 'user', + 'serviceUser' => function($model){ + switch($model->imSession->type) { + case ImSessionTypeEnum::USER_USER: + $serviceUser = User::findOne($model->service_id); + return [ + 'name' => $serviceUser->nickname, + 'avatar' => $serviceUser->avatarurl, + ]; + + case ImSessionTypeEnum::USER_DOC: + $serviceUser = ServiceUser::find()->where([ + 'id' => $model->service_id + ])->with('docInfo')->one(); + return [ + 'name' => $serviceUser->docInfo->name, + 'avatar' => $serviceUser->docInfo->avatar, + ]; + + case ImSessionTypeEnum::USER_LEAD: + $serviceUser = ServiceUser::find()->where([ + 'id' => $model->service_id + ])->with('leadInfo')->one(); + return [ + 'name' => $serviceUser->leadInfo->name, + 'avatar' => $serviceUser->leadInfo->avatar, + ]; + + case ImSessionTypeEnum::DOC_SERV: + case ImSessionTypeEnum::DRUG_SERV: + case ImSessionTypeEnum::LEAD_SERV: + //这三种情况member下暂时不会有 + break; + } + }, + ], + User::class => [ + 'name'=>'nickname','avatar'=>'avatarurl' + ], + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 用户端发送消息 + * @doc-desc session_type是会话的类型,直接取用会话的类型,导医第一次可能没有会话id,会话id传递0,会话类型直接传递3 + * @doc-param int ims_id 会话id,跟导医第一次可能没有会话id,传递0 + * @doc-param int session_type 会话类型1跟医生的会话3跟导医的会话 + * @doc-param json content 消息内容 + * @doc-return int image_limit_status 会话类型1会返回,是否限制回复条数1限制0不限制 + * @doc-return int left_number 会话类型1会返回,剩余条数,限制状态下,为0表示回复条数不足,不限制状态下,为0表示无限制 + */ + public function actionMessageSend() + { + //用戶端发送消息 + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + [['ims_id','session_type'],'required'], + ['session_type','in','range'=>[1,3]], + ['content','required','message'=>'消息内容不能为空'] + ]); + + $form = new ImMessageForm(); + $form->attributes = $post; + $form->from_id = \Yii::$app->user->identity->id; + + switch($post['session_type']) + { + case ImSessionTypeEnum::USER_LEAD: + + //导医用的是最新的会话,不管结束未结束,给导医发送消息也可以传递ims_id,不过后台会根据导医会话的状态重新创建会话并进行接入操作 + $query = ImMessageSession::find()->where([ + 'user_id' => \Yii::$app->user->identity->id,//id 32 + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status'=> ImSessionStatusEnum::ING + ]); + + if($post['ims_id']){ + $query->andWhere([ + 'id' => $post['ims_id'] + ]); + } + $ims= $query->one(); + + $lead_id=LeadInfo::getLastLeadUserId();//空闲导医 + + if(!$ims){ //不要判断!$post['ims_id']否则会添加一堆的会话 + $ims = new ImMessageSession(); + $ims->user_id = \Yii::$app->user->identity->id; + $ims->type = $post['session_type']; + $ims->saveOrFail(); + } + + $form->ims_id = $ims->id; + $form->to_id = $ims->service_id; + + $form->sendMessage(); + + return []; + + case ImSessionTypeEnum::USER_DOC: + + $image_limit_status = 0; + $left_number = 0; + + $ims = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + 'is_delete' => 0 + ])->with('order')->one(); + if(!$ims || !$ims->order){ + throw new Exception('会话不存在或者会话订单不存在'); + } + + $form->to_id = $ims->service_id; + + $order = $ims->order; + //检查订单状态 + if($order->accept_status == OrderAcceptEnum::WAIT_ACCEPT){ + //待接诊状态 - 可以补充回答 + $form->sendMessage(); + + }elseif($order->accept_status == OrderAcceptEnum::ACCEPTING ){ + //已接诊状态 - 发送消息 - 扣除相应的条数 + $ts = \Yii::$app->db->beginTransaction(); + try { + $order = Order::findOne($ims->order->id); + if($order->image_limit_status && $order->left_number <=0){ + throw new Exception('回复条数不足'); + } + + $form->sendMessage(); + + if($order->image_limit_status){ + $order->updateCounters(['left_number' => -1]); + } + + $image_limit_status = $order->image_limit_status; + $left_number = $order->left_number; + + $ts->commit(); + }catch (\Exception $exception){ + $ts->rollBack(); + throw $exception; + } + }else{ + //其他情况-拒绝 + throw new Exception('发送失败:订单非待接诊和接诊状态,无法发送消息'); + } + + return [ + 'image_limit_status' => $image_limit_status, + 'left_number' => $left_number, + ]; + } + } + + + /** + * @doc-name 结束会话 + * @doc-param int ims_id 会话id + * @doc-param int service_id 服务端id + */ + public function actionOverSession() + { + $post= \Yii::$app->request->post(); + $this->requestValidate($post,[ + [ ['ims_id','service_id'],'required' ] + ]); + + $imMessageSession= ImMessageSession::find()->where([ + 'id'=>$post['ims_id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + 'service_id'=>$post['service_id'], + 'status'=>0 + ])->one(); + if (!$imMessageSession)throw new \yii\db\Exception('聊天消息会话不存在或已结束'); + + $order_id=ImMessageSessionOrder::find()->select('order_id')->where([ + 'ims_id'=>$post['ims_id'], + ])->column(); + + $order= Order::find()->where([ + 'id'=>$order_id, + 'user_id'=>\Yii::$app->user->identity->getId(), + 'su_id'=>$post['service_id'] + ])->one(); + + if (!$order)throw new \yii\db\Exception('订单不存在'); + $t=\Yii::$app->db->beginTransaction(); + try { + Order::updateAll(['accept_status'=>OrderAcceptEnum::OVER],[ + 'id'=>$order_id, + 'user_id'=>\Yii::$app->user->identity->getId(), + 'su_id'=>$post['service_id'] + ]); + + ImMessageSession::updateAll( + ['status'=>10], + ['id'=>$post['ims_id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + 'service_id'=>$post['service_id']]); + + $t->commit(); + }catch (\Exception $e){ + $t->rollBack(); + throw $e; + } + + return ['会话已结束']; + } + + +} diff --git a/member/modules/v1/controllers/InfoController.php b/member/modules/v1/controllers/InfoController.php new file mode 100644 index 0000000..b194870 --- /dev/null +++ b/member/modules/v1/controllers/InfoController.php @@ -0,0 +1,74 @@ +request->get(); + $Categories = Categories::find(); + + $this->field = [ + Categories::class => [ + 'id', 'name', 'pid', 'level' + ] + ]; + return $this->create($Categories, $get); + + } + + /** + * @doc-name 资讯列表 + * @doc-param int cid 分类id + * @doc-return mixed @DoctorArticle{*} 资讯列表 + */ + public function actionArticleList() + { + + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['cid','required'] + ]); + $DoctorArticle = DoctorArticle::find()->where(['cid'=>$get['cid'],'is_delete'=>0]); + + $this->field = [ + DoctorArticle::class => [ + 'id', 'cid', 'su_id', 'title', 'intro', 'content', 'video_url','cover', + 'created_at' => function ($d) { + return date('Y-m-d Hi:i:s', $d->created_at); + }, + ] + ]; + return $this->create($DoctorArticle, $get); + + } + + /** + * @doc-name 资讯详情 + * @doc-param int id 资讯id + * @doc-return mixed @DoctorArticle{*} 资讯详情 + */ + public function actionArticleInfo() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + $DoctorArticle = DoctorArticle::findOne(['id' => $get['id'],'is_delete'=>0]); + if (!$DoctorArticle) throw new Exception('资讯不存在'); + return $DoctorArticle; + } +} \ No newline at end of file diff --git a/member/modules/v1/controllers/LeadConsultController.php b/member/modules/v1/controllers/LeadConsultController.php new file mode 100644 index 0000000..321400e --- /dev/null +++ b/member/modules/v1/controllers/LeadConsultController.php @@ -0,0 +1,106 @@ +select('id')->where([ + 'role'=>UserRoleEnum::LEADER, + 'is_delete'=>0, + 'status'=>UserStatusEnum::OK + ])->orderBy('id desc')->column(); + $count=ServiceUser::find()->where([ + 'role'=>UserRoleEnum::LEADER, + 'is_delete'=>0, + 'status'=>UserStatusEnum::OK + ])->count(); + + $ids=ReplayTemplateGroup::find()->where([ + 'in','su_id',$lead_ids, + ])->with(['templates'=>function($t){ + $t->orderBy('sort asc'); + }])->asArray()->all(); + + $cache_key='user_id:'.\Yii::$app->user->identity->getId(); + $cacheData =\Yii::$app->cache->get($cache_key); + + $several=$cacheData?$cacheData-1:$count; + \Yii::$app->cache->set($cache_key,$several); + + if ($several>0){ + return $ids[$several-1]; + }else{ + return ['欢迎进行导医咨询']; + } + } + + /** + * @doc-name 导医聊天创建会话 + * @doc-return int ims_id 会话id + */ + public function actionGetLead() + { + $lead_id=LeadInfo::getLastLeadUserId();//空闲导医 + + $ims = new ImMessageSession(); + $ims->user_id = \Yii::$app->user->identity->id; + $ims->type = 3;//用户导医 + $ims->service_id=$lead_id['id']; + $ims->saveOrFail(); + + $lead= \Yii::$app->db->getLastInsertID(); + return ['ims_id'=>$lead]; + } + + /** + * @doc-name 结束导医会话 + * @doc-param int ims_id 会话id + * @doc-param int service_id 导医id + */ + public function actionOverIms() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + [['ims_id','service_id'],'required'] + ]); + + $Ims=ImMessageSession::find()->where([ + 'id'=>$post['ims_id'], + 'user_id'=>\Yii::$app->user->identity->id, + 'service_id'=>$post['service_id'], + 'type'=>3, + 'status'=>0, + 'is_delete'=>0 + ])->one(); + if (!$Ims) throw new Exception('会话不存在或会话已结束'); + + ImMessageSession::updateAll(['status'=>10],[ + 'id'=>$post['ims_id'], + 'user_id'=>\Yii::$app->user->identity->id, + 'service_id'=>$post['service_id'], + 'is_delete'=>0 + ]); + + return ['会话已结束']; + } + +} \ No newline at end of file diff --git a/member/modules/v1/controllers/MyController.php b/member/modules/v1/controllers/MyController.php new file mode 100644 index 0000000..980a979 --- /dev/null +++ b/member/modules/v1/controllers/MyController.php @@ -0,0 +1,474 @@ +request->post(); + $this->requestValidate($post, [ + ['store_id', 'required'] + ]); + $query = Prescription::find() + ->where([ + 'user_id' => \Yii::$app->user->identity->id, + 'store_id' => $post['store_id'] + ])->orderBy('created_at DESC'); + + if($post['up_id'] > 0){ + $UserPatient = UserPatient::find() + ->where([ + 'user_id' => \Yii::$app->user->identity->id, + 'id' => $post['up_id'] + ]) + ->one(); + + if (!$UserPatient) { + throw new Exception('就诊人不存在'); + } + + $query->andWhere([ + 'up_id' => $post['up_id'] + ]); + } + + $this->field = [ + Prescription::class => [ + 'id', 'prescription_no','prescription_type', 'is_online', 'up_id', 'clinical_diagnose', 'status', + 'created_at' => function ($model) { + return date('Y-m-d H:i:s', $model->created_at); + }, + 'doctor_name' => 'serviceUser.docInfo.name', + 'patient_name' => 'userPatient.name', + 'drug_name' => function ($model) { + $drug = []; + if($model->prescription_type == 1){ + $chineseRepice = ChineseRepice::find() + ->where([ + 'in', 'id', explode(',', $model->cr_ids) + ])->all(); + if($chineseRepice){ + foreach($chineseRepice as $value){ + $content = Json::decode($value['content']); + foreach($content as $v){ + $drug[] = $v['name']; + } + + } + } + }elseif ($model->prescription_type ==2) { + $westRepice = WestRepice::find() + ->where([ + 'in', 'id', explode(',', $model->wr_ids) + ])->all(); + if($westRepice){ + foreach($westRepice as $v){ + $content = Json::decode($v['content']); + $drug[] = $content['drug_name']; + } + } + }else{ + $granulareRepice = GranularRepice::find() + ->where([ + 'in', 'id', explode(',', $model->gr_ids) + ])->all(); + if($granulareRepice){ + foreach($granulareRepice as $value){ + $content = Json::decode($value['content']); + foreach($content as $v){ + $drug[] = $v['name']; + } + } + } + } + return $drug; + } + ] + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 处方详情 + * @doc-param string prescription_no 处方编号 + * @doc-return mixed @List{id-int-处方id,prescription_no-int-处方编号,type-int-类型1普通方2常用方,created_at-int-开具时间,clinical_diagnose-string-临床诊断,category-int-类别1自费2医保,status-int-状态0待审核1已通过2未通过3待使用4已使用5未使用6已失效7已初审,doctor_order-string-医嘱,patient_name-string-患者,sex-int-0默认1男2女,age-int-年龄,depart-string-科室,mobile-string-手机号,doctor_name-string-医生,first_view-string-初审药师,again_view-string-复审药师,patient_name-string-患者,@Rp{@Chinese{content-string-药品有关信息,dosage-int-剂数,useNum-string-用量,usage-int-用法,fufa-string-服法,is_deepfry-int-是否浓煎0否1是,total_price-float-价格},@West{content-string-药品有关信息,number-int-数量,available_days-int-可用天数,total_price-float-价格}}} 处方记录 + */ + public function actionPrescriptionDetail() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['prescription_no', 'required'] + ]); + return (new PrescriptionService())->detail($post['prescription_no']); + } + + /** + * @doc-name 关注医生列表 + * @doc-return mixed @Service{register_price-float-挂号价格,register_status-int-挂号状态0关闭1开启} 医生开通服务信息 + * @doc-return mixed @Hospital{name-string-名称} 医院信息 + * @doc-return mixed @Yard{name-string-名称} 院区信息 + * @doc-return mixed @Depart{name-string-名称} 科室信息 + * @doc-return string accept_percent 接诊率 + * @doc-return string good_comment_percent 好评率 + * @doc-return int inquiry_num 问诊量 + * @doc-return string avg_reply 平均回复时间 + */ + public function actionFollowList() + { + $post = \Yii::$app->request->post(); + + $query = FollowDoctor::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + ]); + + $depart_arr = json_decode(ArrayHelper::getValue($post, 'depart_id', "[]"), true); + $type_arr = json_decode(ArrayHelper::getValue($post, 'type', "[]"), true); + $title_arr = json_decode(ArrayHelper::getValue($post, 'title_id', "[]"), true); + + $query->joinWith(['docInfo' => function ($q) use ($depart_arr, $title_arr) { + $q->alias('i'); + if (!empty($depart_arr)) { + $q->andWhere([ + 'i.depart_id' => $depart_arr + ]); + }; + if (!empty($title_arr)) { + $q->andWhere([ + 'i.title_id' => $title_arr + ]); + } + }]); + + if (!empty($type_arr)) { + $query->joinWith(['docService' => function ($q) use ($type_arr) { + $q->alias('s'); + }]); + } + $query->joinWith(['docIdentity' => function ($q) { + $q->alias('it'); + }]); + + $this->field = [ + FollowDoctor::class => [ + 'id', 'su_id', + 'avator' => 'docIdentity.work_avator', + 'name' => 'docInfo.name', + 'depart' => 'docInfo.depart.name', + 'hospital' => 'docInfo.hospital.name', + 'yard' => 'docInfo.yard.name', + 'title' => 'docInfo.title.name', + 'good_at' => 'docInfo.good_at', + 'accept_percent' => function ($model) { + $accept_num = Order::find()->where([ + 'su_id' => $model->id, + 'is_pay' => 1, + 'accept_status' => [OrderAcceptEnum::ACCEPTING, OrderAcceptEnum::OVER], + ])->count(); + $all_num = Order::find()->where([ + 'su_id' => $model->id, + 'is_pay' => 1, + 'accept_status' => [OrderAcceptEnum::TIMEOUT_ACCEPT, OrderAcceptEnum::REFUSED, OrderAcceptEnum::ACCEPTING, OrderAcceptEnum::OVER], + ])->count(); + return $all_num == 0 ? '100%' : round(($accept_num / $all_num) * 100, 2) . '%'; + }, + 'good_comment_percent' => function ($model) { + return '100%'; + }, + 'inquiry_num' => function ($model) { + $all_num = Order::find()->where([ + 'su_id' => $model->id, + 'is_pay' => 1, + ])->count(); + return $all_num; + }, + 'avg_reply' => function ($model) { + return '1小时内'; + }, + 'service' => 'docService' + ], + DoctorService::class => [ + 'register_status', 'register_price' + ] + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 关注医生 + * @doc-param int su_id 医生id + * @doc-return int status 状态0未关注1已关注 + */ + public function actionAddFollow() + { + + $form = new FollowForm(); + $form->attributes = \Yii::$app->request->post(); + + $form->save(); + return [ + 'status' => 1 + ]; + } + + /** + * @doc-name 取消关注 + * @doc-param int su_id 医生id + */ + public function actionCancelFollow() + { + $form = new FollowForm(); + $form->attributes = \Yii::$app->request->post(); + + $form->cancel(); + } + + /** + * @doc-name 就诊记录 + * @doc-param int up_id 就诊人id + * @doc-return array desc 主诉 + * @doc-return array created_at 时间 + * @doc-return mixed @Diagnosis{content-string-内容} 诊断 + */ + public function actionInquiryRecord() + { + $post = \Yii::$app->request->post(); + $up_id = \Yii::$app->request->post('up_id'); + if (!$up_id) throw new Exception('就诊人up_id不能为空'); + + //患者 + $doctorPatient = DoctorPatient::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + 'up_id' => $post['up_id'] + ])->all(); + + $UserInquiry = UserInquiry::find()->select('id,patient_data')->where([ + 'user_id' => \Yii::$app->user->identity->id, + ])->all(); + if (!$UserInquiry) throw new Exception('暂时还没有就诊记录'); + + foreach ($UserInquiry as $value) { + $val[] = Json::decode($value['patient_data']); + } + + $i = 0; + foreach ($val as $v) { + if ($v['id'] == $post['up_id']) { + $data[] = UserInquiry::find()->select('id,user_id,su_id,desc,created_at')->where([ + 'id' => $UserInquiry[$i]['id'], + 'user_id' => \Yii::$app->user->identity->getId(), + ])->one(); + $i++; + } + } + + foreach ($data as $vv) { + $id[] = Order::find()->select('id')->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'su_id' => $vv['su_id'], + 'ui_id' => $vv['id'], + ])->one(); + } + + foreach ($id as $kk) { + $ImMessageSessionOrder[] = ImMessageSessionOrder::find()->select('ims_id')->where([ + 'order_id' => $kk['id'] + ])->one(); + } + + foreach ($ImMessageSessionOrder as $k) { + $diagnosis[] = ImMessage::find()->select('content')->where([ + 'ims_id' => $k['ims_id'], + 'type' => 1 + ])->orderBy('id desc')->one(); + } + + return [$data,$diagnosis]; + } + + /** + * @doc-name 就诊人就诊记录 + * @doc-param int up_id 就诊人id + * @doc-return mixed @List{up_id-int-患者id,su_id-int-医生id,desc-string-主诉,created_at-int-时间,diagnosis-string-诊断} 诊断 + * @doc-return mixed @Pagination{totalPage-int-总数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionRecord() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['up_id','required'] + ]); + + $query = UserInquiry::find()->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'up_id' => $post['up_id'] + ]); + + $this->field=[ + UserInquiry::class=>[ + 'id','up_id','user_id','su_id','desc','created_at', + 'diagnosis'=>function($m){ + $order=Order::find()->select('id')->where([ + 'ui_id'=>$m->id + ])->column(); + $ims_id= ImMessageSessionOrder::find()->select('ims_id')->where([ + 'order_id' => $order + ])->column(); + + $diagnosis = ImMessage::find()->select('content')->where([ + 'ims_id' => $ims_id, + 'type' => 1 + ])->orderBy('id desc')->one(); + return $diagnosis??'暂未给出诊断'; + } + ] + ]; + return $this->create($query,$post); + + } + /** + * @doc-name 收货地址列表 + * @doc-return mixed @Address{*} 就诊信息 + */ + public function actionAddressList() + { + $list = Address::find()->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0 + ])->all(); + if (!$list) throw new Exception('暂无收货地址'); + + $is_default = Address::find()->select('is_default')->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0 + ])->column(); + + if (!in_array(1,$is_default)){ + $id = Address::find()->select('id')->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0 + ])->orderBy('id asc')->one(); + + Address::updateAll(['is_default'=>1],[ + 'user_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0, + 'id'=>$id + ]); + } + + return $list; + } + + /** + * @doc-name 新增收货地址 + * @doc-param string name 姓名 + * @doc-param string mobile 姓名 + * @doc-param string region 地区 + * @doc-param string detail_address 详细地址 + */ + public function actionSaveAddress() + { + $post = \Yii::$app->request->post(); + + $addressForm = new AddressForm(); + $addressForm->attributes = $post; + + $addressForm->save(); + } + + /** + * @doc-name 修改收货地址 + * @doc-param int id 地址id + * @doc-param string name 姓名 + * @doc-param string mobile 姓名 + * @doc-param string region 地区 + * @doc-param string detail_address 详细地址 + */ + public function actionEditAddress() + { + $post = \Yii::$app->request->post(); + + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $addressForm = new AddressForm(); + $addressForm->attributes = $post; + + $addressForm->edit($post); + } + + /** + * @doc-name 修改默认地址 + * @doc-param int id 地址id + */ + public function actionUpdateDefault() + { + $post = \Yii::$app->request->post(); + + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $addressForm = new AddressForm(); + $addressForm->attributes = $post; + + $addressForm->UpdateDefault($post); + } + + /** + * @doc-name 删除收货地址 + * @doc-param int id 地址id + */ + public function actionDelAddress() + { + $post = \Yii::$app->request->post(); + + $this->requestValidate($post, [ + ['id', 'required'] + ]); + $addressForm = new AddressForm(); + $addressForm->attributes = $post; + + $addressForm->del($post); + return ['删除成功']; + } + + /** + * 挂号记录 + */ + public function actionRegister() + { + + } +} diff --git a/member/modules/v1/controllers/OrderController.php b/member/modules/v1/controllers/OrderController.php new file mode 100644 index 0000000..988579d --- /dev/null +++ b/member/modules/v1/controllers/OrderController.php @@ -0,0 +1,211 @@ +attributes = \Yii::$app->request->post(); + return $form->saves(); + } + + /** + * @doc-name 订单列表 + * @doc-param int status 0全部1待支付2待接诊3咨询中4待评价 + * @doc-param int page 页码 1 optional + * @doc-param int page_size 每页条数 20 optional + * @doc-return mixde @List{Order{id,doctor_avator-string-医生头像,doctor_name-string-医生姓名,doctor_depart-string-医生科室,desc-string-问诊病情,created_at,type,@Order_status{status-int-状态1待支付2待接诊3咨询中4待评价5已完成6已取消,text-string-文字表示}}} 订单列表 + * @doc-return mixed @Pagination{total_count-int-总数量,page_count-int-总页数,current_page-int-当前页,per_page-int-每页条数} 分页数据 + */ + public function actionList() + { + $post = \Yii::$app->request->post(); + + $query = Order::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + ])->with('serviceUser','serviceUser.docInfo','serviceUser.docIdentity','serviceUser.docInfo.depart','inquiry')->orderBy('id desc'); + + $status = ArrayHelper::getValue($post,'status',0); + switch($status){ + case OrderStatusEnum::WAIT_PAY: //待支付 + $query->andWhere([ + 'is_pay' => 0, + 'cancel_status' => 0 + ]); + break; + case OrderStatusEnum::WAIT_ACCEPT: //待接诊 + $query->andWhere([ + 'is_pay' => 1, + 'cancel_status' => 0, + 'accept_status' => OrderStatusEnum::WAIT_ACCEPT, + ]); + break; + case OrderStatusEnum::ACCEPTING: //咨询中 + $query->andWhere([ + 'is_pay' => 1, + 'cancel_status' => 0, + 'accept_status' => OrderStatusEnum::ACCEPTING, + ]); + break; + case OrderStatusEnum::WAIT_COMMENT: //待评价 + $query->andWhere([ + 'is_pay' => 1, + 'cancel_status' => 0, + 'accept_status' => OrderStatusEnum::ACCEPTING, + 'is_comment' => 0 + ]); + break; + } + + $this->field = [ + Order::class => [ + 'id', + 'doctor_avator' => 'serviceUser.docIdentity.work_avator', + 'doctor_name' => 'serviceUser.docInfo.name', + 'doctor_depart' => 'serviceUser.docInfo.depart.name', + 'desc' => function($model){ + if($model->type==1){ + return $model->inquiry->desc; + }else{ + return null; + } + }, + 'created_at', + 'type', + 'order_status' => function($model){ + return Order::status_info($model); + } + ], + ]; + + return $this->create($query,$post); + } + + /** + * @doc-name 订单详情 + * @doc-param int order_id 订单id + * @doc-return mixed Order{id,su_id,up_id-int-患者id,type,order_no,total_pay_price,is_pay,pay_time,pay_type,cancel_status,cancel_time,auto_cancel_time,auto_refund_time,auto_over_time,accept_status,accept_time,over_time,created_at,cancel_remark,@Order_status{status-int-状态1待支付2待接诊3咨询中4待评价5已完成6已取消,text-string-文字表示},ims_id-int-消息会话id,@ServiceUser{avator-string-头像,name-string-名称,depart-string-科室,hospital-string-医院,yard-string-院区},@Inquiry{UserInquiry{desc,images,is_visit,visit_desc},@Patient_data{name-string-姓名,age-int-年龄,sex-int-1男2女}}} 订单详情 + */ + public function actionInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $info = Order::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + 'id' => $post['order_id'], + ])->with('serviceUser','serviceUser.docInfo','serviceUser.docIdentity','serviceUser.docInfo.depart','serviceUser.docInfo.hospital','inquiry','session')->one(); + if(!$info){ + throw new Exception('订单不存在'); + } + + return ArrayHelper::toArray($info,[ + Order::class => [ + 'id','su_id','up_id','type','order_no','total_pay_price','is_pay','pay_time','pay_type','cancel_status','cancel_time','auto_cancel_time','auto_refund_time','auto_over_time','accept_status','accept_time','over_time','created_at','cancel_remark','order_status'=>function($model){ + return Order::status_info($model); + }, + 'ims_id' => 'session.ims_id', + 'serviceUser','inquiry' + ], + ServiceUser::class => [ + 'avator' => 'docIdentity.work_avator', + 'name' => 'docInfo.name', + 'depart' => 'docInfo.depart.name', + 'hospital' => 'docInfo.hospital.name', + 'yard' => 'docInfo.yard.name', + 'title' => 'docInfo.title.name', + ], + UserInquiry::class => [ + 'desc','images','is_visit','visit_desc', + 'patient_data' => function($model){ + $patient_data = json_decode($model->patient_data,true); + return [ + 'name' => $patient_data['name'], + 'age' => FuncHelper::getAgeFromIdNo($patient_data['id_card']), + 'sex' => $patient_data['sex'], + ]; + }, + ] + ]); + } + + /** + * @doc-name 获取支付配置 + * @doc-param int order_id 订单id + * @doc-return int is_paid 1已支付0未支付 + * @doc-return int order_id 订单id + * @doc-return array config 支付配置参数,在is_paid=0时返回 + */ + public function actionPay() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $form = new OrderSubmitResultForm(); + return $form->getPayData($post['order_id']); + } + + /** + * @doc-name 取消订单 + * @doc-param int order_id 订单id + */ + public function actionCancel() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $form = new \common\forms\OrderRefundForm(); + return $form->refund($post['order_id']); + } + + /** + * 去评价 + */ + public function actionComment() + { + + } + + +} \ No newline at end of file diff --git a/member/modules/v1/controllers/OrderVideoController.php b/member/modules/v1/controllers/OrderVideoController.php new file mode 100644 index 0000000..89a11cb --- /dev/null +++ b/member/modules/v1/controllers/OrderVideoController.php @@ -0,0 +1,175 @@ +params['tencent_video']; + $api = new \Tencent\TLSSigAPIv2($config['appid'], $config['secret']); + $user_id = 'member_' . \Yii::$app->user->identity->getId(); + $key = $api->genUserSig($user_id); + + return [ + 'appid' => $config['appid'], + 'key' => $key, + 'user_id' => $user_id, + ]; + } + + /** + * @doc-name 视频基础信息 + * @doc-param int order_id 订单id + * @doc-return int is_limit 0不限制1限制 + * @doc-return int left_minutes 剩余分钟数 + */ + public function actionVideoInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + /* @var Order $order */ + $order = Order::find()->where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->id,//id 53 + ])->with('video')->one(); + if (!$order || !$order['video']) { + throw new Exception('订单不存在'); + } + if ($order->accept_status != OrderAcceptEnum::ACCEPTING) { + throw new Exception('订单状态非接诊中'); + } + if ($order->type != 2) { + throw new Exception('您的订单非视频问诊订单'); + } + /* @var OrderVideoInfo $video */ + $video = $order['video']; + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + } + + /** + * @doc-name 视频通话处理 + * @doc-param int order_id 订单id + * @doc-param string type 类型start开始视频sign上报扣除end结束视频 + * @doc-return int is_limit 0不限制1限制 + * @doc-return int left_minutes 剩余分钟数 + */ + public function actionVideoSign() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'], + ['type', 'required'], + ]); + /* @var Order $order */ + $order = Order::find()->where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->id, + ])->with('video')->one(); + if (!$order || !$order['video']) { + throw new Exception('订单不存在'); + } + if ($order->accept_status != OrderAcceptEnum::ACCEPTING) { + throw new Exception('订单状态非接诊中'); + } + if ($order->type != 2) { + throw new Exception('您的订单非视频问诊订单'); + } + + /* @var OrderVideoInfo $video */ + $video = $order['video']; + if ($video->is_limit == 0) { + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + } + switch ($post['type']) { + // 开始视频 + case 'start': + if ($video->left_minutes <= 0) { + throw new Exception('通话时长不足'); + } + $now = Carbon::now()->toDateTimeString(); + if (!$video->start_at) { + $video->start_at = $now; + } + $video->last_start_left_minutes = $video->left_minutes; + $video->last_start_at = $now; + + $info = $video->info ? json_decode($video->info, true) : []; + $info[] = [ + 'time' => $now, + 'desc' => '开始视频通话', + 'left_minutes' => $video->left_minutes, + ]; + $video->info = json_encode($info); + $video->save(); + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + break; + // 上报扣除 + case 'sign': + if ($video->left_minutes <= 0) { + throw new Exception('通话时长不足'); + } + $now = Carbon::now()->toDateTimeString(); + $video->start_at = $now; + $left_minutes = $video->last_start_left_minutes - Carbon::now()->diffInRealMinutes($video->last_start_at); + $video->left_minutes = max($left_minutes, 0); + $video->last_limit_at = $now; + + $info = $video->info ? json_decode($video->info, true) : []; + $info[] = [ + 'time' => $now, + 'desc' => '扣除时长', + 'left_minutes' => $video->left_minutes, + ]; + $video->info = json_encode($info); + $video->save(); + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + break; + // 结束视频 + case 'end': + $now = Carbon::now()->toDateTimeString(); + $video->end_at = $now; + $left_minutes = $video->last_start_left_minutes - Carbon::now()->diffInRealMinutes($video->last_start_at); + $video->left_minutes = max($left_minutes, 0); + + $info = $video->info ? json_decode($video->info, true) : []; + $info[] = [ + 'time' => $now, + 'desc' => '结束视频通话', + 'left_minutes' => $video->left_minutes, + ]; + $video->info = json_encode($info); + $video->save(); + return ['通话已结束']; + break; + } + } +} \ No newline at end of file diff --git a/member/modules/v1/controllers/OtherController.php b/member/modules/v1/controllers/OtherController.php new file mode 100644 index 0000000..1280fb4 --- /dev/null +++ b/member/modules/v1/controllers/OtherController.php @@ -0,0 +1,115 @@ +request->post(); + + $BaseConfig=BaseConfig::find()->where([ + 'type'=>2, + 'end'=>1, + 'status'=>0 + ])->one(); + if (!$BaseConfig) throw new Exception('不存在有关信息'); + + return $BaseConfig; + } + + /** + * @doc-name 客服热线 + * @doc-return string text 标题 + * @doc-return string msg 电话 + */ + function actionServiceLine() + { + $post=\Yii::$app->request->post(); + + $this->requestValidate($post,[ + [ 'store_id','required'] + ]); + switch ($post['store_id']){ + case 11001: + return [ + 'text'=>'客服热线', + 'msg'=>'13429684168' + ]; + + + default: + return [ + 'text'=>'客服热线', + 'msg'=>'13429684168' + ]; + } + + } + + /** + * @doc-name 服务协议或隐私政策或挂号须知 + * @doc-param int type 类型1服务协议2隐私政策3挂号须知4知情同意书 + * @doc-return mixed @BaseConfig{*} 信息 + */ + public function actionService() + { + $get=\Yii::$app->request->get(); + $this->requestValidate($get, [ + ['type', 'required','message'=>'类型不能为空'] + ]); + $BaseConfig=BaseConfig::find()->where([ + 'type'=>$get['type'], + 'end'=>1, + 'status'=>0 + ])->one(); + if (!$BaseConfig) throw new Exception('不存在有关信息'); + + return $BaseConfig; + } + + /** + * 关于我们 + */ + public function actionAboutUs() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['store_id', 'required'] + ]); + $BaseConfig = BaseConfig::find()->where([ + 'store_id' => $post['store_id'], + 'type' => 1, + 'end' => 1, + ])->andWhere(['like','desc','关于我们'])->one(); + if (!$BaseConfig) throw new Exception('不存在有关信息'); + + return $BaseConfig; + } + + + /** + * 查询小程序版本 + */ + public function actionXcxVersion(){ + $systemConfig=SystemConfig::find()->select('value')->where([ + 'config_type'=>3, + ])->one(); + return $systemConfig; + } + +} \ No newline at end of file diff --git a/member/modules/v1/controllers/PatientController.php b/member/modules/v1/controllers/PatientController.php new file mode 100644 index 0000000..aeb5781 --- /dev/null +++ b/member/modules/v1/controllers/PatientController.php @@ -0,0 +1,186 @@ +where([ + 'user_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->orderBy('id desc')->all(); + return $all; + } + + /** + * @doc-name 就诊人保存 + * @doc-param int id 存在则编辑信息 / optional + * @doc-param int name 姓名 + * @doc-param string id_card 患者身份证 + * @doc-param int age 年龄 + * @doc-param int sex 性别,1男2女 + * @doc-param int relation 关系,通过关系接口获取 + * @doc-param string mobile 患者手机号 + * @doc-param int is_default 是否默认 0 optional + * @doc-param int family_status 家庭遗传史0无1有 0 optional + * @doc-param string family_history 家庭遗传史选项,选项添加不用保存后台,["选项1","选项2"] [] optional + * @doc-param int allergic_status 过敏史0无1有 0 optional + * @doc-param string allergic_history 过敏史选项,选项添加不用保存后台,["选项1","选项2"] [] optional + * @doc-param int person_status 既往史0无1有 0 optional + * @doc-param string person_history 既往史选项,选项添加不用保存后台,["选项1","选项2"] [] optional + * @doc-param int liver_function 肝功能0正常1异常 0 optional + * @doc-param string liver_index 肝功能异常指标 0 optional + * @doc-param int renal_function 肾功能0正常1异常 0 optional + * @doc-param string renal_index 肾功能异常指标 0 optional + */ + public function actionSave() + { + $form = new PatientForm(); + $form->attributes = \Yii::$app->request->post(); + return $form->save(); + } + + /** + * @doc-name 切换默认接诊人 + * @doc-param int up_id 就诊人id + */ + public function actionChangePatient() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['up_id','required'] + ]); + $form = new PatientForm(); + $form->attributes = $post; + + return $form->change(); + } + /** + * @doc-name 就诊人关系 + * @doc-return int key 建 + * @doc-return int value 值 + */ + public function actionRelation() + { + return [ + ['key'=> 0,'text'=>'本人'], + ['key'=> 1,'text'=>'丈夫'], + ['key'=> 2,'text'=>'妻子'], + ['key'=> 3,'text'=>'爸爸'], + ['key'=> 4,'text'=>'妈妈'], + ['key'=> 5,'text'=>'儿子'], + ['key'=> 6,'text'=>'女儿'], + ['key'=> 7,'text'=>'其他'], + ]; + } + + /** + * @doc-name 就诊人详情 + * @doc-param int id 就诊人id + * @doc-return mixed UserPatient{*,age-int-年龄} 就诊人详情 + */ + public function actionInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $patient = UserPatient::find()->where([ + 'id' => $post['id'], + 'user_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0, + ])->one(); + if(!$patient){ + throw new Exception('就诊人不存在'); + } + return ArrayHelper::toArray($patient,[ + UserPatient::class => [ + 'id','name','id_card','sex','relation','mobile','is_default', + 'avatar'=>function($model){ + if (empty($model->avatar)){ + return 'https://hbimg.huabanimg.com/2dbbc9177be8b9912b2a0d881200dd47ccb84d92710aa-IepOs1_fw658'; + } + return $model->avatar; + }, + 'age' => function($model){ + return FuncHelper::getAgeFromIdNo($model->id_card); + }, + ] + ]); + } + + /** + * @doc-name 编辑就诊人信息 + * @doc-param int up_id 就诊人id + * @doc-param string avatar 头像 + */ + public function actionEditPatient() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['up_id','required'], + ['avatar','required'] + ]); + + $userPatient=UserPatient::find()->where([ + 'id'=>$post['up_id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + ])->one(); + if (!$userPatient) throw new \yii\db\Exception('就诊人不存在'); + + UserPatient::updateAll([ + 'avatar'=>$post['avatar'], + ], + ['id'=>$post['up_id'],'user_id'=>\Yii::$app->user->identity->getId()]); + return ['编辑成功']; + } + /** + * @doc-name 删除就诊人 + * @doc-param int id 就诊人id + */ + public function actionDel() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'], + ]); + + $PatientForm=new PatientForm(); + $PatientForm->attributes=$post; + return $PatientForm->del(); + } + + /** + * @doc-name 查看基本健康信息 + * @doc-param int user_patient_id 就诊人id + * @doc-return mixed @UserPatientHealthInquiry{*} 健康信息 + */ + public function actionHealthInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['user_patient_id','required'], + ]); + $HealthForm=new HealthForm(); + $HealthForm->attributes=$post; + + return $HealthForm->info(); + } +} \ No newline at end of file diff --git a/member/modules/v1/controllers/PhysicalController.php b/member/modules/v1/controllers/PhysicalController.php new file mode 100644 index 0000000..0951022 --- /dev/null +++ b/member/modules/v1/controllers/PhysicalController.php @@ -0,0 +1,128 @@ +attributes = Yii::$app->request->post(); + try { + $list = $form->getPhysicalPackageList(); + } catch (Exception $e) { + return $e->getMessage(); + } + $this->field = $list['field']; + + return $list['data']; + } + + /** + * @doc-name 体检套餐详情 + * @doc-desc 体检套餐数据接口 + * @doc-author liwei + * @doc-param int id 套餐id + * @doc-param int yard_id 分院id 0 optional + * @doc-return mixed {image-string-图片} + * @doc-return mixed {sale-int-销量} + * @doc-return mixed {price-float-价格} + * @doc-return mixed {name-string-套餐名称} + * @doc-return mixed {intro-string-描述} + * @doc-return mixed {content-html-项目详情} + * @doc-return mixed {service-html-服务须知} + * @doc-return mixed @YardPhysical{yard_id-int-分院id,physical_id-int-套餐id} 分院关系 + * @doc-return mixed @Yard{name-string-分院名,position-string-分院地址,hospital_id-int-总院id} 分院信息 + * @doc-return mixed @Reserve{day-int-日期对应的剩余预约数} 预约数据 + */ + public function actionPackageDetail(): array + { + $post = Yii::$app->request->post(); + $this->requestValidate($post,[ + [['id'],'required'] + ]); + + $form = new PhysicalForm(); + $form->attributes = $post; + + return $form->getPhysicalPackage(); + } + + /** + * @doc-name 体检预约 + * @doc-desc 体检预约接口 + * @doc-author liwei + * @doc-param int yard_id 分院id + * @doc-param int physical_id 套餐id + * @doc-param int day 预约时间(天) + * @doc-param int way 获取报告方式 0 optional + * @doc-return mixed {success-int-是否成功} + * @doc-return mixed {msg-string-预约信息} + */ + public function actionReserve(): array + { + $post = Yii::$app->request->post(); + $this->requestValidate($post,[ + [['yard_id','physical_id','day'],'required'] + ]); + + $form = new PhysicalForm(); + $form->attributes = $post; + + return $form->setPhysicalReserve(); + } + + /** + * @doc-name 挂号详情 + * @doc-desc 挂号详情接口 + * @doc-author liwei + * @doc-param int id 预约id + * @doc-return mixed {user_id-int-用户id} + * @doc-return mixed {yard_id-int-分院id} + * @doc-return mixed {physical_id-int-体检套餐id} + * @doc-return mixed {id-int-预约id} + * @doc-return mixed {day-string-预约时间} + * @doc-return mixed {status-int-预约状态0预约中(待支付)1预约成功(已支付)2预约取消} + * @doc-return mixed {way-int-获取报告方式0电子报告} + * @doc-return mixed {intro-string-描述} + * @doc-return mixed @Yard{name-string-分院名,position-string-分院地址,hospital_id-int-总院id} 分院信息 + * @doc-return mixed @User{mobile-string-用户手机号码,nickname-string-用户昵称,idcard-string-身份证} 用户数据 + * @doc-return mixed @Package{name-string-套餐名称,image-string-套餐图片,price-float-套餐价格,intro-string-套餐介绍,content-html-项目详情,service-string-项目须知,type-int-类型,sale-int-销量} 体检套餐数据 + */ + public function actionReserveDetail(): array + { + $post = Yii::$app->request->post(); + $this->requestValidate($post,[ + [['id'],'required'] + ]); + + $form = new PhysicalForm(); + $form->attributes = $post; + + return $form->getReserveDetail(); + } +} diff --git a/member/modules/v1/controllers/PrescripOrderController.php b/member/modules/v1/controllers/PrescripOrderController.php new file mode 100644 index 0000000..ef1ad44 --- /dev/null +++ b/member/modules/v1/controllers/PrescripOrderController.php @@ -0,0 +1,63 @@ +request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $form = new PrescripOrderSubmitForm(); + return $form->getPayData($post['order_id']); + } + + /** + *@doc-name 处方退款 + *@doc-param int order_id 订单id + */ + public function actionCancel() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $form= new PrescripRefundForm(); + return $form->refund($post['order_id']); + } + + /** + * @doc-name 中药的使用煎熬方式 + * @doc-return mixed @drug-use-way{*} + */ + public function actionUseWay() + { + return DrugUseWay::find()->all(); + } + +} diff --git a/member/modules/v1/controllers/ProductOrderController.php b/member/modules/v1/controllers/ProductOrderController.php new file mode 100644 index 0000000..28bfb88 --- /dev/null +++ b/member/modules/v1/controllers/ProductOrderController.php @@ -0,0 +1,554 @@ +request->post(); + + $ProductOrder = ProductOrder::find()->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'] ?? 11001 + ])->orderBy('created_at DESC'); + + switch ($post['type']) { + case 'unpaid'://未支付 + $ProductOrder->andWhere([ + 'status' => ProductOrderEnum::UNPAY + ])->all(); + break; + + case 'wait_send'://待发货 + $ProductOrder->andWhere([ + 'status' => ProductOrderEnum::WAIT_SEND + ])->all(); + break; + + case 'wait_accept'://待收货 + $ProductOrder->andWhere([ + 'status' => ProductOrderEnum::WAIT_ACCEPT + ])->all(); + break; + + case 'finished'://已完成(已取消、已收货、已退款、待评价) + $ProductOrder->andWhere([ + 'in','status',[ProductOrderEnum::CANCEL, ProductOrderEnum::ACCEPTED, ProductOrderEnum::CONFIRM,ProductOrderEnum::REFUND, ProductOrderEnum::WAIT_COMMENT] + ])->all(); + break; + + default: + break; + } + + $this->field = [ + ProductOrder::class => [ + 'id','order_no', 'items_price','trans_expenses','decoct_price','process_price','treatement_price','total_pay_price','prescription_type', 'p_id','is_pay', 'status', 'cancel_status', 'refund_status', + 'cancel_status_text' => function ($q){ + return ProductOrderEnum::CANCEL_STATUS_TEXT[$q->cancel_status]; + }, + 'refund_status_text' => function ($q){ + return ProductOrderEnum::REFUND_STATUS_TEXT[$q->refund_status]; + }, + 'status_text' => function ($q) { + return ProductOrderEnum::STATUS_TEXT[$q->status]; + }, + 'number' => function ($q) { + return ProductOrderItems::find()->where(['product_order_id' => $q->id])->count(); + }, + 'items' => function ($q) { + return ProductOrderItems::find()->where(['product_order_id' => $q->id])->with([ + 'drug' => function($q){ + $q->select('function,specification'); + } + ])->asArray()->all(); + }, + 'store' => function ($q) { + return Store::find()->select('id,name')->where(['id' => $q->store_id])->one(); + }, + 'forbiddenRefund' => 1 + // 'forbiddenRefund'=>function($fund){ + // $config = \Yii::$app->params; + // $orderForbiddenRefundTime = isset($config['product_order']['forbidden_refund_time']) ? $config['product_order']['forbidden_refund_time'] :3600*24*7; + + // if ($fund->prescription_type==1 || $fund->prescription_type==3){ + // return 1;////禁止退款 + // }else{ + // if (time()-$fund->pay_time<=$orderForbiddenRefundTime){ + // return 0;//可以退款 + // }else{ + // return 1;//禁止退款 + // } + // } + // } + ] + ]; + + return $this->create($ProductOrder, $post); + } + + //根据互医的订单编号获取萧康的订单id + public function actionOnlineToLocal(){ + $param = \Yii::$app->request->get(); + $this->requestValidate($param, [ + [['order_no'], 'required'] + ]); + $productOrder = ProductOrder::find()->where([ + 'sync_order_no' => $param['order_no'], + 'user_id' => \Yii::$app->user->identity->getId() + ])->one(); + if(!$productOrder){ + throw new Exception('订单生成中,请稍后'); + } + return ['order_id' => $productOrder->id]; + } + + + /*** + * 预约购药 + */ + public function actionAppointMedicine() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['prescription_id', 'required'] + ]); + $ProductOrder = ProductOrder::find()->select('id,order_no,su_id,p_id,user_id,is_pay,prescription_type,address_id,address,decoct_price,items_price,process_price,treatement_price,total_pay_price,pay_method,trans_expenses,created_at,cancel_status,refund_status,status')->where([ + 'p_id' => $post['prescription_id'], + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'] + ])->asArray()->one(); + if(!$ProductOrder){ + throw new Exception('订单不存在'); + } + $ProductOrder['created_at'] = date('Y-m-d H:i:s', $ProductOrder['created_at']); + $forbiddenRefund = 0; + $config = \Yii::$app->params; + $orderForbiddenRefundTime = isset($config['product_order']['forbidden_refund_time']) ? $config['product_order']['forbidden_refund_time'] : 24*3600*30; + if(time() >= $orderForbiddenRefundTime + $ProductOrder['received_time']){ + $forbiddenRefund = 1; + } + $ProductOrder['forbidden_refund'] = $forbiddenRefund; + + $userInfo = User::find()->select('id,nickname,avatarurl')->where([ + 'id' => $ProductOrder['user_id'] + ])->asArray()->one(); + + $hospital = DoctorInfo::find()->select('hospital_id')->where([ + 'su_id' => $ProductOrder['su_id'] + ])->with(['hospital' => function ($h) { + $h->select('name'); + }])->asArray()->one(); + + $prescription = Prescription::find()->select('cr_ids,wr_ids,gr_ids')->where(['id' => $ProductOrder['p_id']])->one(); + + if($prescription['wr_ids']){ + $wr_ids = explode(',', $prescription['wr_ids']); + $west = WestRepice::find()->select('content,number,total_price')->where([ + 'in', 'id', $wr_ids + ])->all(); + foreach ($west as $value) { + $value['content']=Json::decode($value['content']); + } + $count = count($west); + }else if($prescription['cr_ids']){ + $cr_ids = explode(',', $prescription['cr_ids']); + $chinese = ChineseRepice::find()->select('content,total_price')->where([ + 'in', 'id', $cr_ids + ])->all(); + foreach ($chinese as $val) { + $content = Json::decode($val['content']); + foreach ($content as $v){ + $chinese['list'][]= $v; + } + } + $count = count($chinese['list']); + }else{ + $gr_ids = explode(',', $prescription['gr_ids']); + $granular = GranularRepice::find()->select('content,total_price')->where([ + 'in', 'id', $gr_ids + ])->all(); + foreach ($granular as $val) { + $content = Json::decode($val['content']); + foreach ($content as $v){ + $granular['list'][]= $v; + } + } + $count = count($granular['list']); + } + + $ProductOrder['count'] = $count; + return [ + 'ProductOrder' => $ProductOrder, + 'userInfo' => $userInfo, + 'hospital' => $hospital, + 'west' => $west ?? null, + 'chinese' => $chinese ?? null, + 'granular' => $granular ?? null, + ]; + } + + /** + * 代煎服务费用信息 + */ + public function actionDecoctService(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $ProductOrder = ProductOrder::find()->select('dosage,prescription_type')->where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'], + 'status' => 0, + 'cancel_status' => 0 + ])->asArray()->one(); + if(!$ProductOrder){ + throw new Exception('订单信息错误'); + } + + if($ProductOrder['dosage'] == 0){ + throw new Exception('只有中药和颗粒药订单提供代煎服务'); + } + + $systemConfig = SystemConfig::find()->where(['type' => $ProductOrder['prescription_type']])->one(); + return [ + 'decoct_price' => $systemConfig->value, + 'dosage' => $ProductOrder['dosage'], + 'total_decoct_price' => round($ProductOrder['dosage'] * $systemConfig->value, 2) + ]; + } + + + /** + * 更新代煎服务费用 + */ + public function actionUpdateDecoctService(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $ProductOrder = ProductOrder::find()->where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'], + 'status' => 0, + 'cancel_status' => 0 + ])->one(); + if(!$ProductOrder){ + throw new Exception('订单信息错误'); + } + if($ProductOrder['prescription_type'] == 2){ + throw new Exception('只有中药和颗粒药订单提供代煎服务'); + } + + if($post['is_decoct'] ){ // 代煎 + if(!$ProductOrder->is_decoct){ + $systemConfig = SystemConfig::find()->where(['type' => $ProductOrder->prescription_type])->one(); + //根据剂数计算代煎费用 + $dosage = $ProductOrder->dosage; + $decoctPrice = $dosage * $systemConfig->value; + $ProductOrder->is_decoct = 1; + $ProductOrder->decoct_price = $decoctPrice; + $ProductOrder->total_pay_price = $ProductOrder->total_pay_price + $decoctPrice; + $ProductOrder->saveOrFail(); + } + } else { + if($ProductOrder->is_decoct && $ProductOrder->decoct_price > 0){ + $ProductOrder->is_decoct = 0; + $ProductOrder->total_pay_price = $ProductOrder->total_pay_price - $ProductOrder->decoct_price; + $ProductOrder->decoct_price = 0; + $ProductOrder->saveOrFail(); + } + } + + return ['success']; + } + + /** + * 更新订单收货地址 + */ + public function actionUpdateDelivery(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['order_id', 'delivery_method'], 'required'], + [['address_id'], 'integer'] + ]); + $ProductOrder = ProductOrder::find()->where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'], + 'status' => 0, + 'cancel_status' => 0 + ])->one(); + if (!$ProductOrder) throw new Exception('产品订单不存在'); + if(!$post['delivery_method']){ // 快递配送 + if(!$post['address_id']){ + throw new Exception('请选择收货地址'); + } + $address = Address::find()->select(['id','name','mobile','province','region','detail_address'])->where([ + 'id' => $post['address_id'], + 'user_id' => \Yii::$app->user->identity->getId() + ])->asArray()->one(); + if (!$address) throw new Exception('收货地址不存在'); + $ProductOrder->address_id = $address['id']; + $ProductOrder->address = json_encode($address); + $ProductOrder->express_name = $address['name']; + $ProductOrder->express_mobile = $address['mobile']; + $ProductOrder->express_region = $address['region']; + $ProductOrder->express_address = $address['detail_address']; + + if(!$ProductOrder->is_free_shipping) { + $region = Region::find()->where(['name' => $address['province']])->one(); + $ProductOrder->total_pay_price = $ProductOrder->total_pay_price - $ProductOrder->trans_expenses + $region->express_fee; + $ProductOrder->trans_expenses = $region->express_fee; + } + $ProductOrder->delivery_method = 0; + + $ProductOrder->saveOrFail(); + + } else { //门店自提 + if(!$ProductOrder->delivery_method){ + $ProductOrder->address_id = 0; + $ProductOrder->address = ''; + $ProductOrder->express_name = ''; + $ProductOrder->express_mobile = ''; + $ProductOrder->express_region = ''; + $ProductOrder->express_address = ''; + $ProductOrder->delivery_method = 1; + $ProductOrder->total_pay_price = $ProductOrder->total_pay_price - $ProductOrder->trans_expenses; + $ProductOrder->trans_expenses = 0; + $ProductOrder->saveOrFail(); + } + } + return ['success']; + } + + /** + * @doc-name 订单信息 + * @doc-param int order_id 订单id + * @doc-return mixed @UserInfo{avatarurl-string-头像,@Address{name-string-名字,mobile-string-手机号码,region-string-地区,detail_address-string-详细地址}} 用户信息 + * @doc-return mixed @Hospital{hospital_id-int-id,@Hospital{name-string-名字}} 医院信息 + * @doc-return mixed @ProductOrder{order_no-string-订单编号,total_pay_price-float-实付金额,pay_method-int-支付方式1线上2线下,trans_expenses-float-运费,created_at-int-下单时间,status-int-产品订单状态0未支付1待发货2待收货3待评价4已退款5退款中6已收货7确认收货,is_pay-int-是否支付0否1是} 产品订单信息 + * @doc-return mixed @Chinese{content-string-信息,total_price-float-单价} 药品信息 + * @doc-return mixed @West{content-string-信息,number-int-数量,total_price-float-单价} 药品信息 + */ + public function actionInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $ProductOrder = ProductOrder::find()->select('id,is_online,order_no,delivery_method,su_id,p_id,user_id,is_pay,prescription_type,address_id,address,decoct_price,items_price,process_price,treatement_price,total_pay_price,pay_method,trans_expenses,created_at,cancel_status,refund_status,status,pay_time')->where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'] + ])->asArray()->one(); + + $ProductOrder['created_at'] = date('Y-m-d H:i:s', $ProductOrder['created_at']); + + $forbiddenRefund = 1; + $config = \Yii::$app->params; + $orderForbiddenRefundTime = isset($config['product_order']['forbidden_refund_time']) ? $config['product_order']['forbidden_refund_time'] :3600*24*7; + + if ($ProductOrder['prescription_type']==2 || $ProductOrder['prescription_type']==4){ + if (time()-$ProductOrder['pay_time']<=$orderForbiddenRefundTime){ + $ProductOrder['forbidden_refund'] = 0;//可以退款 + }else{ + $ProductOrder['forbidden_refund']=$forbiddenRefund;//禁止退款 + } + }else{ + $ProductOrder['forbidden_refund'] = $forbiddenRefund;//禁止退款 + } + + $userInfo = User::find()->select('id,nickname,avatarurl')->where([ + 'id' => $ProductOrder['user_id'] + ])->asArray()->one(); + + $hospital = DoctorInfo::find()->select('hospital_id')->where([ + 'su_id' => $ProductOrder['su_id'] + ])->with(['hospital' => function ($h) { + $h->select('name'); + }])->asArray()->one(); + $ProductOrderItems = ProductOrderItems::find()->where(['product_order_id' => $ProductOrder['id']])->with(['drug' => function($q){ + $q->select('id,drug_name,function,specification,usage'); + }])->asArray()->all(); + $ProductOrder['count'] = count($ProductOrderItems); + return [ + 'ProductOrder' => $ProductOrder, + 'userInfo' => $userInfo, + 'hospital' => $hospital, + 'ProductOrderItems' => $ProductOrderItems + ]; + + } + + + /** + * @doc-name 支付产品订单 + * @doc-param int order_id 订单id + * @doc-return int is_paid 1已支付0未支付 + * @doc-return int order_id 订单id + * @doc-return array config 支付配置参数,在is_paid=0时返回 + */ + public function actionPay() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $form = new ProductOrderSubmitForm(); + return $form->getPayData($post); + } + + /** + * @doc-name 产品订单确认收货 + * @doc-param int order_id 订单id + */ + public function actionReceive() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $ProductOrder = ProductOrder::find()->where(['id' => $post['order_id'],'user_id' => \Yii::$app->user->identity->getId()])->one(); + if($ProductOrder->status != ProductOrderEnum::WAIT_ACCEPT){ + throw new Exception('订单状态错误'); + } + $ProductOrder->status = ProductOrderEnum::CONFIRM; + $ProductOrder->received_time = time(); + $ProductOrder->save(); + + if($ProductOrder->is_online){ //平台订单状态同步 + \Yii::$app->queue->delay(0)->push(new ProductOrderSyncPlatformJob([ + 'orderId' => $this->event->order->id, + 'status' => 4 + ])); + } + return ['签收成功']; + } + + + /** + * @doc-name 产品订单取消 + * @doc-param int order_id 订单id + */ + public function actionCancel() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $form = new ProductCancelForm(); + return $form->cancel($post); + } + + /** + * @doc-name 产品订单退款 + * @doc-param int order_id 订单id + */ + public function actionRefundBase() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['order_id'], 'required'] + ]); + $productOrder = ProductOrder::find()->where([ + 'id' => $post['order_id'], + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'] + ])->select('id,total_pay_price,trans_expenses,items_price')->one(); + return $productOrder; + } + + + + /** + * @doc-name 产品订单退款 + * @doc-param int order_id 订单id + */ + public function actionRefund() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['order_id', 'reason'], 'required'] + ]); + $form = new ProductRefundForm(); + return $form->refund($post); + } + + + /** + * @doc-name 产品订单退款原因 + * @doc-param int order_id 订单id + */ + public function actionRefundReason() + { + $list = RefundReason::find()->select('id,reason as text')->asArray()->all(); + return $list; + } + + /** + * @doc-name 产品订单退款申请撤销 + * @doc-param int order_id 订单id + */ + public function actionRefundCancel() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $form = new ProductRefundCancelForm(); + return $form->cancel($post['order_id']); + } + + + /** + * 物流详情 + */ + public function actionExpress(){ + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['order_id', 'required'] + ]); + $express = (new ExpressService())->detail($get['order_id']); + return $express; + } + +} \ No newline at end of file diff --git a/member/modules/v1/controllers/RegisterController.php b/member/modules/v1/controllers/RegisterController.php new file mode 100644 index 0000000..85c9c92 --- /dev/null +++ b/member/modules/v1/controllers/RegisterController.php @@ -0,0 +1,201 @@ +request->post(); + $RegisterForm=new RegisterForm(); + $RegisterForm->attributes=$post; + return $RegisterForm->save(); + } + + /** + * @doc-name 挂号信息 + * @doc-param int service_user_id 医生id + * @doc-return string time 日期 + * @doc-return float register_price 金额 + * @doc-return int left_num 剩余号 + * @doc-return int register_num 总号数 + */ + public function actionDocRegisterInfo() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['service_user_id','required'] + ]); + $RegisterForm=new RegisterForm(); + $RegisterForm->attributes=$post; + + return $RegisterForm->info(); + } + + + /** + * @doc-name 支付挂号 + * @doc-param int register_id 挂号id + * @doc-return int is_paid 1已支付0未支付 + * @doc-return int register_id 挂号id + * @doc-return array config 支付配置参数,在is_paid=0时返回 + */ + public function actionPay() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['register_id','required'] + ]); + $RegisterSubmitForm=new RegisterSubmitForm(); + $RegisterSubmitForm->attributes=$post; + + return $RegisterSubmitForm->getPayData($post['register_id']); + } + + /** + * @doc-name 挂号退款 + * @doc-param int register_id 挂号id + */ + public function actionRefund() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['register_id','required'] + ]); + + $RegisterRefundForm=new RegisterRefundForm(); + $RegisterRefundForm->attributes=$post; + + return $RegisterRefundForm->refund($post['register_id']); + } + + /** + * @doc-name 挂号详情 + * @doc-param int register_id 挂号id + * @doc-return string store 门店 + * @doc-return string depart 科室 + * @doc-return string doctor 医生 + * @doc-return int order_number 预约序号 + * @doc-return float price 挂号金额 + * @doc-return string patient 就诊人 + * @doc-return string idcard 身份证 + * @doc-return string mobile 手机号 + * @doc-return int is_pay 是否支付0否1是 + * @doc-return int status 状态1待接诊2接诊中3已结束4已取消5待评价6已评价7已拒诊 + * @doc-return int is_cancel 是否取消0否1是 + * @doc-return int cancel_time 取消时间 + * @doc-return string refuse_reason 拒诊原因 + */ + public function actionRegisterDetail() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['register_id','required'] + ]); + $Register = Register::find()->where([ + 'id'=>$post['register_id'], + 'user_id' => \Yii::$app->user->id, + 'is_delete' => 0, + ])->one(); + if (!$Register) throw new Exception('该挂号不存在'); + + $query = Register::find()->where([ + 'id'=>$post['register_id'], + 'user_id' => \Yii::$app->user->id, + 'is_delete' => 0, + ])->with(['store','depart','doctor','patient']); + + $this->field=[ + Register::class=>[ + 'store'=>'store.name', + 'depart'=>'doctor.depart.name', + 'doctor'=>'doctor.name', + 'order_number','price', + 'patient'=>'patient.name', + 'idcard'=>'patient.id_card', + 'mobile'=>'patient.mobile', + 'status','is_pay','created_at','is_cancel', + 'cancel_time'=>function($m){ + return date('Y-m-d H:i:s',$m->cancel_time); + }, + 'refuse_reason' + ] + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 取消挂号 + * @doc-return string msg 信息 + */ + public function actionCancel() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['register_id','required'] + ]); + $RegisterForm=new RegisterForm(); + $RegisterForm->attributes=$post; + + return $RegisterForm->cancel(); + } + + /** + * @doc-name 挂号列表 + * @doc-param int patient_id 患者id / optional + * @doc-return mixed @List{id-int-挂号id,user_id-int-用户id,order_no-string-订单号,service_user_id-int-医生id,store-string-门店,user_patient_id-int-患者id,depart-string-科室,doctor-string-医生,order_number-int-挂号序号,price-float-挂号金额,patient-string-患者,idcard-string-身份证,mobile-string-手机号,status-int-状态1待接诊2接诊中3已结束4已取消5待评价6已评价7已拒诊,is_pay-int-是否支付0否1是,created_at-string-挂号时间,is_cancel-int0是否取消0否1是} 挂号信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页多少条} 分页信息 + */ + public function actionList() + { + $post=\Yii::$app->request->post(); + $Register = Register::find()->where([ + 'user_id' => \Yii::$app->user->id, + 'is_delete' => 0, + 'is_cancel'=>0, + ])->all(); + if (!$Register) throw new Exception('暂无挂号记录'); + + $query = Register::find()->where([ + 'user_id' => \Yii::$app->user->id, + 'is_delete' => 0, + ])->with(['store','depart','patient','doctor'])->orderBy(['id'=>SORT_DESC]); + + if (!empty($post['patient_id'])) $query->andWhere(['user_patient_id'=>$post['patient_id']]); + + + $this->field=[ + Register::class=>[ + 'id','user_id','order_no','service_user_id', + 'store'=>'store.name', + 'user_patient_id', + 'depart'=>'depart.name', + 'doctor'=>'doctor.name', + 'order_number','price', + 'patient'=>'patient.name', + 'idcard'=>'patient.id_card', + 'mobile'=>'patient.mobile', + 'status','is_pay','created_at','is_cancel' + ] + ]; + return $this->create($query,$post); + } +} \ No newline at end of file diff --git a/member/modules/v1/controllers/StoreController.php b/member/modules/v1/controllers/StoreController.php new file mode 100644 index 0000000..43afceb --- /dev/null +++ b/member/modules/v1/controllers/StoreController.php @@ -0,0 +1,165 @@ +where([ + 'user_id'=>\Yii::$app->user->identity->getId(), + 'store_id'=>\Yii::$app->store, + 'is_delete'=>0 + ])->with(['store' => function ($q) { + $q->select('id,name,position,start_time,end_time,mobile'); + }])->asArray()->one(); + + if (!$StoreUser) throw new Exception('门店不存在'); + return $StoreUser; + } + + //门店详情 + public function actionDetail(){ + $store = Store::find()->select('id,name,position,start_time,end_time,mobile')->where(['id' => \Yii::$app->store])->with(['nav' => function ($q){ + $q->andWhere(['type' => 1]);//首页轮播图 + $q->select(['id','store_id','pic','link_type','external_link']); + }])->asArray()->one(); + if(!$store){ + throw new Exception('门店不存在'); + } + return $store; + } + + /** + * @doc-name 用户所有门店 + * @doc-return mixed @Data{id,store_id-int-门店id,is_online-int-是否在该门店0否1是,@Store{*}} 门店信息 + */ + public function actionList() + { + #为了微信评审能顺利通过,做个开关 + $open_issue = env('OPEN_ISSUE'); + if($open_issue == 'true') + { + #此时开关已打开,就做一些假数据demo + $list = [ + [ + 'image' => 'https://p3.maiyaole.com/img/971/971752/org_org.jpg?v=1', + 'name' => '【日康】对乙酰氨基酚片0.3g*12片*2板/盒', + 'desc' => '清热解毒,咽喉肿痛,牙痛', + 'price' => '¥34.00', + 'num' => 1 + ], + [ + 'image' => 'https://p2.maiyaole.com/img/item/202210/24/202210241042513.jpg', + 'name' => '同仁堂 六味地黄丸(浓缩丸) 200丸/瓶', + 'desc' => '滋阴补肾。用于阴肾亏损,头晕耳鸣,腰膝酸软,骨蒸潮热,盗汗遗精。', + 'price' => '¥22.00', + 'num' => 1 + ] + ]; + }else{ + #首页门店列表 + $list = StoreUser::find()->where([ + 'user_id'=>\Yii::$app->user->identity->getId(), + + 'is_delete'=>0 + ])->with(['store' => function ($q){ + $q->select('id,drugstore_id,name,position,contact,start_time,end_time'); + }])->asArray()->all(); + + if (!$list) throw new Exception('暂时没有任何门店'); + } + $data['open_issue'] = $open_issue; + $data['list'] = $list; + + return $data; + } + + /** + * @doc-name 门店切换 + * @doc-param int store_id 要切换的门店id + */ + public function actionStoreChange() + { + $post=\Yii::$app->request->post(); + + $this->requestValidate($post,[ + ['store_id','required'] + ]); + $t=\Yii::$app->db->beginTransaction(); + try { + $store = Store::findOne($post['store_id']); + if(!$store)throw new Exception('门店不存在'); + + + StoreUser::updateAll(['is_online' => 0],[ + 'user_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0, + 'is_online' => 1 + ]); + + $StoreUser=StoreUser::find()->where([ + 'user_id' => \Yii::$app->user->identity->getId(), + 'store_id' => $post['store_id'], + 'is_delete' => 0, + ])->one(); + if (!$StoreUser){//绑定门店 + $StoreUser = new StoreUser(); + $StoreUser->store_id = $post['store_id']; + $StoreUser->user_id = \Yii::$app->user->identity->getId(); + //如果是搜索小程序进入后扫码其他门店,删除默认门店数据 + + StoreUser::updateAll(['is_delete' => 1],[ + 'user_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0, + 'type' => 1 + ]); + } + $StoreUser->last_login_time = time(); + $StoreUser->type=2; + $StoreUser->is_online=1; + $StoreUser->saveOrFail(); + + $user=User::find()->where(['id'=>\Yii::$app->user->identity->getId()])->one(); + if (!$user) throw new Exception('用户不存在'); + $user->current_store_id=$post['store_id']; + $user->saveOrFail(); + + $t->commit(); + return ['success']; + }catch (\Exception $exception){ + $t->rollBack(); + throw new Exception($exception->getMessage()); + } + } + + /** + * @doc-name 用户端首页开关 + * @doc-return mixed @Data{id,store_id-int-门店id,is_online-int-是否在该门店0否1是,@Store{*}} 门店信息 + */ + public function actionIssue() + { + #为了微信评审能顺利通过,做个开关 + $open_issue = env('OPEN_ISSUE'); + $data['open_issue'] = $open_issue; + + return $data; + } + +} diff --git a/member/modules/v1/controllers/SystemNoticeController.php b/member/modules/v1/controllers/SystemNoticeController.php new file mode 100644 index 0000000..7847609 --- /dev/null +++ b/member/modules/v1/controllers/SystemNoticeController.php @@ -0,0 +1,409 @@ +where([ + 'or', + [ + 'and', + ['store_id' => \Yii::$app->request->get()['store_id']], + ['scene_type' => 1], + ['user_id' => \Yii::$app->user->identity->id], + ['in','base_type',[3,4,5]], + ['read_status' => 0] + ], + [ + 'and', + ['scene_type' => 1], + ['base_type' => 99], + // ['user_id' => \Yii::$app->user->identity->id], + ['read_status' => 0] + ] + ])->select('notice_at')->orderBy('notice_at DESC')->asArray()->all(); + + $orderNotice = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 1, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 1, + 'read_status' => 0 + ])->select('notice_at')->orderBy('notice_at DESC')->asArray()->all(); + + + $doctorNews = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 1, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 6, + 'read_status' => 0 + ])->select('notice_at')->groupBy('notice_at')->orderBy('notice_at DESC')->asArray()->all(); + + $data = []; + if($systemNotice){ + $data['system'] = [ + 'num' => count($systemNotice), + 'time' =>$systemNotice[0]['notice_at'] + ]; + } + if($orderNotice){ + $data['order'] = [ + 'num' => count($orderNotice), + 'time' => $orderNotice[0]['notice_at'] + ]; + } + if($doctorNews){ + $data['doctor_news'] = [ + 'num' => count($doctorNews), + 'time' => $doctorNews[0]['notice_at'] + ]; + } + return $data; + } + + public function actionSystem(){ + $query = SystemNotice::find()->where([ + 'or', + [ + 'and', + ['store_id' => \Yii::$app->request->get()['store_id']], + ['scene_type' => 1], + ['user_id' => \Yii::$app->user->identity->id], + ['in','base_type',[3,4,5,7]], + ], + [ + 'and', + ['scene_type' => 1], + ['base_type' => 99], + // ['user_id' => \Yii::$app->user->identity->id] + ] + ])->select('id,data,content,url,url_type,read_status,base_type,notice_at')->orderBy('notice_at DESC'); + return $this->create($query, \Yii::$app->request->get()); + } + + /** + * @doc-name 订单消息 + */ + public function actionOrder(){ + $query = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 1, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 1 + ])->select('id,data,content,url,url_type,read_status,base_type,notice_at')->orderBy('notice_at DESC'); + return $this->create($query, \Yii::$app->request->get()); + } + + /** + * @doc-name 医生群发消息 + */ + public function actionDoctorNews(){ + $get=\Yii::$app->request->get(); + $query = SystemNotice::find()->where([ + 'store_id' =>$get['store_id'], + 'scene_type' => 1, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 6 + ])->groupBy('notice_at')->orderBy('notice_at DESC'); + + + $this->field = [ + SystemNotice::class => [ + 'id','data','content'=>function($s){ + $is_json= FuncHelper::is_not_null($s->content); + if (!$is_json){ + return Json::decode($s->content); + }else{ + return $s->content; + } + },'url_type','url','read_status','read_status','base_type','notice_at' + ], + ]; + return $this->create($query, $get); + } + /** + * @doc-name 消息详情 + */ + public function actionNewInfo() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get,[ + ['id','required'], + ]); + + $SystemNotice=SystemNotice::find()->select('id,data,content,url,url_type,read_status,base_type,notice_at')->where(['id'=>$get['id']])->asArray()->one(); + if (!$SystemNotice){ + throw new \yii\db\Exception('消息不存在'); + } + $is_json= FuncHelper::is_not_null($SystemNotice['content']); + if (!$is_json){ + $SystemNotice['content']= Json::decode($SystemNotice['content']); + } + + return $SystemNotice; + } + + public function actionRead(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['type','required'], + ['store_id','required'] + ]); + $type = $post['type']; + switch ($type) { + case 'all': + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=1 AND user_id='.\Yii::$app->user->identity->id.' AND store_id='.$post['store_id'])->execute(); + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=1 AND base_type=99 AND user_id='.\Yii::$app->user->identity->id)->execute(); + break; + case 'system': + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=1 AND (base_type=3 or base_type=4 or base_type=5 or base_type=7) AND user_id='.\Yii::$app->user->identity->id.' AND store_id='.$post['store_id'])->execute(); + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=1 AND base_type=99 AND user_id='.\Yii::$app->user->identity->id)->execute(); + break; + case 'order': + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=1 AND base_type=1 AND user_id='.\Yii::$app->user->identity->id.' AND store_id='.$post['store_id'])->execute(); + break; + case 'doctor_news': + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=1 AND base_type=6 AND user_id='.\Yii::$app->user->identity->id.' AND store_id='.$post['store_id'])->execute(); + break; + default: + throw new Exception('错误的type'); + break; + } + return ['success']; + } + + /** + * @doc-name 系统消息列表 + * @doc-return mixed @Accept{text-string-主题,msg-string-消息,num-int-未读数量} 已接诊 + * @doc-return mixed @Reminder{text-string-主题,msg-string-消息,num-int-未读数量} 温馨提示 + * @doc-return mixed @OrderCancel{text-string-主题,msg-string-消息,num-int-未读数量} 订单取消 + * @doc-return mixed @Refuse{text-string-主题,msg-string-消息,num-int-未读数量} 已拒诊 + */ + public function actionList() + { + $doctor_accept='\u5df2\u63a5\u8bca';//已接诊 + //最新一条内容 + $order_cancel_content=SystemNotice::find()->select('content')->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::ORDER_CANCEL, + 'read_status'=>0 + ])->orderBy('id desc')->one(); + $reminder_content=SystemNotice::find()->select('content')->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::REMINDER, + 'read_status'=>0 + ])->orderBy('id desc')->one(); + $refuse_content=SystemNotice::find()->select('content')->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::REFUSE, + 'read_status'=>0 + ])->orderBy('id desc')->one(); + $refund_refuse_content=SystemNotice::find()->select('content')->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::REFUND_REFUSE, + 'read_status'=>0 + ])->orderBy('id desc')->one(); + + //未读数量 + $ORDER_CANCEL=SystemNotice::find()->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::ORDER_CANCEL, + 'read_status'=>0 + ])->count(); + $REFUSE=SystemNotice::find()->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::REFUSE, + 'read_status'=>0 + ])->count(); + $REMINDER=SystemNotice::find()->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::REMINDER, + 'read_status'=>0 + ])->count(); + $ImMessage= ImMessage::find()->select('content')->where([ + 'user_id'=>\Yii::$app->user->identity->getId(),//id 8 + 'read_status'=>0, + 'type'=>1, + ])->andWhere(['like','content',$doctor_accept])->count(); + $REFUND_REFUSE=SystemNotice::find()->where([ + 'scene_type'=>1,//用户端 + 'user_id'=>\Yii::$app->user->identity->getId(), + 'base_type'=>SystemNoticeTypeEnum::REFUND_REFUSE, + 'read_status'=>0 + ])->count(); + return [ + 'accept'=>[ + 'text'=>'医生已接诊', + 'msg'=>'您好,医生已接诊了', + 'num'=>$ImMessage + ], + 'reminder'=>[ + 'text'=>'温馨提示', + 'msg'=>$reminder_content??'', + 'num'=>$REMINDER + ], + 'orderCancel'=>[ + 'text'=>'订单已取消', + 'msg'=>$order_cancel_content??'', + 'num'=>$ORDER_CANCEL + ], + 'refuse'=>[ + 'text'=>'拒诊通知', + 'msg'=>$refuse_content??'', + 'num'=>$REFUSE + ], + 'refund_refuse'=>[ + 'text'=>'拒绝退款通知', + 'msg'=>$refund_refuse_content??'', + 'num'=>$REFUND_REFUSE + ] + ]; + } + + /** + * @doc-name 订单取消 + * @doc-return mixed @List{name-string-店铺名,pic-string-图片,order-string-订单,cancel_time-int-取消时间} 信息 + * @doc-return mixed @Pagination{total-int-总共数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionOrderCancel() + { + $post= \Yii::$app->request->post(); + + SystemNotice::updateAll(['read_status'=>1],[ + 'user_id'=>\Yii::$app->user->identity->getId(), + 'scene_type'=>1, + 'base_type'=>SystemNoticeTypeEnum::ORDER_CANCEL + ]); + + $query= Order::find()->where([ + 'user_id'=>\Yii::$app->user->identity->getId(),//id 18 + 'is_pay'=>1, + 'cancel_status'=>1, + ]); + $this->field=[ + Order::class=>[ + 'name'=>function($m){ + return '萧康医院'; + }, + 'pic'=>function($q){ + return 'https://yanydy.oss-cn-hangzhou.aliyuncs.com/uploads/20230216/0f2603ce881c9e25330d8b2d8bc0e36b.jpg'; + }, + 'cancel_time', + 'order'=>function($m){ + $name= DoctorInfo::find()->select('name')->where([ + 'su_id'=>$m->su_id + ])->one(); + return $name['name'].'医生的药方订单'; + }, + ] + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 已接诊 + * @doc-return mixed @List{name-string-医生,avatar-string-头像,accept_status-int-是否接诊默认0无状态1待接诊2已接诊3已拒绝结束4正常结束5超时未接诊结束6未接诊主动取消结束,accept_time-int-接诊时间} 信息 + * @doc-return mixed @Pagination{total-int-总共数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionAccept() + { + $post= \Yii::$app->request->post(); + + SystemNotice::updateAll(['read_status'=>1],[ + 'user_id'=>\Yii::$app->user->identity->getId(), + 'scene_type'=>1, + 'base_type'=>SystemNoticeTypeEnum::ACCEPT + ]); + + $query= Order::find()->where([ + 'user_id'=>\Yii::$app->user->identity->getId(),//id 18 + 'is_pay'=>1, + 'cancel_status'=>0, + 'accept_status'=>OrderAcceptEnum::ACCEPTING + ]); + $this->field=[ + Order::class=>[ + 'name'=>'serviceUser.docInfo.name', + 'avatar'=>'serviceUser.docInfo.avatar', + 'accept_time','accept_status', + ] + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 已拒诊 + * @doc-return mixed @List{name-string-医生,avatar-string-头像,accept_status-int-是否接诊默认0无状态1待接诊2已接诊3已拒绝结束4正常结束5超时未接诊结束6未接诊主动取消结束,refuse_time-int-拒诊时间} 信息 + * @doc-return mixed @Pagination{total-int-总共数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionRefuse() + { + $post= \Yii::$app->request->post(); + SystemNotice::updateAll(['read_status'=>1],[ + 'user_id'=>\Yii::$app->user->identity->getId(), + 'scene_type'=>1, + 'base_type'=>SystemNoticeTypeEnum::REFUSE + ]); + + $query= Order::find()->where([ + 'user_id'=>\Yii::$app->user->identity->getId(),//id 8 + 'is_pay'=>1, + 'cancel_status'=>0, + 'accept_status'=>OrderAcceptEnum::REFUSED + ]); + $this->field=[ + Order::class=>[ + 'name'=>'serviceUser.docInfo.name', + 'avatar'=>'serviceUser.docInfo.avatar', + 'accept_status','refuse_time', + ] + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 温馨提示列表 + * @doc-return mixed @SystemNotice{*} 详细信息 + */ + public function actionReminder() + { + //已读 + SystemNotice::updateAll(['read_status'=>1],[ + 'user_id'=>\Yii::$app->user->identity->getId(), + 'scene_type'=>1, + 'base_type'=>SystemNoticeTypeEnum::REMINDER + ]); + + return SystemNotice::find()->where([ + 'user_id'=>\Yii::$app->user->identity->getId(),//id 8 + 'scene_type'=>1, + 'base_type'=>SystemNoticeTypeEnum::REMINDER + ])->orderBy('id desc')->all(); + } +} \ No newline at end of file diff --git a/member/modules/v1/controllers/TestController.php b/member/modules/v1/controllers/TestController.php new file mode 100644 index 0000000..05cca48 --- /dev/null +++ b/member/modules/v1/controllers/TestController.php @@ -0,0 +1,51 @@ +queue->delay(0)->push(new OrderRefundJob([ + 'orderId' => 11, + ])); + } + + + public function actionGetPinyin(){ + $type = \Yii::$app->request->post('type'); + $pinyin = new Pinyin(); + if($type == 'drug'){ + $drug = Drug::find()->where(['pinyin_simple' => null])->limit(2000)->asArray()->all(); + $num = 0; + foreach($drug as $k=>$v){ + \Yii::$app->db->createCommand()->update('yii_drug', ['pinyin_simple' =>$pinyin->abbr($v['drug_name'])], ['id' => $v['id']])->execute(); + $num++; + } + return ['获取药品首拼完成,共'.$num.'药品']; + } else { + $disease = Disease::find()->where(['pinyin' => null])->limit(3000)->asArray()->all(); + $num = 0; + foreach($disease as $k=>$v){ + \Yii::$app->db->createCommand()->update('yii_disease', ['pinyin' =>$pinyin->abbr($v['name'])], ['id' => $v['id']])->execute(); + $num++; + } + return ['获取诊断首拼完成,共'.$num.'诊断']; + } + } + +} \ No newline at end of file diff --git a/member/modules/v1/controllers/UserCommentController.php b/member/modules/v1/controllers/UserCommentController.php new file mode 100644 index 0000000..0442f70 --- /dev/null +++ b/member/modules/v1/controllers/UserCommentController.php @@ -0,0 +1,124 @@ +request->post(); + $this->requestValidate($post,[ + [['order_id','su_id','u_id','comment','score'],'required'] + ]); + $order=Order::find()->where([ + 'id'=>$post['order_id'], + 'user_id'=>\Yii::$app->user->identity->getId(), + 'su_id'=>$post['su_id'], + 'up_id'=>$post['u_id'] + ])->one(); + + if (!$order || $order->accept_status != OrderAcceptEnum::OVER) throw new Exception('订单不存在'); + + $t=\Yii::$app->db->beginTransaction(); + try { + //评价 + $UserComment=new UserComment(); + $UserComment->su_id=$post['su_id']; + $UserComment->u_id=$post['u_id']; + $UserComment->score=$post['score']; + $UserComment->comment=$post['comment']; + $UserComment->order_id=$post['order_id']; + $UserComment->user_id=\Yii::$app->user->identity->getId(); + $UserComment->saveOrFail(); + + //订单评价状态 + $order->is_comment=1; + $order->comment_time=time(); + $order->saveOrFail(); + + $t->commit(); + }catch (\Exception $e){ + $t->rollBack(); + throw $e; + } + } + + /** + * @doc-name 删除评价 + * @doc-param int id 评价id + * @doc-param int su_id 医生id + * @doc-param int u_id 患者id + */ + public function actionDel() + { + $post= \Yii::$app->request->post(); + $this->requestValidate($post,[ + [ ['id','su_id','u_id'],'required'] + ]); + $CommentForm=new CommentForm(); + $CommentForm->attributes=$post; + $CommentForm->del($post['id']); + + return ['删除成功']; + } + + /** + * @doc-name 评价列表 + * @doc-param int su_id 医生id + * @doc-return mixed @UserComment{*} 信息 + */ + public function actionList() + { + $post= \Yii::$app->request->post(); + $this->requestValidate($post,[ + [ 'su_id','required'] + ]); + $UserComment=UserComment::find()->where([ + 'su_id'=>$post['su_id'] + ])->all(); + + if (!$UserComment) throw new Exception('暂时没有任何评价'); + return $UserComment; + } + + /** + * @doc-name 编辑评价 + * @doc-param int id 评价id + * @doc-param int su_id 医生id + * @doc-param int u_id 患者id + * @doc-param int score 评分 + * @doc-param string comment 内容 + */ + public function actionEditComment() + { + $post= \Yii::$app->request->post(); + $this->requestValidate($post,[ + [ ['id'],'required'] + ]); + $CommentForm=new CommentForm(); + $CommentForm->attributes=$post; + + + $CommentForm->edit($post['id']); + return ['编辑成功']; + } + +} \ No newline at end of file diff --git a/member/modules/v1/controllers/UserController.php b/member/modules/v1/controllers/UserController.php new file mode 100644 index 0000000..de8dab1 --- /dev/null +++ b/member/modules/v1/controllers/UserController.php @@ -0,0 +1,288 @@ +request->post(); + $this->requestValidate($post, [ + ['status', 'required'] + ]); + $form = new LoginForm(); + $form->attributes = $post; + + return $form->userlogin(); + } + + /** + * 登录互联网医院平台 + */ + public function actionLoginPlatform(){ + $post = \Yii::$app->request->post(); + return (new PlatformService())->userLogin($post); + } + + /** + * @doc-name 用户授权 + * @doc-param string iv iv加密算法的初始向量 + * @doc-param string encryptedData 包括敏感数据在内的完整用户信息的加密数据 + * @doc-return mixed User{*} 用户详情 + */ + public function actionUpdateUserInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['iv', 'encryptedData'], 'required'] + ]); + $user = \Yii::$app->user->identity; + $data = WechatService::getInstance()->app->encryptor->decryptData($user->session_key, $post['iv'], $post['encryptedData']); + + $user->attributes = [ + 'nickname' => $data['nickName'], + 'gender' => $data['gender'], + 'country' => $data['country'], + 'province' => $data['province'], + 'city' => $data['city'], + 'avatarurl' => $data['avatarUrl'], + 'mobile' => $data['phoneNumber'] ?? '', + ]; + + $user->saveOrFail(); + + return $user; + } + + /** + * @doc-name 手机号授权 + * @doc-param string iv iv加密算法的初始向量 + * @doc-param string encryptedData 包括敏感数据在内的完整用户信息的加密数据 + * @doc-return mixed User{*} 用户详情 + */ + public function actionPhoneNumber() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['iv', 'encryptedData'], 'required'], + ]); + + $user = \Yii::$app->user->identity; + $data = WechatService::getInstance()->app->encryptor->decryptData($user->session_key, $post['iv'], $post['encryptedData']); + if(!$user->mobile){ + $user->mobile = $data['phoneNumber']; + $user->saveOrFail(); + + // $response = (new Client(['http_errors' => false]))->post(\Yii::$app->params['platform']['url']."/platform/v1/sync/user", [ + // 'headers' => ['Authorization' =>"Bearer ".\Yii::$app->params['platform']['token']], + // 'form_params' => [ + // 'id' => $user->id, + // 'mobile' => $user->mobile, + // 'nickname' => '微信用户', + // 'avatarurl' => $user->avatarurl + // ], + // ]); + // $result = json_decode($response->getBody(),true); + // if ($result['errcode'] == -1) { + // throw new Exception($result['msg']); + // } + } + + + return[ + 'user'=>$user, + 'plate_token'=>"Bearer ".\Yii::$app->params['platform']['token'], + ]; + } + + /** + * @doc-name 用户信息 + * @doc-return mixed @User{*} 用户详情 + */ + public function actionInfo() + { + $get = \Yii::$app->request->get(); + $user= \Yii::$app->user->identity; + + $ProductOrder['unpay'] = ProductOrder::find()->where([ + 'user_id' => $user->getId(), + 'store_id' => $get['store_id'] ?? 11001 + ])->andWhere([ + 'status' => ProductOrderEnum::UNPAY + ])->count(); + + $ProductOrder['wait_send'] = ProductOrder::find()->where([ + 'user_id' => $user->getId(), + 'store_id' => $get['store_id'] ?? 11001 + ])->andWhere([ + 'status' =>ProductOrderEnum::WAIT_SEND + ])->count(); + + $ProductOrder['wait_accept'] = ProductOrder::find()->where([ + 'user_id' => $user->getId(), + 'store_id' => $get['store_id'] ?? 11001 + ])->andWhere([ + 'status' => ProductOrderEnum::WAIT_ACCEPT + ])->count(); + + + if ($user->gender==1){ + $user->gender='男'; + }elseif ($user->gender==2){ + $user->gender='女'; + }else{ + $user->gender='未知'; + } + + return [ + 'user' => $user, + 'sex' => $user->gender, + 'ProductOrder'=>$ProductOrder + ]; + } + + /** + * @doc-name 编辑信息 + * @doc-param string nickname 昵称 / optional + * @doc-param string mobile 电话 / optional + * @doc-param string gender 性别0默认1男2女 / optional + * @doc-param string country 国家 / optional + * @doc-param string province 省 / optional + * @doc-param string city 市 / optional + * @doc-param string avatarurl 头像 / optional + * @doc-param string idcard 身份证 / optional + * @doc-param int age 年龄 / optional + **/ + public function actionEditInfo() + { + $post = \Yii::$app->request->post(); + $user = User::find()->where([ + 'id' => \Yii::$app->user->id + ])->one(); + if (!$user) throw new Exception('用户不存在'); + + $user->nickname=$post['nickname']??$user->nickname; + $user->mobile=$post['mobile']??$user->mobile; + $user->gender=$post['gender']??$user->gender; + $user->country=$post['country']??$user->country; + $user->province=$post['province']??$user->province; + $user->city=$post['city']??$user->city; + $user->avatarurl=$post['avatarurl']??$user->avatarurl; + $user->idcard=$post['idcard']??$user->idcard; + $user->age=$post['age']??$user->age; + + $user->saveOrFail(); + return ['编辑成功']; + } + + /** + * @doc-name 修改密码 + * @doc-param string old_pass 旧密码 + * @doc-param string new_pass 新密码 + */ + public function actionUpdatePassword() + { + $form = new UpdatePassForm(); + $form->attributes = \Yii::$app->request->post(); + return $form->updatePassword(); + } + + /** + * @doc-name 退出登录 + * @doc-param string token token + */ + public function actionLogout() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['token'], 'required'], + ]); + + $user = User::find()->where([ + 'id' => \Yii::$app->user->identity->getId(), + 'token' => $post['token'], + ])->one(); + if (!$user) throw new Exception('账号不存在'); + + User::updateAll(['token' => ''], ['id' => \Yii::$app->user->identity->getId(), 'token' => $post['token']]); + } + + /** + * @doc-name 手机号登录发送短信 + * @doc-param string mobile 手机号码 + * @doc-return string smsCode 验证码 + */ + public function actionSendCode() + { + $code = (string)mt_rand(100000, 999999); + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['mobile', 'required'] + ]); + $message=[ + 'content' => '您的验证码为:" ' .$code. ' ",请勿泄露与他人', + 'template' => 'SMS_274460204', + 'data' => [ + 'code' => $code + ] + ]; + $cache = \Yii::$app->cache; + $cache->set( 'login_sms_code_'.$post['mobile'], $code, 600); + $cache->set( 'login_sms_time_'.$post['mobile'], time(), 600); + + $response = (new SmsService())->sendCaptcha($post['mobile'], $code); + + return [$response]; + } + + /** + * @doc-name 协议 + * @doc-param int end 1用户端2服务端 + * @doc-return mixed @BaseConfig{*} 信息 + */ + public function actionAgreement() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['end', 'required'] + ]); + $BaseConfig = BaseConfig::find()->where([ + 'end' => $post['end'], + // 'store_id' => $post['store_id'], + 'status' => 0 + ])->andWhere(['type' => [1, 2]])->select(['type', 'content', 'change_at'])->all(); + return $BaseConfig; + } + +} diff --git a/member/tests/_bootstrap.php b/member/tests/_bootstrap.php new file mode 100644 index 0000000..637ce14 --- /dev/null +++ b/member/tests/_bootstrap.php @@ -0,0 +1,10 @@ + 'erau', + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', + // password_0 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', + 'created_at' => '1392559490', + 'updated_at' => '1392559490', + 'email' => 'sfriesen@jenkins.info', + ], + [ + 'username' => 'test.test', + 'auth_key' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT', + // Test1234 + 'password_hash' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT', + 'email' => 'test@mail.com', + 'status' => '9', + 'created_at' => '1548675330', + 'updated_at' => '1548675330', + 'verification_token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330', + ], +]; diff --git a/member/tests/_data/user.php b/member/tests/_data/user.php new file mode 100644 index 0000000..0b94332 --- /dev/null +++ b/member/tests/_data/user.php @@ -0,0 +1,45 @@ + 'okirlin', + 'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv', + 'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi', + 'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(), + 'created_at' => '1391885313', + 'updated_at' => '1391885313', + 'email' => 'brady.renner@rutherford.com', + ], + [ + 'username' => 'troy.becker', + 'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp', + 'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2', + 'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(), + 'created_at' => '1391885313', + 'updated_at' => '1391885313', + 'email' => 'nicolas.dianna@hotmail.com', + 'status' => '0', + ], + [ + 'username' => 'test.test', + 'auth_key' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT', + //Test1234 + 'password_hash' => '$2y$13$d17z0w/wKC4LFwtzBcmx6up4jErQuandJqhzKGKczfWuiEhLBtQBK', + 'email' => 'test@mail.com', + 'status' => '9', + 'created_at' => '1548675330', + 'updated_at' => '1548675330', + 'verification_token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330', + ], + [ + 'username' => 'test2.test', + 'auth_key' => '4XXdVqi3rDpa_a6JH6zqVreFxUPcUPvJ', + //Test1234 + 'password_hash' => '$2y$13$d17z0w/wKC4LFwtzBcmx6up4jErQuandJqhzKGKczfWuiEhLBtQBK', + 'email' => 'test2@mail.com', + 'status' => '10', + 'created_at' => '1548675330', + 'updated_at' => '1548675330', + 'verification_token' => 'already_used_token_1548675330', + ], +]; diff --git a/member/tests/_output/.gitignore b/member/tests/_output/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/member/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/member/tests/_support/.gitignore b/member/tests/_support/.gitignore new file mode 100644 index 0000000..36e264c --- /dev/null +++ b/member/tests/_support/.gitignore @@ -0,0 +1 @@ +_generated diff --git a/member/tests/_support/FunctionalTester.php b/member/tests/_support/FunctionalTester.php new file mode 100644 index 0000000..ec5dd1d --- /dev/null +++ b/member/tests/_support/FunctionalTester.php @@ -0,0 +1,34 @@ +see($message, '.invalid-feedback'); + } + + public function dontSeeValidationError($message) + { + $this->dontSee($message, '.invalid-feedback'); + } +} diff --git a/member/tests/_support/UnitTester.php b/member/tests/_support/UnitTester.php new file mode 100644 index 0000000..025be5f --- /dev/null +++ b/member/tests/_support/UnitTester.php @@ -0,0 +1,26 @@ +amOnRoute(Url::toRoute('/site/index')); + $I->see('My Application'); + + $I->seeLink('About'); + $I->click('About'); + $I->wait(2); // wait for page to be opened + + $I->see('This is the About page.'); + } +} diff --git a/member/tests/acceptance/_bootstrap.php b/member/tests/acceptance/_bootstrap.php new file mode 100644 index 0000000..47716f0 --- /dev/null +++ b/member/tests/acceptance/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cept + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/member/tests/functional.suite.yml b/member/tests/functional.suite.yml new file mode 100644 index 0000000..90047d7 --- /dev/null +++ b/member/tests/functional.suite.yml @@ -0,0 +1,7 @@ +suite_namespace: app\tests\functional +actor: FunctionalTester +modules: + enabled: + - Filesystem + - Yii2 + - Asserts diff --git a/member/tests/functional/AboutCest.php b/member/tests/functional/AboutCest.php new file mode 100644 index 0000000..2aebfc6 --- /dev/null +++ b/member/tests/functional/AboutCest.php @@ -0,0 +1,14 @@ +amOnRoute('site/about'); + $I->see('About', 'h1'); + } +} diff --git a/member/tests/functional/ContactCest.php b/member/tests/functional/ContactCest.php new file mode 100644 index 0000000..39357f8 --- /dev/null +++ b/member/tests/functional/ContactCest.php @@ -0,0 +1,60 @@ +amOnRoute('site/contact'); + } + + public function checkContact(FunctionalTester $I) + { + $I->see('Contact', 'h1'); + } + + public function checkContactSubmitNoData(FunctionalTester $I) + { + $I->submitForm('#contact-form', []); + $I->see('Contact', 'h1'); + $I->seeValidationError('Name cannot be blank'); + $I->seeValidationError('Email cannot be blank'); + $I->seeValidationError('Subject cannot be blank'); + $I->seeValidationError('Body cannot be blank'); + $I->seeValidationError('The verification code is incorrect'); + } + + public function checkContactSubmitNotCorrectEmail(FunctionalTester $I) + { + $I->submitForm('#contact-form', [ + 'ContactForm[name]' => 'tester', + 'ContactForm[email]' => 'tester.email', + 'ContactForm[subject]' => 'test subject', + 'ContactForm[body]' => 'test content', + 'ContactForm[verifyCode]' => 'testme', + ]); + $I->seeValidationError('Email is not a valid email address.'); + $I->dontSeeValidationError('Name cannot be blank'); + $I->dontSeeValidationError('Subject cannot be blank'); + $I->dontSeeValidationError('Body cannot be blank'); + $I->dontSeeValidationError('The verification code is incorrect'); + } + + public function checkContactSubmitCorrectData(FunctionalTester $I) + { + $I->submitForm('#contact-form', [ + 'ContactForm[name]' => 'tester', + 'ContactForm[email]' => 'tester@example.com', + 'ContactForm[subject]' => 'test subject', + 'ContactForm[body]' => 'test content', + 'ContactForm[verifyCode]' => 'testme', + ]); + $I->seeEmailIsSent(); + $I->see('Thank you for contacting us. We will respond to you as soon as possible.'); + } +} diff --git a/member/tests/functional/HomeCest.php b/member/tests/functional/HomeCest.php new file mode 100644 index 0000000..604515b --- /dev/null +++ b/member/tests/functional/HomeCest.php @@ -0,0 +1,17 @@ +amOnRoute(\Yii::$app->homeUrl); + $I->see('My Application'); + $I->seeLink('About'); + $I->click('About'); + $I->see('This is the About page.'); + } +} \ No newline at end of file diff --git a/member/tests/functional/LoginCest.php b/member/tests/functional/LoginCest.php new file mode 100644 index 0000000..1170a36 --- /dev/null +++ b/member/tests/functional/LoginCest.php @@ -0,0 +1,66 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'login_data.php', + ], + ]; + } + + public function _before(FunctionalTester $I) + { + $I->amOnRoute('site/register'); + } + + protected function formParams($login, $password) + { + return [ + 'LoginForm[username]' => $login, + 'LoginForm[password]' => $password, + ]; + } + + public function checkEmpty(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('', '')); + $I->seeValidationError('Username cannot be blank.'); + $I->seeValidationError('Password cannot be blank.'); + } + + public function checkWrongPassword(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('admin', 'wrong')); + $I->seeValidationError('Incorrect username or password.'); + } + + public function checkInactiveAccount(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('test.test', 'Test1234')); + $I->seeValidationError('Incorrect username or password'); + } + + public function checkValidLogin(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('erau', 'password_0')); + $I->see('Logout (erau)', 'form button[type=submit]'); + $I->dontSeeLink('register'); + $I->dontSeeLink('Signup'); + } +} diff --git a/member/tests/functional/ResendVerificationEmailCest.php b/member/tests/functional/ResendVerificationEmailCest.php new file mode 100644 index 0000000..9cb7284 --- /dev/null +++ b/member/tests/functional/ResendVerificationEmailCest.php @@ -0,0 +1,83 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php', + ], + ]; + } + + public function _before(FunctionalTester $I) + { + $I->amOnRoute('/site/resend-verification-email'); + } + + protected function formParams($email) + { + return [ + 'ResendVerificationEmailForm[email]' => $email + ]; + } + + public function checkPage(FunctionalTester $I) + { + $I->see('Resend verification email', 'h1'); + $I->see('Please fill out your email. A verification email will be sent there.'); + } + + public function checkEmptyField(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('')); + $I->seeValidationError('Email cannot be blank.'); + } + + public function checkWrongEmailFormat(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('abcd.com')); + $I->seeValidationError('Email is not a valid email address.'); + } + + public function checkWrongEmail(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('wrong@email.com')); + $I->seeValidationError('There is no user with this email address.'); + } + + public function checkAlreadyVerifiedEmail(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('test2@mail.com')); + $I->seeValidationError('There is no user with this email address.'); + } + + public function checkSendSuccessfully(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('test@mail.com')); + $I->canSeeEmailIsSent(); + $I->seeRecord('common\models\User', [ + 'email' => 'test@mail.com', + 'username' => 'test.test', + 'status' => \common\models\User::STATUS_INACTIVE + ]); + $I->see('Check your email for further instructions.'); + } +} diff --git a/member/tests/functional/SignupCest.php b/member/tests/functional/SignupCest.php new file mode 100644 index 0000000..325e7e8 --- /dev/null +++ b/member/tests/functional/SignupCest.php @@ -0,0 +1,59 @@ +amOnRoute('site/signup'); + } + + public function signupWithEmptyFields(FunctionalTester $I) + { + $I->see('Signup', 'h1'); + $I->see('Please fill out the following fields to signup:'); + $I->submitForm($this->formId, []); + $I->seeValidationError('Username cannot be blank.'); + $I->seeValidationError('Email cannot be blank.'); + $I->seeValidationError('Password cannot be blank.'); + + } + + public function signupWithWrongEmail(FunctionalTester $I) + { + $I->submitForm( + $this->formId, [ + 'SignupForm[username]' => 'tester', + 'SignupForm[email]' => 'ttttt', + 'SignupForm[password]' => 'tester_password', + ] + ); + $I->dontSee('Username cannot be blank.', '.invalid-feedback'); + $I->dontSee('Password cannot be blank.', '.invalid-feedback'); + $I->see('Email is not a valid email address.', '.invalid-feedback'); + } + + public function signupSuccessfully(FunctionalTester $I) + { + $I->submitForm($this->formId, [ + 'SignupForm[username]' => 'tester', + 'SignupForm[email]' => 'tester.email@example.com', + 'SignupForm[password]' => 'tester_password', + ]); + + $I->seeRecord('common\models\User', [ + 'username' => 'tester', + 'email' => 'tester.email@example.com', + 'status' => \common\models\User::STATUS_INACTIVE + ]); + + $I->seeEmailIsSent(); + $I->see('Thank you for registration. Please check your inbox for verification email.'); + } +} diff --git a/member/tests/functional/VerifyEmailCest.php b/member/tests/functional/VerifyEmailCest.php new file mode 100644 index 0000000..1a9fca9 --- /dev/null +++ b/member/tests/functional/VerifyEmailCest.php @@ -0,0 +1,68 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php', + ], + ]; + } + + public function checkEmptyToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => '']); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Verify email token cannot be blank.'); + } + + public function checkInvalidToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => 'wrong_token']); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Wrong verify email token.'); + } + + public function checkNoToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email'); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Missing required parameters: token'); + } + + public function checkAlreadyActivatedToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => 'already_used_token_1548675330']); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Wrong verify email token.'); + } + + public function checkSuccessVerification(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330']); + $I->canSee('Your email has been confirmed!'); + $I->canSee('Congratulations!', 'h1'); + $I->see('Logout (test.test)', 'form button[type=submit]'); + + $I->seeRecord('common\models\User', [ + 'username' => 'test.test', + 'email' => 'test@mail.com', + 'status' => \common\models\User::STATUS_ACTIVE + ]); + } +} diff --git a/member/tests/functional/_bootstrap.php b/member/tests/functional/_bootstrap.php new file mode 100644 index 0000000..30ed54b --- /dev/null +++ b/member/tests/functional/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/member/tests/unit.suite.yml b/member/tests/unit.suite.yml new file mode 100644 index 0000000..285752b --- /dev/null +++ b/member/tests/unit.suite.yml @@ -0,0 +1,7 @@ +suite_namespace: app\tests\unit +actor: UnitTester +modules: + enabled: + - Yii2: + part: [orm, email, fixtures] + - Asserts diff --git a/member/tests/unit/_bootstrap.php b/member/tests/unit/_bootstrap.php new file mode 100644 index 0000000..e432ce5 --- /dev/null +++ b/member/tests/unit/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Tests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ diff --git a/member/tests/unit/models/ContactFormTest.php b/member/tests/unit/models/ContactFormTest.php new file mode 100644 index 0000000..112735f --- /dev/null +++ b/member/tests/unit/models/ContactFormTest.php @@ -0,0 +1,35 @@ +attributes = [ + 'name' => 'Tester', + 'email' => 'tester@example.com', + 'subject' => 'very important letter subject', + 'body' => 'body of current message', + ]; + + verify($model->sendEmail('admin@example.com'))->notEmpty(); + + // using Yii2 module actions to check email was sent + $this->tester->seeEmailIsSent(); + + /** @var MessageInterface $emailMessage */ + $emailMessage = $this->tester->grabLastSentEmail(); + verify($emailMessage)->instanceOf('yii\mail\MessageInterface'); + verify($emailMessage->getTo())->arrayHasKey('admin@example.com'); + verify($emailMessage->getFrom())->arrayHasKey('noreply@example.com'); + verify($emailMessage->getReplyTo())->arrayHasKey('tester@example.com'); + verify($emailMessage->getSubject())->equals('very important letter subject'); + verify($emailMessage->toString())->stringContainsString('body of current message'); + } +} diff --git a/member/tests/unit/models/PasswordResetRequestFormTest.php b/member/tests/unit/models/PasswordResetRequestFormTest.php new file mode 100644 index 0000000..ee6e536 --- /dev/null +++ b/member/tests/unit/models/PasswordResetRequestFormTest.php @@ -0,0 +1,59 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testSendMessageWithWrongEmailAddress() + { + $model = new PasswordResetRequestForm(); + $model->email = 'not-existing-email@example.com'; + verify($model->sendEmail())->false(); + } + + public function testNotSendEmailsToInactiveUser() + { + $user = $this->tester->grabFixture('user', 1); + $model = new PasswordResetRequestForm(); + $model->email = $user['email']; + verify($model->sendEmail())->false(); + } + + public function testSendEmailSuccessfully() + { + $userFixture = $this->tester->grabFixture('user', 0); + + $model = new PasswordResetRequestForm(); + $model->email = $userFixture['email']; + $user = User::findOne(['password_reset_token' => $userFixture['password_reset_token']]); + + verify($model->sendEmail())->notEmpty(); + verify($user->password_reset_token)->notEmpty(); + + $emailMessage = $this->tester->grabLastSentEmail(); + verify($emailMessage)->instanceOf('yii\mail\MessageInterface'); + verify($emailMessage->getTo())->arrayHasKey($model->email); + verify($emailMessage->getFrom())->arrayHasKey(Yii::$app->params['supportEmail']); + } +} diff --git a/member/tests/unit/models/ResendVerificationEmailFormTest.php b/member/tests/unit/models/ResendVerificationEmailFormTest.php new file mode 100644 index 0000000..ff75246 --- /dev/null +++ b/member/tests/unit/models/ResendVerificationEmailFormTest.php @@ -0,0 +1,85 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testWrongEmailAddress() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => 'aaa@bbb.cc' + ]; + + verify($model->validate())->false(); + verify($model->hasErrors())->true(); + verify($model->getFirstError('email'))->equals('There is no user with this email address.'); + } + + public function testEmptyEmailAddress() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => '' + ]; + + verify($model->validate())->false(); + verify($model->hasErrors())->true(); + verify($model->getFirstError('email'))->equals('Email cannot be blank.'); + } + + public function testResendToActiveUser() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => 'test2@mail.com' + ]; + + verify($model->validate())->false(); + verify($model->hasErrors())->true(); + verify($model->getFirstError('email'))->equals('There is no user with this email address.'); + } + + public function testSuccessfullyResend() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => 'test@mail.com' + ]; + + verify($model->validate())->true(); + verify($model->hasErrors())->false(); + + verify($model->sendEmail())->true(); + $this->tester->seeEmailIsSent(); + + $mail = $this->tester->grabLastSentEmail(); + + verify($mail)->instanceOf('yii\mail\MessageInterface'); + verify($mail->getTo())->arrayHasKey('test@mail.com'); + verify($mail->getFrom())->arrayHasKey(\Yii::$app->params['supportEmail']); + verify($mail->getSubject())->equals('Account registration at ' . \Yii::$app->name); + verify($mail->toString())->stringContainsString('4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330'); + } +} diff --git a/member/tests/unit/models/ResetPasswordFormTest.php b/member/tests/unit/models/ResetPasswordFormTest.php new file mode 100644 index 0000000..54fc836 --- /dev/null +++ b/member/tests/unit/models/ResetPasswordFormTest.php @@ -0,0 +1,44 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ], + ]); + } + + public function testResetWrongToken() + { + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new ResetPasswordForm(''); + }); + + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new ResetPasswordForm('notexistingtoken_1391882543'); + }); + } + + public function testResetCorrectToken() + { + $user = $this->tester->grabFixture('user', 0); + $form = new ResetPasswordForm($user['password_reset_token']); + verify($form->resetPassword())->notEmpty(); + } + +} diff --git a/member/tests/unit/models/SignupFormTest.php b/member/tests/unit/models/SignupFormTest.php new file mode 100644 index 0000000..94dc617 --- /dev/null +++ b/member/tests/unit/models/SignupFormTest.php @@ -0,0 +1,72 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testCorrectSignup() + { + $model = new SignupForm([ + 'username' => 'some_username', + 'email' => 'some_email@example.com', + 'password' => 'some_password', + ]); + + $user = $model->signup(); + verify($user)->notEmpty(); + + /** @var \common\models\User $user */ + $user = $this->tester->grabRecord('common\models\User', [ + 'username' => 'some_username', + 'email' => 'some_email@example.com', + 'status' => \common\models\User::STATUS_INACTIVE + ]); + + $this->tester->seeEmailIsSent(); + + $mail = $this->tester->grabLastSentEmail(); + + verify($mail)->instanceOf('yii\mail\MessageInterface'); + verify($mail->getTo())->arrayHasKey('some_email@example.com'); + verify($mail->getFrom())->arrayHasKey(\Yii::$app->params['supportEmail']); + verify($mail->getSubject())->equals('Account registration at ' . \Yii::$app->name); + verify($mail->toString())->stringContainsString($user->verification_token); + } + + public function testNotCorrectSignup() + { + $model = new SignupForm([ + 'username' => 'troy.becker', + 'email' => 'nicolas.dianna@hotmail.com', + 'password' => 'some_password', + ]); + + verify($model->signup())->empty(); + verify($model->getErrors('username'))->notEmpty(); + verify($model->getErrors('email'))->notEmpty(); + + verify($model->getFirstError('username')) + ->equals('This username has already been taken.'); + verify($model->getFirstError('email')) + ->equals('This email address has already been taken.'); + } +} diff --git a/member/tests/unit/models/VerifyEmailFormTest.php b/member/tests/unit/models/VerifyEmailFormTest.php new file mode 100644 index 0000000..1f56e15 --- /dev/null +++ b/member/tests/unit/models/VerifyEmailFormTest.php @@ -0,0 +1,55 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testVerifyWrongToken() + { + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new VerifyEmailForm(''); + }); + + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new VerifyEmailForm('notexistingtoken_1391882543'); + }); + } + + public function testAlreadyActivatedToken() + { + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new VerifyEmailForm('already_used_token_1548675330'); + }); + } + + public function testVerifyCorrectToken() + { + $model = new VerifyEmailForm('4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330'); + $user = $model->verifyEmail(); + verify($user)->instanceOf('common\models\User'); + + verify($user->username)->equals('test.test'); + verify($user->email)->equals('test@mail.com'); + verify($user->status)->equals(\common\models\User::STATUS_ACTIVE); + verify($user->validatePassword('Test1234'))->true(); + } +} diff --git a/platform/config/bootstrap.php b/platform/config/bootstrap.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/platform/config/bootstrap.php @@ -0,0 +1 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => 'Pn1Ql072a0COUnXKgMUv4J7ZGZ0CipXd', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => \yii\debug\Module::class, + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => \yii\gii\Module::class, + ]; +} + +return $config; diff --git a/platform/config/main.php b/platform/config/main.php new file mode 100644 index 0000000..3de1f43 --- /dev/null +++ b/platform/config/main.php @@ -0,0 +1,64 @@ + 'app-platform', + 'basePath' => dirname(__DIR__), + 'bootstrap' => ['log'], + 'controllerNamespace' => 'platform\controllers', + 'modules' => [ + 'v1' => [ + 'class' => 'platform\modules\v1\Module', + ], + 'doc'=>[ + 'class' => 'cfd\doc\Module', + 'modelsMap'=>[ + '\common\models\\', + '\common\modelsgii\\', + ] + ], + ], + 'components' => [ + 'request' => [ + 'csrfParam' => '_csrf-api', + ], + 'response' => [ + 'class' => 'yii\web\Response', + 'format' => \yii\web\Response::FORMAT_JSON, + 'formatters' => [ + \yii\web\Response::FORMAT_JSON => [ + 'class' => 'common\foundation\JsonResponseFormatter', + 'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode + 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, + ], + ], + ], + 'user' => [ + 'identityClass' => 'platform\models\Platform', + 'enableAutoLogin' =>true, + 'enableSession'=>false, + ], + 'log' => [ + 'traceLevel' => YII_DEBUG ? 3 : 0, + 'targets' => [ + [ + 'class' => \yii\log\FileTarget::class, + 'levels' => ['error', 'warning'], + ], + ], + ], +// 'errorHandler' => [ +// 'errorAction' => 'site/error', +// ], + 'urlManager' => [ + 'enablePrettyUrl' => true, + 'showScriptName' => false, + 'rules' => [ + ], + ], + ], + 'params' => $params, +]; diff --git a/platform/models/Platform.php b/platform/models/Platform.php new file mode 100644 index 0000000..091a238 --- /dev/null +++ b/platform/models/Platform.php @@ -0,0 +1,69 @@ + $id]); + } + + public static function findIdentityByAccessToken($token, $type = null) + { + return static::findOne(['token' => $token, 'status' => StatusEnum::ACTIVE]); + } + + public function getId() + { + return $this->id; + } + + /** + * --------------------------------------- + * 获取密码干扰字符串 + * @return string + * --------------------------------------- + */ + public function getAuthKey() + { + return $this->salt; + } + + /** + * --------------------------------------- + * 验证 + * @param string $authKey + * @return bool + * --------------------------------------- + */ + public function validateAuthKey($authKey) + { + return $this->getAuthKey() === $authKey; + } + + /** + * 验证密码 + * + * @param string $password password to validate + * @return boolean if password provided is valid for current user + */ + public function validatePassword($password) + { + return Yii::$app->security->validatePassword($password, $this->password); + } + + /** + * 设置加密后的密码 + * + * @param string $password + */ + public function setPassword($password) + { + $this->password = Yii::$app->security->generatePasswordHash($password); + } +} diff --git a/platform/models/forms/SyncPatientForm.php b/platform/models/forms/SyncPatientForm.php new file mode 100644 index 0000000..33924d0 --- /dev/null +++ b/platform/models/forms/SyncPatientForm.php @@ -0,0 +1,110 @@ + 500], + ['mobile',MobileValidator::class], + ['id_card', 'match', 'pattern' => '/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/i'], + // ['id_card', 'checkCard'], + [['avatar'],'string'], + [['name','avatar'],'string'] + ]; + } + + // public function checkCard($attribute, $params) + // { + // $response = (new Client(['http_errors' => false]))->post("https://eid.shumaidata.com/eid/check", [ + // 'headers' => ['Authorization' =>"APPCODE f98bba3251714c759f5bd29d00e1c46e"], + // 'query' => [ + // 'idcard' => $this->id_card, + // 'name' => $this->name + // ], + // ]); + // $result = json_decode($response->getBody(),true); + // if(!($result['code']==0 && $result['result']['res']==1)){ + // $this->addError($attribute, '身份证名字不匹配'); + // } + // } + + public function save() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + $UserPatient = UserPatient::findOne([ + 'user_id' => $this->user_id, + 'id_card' => $this->id_card, + 'is_delete' => 0 + ]); + + if($UserPatient->id){ + //更新 + $UserPatientHealthInquiry = UserPatientHealthInquiry::findOne(['user_patient_id' => $UserPatient->id]); + if(!$UserPatientHealthInquiry){ + throw new Exception('就诊人健康信息不存在'); + } + }else{ + //新增 + $UserPatient = new UserPatient(); + $UserPatientHealthInquiry = new UserPatientHealthInquiry(); + } + + $Transaction = \Yii::$app->db->beginTransaction(); + try { + if($this->is_default){ + UserPatient::updateAll(['is_default'=>0],['user_id'=>$this->user_id]); + } + //就诊人 + $UserPatient->attributes = $this->attributes; + $UserPatient->saveOrFail(); + + $attributes = $this->attributes; + $attributes['user_patient_id'] = $UserPatient->id; + + //就诊人健康信息 + $UserPatientHealthInquiry->attributes = $attributes; + $UserPatientHealthInquiry->saveOrFail(); + + $Transaction->commit(); + }catch (Exception $exception){ + $Transaction->rollback(); + throw $exception; + } + return ['同步成功']; + } +} \ No newline at end of file diff --git a/platform/modules/v1/Module.php b/platform/modules/v1/Module.php new file mode 100644 index 0000000..303aa61 --- /dev/null +++ b/platform/modules/v1/Module.php @@ -0,0 +1,24 @@ +request->post(); + $service_user_id = $post['service_user_id']; + + $user = ServiceUser::findOne(['id'=>$service_user_id]); + + if(!$user){ + throw new Exception('用户不存在'); + } + $lastToken = ServiceUserToken::find()->where(['su_id' => $service_user_id])->orderBy('id DESC')->one(); + if(!ServiceUserToken::checkToken($lastToken->token)){ + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $service_user_id; + $token = \Yii::$app->security->generateRandomString() . '_' . time(); + $ServiceUserToken->token = $token; + $ServiceUserToken->saveOrFail(); + }else{ + $token = $lastToken->token; + } + + return ['token' => $token]; + } + + +} \ No newline at end of file diff --git a/platform/modules/v1/controllers/ErpController.php b/platform/modules/v1/controllers/ErpController.php new file mode 100644 index 0000000..42cac67 --- /dev/null +++ b/platform/modules/v1/controllers/ErpController.php @@ -0,0 +1,195 @@ +request->getHeaders(); + // $userid = $headers->get('userid'); + $secret = $headers->get('secret'); + $jacErpConfig = \Yii::$app->params['jac_erp']; + if($secret != $jacErpConfig['secret']){ + throw new Exception('非法请求'); + } + $rawData = \Yii::$app->request->rawBody; + $post = Json::decode($rawData); + if(!$post['startDate'] || !$post['endDate']){ + throw new Exception('startDate或endDate不能为空'); + } + try { + ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单开始 startDate:'.$post['startDate'].' endDate:'.$post['endDate']); + $startDate = strtotime($post['startDate']); + $endDate = strtotime($post['endDate']) + 86400; + + $productOrders = ProductOrder::find()->alias('po')->where([ + 'po.prescription_type' => 2, + 'po.is_sync_erp' => 0, + ])->andWhere([ + 'in','po.status',[1,2,3,6,7] + ])->andWhere(['BETWEEN', 'po.created_at', $startDate, $endDate])->joinWith('approvedPrescription')->with(['orderItems','store'])->asArray()->all(); + //解析成erp所需参数(订单详情是否需要改动 - 线上订单的展示) + $erpData = []; + $ids = []; + foreach($productOrders as $k=>$v){ + $erpData[$k]['orderId'] = $v['order_no']; + $erpData[$k]['createTime'] = date('Y-m-d H:i:s', $v['created_at']); + $erpData[$k]['userId'] = $v['store']['erp_id']; + $erpData[$k]['orderStatus'] = $v['status']; + $erpData[$k]['totalAmount'] = $v['total_pay_price']; + // $erpData[$k]['deliveryAmount'] = $v['trans_expenses']; + if($v['delivery_method'] == 1){ //到店自取 + $prescriptionContent = Json::decode($v['prescription']['content']); + $erpData[$k]['deliveryName'] = $prescriptionContent['patient']['name']; + $erpData[$k]['deliveryMobile'] = $prescriptionContent['patient']['mobile']; + $erpData[$k]['deliveryAddress'] = $v['store']['position']; + } else {//快递到家 + $erpData[$k]['deliveryName'] = $v['express_name']; + $erpData[$k]['deliveryMobile'] = $v['express_mobile']; + $erpData[$k]['deliveryAddress'] = $v['express_region'].$v['express_address']; + } + + $orderItems = []; + foreach($v['orderItems'] as $vk=>$vv){ + // $drug = Drug::findOne($vv['drug_id']); + $orderItems[$vk] = [ + 'detailId' => $vv['id'], + 'productSku' => $vv['drug_no'], + 'quantity' => $vv['number'], + 'paymentPrice' => $vv['price'], + 'price' => round($vv['number'] * $vv['price'], 2) + ]; + } + $erpData[$k]['orderItems'] = $orderItems; + $ids[]=$v['id']; + } + if(!empty($ids)){ + //更新为已同步erp + \Yii::$app->db->createCommand()->update('yii_product_order', [ + 'is_sync_erp' => 1 + ], ['in', 'id',$ids])->execute(); + } + + + ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单结束,拉取订单数量:'.count($productOrders).', 拉取的订单ids:'.implode(',',$ids)); + } catch (\Exception $e) { + ProductOrderLog::saveLog(0,'江奥川ERP拉取西(中成)药订单异常:'.$e->getMessage()); + throw new Exception('获取处方异常'.$e->getMessage()); + } + + return $erpData; + } + + /** + * @author: liudiao + * @Date: 2023-08-01 14:10:45 + * @Description: erp发货推送物流信息 + * @return {*} + */ + public function actionExpressNotify(){ + ProductOrderLog::saveLog(0,'江奥川ERP发货推送订单物流信息开始'); + $t = \Yii::$app->db->beginTransaction(); + try { + $headers = \Yii::$app->request->getHeaders(); + $secret = $headers->get('secret'); + $jacErpConfig = \Yii::$app->params['jac_erp']; + if($secret != $jacErpConfig['secret']){ + throw new Exception('非法请求'); + } + $rawData = \Yii::$app->request->rawBody; + $post = Json::decode($rawData); + + if(!$post['order_type'] || !$post['order_no'] || !$post['express_company'] || !$post['express_no'] || !$post['express_mobile']){ + throw new Exception('order_type/order_no/express_company/express_no/express_mobile不能为空'); + } + + if(!in_array($post['express_company'], ['邮政快递','顺丰速运'])){ + throw new Exception('仅支持顺丰速运和邮政快递'); + } + + if($post['order_type'] == 1){ //中药/颗粒药 order_no为处方号 + $prescription = Prescription::find()->where(['prescription_no' => $post['order_no']])->one(); + if(empty($prescription)){ + throw new Exception('订单不存在'); + } + $productOrder = ProductOrder::find()->where(['p_id' =>$prescription->id, 'status' => 1])->one(); + } else { + $productOrder = ProductOrder::find()->where(['order_no' =>$post['order_no'], 'status' => 1])->one(); + } + if(!$productOrder){ + throw new Exception('订单不存在.'); + } + + //快递单号信息 + $ExpressNos = new ExpressNos(); + $ExpressNos->express_company_name = $post['express_company']; + $ExpressNos->express_company_code = $post['express_company'] == '邮政快递' ? 'youzhengguonei' : 'shunfeng'; + $ExpressNos->express_no = $post['express_no']; + $ExpressNos->mobile = $post['express_mobile']; + $ExpressNos->state = null; + $ExpressNos->sync_at = null; + $ExpressNos->created_at = date('Y-m-d H:i:s', time()); + $ExpressNos->updated_at = date('Y-m-d H:i:s', time()); + $ExpressNos->saveOrFail(); + + //更新订单为发货状态 + $productOrder->is_send = 1; + $productOrder->status = 2; + $productOrder->send_time = date('Y-m-d H:i:s', time()); + $productOrder->express_no_id = $ExpressNos->id; + $productOrder->saveOrFail(); + + //订单发货订阅消息通知 + \Yii::$app->queue->push(new ProductOrderSend([ + 'orderId' => $productOrder->id, + ])); + + //订单发货后分账结算 + if($productOrder->type == 2){ //易票联支付的产品订单 + $config = \Yii::$app->params; + $orderAutoSettlementTime = isset($config['product_order']['settlement_time']) ? $config['product_order']['settlement_time'] : 72*3600; + \Yii::$app->queue->delay($orderAutoSettlementTime)->push(new ProductOrderSendJob([ + 'orderId' => $productOrder->id + ])); + } + + $t->commit(); + + //获取最新快递信息 + (new Client(['http_errors' => false]))->get("https://shop.xiaokang88.com/t/express_update", [ + 'query' => [ + 'id' => $ExpressNos->id, + ], + ]); + + ProductOrderLog::saveLog(0,'江奥川ERP发货推送订单物流信息成功,:订单id'.$productOrder->id); + + return ['success']; + } catch (\Exception $e) { + $t->rollBack(); + ProductOrderLog::saveLog(0,'江奥川ERP发货推送订单物流信息异常:'.$e->getMessage()); + throw new Exception($e->getMessage()); + } + + } +} \ No newline at end of file diff --git a/platform/modules/v1/controllers/SyncController.php b/platform/modules/v1/controllers/SyncController.php new file mode 100644 index 0000000..472e89c --- /dev/null +++ b/platform/modules/v1/controllers/SyncController.php @@ -0,0 +1,51 @@ +request->post(); + + $syncPatientForm = new SyncPatientForm(); + $syncPatientForm->attributes = $post; + return $syncPatientForm->save(); + } + + + /** + * @doc-name 就诊人信息删除同步 + * @doc-return mixed 同步结果 + */ + public function actionPatientDelete() + { + $post = \Yii::$app->request->post(); + + $userPatient = UserPatient::findOne(['user_id'=>$post['user_id'],'id_card'=>$post['id_card'],'is_delete' => 0]); + if(!$userPatient){ + throw new Exception('就诊人信息错误,无法进行该操作'); + } + + try { + UserPatient::updateAll(['is_delete' => 1],['id' => $userPatient->id]); + } catch (\Throwable $th) { + throw new Exception('删除失败'); + } catch (\Exception $e) { + throw new Exception('删除失败'); + } + return ['删除同步成功']; + } +} \ No newline at end of file diff --git a/requirements.php b/requirements.php new file mode 100644 index 0000000..67b344b --- /dev/null +++ b/requirements.php @@ -0,0 +1,155 @@ +Error\n\n" + . "

The path to yii framework seems to be incorrect.

\n" + . '

You need to install Yii framework via composer or adjust the framework path in file ' . basename(__FILE__) . ".

\n" + . '

Please refer to the README on how to install Yii.

\n"; + if (!empty($_SERVER['argv'])) { + // do not print HTML when used in console mode + echo strip_tags($message); + } else { + echo $message; + } + exit(1); +} + +require_once $frameworkPath . '/requirements/YiiRequirementChecker.php'; +$requirementsChecker = new YiiRequirementChecker(); + +$gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.'; +$gdOK = $imagickOK = false; + +if (extension_loaded('imagick')) { + $imagick = new Imagick(); + $imagickFormats = $imagick->queryFormats('PNG'); + if (in_array('PNG', $imagickFormats)) { + $imagickOK = true; + } else { + $imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.'; + } +} + +if (extension_loaded('gd')) { + $gdInfo = gd_info(); + if (!empty($gdInfo['FreeType Support'])) { + $gdOK = true; + } else { + $gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.'; + } +} + +/** + * Adjust requirements according to your application specifics. + */ +$requirements = array( + // Database : + array( + 'name' => 'PDO extension', + 'mandatory' => true, + 'condition' => extension_loaded('pdo'), + 'by' => 'All DB-related classes', + ), + array( + 'name' => 'PDO SQLite extension', + 'mandatory' => false, + 'condition' => extension_loaded('pdo_sqlite'), + 'by' => 'All DB-related classes', + 'memo' => 'Required for SQLite database.', + ), + array( + 'name' => 'PDO MySQL extension', + 'mandatory' => false, + 'condition' => extension_loaded('pdo_mysql'), + 'by' => 'All DB-related classes', + 'memo' => 'Required for MySQL database.', + ), + array( + 'name' => 'PDO PostgreSQL extension', + 'mandatory' => false, + 'condition' => extension_loaded('pdo_pgsql'), + 'by' => 'All DB-related classes', + 'memo' => 'Required for PostgreSQL database.', + ), + // Cache : + array( + 'name' => 'Memcache extension', + 'mandatory' => false, + 'condition' => extension_loaded('memcache') || extension_loaded('memcached'), + 'by' => 'MemCache', + 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached to true.' : '' + ), + array( + 'name' => 'APC extension', + 'mandatory' => false, + 'condition' => extension_loaded('apc'), + 'by' => 'ApcCache', + ), + // CAPTCHA: + array( + 'name' => 'GD PHP extension with FreeType support', + 'mandatory' => false, + 'condition' => $gdOK, + 'by' => 'Captcha', + 'memo' => $gdMemo, + ), + array( + 'name' => 'ImageMagick PHP extension with PNG support', + 'mandatory' => false, + 'condition' => $imagickOK, + 'by' => 'Captcha', + 'memo' => $imagickMemo, + ), + // PHP ini : + 'phpExposePhp' => array( + 'name' => 'Expose PHP', + 'mandatory' => false, + 'condition' => $requirementsChecker->checkPhpIniOff("expose_php"), + 'by' => 'Security reasons', + 'memo' => '"expose_php" should be disabled at php.ini', + ), + 'phpAllowUrlInclude' => array( + 'name' => 'PHP allow url include', + 'mandatory' => false, + 'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"), + 'by' => 'Security reasons', + 'memo' => '"allow_url_include" should be disabled at php.ini', + ), + 'phpSmtp' => array( + 'name' => 'PHP mail SMTP', + 'mandatory' => false, + 'condition' => strlen(ini_get('SMTP')) > 0, + 'by' => 'Email sending', + 'memo' => 'PHP mail SMTP server required', + ), +); + +$result = $requirementsChecker->checkYii()->check($requirements)->getResult(); +$requirementsChecker->render(); + +exit($result['summary']['errors'] === 0 ? 0 : 1); diff --git a/service/Dockerfile b/service/Dockerfile new file mode 100644 index 0000000..a0487d2 --- /dev/null +++ b/service/Dockerfile @@ -0,0 +1,4 @@ +FROM yiisoftware/yii2-php:8.1-apache + +# Change document root for Apache +RUN sed -i -e 's|/app/web|/app/frontend/web|g' /etc/apache2/sites-available/000-default.conf diff --git a/service/codeception.yml b/service/codeception.yml new file mode 100644 index 0000000..5d3ed5d --- /dev/null +++ b/service/codeception.yml @@ -0,0 +1,15 @@ +namespace: frontend\tests +actor_suffix: Tester +paths: + tests: tests + output: tests/_output + data: tests/_data + support: tests/_support +bootstrap: _bootstrap.php +settings: + colors: true + memory_limit: 1024M +modules: + config: + Yii2: + configFile: 'config/codeception-local.php' diff --git a/service/config/.gitignore b/service/config/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/service/config/bootstrap.php b/service/config/bootstrap.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/service/config/bootstrap.php @@ -0,0 +1 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => 'BF4x_c1AGvBAUxSfdxLhWh6fUq51A_Uc', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => \yii\debug\Module::class, + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => \yii\gii\Module::class, + ]; +} + +return $config; diff --git a/service/config/main.php b/service/config/main.php new file mode 100644 index 0000000..aab8ed8 --- /dev/null +++ b/service/config/main.php @@ -0,0 +1,67 @@ + 'app-service', + 'basePath' => dirname(__DIR__), + 'bootstrap' => ['log'], + 'controllerNamespace' => 'service\controllers', + 'modules' => [ + 'v1' => [ + 'class' => 'service\modules\v1\Module', + ], + 'doc'=>[ + 'class' => 'cfd\doc\Module', + 'modelsMap'=>[ + '\common\models\\', + '\common\modelsgii\\', + ] + ], + ], + 'components' => [ + 'request' => [ + 'csrfParam' => '_csrf-service', + ], + 'response' => [ + 'class' => 'yii\web\Response', + 'format' => \yii\web\Response::FORMAT_JSON, + 'formatters' => [ + \yii\web\Response::FORMAT_JSON => [ + 'class' => 'common\foundation\JsonResponseFormatter', + 'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode + 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, + ], + ], + ], + 'user' => [ + 'identityClass' => 'service\models\ServiceUser', + 'enableAutoLogin' => true, + 'enableSession'=>false, + ], + 'log' => [ + 'traceLevel' => YII_DEBUG ? 3 : 0, + 'targets' => [ + [ + 'class' => \yii\log\FileTarget::class, + 'levels' => ['error', 'warning','info'], + 'categories' => ['yii\db\*'] + ], + ], + ], +// 'errorHandler' => [ +// 'errorAction' => 'site/error', +// ], + 'urlManager' => [ + 'enablePrettyUrl' => true, + 'showScriptName' => false, + 'rules' => [ + ], + ], + ], + 'params' => $params, +]; diff --git a/service/config/params-local.php b/service/config/params-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/service/config/params-local.php @@ -0,0 +1,4 @@ + 'admin@example.com', +]; diff --git a/service/config/test-local.php b/service/config/test-local.php new file mode 100644 index 0000000..b625128 --- /dev/null +++ b/service/config/test-local.php @@ -0,0 +1,4 @@ + 'app-frontend-tests', + 'components' => [ + 'assetManager' => [ + 'basePath' => __DIR__ . '/../web/assets', + ], + 'urlManager' => [ + 'showScriptName' => true, + ], + 'request' => [ + 'cookieValidationKey' => 'test', + ], + 'mailer' => [ + 'messageClass' => \yii\symfonymailer\Message::class + ] + ], +]; diff --git a/service/models/ServiceUser.php b/service/models/ServiceUser.php new file mode 100644 index 0000000..f85a802 --- /dev/null +++ b/service/models/ServiceUser.php @@ -0,0 +1,82 @@ + $id]); + } + + public static function findIdentityByAccessToken($token, $type = null) + { + $checkToken = ServiceUserToken::checkToken($token); + if(!$checkToken){ + return false; + } + $su_id = $checkToken->su_id; + $su = static::findOne($su_id); + if(!$su_id || !$su || $su->is_delete){ + return false; + } + + self::$token = $token; + return $su; + } + + /** + * 验证密码 + * + * @param string $password password to validate + * @return boolean if password provided is valid for current user + */ + public function validatePassword($password) + { + return Yii::$app->security->validatePassword($password, $this->password); + } + + /** + * 设置加密后的密码 + * + * @param string $password + */ + public function setPassword($password) + { + $this->password = Yii::$app->security->generatePasswordHash($password); + } + + public function getId() + { + return $this->id; + } + + /** + * --------------------------------------- + * 获取密码干扰字符串 + * @return string + * --------------------------------------- + */ + public function getAuthKey() + { + return $this->salt; + } + + /** + * --------------------------------------- + * 验证 + * @param string $authKey + * @return bool + * --------------------------------------- + */ + public function validateAuthKey($authKey) + { + return $this->getAuthKey() === $authKey; + } +} diff --git a/service/models/forms/AgreementForm.php b/service/models/forms/AgreementForm.php new file mode 100644 index 0000000..47b6ec0 --- /dev/null +++ b/service/models/forms/AgreementForm.php @@ -0,0 +1,43 @@ + '区分端', + ]; + } + + public function getAgreement() + { + if (!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + return BaseConfig::find() + ->where([ + 'end' => $this->end, + 'status' => 0, + 'store_id'=>\Yii::$app->store + ])->andWhere(['type'=>[1,2]]) + ->select(['content', 'change_at']) + ->orderBy(['change_at' => SORT_DESC]) + ->all(); + } +} \ No newline at end of file diff --git a/service/models/forms/CaseForm.php b/service/models/forms/CaseForm.php new file mode 100644 index 0000000..d26a3e6 --- /dev/null +++ b/service/models/forms/CaseForm.php @@ -0,0 +1,93 @@ +validate()) { + throw new Exception($this->getErrorMsg()); + } + $today = strtotime(date('Y-m-d', time())); + $end = $today + 60 * 60 * 24; + + $UserPatientCase = UserPatientCase::find()->where([ + 'user_patient_id' => $this->user_patient_id, + 'register_id' => $this->register_id, + 'store_id' => \Yii::$app->store, + 'service_user_id' => \Yii::$app->user->id, + 'is_delete' => 0 + ])->andWhere(['between', 'created_at', $today, $end])->one(); + + try { + if (!$UserPatientCase) { + $UserPatientCase = new UserPatientCase(); + } + $UserPatientCase->store_id = \Yii::$app->store; + $UserPatientCase->service_user_id = \Yii::$app->user->id; + $UserPatientCase->created_at =time(); + $UserPatientCase->updated_at =time(); + $UserPatientCase->attributes = $this->attributes; + + + $UserPatientCase->saveOrFail(); + } catch (\Exception $e) { + throw new Exception($e->getMessage()); + } + } + + public function update() + { + + } + + public function info() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + + $UserPatientCase = UserPatientCase::find()->where([ + 'register_id' => $this->register_id, + 'user_patient_id' => $this->user_patient_id, + 'is_delete' => 0, + 'service_user_id' => \Yii::$app->user->id, + 'store_id' => \Yii::$app->store, + ])->with(['userPatient'])->asArray()->all(); + + if (!$UserPatientCase) throw new Exception('病历不存在'); + + return $UserPatientCase; + } + +} \ No newline at end of file diff --git a/service/models/forms/DoctorCompleteFour.php b/service/models/forms/DoctorCompleteFour.php new file mode 100644 index 0000000..f7f4173 --- /dev/null +++ b/service/models/forms/DoctorCompleteFour.php @@ -0,0 +1,83 @@ +0], + ['register_price','match', 'pattern' => '/^\d+(\.\d{1,2})?$/i','message'=>'挂号价格最多两位小数'] + ]; + } + public function attributeLabels() + { + return [ + 'register_status' => '是否开启挂号服务0否1是', + 'register_price' => '挂号价格', + ]; + } + + public function save() + { + if(!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $serviceUser = ServiceUser::find()->where([ + 'id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->with('docInfo','docIdentity','docPracticing')->one(); + if(!$serviceUser){ + throw new Exception('用户不存在'); + } + if(!$serviceUser->docInfo || !$serviceUser->docIdentity || !$serviceUser->docPracticing){ + throw new Exception('请先完善前几步信息'); + } + $su_id=\Yii::$app->user->identity->id; + + $t = \Yii::$app->db->beginTransaction(); + try { + $model = DoctorService::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + if(!$model){ + $model = new DoctorService(); + $model->su_id =$su_id; + } + $model->attributes = $this->attributes; + + $model->saveOrFail(); + + //第四步完成后需要修改账户的激活状态未待审核 - 后台审核 - 已认证 + //后台拒绝 - 前台修改资料 - 提交 - 重新待审核 + + $user = \Yii::$app->user->identity; + $user->status = UserStatusEnum::WAIT_SH; + $user->reason =null; + $user->saveOrFail(); + + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + file_put_contents('error.log',$exception->getMessage().PHP_EOL,FILE_APPEND); + throw $exception; + } + return ['已完善服务信息']; + } + + +} diff --git a/service/models/forms/DoctorCompleteOne.php b/service/models/forms/DoctorCompleteOne.php new file mode 100644 index 0000000..617623e --- /dev/null +++ b/service/models/forms/DoctorCompleteOne.php @@ -0,0 +1,131 @@ + '/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/i'], + ['idcard', 'checkCard'], + [['good_at','intro'], 'string', 'max' => 500], + ]; + } + + public function checkCard($attribute, $params) + { + $response = (new Client(['http_errors' => false]))->post("https://eid.shumaidata.com/eid/check", [ + 'headers' => ['Authorization' =>"APPCODE f98bba3251714c759f5bd29d00e1c46e"], + 'query' => [ + 'idcard' => $this->idcard, + 'name' => $this->name + ], + ]); + $result = json_decode($response->getBody(),true); + if(!($result['code']==0 && $result['result']['res']==1)){ + $this->addError($attribute, '身份证名字不匹配'); + } + } + + public function attributeLabels() + { + return [ + 'name' => '姓名', + 'avatar' => '头像', + 'mobile' => '手机号', + 'idcard' => '身份证号', + 'store_id' => '门店', + 'depart_id' => '科室', + 'identity' => '身份', + 'title_id' => '职称', + 'good_at' => '擅长', + 'intro' => '个人简介', + ]; + } + + public function save() + { + if(!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $su_id=\Yii::$app->user->identity->getId(); + + $model = DoctorInfo::find()->where([ + 'su_id' => $su_id, + ])->one(); + + + $t=\Yii::$app->db->beginTransaction(); + try + { + if(!$model){//新增 + $model = new DoctorInfo(); + $model->su_id = $su_id; + + $docinfo=DoctorInfo::find()->where(['idcard'=>$this->idcard,'is_delete'=>0])->one(); + $pharmacistrInfo=PharmacistrInfo::find()->where(['idcard'=>$this->idcard])->one(); + if ($pharmacistrInfo){ + throw new \yii\db\Exception('您的身份证不能同时注册医生和药师'); + } + if ($docinfo){ + throw new \yii\db\Exception('您的身份证已经注册过医生了'); + } + } + + + $model->attributes = $this->attributes; + $model->saveOrFail(); + + $store= Json::decode($this->store_id,true); + foreach ($store as $value){ + $store=Store::find()->where(['id'=>$value])->one(); + if ($store){ + if (!StoreDoctor::find()->where([ + 'su_id'=>$su_id, + 'store_id'=>$value + ])->one()) + { + $StoreDoctor=new StoreDoctor(); + $StoreDoctor->store_id=$value; + $StoreDoctor->su_id=$su_id; + $StoreDoctor->last_login_time=time(); + $StoreDoctor->saveOrFail(); + } + } + } + + $t->commit(); + return ['已完善基本信息']; + } + catch (\Exception $e){ + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } +} \ No newline at end of file diff --git a/service/models/forms/DoctorServiceForm.php b/service/models/forms/DoctorServiceForm.php new file mode 100644 index 0000000..117de33 --- /dev/null +++ b/service/models/forms/DoctorServiceForm.php @@ -0,0 +1,71 @@ +0], + [['register_price'],'number','min'=>0], + ['register_price','match', 'pattern' => '/^\d+(\.\d{1,2})?$/i','message'=>'挂号费价格最多两位小数'] + ]; + } + public function attributeLabels() + { + return [ + 'register_status' => '开通挂号', + 'register_price' => '挂号费' + ]; + } + + public function save() + { + if(!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $serviceUser = ServiceUser::find()->where([ + 'id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->with('docInfo','docIdentity','docPracticing')->one(); + + if(!$serviceUser){ + throw new Exception('用户不存在'); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $model = DoctorService::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + + if(!$model){ + $model = new DoctorService(); + $model->su_id = \Yii::$app->user->identity->id; + } + $model->attributes = $this->attributes; + $model->saveOrFail(); + + $user = \Yii::$app->user->identity; + $user->saveOrFail(); + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + return []; + } + + +} diff --git a/service/models/forms/DrugCompleteOne.php b/service/models/forms/DrugCompleteOne.php new file mode 100644 index 0000000..8843726 --- /dev/null +++ b/service/models/forms/DrugCompleteOne.php @@ -0,0 +1,97 @@ + '/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/i'], + ['idcard', 'checkCard'], + ]; + } + + public function checkCard($attribute, $params) + { + $response = (new Client(['http_errors' => false]))->post("https://eid.shumaidata.com/eid/check", [ + 'headers' => ['Authorization' =>"APPCODE f98bba3251714c759f5bd29d00e1c46e"], + 'query' => [ + 'idcard' => $this->idcard, + 'name' => $this->name + ], + ]); + $result = json_decode($response->getBody(),true); + if(!($result['code']==0 && $result['result']['res']==1)){ + $this->addError($attribute, '身份证名字不匹配'); + } + } + + public function attributeLabels() + { + return [ + 'name' => '姓名', + 'avatar' => '头像', + 'mobile' => '手机号', + 'idcard' => '身份证号', + 'store_id' => '门店id', + 'title_id' => '职称', + 'type' => '身份类型1中医药师 2西医药师', + ]; + } + + public function save() + { + if(!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + $model = PharmacistrInfo::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + $t=\Yii::$app->db->beginTransaction(); + if(!$model){ + $model = new PharmacistrInfo(); + $model->su_id = \Yii::$app->user->identity->id; + + $docinfo=DoctorInfo::find()->where(['idcard'=>$this->idcard,'is_delete'=>0])->one(); + $pharmacistrInfo=PharmacistrInfo::find()->where(['idcard'=>$this->idcard])->one(); + if ($pharmacistrInfo){ + throw new \yii\db\Exception('您已经注册过药师了'); + } + if ($docinfo){ + throw new \yii\db\Exception('您的身份证不能同时注册医生和药师'); + } + } + + $model->attributes = $this->attributes; + if (!$model->saveOrFail()){ + $t->rollBack(); + } + + $t->commit(); + return ['已完善基础信息']; + } + + +} \ No newline at end of file diff --git a/service/models/forms/HospitalDocForm.php b/service/models/forms/HospitalDocForm.php new file mode 100644 index 0000000..80e49da --- /dev/null +++ b/service/models/forms/HospitalDocForm.php @@ -0,0 +1,230 @@ +user->identity->getId(); + $store = \Yii::$app->store; + ServiceUser::find()->where([ + 'id' => $su_id, + 'role' => UserRoleEnum::DOCTOR, + 'is_delete' => 0, + ])->one(); + + $sql = "select * from yii_doctor_platform where platform_doctor_id=$su_id and platform_store_id=$store"; + $doctor_is_exist = \Yii::$app->db1->createCommand($sql)->queryOne(); + if (!$doctor_is_exist){ + throw new Exception('您还没成为互医'); + } + + $doctor_id = $doctor_is_exist['su_id']; + + $doctor_info = "select * from yii_doctor_info where su_id=$doctor_id"; + $doctor_info_exist = \Yii::$app->db1->createCommand($doctor_info)->queryOne(); + + $doctor_identity = "select * from yii_doctor_identity where su_id=$doctor_id"; + $doctor_identity_exist = \Yii::$app->db1->createCommand($doctor_identity)->queryOne(); + + $doctor_practicing = "select * from yii_doctor_practicing where su_id=$doctor_id"; + $doctor_practicing_exist = \Yii::$app->db1->createCommand($doctor_practicing)->queryOne(); + + $doctor_service = "select * from yii_doctor_service where su_id=$doctor_id"; + $doctor_service_exist = \Yii::$app->db1->createCommand($doctor_service)->queryOne(); + + return [ + 'doctor'=>$doctor_is_exist, + 'doctor_info'=>$doctor_info_exist, + 'doctor_identity'=>$doctor_identity_exist, + 'doctor_practicing'=>$doctor_practicing_exist, + 'doctor_service'=>$doctor_service_exist + ]; + } + + /** + * 升级为互医 + */ + public function grade() + { + $su_id = \Yii::$app->user->identity->getId(); + $store = \Yii::$app->store; + + $ServiceUser = ServiceUser::find()->where([ + 'id' => $su_id, + 'role' => UserRoleEnum::DOCTOR, + 'is_delete' => 0, + 'plate_type'=>2 //萧康的医生 + ])->one(); + if (!$ServiceUser){ + throw new Exception('萧康不存在该医生'); + } + if (!$ServiceUser->docIdentity || !$ServiceUser->docPracticing || !$ServiceUser->docInfo || !$ServiceUser->docService) + throw new Exception('请完善基本信息'); + + try { + $t = \Yii::$app->db1->beginTransaction(); + $token = \Yii::$app->security->generateRandomString() . '_' . time(); + $mobile=$ServiceUser['mobile']; + + $sql="select * from yii_service_user where mobile=$mobile"; + $is_exist=\Yii::$app->db1->createCommand($sql)->queryOne(); + $id=$is_exist['id']; + + if (!$is_exist){ + \Yii::$app->db1->createCommand()->insert('yii_service_user',[ + 'mobile'=>$mobile, + 'role'=>UserRoleEnum::DOCTOR, + 'status'=>UserStatusEnum::WAIT_JH, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + $last_id=\Yii::$app->db1->getLastInsertID(); + \Yii::$app->db1->createCommand()->insert('yii_service_user_token',[ + 'su_id'=>$last_id, + 'token'=>$token, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + } + + $service_id=$id??$last_id; + + $sql_platform="select * from yii_doctor_platform where su_id=$service_id and platform_doctor_id=$su_id and platform_store_id=$store"; + $doctor_platform=\Yii::$app->db1->createCommand($sql_platform)->queryOne(); + + if (!$doctor_platform){ + //用户平台关系表 + \Yii::$app->db1->createCommand()->insert('yii_doctor_platform',[ + 'su_id'=>$service_id, + 'platform_doctor_id'=>$su_id, + 'platform_id'=>1, + 'platform_store_id'=>\Yii::$app->store, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + } + $t->commit(); + }catch (\Exception $e){ + $t->rollback(); + throw new Exception($e->getMessage()); + } + + $info=$this->DocInfo(); + + if (!$info['doctor'] || !$info['doctor_info'] || !$info['doctor_identity'] || !$info['doctor_practicing'] || !$info['doctor_service']) + { + $transaction = \Yii::$app->db1->beginTransaction(); + try { + \Yii::$app->db1->createCommand()->insert('yii_doctor_info', [ + 'su_id' => $service_id, + 'avatar' => $ServiceUser->docInfo->avatar, + 'name' => $ServiceUser->docInfo->name, + 'mobile' => $ServiceUser->docInfo->mobile, + 'idcard' => $ServiceUser->docInfo->idcard, + 'depart_id' => $ServiceUser->docInfo->depart_id, + 'hospital_id' => $ServiceUser->docInfo->hospital_id, + 'yard_id' => $ServiceUser->docInfo->yard_id, + 'title_id' => $ServiceUser->docInfo->title_id, + 'good_at' => $ServiceUser->docInfo->good_at, + 'intro' => $ServiceUser->docInfo->intro, + 'created_at' => time(), + 'updated_at' => time(), + ])->execute(); + \Yii::$app->db1->createCommand()->insert('yii_doctor_identity', [ + 'su_id' => $service_id, + 'card_up' => $ServiceUser->docIdentity->card_up, + 'card_down' => $ServiceUser->docIdentity->card_down, + 'work_avator' => $ServiceUser->docIdentity->work_avator, + 'sign_type' => $ServiceUser->docIdentity->sign_type, + 'sign_image' => $ServiceUser->docIdentity->sign_image, + 'created_at' => time(), + 'updated_at' => time(), + ])->execute(); + \Yii::$app->db1->createCommand()->insert('yii_doctor_practicing', [ + 'su_id' => $service_id, + 'qualification' => $ServiceUser->docPracticing->qualification, + 'practicing' => $ServiceUser->docPracticing->practicing, + 'title' => $ServiceUser->docPracticing->title, + 'created_at' => time(), + 'updated_at' => time(), + ])->execute(); + \Yii::$app->db1->createCommand()->insert('yii_doctor_service', [ + 'su_id' => $service_id, + 'register_status' => $ServiceUser->docService->register_status, + 'register_price' => $ServiceUser->docService->register_price, + 'created_at' => time(), + 'updated_at' => time(), + ])->execute(); + + + $this->SyncPatient();//同步患者 + + $transaction->commit(); + return ['信息已同步']; + } catch (\Exception $e) { + $transaction->rollback(); + throw new Exception($e->getMessage()); + } + } + return ['您已在互医注册过并已完善相关信息']; + } + + public function SyncPatient() + { + $su_id=\Yii::$app->user->identity->getId(); + $store=\Yii::$app->store; + $patient=DoctorPatient::find()->where([ + 'su_id'=>$su_id, + ])->all(); + + $sql = "select * from yii_doctor_platform where platform_doctor_id=$su_id and platform_store_id=$store"; + $doctor_is_exist = \Yii::$app->db1->createCommand($sql)->queryOne(); + if (!$doctor_is_exist){ + throw new Exception('您还没成为互医'); + } + + $rows=[]; + foreach ($patient as $value){ + $rows[]=[ + 'su_id'=>$doctor_is_exist['su_id'], + 'user_id'=>$value['user_id'], + 'up_id'=>$value['up_id'], + 'name'=>$value['name'], + 'avatar'=>$value['avatar'], + 'id_card'=>$value['id_card'], + 'sex'=>$value['sex'], + 'mobile'=>$value['mobile'], + 'created_at' => time(), + 'updated_at' => time(), + ]; + } + + \Yii::$app->db1->createCommand()->batchInsert('yii_doctor_patient', ['su_id','user_id','up_id','name','avatar','id_card','sex','mobile','created_at','updated_at'],$rows)->execute(); + + return ['患者同步成功']; + } +} diff --git a/service/models/forms/LeadCompleteOne.php b/service/models/forms/LeadCompleteOne.php new file mode 100644 index 0000000..7b07aae --- /dev/null +++ b/service/models/forms/LeadCompleteOne.php @@ -0,0 +1,101 @@ + '/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/i'], + ['id_card', 'checkCard'], + ]; + } + + public function checkCard($attribute, $params) + { + $response = (new Client(['http_errors' => false]))->post("https://eid.shumaidata.com/eid/check", [ + 'headers' => ['Authorization' =>"APPCODE f98bba3251714c759f5bd29d00e1c46e"], + 'query' => [ + 'idcard' => $this->idcard, + 'name' => $this->name + ], + ]); + $result = json_decode($response->getBody(),true); + if(!($result['code']==0 && $result['result']['res']==1)){ + $this->addError($attribute, '身份证名字不匹配'); + } + } + + public function attributeLabels() + { + return [ + 'name' => '姓名', + 'avatar' => '头像', + 'mobile' => '手机号', + 'idcard' => '身份证号', + 'hospital_id' => '医院id', + 'yard_id' => '院区', + 'depart_id' => '科室', + 'title_id' => '职称', + 'card_up' => '身份证正面', + 'card_down' => '身份证反面' + ]; + } + + public function save() + { + if(!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $model = LeadInfo::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + if(!$model){ + $model = new LeadInfo(); + $model->su_id = \Yii::$app->user->identity->id; + } + $model->attributes = $this->attributes; + $model->saveOrFail(); + + //修改状态 + $user = \Yii::$app->user->identity; + $user->status = UserStatusEnum::WAIT_SH; + $user->saveOrFail(); + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + + return []; + } + + +} \ No newline at end of file diff --git a/service/models/forms/LoginForm.php b/service/models/forms/LoginForm.php new file mode 100644 index 0000000..6c6524d --- /dev/null +++ b/service/models/forms/LoginForm.php @@ -0,0 +1,478 @@ + '状态', + 'role' => '角色', + 'code' => '微信code', + 'mobile' => '手机号', + 'smsCode' => '验证码', + ]; + } + + public function userlogin() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + switch ($this->status) { + case 1;//1微信登录 + if (!$this->code) { + throw new Exception('微信code不能为空'); + } + if (!$this->plate_type) { + throw new Exception('平台plate_type不能为空'); + } + return $this->login(); + + case 3://3手机号登录 + if (!$this->mobile) { + throw new Exception('mobile不能为空'); + } + + if (!$this->smsCode) throw new Exception('验证码不能为空'); + return $this->phoneLogin(); + + case 4://4手机号注册 + if (!$this->plate_type) { + throw new Exception('平台plate_type不能为空'); + } + if (!$this->mobile) { + throw new Exception('mobile不能为空'); + } + if (!$this->role) { + throw new Exception('role不能为空'); + } + + if (!$this->smsCode) throw new Exception('验证码不能为空'); + return $this->PhoneRegister(); + case 5: // 开发登陆 + if (!YII_DEBUG) { + return []; + } + if (!$this->mobile) { + throw new Exception('mobile不能为空'); + } + $ServiceUser = ServiceUser::findOne(['mobile' => $this->mobile]); + if (!$ServiceUser) { + throw new Exception('用户不存在'); + } + + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $ServiceUser->id; + $token = \Yii::$app->security->generateRandomString() . '_' . time(); + $ServiceUserToken->token = $token; + $ServiceUserToken->saveOrFail(); + + $StoreDoctor = StoreDoctor::find()->where([ + 'su_id' => $ServiceUser->id, + 'is_delete' => 0, + ])->one(); + + if (!$StoreDoctor){ + throw new Exception('您还没有门店,请先去完善信息'); + } + //更新登录时间 + $StoreDoctor->su_id = $ServiceUser->id; + $StoreDoctor->id = $StoreDoctor->id; + $StoreDoctor->store_id = $StoreDoctor->store_id; + $StoreDoctor->last_login_time = time(); + $StoreDoctor->is_delete = 0; + $StoreDoctor->saveOrFail(); + + return [ + 'token' => $token, + 'StoreDoctor' => $StoreDoctor, + ]; + } + } + + /** + * 微信登录 + */ + public function login() + { + $token = \Yii::$app->security->generateRandomString() . '_' . time(); + + $login = WechatService::getInstance()->app->auth->session($this->code); + if(isset($login['errmsg'])){ + throw new Exception($login['errmsg']); + } + $ServiceUser = ServiceUser::findOne(['openid' => $login['openid']]); + + switch ($this->plate_type){ + //线上 + case 1: + try { + $transaction = \Yii::$app->db->beginTransaction(); + if (!$ServiceUser) { + $ServiceUser = new ServiceUser(); + } + $ServiceUser->openid = $login['openid']; + $ServiceUser->session_key = $login['session_key']; + $ServiceUser->unionid = isset($login['unionid']) ? $login['unionid'] : ''; + $ServiceUser->nickname = $ServiceUser['nickname'] ?? '微信用户'; + $ServiceUser->plate_type = $this->plate_type; + $ServiceUser->role=UserRoleEnum::DOCTOR; + $ServiceUser->saveOrFail(); + + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $ServiceUser->id; + $ServiceUserToken->token = $token; + $ServiceUserToken->saveOrFail(); + $transaction->commit(); + }catch (\Exception $e){ + $transaction->rollBack(); + throw new Exception($e->getMessage()); + } + + try { + $t = \Yii::$app->db1->beginTransaction(); + \Yii::$app->db1->createCommand()->insert('yii_service_user',[ + 'role'=>UserRoleEnum::DOCTOR, + 'status'=>UserStatusEnum::WAIT_JH, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + $su_id=\Yii::$app->db1->getLastInsertID(); + \Yii::$app->db1->createCommand()->insert('yii_service_user_token',[ + 'su_id'=>$su_id, + 'token'=>$token, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + + $sql="select * from yii_doctor_platform where su_id=$su_id and platform_doctor_id=$ServiceUser->id"; + $is_exist=\Yii::$app->db1->createCommand($sql)->queryOne(); + $platform_id=1; + if (!$is_exist){ + //用户平台关系表 + \Yii::$app->db1->createCommand()->insert('yii_doctor_platform',[ + 'su_id'=>$su_id, + 'platform_doctor_id'=>$ServiceUser->id, + 'platform_id'=>$platform_id, + 'platform_store_id'=>\Yii::$app->store, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + } + $t->commit(); + }catch (\Exception $e){ + $t->rollBack(); + throw new Exception($e->getMessage()); + } + $StoreDoctor = StoreDoctor::find()->where([ + 'su_id' => $ServiceUser->id, + ])->with(['serviceUser']) + ->asArray()->one(); + return [ + 'token'=>$token, + 'data'=>$StoreDoctor + ]; + break; + //线下 + case 2: + $transaction = \Yii::$app->db->beginTransaction(); + try { + if (!$ServiceUser) { + $ServiceUser = new ServiceUser(); + } + if ($ServiceUser->status==UserStatusEnum::FORBID && $ServiceUser->role==UserRoleEnum::DOCTOR){ + throw new Exception('您的账号已停用,请联系后台工作人员!!'); + } + $ServiceUser->openid = $login['openid']; + $ServiceUser->session_key = $login['session_key']; + $ServiceUser->unionid = isset($login['unionid']) ? $login['unionid'] : ''; + $ServiceUser->nickname = $ServiceUser['nickname'] ?? '微信用户'; + $ServiceUser->plate_type = $this->plate_type; + $ServiceUser->role=UserRoleEnum::DOCTOR; + $ServiceUser->saveOrFail(); + + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $ServiceUser->id; + $ServiceUserToken->token = $token; + $ServiceUserToken->saveOrFail(); + + $StoreDoctor = StoreDoctor::find()->where([ + 'su_id' => $ServiceUser->id, + 'is_delete' => 0, + ])->one(); + if (!$StoreDoctor){ + throw new Exception('您还没有门店'); + } + + //更新门店登录时间 + $StoreDoctor->id=$StoreDoctor->id; + $StoreDoctor->last_login_time=time(); + $StoreDoctor->saveOrFail(); + + $transaction->commit(); + } catch (Exception $exception) { + $transaction->rollBack(); + throw new Exception('登录失败:' . $exception->getMessage() . ' APPID:' . WechatService::getInstance()->app->getConfig()['app_id']); + } + + $StoreDoctor = StoreDoctor::find()->where([ + 'su_id' => $ServiceUser->id, + ])->with(['serviceUser'])->asArray()->one(); + return [ + 'token'=>$token, + 'data'=>$StoreDoctor, + 'ServiceInfo'=>$ServiceUser + ]; + default: + throw new \yii\db\Exception('参数错误'); + } + } + + + /** + * 手机号登录 + */ + public function phoneLogin() + { + $cache = \Yii::$app->cache; + if ($cache->get('login_sms_code_'.$this->mobile) || $this->smsCode=='999999') { + if ($this->smsCode!='999999' && $cache->get('login_sms_code_'.$this->mobile) != $this->smsCode) { + throw new Exception('手机验证码错误'); + } + $t = \Yii::$app->db->beginTransaction(); + try { + $ServiceUser = ServiceUser::find()->where([ + 'mobile' => $this->mobile, + 'is_delete'=>0 + ])->one(); + if (!$ServiceUser) throw new Exception('您还没有注册,请先注册账号'); + if ($ServiceUser->status==UserStatusEnum::FORBID && $ServiceUser->role==UserRoleEnum::DOCTOR){ + throw new Exception('您的账号已停用,请联系后台工作人员!!'); + } + + $ServiceUser->nickname = $ServiceUser->nickname ?? '微信用户'; + $ServiceUser->saveOrFail(); + + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $ServiceUser->id; + $token = \Yii::$app->security->generateRandomString() . '_' . time(); + $ServiceUserToken->token = $token; + $ServiceUserToken->saveOrFail(); + + $StoreDoctor = StoreDoctor::find()->where([ + 'su_id' => $ServiceUser->id, + 'is_delete' => 0, + ])->one(); + + if (!$StoreDoctor){ + $StoreDoctor=new StoreDoctor(); + $StoreDoctor->su_id=$ServiceUser->id; + $StoreDoctor->is_online=1; + $StoreDoctor->store_id=\Yii::$app->store; + $StoreDoctor->last_login_time=time(); + $StoreDoctor->saveOrFail(); + + }else{ + \Yii::$app->db->createCommand()->update(StoreDoctor::tableName(),['is_online'=>0],['su_id'=>$ServiceUser->id])->execute(); + + //更新门店登录时间 + $StoreDoctor->is_online=1; + $StoreDoctor->last_login_time=time(); + if (!$StoreDoctor->saveOrFail())throw new Exception('更新门店登录时间失败'); + } + + $t->commit(); + return [ + 'token'=>$token, + 'StoreDoctor'=>$StoreDoctor, + 'ServiceUser'=>$ServiceUser + ]; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } else { + throw new Exception('验证码已过期,请从新获取验证码'); + } + } + + /** + * 手机号注册 + */ + public function PhoneRegister() + { + $token = \Yii::$app->security->generateRandomString() . '_' . time(); + $cache = \Yii::$app->cache; + if ($cache->get('login_sms_code_'.$this->mobile)) { + if ($cache->get('login_sms_code_'.$this->mobile) != $this->smsCode) { + throw new Exception('手机验证码错误'); + } + switch ($this->plate_type){ + case 1://线上 + $ServiceUser = ServiceUser::find()->where( + ['mobile' => $this->mobile,'is_delete'=>0] + )->one(); + + $transaction = \Yii::$app->db1->beginTransaction(); + try { + $sql="select * from yii_service_user where mobile=$this->mobile"; + $is_exist=\Yii::$app->db1->createCommand($sql)->queryOne(); + $id=$is_exist['id']; + + if (!$is_exist){ + \Yii::$app->db1->createCommand()->insert('yii_service_user',[ + 'mobile'=>$this->mobile, + 'role'=>UserRoleEnum::DOCTOR, + 'status'=>UserStatusEnum::WAIT_JH, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + $su_id=\Yii::$app->db1->getLastInsertID(); + \Yii::$app->db1->createCommand()->insert('yii_service_user_token',[ + 'su_id'=>$su_id, + 'token'=>$token, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + + //添加线下数据 + if (!$ServiceUser){ + $Service_Users=new ServiceUser(); + $Service_Users->mobile = $this->mobile; + $Service_Users->nickname = '微信用户'; + $Service_Users->role=UserRoleEnum::DOCTOR; + $Service_Users->plate_type = $this->plate_type; + $Service_Users->saveOrFail(); + + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $Service_Users->id; + $ServiceUserToken->token = $token; + $ServiceUserToken->saveOrFail(); + } + + $platform_doctor_id=$ServiceUser['id']??$Service_Users->id; + $service_id=$id??$su_id; + + $sql="select * from yii_doctor_platform where su_id=$service_id and platform_doctor_id=$platform_doctor_id"; + $doctor_platform=\Yii::$app->db1->createCommand($sql)->queryOne(); + $platform_id=1; + if (!$doctor_platform){ + //用户平台关系表 + \Yii::$app->db1->createCommand()->insert('yii_doctor_platform',[ + 'su_id'=>$service_id, + 'platform_doctor_id'=>$platform_doctor_id, + 'platform_id'=>$platform_id, + 'platform_store_id'=>\Yii::$app->store, + 'created_at'=>time(), + 'updated_at'=>time(), + ])->execute(); + } + $transaction->commit(); + return [ + 'token'=>$token, + 'data'=>$ServiceUser??$Service_Users + ]; + } + + if (!$ServiceUser){ + $Service_Users=new ServiceUser(); + $Service_Users->mobile = $this->mobile; + $Service_Users->nickname = '微信用户'; + $Service_Users->role=UserRoleEnum::DOCTOR; + $Service_Users->plate_type = $this->plate_type; + $Service_Users->saveOrFail(); + + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $Service_Users->id; + $ServiceUserToken->token = $token; + $ServiceUserToken->saveOrFail(); + return [ + 'token'=>$token, + 'data'=>$ServiceUser??$Service_Users + ]; + }else{ + throw new Exception('您已注册,请去登录'); + } + }catch (\Exception $e){ + $transaction->rollBack(); + throw new Exception($e->getMessage()); + } + break; + case 2://线下 + $t = \Yii::$app->db->beginTransaction(); + try { + $ServiceUser = ServiceUser::find()->where( + ['mobile' => $this->mobile,'is_delete'=>0] + )->one(); + + if (!$ServiceUser){ + $ServiceUser=new ServiceUser(); + } + $ServiceUser->mobile = $this->mobile; + $ServiceUser->nickname = '微信用户'; + $ServiceUser->plate_type = $this->plate_type; + $ServiceUser->role=$this->role; + $ServiceUser->status=UserStatusEnum::WAIT_JH; + $ServiceUser->save(); + + $ServiceUserToken = new ServiceUserToken(); + $ServiceUserToken->su_id = $ServiceUser->id; + $ServiceUserToken->token = $token; + $ServiceUserToken->save(); + + $t->commit(); + return [ + 'token'=>$token, + 'ServiceUser'=>$ServiceUser + ]; + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + default: + return []; + } + } else { + throw new Exception('验证码已过期,请从新获取验证码'); + } + } + +} \ No newline at end of file diff --git a/service/models/forms/MobileForm.php b/service/models/forms/MobileForm.php new file mode 100644 index 0000000..b7833b8 --- /dev/null +++ b/service/models/forms/MobileForm.php @@ -0,0 +1,31 @@ + '手机号', + ]; + } + + public function sendCode() + { + return ['发送成功']; + } +} \ No newline at end of file diff --git a/service/models/forms/RegisterForm.php b/service/models/forms/RegisterForm.php new file mode 100644 index 0000000..face549 --- /dev/null +++ b/service/models/forms/RegisterForm.php @@ -0,0 +1,78 @@ + '/^.{6,20}$/i','message'=>'密码最少6位'], + ['password', 'compare','message'=>'密码和重复密码不一致'], + ['mobile','checkUnique'], + ]; + } + + public function checkUnique($attribute, $params) + { + $exist = ServiceUser::find()->where([ + 'mobile' => $this->mobile, + 'is_delete' => 0 + ])->one(); + if($exist){ + $this->addError($attribute, '该账号已注册,可以直接去登录'); + } + } + + public function attributeLabels() + { + return [ + 'role' => '角色', + 'mobile' => '手机号', + 'password' => '密码', + 'password_repeat' => '重复密码', + ]; + } + + public function register() + { + if(!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $t = \Yii::$app->db->beginTransaction(); + + try { + $model = new ServiceUser(); + $model->attributes = $this->attributes; + $model->setPassword($this->password); + $model->saveOrFail(); + + $token = ServiceUserToken::createToken($model->id); + $t->commit(); + + return [ + 'token' => $token, + 'user' => ServiceUser::findOne($model->id), + ]; + }catch (Exception $e){ + + $t->rollBack(); + throw $e; + } + } + + +} \ No newline at end of file diff --git a/service/models/forms/ResetPasswordForm.php b/service/models/forms/ResetPasswordForm.php new file mode 100644 index 0000000..86dab0b --- /dev/null +++ b/service/models/forms/ResetPasswordForm.php @@ -0,0 +1,73 @@ + '手机号', + 'mobile_code' => '验证码', + 'password_new' => '新密码', + ]; + } + + public function resetPasswordAndLogin() + { + if (!$this->validate()) { + throw new Exception($this->getErrorMsg()); + } + + if ($this->mobile_code != $this->getCode()) { + throw new Exception('验证码错误'); + } + + $user = $this->getUser(); + if (!$user) { + throw new Exception('用户信息不存在'); + } + $user->setPassword($this->password_new); + $user->saveOrFail(); + + return [ + 'token' => ServiceUserToken::createToken($this->_user->id), + 'user' => $this->_user, + ]; + } + + public function getUser(): ?ServiceUser + { + if ($this->_user === null) { + $this->_user = ServiceUser::find()->where([ + 'mobile' => $this->mobile, + 'is_delete' => 0 + ])->one(); + } + return $this->_user; + } + + public function getCode() + { + return 1234; + } +} \ No newline at end of file diff --git a/service/models/forms/ServiceCompleteOne.php b/service/models/forms/ServiceCompleteOne.php new file mode 100644 index 0000000..0741a96 --- /dev/null +++ b/service/models/forms/ServiceCompleteOne.php @@ -0,0 +1,102 @@ + '/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/i'], + ['id_card', 'checkCard'], + ]; + } + + public function checkCard($attribute, $params) + { + $response = (new Client(['http_errors' => false]))->post("https://eid.shumaidata.com/eid/check", [ + 'headers' => ['Authorization' =>"APPCODE f98bba3251714c759f5bd29d00e1c46e"], + 'query' => [ + 'idcard' => $this->idcard, + 'name' => $this->name + ], + ]); + $result = json_decode($response->getBody(),true); + if(!($result['code']==0 && $result['result']['res']==1)){ + $this->addError($attribute, '身份证名字不匹配'); + } + } + + public function attributeLabels() + { + return [ + 'name' => '姓名', + 'avatar' => '头像', + 'mobile' => '手机号', + 'idcard' => '身份证号', + 'hospital_id' => '医院id', + 'yard_id' => '院区', + 'depart_id' => '科室', + 'title_id' => '职称', + 'card_up' => '身份证正面', + 'card_down' => '身份证反面' + ]; + } + + public function save() + { + if(!$this->validate()){ + throw new Exception($this->getErrorMsg()); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $model = ServInfo::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + if(!$model){ + $model = new ServInfo(); + $model->su_id = \Yii::$app->user->identity->id; + } + $model->attributes = $this->attributes; + $model->saveOrFail(); + + //修改状态 + $user = \Yii::$app->user->identity; + $user->status = UserStatusEnum::WAIT_SH; + $user->saveOrFail(); + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw $exception; + } + + return []; + } + + +} \ No newline at end of file diff --git a/service/models/forms/UpdatePasswordForm.php b/service/models/forms/UpdatePasswordForm.php new file mode 100644 index 0000000..2fcec26 --- /dev/null +++ b/service/models/forms/UpdatePasswordForm.php @@ -0,0 +1,60 @@ + '旧密码', + 'password_new' => '新密码', + ]; + } + + public function validatePassword($attribute, $params) + { + /* @var ServiceUser $user */ + $user = \Yii::$app->user->identity; + + if(!$user->validatePassword($this->password_old)){ + $this->addError($attribute, '旧密码错误'); + } + } + + public function updatePassword() + { + $t = \Yii::$app->db->beginTransaction(); + + try { + /* @var ServiceUser $user */ + $user = \Yii::$app->user->identity; + $user->setPassword($this->password_new); + $user->saveOrFail(); + + $t->commit(); + return []; + } catch (Exception $e) { + $t->rollBack(); + throw $e; + } + } +} \ No newline at end of file diff --git a/service/modules/v1/Module.php b/service/modules/v1/Module.php new file mode 100644 index 0000000..9a9aa56 --- /dev/null +++ b/service/modules/v1/Module.php @@ -0,0 +1,24 @@ + $uploadService->index($name)]; + } +} diff --git a/service/modules/v1/controllers/CallbackController.php b/service/modules/v1/controllers/CallbackController.php new file mode 100644 index 0000000..5dc8805 --- /dev/null +++ b/service/modules/v1/controllers/CallbackController.php @@ -0,0 +1,437 @@ +response->format = Response::FORMAT_RAW; + \Yii::$app->response->formatters = []; + + $response = WechatService::getInstance()->payment->handlePaidNotify(function ($notify, $fail) { + /** + * {"appid":"wx36bbb299d88c6127","bank_type":"ZJRCUB_DEBIT","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1496340382","nonce_str":"637ed1617f5f3","openid":"o88xX5Z-mpVWWV-yw2X6MefDIUqE","out_trade_no":"PY20221124100521434224","result_code":"SUCCESS","return_code":"SUCCESS","sign":"FAB5D4E3AD785DBF7D6FB1FE0E1A897E","time_end":"20221124100606","total_fee":"1","trade_type":"JSAPI","transaction_id":"4200001675202211242752421487"} + */ + //记录回调信息 + $callback = new Callback(); + $callback->content = json_encode($notify); + $callback->type = 'order'; + $callback->save(); + + if($notify['return_code']=='SUCCESS' && $notify['result_code']=='SUCCESS'){ + $t = \Yii::$app->db->beginTransaction(); + try { + $out_trade_no = $notify['out_trade_no']; + $paymentProductOrder = PaymentProductOrder::find()->where([ + 'pay_order_no' => $out_trade_no + ])->one(); + if($paymentProductOrder){ + $data['order_no'] = $paymentProductOrder->order_no; + $data['transaction_id'] = $notify['transaction_id']; + $data['pay_type'] = 1; + $productOrderPayForm = new ProductOrderSubmitForm(); + $order = $productOrderPayForm->paid($data); + $order_type=1; + }else{ + $PaymentRegister=PaymentRegister::find()->where([ + 'pay_order_no' => $out_trade_no + ])->one(); + if (!$PaymentRegister){ + throw new Exception('订单不存在'); + } + $data['order_no']= $PaymentRegister->order_no; + $data['transaction_id'] = $notify['transaction_id']; + $data['pay_type'] = 1; + $RegisterSubmitForm = new RegisterSubmitForm(); + $order = $RegisterSubmitForm->paid($data); + $order_type=2; + } + + // 增加流水记录 + $fundWater = new FundWater(); + $fundWater->store_id = $order->store_id; // 入账 + $fundWater->type = 'enter'; // 入账 + $fundWater->order_type = $order_type; + $fundWater->order_id = $order->id; + $fundWater->user_id = $order->user_id; + $fundWater->service_user_id = $order_type==1?$order->su_id:$order->service_user_id; + $fundWater->order_no = $order->order_no; + $fundWater->price = $order_type==1 ? $order->total_pay_price : $order->price; + $fundWater->pay_type = 1; //微信 + $fundWater->saveOrFail(); + + //回调处理成功 + $callback->status = 1; + $callback->save(); + $t->commit(); + return true; + }catch (\Exception $exception){ + $t->rollBack(); + $callback->message = $exception->getMessage(); + $callback->save(); + return $fail('通信失败,请稍后再通知我'); + } + + } + }); +// $response = unserialize('O:41:"Symfony\\Component\\HttpFoundation\\Response":6:{s:7:"headers";O:50:"Symfony\\Component\\HttpFoundation\\ResponseHeaderBag":5:{s:23:"' . "\0" . '*' . "\0" . 'computedCacheControl";a:1:{s:8:"no-cache";b:1;}s:10:"' . "\0" . '*' . "\0" . 'cookies";a:0:{}s:14:"' . "\0" . '*' . "\0" . 'headerNames";a:2:{s:13:"cache-control";s:13:"Cache-Control";s:4:"date";s:4:"Date";}s:10:"' . "\0" . '*' . "\0" . 'headers";a:2:{s:13:"cache-control";a:1:{i:0;s:8:"no-cache";}s:4:"date";a:1:{i:0;s:29:"Wed, 09 Mar 2022 02:19:18 GMT";}}s:15:"' . "\0" . '*' . "\0" . 'cacheControl";a:0:{}}s:10:"' . "\0" . '*' . "\0" . 'content";s:96:"";s:10:"' . "\0" . '*' . "\0" . 'version";s:3:"1.0";s:13:"' . "\0" . '*' . "\0" . 'statusCode";i:200;s:13:"' . "\0" . '*' . "\0" . 'statusText";s:2:"OK";s:10:"' . "\0" . '*' . "\0" . 'charset";N;}'); + return $response; + } + + /** + * 退款回调 + */ + public function actionRefundNotify() + { + \Yii::$app->response->format = Response::FORMAT_RAW; + \Yii::$app->response->formatters = []; + + + $response = WechatService::getInstance()->payment->handleRefundedNotify(function ($message, $reqInfo, $fail) { + // 其中 $message['req_info'] 获取到的是加密信息 + // $reqInfo 为 message['req_info'] 解密后的信息 + // 你的业务逻辑... + + /** + * {"cash_refund_fee":"1","out_refund_no":"RF20221124103051025400","out_trade_no":"PY20221124100521434224","refund_account":"REFUND_SOURCE_RECHARGE_FUNDS","refund_fee":"1","refund_id":"50300503882022112427569050043","refund_recv_accout":"\u6d59\u6c5f\u519c\u4fe1\u501f\u8bb0\u53617865","refund_request_source":"API","refund_status":"SUCCESS","settlement_refund_fee":"1","settlement_total_fee":"1","success_time":"2022-11-24 10:31:00","total_fee":"1","transaction_id":"4200001675202211242752421487"} + */ + + //记录回调信息 + $callback = new Callback(); + $callback->content = json_encode($reqInfo); + $callback->type = 'refund'; + $callback->save(); + + $t = \Yii::$app->db->beginTransaction(); + try { + $transaction_id = $reqInfo['transaction_id']; + $out_refund_no = $reqInfo['out_refund_no']; + + $paymentProductOrder = PaymentProductOrder::find()->where([ + 'transaction_id' => $transaction_id, + ])->one(); + if ($paymentProductOrder){ + if ($paymentProductOrder->is_pay!=1){ + throw new Exception('支付订单不存在'); + } + $order = ProductOrder::find()->where([ + 'order_no' => $paymentProductOrder->order_no, + ])->with('prescription')->one(); + if(!$order || $order->is_pay!=1){ + throw new Exception('订单不存在'); + } + $order_type = 1; + $refund = ProductOrderRefund::find()->where(['refund_no'=>$out_refund_no])->one();//退款订单 + $payment_refund = PaymentProductRefund::find()->where(['refund_no'=>$out_refund_no])->one(); + }else{ + $PaymentRegister=PaymentRegister::find()->where([ + 'transaction_id' => $transaction_id + ])->one(); + if (!$PaymentRegister || $PaymentRegister->is_pay!=1){ + throw new \yii\db\Exception('支付订单不存在'); + } + + $order = Register::find()->where([ + 'order_no' => $PaymentRegister->order_no, + ])->one(); + if(!$order || $order->is_pay!=1){ + throw new Exception('订单不存在'); + } + $order_type = 2; + $refund= RegisterRefund::find()->where(['refund_no'=>$out_refund_no])->one();//退款订单 + $payment_refund= PaymentRegisterRefund::find()->where(['refund_no'=>$out_refund_no])->one(); + } + + if(!$refund || !$payment_refund){ + throw new Exception('退款订单不存在'); + } + if($reqInfo['refund_status'] == 'SUCCESS'){ + if ($order_type == 1){ + $order->refund_status =3;//已退款 + $order->status = ProductOrderEnum::REFUND;//已退款 + $order->refund_time = time(); + $order->save(); + + if($order->is_online){ //平台订单状态同步 + \Yii::$app->queue->delay(0)->push(new ProductOrderSyncPlatformJob([ + 'orderId' => $this->event->order->id, + 'status' => 3 + ])); + } + } + + $refund->is_refund = 1; + $refund->refund_time = date('Y-m-d H:i:s',strtotime($reqInfo['success_time'])); + $refund->save(); + + $payment_refund->is_pay = 1; + $payment_refund->pay_type = 1; + $payment_refund->save(); + + }else{ + $refund->is_refund = -1; + $refund->save(); + + $payment_refund->is_pay = -1; + $payment_refund->save(); + } + + // 增加流水记录 + $fundWater = new FundWater();//出账 + $fundWater->store_id = $order->store_id; + $fundWater->order_type = $order_type; + $fundWater->type = 'refund'; // 出账 + $fundWater->order_id = $order->id; + $fundWater->user_id = $order->user_id; + $fundWater->service_user_id = $order_type==1?$order->su_id:$order->service_user_id; + $fundWater->refund_no = $refund->refund_no; + $fundWater->price = $order_type==1 ? $order->total_pay_price : $order->price; + $fundWater->pay_type = 1; //微信 + $fundWater->saveOrFail(); + + $callback->status = 1; + $callback->save(); + $t->commit(); + + return true; // 返回 true 告诉微信“我已处理完成” + // 或返回错误原因 $fail('参数格式校验错误'); + }catch (\Exception $exception){ + $t->rollBack(); + $callback->message = $exception->getMessage(); + $callback->save(); + $fail($exception->getMessage()); + } + }); + return $response; + } + + + /** + * 阿里oss直传回调 + */ + public function actionUploadNotify() + { + // 1.获取OSS的签名header和公钥url header + $headers =\Yii::$app->request->getHeaders(); + + $authorizationBase64 = ""; + $pubKeyUrlBase64 = ""; + if(isset($headers['authorization'])) { + $authorizationBase64 = $headers['authorization']; + }else{ + if (isset($_SERVER['HTTP_AUTHORIZATION'])) + { + $authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION']; + } + } + if(isset($headers['x-oss-pub-key-url'])){ + $pubKeyUrlBase64 = $headers['x-oss-pub-key-url']; + }else{ + if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL'])) + { + $pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL']; + } + } + if ($authorizationBase64 == '' || $pubKeyUrlBase64 == '') + { + throw new Exception('参数异常'); + } + + // 2.获取OSS的签名 + $authorization = base64_decode($authorizationBase64); + + // 4.获取回调body + $body = file_get_contents('php://input'); + + // 5.拼接待签名字符串 + $authStr = ''; + $path = $_SERVER['REQUEST_URI']; + $pos = strpos($path, '?'); + if ($pos === false) + { + $authStr = urldecode($path)."\n".$body; + } + else + { + $authStr = urldecode(substr($path, 0, $pos)).substr($path, $pos, strlen($path) - $pos)."\n".$body; + } + + // 3.获取公钥 + $pubKey = (new UploadService())->getPublicKey($pubKeyUrlBase64); + if ($pubKey == "") + { + throw new Exception('公钥异常'); + } + + // 6.验证签名 + $ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5); + if(!$ok){ + throw new Exception('签名异常'); + } + + $data = (new UploadService())->getBody($body); + return $data; + } + + // 互医订单同步 + public function actionPlatformNotify(){ + \Yii::$app->response->format = Response::FORMAT_RAW; + + $content = file_get_contents('php://input'); + $callback = new Callback(); + $callback->content = $content; + $callback->type = 'platform_notify'; + $callback->save(); + + $t = \Yii::$app->db->beginTransaction(); + try { + $data = json_decode($content, true); + $config = \Yii::$app->params; + $sign = md5($data['order']['order_no'].$data['time'].$config['platform']['token'].$data['type']); + if($sign != $data['sign']){ + throw new Exception('sign不匹配'); + } + $isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one(); + switch ($data['type']) { + case 'order_create'://订单创建 + if($isExist){ + throw new Exception('产品订单已存在'); + } + $userPatient = UserPatient::findOne([ + 'user_id' => $data['order']['user_id'], + 'id_card' => $data['order']['patient']['id_card'], + 'is_delete' => 0 + ]); + + $storeUser = StoreUser::find()->where([ + 'user_id' => $data['order']['user_id'], + 'is_online' => 1 + ])->one(); + $userAddress = Address::find()->select('id,name,mobile,province,region,detail_address')->where(['user_id' => $data['order']['user_id']])->orderBy('is_default DESC')->asArray()->all(); + + $productOrder = new ProductOrder(); + $productOrder->store_id = $storeUser->store_id??11001; + $productOrder->is_online = 1; + $productOrder->dosage = isset($data['order']['dosage'])?$data['order']['dosage']:0; + $productOrder->su_id = $data['order']['doctor_id']; + $productOrder->user_id = $data['order']['user_id']; + $productOrder->up_id = $userPatient->id??0; + $productOrder->order_no = Carbon::now()->format('YmdHis') . rand(10000, 99999) . rand(10000, 99999); + $productOrder->sync_order_no = $data['order']['order_no']; + $productOrder->order_type = 2; //商城订单 + $productOrder->prescription_type = $data['order']['prescription_type']; + $productOrder->p_id = 0; + $productOrder->status = 0; + $productOrder->items_price = $data['order']['total_price']; + $productOrder->trans_expenses = 0; + $totalPayPrice = $data['order']['total_price']; + if($userAddress){ + $productOrder->address_id = $userAddress[0]['id']; + $productOrder->address = Json::encode($userAddress[0]); + $productOrder->express_name = $userAddress[0]['name']; + $productOrder->express_mobile = $userAddress[0]['mobile']; + $productOrder->express_region = $userAddress[0]['region']; + $productOrder->express_address = $userAddress[0]['detail_address']; + $region = Region::find()->where(['name' => $userAddress[0]['province']])->one(); + $productOrder->trans_expenses = $region->express_fee; + $totalPayPrice = $totalPayPrice + $region->express_fee; + } + $productOrder->total_pay_price = $totalPayPrice; + $productOrder->saveOrFail(); + + foreach($data['order']['goods'] as $v){ + $drug = Drug::find()->where(['id' => $v['id']])->one(); + if(!$drug){ + throw new Exception('药品不存在:'.$v['id']); + } + $item = new ProductOrderItems(); + $item->product_order_id = $productOrder->id; + if ($drug) { + $item->drug_id = $drug->id; + $item->drug_image = $drug->image; + $item->number = $v['number']; + $item->drug_no = $drug->drug_number; + $item->price = $v['price']; + $item->drug_name = $drug->drug_name; + $item->small_info = $drug->small_info; + $item->saveOrFail(); + } + } + + //触发订单创建事件 + $event = new ProductOrderEvent(); + $event->order = $productOrder; + $event->sender = $this; + \Yii::$app->trigger(ProductOrder::EVENT_CREATED, $event); + + break; + case 'prescription_pass'://处方通过 + if(!$isExist){ + throw new Exception('产品订单不存在'); + } + $isExist->online_prescription_status = 1; + $isExist->save(); + break; + case 'prescription_refuse'://处方拒绝 + if(!$isExist){ + throw new Exception('产品订单不存在'); + } + $isExist->online_prescription_status = 2; + $isExist->save(); + //TODO 未付款订单取消/已付款订单退款 + + break; + default: + throw new Exception('错误的回调类型'); + break; + } + + $callback->status = 1; + $callback->save(); + $t->commit(); + return true; + } catch (Exception $e) { + $t->rollBack(); + $callback->message = $e->getMessage(); + $callback->save(); + Yii::$app->response->setStatusCode('400'); + return false; + } + } + +} \ No newline at end of file diff --git a/service/modules/v1/controllers/CaseController.php b/service/modules/v1/controllers/CaseController.php new file mode 100644 index 0000000..5c737c1 --- /dev/null +++ b/service/modules/v1/controllers/CaseController.php @@ -0,0 +1,96 @@ +request->post(); + $CaseForm=new CaseForm(); + $CaseForm->attributes=$post; + + return $CaseForm->save(); + } + + /** + * 修改病历 + */ + public function actionEditCase() + { + $post=\Yii::$app->request->post(); + $CaseForm=new CaseForm(); + $CaseForm->attributes=$post; + + return $CaseForm->update(); + } + + /** + * @doc-name 查看病历 + * @doc-param int user_patient_id 患者id + * @doc-param int register_id 挂号id + * @doc-return mixed @UserPatientCase{*,@UserPatient{*}} 病历 + */ + public function actionCaseInfo() + { + $post=\Yii::$app->request->post(); + $CaseForm=new CaseForm(); + $CaseForm->attributes=$post; + + return $CaseForm->info(); + } + + /** + * @doc-name 病历列表 + * @doc-param string main_suit 主诉 / optional + * @doc-return mixed @UserPatientCase{*} 病历 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionCaseList() + { + $post=\Yii::$app->request->post(); + $UserPatientCase = UserPatientCase::find()->where([ + 'service_user_id' => \Yii::$app->user->id, + 'store_id' => \Yii::$app->store, + 'is_delete' => 0, + ])->with(['userPatient'])->asArray()->all(); + + if (!$UserPatientCase) throw new Exception('暂无病历'); + + $query= UserPatientCase::find()->where([ + 'service_user_id' => \Yii::$app->user->id, + 'store_id' => \Yii::$app->store, + 'is_delete' => 0, + ])->with(['userPatient'])->orderBy(['id'=>SORT_DESC]); + + if (!empty($post['main_suit'])){ + $query->andWhere(['main_suit'=>$post['main_suit']]); + } + return $this->create($query,$post); + } + +} \ No newline at end of file diff --git a/service/modules/v1/controllers/CompleteController.php b/service/modules/v1/controllers/CompleteController.php new file mode 100644 index 0000000..2deb16d --- /dev/null +++ b/service/modules/v1/controllers/CompleteController.php @@ -0,0 +1,440 @@ +user->identity->getId(); + $store_id = StoreDoctor::find()->where([ + 'su_id' => $id, + 'store_id' => \Yii::$app->store, + 'is_delete' => 0 + ])->one(); + if (!$store_id) throw new \yii\db\Exception('您不在该门店,无法查看基本信息'); + $user = ServiceUser::find()->where([ + 'id' => $id + ])->with('docInfo', 'docIdentity', 'docPracticing', 'docService')->one(); + + return ArrayHelper::toArray($user, [ + ServiceUser::class => [ + 'id', 'status', 'reason', + 'info' => 'docInfo', + 'identity' => 'docIdentity', + 'practicing' => 'docPracticing', + 'service' => 'docService', + ] + ]); + } + + /** + * @doc-name 中西医 + * @doc-return array aa bb + */ + public function actionIdentity() + { + return [ + ['key' => 1, 'value' => '中医'], + ['key' => 2, 'value' => '西医'], + ]; + } + + /** + * @doc-name 中西药 + * @doc-return array aa bb + */ + public function actionDrugIdentity() + { + return [ + ['key' => 0, 'value' => '中药'], + ['key' => 1, 'value' => '西药'], + ]; + } + + /** + * @doc-name 医生-完善基本信息 + * @doc-param string name 姓名 + * @doc-param string avatar 头像 + * @doc-param string mobile 手机号 + * @doc-param string idcard 身份证 + * @doc-param json store_id 门店id["1","2"] + * @doc-param int depart_id 科室id + * @doc-param int identity 身份1中医2西医 + * @doc-param int title_id 职称id + * @doc-param string good_at 擅长 + * @doc-param string intro 简介 + */ + public function actionDoctorStepOne() + { + //医院院区科室职称有删除的怎么办-先不管 + $form = new DoctorCompleteOne(); + $form->attributes = \Yii::$app->request->post(); + return $form->save(); + } + + /** + * @doc-name 医生-完善认证信息 + * @doc-param string card_up 身份证正面 + * @doc-param string card_down 身份证反面 + * @doc-param string work_avator 工作照 + * @doc-param int sign_type 签章类型1电子2手写 + * @doc-param string sign_image 签章图片 + */ + public function actionDoctorStepTwo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['card_up', 'required', 'message' => '身份证正面照不能为空'], + ['card_down', 'required', 'message' => '身份证反面照不能为空'], + ['work_avator', 'required', 'message' => '工作照不能为空'], + ]); + $su_id = \Yii::$app->user->identity->id; + $model = DoctorIdentity::find()->where([ + 'su_id' => $su_id, + ])->one(); + $t = \Yii::$app->db->beginTransaction(); + try { + if (!$model) { + $model = new DoctorIdentity(); + $model->su_id = $su_id; + } + $model->sign_type = 2;//手写 + $model->attributes = $post; + $model->saveOrFail(); + + $t->commit(); + return ['已完善认证信息']; + + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 医生-完善执业信息 + * @doc-param json qualification 资格证书["图片1","图片2"] + * @doc-param json practicing 执业证书["图片1","图片2"] + * @doc-param json title 职称证书["图片1","图片2"] + */ + public function actionDoctorStepThree() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['qualification', 'required', 'message' => '资格证书不能为空'], + ['practicing', 'required', 'message' => '执业证书不能为空'], +// ['title','required','message'=>'职称证书不能为空'], + ]); + + $qualification = json_decode($post['qualification'], true); + $practicing = json_decode($post['practicing'], true); + $title = json_decode($post['title'], true); + if (empty($qualification)) { + throw new Exception("资格证书不能为空"); + } + if (empty($practicing)) { + throw new Exception("执业证书不能为空"); + } +// if(empty($title)){ +// throw new Exception("职称证书不能为空"); +// } + $su_id = \Yii::$app->user->identity->id; + $t = \Yii::$app->db->beginTransaction(); + try { + $model = DoctorPracticing::find()->where([ + 'su_id' => $su_id, + ])->one(); + if (!$model) { + $model = new DoctorPracticing(); + $model->su_id = $su_id; + } + $model->attributes = $post; + $model->saveOrFail(); + + $t->commit(); + return ['已完善执业信息']; + + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 医生-完善服务信息 + * @doc-param int register_status 是否开启挂号服务0否1是 0 optional + * @doc-param double register_price 挂号价格 0 optional + */ + public function actionDoctorStepFour() + { + $form = new DoctorCompleteFour(); + $form->attributes = \Yii::$app->request->post(); + return $form->save(); + } + + /** + * 医生同步互医 + * @return string[] + * @throws Exception + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function actionSyncDoctor() + { + $serviceUser = ServiceUser::find()->where([ + 'id' => \Yii::$app->user->identity->id + ])->with('docInfo', 'docIdentity', 'docPracticing')->one(); + if (empty($serviceUser) || empty($serviceUser->docInfo) || empty($serviceUser->docIdentity) || empty($serviceUser->docPracticing)) { + throw new Exception('医生信息错误'); + } + if($serviceUser->docInfo->is_sync == 1){ + throw new Exception('该医生同步至互医已是审核中状态'); + } + DoctorInfo::updateAll(['is_sync' => 1], ['su_id' => \Yii::$app->user->identity->id]); + return ['同步互医审核中']; + } + + /** + * @doc-name 药师-完善信息详情 + * @doc-return mixed ServiceUser{id,status,@Info{PharmacistrInfo{*}},@Identity{PharmacistIdentity{*}},@Practicing{PharmacistPracticing{*}}} + */ + public function actionDrugInfo() + { + $user = ServiceUser::find()->where([ + 'id' => \Yii::$app->user->identity->id + ])->with('drugInfo', 'drugIdentity', 'drugPracticing')->one(); + + return ArrayHelper::toArray($user, [ + ServiceUser::class => [ + 'id', 'status', 'reason', + 'info' => 'drugInfo', + 'identity' => 'drugIdentity', + 'practicing' => 'drugPracticing' + ] + ]); + } + + /** + * @doc-name 药师-完善基础信息 + * @doc-param string name 姓名 + * @doc-param string avatar 头像 + * @doc-param string mobile 手机号 + * @doc-param string idcard 身份证 + * @doc-param string store_id 门店id + * @doc-param int title_id 职称id + * @doc-param int type 身份类型1中医药师 2西医药师 + */ + public function actionDrugStepOne() + { + $form = new DrugCompleteOne(); + $form->attributes = \Yii::$app->request->post(); + return $form->save(); + } + + /** + * @doc-name 药师-完善认证信息 + * @doc-param string card_up 身份证正面 + * @doc-param string card_down 身份证反面 + * @doc-param int sign_type 签章类型1电子2手写 + * @doc-param string sign_image 签章图片 + */ + public function actionDrugStepTwo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['card_up', 'required', 'message' => '身份证正面照不能为空'], + ['card_down', 'required', 'message' => '身份证反面照不能为空'], + ]); + $model = PharmacistIdentity::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + if (!$model) { + $model = new PharmacistIdentity(); + $model->su_id = \Yii::$app->user->identity->id; + } + $model->sign_type = 2;//手写 + $model->attributes = $post; + $model->saveOrFail(); + return ['已完善认证信息']; + } + + /** + * @doc-name 药师-完善执业信息 + * @doc-param json qualification 资格证书["图片1","图片2"] + * @doc-param json practicing 执业证书["图片1","图片2"] + * @doc-param json title 职称证书["图片1","图片2"] + */ + public function actionDrugStepThree() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['qualification', 'required', 'message' => '资格证书不能为空'], +// ['practicing', 'required', 'message' => '执业证书不能为空'], +// ['title', 'required', 'message' => '职称证书不能为空'], + ]); + $qualification = json_decode($post['qualification'], true); + $practicing = json_decode($post['practicing'], true); + $title = json_decode($post['title'], true); + if (empty($qualification)) { + throw new Exception("资格证书不能为空"); + } +// if (empty($practicing)) { +// throw new Exception("执业证书不能为空"); +// } +// if (empty($title)) { +// throw new Exception("职称证书不能为空"); +// } + + + $serviceUser = ServiceUser::find()->where([ + 'id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->with('drugInfo', 'drugIdentity')->one(); + + if (!$serviceUser) { + throw new Exception('用户不存在'); + } + if (!$serviceUser->drugInfo || !$serviceUser->drugIdentity) { + throw new Exception('请先完善前几步信息'); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + $model = PharmacistPracticing::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + if (!$model) { + $model = new PharmacistPracticing(); + $model->su_id = \Yii::$app->user->identity->id; + } + $model->attributes = $post; + + $model->saveOrFail(); + + //第三步完成后需要修改账户的激活状态未待审核 - 后台审核 - 已认证 + //后台拒绝 - 前台修改资料 - 提交 - 重新待审核 + $user = \Yii::$app->user->identity; + $user->status = UserStatusEnum::WAIT_SH; + $user->reason = null; + $user->saveOrFail(); + + $t->commit(); + } catch (Exception $exception) { + $t->rollBack(); + throw $exception; + } + + return []; + } + + /** + * @doc-name 导医-完善信息详情 + * @doc-return mixed ServiceUser{id,status,@Info{LeadInfo{*}}} + */ + public function actionLeadInfo() + { + $user = ServiceUser::find()->where([ + 'id' => \Yii::$app->user->identity->id + ])->with('leadInfo')->one(); + + return ArrayHelper::toArray($user, [ + ServiceUser::class => [ + 'id', 'status', 'info' => 'leadInfo' + ] + ]); + } + + /** + * @doc-name 导医-完善信息 + * @doc-param string name 姓名 + * @doc-param string avatar 头像 + * @doc-param string mobile 手机号 + * @doc-param string idcard 身份证 + * @doc-param int hospital_id 医院id + * @doc-param int yard_id 院区id + * @doc-param int depart_id 科室id + * @doc-param string card_up 身份证正面 + * @doc-param string card_down 身份证反面 + */ + public function actionLeader() + { + $form = new LeadCompleteOne(); + $form->attributes = \Yii::$app->request->post(); + return $form->save(); + } + + /** + * @doc-name 导医-完善信息详情 + * @doc-return mixed ServiceUser{id,status,@Info{LeadInfo{*}}} + */ + public function actionServInfo() + { + $user = ServiceUser::find()->where([ + 'id' => \Yii::$app->user->identity->id + ])->with('servInfo')->one(); + + return ArrayHelper::toArray($user, [ + ServiceUser::class => [ + 'id', 'status', 'info' => 'servInfo' + ] + ]); + } + + /** + * @doc-name 客服完善信息 + * @doc-param string name 姓名 + * @doc-param string avatar 头像 + * @doc-param string mobile 手机号 + * @doc-param string idcard 身份证 + * @doc-param int hospital_id 医院id + * @doc-param int yard_id 院区id + * @doc-param int depart_id 科室id + * @doc-param string card_up 身份证正面 + * @doc-param string card_down 身份证反面 + */ + public function actionService() + { + $form = new ServiceCompleteOne(); + $form->attributes = \Yii::$app->request->post(); + return $form->save(); + } + + /** + * @doc-name 医生-服务设置 + * @doc-param int register_status 是否开通挂号 0 optioanl + * @doc-param double register_price 挂号价格 0 optional + */ + public function actionDoctorService() + { + $form = new DoctorServiceForm(); + $form->attributes = \Yii::$app->request->post(); + return $form->save(); + } +} diff --git a/service/modules/v1/controllers/DiagnoseController.php b/service/modules/v1/controllers/DiagnoseController.php new file mode 100644 index 0000000..56c5943 --- /dev/null +++ b/service/modules/v1/controllers/DiagnoseController.php @@ -0,0 +1,75 @@ +select('id,content')->where(['su_id' => \Yii::$app->user->identity->id])->all(); + return $diagnoseCommon; + } + + /** + * 添加常用医嘱 + */ + public function actionAdd(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + [['content'],'required'] + ]); + $diagnoseCommon = DiagnoseCommon::find()->where(['content' => $post['content'],'su_id' => \Yii::$app->user->identity->id])->one(); + if($diagnoseCommon){ + throw new Exception('已存在相同内容的医嘱'); + } + $common = new DiagnoseCommon(); + $common->su_id = \Yii::$app->user->identity->id; + $common->content = $post['content']; + $common->saveOrFail(); + return ['success']; + } + + + /** + * 删除常用医嘱 + */ + public function actionDelete(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + [['id'],'required'] + ]); + $ids = explode(',', $post['id']); + $t = \Yii::$app->db->beginTransaction(); + try { + foreach($ids as $v){ + $diagnoseCommon = DiagnoseCommon::find()->where(['id' => $v,'su_id' => \Yii::$app->user->identity->id])->one(); + if(!$diagnoseCommon){ + throw new Exception('医嘱不存在'); + } + $diagnoseCommon->delete(); + } + $t->commit(); + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + return ['success']; + } + +} diff --git a/service/modules/v1/controllers/DoctorArticleController.php b/service/modules/v1/controllers/DoctorArticleController.php new file mode 100644 index 0000000..3e61524 --- /dev/null +++ b/service/modules/v1/controllers/DoctorArticleController.php @@ -0,0 +1,184 @@ +request->post(); + $keyword = \Yii::$app->request->post('keyword'); + $query = DoctorArticle::find()->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'is_draft' => 0, + 'is_delete' => 0, + ])->orderBy(['id'=>SORT_DESC]); + if ($keyword) { + $query->andFilterWhere(['like', 'title', $keyword]); + } + $this->field = [ + DoctorArticle::class => [ + 'id', 'title', 'created_at', 'video_url', 'cover', + ] + ]; + $data = $this->create($query, $post)->getModels(); + foreach ($data as $value) { + $value['created_at'] = Carbon::createFromTimestamp($value['created_at'])->toDateTimeString(); + } + return $data; + } + + /** + * @doc-name 文章详情 + * @doc-return mixed @DoctorArticle{*} 文章详情 + */ + public function actionInfo() + { + $id = \Yii::$app->request->post('id'); + $info = DoctorArticle::find()->where([ + 'id' => $id, + 'su_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0, + ])->one(); + if (!$info) { + throw new Exception('文章不存在'); + } + $info['created_at'] = Carbon::createFromTimestamp($info['created_at'])->toDateTimeString(); + return $info; + } + + /** + * @doc-name 草稿列表 + * @doc-param string title 标题 + * @doc-return mixed @List{id-int-文章id,cover-string-封面,title-string-标题,created_at-int-发布时间} 文章信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionMyDraft() + { + $post = \Yii::$app->request->post(); + $keyword = \Yii::$app->request->post('keyword'); + $query = DoctorArticle::find()->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'is_draft' => 1, + 'is_delete' => 0, + ])->orderBy(['id'=>SORT_DESC]); + if ($keyword) { + $query->andFilterWhere(['like', 'title', $keyword]); + } + $this->field = [ + DoctorArticle::class => [ + 'id', 'title', 'created_at', 'video_url', 'cover', + ] + ]; + $data = $this->create($query, $post)->getModels(); + foreach ($data as $value) { + $value['created_at'] = Carbon::createFromTimestamp($value['created_at'])->toDateTimeString(); + } + return $data; + } + + /** + * @doc-name 文章新增编辑 + * @doc-param int id id可选无为新增 + * @doc-param string title 标题 + * @doc-param string cover 封面图(可空) + * @doc-param string content 内容 + * @doc-param string video_url 视频链接(可空) + * @doc-param int is_draft 是否是草稿0否1是 + */ + public function actionSave() + { + $post = \Yii::$app->request->post(); + + $this->requestValidate($this->post(), [ + ['title', 'required'], + ['content', 'required'], + ['is_draft', 'required'], + ]); + + $id = \Yii::$app->request->post('id'); + if ($id) { + /* @var DoctorArticle $info */ + $info = DoctorArticle::find()->where([ + 'id' => $id, + 'su_id' => \Yii::$app->user->identity->getId(), + 'is_delete' => 0, + ])->one(); + if (!$info) { + throw new Exception('文章不存在'); + } + } else { + $info = new DoctorArticle(); + } + + $info->su_id = \Yii::$app->user->identity->getId(); + $info->title = $post['title'] ?? null; + $info->cover = $post['cover'] ?? null; + $info->content = $post['content'] ?? null; + $info->video_url = $post['video_url'] ?? null; + $info->is_draft = $post['is_draft']; + $info->is_delete = 0; + $info->saveOrFail(); + + return [$id ? '编辑成功' : '新增成功']; + } + + /** + * @doc-name 文章删除 + * @doc-param int id 文章id + */ + public function actionDel() + { + $id = \Yii::$app->user->identity->id; + $article_id = \Yii::$app->request->get('id'); + if (!$article_id) { + throw new Exception('请选择删除的文章'); + } + $article = DoctorArticle::find()->where(['su_id' => $id, 'id' => $article_id])->one(); + if (!$article) throw new Exception('文章不存在'); + + $article->is_delete = 1; + $article->save(); + return ['删除成功']; + } + + /** + * @doc-name 群发文章 + * @doc-param string content 发送内容 + * @doc-param string send_at 发送时间-年月日时分秒 + * @doc-param array up_ids 患者ID数组 + */ + public function actionMassSend() + { + $content = \Yii::$app->request->post('content'); + $up_ids = explode(',', \Yii::$app->request->post('up_ids')); + $send_at = \Yii::$app->request->post('send_at'); + if (count($up_ids) == 0) { + throw new Exception('请选择要群发的患者'); + } + $su_id = \Yii::$app->user->identity->id; + + \Yii::$app->queue->delay(Carbon::now()->diffInSeconds($send_at))->push(new ArticleMassSendJob(([ + 'content' => $content, + 'su_id' => $su_id, + 'up_ids' => $up_ids, + ]))); + + return ['已添加定时发送']; + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/DoctorMyController.php b/service/modules/v1/controllers/DoctorMyController.php new file mode 100644 index 0000000..af07079 --- /dev/null +++ b/service/modules/v1/controllers/DoctorMyController.php @@ -0,0 +1,73 @@ +request->post(); + $HospitalDocForm = new HospitalDocForm(); + $HospitalDocForm->attributes = $post; + + return $HospitalDocForm->grade(); + } + + /** + * @doc-name 获取互医信息 + */ + public function actionHospitalDocInfo() + { + $post = \Yii::$app->request->post(); + $HospitalDocForm = new HospitalDocForm(); + $HospitalDocForm->attributes = $post; + + return $HospitalDocForm->DocInfo(); + } + + /** + * 同步患者(后台) + */ + public function actionSyncPatient() + { + $post = \Yii::$app->request->post(); + $HospitalDocForm = new HospitalDocForm(); + $HospitalDocForm->attributes = $post; + + return $HospitalDocForm->SyncPatient(); + } + + /** + * @doc-name 申请升级为互医 + */ + public function actionApplyUpgrade() + { + + $DoctorApply=DoctorApply::find()->where([ + 'service_user_id'=>\Yii::$app->user->identity->getId(), + 'is_delete'=>0 + ])->one(); + + if ($DoctorApply) { + throw new Exception('您已提交申请'); + } + + $apply=new DoctorApply(); + $apply->service_user_id=\Yii::$app->user->identity->getId(); + $apply->status=0; + + $apply->saveOrFail(); + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/DoctorNoticeController.php b/service/modules/v1/controllers/DoctorNoticeController.php new file mode 100644 index 0000000..15035cd --- /dev/null +++ b/service/modules/v1/controllers/DoctorNoticeController.php @@ -0,0 +1,57 @@ +request; + $param = $request->post(); + $this->requestValidate($param, [ + ['close_notice', 'required', 'message' => '停诊公告不能为空'], + ['content', 'required', 'message' => '内容不能为空'], + ['start_time', 'required', 'message' => '开始时间不能为空'], + ['end_time', 'required', 'message' => '结束时间不能为空'], + ]); + $notice = DoctorNotice::find()->where(['su_id' => \Yii::$app->user->identity->id])->one(); + + if (!$notice) { + $notice = new DoctorNotice(); + $notice->su_id = \Yii::$app->user->identity->id; + } + $notice->attributes = $param; + $notice->saveOrFail(); + return []; + + } + + /** + * @doc-name 查询停诊公告 + */ + public function actionQueryNotice() + { + $notice = DoctorNotice::find()->where(['su_id' => \Yii::$app->user->identity->id])->one(); + + if (!$notice) { + throw new Exception('你还没有公告,可以去添加'); + } + + return $notice; + } + +} \ No newline at end of file diff --git a/service/modules/v1/controllers/DoctorWorkController.php b/service/modules/v1/controllers/DoctorWorkController.php new file mode 100644 index 0000000..49dfa43 --- /dev/null +++ b/service/modules/v1/controllers/DoctorWorkController.php @@ -0,0 +1,281 @@ +request->post(); + $store = Store::findOne(\Yii::$app->store); + if(!$store)throw new Exception('门店不存在'); + + $DoctorInfo= DoctorInfo::find() + ->where(['su_id' => \Yii::$app->user->identity->id]) + ->with(['title', 'hospital','depart','user']) + ->one(); + $DoctorIdentity= DoctorIdentity::find() + ->where(['su_id' => \Yii::$app->user->identity->id]) + ->one(); + $DoctorPracticing= DoctorPracticing::find() + ->where(['su_id' => \Yii::$app->user->identity->id]) + ->one(); + if(!$DoctorInfo || !$DoctorIdentity || !$DoctorPracticing){ + throw new Exception('医生信息错误'); + } + $storeDoctor = StoreDoctor::find()->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'store_id' => \Yii::$app->store + ])->one(); + if(!$storeDoctor)throw new Exception('非该门店医生'); + + + //门店医生小程序码 + if(!$storeDoctor->qr_code){ + $response = WechatService::getInstance()->app->app_code->getUnlimit('su_id='.\Yii::$app->user->identity->getId().'&store_id='.\Yii::$app->store, [ + 'page' => 'subPackages/doctor/doctor-detail', + 'check_path' => false, + ]); + if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) { + $path = 'uploads/doctor_code/' . date('Ymd'); + $filename = $response->save('uploads/doctor_code/' . date('Ymd'), 'doctor_code_' . $DoctorInfo->su_id.\Yii::$app->store); + $realpath = FuncHelper::getRealFilepath('service', $path . '/' . $filename); + $uploadService = new UploadService(); + $url = $uploadService->saveFile($realpath); + $storeDoctor->qr_code = $url; + $storeDoctor->save(); + } + } + //门店医生在线状态 + if($storeDoctor->is_online != 1){ + StoreDoctor::updateAll(['is_online' => 0],['su_id' => \Yii::$app->user->identity->getId(), 'is_online' => 1]); + $storeDoctor->is_online = 1; + $storeDoctor->last_login_time = time(); + $storeDoctor->save(); + } + + $relates = $DoctorInfo->getRelatedRecords(); + $DoctorInfo = $DoctorInfo->toArray(); + $DoctorInfo = array_merge($DoctorInfo, $relates); + + $wait_accept=Register::find()->where([ + 'service_user_id'=> \Yii::$app->user->identity->id, + 'store_id'=> $post['store_id'], + 'status'=>RegisterEnum::WAIT, + 'is_pay'=>1, + 'is_cancel'=>0, + 'is_delete'=>0 + ])->count(); + + $accepting = Register::find()->where([ + 'service_user_id'=> \Yii::$app->user->identity->id, + 'store_id'=> $post['store_id'], + 'status'=>RegisterEnum::ACCEPTING, + 'is_pay'=>1, + 'is_cancel'=>0, + 'is_delete'=>0 + ])->count(); + + $idcard= DoctorInfo::find()->select(['idcard'])->where(['su_id'=>\Yii::$app->user->id])->one(); + $number = substr($idcard['idcard'], strlen($idcard['idcard']) - 2, 1); + $sex=$number % 2 == 0?'女':'男'; + + #医生开通的服务 + $doctor_service = DoctorService::find()->where(['su_id' => \Yii::$app->user->identity->id])->asArray()->one(); + $DoctorInfo['qr_code'] = $storeDoctor->qr_code; + + $ServiceUser=ServiceUser::find()->select(['reason','status'])->where(['id'=>\Yii::$app->user->identity->id])->one(); + + return [ + 'store'=>[ + 'store_id' => $store->id, + 'store' => [ + 'id' => $store->id, + 'name' => $store->name, + 'see_rate'=>$store->see_rate, + ] + + ], + 'DoctorInfo'=>$DoctorInfo, + 'doctor_service'=>$doctor_service, + 'DoctorIdentity'=>$DoctorIdentity, + 'DoctorPracticing'=>$DoctorPracticing, + 'wait_accept'=>$wait_accept, + 'accepting'=>$accepting, + 'sex'=>$sex, + 'ServiceUser'=>$ServiceUser + ]; + } + + /** + * @doc-name 我的评价基础信息(医生端) + */ + public function actionCommentMain() + { + $allCount = (int)UserComment::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + ]) + ->count(); + $highCount = (int)UserComment::find() + ->where(['>=', 'score', 4]) + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + ]) + ->count(); + $lowCount = (int)UserComment::find() + ->where(['<=', 'score', 2]) + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + ]) + ->count(); + $scoreAvg = UserComment::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + ]) + ->average('score'); + + $scoreAvg = ceil($scoreAvg * 2) / 2; + + return [ + 'all_count' => $allCount, + 'high_count' => $highCount, + 'low_count' => $lowCount, + 'score_avg' => $scoreAvg, + ]; + } + + /** + * @doc-name 我的评价(医生端) + * @doc-param string type high高分low低分 + * @doc-return mixed @List{score-int-分数,comment-string-评价内容,created_at-string-评价时间,nickname-string-用户隐私姓名} 评价信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionComments() + { + $type = \Yii::$app->request->post('type'); + $query = UserComment::find() + ->select(['id', 'u_id', 'score', 'comment', 'created_at']) + ->with(['user']) + ->orderBy(['created_at' => SORT_DESC]) + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + ]); + + if ($type == 'high') { + $query->andWhere(['>=', 'score', 4]); + } elseif ($type == 'low') { + $query->andWhere(['<=', 'score', 2]); + } + + $this->field = [ + UserComment::class => [ + 'id', 'u_id', 'score', 'comment', 'created_at', + 'nickname' => function (UserComment $comment) { + $user = User::find() + ->select(['id', 'nickname']) + ->where(['id' => $comment->u_id]) + ->one(); + $nickname = $user->nickname ?? '微信用户'; + if ($nickname) { + $nickname = StringHelper::string_hide_cut($nickname); + } + return $nickname; + }, + 'avatar'=>function($m){ + $avatar= UserPatient::find()->where([ + 'id'=>$m->u_id, +// 'user_id'=>$m->user_id + ])->select('avatar')->one(); + return $avatar??'https://tenfei03.cfp.cn/creative/vcg/veer/1600water/veer-105516317.jpg'; + } + ], + ]; + + return $this->create($query,$type); + } + + /** + * @doc-name 收入明细 + * @doc-return string name 患者姓名 / optional + * @doc-return mixed @List{id-int-挂号id,avatar-string-头像,name-string-名字,price-float-金额,pay_time-string-收款时间} 信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页多少条} 分页信息 + */ + public function actionIncomeDetail() + { + $post=\Yii::$app->request->post(); + $query=Register::find()->where([ + 'store_id'=>\Yii::$app->store, + 'is_pay'=>0, + 'service_user_id'=>\Yii::$app->user->id + ])->with('patient'); + if (!empty($post['name'])){ + $name=$post['name']; + $query->joinWith(['patient' => function ($p) use ($name) { + $p->alias('p'); + $p->andWhere(['like', 'p.name', $name]); + }]); + } + $this->field=[ + Register::class=>[ + 'id','avatar'=>'patient.avatar', + 'name'=>'patient.name', + 'price','pay_time' + ] + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 编辑资料 + * @doc-param string avatar 头像 / optional + */ + public function actionEditInfo() + { + $post = \Yii::$app->request->post(); + $DoctorInfo=DoctorInfo::find()->where([ + 'su_id'=>\Yii::$app->user->id + ])->one(); + + if (!$DoctorInfo) throw new Exception('医生信息不存在'); + $DoctorInfo->avatar=$post['avatar']; + if (!$DoctorInfo->saveOrFail()){ + throw new Exception('编辑失败'); + } + return ['编辑成功']; + } +} diff --git a/service/modules/v1/controllers/ExamineController.php b/service/modules/v1/controllers/ExamineController.php new file mode 100644 index 0000000..5049222 --- /dev/null +++ b/service/modules/v1/controllers/ExamineController.php @@ -0,0 +1,205 @@ +all(); + } + + /** + * @doc-name 查看处方 + * @doc-param int prescription_id 处方id + * @doc-return string issue_date 开方时间 + * @doc-return mixed @PrescriptionWest{*,@UserPatient{*},@DoctorInfo{*,@Department{*}},@PharmacistInfo{name-string-药师}} 西药处方 + * @doc-return mixed @PrescriptionChinese{*,@UserPatient{*},@DoctorInfo{*,@Department{*}},@PharmacistInfo{name-string-药师}} 中药处方 + * @doc-return mixed @WestRepice{*,@DrugUseTime{*},@DrugUseType{*},@DrugUseFrequency{*},@WestUnit{*}} 西药方 + * @doc-return mixed @ChineseRepice{*,@DrugUseTime{*},@DrugUseNum{*}} 中药方 + * @doc-return float total_price 金额 + */ + public function actionDetail() + { + $pharmacistrInfo = PharmacistrInfo::find()->where(['su_id' => \Yii::$app->user->identity->getId()])->one(); + if (!$pharmacistrInfo) { + throw new Exception('药师数据错误'); + } + + $prescription_no = \Yii::$app->request->get('prescription_no'); + if (!$prescription_no) { + throw new Exception('处方no不能为空'); + } + + return (new PrescriptionService())->detail(\Yii::$app->request->get('prescription_no')); + } + + /** + * @doc-name 处方列表 + * @doc-param int status 状态0待审核 1已审核通过 2未通过 + * @doc-return mixed @PrescriptionChinese{*,@UserPatient{*}} 中药处方 + * @doc-return mixed @PrescriptionWest{*,@UserPatient{*}} 中药处方 + */ + public function actionList() + { + $pharmacistrInfo = PharmacistrInfo::find()->where(['su_id' => \Yii::$app->user->identity->getId()])->one(); + if (!$pharmacistrInfo) { + throw new Exception('药师数据错误'); + } + $status = \Yii::$app->request->get('status'); + if($status > 0){ //已审核或未通过审核 + $prescription = Prescription::find()->where(['status' => $status, 'pharmacist_id' => \Yii::$app->user->identity->id])->with('patients')->orderBy('created_at DESC')->asArray()->all(); + } else { + $prescription = Prescription::find()->where(['status' => $status])->with('patients')->orderBy('created_at DESC')->asArray()->all(); + } + if (!$prescription) { + throw new Exception('暂无数据'); + } + + return [ + 'prescription' => $prescription + ]; + } + + /** + * @doc-name 处方审核 + * @doc-param int prescription_id 处方id + * @doc-param int status 状态 1已通过 2拒绝 + */ + public function actionVerify() + { + $pharmacistrInfo = PharmacistrInfo::find()->where(['su_id' => \Yii::$app->user->identity->getId()])->one(); + if (!$pharmacistrInfo) { + throw new Exception('药师数据错误'); + } + //处方号 + $prescription_no = \Yii::$app->request->post('prescription_no'); + if (!$prescription_no) { + throw new Exception('处方号不能为空'); + } + //处方状态 + $status = \Yii::$app->request->post('status'); + if (!in_array($status, [1, 2])) { + throw new Exception('审核状态错误'); + } + + $prescription = Prescription::find()->where(['prescription_no' => $prescription_no])->one(); + if(!$prescription) throw new Exception('处方不存在'); + $t = \Yii::$app->db->beginTransaction(); + try { + $prescription->pharmacist_id = \Yii::$app->user->identity->id; + $prescription->status = $status; + $prescription->reject_view = $status == 2 ? \Yii::$app->user->identity->id:0; + $prescription->reject_reason = $status == 2 ? \Yii::$app->request->post('reject_reason'):''; + $prescription->reject_time = $status == 2 ? time():0; + $prescription->pharmacist_view_time = time(); + $prescription->saveOrFail(); + + if($status == 2){ //审批不通过,已支付订单需要退款 + $productOrder = ProductOrder::find()->where(['p_id' => $prescription->id])->one(); + if($productOrder->status == 0){//待支付订单需要取消 + $form = new ProductCancelForm(); + $form->cancel(['user_id' =>$productOrder->user_id, 'order_id' => $productOrder->id]); + } elseif ($productOrder->status == 1){//已支付订单需要退款 + $form = new ProductRefundForm(); + $form->refund(['user_id' =>$productOrder->user_id, 'order_id' => $productOrder->id], 'auto'); + } + }else{ + //中药处方订单同步江奥川erp + if($prescription->prescription_type == 1){ + $productOrder = ProductOrder::find()->where(['p_id' => $prescription->id, 'status' => 1])->one(); + if($productOrder){ + //触发订单支付事件,同步江奥川ERP + $event = new ProductOrderEvent(); + $event->order = $productOrder; + $event->sender = $this; + \Yii::$app->trigger(ProductOrder::EVENT_PAYED, $event); + } + } + } + + $systemNotice = new SystemNotice(); + $systemNotice->store_id = $prescription->store_id; + $systemNotice->user_id = $prescription->su_id; + $systemNotice->data = $prescription->id; + $systemNotice->content = $status==1?'您开具的处方已通过审核!':'您开具的处方未通过审核,原因是:'.\Yii::$app->request->post('reject_reason'); + $systemNotice->base_type = 5; + $systemNotice->scene_type = 2;// 医生 + $systemNotice->notice_at = date('Y-m-d H:i:s'); + $systemNotice->saveOrFail(); + + $t->commit(); + + //处方生成短信通知药师审方 + if($status == 2){ + \Yii::$app->queue->push(new PrescriptionRefuseMessageJob([ + 'orderId' => $prescription->id, + ])); + } else { + \Yii::$app->queue->push(new PrescriptionPassMessageJob([ + 'orderId' => $prescription->id, + ])); + } + + } catch (\Exception $e) { + $t->rollBack(); + throw new Exception($e->getMessage()); + } + return ['审核成功']; + } + + /** + * @doc-name 处方溯源 + * @doc-param int prescription_id 处方id + * @doc-param string prescription_no 处方编号 + */ + public function actionSource() + { + $prescription_no = \Yii::$app->request->get('prescription_no'); + if (!$prescription_no) throw new Exception('处方号不能为空'); + $store_id = \Yii::$app->request->get('store_id'); + // 先查询是否西药处方 + $prescription = Prescription::find()->where(['prescription_no' => $prescription_no])->with(['pharmacistInfo', 'patients'])->asArray()->one(); + + $doctor = []; + $doctorInfo = DoctorInfo::find()->where(['su_id' => $prescription['su_id']])->one(); + $depart = Department::findOne(['id' => $doctorInfo->depart_id]); + $store = Store::findOne(['id' => $store_id]); + $doctor['store'] = $store->name; + $doctor['depart'] = $depart->name; + $doctor['name'] = $doctorInfo->name; + + return [ + 'type' => $prescription->prescription_type == 1 ? '中药处方' : ($prescription->prescription_type == 2 ? '西药处方' : '颗粒药处方'), + 'prescription' => $prescription, + 'doctor' => $doctor + ]; + + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/HomeController.php b/service/modules/v1/controllers/HomeController.php new file mode 100644 index 0000000..218976d --- /dev/null +++ b/service/modules/v1/controllers/HomeController.php @@ -0,0 +1,41 @@ +where([ + 'su_id'=>\Yii::$app->user->identity->id + ]) + ->with(['docInfo'=>function($query){ + $query->select('su_id,name'); + }]) + ->asArray()->orderBy(['id'=>SORT_DESC])->all(); + } + + /** + * @doc-name 设置精选 + * @doc-return mixed @PatientVisitRecord{*} 问诊记录列表 + */ + public function actionSetSelect() + { + return PatientVisitRecord::find() + ->where([ + 'su_id'=>\Yii::$app->user->identity->id + ]) + ->all(); + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/ImController.php b/service/modules/v1/controllers/ImController.php new file mode 100644 index 0000000..1854c16 --- /dev/null +++ b/service/modules/v1/controllers/ImController.php @@ -0,0 +1,745 @@ +user->identity->role) + { + case UserRoleEnum::DOCTOR: + $this->types = [ImSessionTypeEnum::USER_DOC]; + break; + case UserRoleEnum::DRUG: + $this->types = [ImSessionTypeEnum::DRUG_SERV]; + break; + case UserRoleEnum::LEADER: + //用户-导师 + $this->types = [ImSessionTypeEnum::USER_LEAD];//导医的列表只获取跟用户的聊天,跟客服的聊天单独 + break; + case UserRoleEnum::SERVICE: + //医生-客服,导医-客服,药师-客服 + $this->types = [ImSessionTypeEnum::DOC_SERV,ImSessionTypeEnum::LEAD_SERV,ImSessionTypeEnum::DRUG_SERV]; + break; + default: + throw new Exception('参数异常'); + break; + } + return $parent; + } + + /** + * 医生和客服 + */ + + /** + * 药师和客服 + */ + + /** + * 标记已读 + */ + + /** + * @doc-name 结束会话 + * @doc-param int ims_id 会话id + * @doc-param int user_id 用户id + */ + public function actionOverSession() + { + $ims_id = \Yii::$app->request->post('ims_id'); + $user_id = \Yii::$app->request->post('user_id'); + if (!$ims_id)throw new \yii\db\Exception('会话ims_id不能为空'); + if (!$user_id)throw new \yii\db\Exception('用户id不能为空'); + $imMessageSession= ImMessageSession::find()->where([ + 'id'=>$ims_id, + 'user_id'=>$user_id, + 'service_id'=>\Yii::$app->user->identity->getId(), + 'status'=>0 + ])->one(); + if (!$imMessageSession)throw new \yii\db\Exception('聊天消息会话不存在或已结束'); + ImMessageSession::updateAll(['status'=>10], + ['id'=>$ims_id, + 'user_id'=>$user_id, + 'service_id'=>\Yii::$app->user->identity->getId()]); + + return ['会话已结束']; + } + + + /** + * @doc-name 导医客服会话列表 + * @doc-param string keyword 客户名称或者聊天记录 + * @doc-return mixed ImMessageSession{id,type,@User{name-string-名称,avatar-string-头像},noread_count-int-未读数量,@Last{created_at-int-时间,created_at_format-string-格式化时间,content-string-内容}} 会话列表 + */ + public function actionSessionList() + { + $post = \Yii::$app->request->post(); + $keyword = ArrayHelper::getValue($post,'keyword',''); + + switch(\Yii::$app->user->identity->role) + { + case UserRoleEnum::LEADER: + //用户-导医 + $types = [ImSessionTypeEnum::USER_LEAD]; + if($keyword){ + + $id_arr = User::find()->where(['like','nickname',$keyword])->select('id')->column(); + + $ims_id_arr = ImMessageSession::find()->where([ + 'service_id' => \Yii::$app->user->identity->id, + 'user_id' => $id_arr, + 'type' => $types, + 'status' => ImSessionStatusEnum::ING,//这边只查进行中的 + 'is_delete' => 0 + ])->addSelect('id')->column(); + //查询到所有符合的用户昵称的会话 + + //查询到符合内容的会话,这里的id就是满足查询条件的会话的id - 跟上边是or的关系 + $query1 = ImMessage::find()->where([ + 'service_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0, + ]) + ->andWhere([ + 'or', + ['like','content',$keyword], + ['ims_id'=>$ims_id_arr] + ]) + ->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc'); + }else{ + + //最新的消息排在最上边,不管是谁发送的,不管已读未读 + $query1 = ImMessage::find()->where([ + 'is_delete' => 0, + ])->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc'); + } + + break; + case UserRoleEnum::SERVICE: + //医生-客服,导医-客服,药师-客服 + $types = [ImSessionTypeEnum::DOC_SERV,ImSessionTypeEnum::LEAD_SERV,ImSessionTypeEnum::DRUG_SERV]; + if($keyword){ + //查询用户昵称 + $su_id_arr1 = DoctorInfo::find()->where(['like','name',$keyword])->select('su_id')->column(); + $su_id_arr2 = LeadInfo::find()->where(['like','name',$keyword])->select('su_id')->column(); + $su_id_arr3 = PharmacistrInfo::find()->where(['like','name',$keyword])->select('su_id')->column(); + + $su_id_arr = array_merge($su_id_arr1,$su_id_arr2,$su_id_arr3); + $ims_id_arr = ImMessageSession::find()->where([ + 'service_id' => \Yii::$app->user->identity->id, + 'user_id' => $su_id_arr, + 'type' => $types, + 'status' => ImSessionStatusEnum::ING,//这边只查进行中的 + 'is_delete' => 0 + ])->addSelect('id')->column(); + //查询到所有符合的用户昵称的会话 + + //查询到符合内容的会话,这里的id就是满足查询条件的会话的id - 跟上边是or的关系 + $query1 = ImMessage::find()->where([ + 'service_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0, + ])->andWhere([ + 'or', + ['like','content',$keyword], + ['ims_id'=>$ims_id_arr] + ])->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc'); + + }else{ + //最新的消息排在最上边,不管是谁发送的,不管已读未读 + $query1 = ImMessage::find()->where([ + 'is_delete' => 0, + ])->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc'); + } + break; + default: + throw new Exception('参数异常'); + break; + } + + $sessions_query = ImMessageSession::find()->alias('ims')->select([ + 'ims.*', + ])->addSelect('l.id as last_id,l.created_at as last_time')->where([ + 'ims.service_id' => \Yii::$app->user->identity->id, + 'ims.type' => $types, + 'ims.status' => ImSessionStatusEnum::ING,//这边只查进行中的 + 'ims.is_delete' => 0 + ]); + if($keyword){ + $sessions_query->innerJoin('(' . $query1->createCommand()->getRawSql() . ') l', 'ims.id = l.ims_id'); + }else{ + $sessions_query->leftJoin('(' . $query1->createCommand()->getRawSql() . ') l', 'ims.id = l.ims_id'); + }; + + $sessions = $sessions_query->orderBy('l.created_at desc,ims.id desc')->all(); + + return count($sessions) ? ArrayHelper::toArray($sessions,[ + ImMessageSession::class => [ + 'id', + 'type', + 'user' => function($model){ + switch($model->type) { + case ImSessionTypeEnum::USER_USER: + case ImSessionTypeEnum::USER_DOC: + case ImSessionTypeEnum::USER_LEAD: + + $user = User::findOne($model->user_id); + return [ + 'name' => $user->nickname, + 'avatar' => $user->avatarurl, + ]; + break; + case ImSessionTypeEnum::DOC_SERV: + return [ + 'name' => $model->serviceUserByUserId->docInfo->name, + 'avatar' => $model->serviceUserByUserId->docInfo->name, + ]; + break; + case ImSessionTypeEnum::DRUG_SERV: + return [ + 'name' => $model->serviceUserByUserId->drugInfo->name, + 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, + ]; + break; + case ImSessionTypeEnum::LEAD_SERV: + return [ + 'name' => $model->serviceUserByUserId->leadInfo->name, + 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, + ]; + break; + } + }, + 'noread_count' => function($model){ + $count = ImMessage::find()->where([ + 'ims_id' => $model->id, + 'read_status' => 0, + 'type' => ImMessageSendTypeEnum::USER_SEND, + 'is_delete' => 0 + ])->count(); + return $count; + }, + 'last' => function($model){ + $message = ImMessage::findOne($model->last_id); + if($message){ + return [ + 'created_at' => $model->last_time, + 'created_at_format' => FuncHelper::time_tran($model->last_time), + 'content' => $message->content + ]; + }else{ + return []; + } + } + ] + ]) : []; + } + + /** + * @doc-name 会话消息记录 + * @doc-param int ims_id 会话id + * @doc-param int page 页码 1 optional + * @doc-param int page_size 每页条数 20 optional + * @doc-return mixed @Session{ImMessageSession{*,@User-mixed-用户信息{name-string-名称,avatar-string-头像},@ServiceUser-mixed-服务人员信息{name-string-名称,avator-string-头像}}} 会话信息 + * @doc-return mixed @List{ImMessage{*,@User-mixed-用户信息{name-string-名称,avatar-string-头像},@ServiceUser-mixed-服务人员信息{name-string-名称,avator-string-头像}}} 消息记录 + * @doc-return mixed @Pagination{total_count-int-总数量,page_count-int-总页数,current_page-int-当前页,per_page-int-每页条数} 分页数据 + */ + public function actionMessageList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['ims_id','required'] + ]); + + $imMessageSession = ImMessageSession::find()->with('user','serviceUser')->where([ + 'id' => $post['ims_id'], + 'service_id' => \Yii::$app->user->identity->id, + ])->with('order')->one(); + $session = $imMessageSession ? ArrayHelper::toArray($imMessageSession,[ + ImMessageSession::class => [ + 'id','user_id','service_id','type','status','created_at', + 'order', + 'user' => function($model){ + switch($model->type) { +// case ImSessionTypeEnum::USER_USER: + case ImSessionTypeEnum::USER_DOC: + case ImSessionTypeEnum::USER_LEAD: + return [ + 'name' => $model->user->nickname, + 'avatar' => $model->user->avatarurl, + ]; + break; + case ImSessionTypeEnum::DOC_SERV: + return [ + 'name' => $model->serviceUserByUserId->docInfo->name, + 'avatar' => $model->serviceUserByUserId->docInfo->avatar, + ]; + break; + case ImSessionTypeEnum::DRUG_SERV: + return [ + 'name' => $model->serviceUserByUserId->drugInfo->name, + 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, + ]; + break; + case ImSessionTypeEnum::LEAD_SERV: + return [ + 'name' => $model->serviceUserByUserId->leadInfo->name, + 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, + ]; + break; + } + }, + 'serviceUser' => function($model){ + switch($model->type) { +// case ImSessionTypeEnum::USER_USER: + case ImSessionTypeEnum::USER_DOC: + return [ + 'name' => $model->serviceUser->docInfo->name, + 'avatar' => $model->serviceUser->docInfo->avatar, + ]; + break; + case ImSessionTypeEnum::USER_LEAD: + return [ + 'name' => $model->serviceUser->leadInfo->name, + 'avatar' => $model->serviceUser->leadInfo->avatar, + ]; + break; + case ImSessionTypeEnum::DOC_SERV: + case ImSessionTypeEnum::DRUG_SERV: + case ImSessionTypeEnum::LEAD_SERV: + return [ + 'name' => $model->serviceUser->servInfo->name, + 'avatar' => $model->serviceUser->servInfo->avatar, + ]; + break; + } + } + ], + Order::class => [ + 'id', + 'auto_over_time', + 'image_limit_status', + 'left_number', + 'status' => function($model){ + return Order::status_info($model); + }, + 'accept_status' => function($model){ + return Order::accept_info($model); + }, + ] + ]) : []; + $this->extend_result['session'] = $session; + + $query = ImMessage::find()->where([ + 'ims_id' => $post['ims_id'], + 'service_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->with('imSession','user','serviceUser')->orderBy('id desc'); + $this->field = [ + ImMessage::class => [ + 'id','user_id','service_id','content','read_status','type','created_at', + 'user' => function($model){ + switch($model->imSession->type) { +// case ImSessionTypeEnum::USER_USER: + case ImSessionTypeEnum::USER_DOC: + case ImSessionTypeEnum::USER_LEAD: + return [ + 'name' => $model->user->nickname, + 'avatar' => $model->user->avatarurl, + ]; + break; + case ImSessionTypeEnum::DOC_SERV: + return [ + 'name' => $model->serviceUserByUserId->docInfo->name, + 'avatar' => $model->serviceUserByUserId->docInfo->avatar, + ]; + break; + case ImSessionTypeEnum::DRUG_SERV: + return [ + 'name' => $model->serviceUserByUserId->drugInfo->name, + 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, + ]; + break; + case ImSessionTypeEnum::LEAD_SERV: + return [ + 'name' => $model->serviceUserByUserId->leadInfo->name, + 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, + ]; + break; + } + }, + 'serviceUser' => function($model){ + switch($model->imSession->type) { +// case ImSessionTypeEnum::USER_USER: + case ImSessionTypeEnum::USER_DOC: + return [ + 'name' => $model->serviceUser->docInfo->name, + 'avatar' => $model->serviceUser->docInfo->avatar, + ]; + break; + case ImSessionTypeEnum::USER_LEAD: + return [ + 'name' => $model->serviceUser->leadInfo->name, + 'avatar' => $model->serviceUser->leadInfo->avatar, + ]; + break; + case ImSessionTypeEnum::DOC_SERV: + case ImSessionTypeEnum::DRUG_SERV: + case ImSessionTypeEnum::LEAD_SERV: + return [ + 'name' => $model->serviceUser->servInfo->name, + 'avatar' => $model->serviceUser->servInfo->avatar, + ]; + break; + } + } + ], + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 待接入会话列表 + * @doc-return mixed ImMessageSession{id,@User{name,avatar},@Last{content-string-消息内容,created_at-int-消息时间,created_at_format-string-格式后的时间}} 待接入会话列表 + */ + public function actionWaitInList() + { + //这个就按最新的待接入会话在最上边 + $query = ImMessageSession::find()->where([ + 'service_id' => 0, + 'type' => $this->types, + 'status' => ImSessionStatusEnum::ING + ])->orderBy('id desc'); + + $sessions = $query->with('user','serviceUser')->all(); + + return count($sessions) ? ArrayHelper::toArray($sessions,[ + ImMessageSession::class => [ + 'id' => 'id', + 'user' => function($model){ + switch($model->type) { + case ImSessionTypeEnum::USER_USER: + case ImSessionTypeEnum::USER_DOC: + case ImSessionTypeEnum::USER_LEAD: + return [ + 'name' => $model->user->nickname, + 'avatar' => $model->user->avatarurl, + ]; + break; + case ImSessionTypeEnum::DOC_SERV: + return [ + 'name' => $model->serviceUserByUserId->docInfo->name, + 'avatar' => $model->serviceUserByUserId->docInfo->avatar, + ]; + break; + case ImSessionTypeEnum::DRUG_SERV: + return [ + 'name' => $model->serviceUserByUserId->drugInfo->name, + 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, + ]; + break; + case ImSessionTypeEnum::LEAD_SERV: + return [ + 'name' => $model->serviceUserByUserId->leadInfo->name, + 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, + ]; + break; + } + }, + 'last' => function($model){ + $message = ImMessage::find()->where([ + 'ims_id' => $model->id, + 'user_id' => $model->user_id, + 'is_delete' => 0 + ])->orderBy('id desc')->one(); + if($message){ + return [ + 'content' => $message->content, + 'created_at' => $message->created_at, + 'created_at_format' => FuncHelper::time_tran($message->created_at) + ]; + }else{ + return []; + } + } + ] + ]) : []; + } + + /** + * @doc-name 接入会话 + * @doc-param ims_id 会话id + */ + public function actionSessionIn() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['ims_id','required'] + ]); + + $model = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + 'type' => $this->types, + 'service_id' => 0, + 'status' => ImSessionStatusEnum::ING + ])->one(); + if(!$model){ + throw new Exception('待接入会话不存在'); + } + + $count = ImMessageSession::updateAll(['service_id'=>\Yii::$app->user->identity->id,'in_time'=>time()],[ + 'id' => $post['ims_id'], + 'type' => $this->types, + 'service_id' => 0, + 'status' => ImSessionStatusEnum::ING + ]); + if(!$count){ + throw new Exception('接入失败'); + } + ImMessage::updateAll(['service_id'=>\Yii::$app->user->identity->id],[ + 'ims_id' => $post['ims_id'] + ]); + + //这里可以给用户发一个已接入的提醒 + + //这里进行接入的消息发送 + $form = new ImMessageForm(); + $form->sessionIn($post['ims_id'],0,\Yii::$app->user->identity->role,[ + 'type' => 'session-in' //定义的类型是接入 + ]); + + return []; + } + + /** + * @doc-name 服务端发送消息 + * @doc-desc session_type直接传递用会话返回的会话类型,如果是医生药师导医端和客服的会话,第一次可能没有会话id,则直接会话id=0,会话类型当前角色+4客服 = 567,否则直接传递会话id和会话类型,客服现在只能接入医生药师导医的会话,所以会有会话id和session_type + * @doc-param int ims_id 会话id + * @doc-param int session_type 会话类型1医生发给用户3导医发给用户5医生和客服会话6药师和客服7导医和客服 + * @doc-param json content 消息内容 + */ + public function actionMessageSend() + { + //服务端发送消息 + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + [['ims_id','session_type'],'required'], + ['content','required','message'=>'消息内容不能为空'] + ]); + + $form = new ImMessageForm(); + $form->attributes = $post; + $form->from_id = \Yii::$app->user->identity->id; + + switch($post['session_type']) + { + case ImSessionTypeEnum::USER_DOC: //医生给用户发消息 + + $form->type = ImMessageSendTypeEnum::SERVICE_SEND; + $ims = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + 'is_delete' => 0 + ])->with('order')->one(); + if(!$ims || !$ims->order){ + throw new Exception('会话不存在或者会话订单不存在'); + } + $order = $ims->order; + + $form->to_id = $ims->user_id; + + if($order->accept_status == OrderAcceptEnum::ACCEPTING ){ + $form->sendMessage(); + }else{ + //其他情况-拒绝 + throw new Exception('发送失败:订单非接诊状态,无法发送消息'); + } + return []; + + break; + case ImSessionTypeEnum::USER_LEAD: //导医给用户发消息 - 如果已经结束,则不能再发送 - 在下一步有判断 + + $form->type = ImMessageSendTypeEnum::SERVICE_SEND; + $ims = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + 'service_id' => \Yii::$app->user->identity->id, + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status' => ImSessionStatusEnum::ING + ])->one(); + if(!$ims){ + throw new Exception('会话不存在'); + } + + $form->to_id = $ims->user_id; + $form->sendMessage(); + + break; + + case ImSessionTypeEnum::DOC_SERV://有可能是医生给客服发,也可能是客服给医生发 - 取决于当前的角色 + + if(\Yii::$app->user->identity->role == UserRoleEnum::DOCTOR){//医生给客服发,当前医生相当于user_id,客服相当与service_id + + $form->type = ImMessageSendTypeEnum::USER_SEND; + $query = ImMessageSession::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status' => ImSessionStatusEnum::ING + ]); + if($post['ims_id']){ + $query->andWhere([ + 'id' => $post['ims_id'] + ]); + } + $ims = $query->one(); + if(!$ims){ + $ims = new ImMessageSession(); + $ims->user_id = \Yii::$app->user->identity->id; + $ims->type = $post['session_type']; + $ims->saveOrFail(); + } + + $form->ims_id = $ims->id; + $form->to_id = $ims->service_id; + $form->sendMessage(); + + }elseif(\Yii::$app->user->identity->role == UserRoleEnum::SERVICE){//客服给医生发 + + $form->type = ImMessageSendTypeEnum::SERVICE_SEND; + + $ims = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + 'service_id' => \Yii::$app->user->identity->id, + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status' => ImSessionStatusEnum::ING + ])->one(); + + $form->to_id = $ims->user_id; + $form->sendMessage(); + + }else{ + throw new Exception('客户端传递参数错误'); + } + + break; + case ImSessionTypeEnum::LEAD_SERV://有可能是导医给客服发,也可能是客服给导医发 + + if(\Yii::$app->user->identity->role == UserRoleEnum::LEADER){//导师给客服发,当前导师相当于user_id,客服相当与service_id + + $form->type = ImMessageSendTypeEnum::USER_SEND; + $query = ImMessageSession::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status' => ImSessionStatusEnum::ING + ]); + if($post['ims_id']){ + $query->andWhere([ + 'id' => $post['ims_id'] + ]); + } + $ims = $query->one(); + if(!$ims){ + $ims = new ImMessageSession(); + $ims->user_id = \Yii::$app->user->identity->id; + $ims->type = $post['session_type']; + $ims->saveOrFail(); + } + + $form->ims_id = $ims->id; + $form->to_id = $ims->service_id; + $form->sendMessage(); + + }elseif(\Yii::$app->user->identity->role == UserRoleEnum::SERVICE){//客服给导师发 + + $form->type = ImMessageSendTypeEnum::SERVICE_SEND; + $ims = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + 'service_id' => \Yii::$app->user->identity->id, + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status' => ImSessionStatusEnum::ING + ])->one(); + $form->to_id = $ims->user_id; + $form->sendMessage(); + + }else{ + throw new Exception('客户端传递参数错误'); + } + + break; + case ImSessionTypeEnum::DRUG_SERV://有可能是药师给客服发,也可能是客服给药师发 + + if(\Yii::$app->user->identity->role == UserRoleEnum::DRUG){//药师给客服发 + + $form->type = ImMessageSendTypeEnum::USER_SEND; + $query = ImMessageSession::find()->where([ + 'user_id' => \Yii::$app->user->identity->id, + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status' => ImSessionStatusEnum::ING + ]); + if($post['ims_id']){ + $query->andWhere([ + 'id' => $post['ims_id'] + ]); + } + $ims = $query->one(); + if(!$ims){ + $ims = new ImMessageSession(); + $ims->user_id = \Yii::$app->user->identity->id; + $ims->type = $post['session_type']; + $ims->saveOrFail(); + } + + $form->ims_id = $ims->id; + $form->to_id = $ims->service_id; + $form->sendMessage(); + + }elseif(\Yii::$app->user->identity->role == UserRoleEnum::SERVICE){//客服给药师发 + + $form->type = ImMessageSendTypeEnum::SERVICE_SEND; + $ims = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + 'service_id' => \Yii::$app->user->identity->id, + 'type' => $post['session_type'], + 'is_delete' => 0, + 'status' => ImSessionStatusEnum::ING + ])->one(); + + $form->to_id = $ims->user_id; + $form->sendMessage(); + + }else{ + throw new Exception('客户端传递参数错误'); + } + break; + } + return []; + } +} diff --git a/service/modules/v1/controllers/ImageOrderController.php b/service/modules/v1/controllers/ImageOrderController.php new file mode 100644 index 0000000..5a30260 --- /dev/null +++ b/service/modules/v1/controllers/ImageOrderController.php @@ -0,0 +1,650 @@ +where([ + 'su_id' => \Yii::$app->user->identity->id, + 'type' => 1, + 'is_pay' => 1, + 'accept_status' => OrderAcceptEnum::WAIT_ACCEPT, + ])->count(); + $wait_accepting_count = (int)Order::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'type' => 1, + 'is_pay' => 1, + 'accept_status' => OrderAcceptEnum::ACCEPTING, + ])->count(); + $wait_over_count = (int)Order::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'type' => 1, + 'is_pay' => 1, + 'accept_status' => [OrderAcceptEnum::REFUSED, OrderAcceptEnum::OVER, OrderAcceptEnum::TIMEOUT_ACCEPT, OrderAcceptEnum::CANCEL] + ])->count(); + + return [ + 'wait_accept_count' => $wait_accept_count, + 'wait_accepting_count' => $wait_accepting_count, + 'wait_over_count' => $wait_over_count, + ]; + } + + /** + * @doc-name 咨询列表 + * @doc-param int status 0全部1待接诊2咨询中3已结束 0 optional + * @doc-param int type 1图文2视频 + * @doc-param int page 页码 1 optional + * @doc-param int page_size 每页条数 20 optional + * @doc-return mixed @List{Order{id,user_id-int-用户,type-int-订单类型1图文2视频,avatarurl-string-用户头像,@Accept_info{status-int-状态,text-string-列表文字描述,text_detail-string-详情描述},@Message{no_read-int-未读条数,message-string-最新消息,message_time-int-发送时间,message_time_format-string-格式化时间},@Patient{id-int-患者问诊id,name-string-姓名,sex-int-1男2女,age-int-年龄}}} 咨询列表 + * @doc-return mixed @Pagination{total_count-int-总数量,page_count-int-总页数,current_page-int-当前页,per_page-int-每页条数} 分页数据 + */ + public function actionList() + { + $post = \Yii::$app->request->post(); + $query = Order::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'type' => $post['type'] ?? 1, + 'is_pay' => 1 + ])->with('inquiry','session','user')->orderBy(['id'=>SORT_DESC]); + + $status = ArrayHelper::getValue($post,'status',0); + switch($status){ + case 1: + $query->andWhere([ + 'accept_status' => OrderAcceptEnum::WAIT_ACCEPT + ]); + break; + case 2: + $query->andWhere([ + 'accept_status' => OrderAcceptEnum::ACCEPTING + ]); + break; + case 3: + $query->andWhere([ + 'accept_status' => [OrderAcceptEnum::REFUSED,OrderAcceptEnum::OVER,OrderAcceptEnum::TIMEOUT_ACCEPT,OrderAcceptEnum::CANCEL] + ]); + break; + default: + $query->andWhere([ + '<>','accept_status',[OrderAcceptEnum::NO,OrderAcceptEnum::CANCEL] + ]); + break; + } + + $this->field = [ + Order::class => [ + 'id', 'user_id', 'up_id', 'type', + 'avatarurl' => 'user.avatarurl', + 'accept_info' => function($model){ + return Order::accept_info($model); + }, + 'ims_id' => 'session.ims_id', + 'message' => function($model){ + + $ims_id = $model->session->ims_id; + $count = ImMessage::find()->where([ + 'ims_id' => $ims_id, + 'user_id' => $model->user_id, + 'service_id' => \Yii::$app->user->identity->id, +// 'content_type' => ImMessageTypeEnum::COMMON, + 'read_status' => 0, + 'type' => ImMessageSendTypeEnum::USER_SEND, + 'is_delete' => 0 + ])->count(); + + //未接诊获取第一条病情描述,接诊了获取最新的一条消息 + if($model->accept_status == OrderAcceptEnum::WAIT_ACCEPT){ + $new = ImMessage::find()->where([ + 'ims_id' => $ims_id, + 'user_id' => $model->user_id, + 'service_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->orderBy('id asc')->one(); + }else{ + $new = ImMessage::find()->where([ + 'ims_id' => $ims_id, + 'user_id' => $model->user_id, + 'service_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->orderBy('id desc')->one(); + } + + return [ + 'no_read' => $count, + 'message' => $new->content, + 'message_time' => $new->created_at, + 'message_time_format' => FuncHelper::time_tran($new->created_at) + ]; + }, + 'patient' => function($model){ + $patient_data = json_decode($model->inquiry->patient_data,true); + + return [ + 'id' => $model->inquiry->id, + 'name' => $patient_data['name'], + 'sex' => $patient_data['sex'], + 'age' => FuncHelper::getAgeFromIdNo($patient_data['id_card']), + ]; + }, + ], + ]; + + return $this->create($query, $post); + } + + /** + * @doc-name 最新消息 + * @doc-param int page 页码 1 optional + * @doc-param int page_size 每页条数 20 optional + * @doc-return mixed @List{Order{id,user_id-int-用户,type-int-订单类型1图文2视频,avatarurl-string-用户头像,@Accept_info{status-int-状态,text-string-列表文字描述,text_detail-string-详情描述},@Message{no_read-int-未读条数,message-string-最新消息,message_time-int-发送时间,message_time_format-string-格式化时间},@Patient{id-int-患者问诊id,name-string-姓名,sex-int-1男2女,age-int-年龄}}} 咨询列表 + * @doc-return mixed @Pagination{total_count-int-总数量,page_count-int-总页数,current_page-int-当前页,per_page-int-每页条数} 分页数据 + */ + public function actionNewList() + { + $post = \Yii::$app->request->post(); + $query = Order::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'is_pay' => 1 + ])->with('inquiry', 'session', 'user')->orderBy('id desc'); + $query->where(['in', 'accept_status', [OrderAcceptEnum::WAIT_ACCEPT, OrderAcceptEnum::ACCEPTING]]); + $this->field = [ + Order::class => [ + 'id', 'user_id', 'up_id', 'type', + 'avatarurl' => 'user.avatarurl', + 'accept_info' => function ($model) { + return Order::accept_info($model); + }, + 'ims_id' => 'session.ims_id', + 'message' => function ($model) { + + $ims_id = $model->session->ims_id; + $count = ImMessage::find()->where([ + 'ims_id' => $ims_id, + 'user_id' => $model->user_id, + 'service_id' => \Yii::$app->user->identity->id, +// 'content_type' => ImMessageTypeEnum::COMMON, + 'read_status' => 0, + 'type' => ImMessageSendTypeEnum::USER_SEND, + 'is_delete' => 0 + ])->count(); + + //未接诊获取第一条病情描述,接诊了获取最新的一条消息 + if ($model->accept_status == OrderAcceptEnum::WAIT_ACCEPT) { + $new = ImMessage::find()->where([ + 'ims_id' => $ims_id, + 'user_id' => $model->user_id, + 'service_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->orderBy('id asc')->one(); + } else { + $new = ImMessage::find()->where([ + 'ims_id' => $ims_id, + 'user_id' => $model->user_id, + 'service_id' => \Yii::$app->user->identity->id, + 'is_delete' => 0 + ])->orderBy('id desc')->one(); + } + + return [ + 'no_read' => $count, + 'message' => $new->content ?? '', + 'message_time' => $new->created_at ?? '', + 'message_time_format' => $new ? FuncHelper::time_tran($new->created_at) : '', + ]; + }, + 'patient' => function ($model) { + $patient_data = json_decode($model->inquiry->patient_data, true); + + return [ + 'id' => $model->inquiry->id, + 'name' => $patient_data['name'], + 'sex' => $patient_data['sex'], + 'age' => FuncHelper::getAgeFromIdNo($patient_data['id_card']), + ]; + }, + ], + ]; + + return $this->create($query, $post); + } + + /** + * @doc-name 读取消息 + * @doc-param int ims_id 会话id + * @doc-param int up_id 就诊人id + * @doc-return string up_id 就诊人id + */ + public function actionReadMsg() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['ims_id', 'required'], + ['up_id', 'required'] + ]); + + \Yii::$app->db->createCommand() + ->update('yii_im_message', ['read_status' => 1], ['ims_id' => $post['ims_id'], 'service_id' => \Yii::$app->user->identity->id]) + ->execute(); + + return ['up_id' => $post['up_id']]; + } + + /** + * @doc-name 咨询详情 + * @doc-param int order_id 订单id + * @doc-return mixed Order{id,auto_over_time,@Accept_info{status-int-状态,text-string-列表文字描述,text_detail-string-详情描述},@Patient{id-int-患者问诊id,name-string-姓名,sex-int-1男2女,age-int-年龄}} 咨询详情 + */ + public function actionInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $info = Order::find()->where([ + 'id' => $post['order_id'], + 'su_id' => \Yii::$app->user->identity->id, + ])->with('inquiry','session')->one(); + if(!$info){ + throw new Exception('订单不存在'); + } + return ArrayHelper::toArray($info,[ + Order::class => [ + 'id','auto_over_time', + 'accept_info' => function($model){ + return Order::accept_info($model); + }, + 'ims_id' => 'session.ims_id', + 'patient' => function($model){ + $patient_data = json_decode($model->inquiry->patient_data,true); + return [ + 'id' => $model->inquiry->id, + 'name' => $patient_data['name'], + 'sex' => $patient_data['sex'], + 'age' => FuncHelper::getAgeFromIdNo($patient_data['id_card']), + ]; + }, + ] + ]); + } + + /** + * @doc-name 获取患者详情 + * @doc-param int order_id 订单id + * @doc-return mixed UserInquiry{liver_function,renal_function,allergic_status,allergic_history,person_status,person_history,family_status,family_history,@Patient_data{age-int-年龄,UserPatient{*}}} 患者信息 + */ + public function actionPatientInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $info = Order::find()->where([ + 'id' => $post['order_id'], + 'su_id' => \Yii::$app->user->identity->id, + ])->with('inquiry')->one(); + if(!$info){ + throw new Exception('订单不存在'); + } + return $info->inquiry ? ArrayHelper::toArray($info->inquiry,[ + UserInquiry::class => [ + 'liver_function','renal_function','allergic_status','allergic_history','person_status','person_history','family_status','family_history', + 'patient_data' => function($model){ + $patient_data = json_decode($model->patient_data,true); + $patient_data['age'] = FuncHelper::getAgeFromIdNo($patient_data['id_card']); + return $patient_data; + } + ] + ]) : []; + } + + /** + * @doc-name 退诊原因 + * @doc-return mixed InquiryRefuseReason{*} 退诊原因列表 + */ + public function actionRefuseReason() + { + $all = InquiryRefuseReason::find()->orderBy('id asc')->all(); + return $all; + } + + /** + * @doc-name 退诊 + * @doc-param int order_id 订单id + * @doc-param int reason_id 退针原因id + */ + public function actionRefuse() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'], + ['reason_id','required','message'=>'请选择退诊原因'] + ]); + $info = Order::find()->where([ + 'id' => $post['order_id'], + 'su_id' => \Yii::$app->user->identity->id, + ])->with('inquiry','session','serviceUser')->one(); + if(!$info){ + throw new Exception('订单不存在'); + } + $order = $info; + + $reason = InquiryRefuseReason::findOne($post['reason_id']); + if(!$reason){ + throw new Exception('退诊原因不存在'); + } + if(!$order->session->ims_id){ + throw new Exception('缺少会话,请联系开发者'); + } + $imMessageSession = ImMessageSession::findOne($order->session->ims_id); + if(!$imMessageSession){ + throw new Exception('缺少会话,请联系开发者'); + } + + $t = \Yii::$app->db->beginTransaction(); + try { + //订单状态变更 - 退诊-取消-退款 + //生成记录 + $orderRefund = new OrderRefund(); + $orderRefund->user_id = $order->user_id; + $orderRefund->order_id = $order->id; + $orderRefund->refund_no = FuncHelper::generate_order_no('RF'); + $orderRefund->refund_price = $order->total_pay_price; + $orderRefund->remark = '医生拒诊取消'; + $orderRefund->saveOrFail(); + + //取消状态 + $order->cancel_status = 1; + $order->cancel_time = time(); + $order->cancel_remark = '医生拒诊取消'; + //接诊状态 + $order->accept_status = OrderAcceptEnum::REFUSED; + $order->refuse_time = time(); + //退款状态 + $order->refund_status = 1; + $order->refund_time = time(); + $order->saveOrFail(); + //退款操作 + $refundForm = new \common\forms\OrderRefundForm(); + $refundForm->refundMoney($orderRefund); + + //------------------------------发消息------------------------------- + //以医生身份给用户发一条退诊消息 + $message = [ + 'type' => 'text', + 'from_User' => [ + 'id' => $order->su_id, + 'name' => $order->serviceUser->docInfo->name, + 'avatar' => $order->serviceUser->docIdentity->work_avator + ], + 'data' => [ + 'text' => $reason['reason_message'] + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $order->session->ims_id; + $form->from_id = $order->su_id; + $form->to_id = $order->user_id; + $form->type = ImMessageSendTypeEnum::SERVICE_SEND;//!! + $form->content = json_encode($message); + $form->sendMessage(); + + //以用户身份给医生发送一条event类型的消息 + $message = [ + 'type' => 'end', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => '退诊成功,问诊费用已退回患者账户' + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $order->session->ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + + //以医生身份给用户发送一条event类型的消息 + $message = [ + 'type' => 'end', + 'from_User' => [ + 'id' => $order->su_id, + 'name' => $order->serviceUser->docInfo->name, + 'avatar' => $order->serviceUser->docIdentity->work_avator + ], + 'data' => [ + 'text' => '问诊结束,问诊费用已退回账户' + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $order->session->ims_id; + $form->from_id = $order->su_id; + $form->to_id = $order->user_id; + $form->type = ImMessageSendTypeEnum::SERVICE_SEND;//!! + $form->content = json_encode($message); + $form->sendMessage(); + //----------------------------发消息----------------------------------- + + //结束消息会话 + $imMessageSession->status = ImSessionStatusEnum::END; + $imMessageSession->saveOrFail(); + $t->commit(); + + }catch (Exception $exception) { + $t->rollBack(); + throw new Exception('退诊失败:'.$exception->getMessage()); + } + return []; + } + + /** + * @doc-name 接诊 + * @doc-param int order_id 订单id + */ + public function actionAccess() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['order_id','required'] + ]); + $info = Order::find()->where([ + 'id' => $post['order_id'], + 'su_id' => \Yii::$app->user->identity->id, + ])->with('inquiry','session','serviceUser')->one(); + if(!$info){ + throw new Exception('订单不存在'); + } + $order = $info; + + $t = \Yii::$app->db->beginTransaction(); + try { + //修改订单状态 + $order->accept_status = OrderAcceptEnum::ACCEPTING; + $order->accept_time = time(); + //接诊自动结束 + $config = \Yii::$app->params; + $auto_accept_over_time = isset($config['order']['accept_over_time']) ? $config['order']['accept_over_time'] : 24*60*60; + $auto_over_time = time() + $auto_accept_over_time; + $order->auto_over_time = $auto_over_time; + $order->saveOrFail(); + + //--------------------------------------------发消息-------------------------------------------------------- + //先以用户身份给医生发送一条事件消息 + $message = [ + 'type' => 'end', + 'from_User' => [ + 'id' => $order->user->id, + 'name' => $order->user->nickname, + 'avatar' => $order->user->avatarurl + ], + 'data' => [ + 'text' => '问诊已开始,请及时回复' + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $order->session->ims_id; + $form->from_id = $order->user_id; + $form->to_id = $order->su_id; + $form->type = ImMessageSendTypeEnum::USER_SEND; + $form->content = json_encode($message); + $form->sendMessage(); + //以医生身份给用户发送一条event的消息 + $message = [ + 'type' => 'end', + 'from_User' => [ + 'id' => $order->su_id, + 'name' => $order->serviceUser->docInfo->name, + 'avatar' => $order->serviceUser->docIdentity->work_avator + ], + 'data' => [ + 'text' => '问诊已开始,本次问诊可持续'.FuncHelper::time_left($auto_accept_over_time), + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $order->session->ims_id; + $form->from_id = $order->su_id; + $form->to_id = $order->user_id; + $form->type = ImMessageSendTypeEnum::SERVICE_SEND;//!! + $form->content = json_encode($message); + $form->sendMessage(); + + //以医生身份给用户发送一条notice的消息 + $message = [ + 'type' => 'system', + 'from_User' => [ + 'id' => $order->su_id, + 'name' => $order->serviceUser->docInfo->name, + 'avatar' => $order->serviceUser->docIdentity->work_avator + ], + 'data' => [ + 'text' => '医生已接诊,稍后将与您联系,您可继续补充问诊内容,如目前症状、患病时长、检查及用药情况、需要的帮助等,医生看到后将及时回复您,线上咨询不能代替面诊,医生的回复仅为建议', + ], + ]; + $form = new ImMessageForm(); + $form->ims_id = $order->session->ims_id; + $form->from_id = $order->su_id; + $form->to_id = $order->user_id; + $form->type = ImMessageSendTypeEnum::SERVICE_SEND;//!! + $form->content = json_encode($message); + $form->sendMessage(); + + //-----------------------------------------------发消息---------------------------------------------------- + //发送问诊结束队列 + \Yii::$app->queue->delay($auto_accept_over_time)->push(new OrderOverJob([ + 'orderId' => $order->id, + ])); + + $t->commit(); + }catch (Exception $exception){ + $t->rollBack(); + throw new Exception('接诊失败:'.$exception->getMessage()); + } + return []; + } + + /** + * @doc-name 医生赠送条数 + * @doc-param int ims_id 会话id + * @doc-param int number 赠送条数 + */ + public function giveNumber() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['ims_id','required'], + ['number','required','message'=>'赠送条数不能为空'], + ['number','integer','赠送数量只能是正整数'] + ]); + $number = ArrayHelper::getValue($post,'number',0); + if($number <= 0){ + throw new Exception('赠送数量只能是正整数'); + } + + //查询会话 + $ims = ImMessageSession::find()->where([ + 'id' => $post['ims_id'], + ])->with('order')->one(); + if(!$ims || $ims->status == ImSessionStatusEnum::END){ + throw new Exception('会话不存在或已结束'); + } + if(!$ims->order || $ims->order->accept_status != OrderAcceptEnum::ACCEPTING){ + throw new Exception('会话订单不存在或未接诊状态'); + } + + $model = new OrderNumberChange(); + $model->order_id = $ims->order->id; + $model->number = $number; + $model->type = NumberChangeTypeEnum::GIVE; + $model->saveOrFail(); + + return []; + } + + /** + * 设为精选 + */ + public function setBest() + { + + } + + /** + * @doc-name 结束问诊 + * @doc-param int order_id 订单id + */ + public function actionOrderOver() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + $info = Order::find()->where([ + 'id' => $post['order_id'], + 'su_id' => \Yii::$app->user->identity->id, + ])->with('inquiry', 'session')->one(); + if (!$info) { + throw new Exception('订单不存在'); + } + if ($info->accept_status != OrderAcceptEnum::ACCEPTING) { + throw new Exception('订单当前非接诊中,无法结束'); + } + $info->accept_status = OrderAcceptEnum::OVER; + $info->saveOrFail(); + + return ['结束成功']; + } +} diff --git a/service/modules/v1/controllers/LeaderController.php b/service/modules/v1/controllers/LeaderController.php new file mode 100644 index 0000000..a907847 --- /dev/null +++ b/service/modules/v1/controllers/LeaderController.php @@ -0,0 +1,99 @@ +request->post(); + $keyword = $post['keyword']; + $query = ServiceUser::find()->alias('su')->where([ + 'su.role' => UserRoleEnum::DOCTOR, + 'su.status' => UserStatusEnum::OK, + 'su.is_delete' => 0 + ])->orderBy(['id'=>SORT_DESC]); + + $depart_arr = json_decode(ArrayHelper::getValue($post, 'depart_id', "[]"), true); + + $departs = HospitalDepartment::find()->select('id,name')->where(['<>', 'id', 0])->asArray()->all(); + $id = 0; + foreach ($departs as $v) { + if (in_array($keyword, $v)) { + $id = $v['id']; + } + } + + $query->joinWith(['docInfo' => function ($q) use ($id, $keyword, $depart_arr) { + $q->alias('i'); + // 搜索框搜索姓名和科室 + if (!empty($keyword)) { + $q->andWhere([ + 'or', + ['like', 'i.name', $keyword], + ['i.depart_id' => $id] + ]); + } + // 科室搜索 + if (!empty($depart_arr)) { + $q->andWhere([ + 'i.depart_id' => $depart_arr + ]); + } + }]); + + $this->field = [ + ServiceUser::class => [ + 'id', + 'avator' => 'docIdentity.work_avator', + 'name' => 'docInfo.name', + 'depart' => 'docInfo.depart.name', + 'hospital' => 'docInfo.hospital.name', + 'yard' => 'docInfo.yard.name', + 'title' => 'docInfo.title.name', + 'inquiry_num' => 'docInfo.inquiries', + ], + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 切换在线状态 + * @doc-param int online 0不在线1在线 + */ + public function actionChangeOnline() + { + $online = \Yii::$app->request->post('online'); + $user = \Yii::$app->user->identity; + $user->im_status = $online; + $user->save(); + return ['切换成功']; + } + + /** + * @doc-name 获取空闲导医 + */ + public function actionGetFreeLeaders() + { + return LeadInfo::getLastLeadUserId(); + } +} diff --git a/service/modules/v1/controllers/OrderVideoController.php b/service/modules/v1/controllers/OrderVideoController.php new file mode 100644 index 0000000..764fa17 --- /dev/null +++ b/service/modules/v1/controllers/OrderVideoController.php @@ -0,0 +1,176 @@ +params['tencent_video']; + $api = new \Tencent\TLSSigAPIv2($config['appid'], $config['secret']); + $user_id = 'service_' . \Yii::$app->user->identity->getId(); + $key = $api->genUserSig($user_id); + + return [ + 'appid' => $config['appid'], + 'key' => $key, + 'user_id' => $user_id, + ]; + } + + /** + * @doc-name 视频基础信息 + * @doc-param order_id int 订单id + * @doc-return is_limit int 0不限制1限制 + * @doc-return left_minutes int 剩余分钟数 + */ + public function actionVideoInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'] + ]); + /* @var Order $order */ + $order = Order::find()->where([ + 'id' => $post['order_id'], + 'su_id' => \Yii::$app->user->identity->id, + ])->with('video')->one(); + if (!$order || !$order['video']) { + throw new Exception('订单不存在'); + } + if ($order->accept_status != OrderAcceptEnum::ACCEPTING) { + throw new Exception('订单状态非接诊中'); + } + if ($order->type != 2) { + throw new Exception('您的订单非视频问诊订单'); + } + + /* @var OrderVideoInfo $video */ + $video = $order['video']; + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + } + + /** + * @doc-name 视频通话处理 + * @doc-param order_id int 订单id + * @doc-param type string 类型start开始视频sign上报扣除end结束视频 + * @doc-return is_limit int 0不限制1限制 + * @doc-return left_minutes int 剩余分钟数 + */ + public function actionVideoSign() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['order_id', 'required'], + ['type', 'required'], + ]); + /* @var Order $order */ + $order = Order::find()->where([ + 'id' => $post['order_id'], + 'su_id' => \Yii::$app->user->identity->id, + ])->with('video')->one(); + if (!$order || !$order['video']) { + throw new Exception('订单不存在'); + } + if ($order->accept_status != OrderAcceptEnum::ACCEPTING) { + throw new Exception('订单状态非接诊中'); + } + if ($order->type != 2) { + throw new Exception('您的订单非视频问诊订单'); + } + + /* @var OrderVideoInfo $video */ + $video = $order['video']; + if ($video->is_limit == 0) { + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + } + switch ($post['type']) { + // 开始视频 + case 'start': + if ($video->left_minutes <= 0) { + throw new Exception('通话时长不足'); + } + $now = Carbon::now()->toDateTimeString(); + if (!$video->start_at) { + $video->start_at = $now; + } + $video->last_start_left_minutes = $video->left_minutes; + $video->last_start_at = $now; + + $info = $video->info ? json_decode($video->info, true) : []; + $info[] = [ + 'time' => $now, + 'desc' => '开始视频通话', + 'left_minutes' => $video->left_minutes, + ]; + $video->info = json_encode($info); + $video->save(); + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + break; + // 上报扣除 + case 'sign': + if ($video->left_minutes <= 0) { + throw new Exception('通话时长不足'); + } + $now = Carbon::now()->toDateTimeString(); + $video->start_at = $now; + $left_minutes = $video->last_start_left_minutes - Carbon::now()->diffInRealMinutes($video->last_start_at); + $video->left_minutes = max($left_minutes, 0); + $video->last_limit_at = $now; + + $info = $video->info ? json_decode($video->info, true) : []; + $info[] = [ + 'time' => $now, + 'desc' => '扣除时长', + 'left_minutes' => $video->left_minutes, + ]; + $video->info = json_encode($info); + $video->save(); + return [ + 'is_limit' => $video->is_limit, + 'left_minutes' => $video->left_minutes, + ]; + break; + // 结束视频 + case 'end': + $now = Carbon::now()->toDateTimeString(); + $video->end_at = $now; + $left_minutes = $video->last_start_left_minutes - Carbon::now()->diffInRealMinutes($video->last_start_at); + $video->left_minutes = max($left_minutes, 0); + + $info = $video->info ? json_decode($video->info, true) : []; + $info[] = [ + 'time' => $now, + 'desc' => '结束视频通话', + 'left_minutes' => $video->left_minutes, + ]; + $video->info = json_encode($info); + $video->save(); + return ['通话已结束']; + break; + } + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/PatientController.php b/service/modules/v1/controllers/PatientController.php new file mode 100644 index 0000000..6e588a1 --- /dev/null +++ b/service/modules/v1/controllers/PatientController.php @@ -0,0 +1,503 @@ +request->post('keyword'); + $query = DoctorPatient::find() + ->with('tags') + ->where(['su_id' => \Yii::$app->user->identity->getId()]) + ->orderBy(['id'=>SORT_DESC]); + + $this->field = [ + DoctorPatient::class => [ + 'id', 'user_id', 'su_id', 'up_id', 'name', 'sex', 'avatar', + 'age' => function ($model) { + return FuncHelper::getAgeFromIdNo($model['id_card']); + }, + 'tags' => function ($model) { + return $model->tags; + } + ] + ]; + if ($keyword) { + $query->andFilterWhere(['like', 'name', $keyword]); + } + + return $this->create($query, \Yii::$app->request->post()); + } + + /** + * @doc-name 添加就诊记录 + * @doc-param int up_id 就诊人id + * @doc-param string main_suit 主诉 + * @doc-param string diagnose 诊断 + */ + public function actionAddRecord() + { + $request = \Yii::$app->request; + $param = $request->post(); + $this->requestValidate($param, [ + ['up_id', 'required'], + ['main_suit', 'required'], + ['diagnose', 'required'], + ]); + \Yii::$app->db->createCommand()->insert('yii_patient_visit_record', [ + 'su_id' => \Yii::$app->user->identity->id, + 'up_id' => $param['up_id'], + 'main_suit' => $param['main_suit'], + 'diagnose' => $param['diagnose'], + ])->execute(); + } + + /** + * @doc-name 就诊记录列表 + * @doc-param int up_id 就诊人id + */ + public function actionRecordList() + { + $post = \Yii::$app->request->post(); + $up_id = \Yii::$app->request->post('up_id'); + if (!$up_id) { + throw new Exception('就诊人id不能为空'); + } + $query = PatientVisitRecord::find() + ->where(['su_id' => \Yii::$app->user->identity->id]) + ->andWhere(['up_id' => $up_id]) + ->orderBy(['created_at' => SORT_DESC]); + + return $this->create($query, $post); + } + + + /** + * @doc-name 处方记录 + * @doc-param int up_id 就诊人id + * @doc-param string prescription_no 处方单号 / optional + * @doc-param string clinical_diagnose 诊断 / optional + * @doc-param string start_time 开始时间 / optional + * @doc-param string end_time 结束时间 / optional + * @doc-return mixed @List{id-int-处方id,prescription_no-int-处方编号,up_id-int-就诊人id,created_at-int-开具时间,status-int-状态0待审核1已通过2未通过3待使用4已使用5未使用6已失效7已初审,clinical_diagnose-string-临床诊断,doctor_name-string-医生,drug_name-string-药品} 处方记录 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionPrescripRecord() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['up_id', 'required'] + ]); + + $UserPatient = UserPatient::find() + ->where([ + 'id' => $post['up_id'] + ])->one(); + if (!$UserPatient) { + throw new Exception('就诊人不存在'); + } + + $query = Prescription::find()->alias('p')->with('userPatient')->where(['p.su_id' => \Yii::$app->user->identity->id,'p.up_id' => $post['up_id'],'p.is_deleted'=>0])->orderBy('created_at DESC'); + $this->field = [ + Prescription::class => [ + 'id','su_id','user_id','up_id', 'prescription_type','type','prescription_no','status','clinical_diagnose', + 'created_at' => function ($model) { + return date('Y-m-d',$model->created_at); + }, + 'patient' => function ($model) { + return [ + 'id' => $model->userPatient['id'], + 'name' =>$model->userPatient['name'], + 'sex' => $model->userPatient['sex'], + 'age' => FuncHelper::getAgeFromIdNo($model->userPatient['id_card']), + ]; + } + ] + ]; + return $this->create($query, \Yii::$app->request->post()); + } + + /** + * @doc-name 基础健康信息 + * @doc-param int up_id 就诊人id + * @doc-return mixed @UserPatientHealthInquiry{*} 就诊信息 + */ + public function actionBaseInfo() + { + $up_id = \Yii::$app->request->post('up_id'); + if (!$up_id) throw new Exception('就诊人id不能为空'); + + $patient = UserPatient::find() + ->where(['id' => $up_id]) + ->asArray()->one(); + if (!$patient) throw new Exception('就诊人不存在'); + $UserPatientHealthInquiry = UserPatientHealthInquiry::find()->where([ + 'user_patient_id' => $up_id, + 'is_delete' => 0 + ])->one(); + if (!$UserPatientHealthInquiry) throw new Exception('暂无基础健康信息'); + return $UserPatientHealthInquiry; + } + + /** + * @doc-name 患者添加备注 + * @doc-param int up_id 就诊人id + * @doc-param string remark 备注 + */ + public function actionSaveRemark() + { + $up_id = \Yii::$app->request->post('up_id'); + $remark = \Yii::$app->request->post('remark'); + if (!$up_id) throw new Exception('就诊人id不能为空'); + if (!$remark) throw new Exception('备注不能为空'); + + $doctorRemark = DoctorPatientRemark::find() + ->where(['su_id' => \Yii::$app->user->identity->id, 'up_id' => $up_id]) + ->one(); + if (!$doctorRemark) { + \Yii::$app->db->createCommand()->insert('yii_doctor_patient_remark', [ + 'su_id' => \Yii::$app->user->identity->id, + 'up_id' => $up_id, + 'remark' => $remark, + 'created_at' => time() + ])->execute(); + return []; + } + throw new Exception('该患者已添加备注'); + } + + /** + * @doc-name 查看患者备注 + * @doc-param int up_id 就诊人id + */ + public function actionPatientRemark() + { + $up_id = \Yii::$app->request->post('up_id'); + if (!$up_id) throw new Exception('就诊人id不能为空'); + + $remark = DoctorPatientRemark::find() + ->where(['su_id' => \Yii::$app->user->identity->id, 'up_id' => $up_id]) + ->one(); + if (!$remark) throw new Exception('该就诊人还没有备注'); + + return $remark; + } + + /** + * @doc-name 修改患者备注 + * @doc-param int up_id 就诊人id + * @doc-param string remark 备注 + */ + public function actionUpdatePatientRemark() + { + $up_id = \Yii::$app->request->post('up_id'); + $remark = \Yii::$app->request->post('remark'); + if (!$up_id) throw new Exception('患者id不能为空'); + if (!$remark) throw new Exception('备注不能为空'); + + $doctorRemark = DoctorPatientRemark::find() + ->where(['up_id' => $up_id]) + ->andWhere(['su_id' => \Yii::$app->user->identity->id]) + ->one(); + if (!$doctorRemark) throw new Exception('该就诊人还没有备注,去添加备注'); + + \Yii::$app->db->createCommand()->update('yii_doctor_patient_remark', [ + 'remark' => $remark, + 'updated_at' => time() + ], ['up_id' => $up_id, 'su_id' => \Yii::$app->user->identity->id])->execute(); + return []; + } + + /** + * @doc-name 患者基本信息 + * @doc-param int up_id 就诊人id + * @doc-return mixed @Patient{name-string-姓名,id_card-string-身份证,sex-int-性别0默认1男2女,mobile-string-手机号} 患者信息 + * @doc-return int age 年龄 + * @doc-return string remark 备注 + * @doc-return array group 分组 + */ + public function actionPatientInfo() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['up_id', 'required'] + ]); + $patient = UserPatient::find() + ->select('user_id,name,sex,id_card,mobile') + ->where(['id' => $post['up_id']]) + ->one(); + + if (!$patient) return ['就诊人id不存在']; + $user = User::find() + ->select('avatarurl') + ->where(['id' => $patient['user_id']]) + ->one(); + $ti_ids = UserPatientIll::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'up_id' => $post['up_id'] + ]) + ->select('ti_id') + ->column(); + + $remark = \common\models\DoctorPatientRemark::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'up_id' => $post['up_id'] + ]) + ->select('remark')->one(); + + if (!$ti_ids) { + return [ + 'patient' => $patient, + 'avatar' => $user['avatarurl'], + 'age' => FuncHelper::getAgeFromIdNo($patient->id_card), + 'remark' => $remark, + 'group' => '该就诊人还没有分组' + ]; + } + + $group = DoctorTagIll::find() + ->where([ + 'in', 'id', $ti_ids + ])->andWhere([ + 'su_id' => \Yii::$app->user->identity->id, + ]) + ->select('name')->all(); + + return [ + 'patient' => $patient, + 'avatar' => $user['avatarurl'], + 'age' => FuncHelper::getAgeFromIdNo($patient->id_card), + 'remark' => $remark, + 'group' => $group + ]; + } + + /** + * @doc-name 患者列表 + * @doc-param int status 1到店接诊患者2线上接诊患者 + * @doc-param string name 搜索患者姓名 / optional + * @doc-param int sex 搜索患者性别0默认1男2女 / optional + * @doc-return mixed @Register{id-int-挂号id,patient_id-int-患者ID,,patient-string-患者,avatar-string-头像,price-float-挂号金额,pay_time-string-支付时间,age-int-年龄,sex-int-性别0默认1男2女,recent_accept-string-最近接诊时间} 患者信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页数据} 分页信息 + */ + public function actionPatientList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['status', 'required'] + ]); + switch ($post['status']) { + case 1: + $query = Register::find()->alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.store_id' => \Yii::$app->store, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + ])->groupBy(['r.user_patient_id'])->orderBy(['created_at' => SORT_DESC]) + ->with(['patient']); + break; + case 2: + + + throw new Exception('暂时没写'); + break; + default: + throw new Exception('参数错误'); + } + + if (!empty($post['name'])) { + $name = $post['name']; + $query->joinWith(['patient' => function ($model) use ($name) { + $model->alias('p'); + $model->andWhere(['like', 'p.name', $name]); + }]); + } + if (!empty($post['sex'])) { + $sex = $post['sex']; + $query->joinWith(['patient' => function ($model) use ($sex) { + $model->alias('p'); + $model->andWhere(['p.sex' => $sex]); + }]); + } + + $this->field = [ + Register::class => [ + 'id', + 'patient_id'=>'patient.id', + 'patient' => 'patient.name', + 'avatar' => 'patient.avatar', + 'price', 'pay_time', + 'age' => function ($m) { + return FuncHelper::getAgeFromIdNo($m->patient->id_card); + }, + 'sex' => 'patient.sex', + 'recent_accept' => 'created_at' + ], + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 导出患者 + */ + public function actionPatientExport() + { + + $headlist = ['姓名', '身份证', '性别', '电话', '肝功能状态', '肝功能指标', '肾功能状态', '肾功能指标', '既往史有无', '既往史', '过敏史有无', '过敏史', '家庭遗传史有无', '家庭遗传史']; + + $Name = '导出患者'; + + $class = new DoctorPatient(); + + return (new ExportService())->export($headlist, $Name, $class); + + } + + /** + * @doc-name 挂号记录 + * @doc-param int patient_id 患者 + * @doc-param int id 患者ID / optional + * @doc-param string order_no 挂号单号 / optional + * @doc-param string patient 患者姓名 / optional + * @doc-param string start_time 起始时间 / optional + * @doc-param string end_time 终止时间 / optional + * @doc-return mixed @List{id-int-挂号id,is_case-string-是否有病历0无1有,created_at-string-挂号时间,order_no-string-挂号单号,doctor-string-医生,patient-string-患者,main_suit-string-主诉,family-string-家族史,now_history-string-现病史,popular-string-流行病史,history-string-既往史,allergic-string-过敏史,idea-string-意见,price-string-挂号费,order_number-string-挂号序号,is_pay-int-是否支付0否1是,status-int-状态:1已支付待接诊2接诊中3已结束4已取消5待评价6已评价7已拒诊,refuse_reason-string-拒诊原因,pay_type-int-支付方式1=微信支付,pay_time-string-支付时间=微信支付,is_cancel-int-是否取消,cancel_status-int-1已取消,cancel_time-string-取消时间,user_patient_id-int-患者ID,service_user_id-int-医生ID,user_id-int-医生ID} 挂号记录 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页多少条} 分页信息 + */ + public function actionRegisterList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['patient_id', 'required'] + ]); + + $query = Register::find()->alias('r')->where([ + 'r.user_patient_id' => $post['patient_id'], + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + 'r.is_delete' => 0, + ])->andWhere([ + 'like', 'order_no', $post['order_no'] ?? '', + ])->with(['case', 'doctor'])->orderBy(['id'=>SORT_DESC]); + + if (!empty($post['order_no'])) { + $query->andWhere(['order_no' => $post['order_no']]); + } + + if (!empty($post['id'])) { + $id = $post['id']; + $query->joinWith(['patient' => function ($p) use ($id) { + $p->alias('p'); + $p->andWhere(['p.id' => $id]); + }]); + } + if (!empty($post['patient'])) { + $name = $post['patient']; + $query->joinWith(['patient' => function ($p) use ($name) { + $p->alias('p'); + $p->andWhere(['like', 'p.name', $name]); + }]); + } + + if (!empty($post['start_time']) && !empty($post['end_time'])) { + $query->andWhere(['between', 'r.created_at', strtotime($post['start_time']), strtotime($post['end_time'])]); + } + $this->field = [ + Register::class => [ + 'id', 'created_at'=>function($m){ + return date('Y-m-d H:i:s',$m->created_at); + }, + 'is_case'=>function($m){ + $UserPatientCase= UserPatientCase::find()->where(['register_id'=>$m->id])->one(); + if ($UserPatientCase){ + return 1; + } + return 0; + }, + 'doctor' => 'doctor.name', + 'patient' => 'patient.name', + 'main_suit' => 'case.main_suit', + 'family' => 'case.main_suit', + 'now_history' => 'case.now_history', + 'popular' => 'case.popular', + 'history' => 'case.history', + 'allergic' => 'case.allergic', + 'idea' => 'case.idea', + 'case_created_at' => 'case.created_at', + 'price','order_no','order_number','is_pay','status','refuse_reason','pay_type', + 'pay_time'=>function($model){ + return date('Y-m-d H:i:s',$model->pay_time); + }, + 'is_cancel','cancel_status','cancel_time'=>function($mo){ + return date('Y-m-d H:i:s',$mo->cancel_time); + }, + 'user_patient_id','store_id','service_user_id','user_id' + ] + ]; + + return $this->create($query, $post); + } + + /** + * @doc-name 医生群发消息 + * @doc-param string content 发送内容 + * @doc-param string send_at 发送时间-年月日时分秒 / optional + * @doc-param array up_ids 患者ID数组 + */ + public function actionSendNews() + { + $post=\Yii::$app->request->post(); + \Yii::info('群发消息请求内容:'.Json::encode($post)); + $this->requestValidate($post,[ + [['content','up_ids'],'required'] + ]); + $content = \Yii::$app->request->post('content'); + $doctor_patient_ids =explode(',', \Yii::$app->request->post('up_ids')); + + $send_at = \Yii::$app->request->post('send_at',0); + + $su_id = \Yii::$app->user->identity->id; + + \Yii::$app->queue->delay($send_at ? Carbon::now()->diffInSeconds($send_at) : 0)->push(new NewSendJob([ + 'content' => $content, + 'su_id' => $su_id, + 'doctor_patient_ids' => $doctor_patient_ids, + 'store_id'=>$post['store_id'] + ])); + + return ['群发消息操作成功']; + + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/PharmacistController.php b/service/modules/v1/controllers/PharmacistController.php new file mode 100644 index 0000000..e9301f9 --- /dev/null +++ b/service/modules/v1/controllers/PharmacistController.php @@ -0,0 +1,86 @@ +where(['su_id' => \Yii::$app->user->identity->id]) + ->with(['titles', 'depart','practings','store','identity']) + ->with(['user'=>function($u){ + $u->select(['status','reason']); + }]) + ->asArray()->one(); + } + + /** + * @doc-name 药师-签章信息 + * @doc-return int sign_type 签章类型1电子2手写 + * @doc-return string sign_image 签章图片 + */ + public function actionIdentity() + { + return PharmacistIdentity::find() + ->select(['sign_type', 'sign_image']) + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + ]) + ->one(); + } + + /** + * @doc-name 我的 + * @doc-return mixed @PharmacistrInfo{avatar-string-头像,name-string-姓名,idcard-string-身份证号,@Store{name-string-执业机构},@Titles{name-string-职称},@Yardes{name-string-院区},@Depart{name-string-科室}} 我的页面信息 + */ + public function actionMy() + { + return PharmacistrInfo::find() + ->where(['su_id'=>\Yii::$app->user->identity->id]) + ->select('id,su_id,avatar,idcard,name,store_id') + ->with(['store'=>function($s){ + $s->select('name'); + }]) + ->with(['user'=>function($u){ + $u->select(['status','reason']); + }]) + ->asArray()->one(); + } + + /** + * @doc-name 编辑资料 + * @doc-param string avatar 头像 / optional + */ + public function actionEditInfo(){ + + $post = \Yii::$app->request->post(); + $PharmacistrInfo=PharmacistrInfo::find()->where([ + 'su_id'=>\Yii::$app->user->id + ])->one(); + + if (!$PharmacistrInfo) throw new Exception('药师信息不存在'); + $PharmacistrInfo->avatar=$post['avatar']; + + if (!$PharmacistrInfo->saveOrFail()){ + throw new Exception('编辑失败'); + } + return ['编辑成功']; + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/PrescripDetailController.php b/service/modules/v1/controllers/PrescripDetailController.php new file mode 100644 index 0000000..dc9c235 --- /dev/null +++ b/service/modules/v1/controllers/PrescripDetailController.php @@ -0,0 +1,415 @@ +request->post(); + $query = Prescription::find()->alias('p')->with('userPatient')->where([ + 'p.su_id' => \Yii::$app->user->identity->id, + 'p.is_deleted' => 0, + 'p.store_id' => $post['store_id'] + ])->orderBy('p.created_at DESC'); + $this->field = [ + Prescription::class => [ + 'id','up_id','prescription_type', 'type','is_pay','refund_status','prescription_no','status','created_at', + 'patient' => function ($model) { + return [ + 'id' => $model->userPatient['id'], + 'name' =>$model->userPatient['name'], + 'sex' => $model->userPatient['sex'], + 'age' => FuncHelper::getAgeFromIdNo($model->userPatient['id_card']), + ]; + } + ] + ]; + + $patient_name = $post['patient_name']; + $query->joinWith(['userPatient' => function ($q) use ($patient_name) { + $q->alias('up'); + //搜索就诊人姓名 + if (!empty($patient_name)) { + $q->andWhere(['like', 'up.name', $patient_name]); + } + }]); + + if($post['prescription_no']){ + $query->andWhere(['p.prescription_no'=> $post['prescription_no']]); + } + if($post['status'] ){ + $query->andWhere(['p.status'=> $post['status']]); + }elseif($post['status']==='0'){ + $query->andWhere(['p.status'=> $post['status']]); + }else{ + $query->andWhere(['p.status'=> [0,1,2]]); + } + if($post['type']){ + $query->andWhere(['p.type'=>$post['type']]); + } + if($post['prescription_type']){ + $query->andWhere(['p.prescription_type'=>$post['prescription_type']]); + } + + if($post['start_time']&&!$post['end_time']){ + $query->andWhere(['>=','p.created_at',strtotime($post['start_time'])]); + } + + if(!$post['start_time']&&$post['end_time']){ + $query->andWhere(['<=','p.created_at',strtotime($post['end_time'])]); + } + + if($post['start_time']&&$post['end_time']){ + $query->andWhere(['between','p.created_at',strtotime($post['start_time']),strtotime($post['end_time'])]); + } + + return $this->create($query, \Yii::$app->request->post()); + } + + /** + * 处方详情 + */ + public function actionDetail(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['prescription_id','required'], + ['store_id', 'required'] + ]); + return (new PrescriptionService())->detail('', $post['prescription_id']); + } + + + /** + * 开处方-常用方 + */ + public function actionCommonUse() + { + $post = \YII::$app->request->post(); + + $chinese = PrescriptionChinese::find()->where([ + 'type' => 2, + 'store_id' => $post['store_id'] + ])->andWhere(['su_id' => \Yii::$app->user->identity->id])->all(); + $west = PrescriptionWest::find()->where([ + 'type' => 2, + 'store_id' => $post['store_id'] + ])->andWhere(['su_id' => \Yii::$app->user->identity->id])->all(); + $granular = PrescriptionGranular::find()->where([ + 'type' => 2, + 'store_id' => $post['store_id'] + ])->andWhere(['su_id' => \Yii::$app->user->identity->id])->all(); + if (!$chinese && !$west && !$granular) throw new Exception('没有常用方'); + + $chineseRepice = $westRepice = $granularRepice = []; + if($chinese){ + foreach ($chinese as $value) { + $ids = explode(',', $value['cr_ids']); + $chineseRepice[] = ChineseRepice::find()->where(['in', 'id', $ids])->asArray()->all(); + } + } + + if($west){ + foreach ($west as $value) { + $ids = explode(',', $value['wr_ids']); + $westRepice[] = WestRepice::find()->where(['in', 'id', $ids])->with(['usetime', 'usetype', 'frequency', 'westUnit'])->asArray()->all(); + } + } + + if($granular){ + foreach ($granular as $value) { + $ids = explode(',', $value['gr_ids']); + $granularRepice[] = GranularRepice::find()->where(['in', 'id', $ids])->asArray()->all(); + } + } + + return [ + 'chin_prescription' => $chinese, + 'chinese' => $chineseRepice, + 'west_prescription' => $west, + 'west' => $westRepice, + 'granular_prescription' => $granular, + 'granular' => $granularRepice + ]; + } + + /** + * @doc-name 开处方-常用方详情(中药) + * @doc-param int id 处方id + */ + public function actionCommonChinese() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $chinese = PrescriptionChinese::find()->where([ + 'id' => $post['id'], + 'store_id' => $post['store_id'] + ])->andWhere(['type' => 2])->one(); + if (!$chinese) { + throw new Exception('没有该处方'); + } + $ids = explode(',', $chinese['cr_ids']); + + $recipe = ChineseRepice::find()->where(['in', 'id', $ids])->asArray()->all(); + return $recipe; + } + + /** + * @doc-name 开处方-常用方详情(颗粒药) + * @doc-param int id 处方id + */ + public function actionCommonGranular() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $granular = PrescriptionGranular::find()->where([ + 'id' => $post['id'], + 'store_id' => $post['store_id'] + ])->andWhere(['type' => 2])->one(); + if (!$granular) { + throw new Exception('没有该处方'); + } + $ids = explode(',', $granular['gr_ids']); + + $recipe = GranularRepice::find()->where(['in', 'id', $ids])->asArray()->all(); + return $recipe; + } + + + /** + * @doc-name 开处方-常用方详情(西药) + * @doc-param int id 处方id + */ + public function actionCommonWest() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $west = PrescriptionWest::find()->where([ + 'id' => $post['id'], + 'store_id' => $post['store_id'] + ])->andWhere(['type' => 2])->one(); + if (!$west) { + throw new Exception('没有该处方'); + } + $ids = explode(',', $west['wr_ids']); + + $recipe = WestRepice::find()->where(['in', 'id', $ids])->with(['usetime', 'usetype', 'frequency', 'westUnit'])->asArray()->all(); + return $recipe; + } + + /** + * 开处方-中药常用方 + * @doc-param string clinical_diagnose 临床诊断 + * @doc-param int up_id 就诊人id + * @doc-param string doctor_order 医嘱 + * @doc-param int category 类别1自费2医保 + * @doc-param string cr_ids 拼接药方id + */ + public function actionSaveChinCommon() + { + $id = \Yii::$app->user->identity->id; + $request = \Yii::$app->request; + $param = $request->post(); + $this->requestValidate($param, [ + ['name', 'required'], + ['store_id', 'required'], + //['clinical_diagnose', 'required'], + //['category', 'required'], + //['doctor_order', 'required'], + ['cr_ids', 'required'], + ]); + + $store_id = $param['store_id']; + + try { + $chineseRepice = new PrescriptionChinese(); + $chineseRepice->su_id = $id; + $chineseRepice->name = $param['name']; + $chineseRepice->clinical_diagnose = $param['clinical_diagnose']??''; + $chineseRepice->prescription_no = 'ZY'.rand(111111, 999999) . time(); + $chineseRepice->up_id = 0; + $chineseRepice->store_id = $store_id; + $chineseRepice->status = 0; + $chineseRepice->category = $param['category']??''; + $chineseRepice->doctor_order = $param['doctor_order']??''; + $chineseRepice->cr_ids = $param['cr_ids']; + $chineseRepice->type = 2; + $chineseRepice->saveOrFail(); + + return [ + 'id' => $chineseRepice->id, + 'issue_time' => time(), + 'clinical_diagnose' => $param['clinical_diagnose'] + ]; + } catch (Exception $e) { + throw new Exception($e->getMessage()); + } + } + + + /** + * 开处方-中药常用方 + * @doc-param string clinical_diagnose 临床诊断 + * @doc-param int up_id 就诊人id + * @doc-param string doctor_order 医嘱 + * @doc-param int category 类别1自费2医保 + * @doc-param string cr_ids 拼接药方id + */ + public function actionSaveGranularCommon() + { + $id = \Yii::$app->user->identity->id; + $request = \Yii::$app->request; + $param = $request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['name', 'required'], + //['clinical_diagnose', 'required'], + //['category', 'required'], + //['doctor_order', 'required'], + ['gr_ids', 'required'], + ]); + + $store_id = $param['store_id']; + + try { + $granularRepice = new PrescriptionGranular(); + $granularRepice->su_id = $id; + $granularRepice->name = $param['name']; + $granularRepice->clinical_diagnose = $param['clinical_diagnose']??''; + $granularRepice->prescription_no = 'ZY'.rand(111111, 999999) . time(); + $granularRepice->up_id = 0; + $granularRepice->store_id = $store_id; + $granularRepice->status = 0; + $granularRepice->category = $param['category']??''; + $granularRepice->doctor_order = $param['doctor_order']??''; + $granularRepice->gr_ids = $param['gr_ids']; + $granularRepice->type = 2; + $granularRepice->saveOrFail(); + + return [ + 'id' => $granularRepice->id, + 'issue_time' => time(), + 'clinical_diagnose' => $param['clinical_diagnose'] + ]; + } catch (Exception $e) { + throw new Exception($e->getMessage()); + } + } + + /** + * @doc-name 开处方-西药常用方 + * @doc-param string doctor_order 医嘱 + * @doc-param string clinical_diagnose 临床诊断 + * @doc-param int up_id 就诊人id + * @doc-param int category 类别1自费2医保 + * @doc-param string wr_ids 关联西药药方表 + * @doc-return string aa bb + */ + public function actionSaveWestCommon() + { + $id = \Yii::$app->user->identity->id; + $param = \Yii::$app->request->post(); + try { + $this->requestValidate($param, [ + ['store_id', 'required'], + ['name', 'required'], + //['doctor_order', 'required'], + //['clinical_diagnose', 'required'], + //['category', 'required'], + ['wr_ids', 'required'], + ]); + $store_id = $param['store_id']; + + $westRepice = new PrescriptionWest(); + $westRepice->su_id = $id; + $westRepice->name = $param['name']; + $westRepice->clinical_diagnose = $param['clinical_diagnose']??''; + $westRepice->prescription_no = 'XY'.rand(111111, 999999) . time(); + $westRepice->up_id = 0; + $westRepice->store_id = $store_id; + $westRepice->status = 0; + $westRepice->category = $param['category']??''; + $westRepice->doctor_order = $param['doctor_order']??''; + $westRepice->wr_ids = $param['wr_ids']; + $westRepice->type = 2; + $westRepice->saveOrFail(); + + return [ + 'id' => $westRepice->id, + 'issue_time' => time(), + 'clinical_diagnose' => $param['clinical_diagnose'] + ]; + } catch (Exception $e) { + throw new Exception($e->getMessage()); + } + } + + public function actionDeleteCommon(){ + $param = \Yii::$app->request->post(); + $this->requestValidate($param, [ + ['id', 'required'], + ['type', 'required'] + ]); + try { + switch ($param['type']) { + case 'west': + # code... + $prescription = PrescriptionWest::findOne([ + 'id' => $param['id'], + 'su_id' => \Yii::$app->user->identity->id, + 'type' => 2 + ]); + break; + case 'chinese': + # code... + $prescription = PrescriptionChinese::findOne([ + 'id' => $param['id'], + 'su_id' => \Yii::$app->user->identity->id, + 'type' => 2 + ]); + break; + case 'granular': + # code... + $prescription = PrescriptionGranular::findOne([ + 'id' => $param['id'], + 'su_id' => \Yii::$app->user->identity->id, + 'type' => 2 + ]); + break; + + default: + throw new Exception('错误的type'); + break; + } + if(!$prescription) throw new Exception('常用方不存在'); + $prescription->delete(); + } catch (\Exception $e) { + throw $e; + } + return ['删除成功']; + } + +} \ No newline at end of file diff --git a/service/modules/v1/controllers/PrescriptionController.php b/service/modules/v1/controllers/PrescriptionController.php new file mode 100644 index 0000000..e8e6849 --- /dev/null +++ b/service/modules/v1/controllers/PrescriptionController.php @@ -0,0 +1,1818 @@ + \YII::$app->user->id]); + if(!$doctorInfo){ + throw new Exception('无权限进行该操作'); + } + + $westActions = ['actionProcessRuleList','actionProcessNoteList','actionWestList', 'actionWestCommon', 'actionWestCollection', 'actionWestUncollect', 'actionAddWest', 'actionAddPrescriptionWest','actionUseTime','actionUseType','actionUseFre','actionSearchDisease','actionDiseaseCommon','actionAddDiseaseCommon','actionDelDiseaseCommon','actionWestUnit','actionPrescriptionDetail']; + if($doctorInfo->identity == 2 && !in_array($action->actionMethod, $westActions)){ + throw new Exception('您当前并未拥有开具此方的权限'); + } + + return $ret; + } + + /** + * @doc-name 添加西药-全部西药列表 + * @doc-param name string 药名 + */ + public function actionWestList() + { + $name = \Yii::$app->request->post('name'); + $store_id = \Yii::$app->request->post('store_id'); + if (!$name) { + $common = DoctorCommon::find()->alias('dc')->where([ + 'dc.su_id' => \Yii::$app->user->identity->id, + 'dc.store_id' => $store_id + ])->joinWith([ + 'drug d' => function($q){ + $q->andWhere([ + 'in','d.type',[2,4] + ]); + } + ])->joinWith([ + 'drugStoreDrug','drugStoreRelation' + ])->asArray()->all(); + //有收藏药品 + if ($common) { + foreach ($common as $v) { + $drug = $v['drug']; + $ids[] = $drug['id']; + $drug['buy_price'] = $v['drugStoreRelation']['buy_price']; + $drug['price'] = $v['drugStoreRelation']['price']; + $drug['stock'] = $v['drugStoreDrug']['stock']; + $collect[] = $drug; + } + $unCollect = Drug::find()->alias('d')->select('d.*')->where([ + 'in','d.type',[2,4] + ])->andWhere([ + 'not in', 'd.id', $ids + ])->with('drugStoreDrug')->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->all(); + foreach($unCollect as $k=>$v){ + $unCollect[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $unCollect[$k]['price'] = $v['drugStoreRelation']['price']; + $unCollect[$k]['stock'] = $v['drugStoreDrug']['stock']; + unset($unCollect[$k]['drugStoreRelation']); + unset($unCollect[$k]['drugStoreDrug']); + } + return ['collect' => $collect, 'uncollect' => $unCollect]; + } + + $unCollect = Drug::find()->alias('d')->select('d.*')->where([ + 'in','d.type',[2,4] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->all(); + foreach($unCollect as $k=>$v){ + $unCollect[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $unCollect[$k]['price'] = $v['drugStoreRelation']['price']; + $unCollect[$k]['stock'] = $v['drugStoreDrug']['stock']; + + unset($unCollect[$k]['drugStoreRelation']); + unset($unCollect[$k]['drugStoreDrug']); + } + return ['uncollect' => $unCollect]; + } + //搜索 + $allDrug = Drug::find()->alias('d')->select('d.*')->where([ + 'in','d.type',[2,4] + ])->andWhere([ + 'or', + ['like', 'd.drug_name', '%' . $name . "%", false], + ['like', 'd.pinyin_simple', '%' . $name . "%", false], + ['like', 'd.drug_alias', '%' . $name . "%", false] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->all(); + if (!$allDrug) { + throw new Exception('没有搜到'); + } + + foreach($allDrug as $k=>$v){ + $allDrug[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $allDrug[$k]['price'] = $v['drugStoreRelation']['price']; + $allDrug[$k]['stock'] = $v['drugStoreDrug']['stock']; + unset($allDrug[$k]['drugStoreRelation']); + unset($allDrug[$k]['drugStoreDrug']); + $ids[] = $v['id']; + } + + $is_collect = DoctorCommon::find()->alias('dc')->select(['dc.drug_id'])->where([ + 'in', 'dc.drug_id', $ids + ])->andWhere([ + 'dc.su_id'=>\Yii::$app->user->identity->id, + 'dc.store_id' => $store_id + ])->joinWith([ + 'drug d' => function ($q){ + $q->andWhere([ + 'in','d.type',[2,4] + ]); + } + ])->joinWith([ + 'drugStoreDrug','drugStoreRelation' + ])->column(); + //没有收藏的药品 + if (!$is_collect) { + return ['uncollect' => $allDrug]; + } + + foreach ($ids as $k => $v) { + foreach ($is_collect as $val) { + if ($v == $val) { + unset($ids[$k]); + } + } + } + + $no_collect = Drug::find()->alias('d')->select('d.*')->where([ + 'in', 'd.id', $ids + ])->andWhere([ + 'in','d.type',[2,4] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->all(); + foreach($no_collect as $k=>$v){ + $no_collect[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $no_collect[$k]['price'] = $v['drugStoreRelation']['price']; + $no_collect[$k]['stock'] = $v['drugStoreDrug']['stock']; + unset($no_collect[$k]['drugStoreRelation']); + unset($no_collect[$k]['drugStoreDrug']); + } + + $collected = Drug::find()->alias('d')->select('d.*')->where([ + 'in', 'd.id', $is_collect + ])->andWhere([ + 'in','d.type',[2,4] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->all(); + foreach($collected as $k=>$v){ + $collected[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $collected[$k]['price'] = $v['drugStoreRelation']['price']; + $collected[$k]['stock'] = $v['drugStoreDrug']['stock']; + unset($collected[$k]['drugStoreRelation']); + unset($collected[$k]['drugStoreDrug']); + } + + if (!$no_collect) { + return ['collected' => $collected]; + } + + return [ + 'uncollect' => $no_collect, + 'collected' => $collected + ]; + } + + /** + * @doc-name 添加西药-常用西药列表 + * @doc-param name string 药名 + */ + public function actionWestCommon() + { + $name = \Yii::$app->request->post('name'); + $store_id = \Yii::$app->request->post('store_id'); + $common = DoctorCommon::find()->alias('dc')->where([ + 'dc.su_id' => \Yii::$app->user->identity->id, + 'dc.store_id' => $store_id + ])->joinWith([ + 'drug d' => function ($q) use ($name){ + $q->andWhere([ + 'in','d.type',[2,4] + ]); + if($name){ + $q->andWhere([ + 'like', 'd.drug_name', '%' . $name . "%", false + ]); + } + } + ])->joinWith([ + 'drugStoreDrug','drugStoreRelation' + ])->asArray()->all(); + if (!$common) throw new Exception('你还没有添加常用药'); + foreach($common as $k=>$v){ + $drug = $v['drug']; + $data[$k] = $drug; + $data[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $data[$k]['price'] = $v['drugStoreRelation']['price']; + $data[$k]['stock'] = $v['drugStoreDrug']['stock']; + unset($v[$k]['store']); + unset($v[$k]['drugStoreRelation']); + unset($v[$k]['drugStoreDrug']); + } + return $data; + } + + /** + * @doc-name 西药收藏 + * @doc-param int id 西药id + */ + public function actionWestCollection() + { + $id = \Yii::$app->request->get('id'); + $store_id = \Yii::$app->request->get('store_id'); + if (empty($id)||empty($store_id)) throw new Exception('参数缺失'); + + $drug = Drug::find()->alias('d')->where(['d.id' => $id])->andWhere([ + 'in','d.type',[2,4] + ])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->one(); + if (!$drug) { + throw new Exception('该西药不存在'); + } + $isCollected = DoctorCommon::findOne(['su_id' =>\Yii::$app->user->identity->id,'drug_id' => $id,'store_id'=>$store_id]); + if($isCollected){ + throw new Exception('该西药已收藏'); + } + $DoctorCommon = new DoctorCommon(); + $DoctorCommon->store_id = $store_id; + $DoctorCommon->su_id = \Yii::$app->user->identity->id; + $DoctorCommon->drug_id = $id; + $DoctorCommon->saveOrFail(); + + return ['收藏成功']; + } + + /** + * @doc-name 西药取消收藏 + * @doc-param int id 西药id + */ + public function actionWestUncollect() + { + $id = \Yii::$app->request->get('id'); + if (empty($id)) throw new Exception('id不能为空'); + $drug = DoctorCommon::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'drug_id' => $id + ])->one(); + if (!$drug) { + throw new Exception('该收藏不存在'); + } + $drug->delete(); + return ['取消收藏成功']; + // \Yii::$app->db->createCommand()->delete('yii_doctor_common', ['su_id' => \Yii::$app->user->identity->id, 'drug_id' => $id])->execute(); + } + + /** + * 西药单位列表 + */ + public function actionWestUnit() + { + return WestUnit::find()->all(); + } + + /** + * 药的使用时间列表 + */ + public function actionUseTime() + { + return DrugUseTime::find()->all(); + } + + /** + * 药的使用方式 + */ + public function actionUseType() + { + return DrugUseType::find()->all(); + } + + /** + * 药的使用频率 + */ + public function actionUseFre() + { + return DrugUseFrequency::find()->all(); + } + + /** + * @doc-name 添加西药药方 + * @doc-param int number 数量 + * @doc-param string instruction 说明书 + * @doc-param int time_id 使用时间 + * @doc-param int type_id 使用类型 + * @doc-param int grain_number 粒数 + * @doc-param int f_id 频率 + * @doc-param int wu_id 西药单位id + * @doc-param int content 药品id + * @doc-param int available_days 可用天数 + * @doc-return string aa bb + */ + public function actionAddWest() + { + $param = \Yii::$app->request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['content', 'required'], + ['number', 'required'], + // ['instruction', 'required'], + ['time_id', 'required'], + ['type_id', 'required'], + ['grain_number', 'required'], + ['wu_id', 'required'], + ['available_days', 'required'], + ['f_id', 'required'] + ]); + try { + $store_id = $param['store_id']; + $transaction = \Yii::$app->db->beginTransaction(); + + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $param['content'] + ])->andWhere([ + 'in','d.type',[2,4] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + + if($drug['drugStoreDrug']['stock'] < $param['number']){ + throw new Exception('药品库存数量不足'); + } + $price = $drug['drugStoreRelation']['price']; + $drug['buy_price'] = $drug['drugStoreRelation']['buy_price']; + $drug['price'] = $price; + $drug['stock'] = $drug['drugStoreDrug']['stock']; + unset($drug['drugStoreRelation']); + unset($drug['drugStoreDrug']); + + $usage_dosage = Json::encode($drug); + unset($param['content']); + $WestRecipe = new WestRepice(); + $WestRecipe->content = $usage_dosage; + $WestRecipe->total_price = bcmul($param['number'], $price,2); + $WestRecipe->attributes = $param; + $WestRecipe->saveOrFail(); + + $transaction->commit(); + return [$WestRecipe->id]; + } catch (Exception $e) { + $transaction->commit(); + throw $e; + } + } + + + /** + * @doc-name 开西药处方 + * @doc-param string doctor_order 医嘱 + * @doc-param string clinical_diagnose 临床诊断 + * @doc-param int up_id 就诊人id + * @doc-param int category 类别1自费2医保 + * @doc-param string wr_ids 关联西药药方表 + * @doc-return string aa bb + */ + public function actionAddPrescriptionWest() + { + $id = \Yii::$app->user->identity->id; + + $param = \Yii::$app->request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['register_id', 'required'], + ['doctor_order', 'required'], + ['clinical_diagnose', 'required'], + ['up_id', 'required'], + ['category', 'required'], + ['wr_ids', 'required'], + ['treatement_price', 'number'] + ]); + + $transaction = \Yii::$app->db->beginTransaction(); + try { + $store_id = $param['store_id']; + + /* @var UserPatient $userPatient */ + $userPatient = UserPatient::find()->select('id,name,sex,id_card,user_id,mobile')->where(['id' => $param['up_id']])->one(); + if(!$userPatient){ + throw new Exception('就诊人不存在'); + } + + $register = Register::find()->where([ + 'id' => $param['register_id'], + 'user_patient_id' => $param['up_id'], + 'store_id' => $store_id + ])->with('healthInquery')->one(); + if(!$register){ + throw new Exception('挂号订单不存在'); + } + + $prescription_no = 'XY' . rand(111111, 999999) . time(); + + $marketPrice = '0'; + $priceTotal = 0; + $wr_ids = explode(',', $param['wr_ids']); + $drugStoreDrugs = []; + for ($i = 0; $i < sizeof($wr_ids); $i++) { + $recipe = WestRepice::find()->where(['id' => $wr_ids[$i]])->asArray()->one(); + if(!$recipe){ + throw new Exception('药方数据错误'); + } + $priceTotal += $recipe['total_price']; + $content = Json::decode($recipe['content']); + + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $content['id'] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + + if($drug['drugStoreDrug']['stock']<$recipe['number']){ + throw new Exception($content['drug_name'].'库存数量不足'); + } + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', [ + 'sale_number' => $drug['drugStoreRelation']['sale_number'] + $recipe['number'] + ], ['id' => $drug['drugStoreRelation']['id']])->execute(); + \Yii::$app->db->createCommand()->update('yii_drugstore_drug', [ + 'stock' => $drug['drugStoreDrug']['stock'] - $recipe['number'], + 'frozen_number' => $drug['drugStoreDrug']['frozen_number'] + $recipe['number'] + ], ['id' => $drug['id']])->execute(); + $drug['number'] = $recipe['number']; + $drugStoreDrugs[] = $drug; + $itemMarketPrice = bcmul($recipe['number'],$drug['drugStoreRelation']['buy_price'],2); + $marketPrice = bcadd($marketPrice,$itemMarketPrice,2); + } + + $priceTotal = round($priceTotal, 2); //对药品总价进行四舍五入 + + //组装处方快照 + $wr_ids = explode(',', $param['wr_ids']); + $repice = WestRepice::find()->where(['in', 'id', $wr_ids])->with(['usetime', 'usetype', 'frequency', 'westUnit'])->asArray()->all(); + $prescription_content['prescription_no'] = $prescription_no; + $prescription_content['repice'] = $repice; + $prescription_content['created_at'] = date('Y-m-d',time()); + $prescription_content['doctor_order'] = $param['doctor_order']; + $prescription_content['clinical_diagnose'] = $param['clinical_diagnose']; + $prescription_content['category'] = $param['category']==1?'自费':'医保'; + $prescription_content['patient'] = $userPatient; + $prescription_content['patient']['age'] = FuncHelper::getAgeFromIdNo($userPatient->id_card); + $prescription_content['doctor'] = DoctorInfo::find()->select('name,depart_id,title_id')->where(['su_id' => $id])->with(['depart','title'])->asArray()->one(); + $prescription_content['total_pay_price'] = $priceTotal; + + $prescriptionWest = new PrescriptionWest(); + $prescriptionWest->store_id = $store_id; + $prescriptionWest->prescription_no = $prescription_no; + $prescriptionWest->su_id = $id; + $prescriptionWest->user_id = $userPatient->user_id; + $prescriptionWest->up_id = $param['up_id']; + $prescriptionWest->status = 0; + $prescriptionWest->type = 1;//普通方 + $prescriptionWest->content = Json::encode($prescription_content); + $prescriptionWest->category = $param['category']; + $prescriptionWest->doctor_order = $param['doctor_order']; + $prescriptionWest->clinical_diagnose = $param['clinical_diagnose']; + $prescriptionWest->wr_ids = $param['wr_ids']; + $prescriptionWest->saveOrFail(); + + $prescription = new Prescription(); + $prescription->store_id = $store_id; + $prescription->register_id = $param['register_id']; + $prescription->prescription_no = $prescription_no; + $prescription->su_id = $id; + $prescription->user_id = $userPatient->user_id; + $prescription->up_id = $param['up_id']; + $prescription->status = 0; + $prescription->type = 1;//普通方 + $prescription->is_online = 0; + $prescription->content = Json::encode($prescription_content); + $prescription->prescription_type = 2;//西药 + $prescription->category = $param['category']; + $over_time = \Yii::$app->params['prescription']['over_time']; + $doctor_order = []; + if(date('H')>=16){ + $doctor_order[] = '该处方有效期延长为三天内有效'; + $over_time = 72*3600; + } + if($repice[0]['dosage'] > 7){ + $doctor_order[] = '患者需长期使用此药,开具超七天用量'; + } + $doctor_order[] = $param['doctor_order']; + $prescription->valid_hours = $over_time/3600; + $prescription->doctor_order = implode('|',$doctor_order); + $prescription->clinical_diagnose = $param['clinical_diagnose']; + $prescription->wr_ids = $param['wr_ids']; + $prescription->total_pay_price = $priceTotal; + $prescription->saveOrFail(); + + //获取支付方式配置 + $payConfig = PayConfig::findOne(['status' => 1, 'current_use' => 1]); + // 生成商品订单 + $productOrder = new ProductOrder(); + $productOrder->su_id = $id; + $productOrder->store_id = $store_id; + $productOrder->user_id = $userPatient->user_id; + $productOrder->up_id = $userPatient->id; + $productOrder->order_no = Carbon::now()->format('YmdHis') . rand(10000, 99999) . rand(10000, 99999); + $productOrder->p_id = $prescription->id; + $productOrder->dosage = 0; + $productOrder->prescription_type = 2; // 西(中成)药处方 + $productOrder->order_type = 1; + $productOrder->type = $payConfig->pay_type??0;//0未知 1微信 2易票联 + $productOrder->is_pay = 0; + $productOrder->trans_expenses = 0; + $productOrder->items_price = $priceTotal; + $productOrder->market_price = $marketPrice; + $productOrder->status = ProductOrderEnum::UNPAY; + $treatementPrice = 0; + if($param['treatement_price']){ + $treatementPrice = $param['treatement_price']; + } + $productOrder->treatement_price = $treatementPrice; + + + $productOrder->is_free_shipping = 0;//是否包邮 0不包邮 1包邮 + + $userAddress = Address::find()->select('id,name,mobile,province,region,detail_address')->where(['user_id' => $prescription->user_id])->orderBy('is_default DESC')->asArray()->all(); + if(count($userAddress)>0){ + $productOrder->address_id = $userAddress[0]['id']; + $productOrder->address = Json::encode($userAddress[0]); + $productOrder->express_name = $userAddress[0]['name']; + $productOrder->express_mobile = $userAddress[0]['mobile']; + $productOrder->express_region = $userAddress[0]['region']; + $productOrder->express_address = $userAddress[0]['detail_address']; + //判断是否满足包邮条件 + $systemConfig = SystemConfig::find()->where(['config_type' => 2, 'type' => 2])->one();//西药包邮条件 + if($priceTotal < $systemConfig->value){//不满足条件计算快递费 + $region = Region::find()->where(['name' => $userAddress[0]['province']])->one(); + $productOrder->trans_expenses = $region->express_fee; + $priceTotal = $priceTotal + $region->express_fee; + } else { + $productOrder->is_free_shipping = 1; //1包邮 + } + } + + $productOrder->total_pay_price = $priceTotal + $treatementPrice; + $productOrder->pay_method = 1; + $productOrder->free_ship = 1; + $productOrder->sync_order_no = $param['sync_order_no']??''; + $productOrder->saveOrFail(); + + $productOrderItem = new ProductOrderItems(); + foreach ($drugStoreDrugs as $v) { + $item = clone $productOrderItem; + $item->product_order_id = $productOrder->id; + $item->drug_id = $v['id']; + $item->drug_image = $v['image']; + $item->drug_no = $v['drug_number']; + $item->number = $v['number']; + $item->type = $v['type']; + $item->buy_price = $v['drugStoreRelation']['buy_price']; + $item->price = $v['drugStoreRelation']['price']; + $item->drug_name = $v['drug_name']; + $item->small_info = $v['small_info']; + $item->saveOrFail(); + } + + //触发处方自动失效事件 + $prescriptionEvent = new PrescriptionEvent(); + $prescriptionEvent->prescription = $prescription; + $prescriptionEvent->sender = $this; + \Yii::$app->trigger(Prescription::AUTO_EXPIRE, $prescriptionEvent); + + + //触发订单创建事件 + $event = new ProductOrderEvent(); + $event->order = $productOrder; + $event->sender = $this; + \Yii::$app->trigger(ProductOrder::EVENT_CREATED, $event); + + //处方开具待支付订阅消息通知 + \Yii::$app->queue->push(new PrescriptionCreated([ + 'orderId' => $prescription->id, + ])); + + //发送处方系统通知 + $systemNotice = new SystemNotice(); + $systemNotice->data = $prescription_no; + $systemNotice->store_id = $store_id; + $systemNotice->content = '医生已为您开具处方,请及时查看!'; + $systemNotice->base_type = 4;//处方通知 + $systemNotice->scene_type = 1; + $systemNotice->user_id = $userPatient->user_id; + $systemNotice->notice_at = date('Y-m-d H:i:s',time()); + $systemNotice->saveOrFail(); + + $transaction->commit(); + + //处方生成短信通知药师审方 + \Yii::$app->queue->push(new WaitApprovalMessageJob([ + 'orderId' => $prescription->id, + ])); + + return [ + 'id' => $prescription->id, + 'product_order_id' => $productOrder->id, + 'prescription_no' => $prescription_no, + 'issue_time' => time(), + 'clinical_diagnose' => $param['clinical_diagnose'] + ]; + } catch (Exception $e) { + $transaction->rollBack(); + throw $e; + } + } + + /** + * 中药剂数列表 + */ + public function actionDosage() + { + return DrugDosage::find()->all(); + } + + /** + * 中药用量列表 + */ + public function actionUseNum() + { + return DrugUseNum::find()->all(); + } + + + /** + * @doc-name 中药的使用煎熬方式 + * @doc-return mixed @drug-use-way{*} + */ + public function actionUseWay() + { + return DrugUseWay::find()->all(); + } + + + public function actionProcessRuleList(){ + $pid = \Yii::$app->request->get('pid') ?? 0; + return ProcessRule::find()->where(['pid' => $pid])->asArray()->all(); + } + + + public function actionProcessNoteList(){ + $rule_id = \Yii::$app->request->get('rule_id') ?? 0; + if(!$rule_id){ + throw new Exception("请先选择加工方式"); + } + return ProcessRuleNote::find()->where(['rule_id' => $rule_id])->asArray()->all(); + } + + /** + * @doc-name 中药列表 + * @doc-param string name 药名 + */ + public function actionChineseList() + { + $name = \Yii::$app->request->post('name'); + $store_id =\Yii::$app->request->post('store_id'); + if(!$name){ + throw new Exception('请输入药品名称关键字'); + } + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.type' => 1 + ])->andWhere([ + 'or', + ['like', 'd.drug_name', '%' . $name . "%", false], + ['like', 'd.pinyin_simple', '%' . $name . "%", false], + ['like', 'd.drug_alias', '%' . $name . "%", false] + ])->with('unit')->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->all(); + + if (!$drug) { + throw new Exception('没有找到您要搜索的药品'); + } + + foreach($drug as $k=>$v){ + $drug[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $drug[$k]['price'] = $v['drugStoreRelation']['price']; + $drug[$k]['stock'] = $v['drugStoreDrug']['stock']; + unset($drug[$k]['drugStoreDrug']); + unset($drug[$k]['drugStoreRelation']); + } + + return $drug; + } + + + /** + * @doc-name 一次添加一个中药 + * @doc-param int drug_id 药id + * @doc-param int number 数量 + */ + public function actionAddOneChinese() + { + $request = \Yii::$app->request; + $param = $request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['drug_id', 'required'], + ['number', 'required'] + ]); + + $store_id = $param['store_id']; + + try { + $transaction = \Yii::$app->db->beginTransaction(); + + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $param['drug_id'] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品暂不售卖'); + } + + if ($param['number'] > $drug['drugStoreDrug']['stock']) throw new Exception('库存不足'); + + $ChineseMedicine = new ChineseMedicine(); + $ChineseMedicine->su_id = \Yii::$app->user->id; + $ChineseMedicine->drug_id = $param['drug_id']; + $ChineseMedicine->drug_number = $drug['drug_number']; + $ChineseMedicine->name = $drug['drug_name']; + $ChineseMedicine->number = $param['number']; + $ChineseMedicine->order = $param['order']??0; + $ChineseMedicine->unit = $drug['unit_id']??0; + $ChineseMedicine->price = $drug['drugStoreRelation']['price']; + $ChineseMedicine->buy_price = $drug['drugStoreRelation']['buy_price']; + $ChineseMedicine->saveOrFail(); + + $transaction->commit(); + return [$ChineseMedicine->id]; + } catch (Exception $e) { + $transaction->rollBack(); + throw $e; + } + } + + /** + * @doc-name 添加中药药方 + * @doc-param int deployment 调配1煎煮2外配 + * @doc-param int dosage 剂数id + * @doc-param int consumption 用量id + * @doc-param int usage 用法 + * @doc-param int fufa_id 服法id + * @doc-param string remark 备注 + * @doc-param int is_deepfry 是否浓煎0否1是 + * @doc-param string cm_id 中药处方的中药表id + * @doc-return array aa bb + */ + public function actionAddRecipe() + { + $param = \Yii::$app->request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['deployment', 'required'], + ['dosage', 'required'], + ['consumption', 'required'], + ['cm_id', 'required'], + ['process_rule_id','integer'], + ['process_rule_note','string'] + ]); + + $store_id = $param['store_id']; + + try { + $transaction = \Yii::$app->db->beginTransaction(); + $ids = explode(',', $param['cm_id']); + + $price = 0; + $medicine = ChineseMedicine::find()->select('id,drug_id,name,order,unit,number,price,drug_number,buy_price')->with(['unit','useWay'])->where(['in', 'id', $ids])->asArray()->all(); + $drug_ids= ChineseMedicine::find()->select('drug_id')->where(['in', 'id', $ids])->column(); + $drug_ids_str=implode(',',$drug_ids); + + $totalNum = 0; + foreach ($medicine as $value){ + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $value['drug_id'] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + $drugNumber = (int) $value['number'] * (int) $param['dosage']; + if($drug['drugStoreDrug']['stock'] < $drugNumber){ + throw new Exception($value['name'].'库存数量不足'); + } + $totalNum += $drugNumber; + $price+=$value['number'] * $value['price'] * $param['dosage']; + } + + $process_price = 0; + $processRuleContent = ''; + if($param['process_rule_id']){ + $processRule = ProcessRule::find()->where(['id' => $param['process_rule_id']])->one(); + if(empty($processRule)){ + throw new Exception("加工方式错误"); + } + $parentProcessRule = ProcessRule::find()->where(['id' => $processRule->pid])->one(); + if(empty($parentProcessRule)){ + throw new Exception("加工方式错误"); + } + if($processRule->calc_method == 1){ + $process_price = $processRule->price; + $processRuleContent = '加工方式:'.$parentProcessRule->name.'-'.$processRule->name.'-'.$param['process_rule_note'].",固定收费".$process_price."元"; + }elseif($processRule->calc_method == 2){ + $process_price = $processRule->price * $param['dosage']; + $processRuleContent = '加工方式:'.$parentProcessRule->name.'-'.$processRule->name.'-'.$param['process_rule_note'].",".$processRule->price."元/".$processRule->unit.',共'.$param['dosage'].'贴'; + }else{ + $process_price = $processRule->price * $totalNum; + $processRuleContent = '加工方式:'.$parentProcessRule->name.'-'.$processRule->name.'-'.$param['process_rule_note'].",".$processRule->price."元/".$processRule->unit.',共'.$totalNum.'g'; + } + } + + + $encode = Json::encode($medicine); + + $chineseRecipe = new ChineseRepice(); + $chineseRecipe->su_id = \Yii::$app->user->id; + $chineseRecipe->content = $encode; + $chineseRecipe->deployment = $param['deployment']; + $chineseRecipe->dosage = $param['dosage']; + $chineseRecipe->consumption = $param['consumption']; + $chineseRecipe->is_deepfry = $param['is_deepfry']??0; + $chineseRecipe->volume = $param['volume']??0; + $chineseRecipe->cm_id = $param['cm_id']; + $chineseRecipe->process_rule_id = $param['process_rule_id'] ?? 0; + $chineseRecipe->process_rule = $processRuleContent; + $chineseRecipe->process_rule_note = $param['process_rule_note']; + $chineseRecipe->process_price = $process_price; + $chineseRecipe->total_price = round($price, 4); + $chineseRecipe->drug_ids = $drug_ids_str; + $chineseRecipe->saveOrFail(); + $transaction->commit(); + return [$chineseRecipe->id]; + } catch (Exception $e) { + $transaction->rollBack(); + throw $e; + } + } + + /** + * @doc-name 开中药处方 + * @doc-param string clinical_diagnose 临床诊断 + * @doc-param int up_id 就诊人id + * @doc-param string doctor_order 医嘱 + * @doc-param int category 类别1自费2医保 + * @doc-param string cr_ids 拼接药方id + */ + public function actionAddPrescription() + { + $id = \Yii::$app->user->identity->id; + + $param = \Yii::$app->request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['register_id', 'required'], + ['clinical_diagnose', 'required'], + ['up_id', 'required'], + ['category', 'required'], + ['doctor_order', 'required'], + ['cr_ids', 'required'], + ['treatement_price', 'number'] + ]); + + $transaction = \Yii::$app->db->beginTransaction(); + try { + $store_id = $param['store_id']; + + /* @var UserPatient $userPatient */ + $userPatient = UserPatient::find()->select('id,name,sex,id_card,user_id,mobile')->where(['id' => $param['up_id']])->one(); + if(!$userPatient){ + throw new Exception('就诊人不存在'); + } + + $register = Register::find()->where([ + 'id' => $param['register_id'], + 'user_patient_id' => $param['up_id'], + 'store_id' => $store_id + ])->with('healthInquery')->one(); + if(!$register){ + throw new Exception('挂号订单不存在'); + } + + $prescription_no = 'ZY' . rand(111111, 999999) . time(); + + $marketPrice = '0'; + $priceTotal = 0; + $processTotal = 0; + $ids = explode(',', $param['cr_ids']); + for ($i = 0; $i < sizeof($ids); $i++) { + $recipe = ChineseRepice::find()->where(['id' => $ids[$i]])->asArray()->one(); + if(!$recipe){ + throw new Exception('药方数据错误'); + } + $priceTotal += $recipe['total_price']; + $processTotal += $recipe['process_price']; + $content = Json::decode($recipe['content']); + + for ($j = 0; $j < sizeof($content); $j++) { + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $content[$j]['drug_id'] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + $drugNumber = (int) $content[$j]['number'] * (int) $recipe['dosage']; + if($drug['drugStoreDrug']['stock']<$drugNumber){ + throw new Exception($content['name'].'库存数量不足'); + } + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', [ + 'sale_number' => $drug['drugStoreRelation']['sale_number'] + $drugNumber + ], ['id' => $drug['drugStoreRelation']['id']])->execute(); + \Yii::$app->db->createCommand()->update('yii_drugstore_drug', [ + 'stock' => $drug['drugStoreDrug']['stock'] - $drugNumber, + 'frozen_number' => $drug['drugStoreDrug']['frozen_number'] + $drugNumber + ], ['id' => $drug['drugStoreDrug']['id']])->execute(); + $drug['number'] = $drugNumber; + $drugStoreDrugs[] = $drug; + $itemMarketPrice = bcmul($drugNumber,$drug['drugStoreRelation']['buy_price'],2); + $marketPrice = bcadd($marketPrice,$itemMarketPrice,2); + } + + } + + $priceTotal = round($priceTotal, 2); //对药品总价进行四舍五入 + + $repice = ChineseRepice::find()->where(['in', 'id', $ids])->asArray()->all(); + + $prescription_content['prescription_no'] = $prescription_no; + $prescription_content['repice'] = $repice; + $prescription_content['created_at'] = date('Y-m-d',time()); + $prescription_content['doctor_order'] = $param['doctor_order']; + $prescription_content['clinical_diagnose'] = $param['clinical_diagnose']; + $prescription_content['category'] = $param['category']==1?'自费':'医保'; + $prescription_content['patient'] = $userPatient; + $prescription_content['patient']['age'] = FuncHelper::getAgeFromIdNo($userPatient->id_card); + $prescription_content['doctor'] = DoctorInfo::find()->select('su_id,name,depart_id,title_id')->where(['su_id' => $id])->with(['depart','title'])->asArray()->one(); + $prescription_content['total_pay_price'] = $priceTotal; + + $prescriptionChinese = new PrescriptionChinese(); + $prescriptionChinese->store_id = $store_id; + $prescriptionChinese->prescription_no = $prescription_no; + $prescriptionChinese->su_id = $id; + $prescriptionChinese->user_id = $userPatient->user_id; + $prescriptionChinese->up_id = $param['up_id']; + $prescriptionChinese->status = 0; + $prescriptionChinese->type = 1;//普通方 + $prescriptionChinese->content = Json::encode($prescription_content); + $prescriptionChinese->category = $param['category']; + $prescriptionChinese->doctor_order = $param['doctor_order']; + $prescriptionChinese->clinical_diagnose = $param['clinical_diagnose']; + $prescriptionChinese->cr_ids = $param['cr_ids']; + $prescriptionChinese->saveOrFail(); + + $prescription = new Prescription(); + $prescription->store_id = $store_id; + $prescription->register_id = $param['register_id']; + $prescription->prescription_no = $prescription_no; + $prescription->su_id = $id; + $prescription->user_id = $userPatient->user_id; + $prescription->up_id = $param['up_id']; + $prescription->status = 0; + $prescription->type = 1;//普通方 + $prescription->is_online = 0; + $prescription->content = Json::encode($prescription_content); + $prescription->prescription_type = 1;// 中药 + $prescription->category = $param['category']; + $prescription->process_rule_id = $repice[0]['process_rule_id']; + $prescription->process_rule = $repice[0]['process_rule']; + $prescription->process_rule_note = $repice[0]['process_rule_note']; + $over_time = \Yii::$app->params['prescription']['over_time']; + $doctor_order = []; + if(date('H')>=16){ + $doctor_order[] = '该处方有效期延长为三天内有效'; + $over_time = 72*3600; + } + if($repice[0]['dosage'] > 7){ + $doctor_order[] = '患者需长期使用此药,开具超七天用量'; + } + if($param['doctor_second_sign'] == 1){ + $prescription->doctor_second_sign = 1; + } + $doctor_order[] = $param['doctor_order']; + $prescription->valid_hours = $over_time/3600; + $prescription->doctor_order = implode('|',$doctor_order); + $prescription->clinical_diagnose = $param['clinical_diagnose']; + $prescription->cr_ids = $param['cr_ids']; + $prescription->total_pay_price = $priceTotal; + $prescription->saveOrFail(); + + //获取支付方式配置 + $payConfig = PayConfig::findOne(['status' => 1, 'current_use' => 1]); + + // 生成商品订单 + $productOrder = new ProductOrder(); + $productOrder->store_id = $store_id; + $productOrder->su_id = $id; + $productOrder->user_id = $userPatient->user_id; + $productOrder->up_id = $userPatient->id; + $productOrder->order_no = Carbon::now()->format('YmdHis') . rand(10000, 99999) . rand(10000, 99999); + $productOrder->p_id = $prescription->id; + $productOrder->dosage = $repice[0]['dosage']; + $productOrder->order_type = 1; + $productOrder->prescription_type = 1;//中药处方 + $productOrder->type = $payConfig->pay_type??0;//0未知 1微信 2易票联 + $productOrder->is_pay = 0; + $productOrder->trans_expenses = 0; + $productOrder->items_price = $priceTotal; + $productOrder->market_price = $marketPrice; + $productOrder->process_price = $processTotal; + $treatementPrice = 0; + if($param['treatement_price']){ + $treatementPrice = $param['treatement_price']; + } + $productOrder->treatement_price = $treatementPrice; + + $userAddress = Address::find()->select('id,name,mobile,province,region,detail_address')->where(['user_id' => $prescription->user_id])->orderBy('is_default DESC')->asArray()->all(); + if(count($userAddress)>0){ + $productOrder->address_id = $userAddress[0]['id']; + $productOrder->address = Json::encode($userAddress[0]); + $productOrder->express_name = $userAddress[0]['name']; + $productOrder->express_mobile = $userAddress[0]['mobile']; + $productOrder->express_region = $userAddress[0]['region']; + $productOrder->express_address = $userAddress[0]['detail_address']; + $region = Region::find()->where(['name' => $userAddress[0]['province']])->one(); + $productOrder->trans_expenses = $region->express_fee; + $priceTotal = $priceTotal + $region->express_fee; + } + + $productOrder->total_pay_price = $priceTotal + $processTotal + $treatementPrice; + $productOrder->status = ProductOrderEnum::UNPAY; + $productOrder->pay_method = 1; + $productOrder->free_ship = 1; + $productOrder->sync_order_no = $param['sync_order_no']??''; + $productOrder->saveOrFail(); + + $productOrderItem = new ProductOrderItems(); + foreach ($drugStoreDrugs as $v) { + $item = clone $productOrderItem; + $item->product_order_id = $productOrder->id; + $item->drug_id = $v['id']; + $item->drug_image = $v['image']; + $item->drug_no = $v['drug_number']; + $item->number = $v['number']; + $item->type = $v['type']; + $item->price = $v['drugStoreRelation']['price']; + $item->buy_price = $v['drugStoreRelation']['buy_price']; + $item->drug_name = $v['drug_name']; + $item->small_info = $v['small_info']; + $item->saveOrFail(); + } + + //触发处方自动失效事件 + $prescriptionEvent = new PrescriptionEvent(); + $prescriptionEvent->prescription = $prescription; + $prescriptionEvent->sender = $this; + \Yii::$app->trigger(Prescription::AUTO_EXPIRE, $prescriptionEvent); + + //触发订单创建事件 + $event = new ProductOrderEvent(); + $event->order = $productOrder; + $event->sender = $this; + \Yii::$app->trigger(ProductOrder::EVENT_CREATED, $event); + + //处方开具待支付订阅消息通知 + \Yii::$app->queue->push(new PrescriptionCreated([ + 'orderId' => $prescription->id, + ])); + + //发送处方系统通知 + $systemNotice = new SystemNotice(); + $systemNotice->data = $prescription_no; + $systemNotice->store_id = $store_id; + $systemNotice->content = '医生已为您开具处方,请及时查看!'; + $systemNotice->base_type = 4;//处方通知 + $systemNotice->scene_type = 1; + $systemNotice->user_id = $userPatient->user_id; + $systemNotice->notice_at = date('Y-m-d H:i:s',time()); + $systemNotice->saveOrFail(); + + $transaction->commit(); + + + //处方生成短信通知药师审方 + \Yii::$app->queue->push(new WaitApprovalMessageJob([ + 'orderId' => $prescription->id, + ])); + + return [ + 'id' => $prescription->id, + 'product_order_id' => $productOrder->id, + 'prescription_no' => $prescription_no, + 'issue_time' => time(), + 'clinical_diagnose' => $param['clinical_diagnose'] + ]; + } catch (Exception $e) { + $transaction->rollBack(); + throw $e; + } + } + + /*******************************************************颗粒药******************************************************************************** */ + + + /** + * @doc-name 颗粒药列表 + * @doc-param string name 药名 + */ + public function actionGranularList() + { + $name = \Yii::$app->request->post('name'); + $store_id =\Yii::$app->request->post('store_id'); + + if(!$name){ + throw new Exception('请输入药品名称关键字'); + } + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.type' => 3 + ])->andWhere([ + 'or', + ['like', 'd.drug_name', '%' . $name . "%", false], + ['like', 'd.pinyin_simple', '%' . $name . "%", false], + ['like', 'd.drug_alias', '%' . $name . "%", false] + ])->with('unit')->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->all(); + + if (!$drug) { + throw new Exception('没有找到您要搜索的药品'); + } + + foreach($drug as $k=>$v){ + $drug[$k]['buy_price'] = $v['drugStoreRelation']['buy_price']; + $drug[$k]['price'] = $v['drugStoreRelation']['price']; + $drug[$k]['stock'] = $v['drugStoreDrug']['stock']; + unset($drug[$k]['drugStoreRelation']); + unset($drug[$k]['drugStoreDrug']); + } + + return $drug; + } + + /** + * @doc-name 一次添加一个中药 + * @doc-param int drug_id 药id + * @doc-param int number 数量 + */ + public function actionAddOneGranular() + { + $request = \Yii::$app->request; + $param = $request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['drug_id', 'required'], + ['number', 'required'] + ]); + + $store_id = $param['store_id']; + + try { + $transaction = \Yii::$app->db->beginTransaction(); + + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $param['drug_id'] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品不存在'); + } + if ($param['number'] > $drug['drugStoreDrug']['stock']) throw new Exception('库存不够'); + + $GranularMedicine = new GranularMedicine(); + $GranularMedicine->drug_id = $param['drug_id']; + $GranularMedicine->drug_number = $drug['drug_number']; + $GranularMedicine->name = $drug['drug_name']; + $GranularMedicine->number = $param['number']; + $GranularMedicine->order = $param['order']??0; + $GranularMedicine->order = $drug['unit_id']??0; + $GranularMedicine->price = $drug['drugStoreRelation']['price']; + $GranularMedicine->buy_price = $drug['drugStoreRelation']['buy_price']; + $GranularMedicine->saveOrFail(); + + $transaction->commit(); + return [$GranularMedicine->id]; + } catch (Exception $e) { + $transaction->rollBack(); + throw $e; + } + } + + /** + * @doc-name 添加颗粒药药方 + * @doc-param int deployment 调配1煎煮2外配 + * @doc-param int dosage 剂数id + * @doc-param int consumption 用量id + * @doc-param int usage 用法 + * @doc-param int fufa_id 服法id + * @doc-param string remark 备注 + * @doc-param int is_deepfry 是否浓煎0否1是 + * @doc-param string cm_id 颗粒药处方的颗粒药表id + * @doc-return array aa bb + */ + public function actionAddGranularRecipe() + { + $param = \Yii::$app->request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['deployment', 'required'], + ['dosage', 'required'], + ['consumption', 'required'], + ['gm_id', 'required'], + ['process_rule_id','integer'], + ['process_rule_note','string'] + ]); + + $store_id = $param['store_id']; + + try { + $transaction = \Yii::$app->db->beginTransaction(); + + $ids = explode(',', $param['gm_id']); + + $price = 0; + $totalNum = 0; + $medicine = GranularMedicine::find()->select('id,drug_id,name,order,unit,number,price,buy_price,drug_number')->with(['unit','useWay'])->where(['in', 'id', $ids])->asArray()->all(); + foreach ($medicine as $value){ + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $value['drug_id'] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + $drugNumber = (int) $value['number'] * (int) $param['dosage']; + if($drug['drugStoreDrug']['stock'] < $drugNumber){ + throw new Exception($value['name'].'库存数量不足'); + } + $totalNum += $drugNumber; + $price+=$value['number'] * $value['price'] * $param['dosage']; + } + + $encode = Json::encode($medicine); + + if($param['process_rule_id']){ + $processRule = ProcessRule::find()->where(['id' => $param['process_rule_id']])->one(); + if(empty($processRule)){ + throw new Exception("加工方式错误"); + } + if($processRule->calc_method == 1){ + $process_price = $processRule->price; + $processRuleContent = $processRule->name.",固定收费".$process_price."元"; + }elseif($processRule->calc_method == 2){ + $process_price = $processRule->price * $param['dosage']; + $processRuleContent = $processRule->name.",".$processRule->price."元/".$processRule->unit; + }else{ + $process_price = $processRule->price * $totalNum; + $processRuleContent = $processRule->name.",".$processRule->price."元/".$processRule->unit; + } + } + + + $GranularRecipe = new GranularRepice(); + $GranularRecipe->content = $encode; + $GranularRecipe->total_price = round($price, 4); + $GranularRecipe->deployment = $param['deployment']; + $GranularRecipe->dosage = $param['dosage']; + $GranularRecipe->consumption = $param['consumption']; + $GranularRecipe->is_deepfry = $param['is_deepfry']??0; + $GranularRecipe->volume = $param['volume']??0; + $GranularRecipe->gm_id = $param['gm_id']; + $GranularRecipe->process_rule_id = $param['process_rule_id']; + $GranularRecipe->process_rule = $processRuleContent; + $GranularRecipe->process_rule_note = $param['process_rule_note']; + $GranularRecipe->process_price = $process_price; + $GranularRecipe->saveOrFail(); + + $transaction->commit(); + + return [$GranularRecipe->id]; + } catch (Exception $e) { + $transaction->rollBack(); + throw $e; + } + } + + /** + * @doc-name 开颗粒药处方 + * @doc-param string clinical_diagnose 临床诊断 + * @doc-param int up_id 就诊人id + * @doc-param string doctor_order 医嘱 + * @doc-param int category 类别1自费2医保 + * @doc-param string cr_ids 拼接药方id + */ + public function actionAddPrescriptionGranular() + { + $id = \Yii::$app->user->identity->id; + + $param = \Yii::$app->request->post(); + $this->requestValidate($param, [ + ['store_id', 'required'], + ['register_id', 'required'], + ['clinical_diagnose', 'required'], + ['up_id', 'required'], + ['category', 'required'], + ['doctor_order', 'required'], + ['gr_ids', 'required'], + ['treatement_price', 'number'] + ]); + + $transaction = \Yii::$app->db->beginTransaction(); + try { + $store_id = $param['store_id']; + + /* @var UserPatient $userPatient */ + $userPatient = UserPatient::find()->select('id,name,sex,id_card,user_id,mobile')->where(['id' => $param['up_id']])->one(); + if(!$userPatient){ + throw new Exception('就诊人不存在'); + } + + $register = Register::find()->where([ + 'id' => $param['register_id'], + 'user_patient_id' => $param['up_id'], + 'store_id' => $store_id + ])->with('healthInquery')->one(); + if(!$register){ + throw new Exception('挂号订单不存在'); + } + + $prescription_no = 'GY' . rand(111111, 999999) . time(); + + $marketPrice = '0'; + $priceTotal = 0; + $processTotal = 0; + $ids = explode(',', $param['gr_ids']); + for ($i = 0; $i < sizeof($ids); $i++) { + $recipe = GranularRepice::find()->where(['id' => $ids[$i]])->asArray()->one(); + if(!$recipe){ + throw new Exception('药方数据错误'); + } + $priceTotal += $recipe['total_price']; + $processTotal += $recipe['process_price']; + $content = Json::decode($recipe['content']); + + for ($j = 0; $j < sizeof($content); $j++) { + $drug = Drug::find()->alias('d')->select('d.*')->where([ + 'd.id' => $content[$j]['drug_id'] + ])->joinWith(['drugStoreDrug dsd' => function($q){ + $q->andWhere(['dsd.status' => 2]); + }])->joinWith(['drugStoreRelation dsr' => function ($q) use ($store_id){ + $q->andWhere(['dsr.store_id' => $store_id]); + $q->andWhere(['dsr.status' => 2]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + $drugNumber = (int) $content[$j]['number'] * (int) $recipe['dosage']; + if($drug['drugStoreDrug']['stock']<$drugNumber){ + throw new Exception($content['name'].'库存数量不足'); + } + \Yii::$app->db->createCommand()->update('yii_drug_store_relations', [ + 'sale_number' => $drug['drugStoreRelation']['sale_number'] + $drugNumber + ], ['id' => $drug['drugStoreRelation']['id']])->execute(); + \Yii::$app->db->createCommand()->update('yii_drugstore_drug', [ + 'stock' => $drug['drugStoreDrug']['stock'] - $drugNumber, + 'frozen_number' => $drug['drugStoreDrug']['frozen_number'] + $drugNumber + ], ['id' => $drug['drugStoreDrug']['id']])->execute(); + $drug['number'] = $drugNumber; + $drugStoreDrugs[] = $drug; + $itemMarketPrice = bcmul($drugNumber,$drug['drugStoreRelation']['buy_price'],2); + $marketPrice = bcadd($marketPrice,$itemMarketPrice,2); + } + } + + $priceTotal = round($priceTotal, 2); //对药品总价进行四舍五入 + + + //组装处方快照 + $repice = GranularRepice::find()->where(['in', 'id', $ids])->asArray()->all(); + $prescription_content['prescription_no'] = $prescription_no; + $prescription_content['repice'] = $repice; + $prescription_content['created_at'] = date('Y-m-d',time()); + $prescription_content['doctor_order'] = $param['doctor_order']; + $prescription_content['clinical_diagnose'] = $param['clinical_diagnose']; + $prescription_content['category'] = $param['category']==1?'自费':'医保'; + $prescription_content['patient'] = $userPatient; + $prescription_content['patient']['age'] = FuncHelper::getAgeFromIdNo($userPatient->id_card); + $prescription_content['doctor'] = DoctorInfo::find()->select('su_id,name,depart_id,title_id')->where(['su_id' => $id])->with(['depart','title'])->asArray()->one(); + $prescription_content['total_pay_price'] = $priceTotal; + + + + $prescriptionGranular = new PrescriptionGranular(); + $prescriptionGranular->store_id = $store_id; + $prescriptionGranular->prescription_no = $prescription_no; + $prescriptionGranular->su_id = $id; + $prescriptionGranular->user_id = $userPatient->user_id; + $prescriptionGranular->up_id = $param['up_id']; + $prescriptionGranular->status = 0; + $prescriptionGranular->type = 1;//普通方 + $prescriptionGranular->content = Json::encode($prescription_content); + $prescriptionGranular->category = $param['category']; + $prescriptionGranular->doctor_order = $param['doctor_order']; + $prescriptionGranular->clinical_diagnose = $param['clinical_diagnose']; + $prescriptionGranular->gr_ids = $param['gr_ids']; + $prescriptionGranular->saveOrFail(); + + + + $prescription = new Prescription(); + $prescription->store_id = $store_id; + $prescription->register_id = $param['register_id']; + $prescription->prescription_no = $prescription_no; + $prescription->su_id = $id; + $prescription->user_id = $userPatient->user_id; + $prescription->up_id = $param['up_id']; + $prescription->status = 0; + $prescription->type = 1;//普通方 + $prescription->is_online = 0; + $prescription->content = Json::encode($prescription_content); + $prescription->prescription_type = 3; // 颗粒药 + $prescription->category = $param['category']; + $prescription->process_price = $processTotal; + $prescription->process_rule_id = $repice[0]['process_rule_id']; + $prescription->process_rule = $repice[0]['process_rule']; + $prescription->process_rule_note = $repice[0]['process_rule_note']; + $over_time = \Yii::$app->params['prescription']['over_time']; + $doctor_order = []; + if(date('H')>=16){ + $doctor_order[] = '该处方有效期延长为三天内有效'; + $over_time = 72*3600; + } + if($repice[0]['dosage'] > 7){ + $doctor_order[] = '患者需长期使用此药,开具超七天用量'; + } + $doctor_order[] = $param['doctor_order']; + $prescription->valid_hours = $over_time/3600; + $prescription->doctor_order = implode('|',$doctor_order); + $prescription->clinical_diagnose = $param['clinical_diagnose']; + $prescription->gr_ids = $param['gr_ids']; + $prescription->total_pay_price = $priceTotal; + $prescription->saveOrFail(); + + //获取支付方式配置 + $payConfig = PayConfig::findOne(['status' => 1, 'current_use' => 1]); + + // 生成商品订单 + $productOrder = new ProductOrder(); + $productOrder->store_id = $store_id; + $productOrder->su_id = $id; + $productOrder->user_id = $userPatient->user_id; + $productOrder->up_id = $userPatient->id; + $productOrder->order_no = Carbon::now()->format('YmdHis') . rand(10000, 99999) . rand(10000, 99999); + $productOrder->p_id = $prescription->id; + $productOrder->dosage = $repice[0]['dosage']; + $productOrder->order_type = 1; + $productOrder->prescription_type = 3;//颗粒药处方 + $productOrder->type = $payConfig->pay_type??2;//1微信 2易票联 + $productOrder->is_pay = 0; + $productOrder->trans_expenses = 0; + $productOrder->items_price = $priceTotal; + $productOrder->market_price = $marketPrice; + $productOrder->process_price = $processTotal; + $treatementPrice = 0; + if($param['treatement_price']){ + $treatementPrice = $param['treatement_price']; + } + $productOrder->treatement_price = $treatementPrice; + + $productOrder->status = ProductOrderEnum::UNPAY; + $userAddress = Address::find()->select('id,name,mobile,province,region,detail_address')->where(['user_id' => $prescription->user_id])->orderBy('is_default DESC')->asArray()->all(); + if(count($userAddress)>0){ + $productOrder->address_id = $userAddress[0]['id']; + $productOrder->address = Json::encode($userAddress[0]); + $productOrder->express_name = $userAddress[0]['name']; + $productOrder->express_mobile = $userAddress[0]['mobile']; + $productOrder->express_region = $userAddress[0]['region']; + $productOrder->express_address = $userAddress[0]['detail_address']; + $region = Region::find()->where(['name' => $userAddress[0]['province']])->one(); + $productOrder->trans_expenses = $region->express_fee; + $priceTotal = $priceTotal + $region->express_fee; + } + $productOrder->total_pay_price = $priceTotal + $processTotal + $treatementPrice; + $productOrder->pay_method = 1; + $productOrder->free_ship = 1; + $productOrder->sync_order_no = $param['sync_order_no']??''; + $productOrder->saveOrFail(); + + $productOrderItem = new ProductOrderItems(); + foreach ($drugStoreDrugs as $v) { + $item = clone $productOrderItem; + $item->product_order_id = $productOrder->id; + $item->drug_id = $v['id']; + $item->drug_image = $v['image']; + $item->drug_no = $v['drug_number']; + $item->number = $v['number']; + $item->type = $v['type']; + $item->price = $v['drugStoreRelation']['price']; + $item->buy_price = $v['drugStoreRelation']['buy_price']; + $item->drug_name = $v['drug_name']; + $item->small_info = $v['small_info']; + $item->saveOrFail(); + } + + //触发处方自动失效事件 + $prescriptionEvent = new PrescriptionEvent(); + $prescriptionEvent->prescription = $prescription; + $prescriptionEvent->sender = $this; + \Yii::$app->trigger(Prescription::AUTO_EXPIRE, $prescriptionEvent); + + //触发订单自动取消事件 + $event = new ProductOrderEvent(); + $event->order = $productOrder; + $event->sender = $this; + \Yii::$app->trigger(ProductOrder::EVENT_CREATED, $event); + + //处方开具待支付订阅消息通知 + \Yii::$app->queue->push(new PrescriptionCreated([ + 'orderId' => $prescription->id, + ])); + + //发送处方系统通知 + $systemNotice = new SystemNotice(); + $systemNotice->data = $prescription_no; + $systemNotice->store_id = $store_id; + $systemNotice->content = '医生已为您开具处方,请及时查看!'; + $systemNotice->base_type = 4;//处方通知 + $systemNotice->scene_type = 1; + $systemNotice->user_id = $userPatient->user_id; + $systemNotice->notice_at = date('Y-m-d H:i:s',time()); + $systemNotice->saveOrFail(); + + $transaction->commit(); + + //处方生成短信通知药师审方 + \Yii::$app->queue->push(new WaitApprovalMessageJob([ + 'orderId' => $prescription->id, + ])); + + return [ + 'id' => $prescription->id, + 'product_order_id' => $productOrder->id, + 'prescription_no' => $prescription_no, + 'issue_time' => time(), + 'clinical_diagnose' => $param['clinical_diagnose'] + ]; + } catch (Exception $e) { + $transaction->rollBack(); + throw $e; + } + } + + /** + * 常用诊断 + */ + public function actionDiseaseCommon(){ + $diseaseCommon = DiseaseCommon::find()->select('id,disease_id')->where([ + 'su_id' => \Yii::$app->user->identity->id + ])->with('disease')->orderBy('created_at DESC')->asArray()->all(); + return $diseaseCommon; + } + + /** + * 添加常用诊断 + */ + public function actionAddDiseaseCommon(){ + $post = \YII::$app->request->post(); + $this->requestValidate($post,[ + ['disease_id','required'] + ]); + $diseaseCommon = DiseaseCommon::findOne([ + 'su_id' => \YII::$app->user->identity->id, + 'disease_id' => $post['disease_id'] + ]); + if($diseaseCommon){ + throw new Exception('已是您的常用诊断'); + } + $diseaseCommon = new DiseaseCommon(); + $diseaseCommon->su_id = \YII::$app->user->identity->id; + $diseaseCommon->disease_id = $post['disease_id']; + $diseaseCommon->saveOrFail(); + + return ['添加常用诊断成功']; + } + + /** + * 删除常用诊断 + */ + public function actionDelDiseaseCommon(){ + $post = \YII::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'] + ]); + $diseaseCommon = DiseaseCommon::findOne([ + 'su_id' => \YII::$app->user->identity->id, + 'id' => $post['id'] + ]); + if(!$diseaseCommon){ + throw new Exception('参数错误'); + } + $diseaseCommon->delete(); + + return ['删除常用诊断成功']; + } + + + /** + * @doc-name 搜索疾病 + * @doc-param string name 疾病关键字 + */ + public function actionSearchDisease() + { + $name = \Yii::$app->request->get('name'); + if (!$name) throw new Exception('输入需要搜索的诊断'); + + $query = Disease::find()->where([ + 'or', + ['like', 'name', '%' . $name . "%", false], + ['like', 'pinyin', '%' . $name . "%", false] + ]); + + $this->field = [ + Disease::class => [ + 'id', 'name' + ] + ]; + return $this->create($query, ['page_size' => 50]); + } + + /** + * @doc-name 处方详情 + * @doc-param string prescription_no 处方编号 + * @doc-return mixed @List{id-int-处方id,prescription_no-int-处方编号,type-int-类型1普通方2常用方,created_at-int-开具时间,clinical_diagnose-string-临床诊断,category-int-类别1自费2医保,status-int-状态0待审核1已通过2未通过3待使用4已使用5未使用6已失效7已初审,doctor_order-string-医嘱,patient_name-string-患者,sex-int-0默认1男2女,age-int-年龄,depart-string-科室,mobile-string-手机号,doctor_name-string-医生,first_view-string-初审药师,again_view-string-复审药师,patient_name-string-患者,@Rp{@Granular{content-string-药品有关信息,dosage-int-剂数,useNum-string-用量,usage-int-用法,fufa-string-服法,is_deepfry-int-是否浓煎0否1是,total_price-float-价格},@West{content-string-药品有关信息,number-int-数量,available_days-int-可用天数,total_price-float-价格}}} 处方记录 + */ + public function actionPrescriptionDetail() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['prescription_no', 'required'], + ['store_id', 'required'] + ]); + return (new PrescriptionService())->detail($post['prescription_no']); + } + + + /** + * 中药相冲相畏有毒检查 + */ + public function actionDrugCheck(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['cr_ids', 'required'], + ['store_id', 'required'] + ]); + $ids = explode(',',$post['cr_ids']); + $repice = ChineseRepice::find()->where(['in', 'id', $ids])->asArray()->all(); + if(!$repice){ + throw new Exception('药品不存在'); + } + // $prescription = Prescription::find()->select('content')->where([ + // 'prescription_no' => $post['prescription_no'], + // 'prescription_type' => 1 + // ])->asArray()->one(); + // if(!$prescription){ + // throw new Exception('中药处方不存在'); + // } + // $drugData = $prescription['repice'][0]['content']; + $drugArr = json_decode($repice[0]['content'],true); + $drugs = array_column($drugArr,'name'); + if(array_intersect($drugs,DrugEnum::POISONOUS)){ + return [ + 'is_exist' => true, + 'message'=>'处方中存在有毒药品' + ]; + } + foreach(DrugEnum::OPPOSITION as $key=>$value){ + if(in_array($key,$drugs)){ + if(array_intersect($value,$drugs)){ + return [ + 'is_exist' => true, + 'message' => '处方中存在十八反药品' + ]; + } + } + } + + foreach(DrugEnum::CONFLCT as $v){ + $conflictArr = array_intersect($v,$drugs); + if($conflictArr && !array_diff($conflictArr,$v) && !array_diff($v,$conflictArr)){ + return [ + 'is_exist' => true, + 'message' => '处方中存在十九畏药品' + ]; + } + } + return [ + 'is_exist' => false + ]; + } + +} diff --git a/service/modules/v1/controllers/QuickController.php b/service/modules/v1/controllers/QuickController.php new file mode 100644 index 0000000..ddad50c --- /dev/null +++ b/service/modules/v1/controllers/QuickController.php @@ -0,0 +1,296 @@ +where(['su_id'=> \Yii::$app->user->identity->getId()])->count() == 0) { + $info = new ReplayTemplateGroup(); + $info->su_id = \Yii::$app->user->identity->getId(); + $info->group_name = '默认分组'; + $info->save(); + } + + $keyword = \Yii::$app->request->post('keyword'); + $query = ReplayTemplateGroup::find() + ->alias('group') + ->select(['group.id', 'group.group_name', 'group.sort']) + ->with([ + 'templates' => function ($query) { + $query + ->select(['yii_replay_template.id', 'yii_replay_template.group_id', 'yii_replay_template.content', 'yii_replay_template.sort']) + ->where(['yii_replay_template.su_id' => \Yii::$app->user->identity->getId()]); + } + ]) + ->where([ + 'group.su_id' => \Yii::$app->user->identity->getId(), + ]) + ->orderBy(['sort' => SORT_ASC]); + if ($keyword) { + $query->joinWith([ + 'templates' => function ($query) use ($keyword) { + $query->andFilterWhere(['like', 'content', $keyword]); + } + ]); + } + return $query->asArray()->all(); + } + + /** + * @doc-name 快捷回复-模版新增/修改 + * @doc-desc 如果新增id则不填 + * @doc-param string content 模板内容 + * @doc-param int group_id 分组ID + */ + public function actionTemplateSave() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + [['content','group_id'],'required'] + ]); + + if ($post['id']) { + $info = ReplayTemplate::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'id' => $post['id'], + 'group_id' => $post['group_id'], + ]) + ->one(); + if (!$info) { + throw new Exception('模版不存在'); + } + if ( + ReplayTemplate::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'group_id' => $post['group_id'], + 'content' => $post['content'], + ]) + ->andWhere(['<>', 'id', $post['id']]) + ->exists() + ) { + throw new Exception('模版重复'); + } + $info->content = $post['content']; + $info->saveOrFail(); + return ['修改成功']; + } else { + if ( + ReplayTemplate::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'content' => $post['content'], + ]) + ->exists() + ) + { + throw new Exception('模版重复'); + } + $info = new ReplayTemplate(); + $info->su_id = \Yii::$app->user->identity->getId(); + $info->group_id = $post['group_id']; + $info->content = $post['content']; + $info->saveOrFail(); + return ['新增成功']; + } + } + + /** + * @doc-name 快捷回复-模版删除 + * @doc-param int id 模板ID + * @doc-param int group_id 分组ID + */ + public function actionTemplateDelete() + { + $id = \Yii::$app->request->post('id'); + $group_id = \Yii::$app->request->post('group_id'); + if (!$id || !$group_id) { + throw new Exception('请选择一个模版'); + } + $info = ReplayTemplate::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'id' => $id, + 'group_id' => $group_id, + ]) + ->one(); + if (!$info) { + throw new Exception('模版不存在'); + } + $info->delete(); + return ['删除成功']; + } + + /** + * @doc-name 快捷回复-模板排序更改 + * @doc-param array data 分组[{id:1,sort:0}] + * @doc-param int group_id 分组ID + */ + public function actionTemplateSort() + { + $post = \Yii::$app->request->post(); + + $this->requestValidate($post,[ + [['group_id','data'],'required'] + ]); + foreach ($post['data'] as $value) { + $info = ReplayTemplate::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'id' => $value['id'], + 'group_id' => $post['group_id'], + ]) + ->one(); + $info->sort = $value['sort']; + $info->save(); + } + } + + /** + * @doc-name 快捷回复-分组列表 + * @doc-author hyl + * @doc-return int id 分组id + * @doc-return string group_name 名称 + * @doc-return int sort 排序 + */ + public function actionGroupLists() + { + if (ReplayTemplateGroup::find()->where(['su_id' => \Yii::$app->user->identity->getId(),])->count() == 0) + { + $info = new ReplayTemplateGroup(); + $info->su_id = \Yii::$app->user->identity->getId(); + $info->group_name = '默认分组'; + $info->save(); + } + $lists = ReplayTemplateGroup::find() + ->select(['id', 'group_name', 'sort']) + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + ]) + ->orderBy(['sort' => SORT_ASC]) + ->all(); + return $lists; + } + + /** + * @doc-name 快捷回复-分组新增/修改 + * @doc-desc 分组id如果新增则不传 + * @doc-param int id 分组id / optional + * @doc-param string group_name 分组名 + */ + public function actionGroupSave() + { + $post = \Yii::$app->request->post(); + + $this->requestValidate($post,[ + ['group_name','required'] + ]); + + if ($post['id']) { + $info = ReplayTemplateGroup::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'id' => $post['id'], + ])->one(); + + if (!$info) throw new Exception('分组名不存在'); + + if ($post['group_name'] == '默认分组') throw new Exception('默认分组名不可修改'); + + if ( + ReplayTemplateGroup::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'group_name' => $post['group_name'], + ]) + ->andWhere(['<>', 'id', $post['id']]) + ->exists() + ) throw new Exception('分组名重复'); + + $info->group_name = $post['group_name']; + $info->saveOrFail(); + return ['修改成功']; + } else { + if ( + ReplayTemplateGroup::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'group_name' => $post['group_name'], + ]) + ->exists() + ) { + throw new Exception('分组名重复'); + } + $info = new ReplayTemplateGroup(); + $info->su_id = \Yii::$app->user->identity->getId(); + $info->group_name = $post['group_name']; + $info->saveOrFail(); + return ['新增成功']; + } + } + + /** + * @doc-name 快捷回复-分组删除 + * @doc-param id int 分组id + */ + public function actionGroupDelete() + { + $id = \Yii::$app->request->post('id'); + if (!$id) { + throw new Exception('请选择一个分组'); + } + $info = ReplayTemplateGroup::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'id' => $id, + ]) + ->one(); + if (!$info) { + throw new Exception('分组名不存在'); + } + $info->delete(); + return ['删除成功']; + } + + + /** + * @doc-name 快捷回复-分组排序更改 + * @doc-param array data 分组[{id:1,sort:0}] + */ + public function actionGroupSort() + { + $data = \Yii::$app->request->post('data'); + if (!$data) throw new \yii\db\Exception('data不能为空'); + + foreach ($data as $value) { + $info = ReplayTemplateGroup::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->getId(), + 'id' => $value['id'], + ]) + ->one(); + $info->sort = $value['sort']; + $info->save(); + } + return ['更新成功']; + } +} diff --git a/service/modules/v1/controllers/RecipeController.php b/service/modules/v1/controllers/RecipeController.php new file mode 100644 index 0000000..6ad76cf --- /dev/null +++ b/service/modules/v1/controllers/RecipeController.php @@ -0,0 +1,289 @@ +doctorInfo = DoctorInfo::findOne(['su_id' => \Yii::$app->user->identity->id]); + if(!$this->doctorInfo){ + throw new Exception('无权限进行该操作'); + } + return $ret; + } + + /** + * @doc-name 查看西药药方 + * @doc-param int recipe_id 药方id + * @doc-param int prescription_id 处方id + */ + public function actionQueryWest() + { + $recipe_id = \Yii::$app->request->post('recipe_id'); + if (!$recipe_id) throw new Exception('药方id不能为空'); + $recipe = WestRepice::find()->where(['id' => $recipe_id])->one(); + if (!$recipe) throw new Exception('药方不存在'); + + return $recipe; + } + + /** + * @doc-name 修改西药药方 + * @doc-param int recipe_id 药方id + * @doc-param int number 数量 + * @doc-param string instruction 说明书 + * @doc-param int time_id 使用时间id + * @doc-param int type_id 使用类型id + * @doc-param int grain_number 粒数 + * @doc-param int f_id 频率 + * @doc-param int wu_id 西药单位id + * @doc-param int available_days 可用天数 + */ + public function actionChangeWest() + { + $request=\Yii::$app->request; + $param = $request->post(); + if (!$param['recipe_id']) throw new Exception('药方id不能为空'); + + $this->requestValidate($param,[ + ['store_id', 'required'], + ['number', 'required'], + // ['instruction', 'required'], + ['type_id', 'required'], + ['grain_number', 'required'], + ['wu_id', 'required'], + ['available_days', 'required'], + ['f_id', 'required'] + ]); + $store_id = $param['store_id']; + $recipe = WestRepice::find()->where(['id' => $param['recipe_id']])->one(); + if (!$recipe) throw new Exception('药方不存在'); + + $content = Json::decode($recipe['content']); + $drug = DrugStoreDrug::find()->alias('dsd')->where(['dsd.drug_id' => $content['id']])->joinWith(['store s' => function ($q) use ($store_id){ + $q->andWhere(['s.id' => $store_id]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + if($drug['stock'] < $param['number']){ + throw new Exception('药品库存数量不足'); + } + + $recipe->number = $param['number']; + $recipe->instruction = $param['instruction']??''; + $recipe->time_id = $param['time_id']??0; + $recipe->type_id = $param['type_id']; + $recipe->grain_number = $param['grain_number']; + $recipe->wu_id = $param['wu_id']; + $recipe->available_days = $param['available_days']; + $recipe->f_id = $param['f_id']; + $recipe->save(); + + return ['修改成功']; + } + + public function actionChangeOneChinese(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'], + ['number','required'], + [['id','number','order'],'integer'] + ]); + $chineseMedicine = ChineseMedicine::findOne(['id' => $post['id']]); + if(!$chineseMedicine){ + throw new Exception('药品不存在'); + } + $chineseMedicine->order = $post['order']??0; + $chineseMedicine->number = $post['number']; + $chineseMedicine->save(); + return ['修改成功']; + } + + /** + * @doc-name 修改中药药方 + * @doc-param int recipe_id 药方id + * @doc-param int deployment 调配1煎煮 2外配 + * @doc-param int dosage 剂数 + * @doc-param int consumption 用量id + * @doc-param int usage 用法id + * @doc-param int fufa_id 服法id + * @doc-param string remark 备注 + * @doc-param int is_deepfry 是否浓煎0否1是 + */ + public function actionChangeChinese() + { + $request=\Yii::$app->request; + $param = $request->post(); + if (!$param['recipe_id']) throw new Exception('药方id不能为空'); + + $this->requestValidate($param,[ + ['store_id', 'required'], + ['deployment', 'required'], + ['dosage', 'required'], + ['consumption', 'required'], + ['cm_id', 'required'], + ]); + + $store_id = $param['store_id']; + $recipe = ChineseRepice::find()->where(['id' => $param['recipe_id']])->one(); + if (!$recipe) throw new Exception('药方不存在'); + + $ids = explode(',', $param['cm_id']); + + $price = 0; + $medicine = ChineseMedicine::find()->where(['in', 'id', $ids])->all(); + foreach ($medicine as $value){ + $drug = DrugStoreDrug::find()->alias('dsd')->where(['dsd.drug_id' => $value['drug_id']])->joinWith(['store s' => function ($q) use ($store_id){ + $q->andWhere(['s.id' => $store_id]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + $drugNumber = $value['number'] * $param['dosage']; + if($drug['stock'] < $drugNumber){ + throw new Exception($value['name'].'库存数量不足'); + } + $price+=$drugNumber * $value['price']; + } + + $encode = Json::encode($medicine); + + $recipe->content = $encode; + $recipe->deployment = $param['deployment']; + $recipe->dosage = $param['dosage']; + $recipe->consumption = $param['consumption']; + $recipe->is_deepfry = $param['is_deepfry']?0:1; + $recipe->volume = $param['volume']??0; + $recipe->cm_id = $param['cm_id']; + $recipe->total_price = $price; + $recipe->saveOrFail(); + + return [$param['recipe_id']]; + } + + public function actionChangeOneGranular(){ + $post = \Yii::$app->request->post(); + $this->requestValidate($post,[ + ['id','required'], + ['number','required'], + [['id','number'],'integer'] + ]); + $GranularMedicine = GranularMedicine::findOne(['id' => $post['id']]); + if(!$GranularMedicine){ + throw new Exception('药品不存在'); + } + $GranularMedicine->number = $post['number']; + $GranularMedicine->save(); + return ['修改成功']; + } + + /** + * @doc-name 修改颗粒药药方 + * @doc-param int recipe_id 药方id + * @doc-param int deployment 调配1煎煮2外配 + * @doc-param int dosage 剂数id + * @doc-param int consumption 用量id + * @doc-param int usage 用法id + * @doc-param int fufa_id 服法id + * @doc-param string remark 备注 + * @doc-param int is_deepfry 是否浓煎0否1是 + */ + public function actionChangeGranular() + { + $request=\Yii::$app->request; + $param = $request->post(); + if (!$param['recipe_id']) throw new Exception('药方id不能为空'); + + $this->requestValidate($param,[ + ['store_id', 'required'], + ['deployment', 'required'], + ['dosage', 'required'], + ['consumption', 'required'], + ['gm_id', 'required'], + ]); + $store_id = $param['store_id']; + + $recipe = GranularRepice::find()->where(['id' => $param['recipe_id']])->one(); + if (!$recipe) throw new Exception('药方不存在'); + + $ids = explode(',', $param['cm_id']); + + $price = 0; + $medicine = GranularMedicine::find()->where(['in', 'id', $ids])->all(); + foreach ($medicine as $value){ + $drug = DrugStoreDrug::find()->alias('dsd')->where(['dsd.drug_id' => $value['drug_id']])->joinWith(['store s' => function ($q) use ($store_id){ + $q->andWhere(['s.id' => $store_id]); + }])->asArray()->one(); + if(!$drug){ + throw new Exception('药品库存数据错误'); + } + $drugNumber = $value['number'] * $param['dosage']; + if($drug['stock'] < $drugNumber){ + throw new Exception($value['name'].'库存数量不足'); + } + $price+=$drugNumber * $value['price']; + } + + $encode = Json::encode($medicine); + + $recipe->content = $encode; + $recipe->deployment = $param['deployment']; + $recipe->dosage = $param['dosage']; + $recipe->consumption = $param['consumption']; + $recipe->is_deepfry = $param['is_deepfry']?0:1; + $recipe->volume = $param['volume']??0; + $recipe->gm_id = $param['gm_id']; + $recipe->total_price = $price; + $recipe->saveOrFail(); + + return [$param['recipe_id']]; + + } + + /** + * @doc-name 删除西药药方 + * @doc-param int recipe_id 药方id + * @doc-param int prescription_id 处方id + */ + public function actionDelWest() + { + try { + $request=\Yii::$app->request; + + $recipe_id = $request->post('recipe_id'); + if (!$recipe_id) throw new Exception('药方id不能为空'); + + $transaction = \Yii::$app->db->beginTransaction(); + $recipe = WestRepice::find()->where(['id' => $recipe_id])->one(); + if (!$recipe) throw new Exception('药方不存在'); + + $recipe->delete(); + + $transaction->commit(); + } catch (\Exception $exception) { + $transaction->rollBack(); + return $exception; + } + } + +} \ No newline at end of file diff --git a/service/modules/v1/controllers/RegisterController.php b/service/modules/v1/controllers/RegisterController.php new file mode 100644 index 0000000..deef2fa --- /dev/null +++ b/service/modules/v1/controllers/RegisterController.php @@ -0,0 +1,203 @@ +alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + ])->andWhere(['between', 'created_at', $beginToday, $endToday])->sum('price'); + + $beginThismonth = mktime(0, 0, 0, date('m'), 1, date('Y')); + $endThismonth = mktime(23, 59, 59, date('m'), date('t'), date('Y')); + $current_month = Register::find()->alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + ])->andWhere(['between', 'created_at', $beginThismonth, $endThismonth])->sum('price'); + $total_price = Register::find()->alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + ])->sum('price'); + return [ + 'current_month' => $current_month??0, + 'current_day' => $current_day??0, + 'total_price' => $total_price??0 + ]; + } + + /** + * @doc-name 挂号人数统计 + * @doc-return int current_month 当月挂号人数 + * @doc-return int current_day 当天挂号人数 + */ + public function actionRegisterNumber() + { + $beginThismonth = mktime(0, 0, 0, date('m'), 1, date('Y')); + $endThismonth = mktime(23, 59, 59, date('m'), date('t'), date('Y')); + + $current_month = Register::find()->alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + ])->andWhere(['between', 'created_at', $beginThismonth, $endThismonth])->count(); + + $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y')); + $endToday=mktime(0,0,0,date('m'),date('d')+1,date('Y'))-1; + + $current_day= Register::find()->alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + ])->andWhere(['between', 'created_at', $beginToday, $endToday])->count(); + return [ + 'current_month' => $current_month, + 'current_day' => $current_day + ]; + } + + /** + * @doc-name 挂号列表(或到店接诊或挂号患者接口) + * @doc-param string order_no 挂号单号 / optional + * @doc-param string name 姓名 / optional + * @doc-param string start_time 起始时间 / optional + * @doc-param string end_time 终止时间 / optional + * @doc-param int status 状态:1已支付待接诊2接诊中3已结束4已取消5待评价6已评价7已拒诊 / optional + * @doc-return mixed @List{id-int-挂号id,is_case-string-是否有病历0无1有,user_patient_id-int-患者id,store-string-门店,depart-string-科室,order_number-int-挂号序号,price-float-挂号金额,patient-string-患者,idcard-string-身份证,mobile-string-手机号,status-int-状态1待接诊2接诊中3已结束4已取消5待评价6已评价7已拒诊,is_pay-int-是否支付0否1是,created_at-string-挂号时间,sex-int-性别0未知1男2女,order_no-string-订单单号} 挂号信息 + * @doc-return mixed @Pagination{total-int-总数据,totalPage-int-总页数,pageSize-int-每页多少条} 分页信息 + */ + public function actionList() + { + $post = \Yii::$app->request->post(); + $Register = Register::find()->alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + 'r.store_id' => \Yii::$app->store + ])->all(); + if (!$Register) throw new Exception('没有任何挂号'); + + $query = Register::find()->alias('r')->where([ + 'r.service_user_id' => \Yii::$app->user->id, + 'r.is_delete' => 0, + 'r.is_pay' => 1, + 'r.is_cancel' => 0, + 'r.store_id' => \Yii::$app->store + ])->with(['store', 'depart', 'patient'])->orderBy(['id'=>SORT_DESC]); + + if (!empty($post['order_no'])){ + $query->andWhere(['order_no'=>$post['order_no']]); + } + + if (!empty($post['name'])){ + $name=$post['name']; + $query->joinWith(['patient' => function ($p) use ($name) { + $p->alias('p'); + $p->andWhere(['like', 'p.name', $name]); + }]); + } + + if (!empty($post['start_time']) && !empty($post['end_time']) ){ + $query->andWhere(['between','r.created_at',strtotime($post['start_time']),strtotime($post['end_time'])]); + } + + if (!empty($post['status'])) { + switch ($post['status']) { + case RegisterEnum::WAIT: + $query->andWhere(['status' => RegisterEnum::WAIT]); + break; + case RegisterEnum::ACCEPTING: + $query->andWhere(['status' => RegisterEnum::ACCEPTING]); + break; + case RegisterEnum::OVER: + $query->andWhere(['in','status', [RegisterEnum::OVER, RegisterEnum::REFUSE]]); + break; + case RegisterEnum::CANCEL: + $query->andWhere(['status' => RegisterEnum::CANCEL]); + break; + case RegisterEnum::UNCOMMENT: + $query->andWhere(['status' => RegisterEnum::UNCOMMENT]); + break; + case RegisterEnum::CONMENTED: + $query->andWhere(['status' => RegisterEnum::CONMENTED]); + break; + case RegisterEnum::REFUSE: + $query->andWhere(['status' => RegisterEnum::REFUSE]); + break; + default: + throw new Exception('参数错误'); + } + } + + $this->field = [ + Register::class => [ + 'id','doctor_mobile'=>'doctor.mobile', + 'is_case'=>function($m){ + $UserPatientCase= UserPatientCase::find()->where(['register_id'=>$m->id])->one(); + if ($UserPatientCase){ + return 1; + } + return 0; + }, + 'user_patient_id','order_no', + 'store' => 'store.name', + 'depart' => 'depart.name', + 'order_number', 'price', + 'patient' => 'patient.name', + 'avatar' => 'patient.avatar', + 'idcard' => 'patient.id_card', + 'mobile' => 'patient.mobile', + 'status', 'is_pay', 'created_at', + 'age' => function ($m) { + return FuncHelper::getAgeFromIdNo($m->patient->id_card); + }, + 'sex'=>'patient.sex' + ] + ]; + return $this->create($query, $post); + } + + /** + * @doc-name 挂号导出 + */ + public function actionInventory() + { + $headlist=['就诊人id','诊所id','订单号','挂号序号','挂号金额','是否支付','拒诊原因']; + $Name='导出挂号'; + $class=new Register(); + (new ExportService())->export($headlist,$Name,$class); + + } + + +} \ No newline at end of file diff --git a/service/modules/v1/controllers/StoreAcceptController.php b/service/modules/v1/controllers/StoreAcceptController.php new file mode 100644 index 0000000..0215236 --- /dev/null +++ b/service/modules/v1/controllers/StoreAcceptController.php @@ -0,0 +1,265 @@ +request->post(); + $this->requestValidate($post,[ + [['patient_id','register_id'],'required'] + ]); + $register=Register::find()->where([ + 'id'=>$post['register_id'], + 'service_user_id'=>\Yii::$app->user->id, + 'user_patient_id'=>$post['patient_id'], + 'is_pay'=>1, + 'is_cancel'=>0, + 'is_delete'=>0 + ])->with(['patient','healthInquery']) + ->with(['depart'=>function($d){ + $d->select('name'); + }]) + ->with(['doctor'=>function($d){ + $d->select('name'); + }]) + ->with(['store'=>function($s){ + $s->select('name'); + }]) + ->asArray()->one(); + if (!$register) throw new Exception('挂号不存在'); + $prescription = Prescription::find()->select('id,prescription_no')->where(['register_id' => $register['id']])->all(); + $register['prescription'] = $prescription; + return $register; + } + + /** + * @doc-name 患者详情 + * @doc-param int patient_id 患者id + * @doc-return mixed @Info{@UserPatient{*,@UserPatientCase{*},@UserPatientHealthInquiry{*}}} 基本信息 + * @doc-return mixed @Register{*,@UserPatientCase{*}} 挂号列表 + * @doc-return mixed @Prescription{*} 处方列表 + */ + public function actionPatientInfo() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['patient_id','required'] + ]); + $info=UserPatient::find()->where([ + 'id'=>$post['patient_id'], + 'is_delete'=>0 + ])->with(['case','health'])->asArray()->one(); + + if (!$info){ + throw new Exception('患者不存在'); + } + $register=Register::find()->where([ + 'service_user_id'=>\Yii::$app->user->id, + 'user_patient_id'=>$post['patient_id'], + 'is_delete'=>0, + 'is_pay'=>1, + 'is_cancel'=>0 + ])->andWhere([ + 'like','order_no',$post['order_no']??'', + ])->with(['case'])->asArray()->all(); + Prescription::find()->where([ + 'su_id'=>\Yii::$app->user->id, + 'up_id'=>$post['patient_id'], + 'is_pay'=>1, + 'cancel_status'=>0 + ])->andWhere([ + 'like','prescription_no',$post['prescription_no']??'', + ])->all(); + + return [ + 'info'=>$info, +// 'Register'=>$register, +// 'Prescription'=>$Prescription, + ]; + + } + /** + * @doc-name 接诊/拒诊 + * @doc-param int register_id 挂号id + * @doc-param int status 1接诊2拒绝 + * @doc-param json refuse_reason 拒诊原因["咨询不对症","患者病情复杂"] / optional + */ + public function actionAcceptOrRefuse() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + [['register_id','status'],'required'] + ]); + + $register=Register::find()->where([ + 'id'=>$post['register_id'], + 'service_user_id'=>\Yii::$app->user->id, + 'is_pay'=>1, + 'is_cancel'=>0, + 'is_delete'=>0, + ])->andWhere(['status'=>[RegisterEnum::WAIT]])->one(); + + if (!$register) throw new Exception('挂号不存在'); + + $UserPatient = UserPatient::find()->where([ + 'user_id' => $register->user_id, + 'id' =>$register->user_patient_id + ])->one(); + if (!$UserPatient) throw new Exception('就诊人不存在'); + + if ($post['status']==1){ + + $transaction=\Yii::$app->db->beginTransaction(); + try { + //医生患者表(接诊后添加,已存在不新增) + $isDoctorPatient = DoctorPatient::find()->where([ + 'user_id' => $register->user_id, + 'su_id' => \Yii::$app->user->id, + 'up_id' => $register->user_patient_id + ])->one(); + + if(!$isDoctorPatient){ + $DoctorPatient=new DoctorPatient(); + $DoctorPatient->user_id=$register->user_id; + $DoctorPatient->su_id=\Yii::$app->user->id; + $DoctorPatient->up_id=$register->user_patient_id; + $DoctorPatient->avatar=$UserPatient->avatar; + $DoctorPatient->name=$UserPatient->name; + $DoctorPatient->id_card=$UserPatient->id_card; + $DoctorPatient->sex=$UserPatient->sex; + $DoctorPatient->mobile=$UserPatient->mobile; + $DoctorPatient->saveOrFail(); + } + //接诊 + $register->status=RegisterEnum::ACCEPTING; + $register->created_at=strtotime( $register->created_at); + $register->updated_at=time(); + $register->saveOrFail(); + + $transaction->commit(); + + //挂号接诊订阅消息通知 + \Yii::$app->queue->push(new RegisterAccept([ + 'orderId' => $register->id, + ])); + + //挂号已接诊分账结算 + \Yii::$app->queue->push(new RegisterAcceptJob([ + 'orderId' => $register->id, + ])); + + return ['已接诊']; + }catch (Exception $e){ + $transaction->rollBack(); + throw new $e; + } + }else{ + if(!$post['refuse_reason']) throw new Exception('拒诊原因不能为空'); + $t=\Yii::$app->db->beginTransaction(); + try { + $register->status=RegisterEnum::REFUSE; + $register->refuse_reason=$post['refuse_reason']; + $register->created_at=strtotime( $register->created_at); + $register->updated_at=time(); + $register->saveOrFail(); + + //发送拒诊通知 + $systemNotice = new SystemNotice(); + $systemNotice->content = '由于'.$post['refuse_reason'].',医生已拒绝接诊!'; + $systemNotice->base_type = 3;//处方通知 + $systemNotice->scene_type = 1; + $systemNotice->user_id = $register->user_id; + $systemNotice->notice_at = date('Y-m-d H:i:s',time()); + $systemNotice->saveOrFail(); + + //退款 + $form=new RegisterRefundForm(); + $form->refund($post['register_id']); + + $t->commit(); + return ['已拒诊']; + }catch (\Exception $e){ + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + } + + /** + * @doc-name 问诊结束 + * @doc-param int register_id 挂号id + */ + public function actionRegisterOver() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + [['register_id'],'required'] + ]); + + $register = Register::find()->select('status')->where([ + 'id' => $post['register_id'], + 'service_user_id' => \Yii::$app->user->id, + 'is_pay' => 1, + 'is_cancel' => 0, + 'is_delete' => 0, + ])->andWhere(['status'=>[RegisterEnum::ACCEPTING]])->one(); + + if (!$register) throw new Exception('挂号不存在'); + Register::updateAll(['status' => RegisterEnum::OVER],['id' => $post['register_id']]); + + //发送问诊结束通知 + $systemNotice = new SystemNotice(); + $systemNotice->content = '问诊已结束,祝您早日康复!'; + $systemNotice->base_type = 3;//问诊结束通知 + $systemNotice->scene_type = 1; + $systemNotice->user_id = $register->user_id; + $systemNotice->notice_at = date('Y-m-d H:i:s',time()); + $systemNotice->saveOrFail(); + + return ['已结束']; + } + + + /** + * @doc-name 拒诊原因列表 + */ + public function actionRefuseList() + { + $data=[ + ['key'=>0,'value'=>'咨询不对症'], + ['key'=>1,'value'=>'患者缺少诊疗资料'], + ['key'=>2,'value'=>'患者病情复杂'], + ]; + return $data; + } + +} \ No newline at end of file diff --git a/service/modules/v1/controllers/StoreController.php b/service/modules/v1/controllers/StoreController.php new file mode 100644 index 0000000..e5f0ff3 --- /dev/null +++ b/service/modules/v1/controllers/StoreController.php @@ -0,0 +1,194 @@ +request->post('keyword'); + $query = Store::find()->where(['is_delete'=> 0])->orderBy(['id'=>SORT_DESC]); + //搜索 + if ($keyword) { + $query->andWhere([ + 'or', + ['like', 'name', $keyword], + ['like', 'shouzimu', $keyword] + ]); + } + + $list = $query->all(); + if (!$list) throw new Exception('没搜到任何诊所'); + return $list; + } + + + /** + * @doc-name 医生所属门店列表 + * @doc-author hyl + * @doc-param string search 搜索 / optional + * @doc-return mixed @Store{*} 门店信息 + */ + public function actionStoreList() + { + + $post= \Yii::$app->request->post(); + $search=$post['search']; + $su_id = DoctorInfo::find()->select('su_id')->where([ + 'su_id' => \Yii::$app->user->identity->getId() + ])->column(); + $all_store = StoreDoctor::find()->select('store_id')->where([ + 'su_id' => $su_id + ])->column(); + + $store = Store::find()->where(['in', 'id', $all_store])->all(); + + if (!$store) throw new Exception('您还不属于任何门店'); + $query=Store::find()->where(['in', 'id', $all_store])->orderBy(['id'=>SORT_DESC]); + //搜索门店 + if ($search){ + $query->andWhere(['like','name',$search])->all(); + } + + + $this->field=[ + Store::class=>[ + 'id','name' + ] + ]; + return $this->create($query,$post); + } + + /** + * @doc-name 医生当前门店 + * @doc-author hyl + * @doc-param int doctor_id 医生id + * @doc-return mixed @StoreDoctor{*,@Store{*}} 门店信息 + */ + public function actionCurrentStore() + { + $post=\Yii::$app->request->post(); + $this->requestValidate($post,[ + ['doctor_id','required'] + ]); + + $store=StoreDoctor::find()->where([ + 'su_id'=>$post['doctor_id'], + 'is_online'=>1 + ])->with('store')->asArray()->one(); + + if (!$store) throw new Exception('没有当前门店'); + + return $store; + } + + + /** + * @doc-name 职称列表 + * @doc-author hyl + * @doc-param int type 1医生2药师 + * @doc-return mixed @DoctorTitle{*} 职称信息 + */ + public function actionTitleList() + { + $get=\Yii::$app->request->get(); + $this->requestValidate($get,[ + ['type','required'] + ]); + return DoctorTitle::find()->where(['type'=>$get['type']])->all(); + } + + /** + * @doc-name 科室列表 + * @doc-author hyl + * @doc-param int store_id 门店id + * @doc-param string search 搜索内容 / optional + * @doc-return mixed @Data{id-int-门店id,name-string-门店,position-string-位置,position-string-位置,contact-string-联系人,start_time-int-开始营业时间,end_time-int-结束营业时间,@Departments{name-string-科室,pid-int-父级id,level-int-level,@Child{name-string-科室,pid-int-父级id,level-int-level}}} 信息 + */ + public function actionDepartList() + { + $post=\Yii::$app->request->post(); + + $this->requestValidate($post,[ + ['store_id','required'] + ]); + $store_id=$post['store_id']; + $search= $post['search']; + + $Store=Store::find()->where(['id'=>$store_id])->one(); + + if (!$Store){ + throw new Exception('门店不存在'); + } + + $query=Store::find()->alias('s')->where(['s.id'=>$store_id])->asArray()->one(); + $query['departments']=Department::find()->with(['child'])->asArray()->all(); + //搜索 + if ($search){ + $query=Store::find()->where(['id'=>$store_id])->with(['child'=>function($m)use($search){ + $m->andWhere(['like','name',$search]); + }])->asArray()->one(); + } + + return $query; + } + + /** + * @doc-name 门店切换 + * @doc-param int store 要切换的门店id + */ + public function actionStoreChange() + { + $post=\Yii::$app->request->post(); + + $this->requestValidate($post,[ + ['store','required'] + ]); + + $t=\Yii::$app->db->beginTransaction(); + try { + StoreDoctor::updateAll(['is_online'=>0],[ + 'and', + ['su_id'=>\Yii::$app->user->identity->getId()], + [ 'is_delete'=>0] + ]); + + $StoreDoctor=StoreDoctor::find()->where([ + 'su_id'=>\Yii::$app->user->identity->getId(), + 'store_id'=>$post['store'], + 'is_delete'=>0, + ])->one(); + if (!$StoreDoctor) + { + throw new Exception('您不属于该门店'); + } + $StoreDoctor->store_id=$post['store']; + $StoreDoctor->is_online=1; + $StoreDoctor->saveOrFail(); + + $t->commit(); + return ['切换成功']; + }catch (\Exception $exception){ + $t->rollBack(); + throw new Exception($exception->getMessage()); + } + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/SystemNoticeController.php b/service/modules/v1/controllers/SystemNoticeController.php new file mode 100644 index 0000000..48c4a6c --- /dev/null +++ b/service/modules/v1/controllers/SystemNoticeController.php @@ -0,0 +1,197 @@ +where([ + 'or', + [ + 'and', + ['store_id' => \Yii::$app->request->get()['store_id']], + ['scene_type' => 2], + ['user_id' => \Yii::$app->user->identity->id], + ['base_type' => 5], + ['read_status' => 0] + ], + [ + 'and', + ['scene_type' => 2], + ['base_type' => 99], + // ['user_id' => \Yii::$app->user->identity->id], + ['read_status' => 0] + ] + ])->select('notice_at')->orderBy('notice_at DESC')->asArray()->all(); + + $commentNotice = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 2, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 6, + 'read_status' => 0 + ])->select('notice_at')->orderBy('notice_at DESC')->asArray()->all(); + $patientNotice = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 2, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 2, + 'read_status' => 0 + ])->select('notice_at')->orderBy('notice_at DESC')->asArray()->all(); + $onlinePrescriptionNotice = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 2, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 8, + 'read_status' => 0 + ])->select('notice_at')->orderBy('notice_at DESC')->asArray()->all(); + + $data = []; + if ($systemNotice) { + $data['system'] = [ + 'num' => count($systemNotice), + 'time' => $systemNotice[0]['notice_at'] + ]; + } + if ($commentNotice) { + $data['comment'] = [ + 'num' => count($commentNotice), + 'time' => $commentNotice[0]['notice_at'] + ]; + } + if ($patientNotice) { + $data['patient'] = [ + 'num' => count($patientNotice), + 'time' => $patientNotice[0]['notice_at'] + ]; + } + + if ($onlinePrescriptionNotice) { + $data['online_prescription'] = [ + 'num' => count($onlinePrescriptionNotice), + 'time' => $onlinePrescriptionNotice[0]['notice_at'] + ]; + } + + return $data; + } + + + public function actionSystem() + { + $query = SystemNotice::find()->where([ + 'or', + [ + 'and', + ['store_id' => \Yii::$app->request->get()['store_id']], + ['scene_type' => 2], + ['user_id' => \Yii::$app->user->identity->id], + ['base_type' => 5], + ], + [ + 'and', + ['scene_type' => 2], + // ['user_id' => \Yii::$app->user->identity->id], + ['base_type' => 99] + ] + ])->select('id,content,data,url,url_type,read_status,base_type,notice_at')->orderBy('notice_at DESC'); + return $this->create($query, \Yii::$app->request->get()); + } + + public function actionOnlinePrescription() + { + $query = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 2, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 8, + 'is_delete' => 0 + ])->select('id,content,data,read_status,base_type,notice_at')->orderBy('notice_at DESC'); + return $this->create($query, \Yii::$app->request->get()); + } + + public function actionRotation() + { + $noticeId = \Yii::$app->request->post('notice_id'); + if (!$noticeId) { + throw new Exception('消息id不能为空'); + } + SystemNotice::updateAll(['is_delete' => 1], ['id' => $noticeId]); + return ['success']; + } + + public function actionComment() + { + $query = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 2, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 6 + ])->select('id,content,data,url,url_type,read_status,base_type,notice_at')->orderBy('notice_at DESC'); + return $this->create($query, \Yii::$app->request->get()); + } + + public function actionPatient() + { + $query = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 2, + 'user_id' => \Yii::$app->user->identity->id, + 'base_type' => 2, + ])->select('id,content,data,url,url_type,read_status,base_type,notice_at')->orderBy('notice_at DESC'); + return $this->create($query, \Yii::$app->request->get()); + } + + public function actionRead() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['type', 'required'], + ['store_id', 'required'] + ]); + $type = $post['type']; + switch ($type) { + case 'system': + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=2 AND (base_type=1 or base_type=5) AND user_id=' . \Yii::$app->user->identity->id . ' AND store_id=' . $post['store_id'])->execute(); + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=2 AND base_type=99 AND user_id=' . \Yii::$app->user->identity->id)->execute(); + break; + case 'comment': + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=2 AND base_type=6 AND user_id=' . \Yii::$app->user->identity->id . ' AND store_id=' . $post['store_id'])->execute(); + break; + case 'patient': + \Yii::$app->db->createCommand()->update(SystemNotice::tableName(), ['read_status' => '1'], 'read_status=0 AND scene_type=2 AND base_type=2 AND user_id=' . \Yii::$app->user->identity->id . ' AND store_id=' . $post['store_id'])->execute(); + break; + + default: + throw new Exception('错误的type'); + break; + } + return ['success']; + } + + /** + * 医生历史消息(当日已读) + */ + public function actionHistory() + { + $start = strtotime(date('Y-m-d')); + $end = strtotime(date('Y-m-d', strtotime('+1 day'))); + $query = SystemNotice::find()->where([ + 'store_id' => \Yii::$app->request->get()['store_id'], + 'scene_type' => 2, + 'user_id' => \Yii::$app->user->identity->id, + 'read_status' => 1 + ])->andWhere([ + 'between', 'created_at', [$start, $end] + ])->select('id,content,data,url,url_type,read_status,base_type,notice_at')->orderBy('notice_at DESC'); + return $this->create($query, \Yii::$app->request->get()); + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/TagManageController.php b/service/modules/v1/controllers/TagManageController.php new file mode 100644 index 0000000..531aa7d --- /dev/null +++ b/service/modules/v1/controllers/TagManageController.php @@ -0,0 +1,200 @@ +request; + $param = $request->post(); + $this->requestValidate($param, [ + ['name', 'required'], + ['is_default', 'required'] + ]); + $tag = DoctorTagIll::find() + ->where(['su_id' => \Yii::$app->user->identity->id]) + ->andWhere(['name' => $param['name']]) + ->one(); + if ($tag) { + throw new Exception('你已经添加过该标签'); + } + \Yii::$app->db->createCommand()->insert('yii_doctor_tag_ill', [ + 'su_id' => \Yii::$app->user->identity->id, + 'name' => $param['name'], + 'is_default' => $param['is_default'], + 'created_at' => time(), + ])->execute(); + return ['添加成功']; + } + + /** + * @doc-name 删除疾病标签 + * @doc-param int id 标签id + */ + public function actionDelIllTag() + { + $id = \Yii::$app->request->post('id'); + if (!$id) throw new Exception('id不能为空'); + + $tag = DoctorTagIll::find() + ->where(['su_id' => \Yii::$app->user->identity->id]) + ->andWhere(['id' => $id]) + ->one(); + if (!$tag) { + throw new Exception('该标签不存在'); + } + $tag->delete(); + return ['删除成功']; + } + + /** + * @doc-name 查看所有标签 + */ + public function actionSeeIllTag() + { + $tags = DoctorTagIll::find() + ->where(['su_id' => \Yii::$app->user->identity->id]) + ->all(); + if (!$tags) { + throw new Exception('你还没有添加任何标签'); + } + return $tags; + } + + /** + * @doc-name 标签添加就诊人 + * @doc-param int up_ids 就诊人id数组 + * @doc-param int ti_id 标签id + */ + public function actionTagSavePatient() + { + $up_ids = explode(',', \Yii::$app->request->post('up_ids')); + $ti_id = \Yii::$app->request->post('ti_id'); + if (!$up_ids) throw new Exception('就诊人up_ids不能为空'); + if (!$ti_id) throw new Exception('ti_id不能为空'); + + $successCount = $errorCount = 0; + foreach ($up_ids as $up_id) { + $PatientIll = UserPatientIll::find() + ->where(['su_id' => \Yii::$app->user->identity->id, 'up_id' => $up_id, 'ti_id' => $ti_id]) + ->one(); + if (!$PatientIll) { + $successCount++; + \Yii::$app->db->createCommand()->insert('yii_user_patient_ill', [ + 'su_id' => \Yii::$app->user->identity->id, + 'up_id' => $up_id, + 'ti_id' => $ti_id, + 'created_at' => time(), + ])->execute(); + } else { + $errorCount++; + } + } + + return ["成功添加标签{$successCount}个,重复跳过{$errorCount}个"]; + } + + /** + * @doc-name 从标签中删除就诊人 + * @doc-param int up_id 就诊人id + * @doc-param int ti_id 标签id + */ + public function actionTagDelPatient() + { + $up_id = \Yii::$app->request->post('up_id'); + $ti_id = \Yii::$app->request->post('ti_id'); + if (!$up_id) throw new Exception('就诊人up_id不能为空'); + if (!$ti_id) throw new Exception('ti_id不能为空'); + + $PatientIll = UserPatientIll::find() + ->where(['su_id' => \Yii::$app->user->identity->id, 'up_id' => $up_id, 'ti_id' => $ti_id]) + ->one(); + if (!$PatientIll) { + throw new Exception('标签没有该就诊人'); + } + + $PatientIll->delete(); + return []; + } + + /** + * @doc-name 查看就诊人所属标签 + * @doc-param int up_id 就诊人id + */ + public function actionSeeTagPatient() + { + $up_id = \Yii::$app->request->post('up_id'); + if (!$up_id) throw new Exception('就诊人up_id不能为空'); + + $ti_ids = UserPatientIll::find() + ->select(['ti_id']) + ->where(['su_id' => \Yii::$app->user->identity->id, 'up_id' => $up_id]) + ->column(); + + $tags = DoctorTagIll::find() + ->where(['in', 'id', $ti_ids]) + ->andWhere(['su_id' => \Yii::$app->user->identity->id]) + ->all(); + if (!$tags) { + throw new Exception('没有添加标签'); + } + return $tags; + } + + /** + * @doc-name 患者管理中心-列表 + * @doc-param int dti_id 疾病id + * @doc-return mixed @Tags{name-string-名称} 左侧标签列表 + * @doc-return mixed @SelectTag{name-string-名称} 选中的标签 + * @doc-return mixed @Tag_Patient{up_id-int-就诊人id,@UserPatient{avatar-string-头像,name-string-姓名,sex-int-性别0默认1男2女,id_card-string-身份证}} 患者列表 + */ + public function actionList() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + ['dti_id', 'required'] + ]); + + $AllTags=DoctorTagIll::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->id + ]) + ->select('id,name')->all(); + $SelectedTag=DoctorTagIll::find() + ->where([ + 'id' => $post['dti_id'], + 'su_id' => \Yii::$app->user->identity->id + ]) + ->one(); + $Tag_Patient = UserPatientIll::find() + ->where([ + 'su_id' => \Yii::$app->user->identity->id, + 'ti_id' => $post['dti_id'] + ]) + ->with(['userPatient']) + ->asArray()->all(); + foreach ($Tag_Patient as &$patient) { + $patient['userPatient']['age'] = FuncHelper::getAgeFromIdNo($patient['userPatient']['id_card']); + } + return [ + 'Tags' => $AllTags, + 'SelectTag' => $SelectedTag, + 'Tag_Patient' => $Tag_Patient + ]; + } +} \ No newline at end of file diff --git a/service/modules/v1/controllers/UserController.php b/service/modules/v1/controllers/UserController.php new file mode 100644 index 0000000..fad853d --- /dev/null +++ b/service/modules/v1/controllers/UserController.php @@ -0,0 +1,288 @@ +request->post(); + $this->requestValidate($post, [ + ['status', 'required'] + ]); + $form = new LoginForm(); + $form->attributes = $post; + + return $form->userlogin(); + } + + /** + * @doc-name 选择角色 + * @doc-param int role 角色1医生2药师3导医4客服 + * @doc-param string mobile 手机号 / optional + */ + public function actionRole() + { + $post = \Yii::$app->request->post(); + $this->requestValidate($post, [ + [['role', 'mobile'], 'required'] + ]); + $ServiceUser = \common\models\ServiceUser::findOne(['mobile' => $post['mobile']]); + if (!$ServiceUser) { + throw new Exception('您还没有任何账号'); + } + ServiceUser::updateAll(['role' => $post['role']], [ + 'mobile' => $post['mobile'], + 'is_delete' => 0 + ]); + return []; + } + + /** + * @doc-name 忘记密码重置密码 + * @doc-param string mobile 手机号 + * @doc-param string password_new 新密码 + * @doc-param string mobile_code 验证码 + */ + public function actionResetPassword() + { + $form = new ResetPasswordForm(); + $form->attributes = \Yii::$app->request->post(); + return $form->resetPasswordAndLogin(); + } + + /** + * @doc-name 忘记密码发送短信 + * @doc-param string mobile 手机号 + */ + public function actionMobileSend() + { + $form = new MobileForm; + $form->attributes = \Yii::$app->request->post(); + return $form->sendCode(); + } + + /** + * @doc-name 用户退出 + */ + public function actionLogout() + { + $token = ServiceUser::$token; + ServiceUserToken::disableToken($token); + return []; + } + + /** + * @doc-name 用户信息 + * @doc-return mixed ServiceUser{*} 用户信息 + */ + public function actionInfo() + { + return \Yii::$app->user->identity; + } + + /** + * @doc-name 协议 + * @doc-param int end 1用户端2服务端 + */ + public function actionAgreement() + { + $form = new AgreementForm(); + $form->attributes = \Yii::$app->request->post(); + return $form->getAgreement(); + } + + /** + * @doc-name 修改密码 + * @doc-param string password_old 旧密码 + * @doc-param string password_new 新密码 + */ + public function actionUpdatePassword() + { + $form = new UpdatePasswordForm(); + $form->attributes = \Yii::$app->request->post(); + return $form->updatePassword(); + } + + /** + * @doc-name 手机号登录发送短信 + * @doc-param string mobile 手机号码 + * @doc-return string smsCode 验证码 + */ + public function actionSendCode() + { + $code = (string)mt_rand(100000, 999999); + $post = \Yii::$app->request->post(); + + $this->requestValidate($post, [ + ['mobile', 'required'] + ]); + $message = [ + 'content' => '您的验证码为:" ' . $code . ' ",请勿泄露与他人', + 'template' => 'SMS_274460204', + 'data' => [ + 'code' => $code + ] + ]; + $cache = \Yii::$app->cache; + $cache->set( 'login_sms_code_'.$post['mobile'], $code, 600); + $cache->set( 'login_sms_time_'.$post['mobile'], time(), 600); + $response = (new SmsService())->sendCaptcha($post['mobile'], $code); + return [$result]; + } + + public function actionToken() + { + return [ + 'token' => (new WeappService())->getAccessToken() + ]; + } + + /** + * @doc-name 修改医生信息 + * @doc-param string avatar 头像 '' optional + * @doc-param int title_id 职称(1主任医师,2副主任医师,3主治医师,4执业医师) 0 optional + * @doc-param int yard_id 医院院区 0 optional + * @doc-param int depart_id 科室 0 optional + * @doc-param string good_at 擅长 '' optional + * @doc-param string intro 简介 '' optional + * @doc-param string work_avator 资格证书 '' optional + * @return array + */ + public function actionUpdateUserInfo() + { + $attributes = \Yii::$app->request->post(); + + //$model = new DoctorInfo(); + $model = DoctorInfo::find()->where([ + 'su_id' => \Yii::$app->user->identity->id, + ])->one(); + + #修改头像 + if(isset($attributes['avatar']) && !empty($attributes['avatar'])){ + $model->avatar = $attributes['avatar']; + } + #修改职称 + if(isset($attributes['title_id']) && !empty($attributes['title_id'])){ + $model->title_id = $attributes['title_id']; + } + #修改医院院区 + if(isset($attributes['yard_id']) && !empty($attributes['yard_id'])){ + $yard = HospitalYard::find()->where([ + 'id' => $attributes['yard_id'], + ])->one(); + $model->hospital_id = $yard->hospital_id; + $model->yard_id = $attributes['yard_id']; + } + #修改科室 + if(isset($attributes['depart_id']) && !empty($attributes['depart_id'])){ + $model->depart_id = $attributes['depart_id']; + } + #修改擅长 + if(isset($attributes['good_at']) && !empty($attributes['good_at'])){ + $model->good_at = $attributes['good_at']; + } + #修改简介 + if(isset($attributes['intro']) && !empty($attributes['intro'])){ + $model->intro = $attributes['intro']; + } + + $model->saveOrFail(); + + } + + public function actionCheckIdcard(){ + $post = \Yii::$app->request->post(); + + $this->requestValidate($post, [ + [['name', 'idcard'], 'required'] + ]); + $response = (new Client(['http_errors' => false]))->post("https://eid.shumaidata.com/eid/check", [ + 'headers' => ['Authorization' => "APPCODE f98bba3251714c759f5bd29d00e1c46e"], + 'query' => [ + 'idcard' => $post['idcard'], + 'name' => $post['name'] + ], + ]); + $result = json_decode($response->getBody(), true); + if (!($result['code'] == 0 && $result['result']['res'] == 1)) { + throw new Exception('姓名和身份证号码不符'); + } + return ['success']; + } + + /** + * @doc-name 审核失败后重新注册账号 + * @doc-param int id 用户ID + */ + public function actionFailRegister() + { + $get = \Yii::$app->request->get(); + $this->requestValidate($get, [ + ['id', 'required'] + ]); + $ServiceUser=ServiceUser::findOne(['id'=>$get['id'],'status'=>3]); + if (!$ServiceUser) throw new Exception('账号不存在或账号非审核失败状态'); + $t=\Yii::$app->db->beginTransaction(); + try { + $ServiceUser->status=3; + $ServiceUser->reason=null; + $ServiceUser->saveOrFail(); + +// if ($ServiceUser->role==UserRoleEnum::DOCTOR){ +// $DoctorInfo=DoctorInfo::find()->where(['su_id'=>$get['id']])->one(); +// if ($DoctorInfo){ +// $DoctorInfo->is_delete=1; +// $DoctorInfo->saveOrFail(); +// } +// } +// +// if ($ServiceUser->role==UserRoleEnum::DRUG){ +// $PharmacistrInfo=PharmacistrInfo::find()->where(['su_id'=>$get['id']])->one(); +// if ($PharmacistrInfo){ +// $PharmacistrInfo->delete(); +// } +// } + + $t->commit(); + }catch (\Exception $e){ + $t->rollBack(); + throw new Exception($e->getMessage()); + } + } + +} diff --git a/service/tests/_bootstrap.php b/service/tests/_bootstrap.php new file mode 100644 index 0000000..637ce14 --- /dev/null +++ b/service/tests/_bootstrap.php @@ -0,0 +1,10 @@ + 'erau', + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', + // password_0 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', + 'created_at' => '1392559490', + 'updated_at' => '1392559490', + 'email' => 'sfriesen@jenkins.info', + ], + [ + 'username' => 'test.test', + 'auth_key' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT', + // Test1234 + 'password_hash' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT', + 'email' => 'test@mail.com', + 'status' => '9', + 'created_at' => '1548675330', + 'updated_at' => '1548675330', + 'verification_token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330', + ], +]; diff --git a/service/tests/_data/user.php b/service/tests/_data/user.php new file mode 100644 index 0000000..0b94332 --- /dev/null +++ b/service/tests/_data/user.php @@ -0,0 +1,45 @@ + 'okirlin', + 'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv', + 'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi', + 'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(), + 'created_at' => '1391885313', + 'updated_at' => '1391885313', + 'email' => 'brady.renner@rutherford.com', + ], + [ + 'username' => 'troy.becker', + 'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp', + 'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2', + 'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(), + 'created_at' => '1391885313', + 'updated_at' => '1391885313', + 'email' => 'nicolas.dianna@hotmail.com', + 'status' => '0', + ], + [ + 'username' => 'test.test', + 'auth_key' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT', + //Test1234 + 'password_hash' => '$2y$13$d17z0w/wKC4LFwtzBcmx6up4jErQuandJqhzKGKczfWuiEhLBtQBK', + 'email' => 'test@mail.com', + 'status' => '9', + 'created_at' => '1548675330', + 'updated_at' => '1548675330', + 'verification_token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330', + ], + [ + 'username' => 'test2.test', + 'auth_key' => '4XXdVqi3rDpa_a6JH6zqVreFxUPcUPvJ', + //Test1234 + 'password_hash' => '$2y$13$d17z0w/wKC4LFwtzBcmx6up4jErQuandJqhzKGKczfWuiEhLBtQBK', + 'email' => 'test2@mail.com', + 'status' => '10', + 'created_at' => '1548675330', + 'updated_at' => '1548675330', + 'verification_token' => 'already_used_token_1548675330', + ], +]; diff --git a/service/tests/_output/.gitignore b/service/tests/_output/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/service/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/service/tests/_support/.gitignore b/service/tests/_support/.gitignore new file mode 100644 index 0000000..36e264c --- /dev/null +++ b/service/tests/_support/.gitignore @@ -0,0 +1 @@ +_generated diff --git a/service/tests/_support/FunctionalTester.php b/service/tests/_support/FunctionalTester.php new file mode 100644 index 0000000..ec5dd1d --- /dev/null +++ b/service/tests/_support/FunctionalTester.php @@ -0,0 +1,34 @@ +see($message, '.invalid-feedback'); + } + + public function dontSeeValidationError($message) + { + $this->dontSee($message, '.invalid-feedback'); + } +} diff --git a/service/tests/_support/UnitTester.php b/service/tests/_support/UnitTester.php new file mode 100644 index 0000000..025be5f --- /dev/null +++ b/service/tests/_support/UnitTester.php @@ -0,0 +1,26 @@ +amOnRoute(Url::toRoute('/site/index')); + $I->see('My Application'); + + $I->seeLink('About'); + $I->click('About'); + $I->wait(2); // wait for page to be opened + + $I->see('This is the About page.'); + } +} diff --git a/service/tests/acceptance/_bootstrap.php b/service/tests/acceptance/_bootstrap.php new file mode 100644 index 0000000..47716f0 --- /dev/null +++ b/service/tests/acceptance/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cept + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/service/tests/functional.suite.yml b/service/tests/functional.suite.yml new file mode 100644 index 0000000..90047d7 --- /dev/null +++ b/service/tests/functional.suite.yml @@ -0,0 +1,7 @@ +suite_namespace: app\tests\functional +actor: FunctionalTester +modules: + enabled: + - Filesystem + - Yii2 + - Asserts diff --git a/service/tests/functional/AboutCest.php b/service/tests/functional/AboutCest.php new file mode 100644 index 0000000..2aebfc6 --- /dev/null +++ b/service/tests/functional/AboutCest.php @@ -0,0 +1,14 @@ +amOnRoute('site/about'); + $I->see('About', 'h1'); + } +} diff --git a/service/tests/functional/ContactCest.php b/service/tests/functional/ContactCest.php new file mode 100644 index 0000000..39357f8 --- /dev/null +++ b/service/tests/functional/ContactCest.php @@ -0,0 +1,60 @@ +amOnRoute('site/contact'); + } + + public function checkContact(FunctionalTester $I) + { + $I->see('Contact', 'h1'); + } + + public function checkContactSubmitNoData(FunctionalTester $I) + { + $I->submitForm('#contact-form', []); + $I->see('Contact', 'h1'); + $I->seeValidationError('Name cannot be blank'); + $I->seeValidationError('Email cannot be blank'); + $I->seeValidationError('Subject cannot be blank'); + $I->seeValidationError('Body cannot be blank'); + $I->seeValidationError('The verification code is incorrect'); + } + + public function checkContactSubmitNotCorrectEmail(FunctionalTester $I) + { + $I->submitForm('#contact-form', [ + 'ContactForm[name]' => 'tester', + 'ContactForm[email]' => 'tester.email', + 'ContactForm[subject]' => 'test subject', + 'ContactForm[body]' => 'test content', + 'ContactForm[verifyCode]' => 'testme', + ]); + $I->seeValidationError('Email is not a valid email address.'); + $I->dontSeeValidationError('Name cannot be blank'); + $I->dontSeeValidationError('Subject cannot be blank'); + $I->dontSeeValidationError('Body cannot be blank'); + $I->dontSeeValidationError('The verification code is incorrect'); + } + + public function checkContactSubmitCorrectData(FunctionalTester $I) + { + $I->submitForm('#contact-form', [ + 'ContactForm[name]' => 'tester', + 'ContactForm[email]' => 'tester@example.com', + 'ContactForm[subject]' => 'test subject', + 'ContactForm[body]' => 'test content', + 'ContactForm[verifyCode]' => 'testme', + ]); + $I->seeEmailIsSent(); + $I->see('Thank you for contacting us. We will respond to you as soon as possible.'); + } +} diff --git a/service/tests/functional/HomeCest.php b/service/tests/functional/HomeCest.php new file mode 100644 index 0000000..604515b --- /dev/null +++ b/service/tests/functional/HomeCest.php @@ -0,0 +1,17 @@ +amOnRoute(\Yii::$app->homeUrl); + $I->see('My Application'); + $I->seeLink('About'); + $I->click('About'); + $I->see('This is the About page.'); + } +} \ No newline at end of file diff --git a/service/tests/functional/LoginCest.php b/service/tests/functional/LoginCest.php new file mode 100644 index 0000000..1170a36 --- /dev/null +++ b/service/tests/functional/LoginCest.php @@ -0,0 +1,66 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'login_data.php', + ], + ]; + } + + public function _before(FunctionalTester $I) + { + $I->amOnRoute('site/register'); + } + + protected function formParams($login, $password) + { + return [ + 'LoginForm[username]' => $login, + 'LoginForm[password]' => $password, + ]; + } + + public function checkEmpty(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('', '')); + $I->seeValidationError('Username cannot be blank.'); + $I->seeValidationError('Password cannot be blank.'); + } + + public function checkWrongPassword(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('admin', 'wrong')); + $I->seeValidationError('Incorrect username or password.'); + } + + public function checkInactiveAccount(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('test.test', 'Test1234')); + $I->seeValidationError('Incorrect username or password'); + } + + public function checkValidLogin(FunctionalTester $I) + { + $I->submitForm('#register-form', $this->formParams('erau', 'password_0')); + $I->see('Logout (erau)', 'form button[type=submit]'); + $I->dontSeeLink('register'); + $I->dontSeeLink('Signup'); + } +} diff --git a/service/tests/functional/ResendVerificationEmailCest.php b/service/tests/functional/ResendVerificationEmailCest.php new file mode 100644 index 0000000..9cb7284 --- /dev/null +++ b/service/tests/functional/ResendVerificationEmailCest.php @@ -0,0 +1,83 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php', + ], + ]; + } + + public function _before(FunctionalTester $I) + { + $I->amOnRoute('/site/resend-verification-email'); + } + + protected function formParams($email) + { + return [ + 'ResendVerificationEmailForm[email]' => $email + ]; + } + + public function checkPage(FunctionalTester $I) + { + $I->see('Resend verification email', 'h1'); + $I->see('Please fill out your email. A verification email will be sent there.'); + } + + public function checkEmptyField(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('')); + $I->seeValidationError('Email cannot be blank.'); + } + + public function checkWrongEmailFormat(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('abcd.com')); + $I->seeValidationError('Email is not a valid email address.'); + } + + public function checkWrongEmail(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('wrong@email.com')); + $I->seeValidationError('There is no user with this email address.'); + } + + public function checkAlreadyVerifiedEmail(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('test2@mail.com')); + $I->seeValidationError('There is no user with this email address.'); + } + + public function checkSendSuccessfully(FunctionalTester $I) + { + $I->submitForm($this->formId, $this->formParams('test@mail.com')); + $I->canSeeEmailIsSent(); + $I->seeRecord('common\models\User', [ + 'email' => 'test@mail.com', + 'username' => 'test.test', + 'status' => \common\models\User::STATUS_INACTIVE + ]); + $I->see('Check your email for further instructions.'); + } +} diff --git a/service/tests/functional/SignupCest.php b/service/tests/functional/SignupCest.php new file mode 100644 index 0000000..325e7e8 --- /dev/null +++ b/service/tests/functional/SignupCest.php @@ -0,0 +1,59 @@ +amOnRoute('site/signup'); + } + + public function signupWithEmptyFields(FunctionalTester $I) + { + $I->see('Signup', 'h1'); + $I->see('Please fill out the following fields to signup:'); + $I->submitForm($this->formId, []); + $I->seeValidationError('Username cannot be blank.'); + $I->seeValidationError('Email cannot be blank.'); + $I->seeValidationError('Password cannot be blank.'); + + } + + public function signupWithWrongEmail(FunctionalTester $I) + { + $I->submitForm( + $this->formId, [ + 'SignupForm[username]' => 'tester', + 'SignupForm[email]' => 'ttttt', + 'SignupForm[password]' => 'tester_password', + ] + ); + $I->dontSee('Username cannot be blank.', '.invalid-feedback'); + $I->dontSee('Password cannot be blank.', '.invalid-feedback'); + $I->see('Email is not a valid email address.', '.invalid-feedback'); + } + + public function signupSuccessfully(FunctionalTester $I) + { + $I->submitForm($this->formId, [ + 'SignupForm[username]' => 'tester', + 'SignupForm[email]' => 'tester.email@example.com', + 'SignupForm[password]' => 'tester_password', + ]); + + $I->seeRecord('common\models\User', [ + 'username' => 'tester', + 'email' => 'tester.email@example.com', + 'status' => \common\models\User::STATUS_INACTIVE + ]); + + $I->seeEmailIsSent(); + $I->see('Thank you for registration. Please check your inbox for verification email.'); + } +} diff --git a/service/tests/functional/VerifyEmailCest.php b/service/tests/functional/VerifyEmailCest.php new file mode 100644 index 0000000..1a9fca9 --- /dev/null +++ b/service/tests/functional/VerifyEmailCest.php @@ -0,0 +1,68 @@ + [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php', + ], + ]; + } + + public function checkEmptyToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => '']); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Verify email token cannot be blank.'); + } + + public function checkInvalidToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => 'wrong_token']); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Wrong verify email token.'); + } + + public function checkNoToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email'); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Missing required parameters: token'); + } + + public function checkAlreadyActivatedToken(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => 'already_used_token_1548675330']); + $I->canSee('Bad Request', 'h1'); + $I->canSee('Wrong verify email token.'); + } + + public function checkSuccessVerification(FunctionalTester $I) + { + $I->amOnRoute('site/verify-email', ['token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330']); + $I->canSee('Your email has been confirmed!'); + $I->canSee('Congratulations!', 'h1'); + $I->see('Logout (test.test)', 'form button[type=submit]'); + + $I->seeRecord('common\models\User', [ + 'username' => 'test.test', + 'email' => 'test@mail.com', + 'status' => \common\models\User::STATUS_ACTIVE + ]); + } +} diff --git a/service/tests/functional/_bootstrap.php b/service/tests/functional/_bootstrap.php new file mode 100644 index 0000000..30ed54b --- /dev/null +++ b/service/tests/functional/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/service/tests/unit.suite.yml b/service/tests/unit.suite.yml new file mode 100644 index 0000000..285752b --- /dev/null +++ b/service/tests/unit.suite.yml @@ -0,0 +1,7 @@ +suite_namespace: app\tests\unit +actor: UnitTester +modules: + enabled: + - Yii2: + part: [orm, email, fixtures] + - Asserts diff --git a/service/tests/unit/_bootstrap.php b/service/tests/unit/_bootstrap.php new file mode 100644 index 0000000..e432ce5 --- /dev/null +++ b/service/tests/unit/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Tests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ diff --git a/service/tests/unit/models/ContactFormTest.php b/service/tests/unit/models/ContactFormTest.php new file mode 100644 index 0000000..112735f --- /dev/null +++ b/service/tests/unit/models/ContactFormTest.php @@ -0,0 +1,35 @@ +attributes = [ + 'name' => 'Tester', + 'email' => 'tester@example.com', + 'subject' => 'very important letter subject', + 'body' => 'body of current message', + ]; + + verify($model->sendEmail('admin@example.com'))->notEmpty(); + + // using Yii2 module actions to check email was sent + $this->tester->seeEmailIsSent(); + + /** @var MessageInterface $emailMessage */ + $emailMessage = $this->tester->grabLastSentEmail(); + verify($emailMessage)->instanceOf('yii\mail\MessageInterface'); + verify($emailMessage->getTo())->arrayHasKey('admin@example.com'); + verify($emailMessage->getFrom())->arrayHasKey('noreply@example.com'); + verify($emailMessage->getReplyTo())->arrayHasKey('tester@example.com'); + verify($emailMessage->getSubject())->equals('very important letter subject'); + verify($emailMessage->toString())->stringContainsString('body of current message'); + } +} diff --git a/service/tests/unit/models/PasswordResetRequestFormTest.php b/service/tests/unit/models/PasswordResetRequestFormTest.php new file mode 100644 index 0000000..ee6e536 --- /dev/null +++ b/service/tests/unit/models/PasswordResetRequestFormTest.php @@ -0,0 +1,59 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testSendMessageWithWrongEmailAddress() + { + $model = new PasswordResetRequestForm(); + $model->email = 'not-existing-email@example.com'; + verify($model->sendEmail())->false(); + } + + public function testNotSendEmailsToInactiveUser() + { + $user = $this->tester->grabFixture('user', 1); + $model = new PasswordResetRequestForm(); + $model->email = $user['email']; + verify($model->sendEmail())->false(); + } + + public function testSendEmailSuccessfully() + { + $userFixture = $this->tester->grabFixture('user', 0); + + $model = new PasswordResetRequestForm(); + $model->email = $userFixture['email']; + $user = User::findOne(['password_reset_token' => $userFixture['password_reset_token']]); + + verify($model->sendEmail())->notEmpty(); + verify($user->password_reset_token)->notEmpty(); + + $emailMessage = $this->tester->grabLastSentEmail(); + verify($emailMessage)->instanceOf('yii\mail\MessageInterface'); + verify($emailMessage->getTo())->arrayHasKey($model->email); + verify($emailMessage->getFrom())->arrayHasKey(Yii::$app->params['supportEmail']); + } +} diff --git a/service/tests/unit/models/ResendVerificationEmailFormTest.php b/service/tests/unit/models/ResendVerificationEmailFormTest.php new file mode 100644 index 0000000..ff75246 --- /dev/null +++ b/service/tests/unit/models/ResendVerificationEmailFormTest.php @@ -0,0 +1,85 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testWrongEmailAddress() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => 'aaa@bbb.cc' + ]; + + verify($model->validate())->false(); + verify($model->hasErrors())->true(); + verify($model->getFirstError('email'))->equals('There is no user with this email address.'); + } + + public function testEmptyEmailAddress() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => '' + ]; + + verify($model->validate())->false(); + verify($model->hasErrors())->true(); + verify($model->getFirstError('email'))->equals('Email cannot be blank.'); + } + + public function testResendToActiveUser() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => 'test2@mail.com' + ]; + + verify($model->validate())->false(); + verify($model->hasErrors())->true(); + verify($model->getFirstError('email'))->equals('There is no user with this email address.'); + } + + public function testSuccessfullyResend() + { + $model = new ResendVerificationEmailForm(); + $model->attributes = [ + 'email' => 'test@mail.com' + ]; + + verify($model->validate())->true(); + verify($model->hasErrors())->false(); + + verify($model->sendEmail())->true(); + $this->tester->seeEmailIsSent(); + + $mail = $this->tester->grabLastSentEmail(); + + verify($mail)->instanceOf('yii\mail\MessageInterface'); + verify($mail->getTo())->arrayHasKey('test@mail.com'); + verify($mail->getFrom())->arrayHasKey(\Yii::$app->params['supportEmail']); + verify($mail->getSubject())->equals('Account registration at ' . \Yii::$app->name); + verify($mail->toString())->stringContainsString('4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330'); + } +} diff --git a/service/tests/unit/models/ResetPasswordFormTest.php b/service/tests/unit/models/ResetPasswordFormTest.php new file mode 100644 index 0000000..54fc836 --- /dev/null +++ b/service/tests/unit/models/ResetPasswordFormTest.php @@ -0,0 +1,44 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ], + ]); + } + + public function testResetWrongToken() + { + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new ResetPasswordForm(''); + }); + + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new ResetPasswordForm('notexistingtoken_1391882543'); + }); + } + + public function testResetCorrectToken() + { + $user = $this->tester->grabFixture('user', 0); + $form = new ResetPasswordForm($user['password_reset_token']); + verify($form->resetPassword())->notEmpty(); + } + +} diff --git a/service/tests/unit/models/SignupFormTest.php b/service/tests/unit/models/SignupFormTest.php new file mode 100644 index 0000000..94dc617 --- /dev/null +++ b/service/tests/unit/models/SignupFormTest.php @@ -0,0 +1,72 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testCorrectSignup() + { + $model = new SignupForm([ + 'username' => 'some_username', + 'email' => 'some_email@example.com', + 'password' => 'some_password', + ]); + + $user = $model->signup(); + verify($user)->notEmpty(); + + /** @var \common\models\User $user */ + $user = $this->tester->grabRecord('common\models\User', [ + 'username' => 'some_username', + 'email' => 'some_email@example.com', + 'status' => \common\models\User::STATUS_INACTIVE + ]); + + $this->tester->seeEmailIsSent(); + + $mail = $this->tester->grabLastSentEmail(); + + verify($mail)->instanceOf('yii\mail\MessageInterface'); + verify($mail->getTo())->arrayHasKey('some_email@example.com'); + verify($mail->getFrom())->arrayHasKey(\Yii::$app->params['supportEmail']); + verify($mail->getSubject())->equals('Account registration at ' . \Yii::$app->name); + verify($mail->toString())->stringContainsString($user->verification_token); + } + + public function testNotCorrectSignup() + { + $model = new SignupForm([ + 'username' => 'troy.becker', + 'email' => 'nicolas.dianna@hotmail.com', + 'password' => 'some_password', + ]); + + verify($model->signup())->empty(); + verify($model->getErrors('username'))->notEmpty(); + verify($model->getErrors('email'))->notEmpty(); + + verify($model->getFirstError('username')) + ->equals('This username has already been taken.'); + verify($model->getFirstError('email')) + ->equals('This email address has already been taken.'); + } +} diff --git a/service/tests/unit/models/VerifyEmailFormTest.php b/service/tests/unit/models/VerifyEmailFormTest.php new file mode 100644 index 0000000..1f56e15 --- /dev/null +++ b/service/tests/unit/models/VerifyEmailFormTest.php @@ -0,0 +1,55 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::class, + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testVerifyWrongToken() + { + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new VerifyEmailForm(''); + }); + + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new VerifyEmailForm('notexistingtoken_1391882543'); + }); + } + + public function testAlreadyActivatedToken() + { + $this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() { + new VerifyEmailForm('already_used_token_1548675330'); + }); + } + + public function testVerifyCorrectToken() + { + $model = new VerifyEmailForm('4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330'); + $user = $model->verifyEmail(); + verify($user)->instanceOf('common\models\User'); + + verify($user->username)->equals('test.test'); + verify($user->email)->equals('test@mail.com'); + verify($user->status)->equals(\common\models\User::STATUS_ACTIVE); + verify($user->validatePassword('Test1234'))->true(); + } +} diff --git a/vagrant/config/.gitignore b/vagrant/config/.gitignore new file mode 100644 index 0000000..0685a56 --- /dev/null +++ b/vagrant/config/.gitignore @@ -0,0 +1,2 @@ +# local configuration +vagrant-local.yml \ No newline at end of file diff --git a/vagrant/config/vagrant-local.example.yml b/vagrant/config/vagrant-local.example.yml new file mode 100644 index 0000000..7b36400 --- /dev/null +++ b/vagrant/config/vagrant-local.example.yml @@ -0,0 +1,22 @@ +# Your personal GitHub token +github_token: +# Read more: https://github.com/blog/1509-personal-api-tokens +# You can generate it here: https://github.com/settings/tokens + +# Guest OS timezone +timezone: Europe/London + +# Are we need check box updates for every 'vagrant up'? +box_check_update: false + +# Virtual machine name +machine_name: y2aa + +# Virtual machine IP +ip: 192.168.83.137 + +# Virtual machine CPU cores number +cpus: 1 + +# Virtual machine RAM +memory: 1024 diff --git a/vagrant/nginx/app.conf b/vagrant/nginx/app.conf new file mode 100644 index 0000000..ab286c0 --- /dev/null +++ b/vagrant/nginx/app.conf @@ -0,0 +1,77 @@ +server { + charset utf-8; + client_max_body_size 128M; + sendfile off; + + listen 80; ## listen for ipv4 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 + + server_name y2aa-app.test; + root /app/web/app/; + index index.php; + + access_log /app/vagrant/nginx/log/frontend-access.log; + error_log /app/vagrant/nginx/log/frontend-error.log; + + location / { + # Redirect everything that isn't a real file to index.php + try_files $uri $uri/ /index.php$is_args$args; + } + + # uncomment to avoid processing of calls to non-existing static files by Yii + #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { + # try_files $uri =404; + #} + #error_page 404 /404.html; + + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + #fastcgi_pass 127.0.0.1:9000; + fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; + try_files $uri =404; + } + + location ~ /\.(ht|svn|git) { + deny all; + } +} + +server { + charset utf-8; + client_max_body_size 128M; + sendfile off; + + listen 80; ## listen for ipv4 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 + + server_name y2aa-admin.test; + root /app/web/admin/; + index index.php; + + access_log /app/vagrant/nginx/log/backend-access.log; + error_log /app/vagrant/nginx/log/backend-error.log; + + location / { + # Redirect everything that isn't a real file to index.php + try_files $uri $uri/ /index.php$is_args$args; + } + + # uncomment to avoid processing of calls to non-existing static files by Yii + #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { + # try_files $uri =404; + #} + #error_page 404 /404.html; + + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + #fastcgi_pass 127.0.0.1:9000; + fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; + try_files $uri =404; + } + + location ~ /\.(ht|svn|git) { + deny all; + } +} diff --git a/vagrant/nginx/log/.gitignore b/vagrant/nginx/log/.gitignore new file mode 100644 index 0000000..38f1cec --- /dev/null +++ b/vagrant/nginx/log/.gitignore @@ -0,0 +1,5 @@ +# nginx logs +admin-access.log +admin-error.log +app-access.log +app-error.log \ No newline at end of file diff --git a/vagrant/provision/always-as-root.sh b/vagrant/provision/always-as-root.sh new file mode 100644 index 0000000..cca9cfb --- /dev/null +++ b/vagrant/provision/always-as-root.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +source /app/vagrant/provision/common.sh + +#== Provision script == + +info "Provision-script user: `whoami`" + +info "Restart web-stack" +service php7.4-fpm restart +service nginx restart +service mysql restart \ No newline at end of file diff --git a/vagrant/provision/common.sh b/vagrant/provision/common.sh new file mode 100644 index 0000000..ab5e1e0 --- /dev/null +++ b/vagrant/provision/common.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +#== Bash helpers == + +function info { + echo " " + echo "--> $1" + echo " " +} diff --git a/vagrant/provision/once-as-root.sh b/vagrant/provision/once-as-root.sh new file mode 100644 index 0000000..4542a43 --- /dev/null +++ b/vagrant/provision/once-as-root.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +source /app/vagrant/provision/common.sh + +#== Import script args == + +timezone=$(echo "$1") +readonly IP=$2 + +#== Provision script == + +info "Provision-script user: `whoami`" + +export DEBIAN_FRONTEND=noninteractive + +info "Configure timezone" +timedatectl set-timezone ${timezone} --no-ask-password + +info "AWK initial replacement work" +awk -v ip=$IP -f /app/vagrant/provision/provision.awk /app/environments/dev/*end/config/main-local.php + +info "Prepare root password for MySQL" +debconf-set-selections <<< "mysql-community-server mysql-community-server/root-pass password \"''\"" +debconf-set-selections <<< "mysql-community-server mysql-community-server/re-root-pass password \"''\"" +echo "Done!" + +info "Update OS software" +apt-get update +apt-get upgrade -y + +info "Add ppa:ondrej/php" +apt-get install -y python-software-properties +apt-get update && apt-get upgrade -y +add-apt-repository -y ppa:ondrej/php + +info "Install additional software" +apt-get install -y php7.4-curl php7.4-cli php7.4-intl php7.4-mysqlnd php7.4-gd php7.4-fpm php7.4-mbstring php7.4-xml unzip nginx mysql-server-5.7 php7.4-xdebug + +info "Configure MySQL" +sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/mysql.conf.d/mysqld.cnf +mysql -uroot <<< "CREATE USER 'root'@'%' IDENTIFIED BY ''" +mysql -uroot <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'" +mysql -uroot <<< "DROP USER 'root'@'localhost'" +mysql -uroot <<< "FLUSH PRIVILEGES" +echo "Done!" + +info "Configure PHP-FPM" +sed -i 's/user = www-data/user = vagrant/g' /etc/php/7.4/fpm/pool.d/www.conf +sed -i 's/group = www-data/group = vagrant/g' /etc/php/7.4/fpm/pool.d/www.conf +sed -i 's/owner = www-data/owner = vagrant/g' /etc/php/7.4/fpm/pool.d/www.conf +cat << EOF > /etc/php/7.4/mods-available/xdebug.ini +zend_extension=xdebug.so +xdebug.remote_enable=1 +xdebug.remote_connect_back=1 +xdebug.remote_port=9000 +xdebug.remote_autostart=1 +EOF +echo "Done!" + +info "Configure NGINX" +sed -i 's/user www-data/user vagrant/g' /etc/nginx/nginx.conf +echo "Done!" + +info "Enabling site configuration" +ln -s /app/vagrant/nginx/app.conf /etc/nginx/sites-enabled/app.conf +echo "Done!" + +info "Initailize databases for MySQL" +mysql -uroot <<< "CREATE DATABASE yii2advanced" +mysql -uroot <<< "CREATE DATABASE yii2advanced_test" +echo "Done!" + +info "Install composer" +curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ No newline at end of file diff --git a/vagrant/provision/once-as-vagrant.sh b/vagrant/provision/once-as-vagrant.sh new file mode 100644 index 0000000..ffaa898 --- /dev/null +++ b/vagrant/provision/once-as-vagrant.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +source /app/vagrant/provision/common.sh + +#== Import script args == + +github_token=$(echo "$1") + +#== Provision script == + +info "Provision-script user: `whoami`" + +info "Configure composer" +composer config --global github-oauth.github.com ${github_token} +echo "Done!" + +info "Install project dependencies" +cd /app +composer --no-progress --prefer-dist install + +info "Init project" +./init --env=Development --overwrite=y + +info "Apply migrations" +./yii migrate --interactive=0 +./yii_test migrate --interactive=0 + +info "Create bash-alias 'app' for vagrant user" +echo 'alias app="cd /app"' | tee /home/vagrant/.bash_aliases + +info "Enabling colorized prompt for guest console" +sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/" /home/vagrant/.bashrc diff --git a/vagrant/provision/provision.awk b/vagrant/provision/provision.awk new file mode 100644 index 0000000..65e9bde --- /dev/null +++ b/vagrant/provision/provision.awk @@ -0,0 +1,70 @@ +### +# Modifying Yii2's files for initialize Vagrant VM +# +# @author HA3IK +# @version 1.0.0 + +BEGIN { + print "AWK BEGINs its work:" + IGNORECASE = 1 + # Correct IP - wildcard last octet + match(ip, /(([0-9]+\.)+)/, arr) + ip = arr[1] "*" +} +BEGINFILE { + msg = "- Work with: " FILENAME + # Define array index for the file + switch (FILENAME) { + case /environments\/dev\/(back|front)end\/config\/main\-local\.php$/: + isFile["IsMainLocConf"] = 1 + msg = msg " - allow VM IP for Gii and debug toolbar" + break + } + # Print the final message + print msg +} +# BODY +{ + # IF environments/dev/(back|front)end/config/main-local.php + if (isFile["IsMainLocConf"]) { + # IF the line[s] after yii\(debug|gii)\Module + if (FNR == nextLine["nubmer"]) { + # Prepare for next line + ++nextLine["nubmer"] + # IF line has "allowedIPs" + if (index($0, "allowedIPs")) { + # IF our IP is not there + if (!index($0, ip)) { + # Add it + match($0, /([^\]]+)(.+)/, arr) + $0 = sprintf("%s, '%s'%s", arr[1], ip, arr[2]) + } + # Delete next line + delete nextLine + # IF "allowedIPs" are not set - search for the end of an array structure + } else if ($0 ~ /\];$/) { + # Rewrite line + $0 = nextLine["indent"] "'allowedIPs' => ['127.0.0.1', '::1', '" ip "'],\n" $0 + delete nextLine + } + # IF line is done + if (!length(nextLine)) { + printf " Line %d: Allowed IP: %s\n", FNR, ip + } + # Search for yii\(debug|gii)\Module + } else if (match($0, /^(\s+).+yii\\(debug|gii)\\Module/, arr)) { + # Save next line and indent + nextLine["nubmer"] = FNR + 1 + nextLine["indent"] = arr[1] + } + # Rewrite the file + print $0 > FILENAME + } +} +ENDFILE { + delete isFile + close(FILENAME) +} +END { + print "AWK ENDs its work." +} diff --git a/web/assets/.gitignore b/web/assets/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/web/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/web/css/site.css b/web/css/site.css new file mode 100644 index 0000000..4a65ca7 --- /dev/null +++ b/web/css/site.css @@ -0,0 +1,103 @@ +main > .container, main > .container-fluid +{ + padding: 70px 15px 20px; +} + +.footer { + background-color: #f5f5f5; + font-size: .9em; + height: 60px; +} + +.footer > .container, .footer > .container-fluid { + padding-right: 15px; + padding-left: 15px; +} + +.not-set { + color: #c55; + font-style: italic; +} + +/* add sorting icons to gridview sort links */ +a.asc:after, a.desc:after { + content: ''; + left: 3px; + display: inline-block; + width: 0; + height: 0; + border: solid 5px transparent; + margin: 4px 4px 2px 4px; + background: transparent; +} + +a.asc:after { + border-bottom: solid 7px #212529; + border-top-width: 0; +} + +a.desc:after { + border-top: solid 7px #212529; + border-bottom-width: 0; +} + +.grid-view th, +.grid-view td:last-child { + white-space: nowrap; +} + +.grid-view .filters input, +.grid-view .filters select { + min-width: 50px; +} + +.hint-block { + display: block; + margin-top: 5px; + color: #999; +} + +.error-summary { + color: #a94442; + background: #fdf7f7; + border-left: 3px solid #eed3d7; + padding: 10px 20px; + margin: 0 0 15px 0; +} + +/* align the logout "link" (button in form) of the navbar */ +.navbar form > button.logout { + padding-top: 7px; + color: rgba(255, 255, 255, 0.5); +} + +@media(max-width:767px) { + .navbar form > button.logout { + display:block; + text-align: left; + width: 100%; + padding: 10px 0; + } +} + +.navbar form > button.logout:focus, +.navbar form > button.logout:hover { + text-decoration: none; + color: rgba(255, 255, 255, 0.75); +} + +.navbar form > button.logout:focus { + outline: none; +} + +/* style breadcrumb widget as in previous bootstrap versions */ +.breadcrumb { + background-color: var(--bs-gray-200); + border-radius: .25rem; + padding: .75rem 1rem; +} + +.breadcrumb-item > a +{ + text-decoration: none; +} \ No newline at end of file diff --git a/web/favicon.ico b/web/favicon.ico new file mode 100644 index 0000000..580ed73 Binary files /dev/null and b/web/favicon.ico differ diff --git a/web/index-test.php b/web/index-test.php new file mode 100644 index 0000000..19bdc29 --- /dev/null +++ b/web/index-test.php @@ -0,0 +1,28 @@ +run(); diff --git a/web/index.php b/web/index.php new file mode 100644 index 0000000..3f190f9 --- /dev/null +++ b/web/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/web/member/assets/.gitignore b/web/member/assets/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/web/member/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/web/member/index-test.php b/web/member/index-test.php new file mode 100644 index 0000000..c435941 --- /dev/null +++ b/web/member/index-test.php @@ -0,0 +1,29 @@ +run(); diff --git a/web/member/index.php b/web/member/index.php new file mode 100644 index 0000000..3ae0678 --- /dev/null +++ b/web/member/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/web/member/robots.txt b/web/member/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/web/member/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/web/platform/assets/.gitignore b/web/platform/assets/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/web/platform/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/web/platform/index.php b/web/platform/index.php new file mode 100644 index 0000000..94941dc --- /dev/null +++ b/web/platform/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/web/platform/robots.txt b/web/platform/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/web/platform/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/web/robots.txt b/web/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/web/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/web/service/assets/.gitignore b/web/service/assets/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/web/service/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/web/service/index-test.php b/web/service/index-test.php new file mode 100644 index 0000000..aee31f8 --- /dev/null +++ b/web/service/index-test.php @@ -0,0 +1,29 @@ +run(); diff --git a/web/service/index.php b/web/service/index.php new file mode 100644 index 0000000..72671e6 --- /dev/null +++ b/web/service/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/web/service/robots.txt b/web/service/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/web/service/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/web/websoct.html b/web/websoct.html new file mode 100644 index 0000000..e58c298 --- /dev/null +++ b/web/websoct.html @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/yii b/yii new file mode 100644 index 0000000..00e939d --- /dev/null +++ b/yii @@ -0,0 +1,24 @@ +#!/usr/bin/env php +run(); +exit($exitCode); diff --git a/yii.bat b/yii.bat new file mode 100644 index 0000000..3a68942 --- /dev/null +++ b/yii.bat @@ -0,0 +1,15 @@ +@echo off + +rem ------------------------------------------------------------- +rem Yii command line bootstrap script for Windows. +rem ------------------------------------------------------------- + +@setlocal + +set YII_PATH=%~dp0 + +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe + +"%PHP_COMMAND%" "%YII_PATH%yii" %* + +@endlocal