修正
This commit is contained in:
@@ -39,6 +39,67 @@
|
||||
color: #090;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* 账户搜索下拉框相关样式 */
|
||||
.account-search-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.account-search-input {
|
||||
width: 100%;
|
||||
padding: 6px !important;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.account-search-input:focus {
|
||||
outline: none;
|
||||
border-color: #4caf50;
|
||||
box-shadow: 0 0 4px rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.account-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: white;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
border-radius: 0 0 4px 4px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.account-dropdown.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.account-option {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.account-option:hover,
|
||||
.account-option.selected {
|
||||
background-color: #e3f2fd;
|
||||
}
|
||||
|
||||
.account-option-strong {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.account-option-light {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -84,6 +145,187 @@
|
||||
const API = "";
|
||||
let accounts = [];
|
||||
|
||||
// 科目グループ定義(仕訳入力と同期)
|
||||
const ACCOUNT_GROUPS = [
|
||||
// 資産の部
|
||||
{
|
||||
label: "現金・預金",
|
||||
codes: ["101", "102", "103", "104", "105"],
|
||||
},
|
||||
{
|
||||
label: "売上債権",
|
||||
codes: ["201", "202"],
|
||||
},
|
||||
{
|
||||
label: "有価証券",
|
||||
codes: ["301"],
|
||||
},
|
||||
{
|
||||
label: "棚卸資産",
|
||||
codes: ["210"],
|
||||
},
|
||||
{
|
||||
label: "他流動資産",
|
||||
codes: ["203", "204", "205", "206", "207", "208"],
|
||||
},
|
||||
{
|
||||
label: "有形固定資産",
|
||||
codes: ["401", "402", "403", "404", "405", "406", "407"],
|
||||
},
|
||||
{
|
||||
label: "無形固定資産",
|
||||
codes: ["408"],
|
||||
},
|
||||
{
|
||||
label: "投資その他資産",
|
||||
codes: ["410"],
|
||||
},
|
||||
// 負債の部
|
||||
{
|
||||
label: "仕入債務",
|
||||
codes: ["501"],
|
||||
},
|
||||
{
|
||||
label: "その他流動負債",
|
||||
codes: ["502", "503", "504", "505", "506", "507", "508"],
|
||||
},
|
||||
{
|
||||
label: "固定負債",
|
||||
codes: ["509"],
|
||||
},
|
||||
// 資本の部
|
||||
{
|
||||
label: "資本金",
|
||||
codes: ["601"],
|
||||
},
|
||||
{
|
||||
label: "利益剰余金",
|
||||
codes: ["602"],
|
||||
},
|
||||
// 収益・費用
|
||||
{
|
||||
label: "収益",
|
||||
codes: ["701", "702", "703", "704", "705"],
|
||||
},
|
||||
{
|
||||
label: "費用",
|
||||
codes: [
|
||||
"801",
|
||||
"802",
|
||||
"803",
|
||||
"804",
|
||||
"805",
|
||||
"806",
|
||||
"807",
|
||||
"808",
|
||||
"809",
|
||||
"810",
|
||||
"811",
|
||||
"812",
|
||||
"813",
|
||||
"814",
|
||||
"815",
|
||||
"816",
|
||||
"817",
|
||||
"818",
|
||||
"819",
|
||||
"820",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// ========================================
|
||||
// 账户搜索功能
|
||||
// ========================================
|
||||
function setupAccountSearch(inputElement, row) {
|
||||
const container = inputElement.closest(".account-search-container");
|
||||
const dropdown = container.querySelector(".account-dropdown");
|
||||
|
||||
inputElement.addEventListener("input", (e) => {
|
||||
const searchText = e.target.value.toLowerCase().trim();
|
||||
|
||||
if (!searchText) {
|
||||
dropdown.classList.remove("active");
|
||||
return;
|
||||
}
|
||||
|
||||
// 过滤账户
|
||||
const filtered = accounts.filter((acc) => {
|
||||
const code = acc.account_code.toLowerCase();
|
||||
const name = acc.account_name.toLowerCase();
|
||||
return code.includes(searchText) || name.includes(searchText);
|
||||
});
|
||||
|
||||
// 生成下拉建议
|
||||
dropdown.innerHTML = "";
|
||||
if (filtered.length === 0) {
|
||||
dropdown.innerHTML = `<div style="padding: 8px 12px; color: #999;">該当する科目がありません</div>`;
|
||||
} else {
|
||||
filtered.slice(0, 20).forEach((acc) => {
|
||||
const option = document.createElement("div");
|
||||
option.className = "account-option";
|
||||
option.innerHTML = `
|
||||
<span class="account-option-strong">${acc.account_code}</span>
|
||||
<span class="account-option-light">${acc.account_name}</span>
|
||||
`;
|
||||
option.addEventListener("click", () => {
|
||||
inputElement.value = `${acc.account_code} ${acc.account_name}`;
|
||||
inputElement.dataset.accountId = acc.account_id;
|
||||
dropdown.classList.remove("active");
|
||||
});
|
||||
dropdown.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
dropdown.classList.add("active");
|
||||
});
|
||||
|
||||
// クリック以外の場所のドロップダウンを非表示
|
||||
document.addEventListener("click", (e) => {
|
||||
if (!container.contains(e.target)) {
|
||||
dropdown.classList.remove("active");
|
||||
}
|
||||
});
|
||||
|
||||
// フォーカス時にドロップダウンを表示(既存値がある場合)
|
||||
inputElement.addEventListener("focus", () => {
|
||||
if (inputElement.value) {
|
||||
dropdown.classList.add("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 科目選択肢をグループ分けして構築
|
||||
function buildAccountOptions() {
|
||||
let html = "";
|
||||
|
||||
ACCOUNT_GROUPS.forEach((group) => {
|
||||
html += `<optgroup label="${group.label}">`;
|
||||
accounts
|
||||
.filter((a) => group.codes.includes(a.account_code))
|
||||
.forEach((a) => {
|
||||
html += `<option value="${a.account_id}">${a.account_code} ${a.account_name}</option>`;
|
||||
});
|
||||
html += `</optgroup>`;
|
||||
});
|
||||
|
||||
// 未分組の科目を「その他」グループに追加
|
||||
const groupedCodes = ACCOUNT_GROUPS.flatMap((g) => g.codes);
|
||||
const others = accounts.filter(
|
||||
(a) => !groupedCodes.includes(a.account_code),
|
||||
);
|
||||
|
||||
if (others.length > 0) {
|
||||
html += `<optgroup label="その他">`;
|
||||
others.forEach((a) => {
|
||||
html += `<option value="${a.account_id}">${a.account_code} ${a.account_name}</option>`;
|
||||
});
|
||||
html += `</optgroup>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// 初期化
|
||||
// ------------------------------------
|
||||
@@ -122,14 +364,14 @@
|
||||
|
||||
tr.innerHTML = `
|
||||
<td>
|
||||
<select>
|
||||
${accounts
|
||||
.map(
|
||||
(a) =>
|
||||
`<option value="${a.account_id}">${a.account_code} ${a.account_name}</option>`,
|
||||
)
|
||||
.join("")}
|
||||
</select>
|
||||
<div class="account-search-container">
|
||||
<input
|
||||
type="text"
|
||||
class="account-search-input account"
|
||||
placeholder="科目を入力・検索"
|
||||
autocomplete="off" />
|
||||
<div class="account-dropdown"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><input type="number" min="0"></td>
|
||||
<td><input type="number" min="0"></td>
|
||||
@@ -138,10 +380,19 @@
|
||||
|
||||
tbody.appendChild(tr);
|
||||
|
||||
// Setup account search for this row
|
||||
const accountInput = tr.querySelector(".account-search-input");
|
||||
setupAccountSearch(accountInput, tr);
|
||||
|
||||
if (line) {
|
||||
tr.querySelector("select").value = line.account_id;
|
||||
tr.querySelectorAll("input")[0].value = line.debit || "";
|
||||
tr.querySelectorAll("input")[1].value = line.credit || "";
|
||||
// Find the account and populate the input
|
||||
const account = accounts.find(a => a.account_id === line.account_id);
|
||||
if (account) {
|
||||
accountInput.value = `${account.account_code} ${account.account_name}`;
|
||||
accountInput.dataset.accountId = account.account_id;
|
||||
}
|
||||
tr.querySelectorAll("input")[1].value = line.debit || "";
|
||||
tr.querySelectorAll("input")[2].value = line.credit || "";
|
||||
}
|
||||
|
||||
// 入力時に合計を自動更新
|
||||
@@ -191,9 +442,10 @@
|
||||
c = 0;
|
||||
|
||||
document.querySelectorAll("#linesTable tbody tr").forEach((tr) => {
|
||||
const accountId = Number(tr.querySelector("select").value);
|
||||
const debit = Number(tr.querySelectorAll("input")[0].value || 0);
|
||||
const credit = Number(tr.querySelectorAll("input")[1].value || 0);
|
||||
const accountInput = tr.querySelector(".account-search-input");
|
||||
const accountId = Number(accountInput.dataset.accountId || 0);
|
||||
const debit = Number(tr.querySelectorAll("input")[1].value || 0);
|
||||
const credit = Number(tr.querySelectorAll("input")[2].value || 0);
|
||||
if (debit === 0 && credit === 0) return;
|
||||
lines.push({ account_id: accountId, debit, credit });
|
||||
d += debit;
|
||||
|
||||
Reference in New Issue
Block a user