From 8f5879725688aa31cc9ce4332bbdc61711b95dd7 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Fri, 13 May 2022 15:25:29 +0800 Subject: [PATCH] no message --- app/Http/Controllers/Api/SystemController.php | 45 +++++ app/Http/Controllers/Api/UsersController.php | 50 ++++++ app/Models/UmengAlias.php | 165 ++++++++++++++++++ app/Tasks/PushUmengMsg.php | 38 ++++ app/Tasks/WebSocketDialogMsgTask.php | 14 ++ composer.json | 1 + composer.lock | 68 +++++++- ..._05_13_065531_create_umeng_alias_table.php | 34 ++++ electron/build.js | 2 +- resources/assets/js/App.vue | 16 +- resources/assets/js/app.js | 3 + .../setting/components/SystemAppPush.vue | 92 ++++++++++ .../setting/components/SystemEmailSetting.vue | 6 +- .../assets/js/pages/manage/setting/index.vue | 7 +- .../assets/js/pages/manage/setting/system.vue | 26 ++- resources/assets/sass/pages/page-setting.scss | 6 +- 16 files changed, 560 insertions(+), 13 deletions(-) create mode 100644 app/Models/UmengAlias.php create mode 100644 app/Tasks/PushUmengMsg.php create mode 100644 database/migrations/2022_05_13_065531_create_umeng_alias_table.php create mode 100644 resources/assets/js/pages/manage/setting/components/SystemAppPush.vue diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index 2d5f7fb8e..b7bcf7d7e 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -153,6 +153,51 @@ class SystemController extends AbstractController return Base::retSuccess('success', $setting ?: json_decode('{}')); } + /** + * @api {get} api/system/setting/apppush 02. 获取APP推送设置、保存APP推送设置(限管理员) + * + * @apiVersion 1.0.0 + * @apiGroup system + * @apiName setting__apppush + * + * @apiParam {String} type + * - get: 获取(默认) + * - save: 保存设置(参数:['push', 'ios_key', 'ios_secret', 'android_key', 'android_secret']) + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function setting__apppush() + { + User::auth('admin'); + // + $type = trim(Request::input('type')); + if ($type == 'save') { + if (env("SYSTEM_SETTING") == 'disabled') { + return Base::retError('当前环境禁止修改'); + } + $all = Request::input(); + foreach ($all as $key => $value) { + if (!in_array($key, [ + 'push', + 'ios_key', + 'ios_secret', + 'android_key', + 'android_secret' + ])) { + unset($all[$key]); + } + } + $setting = Base::setting('appPushSetting', Base::newTrim($all)); + } else { + $setting = Base::setting('appPushSetting'); + } + // + $setting['push'] = $setting['push'] ?: 'close'; + // + return Base::retSuccess('success', $setting ?: json_decode('{}')); + } + /** * @api {get} api/system/demo 03. 获取演示帐号 * diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index d472f3f77..d8c7d07b6 100755 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api; use App\Models\AbstractModel; +use App\Models\UmengAlias; use App\Models\User; use App\Models\UserEmailVerification; use App\Models\UserTransfer; @@ -684,4 +685,53 @@ class UsersController extends AbstractController return Base::retSuccess('绑定邮箱成功'); } + + /** + * @api {get} api/users/umeng/alias 13. 设置友盟别名 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup users + * @apiName umeng__alias + * + * @apiParam {String} alias 别名 + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据(同"获取我的信息"接口) + */ + public function umeng__alias() + { + $data = Request::input(); + // 表单验证 + Base::validator($data, [ + 'alias.required' => '别名不能为空', + 'alias.between:2,20' => '别名的长度在2-20个字符', + ]); + // + $agent = strtolower(Request::server('HTTP_USER_AGENT')); + if (str_contains($agent, 'android')) { + $platform = 'android'; + } elseif (str_contains($agent, 'iphone') || str_contains($agent, 'ipad')) { + $platform = 'ios'; + } else { + return Base::retError('设备类型错误'); + } + // + $user = User::auth(); + $inArray = [ + 'userid' => $user->userid, + 'alias' => $data['alias'], + 'platform' => $platform, + ]; + if (UmengAlias::where($inArray)->exists()) { + return Base::retSuccess('别名已存在'); + } + $row = UmengAlias::createInstance($inArray); + if ($row->save()) { + return Base::retSuccess('添加成功'); + } else { + return Base::retError('添加错误'); + } + } } diff --git a/app/Models/UmengAlias.php b/app/Models/UmengAlias.php new file mode 100644 index 000000000..64ee61408 --- /dev/null +++ b/app/Models/UmengAlias.php @@ -0,0 +1,165 @@ + $setting['ios_key'], + 'appMasterSecret' => $setting['ios_secret'], + 'production_mode' => true, + ]; + } + if ($setting['android_key']) { + $config['Android'] = [ + 'appKey' => $setting['android_key'], + 'appMasterSecret' => $setting['android_secret'], + 'production_mode' => true, + ]; + } + return $config; + } + + /** + * 推送消息 + * @param string $alias + * @param string $platform + * @param array $array [title, subtitle, body, description, extra, seconds, badge] + * @return array|false + */ + public static function pushMsgToAlias($alias, $platform, $array) + { + $config = self::getPushConfig(); + if ($config === false) { + return false; + } + // + $title = $array['title'] ?: ''; // 标题 + $subtitle = $array['subtitle'] ?: ''; // 副标题(iOS) + $body = $array['body'] ?: ''; // 通知内容 + $description = $array['description'] ?: 'no description'; // 描述 + $extra = is_array($array['extra']) ? $array['extra'] : []; // 额外参数 + $seconds = intval($array['seconds']) ?: 86400; // 有效时间(单位:秒) + $badge = intval($array['badge']) ?: 0; // 角标数(iOS) + // + switch ($platform) { + case 'ios': + if (!isset($config['iOS'])) { + return false; + } + $ios = new IOS($config); + return $ios->send([ + 'description' => $description, + 'payload' => array_merge([ + 'aps' => [ + 'alert' => [ + 'title' => $title, + 'subtitle' => $subtitle, + 'body' => $body, + ], + 'sound' => 'default', + 'badge' => $badge, + ], + ], $extra), + 'type' => 'customizedcast', + 'alias_type' => 'userid', + 'alias' => $alias, + 'policy' => [ + 'expire_time' => Carbon::now()->addSeconds($seconds)->toDateTimeString(), + ], + ]); + + case 'android': + if (!isset($config['Android'])) { + return false; + } + $android = new Android($config); + return $android->send([ + 'description' => $description, + 'payload' => array_merge([ + 'display_type' => 'notification', + 'body' => [ + 'ticker' => $title, + 'text' => $body, + 'title' => $title, + 'after_open' => 'go_app', + 'play_sound' => true, + ], + ], $extra), + 'type' => 'customizedcast', + 'alias_type' => 'userid', + 'alias' => $alias, + 'policy' => [ + 'expire_time' => Carbon::now()->addSeconds($seconds)->toDateTimeString(), + ], + ]); + + default: + return false; + } + } + + /** + * 推送给指定会员 + * @param array|int $userid + * @param array $array + * @return void + */ + public static function pushMsgToUserid($userid, $array) + { + $builder = self::select(['id', 'platform', 'alias']); + if (is_array($userid)) { + $builder->whereIn('userid', $userid); + } elseif (Base::isNumber($userid)) { + $builder->whereUserid($userid); + } + $builder + ->orderByDesc('id') + ->chunkById(100, function ($rows) use ($array) { + $lists = $rows->groupBy('platform'); + foreach ($lists as $platform => $list) { + $alias = $list->pluck('alias')->implode(','); + self::pushMsgToAlias($alias, $platform, $array); + } + }); + } +} diff --git a/app/Tasks/PushUmengMsg.php b/app/Tasks/PushUmengMsg.php new file mode 100644 index 000000000..a8f04a393 --- /dev/null +++ b/app/Tasks/PushUmengMsg.php @@ -0,0 +1,38 @@ +userid = $userid; + $this->array = is_array($array) ? $array : []; + } + + public function start() + { + if (empty($this->userid) || empty($this->array)) { + return; + } + $setting = Base::setting('appPushSetting'); + if ($setting['push'] !== 'open') { + return; + } + UmengAlias::pushMsgToUserid($this->userid, $this->array); + } +} diff --git a/app/Tasks/WebSocketDialogMsgTask.php b/app/Tasks/WebSocketDialogMsgTask.php index 2dcc628fa..dc1853b61 100644 --- a/app/Tasks/WebSocketDialogMsgTask.php +++ b/app/Tasks/WebSocketDialogMsgTask.php @@ -8,6 +8,7 @@ use App\Models\User; use App\Models\WebSocketDialog; use App\Models\WebSocketDialogMsg; use App\Models\WebSocketDialogMsgRead; +use Hhxsv5\LaravelS\Swoole\Task\Task; use Request; @@ -80,6 +81,19 @@ class WebSocketDialogMsgTask extends AbstractTask ] ]); } + // umeng推送app + $msgTitle = User::userid2nickname($msg->userid); + if ($dialog->type == 'group') { + $msgTitle = "{$dialog->name} ($msgTitle)"; + } + $umengMsg = new PushUmengMsg(array_keys($array), [ + 'title' => $msgTitle, + 'body' => $msg->previewMsg(), + 'description' => "消息推送-ID:{$msg->id}", + 'seconds' => 3600, + 'badge' => 1, + ]); + Task::deliver($umengMsg); // 推送目标②:正在打开这个任务会话的会员 if ($dialog->type == 'group' && $dialog->group_type == 'task') { diff --git a/composer.json b/composer.json index 3dc3b9408..7f807d363 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "fruitcake/laravel-cors": "^2.0.4", "guanguans/notify": "^1.20", "guzzlehttp/guzzle": "^7.3.0", + "hedeqiang/umeng": "^2.1", "laravel/framework": "^v8.48.1", "laravel/tinker": "^v2.6.1", "maatwebsite/excel": "^3.1.31", diff --git a/composer.lock b/composer.lock index b4e15d7fa..4b2a15037 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ea9cf5820d67b47b3ade5df2398c7365", + "content-hash": "7cf09e78a30054fd005c1dac6a92ec6e", "packages": [ { "name": "brick/math", @@ -1207,6 +1207,72 @@ ], "time": "2021-10-06T17:43:30+00:00" }, + { + "name": "hedeqiang/umeng", + "version": "v2.1.3", + "source": { + "type": "git", + "url": "https://github.com/hedeqiang/UMeng-Push.git", + "reference": "6f48d7b8e43dbf88cf7cd22d0693e8cf5b44c118" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hedeqiang/UMeng-Push/zipball/6f48d7b8e43dbf88cf7cd22d0693e8cf5b44c118", + "reference": "6f48d7b8e43dbf88cf7cd22d0693e8cf5b44c118", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.3|^7.0", + "php": ">=7.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.19|^3.8" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Hedeqiang\\UMeng\\PushServiceProvider" + ] + }, + "hyperf": { + "config": "Hedeqiang\\UMeng\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Hedeqiang\\UMeng\\": "./src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "hedeqiang", + "email": "laravel_code@163.com" + }, + { + "name": "housemecn", + "email": "houseme@outlook.com" + } + ], + "description": "友盟推送", + "keywords": [ + "U-Push", + "php", + "sdk", + "umeng", + "友盟" + ], + "support": { + "issues": "https://github.com/hedeqiang/UMeng-Push/issues", + "source": "https://github.com/hedeqiang/UMeng-Push/tree/v2.1.3" + }, + "time": "2022-04-22T12:03:37+00:00" + }, { "name": "intervention/image", "version": "2.7.1", diff --git a/database/migrations/2022_05_13_065531_create_umeng_alias_table.php b/database/migrations/2022_05_13_065531_create_umeng_alias_table.php new file mode 100644 index 000000000..b59197b80 --- /dev/null +++ b/database/migrations/2022_05_13_065531_create_umeng_alias_table.php @@ -0,0 +1,34 @@ +bigIncrements('id'); + $table->bigInteger('userid')->nullable()->default(0)->comment('会员ID'); + $table->string('alias', 50)->nullable()->default('')->comment('别名'); + $table->string('platform', 50)->nullable()->default('')->comment('平台类型'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('umeng_alias'); + } +} diff --git a/electron/build.js b/electron/build.js index c85a798ad..f5297aaf8 100644 --- a/electron/build.js +++ b/electron/build.js @@ -132,7 +132,7 @@ function startBuild(data, publish) { econfig.build.directories.output = `dist/${data.id}/${data.platform}`; econfig.build.artifactName = utils.getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}"; econfig.build.nsis.artifactName = utils.getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}"; - if (!process.env.APPLEID || !process.env.APPLEIDPASS) { + if (!process.env.APPLEID || !process.env.APPLEIDPASS || publish !== true) { delete econfig.build.afterSign; } if (process.env.RELEASE_BODY) { diff --git a/resources/assets/js/App.vue b/resources/assets/js/App.vue index 9f56258c4..2ebadd575 100755 --- a/resources/assets/js/App.vue +++ b/resources/assets/js/App.vue @@ -62,7 +62,7 @@ export default { }, computed: { - ...mapState(['userId', 'cacheDrawerOverlay']), + ...mapState(['userId', 'userToken', 'cacheDrawerOverlay']), }, watch: { @@ -90,7 +90,19 @@ export default { userId: { handler() { - this.$store.dispatch("websocketConnection") + this.$store.dispatch("websocketConnection"); + // + if (this.$isEEUiApp) { + setTimeout(_ => { + const webview = requireModuleJs("webview"); + webview && webview.sendMessage({ + action: 'setUmengAlias', + userid: this.userId, + token: this.userToken, + url: $A.apiUrl('users/umeng/alias') + }); + }, 6000) + } }, immediate: true }, diff --git a/resources/assets/js/app.js b/resources/assets/js/app.js index c3eebdb7d..2f72c7935 100644 --- a/resources/assets/js/app.js +++ b/resources/assets/js/app.js @@ -108,6 +108,7 @@ Vue.prototype.$Electron = null; Vue.prototype.$Platform = "web"; Vue.prototype.$isMainElectron = false; Vue.prototype.$isSubElectron = false; +Vue.prototype.$isEEUiApp = isEEUiApp; if (isElectron) { Vue.prototype.$Electron = electron; Vue.prototype.$Platform = /macintosh|mac os x/i.test(navigator.userAgent) ? "mac" : "win"; @@ -139,6 +140,7 @@ $A.Electron = app.$Electron; $A.Platform = app.$Platform; $A.isMainElectron = app.$isMainElectron; $A.isSubElectron = app.$isSubElectron; +$A.isEEUiApp = app.$isEEUiApp; $A.execMainDispatch = (action, data) => { if ($A.isSubElectron) { $A.Electron.sendMessage('sendForwardMain', { @@ -147,3 +149,4 @@ $A.execMainDispatch = (action, data) => { }); } }; + diff --git a/resources/assets/js/pages/manage/setting/components/SystemAppPush.vue b/resources/assets/js/pages/manage/setting/components/SystemAppPush.vue new file mode 100644 index 000000000..937383ca6 --- /dev/null +++ b/resources/assets/js/pages/manage/setting/components/SystemAppPush.vue @@ -0,0 +1,92 @@ + + + diff --git a/resources/assets/js/pages/manage/setting/components/SystemEmailSetting.vue b/resources/assets/js/pages/manage/setting/components/SystemEmailSetting.vue index 8fb7fd680..29507defe 100644 --- a/resources/assets/js/pages/manage/setting/components/SystemEmailSetting.vue +++ b/resources/assets/js/pages/manage/setting/components/SystemEmailSetting.vue @@ -1,7 +1,7 @@ @@ -22,13 +25,34 @@ import SystemSetting from "./components/SystemSetting"; import SystemTaskPriority from "./components/SystemTaskPriority"; import SystemColumnTemplate from "./components/SystemColumnTemplate"; import SystemEmailSetting from "./components/SystemEmailSetting"; +import SystemAppPush from "./components/SystemAppPush"; export default { - components: {SystemColumnTemplate, SystemTaskPriority, SystemSetting, SystemEmailSetting}, + components: {SystemAppPush, SystemColumnTemplate, SystemTaskPriority, SystemSetting, SystemEmailSetting}, data() { return { tabAction: 'setting', + appPush: false, } }, + + mounted() { + if ([ + '127.0.0.1:2222', + 't.hitosea.com', + 'dootask.com', + 'www.dootask.com' + ].includes(this.getDomain($A.apiUrl('../')))) { + this.appPush = true; + } + }, + + methods: { + getDomain(weburl) { + let urlReg = /http(s)?:\/\/([^\/]+)/i; + let domain = (weburl + "").match(urlReg); + return ((domain != null && domain.length > 0) ? domain[2] : ""); + } + } } diff --git a/resources/assets/sass/pages/page-setting.scss b/resources/assets/sass/pages/page-setting.scss index 13db7b046..823f9ef46 100755 --- a/resources/assets/sass/pages/page-setting.scss +++ b/resources/assets/sass/pages/page-setting.scss @@ -209,7 +209,7 @@ .setting-footer { margin: 0 -32px; } - .email-setting-box { + .block-setting-box { position: relative; padding: 44px 24px 4px; margin: 24px 0 12px; @@ -247,7 +247,7 @@ } } - .email-setting-placeholder { + .block-setting-placeholder { height: 8px; } } @@ -267,6 +267,7 @@ @media (max-width: 768px) { .page-setting { .setting-head { + margin: 32px 32px 0; .setting-titbox { .setting-title { .setting-more { @@ -299,6 +300,7 @@ padding: 12px 32px; > li { padding: 0 8px; + font-size: 16px; &:hover { background-color: transparent; }