WEBプッシュ通知対応デジタル回覧板を作って見た
地域活動にに対してデジタルを推進する動きが始まっています。 ホームページ デジタル回覧板 メーリングリストみんなスマホを持っているのだから、紙の回覧板を回すのはちょっと面倒ですline公式アカウント、自治会アプリなどでデジタル化できますが、結構費用が掛かりますレンタルサーバは220円/月で利用できるところがありますここにホームページとWEBプッシュ対応デジタル回覧板を作ればいいですホームページはwordpressで作れば簡単アプリはPHPで作り、少し汎用性を入れましたので、サーバにアップすればそのまま使えます運用は、コンテンツのスクショをパソコンで撮って、サーバにアップするだけです。アップロード専用のアプリも作りましたちょっとしたプログラミングやIT知識でいろんなことの融通性が高まります今回作ったWEBプッシュ対応デジタル回覧板は下記を使いました pushcode bootstrap5 jquery fontawsome javascript シングルページ対応のため、コーディング売りはpushcodeに対応した通知ができることです。IPHONEにも対応していますアプリと同じようにホーム画面にアイコンを置けます5000件/月まで無料で使えるので、町内会では週1で配信ができますシングルページにしたので、フッター部のアイコンをクリックすると動的にコンテンツを取得して、配置します紙の町会だよりのコンテンツを画像化して登録しますできたソースは<?PHP //デジタル回覧板システム//外部サイトへのURL取得$xml=simplexml_load_file("siteinfo.xml");if ($xml===FALSE) { return;}else { $homepage=$xml- > homepage; $mail=$xml- > mail;}?> < !DOCTYPE html > <html lang="ja" > <head > <meta charset="UTF-8"/ > <meta name="viewport"content="width=device-width, initial-scale=1" > <link rel="manifest"href="/push/manifest.json" > <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"rel="stylesheet"integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM"crossorigin="anonymous" > <script defer src="https://www.pushcode.jp/dist/js/pushcode.js" > </script > <link rel="stylesheet"href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" > <script src="https://kit.fontawesome.com/25fb059f3e.js"crossorigin="anonymous" > </script > <script src="https://code.jquery.com/jquery-3.7.1.min.js"integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="crossorigin="anonymous" > </script > <script > window.PushCodeInit=function() { try { if (PushCode && PushCode.isSupport()) { PushCode.init( { domainToken: 'dxxxxxxxxxxxxxxxxxxxxxxa', userid: '', serviceWorkerPath: '/push/pushcode_sw.js', scopePath: '/push/' } ); PushCode.components.openSubscribeDialog(); } } catch (err) { console.error(err); if (PushCode) { PushCode.sendError(err); } }};</script > <title > デジタル回覧板</title > <meta name="msapplication-square70x70logo"content="/site-tile-70x70.png" > <meta name="msapplication-square150x150logo"content="/site-tile-150x150.png" > <meta name="msapplication-wide310x150logo"content="/site-tile-310x150.png" > <meta name="msapplication-square310x310logo"content="/site-tile-310x310.png" > <meta name="msapplication-TileColor"content="#0078d7" > <link rel="shortcut icon"type="image/vnd.microsoft.icon"href="/push/images/favicon.ico" > <link rel="icon"type="image/vnd.microsoft.icon"href="/push/images/favicon.ico" > <link rel="apple-touch-icon"sizes="57x57"href="images/apple-touch-icon-57x57.png" > <link rel="apple-touch-icon"sizes="60x60"href="images/apple-touch-icon-60x60.png" > <link rel="apple-touch-icon"sizes="72x72"href="images/apple-touch-icon-72x72.png" > <link rel="apple-touch-icon"sizes="76x76"href="images/apple-touch-icon-76x76.png" > <link rel="apple-touch-icon"sizes="114x114"href="images/apple-touch-icon-114x114.png" > <link rel="apple-touch-icon"sizes="120x120"href="images/apple-touch-icon-120x120.png" > <link rel="apple-touch-icon"sizes="144x144"href="images/apple-touch-icon-144x144.png" > <link rel="apple-touch-icon"sizes="152x152"href="images/apple-touch-icon-152x152.png" > <link rel="apple-touch-icon"sizes="180x180"href="images/apple-touch-icon-180x180.png" > <link rel="icon"type="image/png"sizes="36x36"href="images/android-chrome-36x36.png" > <link rel="icon"type="image/png"sizes="48x48"href="images/android-chrome-48x48.png" > <link rel="icon"type="image/png"sizes="72x72"href="images/android-chrome-72x72.png" > <link rel="icon"type="image/png"sizes="96x96"href="images/android-chrome-96x96.png" > <link rel="icon"type="image/png"sizes="128x128"href="images/android-chrome-128x128.png" > <link rel="icon"type="image/png"sizes="144x144"href="images/android-chrome-144x144.png" > <link rel="icon"type="image/png"sizes="152x152"href="images/android-chrome-152x152.png" > <link rel="icon"type="image/png"sizes="192x192"href="images/android-chrome-192x192.png" > <link rel="icon"type="image/png"sizes="256x256"href="images/android-chrome-256x256.png" > <link rel="icon"type="image/png"sizes="384x384"href="images/android-chrome-384x384.png" > <link rel="icon"type="image/png"sizes="512x512"href="images/android-chrome-512x512.png" > <link rel="icon"type="image/png"sizes="36x36"href="images/icon-36x36.png" > <link rel="icon"type="image/png"sizes="48x48"href="images/icon-48x48.png" > <link rel="icon"type="image/png"sizes="72x72"href="images/icon-72x72.png" > <link rel="icon"type="image/png"sizes="96x96"href="images/icon-96x96.png" > <link rel="icon"type="image/png"sizes="128x128"href="images/icon-128x128.png" > <link rel="icon"type="image/png"sizes="144x144"href="images/icon-144x144.png" > <link rel="icon"type="image/png"sizes="152x152"href="images/icon-152x152.png" > <link rel="icon"type="image/png"sizes="160x160"href="images/icon-160x160.png" > <link rel="icon"type="image/png"sizes="192x192"href="images/icon-192x192.png" > <link rel="icon"type="image/png"sizes="196x196"href="images/icon-196x196.png" > <link rel="icon"type="image/png"sizes="256x256"href="images/icon-256x256.png" > <link rel="icon"type="image/png"sizes="384x384"href="images/icon-384x384.png" > <link rel="icon"type="image/png"sizes="512x512"href="images/icon-512x512.png" > <link rel="icon"type="image/png"sizes="16x16"href="images/icon-16x16.png" > <link rel="icon"type="image/png"sizes="24x24"href="images/icon-24x24.png" > <link rel="icon"type="image/png"sizes="32x32"href="images/icon-32x32.png" > < !-- Webpush機能搭載 -- > <style > a { text-decoration: none; color: #fff;}.space100 { height: 400px;}.s16 { font-size: 10px;}.s20 { font-size: 16px;}</style > </head > <body > <div class=container > <div class=row > <div class="col-12 bg-primary text-white" > <h4 class="text-center" > 三ツ沢上町デジタル町会だより</h4 > </div > < !--動的にコンテンツが変わります-- > <div id=contents class="col-12" > <img class=img-fluid src=contents/tayori.png alt="" > <img class=img-fluid src=contents/tayori_2.png alt="" > </div > <div class=space100 > .</div > < !--fottermenu-- > <div class="d-block footer-menu-bar w-100 fixed-bottom bg-secondary text-white s16" > <div class="row m-2" > <p class="text-center s20" > 通知を許可するとスマホに最新情報のお知らせが届きます</p > <div id=link_home class="col text-center" > <a href="<?PHP print $homepage;?>" > <i class="fa-solid fa-house-chimney fa-2xl" > </i > </a > <br > ホームページ </div > <div id=link_tayori class="col text-center" > <i class="fa-solid fa-newspaper fa-2xl" > </i > <br > 町会だより </div > <div id=link_news class="col text-center" > <i class="fa-solid fa-newspaper fa-2xl" > </i > <br > お知らせ </div > <div id=link_disaster class="col text-center" > <i class="fa-solid fa-house-fire fa-2xl" > </i > <br > 防災 </div > <div id=link_event class="col text-center" > <i class="fa-regular fa-calendar-days fa-2xl" > </i > <br > イベント </div > <div id=link_trash class="col text-center" > <i class="fa-solid fa-trash fa-2xl" > </i > <br > ゴミ</i > </a > </div > <div id=link_mail class="col text-center" > <a href="<?PHP print $mail;?>" > <i class="fa-regular fa-envelope fa-2xl" > </i > <br > 問い合わせ</a > </div > </div > </div > </div > </div > <script >//シングルページの部分、アイコンクリックでコンテンツを更新 $("#link_tayori").on('click', function() { get_file("tayori.php"); });$("#link_news").on('click', function() { get_file("news.php"); });$("#link_disaster").on('click', function() { get_file("disaster.php"); });$("#link_event").on('click', function() { get_file("event.php"); });$("#link_trash").on('click', function() { get_file("trash.php"); });function get_file(w) { $.get(w, function(data) { $("#contents").html(data); } );//クリックがわかるようにバイブレーション if(window.navigator.vibrate) { window.navigator.vibrate([100]); } else if(window.navigator.mozVibrate) { window.navigator.mozVibrate([100]); } else if(window.navigator.webkitVibrate) { window.navigator.webkitVibrate([100]); } else { alert("sorry (T-T)"); }}</script > </body > </html >運用 コンテンツに連番を付けてサーバにアップするだけ アップロード用のページも別途作りましたアップロード<html><head><title>画像をドラッグ&ドロップで一括アップロード</title><script src="../js/dropzone.js"></script><link rel="stylesheet" href="../css/dropzone.css?v=1473248119" /><link rel="stylesheet" href="../css/style.css?v=1473248119" /></head><body><pre>contents画像コンテンツを連番で作成しアップロードしますtayori.php tayori_??.pngnews.php news_??.png</pre><form action="upload.php" class="dropzone" id="my-awesome-dropzone"></form><form action=delall.php> <input type=submit value=コンテンツ削除><form></body></html>ファイル設置<?php$ds = DIRECTORY_SEPARATOR; $storeFolder = '../contents'; if (!empty($_FILES)) { $tempFile = $_FILES['file']['tmp_name']; $ext=substr($_FILES['file']['name'],-3,3); $targetFile = $targetPath. $_FILES['file']['name']; $a=(move_uploaded_file($tempFile,'../contents/'.$targetFile));構成contents 画像コンテンツtayori.php tayori_??.pngnews.php news_??.pngevent.php event.png スケジュール画像siteinfo.xml 外部サイトURL(ホームページ、問い合わせ)pushcode_sw.js pushcodeスクリプトmanifest.json PWAimages logo.png サイトロゴ index.php tayori.php 町会だより news.php お知らせ event.php イベントスケジュール disaster.php 防災 trash.php ゴミ mail.php 問い合わせコンテンツhomepage 外部へリンクtayori.php 町会だより 画像<?php$t="<img class='img-fluid' src=contents/[file]>";$d = dir("contents");while (false !== ($entry = $d->read())) { if (false !== strpos($entry, 'tayori_')) { echo str_replace("[file]",$entry,$t); }}$d->close();news.php お知らせ 画像<?php$t="<img class='img-fluid' src=contents/[file]>";$d = dir("contents");while (false !== ($entry = $d->read())) { if (false !== strpos($entry, 'news_')) { echo str_replace("[file]",$entry,$t); }}$d->close();event.php イベントスケジュール 固定画像 <img class="img-fluid d-block mx-auto" src=contents/event.png alt=""><div class=space100>/</div>disaster.php 防災 HTMLで作成 trash.php ゴミ HTMLで作成 mail.php 問い合わせ 外部へリンク