【市区マスタ】新規、編集画面修正
All checks were successful
Deploy main / deploy (push) Successful in 24s

This commit is contained in:
你的名字 2025-10-08 22:45:23 +09:00
parent 1cf94bc8aa
commit 1d5db12a27
5 changed files with 305 additions and 86 deletions

View File

@ -12,12 +12,9 @@ class CityController extends Controller
{
public function list(Request $request)
{
$inputs = [
'isMethodPost' => $request->isMethod('post'),
'sort' => $request->input('sort', ''),
'sort_type' => $request->input('sort_type', ''),
'page' => $request->get('page', 1),
];
$sort = $request->input('sort', 'city_id');
$sortType = $request->input('sort_type', 'asc');
$page = $request->get('page', 1);
$query = City::query();
@ -25,17 +22,28 @@ class CityController extends Controller
$query->where('city_name', 'like', '%' . $request->input('city_name') . '%');
}
if (!empty($inputs['sort'])) {
$query->orderBy($inputs['sort'], $inputs['sort_type'] ?? 'asc');
// 排序处理
if (!empty($sort)) {
$query->orderBy($sort, $sortType);
}
$inputs['list'] = $query->paginate(20);
$list = $query->paginate(20);
if ($inputs['list']->total() > 0 && $inputs['page'] > $inputs['list']->lastPage()) {
return redirect()->route('city');
// 页码越界处理
if ($list->total() > 0 && $page > $list->lastPage()) {
return redirect()->route('city', [
'sort' => $sort,
'sort_type' => $sortType,
]);
}
return view('admin.CityMaster.list', $inputs);
return view('admin.CityMaster.list', [
'isMethodPost' => $request->isMethod('post'),
'sort' => $sort,
'sort_type' => $sortType,
'list' => $list,
'page' => $page,
]);
}
public function add(Request $request)
@ -49,10 +57,10 @@ class CityController extends Controller
if ($request->isMethod('POST')) {
$rules = [
'city_name' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], // 全角のみ
'print_layout' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], // 全角のみ
'city_user' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], // 全角のみ
'city_remarks' => ['nullable', 'string', 'max:20'], // 全角半角可・任意
'city_name' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'],
'print_layout' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'],
'city_user' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'],
'city_remarks' => ['nullable', 'string', 'max:20'],
];
$messages = [
'city_name.required' => '市区名は必須です。',
@ -163,4 +171,4 @@ class CityController extends Controller
return redirect()->route('city')->with('error', __('削除に失敗しました。'));
}
}
}
}

View File

@ -1,24 +1,53 @@
<div class="form-group">
<label for="city_id">市区ID</label>
<input type="text" name="city_id" id="city_id" class="form-control" value="{{ old('city_id', $city->city_id ?? '') }}" readonly>
</div>
@php
$city = $city ?? null;
@endphp
<div class="form-group">
<label for="city_name">市区名 <span class="text-danger">*</span></label>
<input type="text" name="city_name" id="city_name" class="form-control" value="{{ old('city_name', $city->city_name ?? '') }}" required maxlength="10" pattern="[^ -~。-゚]+" title="全角で入力してください">
</div>
<div class="rv-city-form-fields">
<div class="form-group row rv-city-field align-items-center">
<div class="form-group col-12 col-md-3 mb-2 mb-md-0">
<label for="city_name" class="col-form-label fw-semibold rv-city-label mb-0">
{{ __('市区名') }}<span class="text-danger">*</span>
</label>
</div>
<div class="form-group col-12 col-md-9 mb-0">
<input type="text" name="city_name" id="city_name" class="form-control"
value="{{ old('city_name', optional($city)->city_name) }}" maxlength="50" placeholder="市区名">
</div>
</div>
<div class="form-group">
<label for="print_layout">印字レイアウトファイル <span class="text-danger">*</span></label>
<input type="text" name="print_layout" id="print_layout" class="form-control" value="{{ old('print_layout', $city->print_layout ?? '') }}" required maxlength="10" pattern="[^ -~。-゚]+" title="全角で入力してください">
</div>
<div class="form-group row rv-city-field align-items-center">
<div class="form-group col-12 col-md-3 mb-2 mb-md-0">
<label for="print_layout" class="col-form-label fw-semibold rv-city-label mb-0">
{{ __('印字レイアウトファイル') }}<span class="text-danger">*</span>
</label>
</div>
<div class="form-group col-12 col-md-9 mb-0">
<input type="text" name="print_layout" id="print_layout" class="form-control"
value="{{ old('print_layout', optional($city)->print_layout) }}" maxlength="100" placeholder="印字レイアウトファイル">
</div>
</div>
<div class="form-group">
<label for="city_user">顧客M入力不要フィールドID <span class="text-danger">*</span></label>
<input type="text" name="city_user" id="city_user" class="form-control" value="{{ old('city_user', $city->city_user ?? '') }}" required maxlength="10" pattern="[^ -~。-゚]+" title="全角で入力してください">
</div>
<div class="form-group row rv-city-field align-items-center">
<div class="form-group col-12 col-md-3 mb-2 mb-md-0">
<label for="city_user" class="col-form-label fw-semibold rv-city-label mb-0">
{{ __('顧客M入力不要フィールドID') }}
</label>
</div>
<div class="form-group col-12 col-md-9 mb-0">
<input type="text" name="city_user" id="city_user" class="form-control"
value="{{ old('city_user', optional($city)->city_user) }}" maxlength="50" placeholder="顧客M入力不要フィールドID">
</div>
</div>
<div class="form-group">
<label for="city_remarks">備考</label>
<textarea name="city_remarks" id="city_remarks" class="form-control" rows="3" maxlength="20">{{ old('city_remarks', $city->city_remarks ?? '') }}</textarea>
<div class="form-group row rv-city-field align-items-center">
<div class="form-group col-12 col-md-3 mb-2 mb-md-0">
<label for="city_remarks" class="col-form-label fw-semibold rv-city-label mb-0">
{{ __('備考') }}
</label>
</div>
<div class="form-group col-12 col-md-9 mb-0">
<textarea name="city_remarks" id="city_remarks" rows="3" class="form-control"
maxlength="200" placeholder="備考">{{ old('city_remarks', optional($city)->city_remarks) }}</textarea>
</div>
</div>
</div>

View File

@ -1,27 +1,120 @@
{{-- filepath: c:\xampp82\htdocs\somanager-git_main\resources\views\admin\CityMaster\add.blade.php --}}
@extends('layouts.app')
@section('content')
<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center mb-3">
<h3 class="mb-0">新規登録</h3>
<ol class="breadcrumb float-sm-right text-sm mb-0" style="background: #f8f9fa;">
<li class="breadcrumb-item"><a href="{{ url('/home') }}">ホーム</a></li>
<li class="breadcrumb-item"><a href="{{ route('city') }}">市区マスタ</a></li>
<li class="breadcrumb-item active">新規</li>
</ol>
</div>
<div class="card shadow mb-4">
<div class="card-body">
<form method="POST" action="{{ route('city_add') }}">
<div class="d-flex flex-column flex-md-row align-items-md-center justify-content-between mb-3 gap-2">
<h2 class="mb-0 fw-bold">{{ __('新規') }}</h2>
<ol class="breadcrumb float-md-right text-sm mb-0 bg-transparent">
<li class="breadcrumb-item"><a href="{{ url('/home') }}">ホーム</a></li>
<li class="breadcrumb-item"><a href="{{ route('city') }}">市区マスタ</a></li>
<li class="breadcrumb-item active">新規</li>
</ol>
</div>
@php($errorMessages = $errorMsg ?? [])
@if(!empty($errorMessages))
<div class="alert alert-danger">
<ul class="mb-0">
@foreach($errorMessages as $message)
<li>{{ $message }}</li>
@endforeach
</ul>
</div>
@endif
<div class="card shadow-sm">
<div class="card-header bg-white py-3 d-flex justify-content-start">
<button type="submit" form="city-form" class="btn btn-lg btn-default mr-2 register">{{ __('登録') }}</button>
</div>
<div class="card-body py-4">
<form id="city-form" class="city-form" method="POST" action="{{ route('city_add') }}">
@csrf
@include('admin.CityMaster._form', ['isEdit' => 0, 'isInfo' => 0])
<div class="mt-3">
<button type="submit" class="btn btn-primary" onclick="return confirm('登録してよろしいですか?');">登録</button>
<a href="{{ route('city') }}" class="btn btn-secondary">戻る</a>
<div class="d-flex flex-column flex-md-row align-items-md-center gap-3 mt-4">
<button type="submit" class="btn btn-lg btn-default mr-2 register">{{ __('登録') }}</button>
<a href="{{ route('city') }}" class="btn btn-lg btn-default">{{ __('戻る') }}</a>
</div>
</form>
</div>
</div>
</div>
@endsection
@endsection
@push('styles')
<style>
.city-form .form-group {
display: flex;
align-items: center;
gap: 1.5rem;
margin-bottom: 1.5rem;
}
.city-form .form-group .form-label {
flex: 0 0 180px;
margin-bottom: 0;
font-weight: 600;
color: #333;
}
.city-form .form-group .form-control {
flex: 1 1 auto;
}
@media (max-width: 767.98px) {
.city-form .form-group {
flex-direction: column;
align-items: stretch;
}
.city-form .form-group .form-label {
flex: none;
width: 100%;
}
}
</style>
@endpush
@push('scripts')
<script>
(function ($) {
$(function () {
var validationErrors = @json($errorMessages);
if (validationErrors.length) {
var message = validationErrors.join('\n');
if ($.alert) {
$.alert({ title: 'エラー', content: message });
} else {
window.alert(message);
}
}
$('.register').off('click.cityConfirm').on('click.cityConfirm', function (e) {
e.preventDefault();
const formId = this.getAttribute('form');
const $form = formId ? $('#' + formId) : $('#city-form');
if (!$form.length) { return; }
const submit = function () {
if (typeof $form[0].requestSubmit === 'function') {
$form[0].requestSubmit();
} else {
$form.trigger('submit');
}
};
if ($.confirm) {
$.confirm({
title: '確認ダイアログ',
content: '登録してよろしいですか? はい/いいえ',
buttons: {
ok: { text: 'はい', btnClass: 'btn-primary', action: submit },
いいえ: function () {}
}
});
} else if (window.confirm('登録してよろしいですか?')) {
submit();
}
});
});
})(window.jQuery);
</script>
@endpush

View File

@ -30,8 +30,8 @@
])
<div class="mt-3">
<button type="submit" class="btn btn-primary">更新</button>
<a href="{{ route('city') }}" class="btn btn-secondary">戻る</a>
<button type="button" class="btn btn-default register">登録</button>
<a href="{{ route('city') }}" class="btn btn-default">戻る</a>
</div>
</form>
</div>
@ -39,3 +39,36 @@
</div>
</section>
@endsection
@push('scripts')
<script>
(function ($) {
$(function () {
var $form = $('form[action="{{ route('city_edit', ['id' => $city->city_id]) }}"]');
$('.register').off('click.cityConfirm').on('click.cityConfirm', function (e) {
e.preventDefault();
if (!$form.length) { return; }
var submit = function () {
if (typeof $form[0].requestSubmit === 'function') {
$form[0].requestSubmit();
} else {
$form.trigger('submit');
}
};
if ($.confirm) {
$.confirm({
title: '確認ダイアログ',
content: '登録してよろしいですか? はい/いいえ',
buttons: {
ok: { text: 'はい', btnClass: 'btn-primary', action: submit },
いいえ: function () {}
}
});
} else if (window.confirm('登録してよろしいですか?')) {
submit();
}
});
});
})(window.jQuery);
</script>
@endpush

View File

@ -31,38 +31,50 @@
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<form id="list-form" method="GET" action="{{ route('city') }}">
<input type="hidden" name="sort" value="{{ $sort }}">
<input type="hidden" name="sort_type" value="{{ $sort_type }}">
<!-- Action Buttons -->
<div class="mb-3">
<a href="{{ route('city_add') }}" class="btn btn-sm btn-primary">新規</a>
<button type="submit" form="deleteForm" class="btn btn-sm btn-danger"
onclick="return confirm('選択した市区を削除しますか?');">削除</button>
</form>
<div class="d-flex flex-column flex-md-row align-items-md-center justify-content-between mb-3 gap-2">
<div>
<a href="{{ route('city_add') }}" class="btn btn-sm btn-default">新規</a>
<button type="button" id="delete" class="btn btn-sm btn-default">削除</button>
</div>
@if ($list->count() > 0)
<div class="mt-2 mt-md-0 ms-md-3">
{{ $list->appends([
'sort' => $sort,
'sort_type' => $sort_type,
] + request()->except('page'))->links('pagination::bootstrap-4') }}
</div>
@endif
</div>
@if ($list->count() > 0)
<form id="deleteForm" method="POST" action="{{ route('city_delete') }}">
<form id="form_delete" method="POST" action="{{ route('city_delete') }}">
@csrf
<div class="table-responsive ">
<table class="table table-bordered table-hover" >
<thead class="thead-light ">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead class="thead-light">
<tr>
<th><input type="checkbox"
onclick="$('input[name*=\'pk\']').prop('checked', this.checked);"></th>
<th>
<a href="{{ route('city', array_merge(request()->all(), ['sort' => 'city_id', 'sort_type' => $sort === 'city_id' && $sort_type === 'asc' ? 'desc' : 'asc'])) }}">
市区ID
@if($sort === 'city_id')
<i class="fa fa-sort-{{ $sort_type }}"></i>
@endif
</a>
<th><input type="checkbox" class="js-check-all"></th>
<th class="sorting{{ $sort === 'city_id' ? ($sort_type === 'asc' ? '_asc' : '_desc') : '' }}"
sort="city_id">
市区ID
@if($sort === 'city_id')
<i class="fa fa-arrow-up ms-1" style="font-size: 0.7em; color: {{ $sort && $sort_type ? 'black' : '#ccc' }}"></i>
<i class="fa fa-arrow-down ms-1" style="font-size: 0.7em; color: {{ $sort && !$sort_type ? 'black' : '#ccc' }}"></i>
@endif
</th>
<th>
<a href="{{ route('city', array_merge(request()->all(), ['sort' => 'city_name', 'sort_type' => $sort === 'city_name' && $sort_type === 'asc' ? 'desc' : 'asc'])) }}">
市区名
@if($sort === 'city_name')
<i class="fa fa-sort-{{ $sort_type }}"></i>
@endif
</a>
<th class="sorting{{ $sort === 'city_name' ? ($sort_type === 'asc' ? '_asc' : '_desc') : '' }}"
sort="city_name">
市区名
@if($sort === 'city_name')
<i class="fa fa-arrow-up ms-1" style="font-size: 0.7em; color: {{ $sort && $sort_type ? 'black' : '#ccc' }}"></i>
<i class="fa fa-arrow-down ms-1" style="font-size: 0.7em; color: {{ $sort && !$sort_type ? 'black' : '#ccc' }}"></i>
@endif
</th>
<th>印字レイアウトファイル</th>
<th>顧客M入力不要フィールドID</th>
@ -72,9 +84,10 @@
<tbody>
@foreach ($list as $city)
<tr>
<td style="background: #faebd7; width:100px; padding-right:4px; padding-left:4px;">
<td style="background: #faebd7; width: 110px; padding: 0 4px;">
<input type="checkbox" name="pk[]" value="{{ $city->city_id }}">
<a href="{{ route('city_edit', ['id' => $city->city_id]) }}" class="btn btn-sm btn-default" style="margin-left:4px;">編集</a>
<a href="{{ route('city_edit', ['id' => $city->city_id]) }}"
class="btn btn-sm btn-default ms-1">編集</a>
</td>
<td>{{ $city->city_id }}</td>
<td>{{ $city->city_name }}</td>
@ -87,13 +100,56 @@
</table>
</div>
</form>
<div class="mt-3">
{{ $list->appends(request()->except('page'))->links('pagination::bootstrap-4') }}
</div>
@else
<div class="alert alert-info mt-4">表示する市区データがありません。</div>
@endif
</div>
</section>
@endsection
@endsection
@push('scripts')
<script>
(function ($) {
$(function () {
var $form = $('#form_delete');
if (!$form.length) { return; }
$(document)
.off('change.cityCheckAll', '.js-check-all')
.on('change.cityCheckAll', '.js-check-all', function () {
var checked = $(this).prop('checked');
$form.find('input[name="pk[]"]').prop('checked', checked);
});
$(document)
.off('click.cityDeleteGuard', '#delete')
.on('click.cityDeleteGuard', '#delete', function (event) {
if (!$form.find('input[name="pk[]"]:checked').length) {
event.preventDefault();
event.stopImmediatePropagation();
window.alert('削除対象を選択してください。');
}
});
});
})(window.jQuery);
$(document).on('click', 'th[sort]', function () {
const $form = $('#list-form');
const sortKey = $(this).attr('sort');
const currentSort = $form.find('input[name="sort"]').val();
const currentType = $form.find('input[name="sort_type"]').val();
if (currentSort === sortKey) {
// 切换方向
const newType = currentType === 'asc' ? 'desc' : 'asc';
$form.find('input[name="sort_type"]').val(newType);
} else {
// 新字段,默认升序
$form.find('input[name="sort"]').val(sortKey);
$form.find('input[name="sort_type"]').val('asc');
}
$form.submit();
});
</script>
@endpush