3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VS Code+Baidu Comateでkintoneのレコード一括削除設定が有効化されているアプリをリストアップするブックマークレットを作るよ

Last updated at Posted at 2025-12-21

kintone Advent Calendar 2025 の 22日目の記事です。

内容

VS Code+Baidu Comateでkintoneのレコード一括削除設定がされているアプリをリストアップするブックマークレットを作ってみます。

↓悪魔の設定項目
image.png

kintoneのレコード一括削除設定が有効化されているとすごくこわいですよね。ワンクリックで数年分のデータが消えて、復旧もできません。普段からのバックアップも必要ですが、一番の予防策は設定を無効化しておくことです。
とはいえ、データメンテナンス等で一時的に有効化することもあり、消し忘れて冷や冷やした人も多いのではないでしょうか。

ブックマークレットとは

ブックマークレットは、ブラウザのブックマークにコード埋め込んで、色々できるものです。詳しくはwikipediaを御覧ください。

作ったもの

kintoneのログイン後、ブックマークレットをクリックしたら、そのkintone環境のレコード一括削除設定が有効化されているアプリをリストアップします。ゲストスペースは考慮していません。

image.png

image.png

Baidu Comate(文心快码)とは

中国の百度が出してるコーディング用のAIです。

私中国に住んでまして、中国だと海外のAIは色々あって使いにくいので、中国のAI使って書いてみます。

Baidu ComateはVS Codeに組み込んで使用可能です。まずは、Baidu Comateにkintone REST APIのお作法を覚えてもらいます。
この知識は、会社のみんなで共有したいので、組織としての知識集的な感じで設定します。自分オリジナルのお作法とかは、個人の知識集にいらられるので面白いですね。

image.png

コードも知識として設定できますが、今回はドキュメントなので、txtファイルで読み込ませておきます。

image.png

これらの知識は、VS Codeでコードを書いてもらうときに、#マークをつけて、AIに参照させられます。

image.png

VS Codeで書いていきます(Baidu Comateが)

プロンプト

*	ブックマークレットを作成してください。
*	kintone環境の全アプリの中から、レコード一括削除が設定が有効になっているアプリをリスト化、クリックで、該当アプリを開くブックマークレットです。
*	デザインはシンプルにして。
*	kintoneにログインしている状態で使うので、認証情報等はJS内には記載不要。
*	元となるJS Codeとブックマークレットへ貼り付けるためのJS Codeの2つのファイルを作成してください。
*	仕様は下記
1.	kintoneにログインした状態で使用する前提
2.	実行時、該当kintone環境にある全アプリを取得。100件を超える場合は複数回APIを呼び出してページングして。
 アプリ一覧取得はREST APIの apps.json を使用
3.	取得したアプリのリストの一般設定を取得。settings.json を使用。
4.	レコード一括削除有効(enableBulkDeletion)が有効なアプリのリストを画面表示。表示項目は アプリ名 アプリ番号 URL
5.	URLはクリックしたら別タブで該当アプリが開くように。例えばアプリ番号が999の場合、リンクURLは https://各環境のドメイン名/k/999 という感じ。

知識集で渡しているので、APIの詳細はAIに指示していませんが、使用を指示したのは、下記2つのAPIです。

複数のアプリの情報を取得する

アプリの一般設定を取得する

image.png

中国のAIなので、中国語で考えるんですが、僕が日本語で指示しているので、途中から日本語になってきました。助かりますね。

image.png

結果、途中何度かデバッグはしましたが、ほぼちゃんと書いてくれました。×をクリックしても閉じないバグがありますが、ご愛敬ということでなおしていません。

コードざっと確認して、致命的なセキュリティリスクとかはないと思いますが、コピペして使う場合は自己責任でよろしくお願いします。他のAIとかに読み込ませて、改行いれて、自分の目で確認してもらうと、一番安心です。

javascript:(function(){if(typeof kintone=='undefined'||typeof kintone.api=='undefined'){alert('エラー: kintone環境で実行してください');return}async function checkBulkDeletionSettings(){try{showLoading('アプリ一覧を取得中...');const allApps=await getAllApps();if(!allApps||allApps.length===0){throw new Error('閲覧権限のあるアプリが見つかりませんでした')}showLoading(''+allApps.length+'アプリの設定を確認中(有効なもののみ表示)...');const enabledApps=[];let checkedCount=0;for(let i=0;i<allApps.length;i++){const app=allApps[i];checkedCount++;updateProgress(checkedCount,allApps.length,app.name);try{const settings=await getAppSettings(app.appId);if(settings.enableBulkDeletion===true){enabledApps.push({appId:app.appId,name:app.name,code:app.code,url:window.location.origin+'/k/'+app.appId})}}catch(error){console.warn('アプリ '+app.name+' ('+app.appId+') の設定取得エラー:',error)}await delay(100)}displayEnabledApps(enabledApps,allApps.length)}catch(error){alert('エラー: '+error.message)}finally{hideLoading()}}async function getAllApps(){const allApps=[];let offset=0;const limit=100;while(true){try{const response=await kintone.api(kintone.api.url('/k/v1/apps',true),'GET',{offset:offset,limit:limit});const apps=response.apps||[];if(apps.length===0){break}allApps.push(...apps);offset+=apps.length;if(apps.length<limit){break}}catch(error){console.error('アプリ一覧取得エラー:',error);throw new Error('アプリ一覧の取得に失敗しました')}}return allApps}async function getAppSettings(appId){try{const response=await kintone.api(kintone.api.url('/k/v1/app/settings',true),'GET',{app:appId,lang:'ja'});return response}catch(error){throw new Error('アプリ設定の取得に失敗しました')}}function createPopup(){const popup=document.createElement('div');popup.id='bulk-deletion-checker-popup';popup.style.cssText='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:90%;max-width:800px;max-height:80vh;background:white;border:2px solid #3498db;border-radius:10px;box-shadow:0 4px 20px rgba(0,0,0,0.3);z-index:10000;font-family:メイリオ,Meiryo,sans-serif;overflow:hidden';const header=document.createElement('div');header.style.cssText='background:#3498db;color:white;padding:15px 20px;font-size:18px;font-weight:bold;display:flex;justify-content:space-between;align-items:center';header.innerHTML='<span>📋 レコード一括削除設定確認(有効なアプリのみ表示)</span><button id="close-popup" style="background:none;border:none;color:white;font-size:20px;cursor:pointer;">×</button>';const content=document.createElement('div');content.id='popup-content';content.style.cssText='padding:20px;max-height:calc(80vh - 100px);overflow-y:auto';popup.appendChild(header);popup.appendChild(content);document.body.appendChild(popup);document.getElementById('close-popup').addEventListener('click',()=>{document.body.removeChild(popup)});popup.addEventListener('click',(e)=>{if(e.target===popup){document.body.removeChild(popup)}});return content}function showLoading(message){let popupContent=document.getElementById('popup-content');if(!popupContent){popupContent=createPopup()}popupContent.innerHTML='<div style="text-align:center;padding:40px 20px;"><div style="font-size:48px;margin-bottom:20px;">⏳</div><div style="font-size:16px;color:#666;">'+message+'</div></div>'}function updateProgress(current,total,appName){const progress=Math.round((current/total)*100);const progressElement=document.querySelector('#popup-content div');if(progressElement){progressElement.innerHTML='<div style="font-size:48px;margin-bottom:20px;">⏳</div><div style="font-size:16px;color:#666;">処理中: '+current+'/'+total+' ('+progress+'%)<br><small>'+appName+'</small></div>'}}function hideLoading(){const popup=document.getElementById('bulk-deletion-checker-popup');if(popup){document.body.removeChild(popup)}}function displayEnabledApps(enabledApps,totalAppsCount){const popupContent=createPopup();let html='<div style="margin-bottom:20px;padding:15px;background:#ecf0f1;border-radius:5px;text-align:center;"><strong>全 '+totalAppsCount+' アプリ中、レコード一括削除が有効なアプリ:</strong><br>✅ <strong>'+enabledApps.length+'個</strong>が有効設定されています</div>';if(enabledApps.length>0){html+='<h3 style="color:#27ae60;margin-top:20px;">✅ レコード一括削除が有効なアプリ一覧</h3>';enabledApps.forEach(app=>{html+='<div style="border:1px solid #27ae60;border-radius:5px;padding:15px;margin-bottom:10px;background:#f0f8f0;border-left:4px solid #27ae60"><div style="font-weight:bold;font-size:16px;margin-bottom:8px;">'+app.name+'<span style="color:#666;font-size:14px;">(ID: '+app.appId+')</span><a href="'+app.url+'" target="_blank" style="color:#3498db;text-decoration:none;margin-left:10px;">▶ アプリを開く</a></div></div>'})}else{html+='<div style="text-align:center;padding:40px 20px;color:#666;"><div style="font-size:48px;margin-bottom:20px;">📭</div><div style="font-size:16px;">レコード一括削除が有効なアプリは見つかりませんでした</div></div>'}popupContent.innerHTML=html}function delay(ms){return new Promise(resolve=>setTimeout(resolve,ms))}checkBulkDeletionSettings()})();

ブックマークを作って、そこに貼り付けたら動く(はず)です。

image.png

動作イメージ

動かすと、まずアプリを一通り読み込みます。
image.png

レコード一括削除が有効になっているアプリがリストアップされます。ちゃんと動いていますね。

image.png

さいごに

AIにどこまでkintoneのお作法を正確に伝えられるかで、生成されるコードの品質が変わるのだろうなと思いました。

メリークリスマス!

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?