小愛スピーカー ユニバーサルリモコン版

またしてもXiaomi製品です。今回開封するのは、Xiaomiスピーカーの万能リモコン版。従来の家電をあっという間にスマートホーム化させます。 開封。想像していたよりずっと小さいです。 新発売のXiaomi AIスピーカーHDはかなり大きいですが、Xiaomiストアで抱えてみたことがあります(〃’▽’〃) パッケージ内容:本体+電源アダプター+データケーブル+取扱説明書 下の周りにあるのは本物の穴です。最初は写真で見たとき、ただの模様だと思っていました。 内部の中央には、円錐形のダブルピラミッドのようなものがあります。分かりやすく言うと、コマみたいな感じでしょうか。 マイクミュートボタン(上)は10秒長押しで工場出荷時設定にリセット、音量+/-ボタン(左右)、一時停止/再生ボタンは長押しで設定モードに入ります。 次に、Mi AIスピーカーアプリをダウンロードして、一連の設定を行います。 QQ Musicが内蔵されていますが、管理はできず、QQ Music上で行う必要があります。 これで、遊べるようになります。 お使いの小愛同学に「自爆モード起動」と言うと、新しいスキルをゲットできます(注意!!) また、一つ厄介な設定というかバグがあります。Bluetoothに接続して設定すると、ネットに繋がらなくなるのです。(意味不明??)

2019年11月20日 · 1 分 · MoeJue

感熱ブルートゥースプリンター開発

最近、レシート印刷の作業をしており、プロジェクトの要件としてiOSとAndroidの両方で実装する必要がありました。最初は全く分からず、インターネットで多くの資料を探し、たくさんの落とし穴にはまり、多くの記事を読みましたが、結果的にはうまくいきました。 Bluetoothプリンターは一般的に、レシート印刷とラベル印刷の2種類の印刷モードに分けられます。 会社が購入した粗悪なプリンターには開発ドキュメントすらなく、多くの落とし穴にはまる羽目になりました。開発担当者に購入時に相談してくれればよかったのに。 現在、WeChatミニプログラムでBluetoothプリンターに接続する wx.createBLEConnection は、iOSデバイスでは問題なく動作しますが、一部のAndroidスマートフォンでは異常が発生します(接続時にシステムペアリングボックスがポップアップ表示され、キャンセルをタップしても、ペアリングコードを入力して確定をタップしても、すぐに接続が切断されます。入力もキャンセルもしない場合、30秒以内にBluetoothプリンターから自動的に切断されます)。 現在採用している方法は、AndroidとiOSそれぞれにBluetooth印刷コマンドのセットを作成することです。 IOS // ====================蓝牙操作================== //初始化蓝牙模块 openBluetoothAdapter() { if (app.sysinfo.provider == 1) { // 开启蓝牙 app.onBluetooth() setTimeout(() => { this.android_search() }, 2000) return false; } this.closeBluetoothAdapter() uni.openBluetoothAdapter({ success: (res) => { console.log("初始化蓝牙模块: " + JSON.stringify(res)); this.startBluetoothDevicesDiscovery() }, fail: (res) => { if (res.errCode === 10001) { uni.onBluetoothAdapterStateChange((res) => { console.log('监听蓝牙适配器状态变化事件', res) if (res.available == false) { app.global_printing = {} this.connected = false this.chs = [] this.canWrite = false } if (res.available) { this.startBluetoothDevicesDiscovery() } }) } if (res.errCode) { app.alert('初始化蓝牙失败,错误码:' + res.errCode) return false; } app.alert(res.errMsg) } }) }, //获取本机蓝牙适配器状态 getBluetoothAdapterState() { uni.getBluetoothAdapterState({ success: (res) => { console.log('获取本机蓝牙适配器状态。', JSON.stringify(res)) if (res.discovering) { this.onBluetoothDeviceFound() } else if (res.available) { this.startBluetoothDevicesDiscovery() } }, fail: (res) => { console.log('error:获取本机蓝牙适配器状态失败', JSON.stringify(res)) setTimeout(() => { this.getBluetoothAdapterState() }, 500) } }) }, //开始搜寻附近的蓝牙外围设备 startBluetoothDevicesDiscovery() { console.log(this.discoveryStarted); if (this.discoveryStarted) { return } console.log('开始搜索蓝牙设备'); this.discoveryStarted = true this.onBluetoothDeviceFound() setTimeout(() => { uni.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true, success: (res) => { console.log('startBluetoothDevicesDiscovery success', JSON.stringify( res)) }, fail: (res) => { if (res.errCode == '10001') { app.alert('当前蓝牙适配器不可用') } else { app.alert('搜索蓝牙失败,状态码:' + res.errCode) } } }) }, 500) }, // 停止搜索 stopBluetoothDevicesDiscovery() { uni.stopBluetoothDevicesDiscovery() this.discoveryStarted = false }, //寻找到新设备的事件的回调函数 onBluetoothDeviceFound() { console.log('寻找到新设备的事件的回调函数'); uni.onBluetoothDeviceFound((res) => { console.log(res); res.devices.forEach(device => { if (!device.name && !device.localName) { return } const foundDevices = this.devices const idx = this.inArray(foundDevices, 'deviceId', device.deviceId) if (idx === -1) { this.devices.push(device) } else { this.devices[idx] = device } }) }) }, //连接低功耗蓝牙设备 createBLEConnection(e) { uni.showLoading({ title: '设备连接中', mask: true }); const ds = e.currentTarget.dataset const deviceId = ds.deviceId const name = ds.name if (app.sysinfo.provider == 1) { if (ds.pair !== true) { this.android_search(deviceId) } else { console.log('已配对') } var device = null, BAdapter = null, BluetoothAdapter = null, uuid = null, main = null, bluetoothSocket = null; var mac_address = deviceId var main = plus.android.runtimeMainActivity(); BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter"); var UUID = plus.android.importClass("java.util.UUID"); uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); BAdapter = BluetoothAdapter.getDefaultAdapter(); device = BAdapter.getRemoteDevice(mac_address); plus.android.importClass(device); bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid); plus.android.importClass(bluetoothSocket); if (!bluetoothSocket.isConnected()) { console.log('检测到设备未连接,尝试连接....'); bluetoothSocket.connect(); } this.connected = true this.name = name this.deviceId = deviceId this.canWrite = true app.global_printing = { name: name, deviceId: deviceId } app.saveData1('global_printing', app.global_printing) uni.hideLoading(); return false; } uni.createBLEConnection({ deviceId, success: (res) => { this.connected = true this.name = name this.deviceId = deviceId app.global_printing = { name: name, deviceId: deviceId } this.onBLEConnectionStateChange() // 防止获取失败 setTimeout(() => { this.getBLEDeviceServices(deviceId) }, 1000) }, fail: (res) => { uni.hideLoading(); app.Toast('设备连接失败') console.log("蓝牙连接失败:", res); } }) this.stopBluetoothDevicesDiscovery() }, //获取蓝牙设备所有服务(service) getBLEDeviceServices(deviceId) { uni.getBLEDeviceServices({ deviceId, success: (res) => { console.log("获取蓝牙服务成功:" + JSON.stringify(res)) if (res.services.length == 0) { uni.hideLoading(); app.alert('没有获取到蓝牙服务,无法打印001') app.global_printing = {} return false } for (let i = 0; i < res.services.length; i++) { if (res.services[i].isPrimary) { this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) return } } }, fail: (res) => { setTimeout(() => { this.getBLEDeviceServices(deviceId) }, 500) console.log("获取蓝牙服务失败:" + JSON.stringify(res)) } }) }, //获取蓝牙设备某个服务中所有特征值(characteristic) getBLEDeviceCharacteristics(deviceId, serviceId) { console.log('获取蓝牙设备某个服务中所有特征值', deviceId, serviceId) uni.getBLEDeviceCharacteristics({ deviceId, serviceId, success: (res) => { console.log('获取蓝牙设备某个服务中所有特征值 success', JSON.stringify(res)) uni.hideLoading(); if (res.characteristics.length == 0) { app.alert('没有获取到蓝牙服务,无法打印002') app.global_printing = {} return false } for (let i = 0; i < res.characteristics.length; i++) { let item = res.characteristics[i] if (item.properties.read) { uni.readBLECharacteristicValue({ deviceId, serviceId, characteristicId: item.uuid, }) } if (item.properties.write) { this.canWrite = true app.global_printing._deviceId = deviceId app.global_printing._serviceId = serviceId app.global_printing._characteristicId = item.uuid app.saveData1('global_printing', app.global_printing) //this.writeBLECharacteristicValue() } if (item.properties.notify || item.properties.indicate) { uni.notifyBLECharacteristicValueChange({ deviceId, serviceId, characteristicId: item.uuid, state: true, }) } } }, fail(res) { console.error('获取特征值失败:', res) } }) // 操作之前先监听,保证第一时间获取数据 uni.onBLECharacteristicValueChange((characteristic) => { console.log(this.data.chs); const idx = this.inArray(this.data.chs, 'uuid', characteristic.characteristicId) const data = {} if (idx === -1) { this.chs[this.data.chs.length] = { uuid: characteristic.characteristicId, value: ab2hex(characteristic.value) } } else { this.chs[idx] = { uuid: characteristic.characteristicId, value: ab2hex(characteristic.value) } } }) }, onBLEConnectionStateChange() { uni.onBLEConnectionStateChange((res) => { // 该方法回调中可以用于处理连接意外断开等异常情况 console.log(`蓝牙连接状态改变device ${res.deviceId} state has changed, connected: ${res.connected}`) if (res.connected == false) { app.global_printing = {} this.connected = false this.chs = [] this.canWrite = false } }) }, //断开与低功耗蓝牙设备的连接 closeBLEConnection() { app.global_printing = {} uni.closeBLEConnection({ deviceId: this.deviceId }) this.connected = false this.chs = [] this.canWrite = false }, //关闭蓝牙模块 closeBluetoothAdapter() { app.global_printing = {} uni.closeBluetoothAdapter() this.discoveryStarted = false }, //发送数据 sendStr(bufferstr, success, fail) { var that = this; uni.writeBLECharacteristicValue({ deviceId: app.global_printing._deviceId, serviceId: app.global_printing._serviceId, characteristicId: app.global_printing._characteristicId, value: bufferstr, success: function(res) { success(res); console.log('发送的数据:' + bufferstr) // console.log('message发送成功') }, fail: function(res) { fail(res) console.log("数据发送失败:" + JSON.stringify(res)) }, complete: function(res) { // console.log("发送完成:" + JSON.stringify(res)) } }) }, //遍历发送数据 printCode(arr) { var that = this; if (arr.length > 0) { this.sendStr(arr[0], function(success) { arr.shift(); that.printCode(arr); }, function(error) { app.alert('打印失败,错误码:' + error.errCode) app.printing_status = false console.log(error); }); return false; } setTimeout(function() { app.printing_status = false console.log('打印结束'); }, 1000); }, Android 比較的シンプルで便利です。Native.jsを使用してNative Javaインターフェースチャネルを直接呼び出し、plus.androidを介してAndroidネイティブシステムAPIを呼び出します。 ネイティブAndroidドキュメント https://developer.android.google.cn/reference/android/bluetooth/BluetoothAdapter?hl=en ...

2019年11月5日 · 9 分 · MoeJue

サボっていた主が、新版の三合一を持って帰ってきました。

5月20日の告白以来、ハト主は行方不明の状態が続いていました……. 何ヶ月ぶりか分かりませんが、三合一がまた更新されました。2ヶ月前にグループで立てた目標を、今日達成しました。間の2ヶ月間何をしていたかは聞かないでください-.-(大規模なハトの集会に参加するのに忙しかった) 正文 ネットワーク認識が頻繁にダウンし、非常に不安定であるというフィードバックを多くの仲間から受けていたため、今回特別にローカル認識を更新しました。 1G以上のメモリを搭載したマシンへのインストールを推奨します。推奨構成は2コア2G、最適構成は16コア32Gです [#手動顔文字] v2.0 ローカルQRコード認識と生成を追加 ネットワーク認識インターフェースを削除 既知のバグを修正 その他のいくつかの詳細な最適化 詳細な説明とインストールチュートリアルは、こちらをクリックして以前のバージョンをご覧ください。 新しいバージョンのウェブサイトはすべて古いバージョンのデータを保持しており、以前のユーザーの使用には影響せず、スポンサー版のデータとも同期されています。 スポンサー版 旧バージョンの海賊版が横行していたため、新版の三合一にはスポンサー版が追加されました。 デモサイト:https://qr.moeins.cn スポンサー版の主な特徴: QRコードの認識と生成を最適化し、認識精度を大幅に向上させ、認識速度を高速化し、CPUとメモリを占有せず、より安定しています。 21種類の三合一生成テンプレートを新規追加し、無限拡張をサポートします。追加チュートリアルは文末にあります。 外部APIインターフェースを新規追加しました。このプログラムに限定されず、どのプログラムからでも呼び出し可能です。 入手方法: こちらをクリックして18.88元以上をプロジェクトに寄付すると、決済コード三合一のスポンサー限定版を入手できます。ぜひお試しください! スポンサー版に関するいくつかの小さな説明(これまでは特に説明していませんでした) これまでのところ、私のすべてのスポンサー版プロジェクトはドメインに縛られず、暗号化されておらず、自由に拡張でき、二次開発をサポートしており、スポンサー金額も低く設定されています。そのため、スポンサーしてくださった方々は、入手したソースコードを安易に共有しないようお願いいたします。これは作者への敬意であり、ご自身の権利の保護でもあります。売買関係ではないため、重大なバグがない限り、作者は不定期に更新するか、無期限に更新を延期する場合があります。小さな問題が発生した場合、作者が空いている時間であれば指導や修正を手伝う用意がありますが、大規模な新機能の追加といった場合には、協力を拒否するか、別途料金をいただく権利があります。 スポンサー版テンプレート拡張チュートリアル テンプレートの推奨サイズは:900*1200 テンプレート画像を/public/static/images/template/テンプレートディレクトリに配置します。注意点として、中国語名を使用せず、jpg拡張子のみをサポートします。 ルートディレクトリのconfig.phpにあるqr_template項目に関連データを以下のような形式で設定します。 '001' => [ 'name' => '默认模板', 'data' => [ 150,200 ], 'title' => true, 'size' => 20 ] パラメータ説明 名称 変数名 必須 型 例 説明 テンプレートID なし はい int 001 テンプレートのファイル名。数字を推奨し、重複不可。 エイリアス name はい string デフォルトテンプレート フロントエンドに表示されるテンプレートのエイリアス X,Y data はい array [150,200] QRコード生成の左上隅の開始X(横座標)、Y(縦座標)座標。負の値は不可で、テンプレートサイズより小さいこと。 テンプレートタイトル title いいえ bool false テンプレートタイトルを有効にするかどうか。テンプレートがサポートしている場合(デフォルトテンプレートなど)に使用。空でも可。 サイズ size いいえ int 20 QRコードの生成サイズ。デフォルトは20。空でも可。 はい、とても簡単です!

2019年8月4日 · 1 分 · MoeJue

ミニプログラムアーキテクチャ

皆さんがミニプログラムをどのように書いているかは分かりませんが、数ヶ月前にWeChatミニプログラムを書いていた時、自分で考えたアーキテクチャ、あるいはフレームワークと呼べるものがあります。 WeChatネイティブのアーキテクチャは次のようになっています。 ├── app.js ├── app.json ├── app.wxss ├── pages │ │── index │ │ ├── index.wxml │ │ ├── index.js │ │ ├── index.json │ │ └── index.wxss │ └── logs │ ├── logs.wxml │ └── logs.js └── utils なぜWeChatネイティブの書き方を使わないのか? ミニプログラムはスマホアプリに似ていて、tabBarがありますよね。WeChat公式のtabBarはapp.jsonでグローバルに設定されます。一般的な開発では何の問題もありませんが、複雑なtabBarを実装する場合、公式のネイティブな方法では実現できず、動的に読み込むこともできません。例えば、ある動画アプリの中央にある撮影・録画機能のようなものです。 これは、公式が提供するtabBarを使えず、自作する必要があることを意味します。 最初の私のアプローチは、ネイティブの構造を維持しつつ、tabBarだけを自作するというものでした。そのため、ページのコードはすべて1つのファイルに書き、デフォルトで最初の画面を表示し、他は非表示にします。ページを切り替える際に、対応するページを表示し、他を非表示にして、データを動的にレンダリングします。しかし、これには問題がありました。小規模なプロジェクトなら大した問題はありませんが、大規模なプロジェクトでコード量が膨大になると、すべてを1つのファイルに書くのは後のメンテナンスが困難になります。そのため、この方法は最終的に却下されました。 その後、ページの切り替え方法を(wx.switchTabなどを使った)画面遷移に変更し、異なるページのコードを別々のファイルに分けました。しかし、まだ問題がありました。切り替え時に画面がちらつくのです。ページを切り替えるたびに、まるで新しいウェブページを開くかのように、tabBarが再レンダリングされるため、ちらつきが発生します。これも却下です。 そこで、現在の全く新しいアーキテクチャ方式が生まれました: /pages/index/以下のファイルをすべてエントリーファイル(JSエントリー、CSSエントリー、ビューエントリー)として定義します。異なるページのファイルは、管理しやすいように、やはり別の場所に置きます。新しくtemplateというフォルダを作成し、異なるページ間のコードを格納します。その構造は公式の単一ページの構造と同じです。 ルートディレクトリのapp.jsはグローバル関数を格納するために使用し、他のページからはgetApp()で呼び出すだけです。 JSのエントリーファイル const app = getApp(); var index_js = require("../../template/index/index.js"); var types_js = require("../../template/types/types.js"); var Global_Data = []; Page({ data: { active: 0, show: { index: true, types: false, course: false, user: false } }, onLoad(options) { this.setData({ Global_Data: index_js.getData() }) }, // 下部ナビゲーションの切り替え tabbar_onChange(event) { var key = ''; this.data.show = { index: false, types: false, course: false, user: false }; console.log(event) switch (event.detail) { case 0: key = 'index'; Global_Data = index_js.getData(); break; case 1: key = 'types'; Global_Data = types_js.getData() break; case 2: key = 'course'; Global_Data = index_js.getData(); break; case 3: key = 'user'; Global_Data = index_js.getData(); break; } this.data.show[key] = true; console.log(Global_Data) this.setData({ show: this.data.show, Global_Data: Global_Data }) }, }); wxmlエントリーファイル ...

2019年5月17日 · 2 分 · MoeJue

よく使われる機能のクエリSQL

1、シーン:ある選手のランキングと、1つ上の順位の選手との票差をクエリする 方法2(重複を除外してソートし、自分より票の少ない数をクエリする) $temp = DB::fetch_first(“SELECT distinct total+jewel_vote+forge_vote ,COUNT(*)+1 AS RANK FROM " . DB::table(‘vote_competition’) .” WHERE total+jewel_vote+forge_vote>" . $competition[‘all’] . " and aid={$aid} ORDER by forge_vote desc"); $rank = $temp[‘RANK’]; 1つ上の順位の選手の票数を直接クエリすることはできない if ($temp[’total+jewel_vote+forge_vote’]) { //ここでクエリされるのは1位の選手との票差です $up = $temp[’total+jewel_vote+forge_vote’]-$competition[‘all’]; } 方法1(変数を定義して累加ソート) $temp = DB::fetch_all(“SELECT a.cid,a.total,a.forge_vote,a.jewel_vote,(@rowNum:=@rowNum+1) AS rank FROM pre_vote_competition AS a, (SELECT (@rowNum :=0) ) b WHERE aid={$aid} ORDER BY (a.total+a.forge_vote+a.jewel_vote) DESC “); foreach ($temp as $key => $value) { if ($value[‘cid’] == $cid) { //現在の自分のランキング $rank = $value[‘rank’]; if ($up) { $up = $up - ($value[’total’] + $value[‘forge_vote’] + $value[‘jewel_vote’]); } break; } //1つ上の順位の選手との票差 $up = $value[’total’] + $value[‘forge_vote’] + $value[‘jewel_vote’]; } ...

2019年4月10日 · 3 分 · MoeJue

WeChat JSAPI 決済

以前からWeChat関連の業務を行っていましたが、新しい技術ではないものの、これまで触れる機会がなく、いくつかの落とし穴にはまりました。そこで、時間を取って整理し、記録しておきます。 WeChat Payは全部で7種類あり、それぞれ:支払いコード決済、JSAPI決済、Native決済、APP決済、H5決済、ミニプログラム決済、顔認証決済です。 今回の業務で使用したのはWeChat JSAPI決済です。ユーザーがWeChatスキャン、公式アカウントのフォローなどの方法で販売者のH5ページに入り、WeChat内でJSSDKを呼び出して支払いを完了します。 ドキュメント:https://pay.weixin.qq.com/wiki/doc/api/index.html SDK:[https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1 ](https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1)JSAPI決済は、WeChat内のブラウザで開くことでWeChat Payを起動できます。効果は以下の図の通りです。 インターフェースコードを添付します。 コードではテンプレートエンジンを使用しています。 html: {$competition\['username'\]} {$prices\[0\]}钻 {$prices\[1\]}钻 {$prices\[2\]}钻 {$prices\[3\]}钻 {$prices\[4\]}钻 注:1钻=1元,1钻={$activity\['offset'\]}票 立即微信支付 JavaScript: // 投票 var offset = {$activity[‘offset’]}; $(’#tips’).html(‘正在给{$competition[‘code’]}号赠送{$prices[0]}钻=’+({$prices[0]}*offset)+‘票’); $(’#vote’).click(function(){ $.post(’/index/index/detailed.html?cid={$cid}&aid={$aid}’,{ formhash :’{FORMHASH}’, submit:‘1’, type:1, openid:’{$_G[‘member’][‘openid’]}’ },function(res){ alert(res.msg); if (res.code == 0) { $(’.box-1 span’).text(res.data.all); $(’.box-2 span’).text(res.data.rank); $(’.box-3 span’).text(res.data.up + ‘票’); } }); }) /* jQuery对象级别プラグイン拡張 */ $.fn.extend({ /* 単選框 */ hlRadio:function () { var radioEl=$(this); radioEl.click(function () { var price = 0; price = $(‘input:radio:checked’).val(); $(’#price’).val(’’); $(’#tips’).html(‘正在给{$competition[‘code’]}号赠送’+price+‘钻=’+(price*offset)+‘票’); radioEl.siblings(“div”).removeClass(“active”); $(this).siblings(“div”).addClass(“active”); }); }, }); $(“input[name=‘price’]”).hlRadio(); $(’#price’).bind(‘input propertychange’, function(){ var price = 0; price = $(’#price’).val(); $(’#tips’).html(‘正在给{$competition[‘code’]}号赠送’+price+‘钻=’+(price*offset)+‘票’); }) ...

2019年3月30日 · 4 分 · MoeJue

大金持ちになれると思ったが、そうはならなかった。

2018年ももう終わりを迎えました 大金持ちになるという願いは叶わず さらに悲惨なことに、年次大作を完成させなければなりません ――年末総括 そういえば、この世にはもともと年末総括なんてありませんでした KPIができてからというもの 尽きることのない恨みつらみが生まれました 以下、本文です 記事アーカイブでは、すべての記事と投稿日時をはっきりと確認できます。2018年は毎月記事を投稿し、ほぼ毎日チェックしに来ていました。 振り返り 1月:初めての自作ブログシステムを開発 2月:初めてのフィギュア(嫁)を購入 3月:幻想領域画像アップローダーの初版をリリース 4月:幻想領域画像アップローダーの正式版を更新、emlogの新浪(Sina)プラグインを統合 5月:萌音カード販売プラットフォームをローンチ 6月:長らく放置していたプレイリストを修正 7月:わー、萌音コミュニティが登場 8月:三位一体決済コードをリリース 9月:萌音映像サイトをローンチ 10月:3回目のプログラマーの日(1024)を過ごす 11月:Xiaomiのノートパソコンを購入&萌音クラウドノートをリリース 12月:遠くへ旅立ったが、二次元だけは諦められない 2019年 2019年は、忙しく、学び、そして成長する一年になるでしょう。年始の抱負は裏切らず、今年は大小さまざまなプロジェクトを数多くこなし、多くのことを学びました。初めてのQQグループを作り、私を愛してくれる仲間たちと出会いました。 今年もまたまたブログの定時投稿を忘れてしまいましたが、去年のような賢(厚)い(顔)で投稿時間を修正するようなことはもうしません。過ぎ去った時間は、畢竟戻ってこないのですから。 この2ヶ月で学んだことは、萌音クラウドノートに記録しており、ブログには投稿していません。興味のある方はぜひご覧ください。一体何があったのか、以前は1、2ヶ月かけてプロジェクトを一つ生み出していましたが、今では週に一つ作り上げています。これはただの愚痴で、不満ではありません。 去年の抱負は敬業福(去年来てくれた方ならご存知のはず)に書いたのですが、今年もそれを掲げようと思ったら、ソースコードが遥か彼方にあることに気づき、諦めました。まあ、ブログを一本投稿すればいいだけのことです。 この2ヶ月で、C、C++、Java、node.jsにも入門し、discuzのプラグイン&テンプレート、Baidu&WeChatのミニプログラム、公式アカウントなどにも手を出しました…… 2019年も引き続き頑張ります….

2019年1月2日 · 1 分 · MoeJue

萌音影视 - オンライン動画アプリ

ブログ | デモサイト | QQグループ | GitHub 洗練されたLaravelフレームワークと、全然可愛くないMeizi UIに基づいたオンライン動画アプリケーション 作者より オンライン動画サイトはどこにでも溢れていますが、それは私が自分で一つ書くことを妨げるものではありません。こうすれば、後で自分でアニメを見るのも便利になりますし、結局、自分で手を動かしてこそ豊かになれるものです。さらに新しい知識も学べるのですから、なんと素晴らしいことでしょう。 ページデザインは一部のウェブサイトを参考にしました。動画リソースはすべてインターネットからのものです。もし著作権侵害がありましたら、速やかにご連絡ください。 一緒にあのうんざりする60秒広告を捨てましょう〜 データベースなし、バックエンドモードなし、設定ファイルは一つだけ(config/web.php) 広告なし、VIP解析をサポート、公式ソース、高速、多チャンネル、多カテゴリ To-do: 独立したチャンネルホームページ テレビ局ライブ配信 複数の解析インターフェース 追加予定… スポンサー限定版 これはデュアルバージョンアプリケーションです。つまり、2つの異なるバージョンがあります。スポンサー版は通常版を最適化したもので、機能とパフォーマンスが大幅に向上し、実行速度が大幅に向上し、優先的な更新が維持されます。 さて、問題です。スポンサー限定版はどのように入手できますか? ここ または ここ でプロジェクトに58元以上を寄付することで入手できます。 もちろん、もしプロジェクトがあなたのお役に立てたなら、またはあなたが必要とするなら、私たちを支援することを選択できます。たとえわずかな金額でも、それは愛です。 オープンソースプロジェクトを書く人が利益のために書くことはないと思います。結局のところ、それはレンガ工場で一日レンガを運ぶよりも稼げないからです。 インストール要件 LNMP/AMP (PHP5.6+が必要) curl、OpenSSL拡張機能 Composer Composerによるメインプログラムのインストール 1. Composerを使用してmoeinsをインストール $ composer create-project a-jue/moeins #依存ライブラリのインストール後、インストールスクリプトが自動的に実行されます #以下のプロンプトが表示されたらインストール完了です > Illuminate\Foundation\ComposerScripts::postInstall > php artisan optimize Generating optimized class loader The compiled services file has been removed. > php artisan key:generate Application key [base64:Hx0I9UUQg7OyIz8lpDYG6Y/gW1uxS760ERdWfGG2jyQ=] set successfully. 2. ディレクトリ権限 publicサブディレクトリを公開Webディレクトリとして設定します 3. URLリライト Apacheサーバーの場合、プロジェクトディレクトリ内の.htaccessにはすでにリライトルールが設定されています。必要に応じて適宜修正してください。Nginxサーバーの場合、以下は参考となる設定です: ...

2018年9月25日 · 1 分 · MoeJue

QQ、支付宝(アリペイ)、微信支付(WeChat)の3つの決済コードが1つに

Receive the money ラ受け取りは、アリペイ、ウィーチャット、QQキャッシュコードの3つの統合システムです。 thinkPHP5.0 + MySQL + layuiで完成しました。 デモサイト:Paypal プロジェクトアドレス: GitHub 序文 チュートリアルも既成のコードも、インターネット上ではほとんどどこにでもある。 QRコードのアップロード、QRコードの識別、3-in-one支払いコードの生成、プロセスサービスの完全なセットを含むセットという言葉の具体化です。 3 in 1の大部分は個人的な使用のためだけであり、お金ラのコレクションは、複数のユーザーに3 in 1のサービスを提供することができます。 しかし、それは背景を持っていない、2つの主な理由があります: 1.頻繁に表示したり、構成、構成、生涯使用を変更する必要はありません。 2.著者の怠惰な癌の攻撃(また、インストールウィザードの不在を促した) 3.あなたが本当にそれを必要とする場合は、後でそれについて話します コード自体は比較的軽量で、フレームワークを使っているためにサイズが大きくなっている。 まあ、技術的な内容自体はなく、ほとんど使われない、人間の必要性に応じて書かれている、ちなみに、水水テキスト〜〜エスケープ(-)。 原則 3つのコードが1つになった領収書、とても魔法のように聞こえるし、感じるが、実際には、原理は非常に簡単です! QRコードは、実際には一連の文字列を含む単なる画像である。アリペイであれWeChatの支払いコードであれ、基本的には支払いリンクを含むQRコードなのだ。つまり、アリペイの閲覧ページであればアリペイの決済リンクを、WeChatであればWeChatのリンクを……という具合だ。 そして、ここには「ユーザーエージェント」というナレッジポイントがあり、例えばウェブビューの大手メーカーは独自のUA情報を持っている: QQ: MQQBrowser/6.2 TBS/043221 Safari/537.36 QQ/7.0.0.3135. WeChat: MQQBrowser/6.2 TBS 043220 Safari/537.36 MicroMessenger/6.5.8.1060 NetType/4G Language/zh_CN. Alipay: UCBrowser/11.5.0.939 UCBS/2.10.1.6 Mobile Safari/537.36 AliApp(AP/10.0.15.051805) AlipayClient/10.0.15.051805 Language/zh-Hans. これでQQなのかWeChatなのかアリペイのスキャンなのか一目瞭然: ユーザーエージェント`にQQ/が含まれている。 MicroMessengerを含むUser-AgentはWeChatです。 User-Agent` には AlipayClient が含まれています。 各ソフトウェアを区別できるので、URLを作成し、QRコード生成でURLをスキャンし、ブラウザのUAを判別して異なる決済コードを配信することができる。 大まかには以下のような流れになる: クライアントがコードをスキャン → サーバが User-Agent によってクライアントの種類を判別 → 異なる処理を返す これも注目に値する: QQ: httpsプロトコルは、QQを起こすことができない。 アリペイ:httpsプロトコル、直接アリペイAPPを起動することができます。 ...

2018年8月24日 · 1 分 · MoeJue

世界はこんなに広い、私が連れて行ってあげる 123

賢い人にしかこの文章は見えないそうです。パスワードは記事タイトルの後ろにあります 人生は短く、世界は広い。 小飞机助手は、S*h·a·d·o·w·s·o·c·k·sをベースにしたVPNプロキシソフトウェアアシスタントです。複数のノードが内蔵されており、可用率は80%にも達します。ワンクリックでグレートファイアウォールを回避し、科学的なインターネットアクセスという目的を達成できます。 免責事項 とある月のない嵐の夜、プログラマーである某ブロガーは、資料検索や学習のために頻繁にインターネットを利用する必要がありました。しかし、国内のBaiduでは英語の検索結果が不十分なため、Googleを使う必要があります。そして、中国大陸ではGoogleに直接アクセスできないため、やむを得ず「梯子」(VPNなどの迂回ツール)を使い、グレートファイアウォールを乗り越えるしかありませんでした。 本ソフトウェアはフリーソフトです。無断で販売しないでください! 本ソフトウェアは学習と交流のみを目的としています。違法な用途には使用しないでください。 本ソフトウェアを使用したことによるいかなる行為も作者とは無関係であり、作者は一切の法的責任を負いません! 動作環境 .NET Framework 4.6.2 と Microsoft Visual C++ 2015 Redistributable (x86) のインストールが必要です。 基本的な使い方 小飞机助手をダブルクリックして実行すると、内蔵のS·h·a·d·o·w·s·o·c·k·sが自動的に展開されます(ウイルス対策ソフトにご注意ください)。 小飞机助手はデフォルトで高可用性モードを使用していますが、モードを切り替えたり、お好みのノードを選択したりすることもできます。 システムプロキシを有効にする を選択して、システムプロキシを有効にします。ブラウザのプロキシプラグインを無効にするか、システムプロキシを使用するように設定してください。 サーバーの自由な切り替え 負荷分散:サーバーをランダムに選択します。 高可用性:遅延とパケットロス率に基づいてサーバーを自動的に選択します。 累積パケットロス率:定期的なpingによって速度を測定し、選択します。この機能を使用するには、メニューの可用性を統計を有効にしてください。 IStrategyインターフェースを実装して切り替えルールをカスタマイズし、pull requestを送信することもできます。 現在のノードが利用できない場合は、ご自身でノードの切り替えをお試しください。 ウイルス対策ソフトがウイルスとして検出する可能性があります。信頼リストに追加してください。ご心配な場合は、仮想マシンで実行してください。 Haboレポート:https://habo.qq.com/file/showdetail?pk=AD0GYV1oB2UIP1s9#pephoto .down_link{background:url(‘https://www.52ecy.cn/content/uploadfile/201707/md-bg.jpeg') no-repeat 100% 0% #fffdff; border: 1px solid #faf8fb; border-radius: 2px; color: #666; font-size: 14px; margin-bottom: 10px; padding: 5px 20px;}.downbtn{background: none repeat scroll 0 0 #1BA1E2; border: 0 none; border-radius: 2px; color: #FFFFFF; cursor: pointer; font-family: “Open Sans”,“Hiragino Sans GB”,“Microsoft YaHei”,“WenQuanYi Micro Hei”,Arial,Verdana,Tahoma,sans-serif; font-size: 14px; margin: -4px 20px 0 0; padding: 8px 30px;text-transform:none;text-decoration:none;} .downlink a{text-decoration:none;} .downlink a{text-decoration:none;font-size:15px;} .downlink a:link{color: #ffffff;} .downlink a:visited{color: #ffffff;} .downlink a:hover{color: #ffffff;} .downlink a:active{color: #ffffff;} .downbtn{background: none repeat scroll 0 0 #1BA1E2; border: 0 none; border-radius: 2px; color: #FFFFFF !important; cursor: pointer; font-family: “Open Sans”,“Hiragino Sans GB”,“Microsoft YaHei”,“WenQuanYi Micro Hei”,Arial,Verdana,Tahoma,sans-serif; font-size: 14px; margin: -4px 20px 0 0; padding: 8px 30px;} .yanshibtn{background: none repeat scroll 0 0 #d33431; border: 0 none; border-radius: 2px; color: #FFFFFF!important; cursor: pointer; font-family: “Open Sans”,“Hiragino Sans GB”,“Microsoft YaHei”,“WenQuanYi Micro Hei”,Arial,Verdana,Tahoma,sans-serif; font-size: 14px; margin: -4px 20px 0 0; padding: 8px 30px;text-transform:none;text-decoration:none;} .downbtn:hover,.yanshibtn:hover{background: none repeat scroll 0 0 #9B59B6; border: 0 none; border-radius: 2px; color: #FFFFFF!important; cursor: pointer; font-family: “Open Sans”,“Hiragino Sans GB”,“Microsoft YaHei”,“WenQuanYi Micro Hei”,Arial,Verdana,Tahoma,sans-serif; font-size: 14px; margin: -4px 20px 0 0; padding: 8px 30px;} .downbtn a:hover,.yanshibtn a:hover{background: none repeat scroll 0 0 #9B59B6; border: 0 none; border-radius: 2px; color: #FFFFFF; cursor: pointer; font-family: “Open Sans”,“Hiragino Sans GB”,“Microsoft YaHei”,“WenQuanYi Micro Hei”,Arial,Verdana,Tahoma,sans-serif; font-size: 14px; margin: -4px 20px 0 0; padding: 8px 30px;} ...

2018年8月1日 · 2 分 · MoeJue