财务台账:增加编辑模式开关 #428
@ -5,6 +5,7 @@
|
||||
$canEdit = (bool) ($ledgerCanEditMapping ?? false);
|
||||
$canEditAccountStatus = (bool) ($ledgerCanEditAccountStatus ?? false);
|
||||
$canEditAccountType = (bool) ($ledgerCanEditAccountType ?? false);
|
||||
$canEditAccounts = $canEditAccountStatus || $canEditAccountType;
|
||||
$accountStatusOptions = $ledgerAccountStatusOptions ?? \App\Utilities\FinanceLedgerAccountStatus::OPTIONS;
|
||||
$accountFilterOptions = $ledgerAccountFilterOptions ?? ['regions' => [], 'types' => []];
|
||||
$accountTypeOptions = $accountFilterOptions['types'] ?? [];
|
||||
@ -45,6 +46,18 @@
|
||||
.ledger-field input, .ledger-field select { height:2.15rem; padding:0 .6rem; border:1px solid var(--vip-border, #D8D2C7); border-radius:.45rem; background:#fff; color:var(--vip-content-ink, #171717); font:inherit; }
|
||||
.ledger-field input:focus, .ledger-field select:focus { border-color:var(--vip-content-accent-dark, #856632); outline:none; box-shadow:0 0 0 3px rgba(133,102,50,.16); }
|
||||
.ledger-actions { display:flex; gap:.45rem; padding-bottom:.05rem; }
|
||||
.ledger-edit-switch { position:relative; display:inline-flex; align-items:center; align-self:flex-end; gap:.45rem; height:2.15rem; padding:0 .65rem; border:1px solid var(--vip-border, #D8D2C7); border-radius:.45rem; background:#fff; color:var(--vip-content-muted, #595959); font-size:.72rem; font-weight:600; cursor:pointer; user-select:none; white-space:nowrap; }
|
||||
.ledger-edit-switch input { position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }
|
||||
.ledger-edit-switch__track { position:relative; width:2.15rem; height:1.2rem; border-radius:999px; background:#d6d0c5; transition:background .16s ease; }
|
||||
.ledger-edit-switch__thumb { position:absolute; top:.15rem; left:.15rem; width:.9rem; height:.9rem; border-radius:50%; background:#fff; box-shadow:0 1px 2px rgba(23,23,23,.2); transition:transform .16s ease; }
|
||||
.ledger-edit-switch input:checked + .ledger-edit-switch__track { background:var(--vip-content-accent-dark, #856632); }
|
||||
.ledger-edit-switch input:checked + .ledger-edit-switch__track .ledger-edit-switch__thumb { transform:translateX(.95rem); }
|
||||
.ledger-edit-switch input:focus-visible + .ledger-edit-switch__track { outline:2px solid var(--vip-content-accent-dark, #856632); outline-offset:2px; }
|
||||
.ledger-edit-switch:has(input:checked) { border-color:var(--vip-content-accent-dark, #856632); background:var(--vip-content-accent-soft, #F7F0DE); color:var(--vip-content-accent-dark, #856632); }
|
||||
.ledger-edit-switch.is-disabled { cursor:not-allowed; opacity:.55; }
|
||||
#ledger-panel-accounts .ledger-account-editor { display:none; }
|
||||
#ledger-panel-accounts.is-account-edit-mode .ledger-account-readonly { display:none; }
|
||||
#ledger-panel-accounts.is-account-edit-mode .ledger-account-editor { display:block; }
|
||||
.ledger-btn { display:inline-flex; align-items:center; justify-content:center; gap:.35rem; height:2.15rem; padding:0 .8rem; border:1px solid var(--vip-border, #D8D2C7); border-radius:.45rem; background:#fff; color:var(--vip-content-ink, #171717); font:inherit; font-weight:600; text-decoration:none; cursor:pointer; white-space:nowrap; }
|
||||
.ledger-btn:hover { border-color:var(--vip-content-accent-dark, #856632); color:var(--vip-content-accent-dark, #856632); }
|
||||
.ledger-btn.primary { border-color:var(--vip-content-accent-dark, #856632); background:var(--vip-content-accent-dark, #856632); color:#fff; }
|
||||
@ -178,6 +191,11 @@
|
||||
@if ($activeAccountFilterCount > 0)
|
||||
<span class="ledger-filter-state" data-account-filter-state role="status" aria-live="polite" title="当前有 {{ $activeAccountFilterCount }} 个筛选条件生效"><span class="material-icons-outlined" aria-hidden="true">filter_alt</span><span>筛选中</span><b>{{ $activeAccountFilterCount }}</b></span>
|
||||
@endif
|
||||
<label class="ledger-edit-switch {{ $canEditAccounts ? '' : 'is-disabled' }}" title="{{ $canEditAccounts ? '开启后可修改账户类型和账户状态' : '当前账号没有财务台账编辑权限' }}">
|
||||
<span>编辑模式</span>
|
||||
<input type="checkbox" role="switch" aria-label="编辑模式" aria-checked="false" data-ledger-edit-mode-toggle @disabled(! $canEditAccounts)>
|
||||
<span class="ledger-edit-switch__track" aria-hidden="true"><span class="ledger-edit-switch__thumb"></span></span>
|
||||
</label>
|
||||
<div class="ledger-column-picker" data-ledger-column-picker data-column-storage-key="caiwu.financial-ledger.accounts.preferences.v1.{{ auth()->id() }}.{{ company_id() }}">
|
||||
<button class="ledger-btn" type="button" data-ledger-column-toggle aria-expanded="false"><span class="material-icons-outlined" aria-hidden="true">view_column</span>列设置</button>
|
||||
<div class="ledger-column-panel" data-ledger-column-panel role="group" aria-label="选择账户总表展示列" hidden>
|
||||
@ -205,25 +223,27 @@
|
||||
<td>{{ $row->account_short }}</td>
|
||||
<td>
|
||||
@if ($canEditAccountType)
|
||||
<select class="ledger-inline-select ledger-type-select" data-account-type data-account-short="{{ $row->account_short }}" data-url="{{ route('business.financial-ledger.accounts.type') }}" aria-label="账户 {{ $row->account_short }} 类型">
|
||||
<span class="ledger-account-readonly" data-account-edit-display data-account-type-display>{{ $row->account_type ?: '未填写' }}</span>
|
||||
<select class="ledger-inline-select ledger-type-select ledger-account-editor" data-account-editor data-account-type data-account-short="{{ $row->account_short }}" data-url="{{ route('business.financial-ledger.accounts.type') }}" aria-label="账户 {{ $row->account_short }} 类型" disabled>
|
||||
<option value="" @selected(($row->account_type ?? '') === '')>未填写</option>
|
||||
@foreach ($accountTypeOptions as $accountType)
|
||||
<option value="{{ $accountType }}" @selected($row->account_type === $accountType)>{{ $accountType }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@else
|
||||
{{ $row->account_type ?: '未填写' }}
|
||||
<span class="ledger-account-readonly">{{ $row->account_type ?: '未填写' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="ledger-status-column">
|
||||
@if ($canEditAccountStatus)
|
||||
<select class="ledger-inline-select ledger-status-select" data-account-status data-account-short="{{ $row->account_short }}" data-status="{{ $row->account_status }}" data-url="{{ route('business.financial-ledger.accounts.status') }}" aria-label="账户 {{ $row->account_short }} 状态">
|
||||
<span class="ledger-status-badge ledger-account-readonly" data-account-edit-display data-account-status-display data-status="{{ $row->account_status }}">{{ $accountStatusOptions[$row->account_status] ?? '正常' }}</span>
|
||||
<select class="ledger-inline-select ledger-status-select ledger-account-editor" data-account-editor data-account-status data-account-short="{{ $row->account_short }}" data-status="{{ $row->account_status }}" data-url="{{ route('business.financial-ledger.accounts.status') }}" aria-label="账户 {{ $row->account_short }} 状态" disabled>
|
||||
@foreach ($accountStatusOptions as $statusCode => $statusLabel)
|
||||
<option value="{{ $statusCode }}" @selected($row->account_status === $statusCode)>{{ $statusLabel }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@else
|
||||
<span class="ledger-status-badge" data-status="{{ $row->account_status }}">{{ $accountStatusOptions[$row->account_status] ?? '正常' }}</span>
|
||||
<span class="ledger-status-badge ledger-account-readonly" data-status="{{ $row->account_status }}">{{ $accountStatusOptions[$row->account_status] ?? '正常' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $row->region }}</td><td>{{ $row->account_no }}</td><td>{{ $row->bank_name }}</td><td>{{ $row->bank_city_branch }}</td>
|
||||
@ -415,6 +435,19 @@
|
||||
});
|
||||
|
||||
const accountPanel = page.querySelector('#ledger-panel-accounts');
|
||||
const accountEditToggle = page.querySelector('[data-ledger-edit-mode-toggle]');
|
||||
const applyAccountEditMode = (enabled) => {
|
||||
const active = Boolean(enabled && accountEditToggle && !accountEditToggle.disabled);
|
||||
accountPanel?.classList.toggle('is-account-edit-mode', active);
|
||||
accountPanel?.querySelectorAll('[data-account-editor]').forEach((editor) => {
|
||||
editor.disabled = !active;
|
||||
});
|
||||
accountEditToggle?.setAttribute('aria-checked', active ? 'true' : 'false');
|
||||
};
|
||||
accountEditToggle?.addEventListener('change', () => {
|
||||
applyAccountEditMode(accountEditToggle.checked);
|
||||
notify(accountEditToggle.checked ? '编辑模式已开启' : '编辑模式已关闭');
|
||||
});
|
||||
const accountColumnPicker = page.querySelector('[data-ledger-column-picker]');
|
||||
const accountColumnPanel = accountColumnPicker?.querySelector('[data-ledger-column-panel]');
|
||||
const accountColumnOptions = accountColumnPicker?.querySelector('[data-ledger-column-options]');
|
||||
@ -749,6 +782,11 @@
|
||||
item.value = value;
|
||||
item.dataset.previousValue = value;
|
||||
if (field === 'status') item.dataset.status = value;
|
||||
const display = item.closest('td')?.querySelector('[data-account-edit-display]');
|
||||
if (display) {
|
||||
display.textContent = payload.label || (value || '未填写');
|
||||
if (field === 'status') display.dataset.status = value;
|
||||
}
|
||||
});
|
||||
notify(successLabel + ':' + (payload.label || ''));
|
||||
} catch (error) {
|
||||
@ -764,6 +802,7 @@
|
||||
};
|
||||
bindInlineAccountSelect('[data-account-status]', 'status', '账户状态已保存');
|
||||
bindInlineAccountSelect('[data-account-type]', 'account_type', '账户类型已保存');
|
||||
applyAccountEditMode(accountEditToggle?.checked === true);
|
||||
|
||||
let accountPageRequest = null;
|
||||
const bindAccountPagination = () => {
|
||||
@ -825,6 +864,7 @@
|
||||
}
|
||||
bindInlineAccountSelect('[data-account-status]', 'status', '账户状态已保存');
|
||||
bindInlineAccountSelect('[data-account-type]', 'account_type', '账户类型已保存');
|
||||
applyAccountEditMode(accountEditToggle?.checked === true);
|
||||
applyAccountColumnLayout();
|
||||
bindAccountPagination();
|
||||
notify(targetPage ? '已加载第 ' + targetPage + ' 页' : '下一页已加载');
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace Tests\Feature\Business;
|
||||
|
||||
use App\Models\Auth\Permission;
|
||||
use App\Models\Auth\Role;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Tests\Feature\FeatureTestCase;
|
||||
|
||||
@ -78,6 +79,10 @@ class FinanceLedgerAccountStatusTest extends FeatureTestCase
|
||||
->assertSee('1 / 1', false)
|
||||
->assertSee('data-ledger-column-picker', false)
|
||||
->assertSee('data-ledger-column-panel', false)
|
||||
->assertSee('data-ledger-edit-mode-toggle', false)
|
||||
->assertSee('aria-checked="false"', false)
|
||||
->assertSee('ledger-account-editor', false)
|
||||
->assertSee('data-account-edit-display', false)
|
||||
->assertSee('列设置')
|
||||
->assertSee('拖动字段可调整列顺序')
|
||||
->assertSee('恢复默认')
|
||||
@ -325,8 +330,16 @@ class FinanceLedgerAccountStatusTest extends FeatureTestCase
|
||||
'created_from' => 'core::test',
|
||||
]);
|
||||
$viewer->companies()->attach($this->company->id);
|
||||
$viewer->roles()->attach(Role::where('name', 'user')->firstOrFail()->id);
|
||||
$viewer->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
||||
|
||||
$this->loginAs($viewer)->get($this->pageUrl())
|
||||
->assertOk()
|
||||
->assertSee('data-ledger-edit-mode-toggle', false)
|
||||
->assertSee('当前账号没有财务台账编辑权限')
|
||||
->assertDontSee('data-account-status data-account-short', false)
|
||||
->assertDontSee('data-account-type data-account-short', false);
|
||||
|
||||
$this->withExceptionHandling()->loginAs($viewer)->postJson($this->statusUrl(), [
|
||||
'account_short' => '测试账户',
|
||||
'status' => 'limited',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user