神祖牌位管理模組,掛單模組前端URL添加HTTP_HOST
This commit is contained in:
908
web/admin/ancestraltablet/ancestraltabletarea/index.aspx
Normal file
908
web/admin/ancestraltablet/ancestraltabletarea/index.aspx
Normal file
@@ -0,0 +1,908 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="admin_ancestraltablet_ancestraltabletarea_index" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||
<nav class="mb-2 ps-3">
|
||||
<button class="btn btn-primary me-2" type="button" @click="showNewtAreadialogMethod">
|
||||
<i class="mdi mdi-plus"></i> 新增區域
|
||||
</button>
|
||||
<button class="btn btn-secondary me-2" @click="expandAll" type="button">
|
||||
<i class="mdi mdi-arrow-expand-all"></i> 全部展開
|
||||
</button>
|
||||
<button class="btn btn-secondary" @click="collapseAll" type="button">
|
||||
<i class="mdi mdi-arrow-collapse-all"></i> 全部收起
|
||||
</button>
|
||||
</nav>
|
||||
<nav>
|
||||
<button type="button" class="btn btn-primary" @click="toggleAreaData">
|
||||
{{ showAreaDataFlag ? '隱藏區域資料' : '顯示區域資料' }}
|
||||
</button>
|
||||
</nav>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-lg-3">
|
||||
<div class="card shadow-sm my-2">
|
||||
<div class="card-header">神主牌區域列表</div>
|
||||
<div class="card-body">
|
||||
<ul class="tree">
|
||||
<li v-for="area in ancestral_tablet_areas" :key="area.AreaId">
|
||||
<region-item
|
||||
:item="area"
|
||||
:selected-id="currentSelectAreaId"
|
||||
@select-area="selectAreaMethod"
|
||||
:expand-all="expandAllFlag"
|
||||
:collapse-all="collapseAllFlag"
|
||||
@clear-expand-all="expandAllFlag = false"
|
||||
@clear-collapse-all="collapseAllFlag = false"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 col-lg-9" v-if="currentSelectArea && showAreaDataFlag">
|
||||
<div class="card shadow-sm my-2"style="position: sticky; top: 20px;">
|
||||
<div class="card-header" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div>
|
||||
<span class="fw-bold">
|
||||
{{ ' ' + currentSelectArea?.areaName + ' ' }}
|
||||
</span>
|
||||
<span>
|
||||
資料
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-primary" type="button" @click="showEidtAreadialogMethod">
|
||||
編輯
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域名稱</label>
|
||||
<input v-model="currentSelectArea.areaName" type="text" class="form-control" readonly/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域編號</label>
|
||||
<input v-model="currentSelectArea.areaCode" type="text" class="form-control" readonly/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>上層區域(可選)</label>
|
||||
<input v-model="currentSelectArea.parentAreaId" type="text" class="form-control" readonly />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域類型(可空)</label>
|
||||
<input v-model="currentSelectArea.areaType" type="text" class="form-control" readonly/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>價格</label>
|
||||
<input v-model="currentSelectArea.price" class="form-control" readonly/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>排序</label>
|
||||
<input v-model="currentSelectArea.sortOrder" class="form-control" readonly/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<div style="display: flex; align-items: center; height: 100%; margin-top: 8px;">
|
||||
<input
|
||||
v-model="currentSelectArea.isDisabled"
|
||||
type="checkbox"
|
||||
disabled
|
||||
id="disabledToggle"
|
||||
style="width: 20px; height: 20px; margin-right: 8px; cursor: pointer;"
|
||||
/>
|
||||
<label
|
||||
for="disabledToggle"
|
||||
style="font-weight: bold; font-size: 14px; color: #333; margin: 0;"
|
||||
>
|
||||
是否停用
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-3">
|
||||
<label>描述</label>
|
||||
<textarea v-model="currentSelectArea.description" rows="3" class="form-control" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 col-lg-9" v-if="currentSelectArea">
|
||||
<div class="card shadow-sm my-2" style="flex: 1 1 auto; min-height: 0; overflow: auto;">
|
||||
<div class="card-header" style="display: flex; justify-content: space-between; align-items: center;background-color: #ffc107;">
|
||||
<div>
|
||||
{{currentSelectArea.areaName + ' - ' + '神主牌位置'}}
|
||||
</div>
|
||||
<div>
|
||||
<v-btn color="primary" @click="openNewPositionDialogMethod">批次新增神主牌位置</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="grid-container">
|
||||
<div
|
||||
v-for="pos in positions"
|
||||
:key="pos.positionCode"
|
||||
class="grid-item"
|
||||
:class="'status-' + pos.statusCode"
|
||||
:style="{ gridRow: pos.rowNo, gridColumn: pos.columnNo }"
|
||||
>
|
||||
<div class="position-name">{{ pos.positionName }}</div>
|
||||
<div class="position-content">
|
||||
<!-- 這裡可以放更多資訊,比如價格或狀態 -->
|
||||
<!-- 例如:價格: {{ pos.price }} -->
|
||||
<v-btn small @click="editPositionMethod(pos)">修改</v-btn>
|
||||
<v-btn small @click="deletePositionMethod(pos)">刪除</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 新增區域彈出視窗 -->
|
||||
<div>
|
||||
<v-dialog v-model="showNewAreadialogFlag" max-width="1200px">
|
||||
<v-card
|
||||
style="min-height: 50vh; max-height: 80vh; overflow-y: auto;"
|
||||
>
|
||||
<v-card-title>
|
||||
<span class="headline">新增區域</span>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域名稱</label>
|
||||
<input v-model="newArea.areaName" type="text" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域編號</label>
|
||||
<input v-model="newArea.areaCode" type="text" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>上層區域(可選)</label>
|
||||
<select v-model="newArea.parentAreaId" class="form-control" >
|
||||
<option value="">請選擇</option>
|
||||
<!-- 手動添加選項 -->
|
||||
<option v-for="r in flatAreas"
|
||||
:value="r.areaId"
|
||||
:disabled="disabledParentOptions.includes(r.areaId)">{{ r.areaName }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域類型(可空)</label>
|
||||
<input type="text" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>價格</label>
|
||||
<input v-model="newArea.price" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>排序</label>
|
||||
<input v-model="newArea.sortOrder" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<div style="display: flex; align-items: center; height: 100%; margin-top: 8px;">
|
||||
<input
|
||||
v-model="newArea.isDisabled"
|
||||
type="checkbox"
|
||||
style="width: 20px; height: 20px; margin-right: 8px; cursor: pointer;"
|
||||
/>
|
||||
<label
|
||||
for="disabledToggle"
|
||||
style="font-weight: bold; font-size: 14px; color: #333; margin: 0;"
|
||||
>
|
||||
是否停用
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-3">
|
||||
<label>描述</label>
|
||||
<textarea v-model="newArea.description" rows="3" class="form-control" ></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="grey" text @click="closeNewAreadialogMethod">取消</v-btn>
|
||||
<v-btn color="primary" @click="createNewAreaMethod">確定新增</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
<!-- 編輯區域彈出視窗 -->
|
||||
<div>
|
||||
<v-dialog v-model="showEidtAreadialogFlag" max-width="1200px">
|
||||
<v-card
|
||||
style="min-height: 50vh; max-height: 80vh; overflow-y: auto;"
|
||||
>
|
||||
<v-card-title>
|
||||
<span class="headline">編輯區域</span>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域名稱</label>
|
||||
<input v-model="editArea.areaName" type="text" class="form-control" required />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域編號</label>
|
||||
<input v-model="editArea.areaCode" type="text" class="form-control" required />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>上層區域(可選)</label>
|
||||
<select v-model="editArea.parentAreaId" class="form-control" >
|
||||
<option value="">請選擇</option>
|
||||
<!-- 手動添加選項 -->
|
||||
<option v-for="r in flatAreas"
|
||||
:value="r.areaId"
|
||||
:disabled="disabledParentOptions.includes(r.areaId)">{{ r.areaName }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>區域類型(可空)</label>
|
||||
<input v-model="editArea.areaType" type="text" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>價格</label>
|
||||
<input v-model="editArea.price" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label>排序</label>
|
||||
<input v-model="editArea.sortOrder" class="form-control" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<div style="display: flex; align-items: center; height: 100%; margin-top: 8px;">
|
||||
<input
|
||||
v-model="editArea.isDisabled"
|
||||
type="checkbox"
|
||||
id="disabledToggle1"
|
||||
style="width: 20px; height: 20px; margin-right: 8px; cursor: pointer;"
|
||||
/>
|
||||
<label
|
||||
for="disabledToggle"
|
||||
style="font-weight: bold; font-size: 14px; color: #333; margin: 0;"
|
||||
>
|
||||
是否停用
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-3">
|
||||
<label>描述</label>
|
||||
<textarea v-model="editArea.description" rows="3" class="form-control" ></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="grey" text @click="closeEidtAreadialogMethod">取消</v-btn>
|
||||
<v-btn color="primary" @click="editAreaMethod">送出修改</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
<!-- 批次新增神主牌彈出視窗 -->
|
||||
<div>
|
||||
<!-- 彈出視窗組件 -->
|
||||
<v-dialog v-model="showNewPositionDialogFlag" max-width="800px">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
批次新增神主牌位置
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="closeNewPositionDialogMethod">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<div class="card p-3 mt-4">
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<label>起始行</label>
|
||||
<input v-model.number="batchPositionForm.startRow" type="number" class="form-control" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<label>起始列</label>
|
||||
<input v-model.number="batchPositionForm.startCol" type="number" class="form-control" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<label>行數</label>
|
||||
<input v-model.number="batchPositionForm.rows" type="number" class="form-control" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<label>列數</label>
|
||||
<input v-model.number="batchPositionForm.cols" type="number" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<label>價格</label>
|
||||
<input v-model.number="batchPositionForm.price" type="number" class="form-control" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<label>狀態</label>
|
||||
<select v-model="batchPositionForm.status" class="form-control">
|
||||
<option v-for="s in statusList" :key="s.statusCode" :value="s.statusCode">
|
||||
{{ s.statusName }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label>Name模板</label>
|
||||
<input v-model="batchPositionForm.nameTemplate" class="form-control" placeholder="如:神位編號{code}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<label>Code起始值</label>
|
||||
<input v-model.number="batchPositionForm.startCode" type="number" class="form-control" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<label>Code長度</label>
|
||||
<input v-model.number="batchPositionForm.codeLength" type="number" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="previewPositions.length">
|
||||
<h3>預覽新增位置</h3>
|
||||
<ul>
|
||||
<li v-for="pos in previewPositions" :key="pos.PositionCode">
|
||||
{{ pos.PositionCode }} - {{ pos.PositionName }} (行: {{ pos.RowNo }}, 列: {{ pos.ColumnNo }})
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions class="justify-end">
|
||||
<v-btn color="primary" @click="generatePositionsMethod">生成預覽</v-btn>
|
||||
<v-btn color="pirmary" @click="clearPreviewPositionsMethod">清除預覽</v-btn>
|
||||
<v-btn color="primary" @click="confirmAddPositionsMethod">確認新增</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
<!-- 編輯牌位位置彈出視窗 -->
|
||||
<div v-if="currentEditPosition">
|
||||
<v-dialog v-model="editPositionFormVisible" max-width="500">
|
||||
<v-card>
|
||||
<v-card-title class="text-h6">
|
||||
編輯位置:{{ currentEditPosition?.positionName || '未選擇' }}
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<div class="form-row">
|
||||
<label>位置名稱:</label>
|
||||
<input v-model="currentEditPosition.positionName" class="form-control" />
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label>價格:</label>
|
||||
<input v-model="currentEditPosition.price" type="number" class="form-control" />
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label>狀態:</label>
|
||||
<select v-model="currentEditPosition.statusCode" class="form-control">
|
||||
<option v-for="s in statusList" :key="s.statusCode" :value="s.statusCode">
|
||||
{{ s.statusName }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" @click="saveEditPositionMethod">保存</v-btn>
|
||||
<v-btn text @click="editPositionFormVisible = false">取消</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
</div>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||
<script>
|
||||
Vue.component('region-item', {
|
||||
props: ['item', 'selectedId', 'expandAll', 'collapseAll'],
|
||||
data() {
|
||||
return {
|
||||
expanded: false, // 預設全部收起
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
expandAll(newVal) {
|
||||
if (newVal) {
|
||||
this.expanded = true;
|
||||
// 執行完後發事件通知父組件清除標誌
|
||||
this.$nextTick(() => this.$emit('clear-expand-all'));
|
||||
}
|
||||
},
|
||||
collapseAll(newVal) {
|
||||
if (newVal) {
|
||||
this.expanded = false;
|
||||
this.$nextTick(() => this.$emit('clear-collapse-all'));
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasChildren() {
|
||||
return this.item.children && this.item.children.length > 0;
|
||||
},
|
||||
icon() {
|
||||
// 無論有無子節點,皆可點擊展開/收起
|
||||
return this.expanded ? '▼' : '▶';
|
||||
},
|
||||
isSelected() {
|
||||
return this.item.areaId === this.selectedId;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.expanded = !this.expanded;
|
||||
},
|
||||
select() {
|
||||
this.$emit('select-area', this.item);
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<span class="toggle-icon" @click="toggle">{{ icon }}</span>
|
||||
<span @click="select"
|
||||
class="region-item-label"
|
||||
:class="{ 'selected': isSelected }">
|
||||
{{ item.areaName }}
|
||||
</span>
|
||||
|
||||
<!-- 子區域列表 -->
|
||||
<ul v-if="hasChildren && expanded">
|
||||
<li v-for="child in item.children" :key="child.areaId">
|
||||
<region-item
|
||||
:item="child"
|
||||
:selected-id="selectedId"
|
||||
:expand-all="expandAll"
|
||||
:collapse-all="collapseAll"
|
||||
@select-area="$emit('select-area', $event)"
|
||||
@clear-expand-all="$emit('clear-expand-all')"
|
||||
@clear-collapse-all="$emit('clear-collapse-all')"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
new Vue({
|
||||
el: '#app',
|
||||
vuetify: new Vuetify(vuetify_options),
|
||||
data() {
|
||||
return {
|
||||
expandAllFlag: false, // 控制全部展開
|
||||
collapseAllFlag: false, // 控制全部收起
|
||||
ancestral_tablet_areas: [], //神主牌區域列表
|
||||
currentSelectArea: null,
|
||||
currentSelectAreaId: null,
|
||||
showEidtAreadialogFlag: false,
|
||||
showNewAreadialogFlag: false,
|
||||
showAreaDataFlag: false,//是否顯示區域資料
|
||||
flatAreas: [],//所有區域展平
|
||||
disabledParentOptions: [],//某個區域禁止選擇作為父區域的函數
|
||||
newArea: {
|
||||
areaId: null, // 自增主鍵,新增時通常為 null
|
||||
areaName: null, // 區域名稱,必填
|
||||
areaCode: null, // 區域編號,必填
|
||||
parentAreaId: null, // 上層區域 ID,可為 null
|
||||
areaType: null, // 區域類型,可空
|
||||
price: null, // 價格,可空
|
||||
sortOrder: null, // 排序,可空
|
||||
description: null, // 區域描述
|
||||
isDisabled: null
|
||||
},
|
||||
editArea: {
|
||||
areaId: null, // 自增主鍵,新增時通常為 null
|
||||
areaName: null, // 區域名稱,必填
|
||||
areaCode: null, // 區域編號,必填
|
||||
parentAreaId: null, // 上層區域 ID,可為 null
|
||||
areaType: null, // 區域類型,可空
|
||||
price: null, // 價格,可空
|
||||
sortOrder: null, // 排序,可空
|
||||
description: null, // 區域描述
|
||||
isDisabled: null
|
||||
},
|
||||
statusList: [],
|
||||
//--------------------------------神主牌位置變數
|
||||
showNewPositionDialogFlag: false,//控制是否顯示批次新增神主牌彈出視窗
|
||||
editPositionFormVisible: false, // 控制是否顯示編輯彈出視窗
|
||||
currentEditPosition: null, // 儲存當前正在編輯的位置資訊
|
||||
batchPositionForm: {
|
||||
startRow: 1,
|
||||
startCol: 1,
|
||||
rows: 5,
|
||||
cols: 10,
|
||||
price: 0,
|
||||
status: 'available',
|
||||
nameTemplate: '神位{code}',
|
||||
startCode: 1,
|
||||
codeLength: 3
|
||||
},
|
||||
positions: [],
|
||||
// 預覽數據
|
||||
previewPositions: [],
|
||||
//--------------------------------神主牌位置變數
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectAreaMethod(area) {
|
||||
this.currentSelectAreaId = area.areaId;
|
||||
this.currentSelectArea = area;
|
||||
const node = this.findRegionById(this.ancestral_tablet_areas, area.areaId);
|
||||
this.disabledParentOptions = this.getAllDescendants(node);
|
||||
this.loadTabletPositionsMethod(area.areaId);
|
||||
},
|
||||
showEidtAreadialogMethod() {
|
||||
this.showEidtAreadialogFlag = true;
|
||||
if (this.currentSelectArea) {
|
||||
this.editArea = {
|
||||
areaId: this.currentSelectArea?.areaId,
|
||||
areaName: this.currentSelectArea?.areaName,
|
||||
areaCode: this.currentSelectArea?.areaCode,
|
||||
parentAreaId: this.currentSelectArea?.parentAreaId ?? null,
|
||||
areaType: this.currentSelectArea?.areaType ?? null,
|
||||
price: this.currentSelectArea?.price ?? null,
|
||||
sortOrder: this.currentSelectArea?.sortOrder ?? null,
|
||||
description: this.currentSelectArea?.description ?? null,
|
||||
isDisabled: this.currentSelectArea?.isDisabled ?? true
|
||||
};
|
||||
}
|
||||
|
||||
},
|
||||
closeEidtAreadialogMethod() {
|
||||
this.showEidtAreadialogFlag = false;
|
||||
this.resetEditArea();
|
||||
},
|
||||
showNewtAreadialogMethod() {
|
||||
this.showNewAreadialogFlag = true;
|
||||
},
|
||||
closeNewAreadialogMethod() {
|
||||
this.showNewAreadialogFlag = false;
|
||||
this.resetNewArea();
|
||||
},
|
||||
createNewAreaMethod() {
|
||||
//新建區域
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/area/create', this.newArea)
|
||||
.then(response => {
|
||||
this.closeEidtAreadialogMethod();
|
||||
this.getAreaListMethod();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('失敗:', error);
|
||||
});
|
||||
|
||||
},
|
||||
editAreaMethod() {
|
||||
//修改區域資料
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/area/edit', this.editArea)
|
||||
.then(response => {
|
||||
this.currentSelectArea = response.data.area;
|
||||
this.getAreaListMethod();
|
||||
this.closeEidtAreadialogMethod();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('失敗:', error);
|
||||
});
|
||||
|
||||
},
|
||||
resetNewArea() {
|
||||
this.newArea = {
|
||||
areaId: null,
|
||||
areaName: null,
|
||||
areaCode: null,
|
||||
parentAreaId: null,
|
||||
areaType: null,
|
||||
price: null,
|
||||
sortOrder: null,
|
||||
description: null,
|
||||
isDisabled: false
|
||||
};
|
||||
},
|
||||
resetEditArea() {
|
||||
this.editArea = {
|
||||
areaId: null,
|
||||
areaName: null,
|
||||
areaCode: null,
|
||||
parentAreaId: null,
|
||||
areaType: null,
|
||||
price: null,
|
||||
sortOrder: null,
|
||||
description: null,
|
||||
isDisabled: false
|
||||
};
|
||||
},
|
||||
getAreaListMethod() {
|
||||
//獲取區域列表
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/area/getlist')
|
||||
.then(res => {
|
||||
this.ancestral_tablet_areas = res.data
|
||||
this.flatAreas = this.flattenAreas(res.data);
|
||||
})
|
||||
},
|
||||
expandAll() {
|
||||
this.expandAllFlag = true;
|
||||
this.collapseAllFlag = false;
|
||||
},
|
||||
collapseAll() {
|
||||
this.collapseAllFlag = true;
|
||||
this.expandAllFlag = false;
|
||||
},
|
||||
|
||||
//區域展開是否可以被選擇作為上級區域相關函數
|
||||
flattenAreas(data, list = []) {
|
||||
data.forEach(item => {
|
||||
list.push({ areaId: item.areaId, areaName: item.areaName });
|
||||
if (item.children && item.children.length) {
|
||||
this.flattenAreas(item.children, list);
|
||||
}
|
||||
});
|
||||
return list;
|
||||
},
|
||||
findRegionById(list, areaId) {
|
||||
for (const item of list) {
|
||||
if (item.areaId === areaId) return item;
|
||||
if (item.children) {
|
||||
const found = this.findRegionById(item.children, areaId);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getAllDescendants(node) {
|
||||
//尋找某個區域的所有子區域
|
||||
const ids = [];
|
||||
const dfs = (n) => {
|
||||
ids.push(n.areaId);
|
||||
if (n.children) {
|
||||
n.children.forEach(child => dfs(child));
|
||||
}
|
||||
};
|
||||
dfs(node);
|
||||
return ids;
|
||||
},
|
||||
toggleAreaData() {
|
||||
this.showAreaDataFlag = !this.showAreaDataFlag;
|
||||
},
|
||||
//--------------------------------神主牌位置相關函數
|
||||
padCodeMethod(codeNum, length) {
|
||||
return codeNum.toString().padStart(length, '0');
|
||||
},
|
||||
loadTabletPositionsMethod(areaId) {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/area/position/getlist', {
|
||||
params: {
|
||||
areaId: areaId
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.positions = response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('失敗:', error);
|
||||
});
|
||||
},
|
||||
generatePositionsMethod() {
|
||||
const form = this.batchPositionForm;
|
||||
const positions = [];
|
||||
let codeCounter = form.startCode;
|
||||
|
||||
for (let i = 0; i < form.rows; i++) {
|
||||
for (let j = 0; j < form.cols; j++) {
|
||||
const row = form.startRow + i;
|
||||
const col = form.startCol + j;
|
||||
const paddedCode = this.padCodeMethod(codeCounter, form.codeLength);
|
||||
const positionCode = paddedCode;
|
||||
const positionName = form.nameTemplate.replace('{code}', paddedCode);
|
||||
|
||||
positions.push({
|
||||
AreaId: this.currentSelectArea.areaId,
|
||||
RowNo: row,
|
||||
ColumnNo: col,
|
||||
PositionCode: positionCode,
|
||||
PositionName: positionName,
|
||||
Price: form.price,
|
||||
StatusCode: form.status,
|
||||
Description: ''
|
||||
});
|
||||
|
||||
codeCounter++;
|
||||
}
|
||||
}
|
||||
this.previewPositions = positions; // 先賦值預覽,不發請求
|
||||
},
|
||||
async confirmAddPositionsMethod() {
|
||||
if (this.previewPositions.length === 0) {
|
||||
alert('請先生成預覽數據');
|
||||
return;
|
||||
}
|
||||
// 調用後端批次新增介面
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`${HTTP_HOST}api/ancestraltablet/position/batchcreate`,
|
||||
this.previewPositions
|
||||
);
|
||||
|
||||
// 如果後端成功響應(HTTP 200/201)
|
||||
alert('批次新增成功');
|
||||
this.loadTabletPositionsMethod(this.currentSelectArea.areaId); // 刷新數據
|
||||
} catch (error) {
|
||||
// 捕獲錯誤響應(如500、400等)
|
||||
console.error('批次新增失敗', error);
|
||||
|
||||
let msg = '批次新增失敗';
|
||||
if (error.response && error.response.data && error.response.data.exceptionMessage) {
|
||||
msg += `:${error.response.data.exceptionMessage}`;
|
||||
}
|
||||
|
||||
alert(msg);
|
||||
}
|
||||
this.previewPositions = []; // 清空預覽
|
||||
},
|
||||
clearPreviewPositionsMethod() {
|
||||
this.previewPositions = [];
|
||||
},
|
||||
openNewPositionDialogMethod() {
|
||||
this.showNewPositionDialogFlag = true;
|
||||
this.batchPositionForm.price = this.currentSelectArea.price
|
||||
},
|
||||
closeNewPositionDialogMethod() {
|
||||
this.showNewPositionDialogFlag = false;
|
||||
this.previewPositions = [];
|
||||
},
|
||||
editPositionMethod(position) {
|
||||
// 彈出編輯表單、打開模態框或跳轉到編輯頁面
|
||||
this.currentEditPosition = position;
|
||||
this.editPositionFormVisible = true;
|
||||
},
|
||||
async saveEditPositionMethod() {
|
||||
try {
|
||||
await axios.post(`${HTTP_HOST}api/ancestraltablet/position/edit`, this.currentEditPosition);
|
||||
this.$message?.success?.('保存成功') || alert('保存成功');
|
||||
this.editPositionFormVisible = false;
|
||||
this.loadTabletPositionsMethod(this.currentSelectArea.areaId);
|
||||
this.currentEditPosition = null
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
this.$message?.error?.('保存失敗') || alert('保存失敗');
|
||||
}
|
||||
},
|
||||
async deletePositionMethod(position) {
|
||||
if (confirm(`確定要刪除【${position.positionName}】嗎?`)) {
|
||||
try {
|
||||
await axios.delete(`${HTTP_HOST}api/ancestraltablet/position/delete/${position.positionId}`);
|
||||
this.$message?.success?.('刪除成功'); // 如果用的是 Element Plus 或其他 UI 框架
|
||||
this.loadTabletPositionsMethod(this.currentSelectArea.areaId); // 刷新數據
|
||||
} catch (error) {
|
||||
console.error('刪除失敗', error);
|
||||
this.$message?.error?.('刪除失敗,請檢查網路或稍後再試');
|
||||
}
|
||||
}
|
||||
},
|
||||
//--------------------------------神主牌位置相關函數
|
||||
async loadStatusList() {
|
||||
//獲取狀態列表
|
||||
try {
|
||||
const response = await axios.get(`${HTTP_HOST}api/ancestraltablet/status/list`);
|
||||
this.statusList = response.data;
|
||||
} catch (err) {
|
||||
console.error('獲取狀態列表失敗', err);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.getAreaListMethod();
|
||||
this.loadStatusList();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.tree, .tree ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
.toggle-icon {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
width: 1rem;
|
||||
display: inline-block;
|
||||
color: #007bff;
|
||||
}
|
||||
.region-item-label {
|
||||
cursor: pointer;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
.region-item-label.selected {
|
||||
background-color: #eaf4ff;
|
||||
color: #0d6efd;
|
||||
font-weight: bold;
|
||||
}
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 120px); /* 6列 */
|
||||
grid-auto-rows: 100px; /* 行高 */
|
||||
gap: 10px;
|
||||
}
|
||||
/* 可用(綠色) */
|
||||
.status-available {
|
||||
background-color: #d4edda;
|
||||
border-color: #28a745;
|
||||
}
|
||||
|
||||
/* 維護中(黃色) */
|
||||
.status-maintenance {
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffc107;
|
||||
}
|
||||
|
||||
/* 預訂中(藍色) */
|
||||
.status-reserved {
|
||||
background-color: #cce5ff;
|
||||
border-color: #007bff;
|
||||
}
|
||||
|
||||
/* 已使用(灰色) */
|
||||
.status-used {
|
||||
background-color: #e2e3e5;
|
||||
border-color: #6c757d;
|
||||
}
|
||||
.grid-item {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 1px 3px rgba(0,0,0,0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.position-name {
|
||||
background-color: #f0f0f0;
|
||||
padding: 4px 8px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.position-content {
|
||||
flex-grow: 1;
|
||||
padding: 3px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
</asp:Content>
|
||||
14
web/admin/ancestraltablet/ancestraltabletarea/index.aspx.cs
Normal file
14
web/admin/ancestraltablet/ancestraltabletarea/index.aspx.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public partial class admin_ancestraltablet_ancestraltabletarea_index : MyWeb.config
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
569
web/admin/ancestraltablet/ancestraltabletposition/index.aspx
Normal file
569
web/admin/ancestraltablet/ancestraltabletposition/index.aspx
Normal file
@@ -0,0 +1,569 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="admin_ancestraltablet_ancestraltabletposition_index" %>
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||
<nav class="mb-2 ps-3">
|
||||
<button class="btn btn-secondary me-2" @click="expandAll" type="button">
|
||||
<i class="mdi mdi-arrow-expand-all"></i> 全部展開
|
||||
</button>
|
||||
<button class="btn btn-secondary" @click="collapseAll" type="button">
|
||||
<i class="mdi mdi-arrow-collapse-all"></i> 全部收起
|
||||
</button>
|
||||
</nav>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-lg-2">
|
||||
<div class="card shadow-sm my-2">
|
||||
<div class="card-header">神主牌區域列表</div>
|
||||
<div class="card-body">
|
||||
<ul class="tree">
|
||||
<li v-for="area in ancestral_tablet_areas" :key="area.AreaId">
|
||||
<region-item
|
||||
:item="area"
|
||||
:selected-id="currentSelectAreaId"
|
||||
@select-area="selectAreaMethod"
|
||||
:expand-all="expandAllFlag"
|
||||
:collapse-all="collapseAllFlag"
|
||||
@clear-expand-all="expandAllFlag = false"
|
||||
@clear-collapse-all="collapseAllFlag = false"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 col-lg-10" v-if="currentSelectArea">
|
||||
<div class="card shadow-sm my-2" style="position: sticky; top: 20px; display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;">
|
||||
<div class="card-header" style="display: flex; justify-content: space-between; align-items: center;background-color: #ffc107;">
|
||||
<div>
|
||||
{{currentSelectArea.areaName + ' - ' + '神主牌位置'}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body" style="flex: 1 1 auto; min-height: 0; overflow: auto;">
|
||||
<div class="grid-container">
|
||||
<div
|
||||
v-for="pos in positions"
|
||||
:key="pos.positionCode"
|
||||
class="grid-item"
|
||||
:class="'status-' + pos.statusCode"
|
||||
:style="{ gridRow: pos.rowNo, gridColumn: pos.columnNo }"
|
||||
>
|
||||
<div class="position-name">{{ pos.positionName }}</div>
|
||||
<div class="position-content">
|
||||
<span v-if="pos.statusCode == 'maintenance'">維護中</span>
|
||||
<v-btn v-else-if="!pos.ancestralTabletRegistrant" @click="showCreatePWMethod(pos)">登記</v-btn>
|
||||
<!-- 已預訂 -->
|
||||
<div v-else>
|
||||
<div>登記人:{{ pos.ancestralTabletRegistrant?.name }}</div>
|
||||
<div>登記日期:{{ pos.ancestralTabletRegistrant?.registerDate|timeString('YYYY/MM/DD') }}</div>
|
||||
<v-btn small color="btn-primary" @click="showEditPWMethod(pos)">
|
||||
詳細資訊
|
||||
</v-btn>
|
||||
|
||||
</>
|
||||
</div>
|
||||
|
||||
<!-- 已使用 -->
|
||||
<div v-else-if="pos.statusCode === 'used'">
|
||||
<div>已使用</div>
|
||||
<div v-if="pos.usedBy">使用人:{{ pos.usedBy }}</div>
|
||||
<div v-if="pos.usedDate">使用日期:{{ pos.usedDate|timeString('YYYY/MM/DD') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 登記資料彈出視窗 -->
|
||||
<div>
|
||||
<v-dialog v-model="showCreatePWFlag" max-width="800">
|
||||
<v-card>
|
||||
<v-card-title class="headline">登記資料({{'位置: ' + selectedPos?.positionName}})</v-card-title>
|
||||
<v-card-text>
|
||||
<!-- 登記人資料 -->
|
||||
<hr />
|
||||
<h5>登記人資料</h5>
|
||||
<label>姓名:
|
||||
<input class="form-control" type="text" v-model="form.createRegister.name" />
|
||||
</label><br />
|
||||
<label>電話:
|
||||
<input class="form-control" type="text" v-model="form.createRegister.phone" />
|
||||
</label><br />
|
||||
<label>住址:
|
||||
<input class="form-control" type="text" v-model="form.createRegister.address" />
|
||||
</label><br />
|
||||
<label>費用:
|
||||
<input class="form-control" v-model="form.createRegister.price" />
|
||||
</label><br />
|
||||
<label>登記時間:
|
||||
<input class="form-control" type="date" v-model="form.createRegister.registerDate" />
|
||||
</label><br />
|
||||
<label>開始時間:
|
||||
<input class="form-control" type="date" v-model="form.createRegister.startDate" />
|
||||
</label><br />
|
||||
<label>結束時間:
|
||||
<input class="form-control" type="date" v-model="form.createRegister.endDate" />
|
||||
</label><br />
|
||||
<label>長期有效:
|
||||
<input type="checkbox" v-model="form.createRegister.isLongTerm" />
|
||||
</label><br />
|
||||
<label>是否啟用:
|
||||
<input type="checkbox" v-model="form.createRegister.isActive" />
|
||||
</label><br />
|
||||
<div class="mt-2 mb-4">
|
||||
<button
|
||||
v-if="!form.createRegister.registrantCode"
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="saveRegistrantMethod">
|
||||
保存登記人
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="updateRegistrantMethod">
|
||||
送出修改
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 牌位資料 -->
|
||||
<hr />
|
||||
<h5>牌位資料</h5>
|
||||
<label>牌位標題:
|
||||
<input class="form-control" type="text" v-model="form.createPositionRecord.npTitle" />
|
||||
</label><br />
|
||||
<label>立牌時間:
|
||||
<input class="form-control" type="date" v-model="form.createPositionRecord.npStandDate" />
|
||||
</label><br />
|
||||
<label>陽上:
|
||||
<input class="form-control" type="text" v-model="form.createPositionRecord.npYangShang" />
|
||||
</label><br />
|
||||
<label>內牌內容:</label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
rows="4"
|
||||
v-model="form.createPositionRecord.wpContent"
|
||||
style="width: 100%; box-sizing: border-box;"
|
||||
></textarea><br />
|
||||
<div class="mt-2 mb-2">
|
||||
<button v-if="form.createPositionRecord.recordId == null" class="btn btn-primary" type="button" @click="saveCreatePositionRecordMethod">保存牌位</button>
|
||||
<button v-else type="button" class="btn btn-primary" @click="updateCreatePositionRecordMethod">
|
||||
送出修改
|
||||
</button>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<button class="btn btn-secondary" type="button" @click="closePWDialogMethod">關閉</button>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||
<script>
|
||||
Vue.component('region-item', {
|
||||
props: ['item', 'selectedId', 'expandAll', 'collapseAll'],
|
||||
data() {
|
||||
return {
|
||||
expanded: false, // 預設全部收起
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
expandAll(newVal) {
|
||||
if (newVal) {
|
||||
this.expanded = true;
|
||||
// 執行完後發事件通知父組件清除標誌
|
||||
this.$nextTick(() => this.$emit('clear-expand-all'));
|
||||
}
|
||||
},
|
||||
collapseAll(newVal) {
|
||||
if (newVal) {
|
||||
this.expanded = false;
|
||||
this.$nextTick(() => this.$emit('clear-collapse-all'));
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasChildren() {
|
||||
return this.item.children && this.item.children.length > 0;
|
||||
},
|
||||
icon() {
|
||||
// 無論有無子節點,皆可點擊展開/收起
|
||||
return this.expanded ? '▼' : '▶';
|
||||
},
|
||||
isSelected() {
|
||||
return this.item.areaId === this.selectedId;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.expanded = !this.expanded;
|
||||
},
|
||||
select() {
|
||||
this.$emit('select-area', this.item);
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<span class="toggle-icon" @click="toggle">{{ icon }}</span>
|
||||
<span @click="select"
|
||||
class="region-item-label"
|
||||
:class="{ 'selected': isSelected }">
|
||||
{{ item.areaName }}
|
||||
</span>
|
||||
|
||||
<!-- 子區域列表 -->
|
||||
<ul v-if="hasChildren && expanded">
|
||||
<li v-for="child in item.children" :key="child.areaId">
|
||||
<region-item
|
||||
:item="child"
|
||||
:selected-id="selectedId"
|
||||
:expand-all="expandAll"
|
||||
:collapse-all="collapseAll"
|
||||
@select-area="$emit('select-area', $event)"
|
||||
@clear-expand-all="$emit('clear-expand-all')"
|
||||
@clear-collapse-all="$emit('clear-collapse-all')"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
Vue.filter('timeString', function (value, myFormat) {
|
||||
return value == null || value == "" ? "" : moment(value).format(myFormat || 'YYYY-MM-DD, HH:mm:ss');
|
||||
});
|
||||
new Vue({
|
||||
el: '#app',
|
||||
vuetify: new Vuetify(vuetify_options),
|
||||
data() {
|
||||
return {
|
||||
expandAllFlag: false, // 控制全部展開
|
||||
collapseAllFlag: false, // 控制全部收起
|
||||
ancestral_tablet_areas: [], //神主牌區域列表
|
||||
currentSelectArea: null,
|
||||
currentSelectAreaId: null,
|
||||
statusList: [],
|
||||
//--------------------------------神主牌位置變數
|
||||
positions: [],
|
||||
selectedPos: null, //點擊登記的的pos
|
||||
showCreatePWFlag: false, //控制是否打開登記神主牌位資料彈出視窗
|
||||
form: {
|
||||
createRegister: {
|
||||
//新增登記人form
|
||||
registrantCode: null, // 登記編號
|
||||
positionId: null,
|
||||
name: null,
|
||||
phone: null,
|
||||
address: null,
|
||||
registerDate: null,
|
||||
price: null,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
isLongTerm: false,
|
||||
isActive: true,
|
||||
|
||||
|
||||
},
|
||||
createPositionRecord: {
|
||||
//新增牌位登記form
|
||||
recordId: null, // 自增主鍵,前端一般不用填
|
||||
registrantCode: null, // 外鍵,關聯登記人編號
|
||||
npTitle: null,
|
||||
npStandDate: null,
|
||||
npYangShang: null,
|
||||
wpContent: null,
|
||||
},
|
||||
},
|
||||
//--------------------------------神主牌位置變數
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectAreaMethod(area) {
|
||||
this.currentSelectAreaId = area.areaId;
|
||||
this.currentSelectArea = area;
|
||||
this.loadTabletPositionsMethod(area.areaId);
|
||||
},
|
||||
getAreaListMethod() {
|
||||
//獲取區域列表
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/area/getlist')
|
||||
.then(res => {
|
||||
this.ancestral_tablet_areas = res.data
|
||||
})
|
||||
},
|
||||
expandAll() {
|
||||
this.expandAllFlag = true;
|
||||
this.collapseAllFlag = false;
|
||||
},
|
||||
collapseAll() {
|
||||
this.collapseAllFlag = true;
|
||||
this.expandAllFlag = false;
|
||||
},
|
||||
//--------------------------------神主牌位置相關函數
|
||||
loadTabletPositionsMethod(areaId) {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/position/getlist', {
|
||||
params: {
|
||||
areaId: areaId
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.positions = response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('失敗:', error);
|
||||
});
|
||||
},
|
||||
showCreatePWMethod(pos) {
|
||||
//打開新增彈出視窗
|
||||
this.selectedPos = pos;
|
||||
this.showCreatePWFlag = true;
|
||||
this.form.createRegister.positionId = pos.positionId
|
||||
this.form.createRegister.price = pos.price
|
||||
},
|
||||
showEditPWMethod(pos) {
|
||||
//打開編輯彈出視窗
|
||||
this.selectedPos = pos;
|
||||
const registrant = pos.ancestralTabletRegistrant;
|
||||
|
||||
if (registrant) {
|
||||
this.form.createRegister.registrantCode = registrant.registrantCode;
|
||||
this.form.createRegister.positionId = pos.positionId;
|
||||
this.form.createRegister.name = registrant.name;
|
||||
this.form.createRegister.phone = registrant.phone;
|
||||
this.form.createRegister.address = registrant.address;
|
||||
this.form.createRegister.registerDate = registrant.registerDate
|
||||
? registrant.registerDate?.split('T')[0]
|
||||
: '';
|
||||
this.form.createRegister.price = registrant.price;
|
||||
this.form.createRegister.startDate = registrant.startDate ? registrant.startDate?.split('T')[0]
|
||||
: '';
|
||||
this.form.createRegister.endDate = registrant.endDate ? registrant.endDate?.split('T')[0]
|
||||
: '';
|
||||
this.form.createRegister.isLongTerm = registrant.isLongTerm;
|
||||
this.form.createRegister.isActive = registrant.isActive;
|
||||
this.form.createPositionRecord.registrantCode = registrant.registrantCode;
|
||||
this.showCreatePWFlag = true;
|
||||
if (registrant.tabletRecord) {
|
||||
this.form.createPositionRecord.recordId = registrant.tabletRecord.recordId;
|
||||
this.form.createPositionRecord.registrantCode = registrant.tabletRecord.registrantCode;
|
||||
this.form.createPositionRecord.npTitle = registrant.tabletRecord.npTitle;
|
||||
this.form.createPositionRecord.npStandDate = registrant.tabletRecord.npStandDate ? registrant.tabletRecord.npStandDate.split('T')[0]
|
||||
: '';
|
||||
this.form.createPositionRecord.npYangShang = registrant.tabletRecord.npYangShang;
|
||||
this.form.createPositionRecord.wpContent = registrant.tabletRecord.wpContent;
|
||||
}
|
||||
}
|
||||
},
|
||||
closePWDialogMethod(pos) {
|
||||
//關閉編輯彈出視窗
|
||||
this.selectedPos = null;
|
||||
|
||||
// 重設登記人欄位
|
||||
this.form.createRegister = {
|
||||
registrantCode: null,
|
||||
positionId: null,
|
||||
name: null,
|
||||
phone: null,
|
||||
address: null,
|
||||
registerDate: null,
|
||||
price: null,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
isLongTerm: false,
|
||||
isActive: false
|
||||
};
|
||||
|
||||
// 清空牌位記錄
|
||||
this.form.createPositionRecord = {
|
||||
recordId: null,
|
||||
registrantCode: null,
|
||||
npTitle: null,
|
||||
npStandDate: null,
|
||||
npYangShang: null,
|
||||
wpContent: null
|
||||
};
|
||||
|
||||
this.showCreatePWFlag = false;
|
||||
},
|
||||
//--------------------------------神主牌位置相關函數
|
||||
//--------------------------------登記人相關函數 start
|
||||
async saveRegistrantMethod() {
|
||||
try {
|
||||
const response = await axios.post(HTTP_HOST + 'api/ancestraltablet/registrant/create', this.form.createRegister);
|
||||
console.log('保存成功', response.data);
|
||||
|
||||
// 可選:提示用戶、關閉對話框、刷新數據等
|
||||
this.$toast?.success('登記人保存成功'); // 取決於你是否使用 toast 插件
|
||||
this.form.createRegister.registrantCode = response.data.registrantCode
|
||||
this.form.createPositionRecord.registrantCode = response.data.registrantCode
|
||||
this.loadTabletPositionsMethod(this.selectedPos.areaId)
|
||||
alert("修改成功")
|
||||
} catch (error) {
|
||||
console.error('保存失敗', error);
|
||||
this.$toast?.error('登記人保存失敗');
|
||||
}
|
||||
},
|
||||
updateRegistrantMethod() {
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/registrant/update', this.form.createRegister)
|
||||
.then(response => {
|
||||
console.log('登記人更新成功:', response.data);
|
||||
this.$toast?.success?.('登記人更新成功'); // 可選:使用 toast 彈出提示
|
||||
//this.showCreatePWFlag = false; // 關閉彈出視窗
|
||||
// 可選:刷新列表等
|
||||
this.loadTabletPositionsMethod(this.selectedPos.areaId)
|
||||
alert("修改成功")
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('更新登記人失敗:', error);
|
||||
this.$toast?.error?.('更新失敗,請檢查數據');
|
||||
});
|
||||
},
|
||||
//--------------------------------登記人相關函數 end
|
||||
|
||||
//--------------------------------牌位資料相關函數 Start
|
||||
saveCreatePositionRecordMethod() {
|
||||
// 校驗必須欄位
|
||||
if (!this.form.createPositionRecord.registrantCode) {
|
||||
alert('請先填寫登記人資料並且送出保存!');
|
||||
return;
|
||||
}
|
||||
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/pw/create', this.form.createPositionRecord)
|
||||
.then(res => {
|
||||
if (res.data && res.data.message) {
|
||||
alert(res.data.message);
|
||||
} else {
|
||||
alert('保存成功');
|
||||
}
|
||||
// 成功後可以關閉彈出視窗或清空表單
|
||||
//this.showCreatePWFlag = false;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('保存失敗:', err);
|
||||
alert('保存失敗,請檢查伺服器日誌');
|
||||
});
|
||||
},
|
||||
updateCreatePositionRecordMethod() {
|
||||
// 校驗必須欄位
|
||||
if (!this.form.createPositionRecord.recordId) {
|
||||
alert('不存在牌位資料,無法更新');
|
||||
return;
|
||||
}
|
||||
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/pw/update', this.form.createPositionRecord)
|
||||
.then(res => {
|
||||
if (res.data && res.data.message) {
|
||||
alert(res.data.message);
|
||||
} else {
|
||||
alert('牌位資料更新成功');
|
||||
}
|
||||
// 成功後可以關閉彈出視窗或清空表單
|
||||
//this.showCreatePWFlag = false;
|
||||
})
|
||||
.catch(err => {
|
||||
alert('更新失敗:', err);
|
||||
});
|
||||
},
|
||||
//--------------------------------牌位資料相關函數 end
|
||||
async loadStatusList() {
|
||||
//獲取狀態列表
|
||||
try {
|
||||
const response = await axios.get(`${HTTP_HOST}api/ancestraltablet/status/list`);
|
||||
this.statusList = response.data;
|
||||
} catch (err) {
|
||||
console.error('獲取狀態列表失敗', err);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.getAreaListMethod();
|
||||
this.loadStatusList();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.tree, .tree ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
.toggle-icon {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
width: 1rem;
|
||||
display: inline-block;
|
||||
color: #007bff;
|
||||
}
|
||||
.region-item-label {
|
||||
cursor: pointer;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
.region-item-label.selected {
|
||||
background-color: #eaf4ff;
|
||||
color: #0d6efd;
|
||||
font-weight: bold;
|
||||
}
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 150px); /* 6列 */
|
||||
grid-auto-rows: 150px; /* 行高 */
|
||||
gap: 10px;
|
||||
}
|
||||
/* 可用(綠色) */
|
||||
.status-available {
|
||||
background-color: #d4edda;
|
||||
border-color: #28a745;
|
||||
}
|
||||
|
||||
/* 維護中(黃色) */
|
||||
.status-maintenance {
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffc107;
|
||||
}
|
||||
|
||||
/* 已使用(灰色) */
|
||||
.status-used {
|
||||
background-color: #e2e3e5;
|
||||
border-color: #6c757d;
|
||||
}
|
||||
.grid-item {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 1px 3px rgba(0,0,0,0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.position-name {
|
||||
background-color: #f0f0f0;
|
||||
padding: 4px 8px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.position-content {
|
||||
flex-grow: 1;
|
||||
padding: 3px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
</asp:Content>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public partial class admin_ancestraltablet_ancestraltabletposition_index : MyWeb.config
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
126
web/admin/ancestraltablet/ancestraltabletstatistics/index.aspx
Normal file
126
web/admin/ancestraltablet/ancestraltabletstatistics/index.aspx
Normal file
@@ -0,0 +1,126 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="admin_ancestraltablet_ancestraltabletstatistics_index" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||
<div class="container">
|
||||
<h2 class="title">區域牌位統計</h2>
|
||||
<table class="stats-table" border="1" cellspacing="0" cellpadding="5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>區域編號</th>
|
||||
<th>區域名稱</th>
|
||||
<th>總位置數</th>
|
||||
<th>可用位置數</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="area in areas" :key="area.areaId">
|
||||
<td>{{ area.areaId }}</td>
|
||||
<td>{{ area.areaName }}</td>
|
||||
<td>{{ area.totalPositions }}</td>
|
||||
<td>{{ area.availableCount }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
vuetify: new Vuetify(vuetify_options),
|
||||
data() {
|
||||
return {
|
||||
areas: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getAncestralTabletPositionsStatisticsMethod() {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/statistics/positions/availablepositions')
|
||||
.then((res) => {
|
||||
this.areas = res.data
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getAncestralTabletPositionsStatisticsMethod()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
background: #ffffff;
|
||||
padding: 25px 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||
font-family: "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 25px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.stats-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.stats-table th {
|
||||
background-color: #1976d2;
|
||||
color: #fff;
|
||||
padding: 12px;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.stats-table td {
|
||||
padding: 10px;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
/* 奇偶行區分 */
|
||||
.stats-table tbody tr:nth-child(odd) {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
/* 滑鼠懸停高亮 */
|
||||
.stats-table tbody tr:hover {
|
||||
background-color: #e3f2fd;
|
||||
transition: 0.3s ease;
|
||||
}
|
||||
|
||||
/* 響應式支持 */
|
||||
@media (max-width: 600px) {
|
||||
.container {
|
||||
padding: 15px;
|
||||
}
|
||||
.title {
|
||||
font-size: 18px;
|
||||
}
|
||||
.stats-table th, .stats-table td {
|
||||
padding: 8px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</asp:Content>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public partial class admin_ancestraltablet_ancestraltabletstatistics_index : MyWeb.config
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
15
web/admin/ancestraltablet/ancestraltabletuselist/create.aspx
Normal file
15
web/admin/ancestraltablet/ancestraltabletuselist/create.aspx
Normal file
@@ -0,0 +1,15 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="create.aspx.cs" Inherits="admin_ancestraltablet_ancestraltabletuselist_create" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||
<div>
|
||||
這是新增頁面
|
||||
</div>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||
</asp:Content>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public partial class admin_ancestraltablet_ancestraltabletuselist_create : MyWeb.config
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
99
web/admin/ancestraltablet/ancestraltabletuselist/detail.aspx
Normal file
99
web/admin/ancestraltablet/ancestraltabletuselist/detail.aspx
Normal file
@@ -0,0 +1,99 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="detail.aspx.cs" Inherits="admin_ancestraltablet_ancestraltabletuselist_detail" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||
<nav>
|
||||
<a :href="'edit.aspx?registrantCode=' + registrantCode" class="btn btn-primary">修改資料</a>
|
||||
</nav>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||
<div>
|
||||
{{registrantCode}}
|
||||
</div>
|
||||
<div>
|
||||
<div class="card">
|
||||
<h2>登記人資訊</h2>
|
||||
<p><strong>登記編碼:</strong> {{ registrant.registrantCode }}</p>
|
||||
<p><strong>姓名:</strong> {{ registrant.name }}</p>
|
||||
<p><strong>電話:</strong> {{ registrant.phone }}</p>
|
||||
<p><strong>地址:</strong> {{ registrant.address }}</p>
|
||||
<p><strong>登記日期:</strong> {{ formatDate(registrant.registerDate) }}</p>
|
||||
<div style="border: 1px solid #007bff; background-color: #f0f8ff; padding: 10px 15px; border-radius: 5px; display: flex; flex-direction: column; gap: 5px; max-width: 400px; margin-bottom: 10px;">
|
||||
<div>
|
||||
<label style="font-weight: bold; margin-right: 5px;">已選擇位置:</label>
|
||||
<span>{{ registrant?.positionName || '未選擇' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>價格:</strong> {{ registrant.price }}</p>
|
||||
<p><strong>開始日期:</strong> {{ formatDate(registrant.startDate) }}</p>
|
||||
<p><strong>結束日期:</strong> {{ formatDate(registrant.endDate) }}</p>
|
||||
<p><strong>是否長期:</strong> {{ registrant.isLongTerm ? '是' : '否' }}</p>
|
||||
<p><strong>是否啟用:</strong> {{ registrant.isActive ? '是' : '否' }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card" v-if="registrant.tabletRecord">
|
||||
<h2>牌位資料</h2>
|
||||
<p><strong>記錄ID:</strong> {{ registrant.tabletRecord.recordId }}</p>
|
||||
<p><strong>登記編碼:</strong> {{ registrant.tabletRecord.registrantCode }}</p>
|
||||
|
||||
<p><strong>牌位標題:</strong> {{ registrant.tabletRecord.npTitle }}</p>
|
||||
<p><strong>立牌日期:</strong> {{ formatDate(registrant.tabletRecord.npStandDate) }}</p>
|
||||
<p><strong>陽上:</strong> {{ registrant.tabletRecord.npYangShang }}</p>
|
||||
<p><strong>內牌內容:</strong> {{ registrant.tabletRecord.wpContent }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card" v-else>
|
||||
<h2>牌位資料</h2>
|
||||
<p>暫無牌位資料</p>
|
||||
</div>
|
||||
</div>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
vuetify: new Vuetify(vuetify_options),
|
||||
data() {
|
||||
return {
|
||||
registrantCode: '<%=Request.QueryString["registrantCode"]%>',
|
||||
registrant: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return "";
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleDateString();
|
||||
},
|
||||
getRegistrantByCodeMethod(code) {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/registrant/getbycode', {
|
||||
params: {
|
||||
registrantCode: code
|
||||
}
|
||||
})
|
||||
.then((res => {
|
||||
this.registrant = res.data
|
||||
}))
|
||||
.catch((error => {
|
||||
|
||||
}))
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getRegistrantByCodeMethod(this.registrantCode);
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
.card {
|
||||
border: 1px solid #ccc;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 5px;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</asp:Content>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public partial class admin_ancestraltablet_ancestraltabletuselist_detail : MyWeb.config
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
419
web/admin/ancestraltablet/ancestraltabletuselist/edit.aspx
Normal file
419
web/admin/ancestraltablet/ancestraltabletuselist/edit.aspx
Normal file
@@ -0,0 +1,419 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="edit.aspx.cs" Inherits="admin_ancestraltablet_ancestraltabletuselist_edit" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||
<nav>
|
||||
<a :href="'detail.aspx?registrantCode=' + registrantCode" class="btn btn-secondary">返回詳情</a>
|
||||
</nav>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||
<div>
|
||||
<!-- 登記人資料編輯區域 -->
|
||||
<div class="card">
|
||||
<h2>編輯登記人資訊</h2>
|
||||
<label>登記編碼:</label>
|
||||
<input type="text" v-model="registrant.registrantCode" class="form-control" disabled />
|
||||
|
||||
<label>姓名:</label>
|
||||
<input type="text" v-model="registrant.name" class="form-control" />
|
||||
|
||||
<label>電話:</label>
|
||||
<input type="text" v-model="registrant.phone" class="form-control" />
|
||||
|
||||
<label>地址:</label>
|
||||
<input type="text" v-model="registrant.address" class="form-control" />
|
||||
|
||||
<label>登記日期:</label>
|
||||
<input type="date" v-model="registrant.registerDate" class="form-control" />
|
||||
<div class="mt-4" style="border: 1px solid #007bff; background-color: #f0f8ff; padding: 10px 15px; border-radius: 5px; display: flex; flex-direction: column; gap: 5px; max-width: 400px; margin-bottom: 10px;">
|
||||
<div>
|
||||
<label style="font-weight: bold; margin-right: 5px;">已選擇位置:</label>
|
||||
<span>{{ registrant?.positionName || '未選擇' }}</span>
|
||||
</div>
|
||||
<div v-if="newPositionId">
|
||||
<label style="font-weight: bold; margin-right: 5px;">新選擇位置:</label>
|
||||
<span>{{ this.newPositionEntity?.positionName }}</span>
|
||||
</div>
|
||||
<button type="button" @click="isShowPositionDialog=true"
|
||||
style="align-self: flex-start; padding: 5px 10px; background-color: #007bff; color: #fff; border: none; border-radius: 3px; cursor: pointer;"
|
||||
>
|
||||
{{registrant?.positionId ? '更換位置' : '選擇位置'}}
|
||||
</button>
|
||||
</div>
|
||||
<label>價格:</label>
|
||||
<input type="number" v-model="registrant.price" class="form-control" />
|
||||
|
||||
<label>開始日期:</label>
|
||||
<input type="date" v-model="registrant.startDate" class="form-control" />
|
||||
|
||||
<label>結束日期:</label>
|
||||
<input type="date" v-model="registrant.endDate" class="form-control" />
|
||||
|
||||
<div class="mt-3" style="display:flex; align-items:center; gap:15px; margin-bottom:10px; font-family:Arial, sans-serif;">
|
||||
<label style="font-weight:500;">是否長期:</label>
|
||||
<input type="checkbox" v-model="registrant.isLongTerm" style="width:16px; height:16px; cursor:pointer;" />
|
||||
<span>是</span>
|
||||
</div>
|
||||
|
||||
<div style="display:flex; align-items:center; gap:15px; margin-bottom:10px; font-family:Arial, sans-serif;">
|
||||
<label style="font-weight:500;">是否啟用:</label>
|
||||
<input type="checkbox" v-model="registrant.isActive" style="width:16px; height:16px; cursor:pointer;" />
|
||||
<span>是</span>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-primary mt-2" @click="updateRegistrant">保存登記資料</button>
|
||||
</div>
|
||||
|
||||
<!-- 牌位資料區域 -->
|
||||
<div class="card" v-if="registrant.tabletRecord">
|
||||
<h2>編輯牌位資料</h2>
|
||||
<label>記錄ID:</label>
|
||||
<input type="text" v-model="registrant.tabletRecord.recordId" class="form-control" disabled />
|
||||
|
||||
<label>登記編碼 (外鍵):</label>
|
||||
<input type="text" v-model="registrant.tabletRecord.registrantCode" class="form-control" disabled />
|
||||
|
||||
|
||||
<label>牌位標題:</label>
|
||||
<input type="text" v-model="registrant.tabletRecord.npTitle" class="form-control" />
|
||||
|
||||
<label>立牌日期:</label>
|
||||
<input type="date" v-model="registrant.tabletRecord.npStandDate" class="form-control" />
|
||||
|
||||
<label>陽上:</label>
|
||||
<input type="text" v-model="registrant.tabletRecord.npYangShang" class="form-control" />
|
||||
|
||||
<label>內牌內容:</label>
|
||||
<textarea v-model="registrant.tabletRecord.wpContent" class="form-control"></textarea>
|
||||
|
||||
<button type="button" class="btn btn-success mt-2" @click="updateTabletRecord">保存牌位資料</button>
|
||||
</div>
|
||||
|
||||
<div class="card" v-else>
|
||||
<h2>牌位資料</h2>
|
||||
<p>暫無牌位資料</p>
|
||||
<button type="button" class="btn btn-primary" @click="createTabletRecordForm">新增牌位資料</button>
|
||||
|
||||
<div v-if="creatingTablet" class="mt-3">
|
||||
<label>牌位標題:</label>
|
||||
<input type="text" v-model="newTablet.npTitle" class="form-control" />
|
||||
|
||||
<label>立牌日期:</label>
|
||||
<input type="date" v-model="newTablet.npStandDate" class="form-control" />
|
||||
|
||||
<label>陽上:</label>
|
||||
<input type="text" v-model="newTablet.npYangShang" class="form-control" />
|
||||
|
||||
<label>牌位內容:</label>
|
||||
<textarea v-model="newTablet.wpContent" class="form-control"></textarea>
|
||||
|
||||
<button type="button" class="btn btn-success mt-2" @click="createTabletRecord">保存新增</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<v-dialog v-model="isShowPositionDialog" persistent
|
||||
width="80%"
|
||||
height="80%">
|
||||
<v-card style="
|
||||
width: 80vw;
|
||||
height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
">
|
||||
<v-card-title
|
||||
style="display: flex; align-items: center; font-weight: 600; font-size: 18px;"
|
||||
>
|
||||
<span>選擇位置:</span>
|
||||
|
||||
<select
|
||||
class="form-control"
|
||||
style="
|
||||
flex: 0 0 200px;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
"
|
||||
v-model="selectedArea"
|
||||
@focus="e => e.target.style.borderColor = '#007bff'"
|
||||
@blur="e => e.target.style.borderColor = '#ccc'"
|
||||
@change="onAreaChange"
|
||||
>
|
||||
<option value="">請選擇區域</option>
|
||||
<option v-for="area in areaList" :value="area.areaId" :key="area.areaId">{{area.areaName}}</option>
|
||||
</select>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text style="flex: 1; overflow: auto;">
|
||||
<div class="grid-container">
|
||||
<div
|
||||
v-for="pos in positionList"
|
||||
:key="pos.positionId"
|
||||
class="grid-item"
|
||||
:class="'status-' + (pos.isCanUse? 'canuse':'cannotuse')"
|
||||
:style="{ gridRow: pos.rowNo, gridColumn: pos.columnNo }"
|
||||
>
|
||||
<div class="position-name">{{ pos.positionName }}</div>
|
||||
<div class="position-content">
|
||||
<button type="button" v-if="pos.isCanUse"
|
||||
class="btn btn-primary"
|
||||
@click="chooseNewPositionMethod(pos)"
|
||||
>選擇</button>
|
||||
<span v-else>已被使用</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<div class="me-5">新位置:{{newPositionEntity?.positionName}}</div>
|
||||
<v-btn color="primary" @click="saveChoosePositionMethod">確定</v-btn>
|
||||
<v-btn color="grey" @click="cancelChoosePositionMethod">取消</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
vuetify: new Vuetify(vuetify_options),
|
||||
data() {
|
||||
return {
|
||||
registrantCode: '<%=Request.QueryString["registrantCode"]%>',
|
||||
registrant: {},
|
||||
creatingTablet: false,
|
||||
newPositionId: null,
|
||||
newPositionEntity: null,
|
||||
newTablet: {
|
||||
//新增牌位登記form
|
||||
recordId: null, // 自增主鍵,前端一般不用填
|
||||
registrantCode: null, // 外鍵,關聯登記人編號
|
||||
npTitle: null,
|
||||
npStandDate: null,
|
||||
npYangShang: null,
|
||||
wpContent: null,
|
||||
},
|
||||
positionList: [],//選擇神位位置的時候獲取的位置列表
|
||||
isShowPositionDialog: false,
|
||||
selectedArea: "",
|
||||
areaList: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return "";
|
||||
return dateStr.split('T')[0];
|
||||
},
|
||||
getRegistrantByCodeMethod(code) {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/registrant/getbycode', {
|
||||
params: {
|
||||
registrantCode: code
|
||||
}
|
||||
})
|
||||
.then((res => {
|
||||
const data = res.data;
|
||||
|
||||
// 格式化登記日期欄位
|
||||
if (data.registerDate) data.registerDate = this.formatDate(data.registerDate);
|
||||
if (data.startDate) data.startDate = this.formatDate(data.startDate);
|
||||
if (data.endDate) data.endDate = this.formatDate(data.endDate);
|
||||
|
||||
// 格式化牌位日期欄位
|
||||
if (data.tabletRecord && data.tabletRecord.npStandDate)
|
||||
data.tabletRecord.npStandDate = this.formatDate(data.tabletRecord.npStandDate);
|
||||
|
||||
this.registrant = data;
|
||||
}))
|
||||
.catch((error => {
|
||||
|
||||
}))
|
||||
},
|
||||
// 更新登記資料
|
||||
updateRegistrant() {
|
||||
const newPositionId = this.newPositionId; // 假設 newPositionId 存在組件裡
|
||||
|
||||
// 如果 newPositionId 不為空,則更新 registrant.PositionId
|
||||
if (newPositionId != null && newPositionId !== '') {
|
||||
this.registrant.PositionId = newPositionId;
|
||||
}
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/registrant/update', this.registrant)
|
||||
.then(() => {
|
||||
alert('登記資料已保存!')
|
||||
this.getRegistrantByCodeMethod(this.registrantCode);
|
||||
this.newPositionId = null;
|
||||
}
|
||||
)
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
alert('保存失敗!');
|
||||
});
|
||||
},
|
||||
|
||||
// 更新牌位資料
|
||||
updateTabletRecord() {
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/pw/update', this.registrant.tabletRecord)
|
||||
.then(() => alert('牌位資料已更新!'))
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
alert('保存失敗!');
|
||||
});
|
||||
},
|
||||
|
||||
// 顯示新增牌位表單
|
||||
createTabletRecordForm() {
|
||||
this.creatingTablet = true;
|
||||
},
|
||||
|
||||
// 新增牌位資料
|
||||
createTabletRecord() {
|
||||
const data = {
|
||||
...this.newTablet,
|
||||
registrantCode: this.registrant.registrantCode,
|
||||
};
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/pw/create', data)
|
||||
.then(() => {
|
||||
alert('牌位資料已新增!');
|
||||
this.creatingTablet = false;
|
||||
this.getRegistrantByCodeMethod(this.registrantCode);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
alert('新增失敗!');
|
||||
});
|
||||
},
|
||||
getPositionList(areaId) {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/position/shortlist',
|
||||
{
|
||||
params: {
|
||||
areaId: areaId
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
this.positionList = res.data
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
});
|
||||
},
|
||||
getArea() {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/area/getereawithposition')
|
||||
.then((res) => {
|
||||
this.areaList = res.data;
|
||||
})
|
||||
.catch();
|
||||
},
|
||||
onAreaChange() {
|
||||
//獲取有神位的區域
|
||||
if (!this.selectedArea) {
|
||||
this.positionList = [];
|
||||
return; // 如果沒有選擇,不請求
|
||||
}
|
||||
this.getPositionList(this.selectedArea)
|
||||
|
||||
},
|
||||
chooseNewPositionMethod(newPos) {
|
||||
this.newPositionEntity = newPos
|
||||
},
|
||||
closeChoosePositionDialogMethod() {
|
||||
this.isShowPositionDialog = false;
|
||||
this.selectedArea = "";
|
||||
this.positionList = [];
|
||||
},
|
||||
cancelChoosePositionMethod() {
|
||||
this.newPositionEntity = null;
|
||||
this.closeChoosePositionDialogMethod()
|
||||
},
|
||||
saveChoosePositionMethod() {
|
||||
this.newPositionId = this.newPositionEntity.positionId
|
||||
this.closeChoosePositionDialogMethod()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getRegistrantByCodeMethod(this.registrantCode);
|
||||
this.getArea()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
.card {
|
||||
border: 1px solid #ccc;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 5px;
|
||||
background-color: #fafafa;
|
||||
width: 90%;
|
||||
max-width: 900px;
|
||||
min-width: 300px; /* 最小寬度防止太窄 */
|
||||
margin: 0 auto; /* 居中 */
|
||||
}
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 150px); /* 6列 */
|
||||
grid-auto-rows: 150px; /* 行高 */
|
||||
gap: 10px;
|
||||
}
|
||||
.status-available {
|
||||
background-color: #d4edda;
|
||||
border-color: #28a745;
|
||||
}
|
||||
|
||||
/* 維護中(黃色) */
|
||||
.status-maintenance {
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffc107;
|
||||
}
|
||||
|
||||
/* 已使用(灰色) */
|
||||
.status-used {
|
||||
background-color: #e2e3e5;
|
||||
border-color: #6c757d;
|
||||
}
|
||||
/* 可以使用(綠色) */
|
||||
.status-canuse {
|
||||
background-color: #d4edda; /* 淺綠色背景 */
|
||||
border-color: #28a745; /* 綠色邊框 */
|
||||
color: #155724; /* 深綠色文字 */
|
||||
}
|
||||
|
||||
/* 不能使用(紅色) */
|
||||
.status-cannotuse {
|
||||
background-color: #f8d7da; /* 淺紅色背景 */
|
||||
border-color: #dc3545; /* 紅色邊框 */
|
||||
color: #721c24; /* 深紅文字 */
|
||||
}
|
||||
.grid-item {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 1px 3px rgba(0,0,0,0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.position-name {
|
||||
background-color: #f0f0f0;
|
||||
padding: 4px 8px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.position-content {
|
||||
flex-grow: 1;
|
||||
padding: 3px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
</asp:Content>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public partial class admin_ancestraltablet_ancestraltabletuselist_edit : MyWeb.config
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
192
web/admin/ancestraltablet/ancestraltabletuselist/index.aspx
Normal file
192
web/admin/ancestraltablet/ancestraltabletuselist/index.aspx
Normal file
@@ -0,0 +1,192 @@
|
||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="admin_ancestraltablet_ancestraltabletuselist_index" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||
<nav>
|
||||
<!--
|
||||
<a :href="'create.aspx'" class="btn btn-primary">
|
||||
新增使用申請
|
||||
</a>
|
||||
-->
|
||||
<div style="display: inline">
|
||||
<span>
|
||||
查詢條件 :
|
||||
</span>
|
||||
<input v-model="search.registrantUserName" class="form-control" style="display:inline-block; width: auto;"
|
||||
placeholder="請輸入登記人"
|
||||
/>
|
||||
<button type="button" class="btn btn-primary" @click="handleSearch">搜尋</button>
|
||||
<button type="button" class="btn btn-primary" @click="clearSearch">清除條件</button>
|
||||
</div>
|
||||
</nav>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||
神主牌使用記錄
|
||||
<div>
|
||||
<v-data-table
|
||||
:items="registrantList"
|
||||
:headers="headers"
|
||||
hide-default-footer>
|
||||
<template #item.registerdate="{item}">
|
||||
{{item.registerDate |timeString('YYYY-MM-DD')}}
|
||||
</template>
|
||||
<template #item.startdate="{item}">
|
||||
{{item.startDate |timeString('YYYY-MM-DD')}}
|
||||
</template>
|
||||
<template #item.enddate="{item}">
|
||||
{{item.endDate |timeString('YYYY-MM-DD')}}
|
||||
</template>
|
||||
<template #item.createdat="{item}">
|
||||
{{item.createdAt |timeString('YYYY-MM-DD HH:MM')}}
|
||||
</template>
|
||||
<template #item.islongterm="{item}">
|
||||
{{item.isLongTerm ? "是": "否"}}
|
||||
</template>
|
||||
<template #item.isactive="{item}">
|
||||
{{item.isActive ? "是" : "否"}}
|
||||
</template>
|
||||
<template #item.actions="{item}">
|
||||
<a :href="'detail.aspx?registrantCode=' + item.registrantCode" class="btn btn-primary">詳細資訊</a>
|
||||
</template>
|
||||
</v-data-table>
|
||||
<v-container>
|
||||
<v-row class="align-baseline" wrap="false">
|
||||
<v-col cols="12" md="8">
|
||||
<v-pagination
|
||||
v-model="options.page"
|
||||
:length="pageCount">
|
||||
</v-pagination>
|
||||
</v-col>
|
||||
<v-col class="text-truncate text-right" cols="12" md="2">
|
||||
共 {{ total }} 筆, 頁數:
|
||||
</v-col>
|
||||
<v-col cols="6" md="1">
|
||||
<v-text-field
|
||||
v-model="options.page"
|
||||
type="number"
|
||||
hide-details
|
||||
dense
|
||||
min="1"
|
||||
:max="pageCount"
|
||||
@input="options.page = parseInt($event, 10)"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<!-- 每頁條數選擇 -->
|
||||
<v-col cols="12" md="1">
|
||||
<v-select
|
||||
v-model="options.itemsPerPage"
|
||||
:items="[5, 10, 20, 50]"
|
||||
label="每頁條數"
|
||||
dense
|
||||
hide-details
|
||||
style="width: 100px;"
|
||||
></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||
<script>
|
||||
Vue.filter('timeString', function (value, myFormat) {
|
||||
return value == null || value == "" ? "" : moment(value).format(myFormat || 'YYYY-MM-DD, HH:mm:ss');
|
||||
});
|
||||
new Vue({
|
||||
el: "#app",
|
||||
vuetify: new Vuetify(vuetify_options),
|
||||
data() {
|
||||
return {
|
||||
registrantList: [],
|
||||
headers: [
|
||||
{ text: '登記編號', value: 'registrantCode' },
|
||||
{ text: '姓名', value: 'name' },
|
||||
{ text: '電話', value: 'phone' },
|
||||
{ text: '住址', value: 'address' },
|
||||
{ text: '登記日期', value: 'registerdate' },
|
||||
{ text: '費用', value: 'price' },
|
||||
{ text: '牌位編號', value: 'positionId' },
|
||||
{ text: '開始時間', value: 'startdate' },
|
||||
{ text: '結束時間', value: 'enddate' },
|
||||
{ text: '是否長期', value: 'islongterm' },
|
||||
{ text: '是否有效', value: 'isactive' },
|
||||
{ text: '創建時間', value: 'createdat' },
|
||||
{ text: '', value: 'actions' },
|
||||
],
|
||||
options: {
|
||||
page: 1, // 當前頁
|
||||
itemsPerPage: 10, // 每頁條數
|
||||
sortBy: [],
|
||||
sortDesc: []
|
||||
},
|
||||
search: {
|
||||
registrantUserName: null,
|
||||
},
|
||||
total: 0,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getRegistrantListMethod() {
|
||||
axios.get(HTTP_HOST + 'api/ancestraltablet/registrant/getlist')
|
||||
.then((res) => {
|
||||
this.registrantList = res.data;
|
||||
}).catch((error) => {
|
||||
alert("載入失敗")
|
||||
})
|
||||
},
|
||||
getRegistrantListByPageMethod() {
|
||||
if (this.loading) return;
|
||||
this.loading = true;
|
||||
axios.post(HTTP_HOST + 'api/ancestraltablet/registrant/getlistbypage', {
|
||||
page: this.options.page,
|
||||
pageSize: this.options.itemsPerPage,
|
||||
searchName: this.search.registrantUserName
|
||||
})
|
||||
.then((res) => {
|
||||
this.registrantList = res.data.data;
|
||||
this.total = res.data.total;
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
resetTableOptions() {
|
||||
this.options = {
|
||||
page: 1,
|
||||
itemsPerPage: 10,
|
||||
sortBy: [],
|
||||
sortDesc: []
|
||||
};
|
||||
},
|
||||
clearSearch() {
|
||||
this.search.registrantUserName = null;
|
||||
this.resetTableOptions();
|
||||
},
|
||||
handleSearch() {
|
||||
this.resetTableOptions();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
handler() {
|
||||
this.getRegistrantListByPageMethod();
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getRegistrantListByPageMethod()
|
||||
},
|
||||
computed: {
|
||||
pageCount() {
|
||||
return Math.ceil(this.total / this.options.itemsPerPage)
|
||||
},
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
</asp:Content>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public partial class admin_ancestraltablet_ancestraltabletuselist_index : MyWeb.config
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1084,7 +1084,7 @@
|
||||
newCheckoutDate: this.guadanguest.xuzhu.newCheckoutDate
|
||||
};
|
||||
|
||||
axios.post('/api/guadanorderguest/xuzhu', payload)
|
||||
axios.post(HTTP_HOST + 'api/guadanorderguest/xuzhu', payload)
|
||||
.then((res) => {
|
||||
this.$refs.messageModal.open({
|
||||
title: '续住成功',
|
||||
@@ -1113,13 +1113,13 @@
|
||||
},
|
||||
//续住相關方法--------------------end
|
||||
getActivityList() {
|
||||
axios.post('/api/activity/GetList?page=1&pageSize=500', { kind: 0, subject: "" })
|
||||
axios.post(HTTP_HOST + 'api/activity/GetList?page=1&pageSize=500', { kind: 0, subject: "" })
|
||||
.then((res) => {
|
||||
this.activityList = res.data.list
|
||||
})
|
||||
},
|
||||
getavailablebedcountbytime(startTime, endTime) {
|
||||
axios.get('/api/region/bed/getavailablebedcountbytime', {
|
||||
axios.get(HTTP_HOST + 'api/region/bed/getavailablebedcountbytime', {
|
||||
params: {
|
||||
startTime: startTime,
|
||||
endTime: endTime
|
||||
@@ -1141,7 +1141,7 @@
|
||||
},
|
||||
confirmAllocation() {
|
||||
//確認分配
|
||||
axios.post('/api/region/bed/confirmallocation', {
|
||||
axios.post(HTTP_HOST + 'api/region/bed/confirmallocation', {
|
||||
preBeds: this.automaticBedAllocation.preBeds,
|
||||
orderNo: this.guadanorder.order_form.orderNo,
|
||||
checkInAt: this.guadanorder.order_form.startdate,
|
||||
@@ -1169,7 +1169,7 @@
|
||||
CheckInAt: this.guadanorder.order_form.startdate || new Date(), // 入住時間
|
||||
CheckOutAt: this.guadanorder.order_form.enddate || null // 退房時間,可為空
|
||||
};
|
||||
axios.post('/api/region/bed/preallocation', payload)
|
||||
axios.post(HTTP_HOST + 'api/region/bed/preallocation', payload)
|
||||
.then(res => {
|
||||
this.automaticBedAllocation.preBeds = res.data.data;
|
||||
})
|
||||
@@ -1217,7 +1217,7 @@
|
||||
getMultiSelectFollowers: function () {
|
||||
var fm = this.automaticBedAllocation.followerModal;
|
||||
var self = this;
|
||||
axios.post('/api/lianyou/getfollowers', null, {
|
||||
axios.post(HTTP_HOST + 'api/lianyou/getfollowers', null, {
|
||||
params: {
|
||||
page: fm.page,
|
||||
pageSize: fm.pageSize,
|
||||
@@ -1288,7 +1288,7 @@
|
||||
},
|
||||
getGuadanOrderById() {
|
||||
if (this.guadanorder.order_form.uuid) {
|
||||
axios.get('/api/guadan/getorderbyid', {
|
||||
axios.get(HTTP_HOST + 'api/guadan/getorderbyid', {
|
||||
params: {
|
||||
orderId: this.guadanorder.order_form.uuid
|
||||
}
|
||||
@@ -1307,7 +1307,7 @@
|
||||
},
|
||||
getGuadanOrderGuestByOrderNo() {
|
||||
if (this.guadanorder.order_form.orderNo) {
|
||||
axios.get('/api/guadanorderguest/getbyorderno', {
|
||||
axios.get(HTTP_HOST + 'api/guadanorderguest/getbyorderno', {
|
||||
params: {
|
||||
orderNo: this.guadanorder.order_form.orderNo
|
||||
}
|
||||
@@ -1317,7 +1317,7 @@
|
||||
}
|
||||
},
|
||||
getGuadanOrderStatus() {
|
||||
axios.get('/api/region/guadan/status/list')
|
||||
axios.get(HTTP_HOST + 'api/region/guadan/status/list')
|
||||
.then((res) => {
|
||||
this.guadanorder.status_items = res.data;
|
||||
})
|
||||
@@ -1326,7 +1326,7 @@
|
||||
if (!this.validateOrderForm()) {
|
||||
return;
|
||||
}
|
||||
axios.post('/api/guadan/create', this.guadanorder.order_form)
|
||||
axios.post(HTTP_HOST + 'api/guadan/create', this.guadanorder.order_form)
|
||||
.then((res => {
|
||||
this.$refs.messageModal.open({
|
||||
title: '掛單提示',
|
||||
@@ -1350,7 +1350,7 @@
|
||||
if (!this.validateOrderForm()) {
|
||||
return;
|
||||
}
|
||||
axios.post('/api/guadan/update', this.guadanorder.order_form)
|
||||
axios.post(HTTP_HOST + 'api/guadan/update', this.guadanorder.order_form)
|
||||
.then((res => {
|
||||
this.$refs.messageModal.open({
|
||||
title: '掛單提示',
|
||||
@@ -1495,13 +1495,13 @@
|
||||
|
||||
},
|
||||
createCheckInGuest() {
|
||||
return axios.post('/api/guadanorderguest/create', this.checkInGuest.inGuest)
|
||||
return axios.post(HTTP_HOST + 'api/guadanorderguest/create', this.checkInGuest.inGuest)
|
||||
},
|
||||
checkBedAndFollower() {
|
||||
this.checkInGuest.inGuest
|
||||
},
|
||||
getGuadanGuestStatus() {
|
||||
axios.get('/api/region/bed/status/list')
|
||||
axios.get(HTTP_HOST + 'api/region/bed/status/list')
|
||||
.then((res) => {
|
||||
this.checkInGuest.status = res.data.filter(item => item.category === 4 && item.code != '404');
|
||||
})
|
||||
@@ -1524,7 +1524,7 @@
|
||||
pageSize: itemsPerPage,
|
||||
searchName: this.selectGuestModal.searchNameOrPhone
|
||||
};
|
||||
axios.post('/api/lianyou/getfollowers', null, {
|
||||
axios.post(HTTP_HOST + 'api/lianyou/getfollowers', null, {
|
||||
params: params
|
||||
}).then((res) => {
|
||||
this.selectGuestModal.items = res.data.data
|
||||
@@ -1559,7 +1559,7 @@
|
||||
},
|
||||
async saveEditGuadanOrderGuest() {
|
||||
try {
|
||||
const res = await axios.post('/api/guadanorderguest/update', this.checkInGuest.inGuest)
|
||||
const res = await axios.post(HTTP_HOST + 'api/guadanorderguest/update', this.checkInGuest.inGuest)
|
||||
this.getGuadanOrderGuestByOrderNo();
|
||||
this.closeCheckInModal();
|
||||
} catch (error) {
|
||||
@@ -1570,7 +1570,7 @@
|
||||
|
||||
},
|
||||
deleteGuadanOrderGuest(guest) {
|
||||
axios.post('/api/guadanorderguest/cancel?uuid=' + guest.uuid)
|
||||
axios.post(HTTP_HOST + 'api/guadanorderguest/cancel?uuid=' + guest.uuid)
|
||||
.then((res) => {
|
||||
this.guadanguest.items = this.guadanguest.items.filter(i => i.uuid != guest.uuid);
|
||||
}).catch((error) => {
|
||||
@@ -1628,7 +1628,7 @@
|
||||
|
||||
//床位選擇相關方法----------------start
|
||||
async loadRegions() {
|
||||
const res = await axios.post('/api/region/getRegionList');
|
||||
const res = await axios.post(HTTP_HOST + 'api/region/getRegionList');
|
||||
this.region_modal.regions = res.data;
|
||||
},
|
||||
async loadRegionsByGender() {
|
||||
@@ -1643,7 +1643,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
const res = await axios.post('/api/region/getRegionListByGender', {
|
||||
const res = await axios.post(HTTP_HOST + 'api/region/getRegionListByGender', {
|
||||
IsMale: isMale
|
||||
});
|
||||
|
||||
@@ -1660,7 +1660,7 @@
|
||||
this.region_modal.selectedType = 'room';
|
||||
this.region_modal.currentSelectBeds = room.beds;
|
||||
if (this.checkInGuest.inGuest.checkInAt && this.checkInGuest.inGuest.checkOutAt) {
|
||||
axios.get('/api/region/room/bed/list', {
|
||||
axios.get(HTTP_HOST + 'api/region/room/bed/list', {
|
||||
params: {
|
||||
roomUuid: room.uuid,
|
||||
StartTime: this.checkInGuest.inGuest.checkInAt,
|
||||
@@ -1678,7 +1678,7 @@
|
||||
},
|
||||
GetRegionRoomBedListByRoomId(roomUuid) {
|
||||
if (this.checkInGuest.inGuest.checkInAt && this.checkInGuest.inGuest.checkOutAt) {
|
||||
axios.get('/api/region/bed/list')
|
||||
axios.get(HTTP_HOST + 'api/region/bed/list')
|
||||
.then((res) => {
|
||||
|
||||
})
|
||||
|
||||
@@ -198,7 +198,7 @@ button:hover {
|
||||
}
|
||||
if (this.loading) return;
|
||||
this.loading = true;
|
||||
axios.post('/api/guadan/guest/query/list',
|
||||
axios.post(HTTP_HOST + 'api/guadan/guest/query/list',
|
||||
{
|
||||
page: this.options.page,
|
||||
pageSize: this.options.itemsPerPage,
|
||||
|
||||
@@ -72,40 +72,40 @@
|
||||
</template>
|
||||
</v-data-table>
|
||||
<v-container>
|
||||
<v-row class="align-baseline" wrap="false">
|
||||
<v-col cols="12" md="8">
|
||||
<v-pagination
|
||||
v-model="options.page"
|
||||
:length="pageCount">
|
||||
</v-pagination>
|
||||
</v-col>
|
||||
<v-col class="text-truncate text-right" cols="12" md="2">
|
||||
共 {{ total }} 筆, 頁數:
|
||||
</v-col>
|
||||
<v-col cols="6" md="1">
|
||||
<v-text-field
|
||||
v-model="options.page"
|
||||
type="number"
|
||||
hide-details
|
||||
dense
|
||||
min="1"
|
||||
:max="pageCount"
|
||||
@input="options.page = parseInt($event, 10)"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<!-- 每頁條數選擇 -->
|
||||
<v-col cols="12" md="1">
|
||||
<v-select
|
||||
v-model="options.itemsPerPage"
|
||||
:items="[5, 10, 20, 50]"
|
||||
label="每頁條數"
|
||||
dense
|
||||
hide-details
|
||||
style="width: 100px;"
|
||||
></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
<v-row class="align-baseline" wrap="false">
|
||||
<v-col cols="12" md="8">
|
||||
<v-pagination
|
||||
v-model="options.page"
|
||||
:length="pageCount">
|
||||
</v-pagination>
|
||||
</v-col>
|
||||
<v-col class="text-truncate text-right" cols="12" md="2">
|
||||
共 {{ total }} 筆, 頁數:
|
||||
</v-col>
|
||||
<v-col cols="6" md="1">
|
||||
<v-text-field
|
||||
v-model="options.page"
|
||||
type="number"
|
||||
hide-details
|
||||
dense
|
||||
min="1"
|
||||
:max="pageCount"
|
||||
@input="options.page = parseInt($event, 10)"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<!-- 每頁條數選擇 -->
|
||||
<v-col cols="12" md="1">
|
||||
<v-select
|
||||
v-model="options.itemsPerPage"
|
||||
:items="[5, 10, 20, 50]"
|
||||
label="每頁條數"
|
||||
dense
|
||||
hide-details
|
||||
style="width: 100px;"
|
||||
></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
<!-- 更新修改確認彈出視窗 -->
|
||||
<message-modal ref="messageModal"></message-modal>
|
||||
@@ -198,7 +198,7 @@
|
||||
},
|
||||
getGuadanOrder() {
|
||||
if (this.loading) return;
|
||||
axios.post('/api/guadan/list', {
|
||||
axios.post(HTTP_HOST + 'api/guadan/list', {
|
||||
startDate: this.search.startDate,
|
||||
endDate: this.search.endDate,
|
||||
guadanUser: this.search.guadanUser,
|
||||
@@ -219,7 +219,7 @@
|
||||
this.$refs.confirmModal.open({
|
||||
message: '確認取消掛單?',
|
||||
onConfirm: () => {
|
||||
axios.post('/api/guadan/cancel', null, {
|
||||
axios.post(HTTP_HOST + 'api/guadan/cancel', null, {
|
||||
params: {
|
||||
uuid: order.uuid
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@
|
||||
saveAs(new Blob([wbout], { type: "application/octet-stream" }), "statistics.xlsx");
|
||||
},
|
||||
GetGuadanStatistics() {
|
||||
axios.get('/api/guadanStatistics/GetGuadanStatistics')
|
||||
axios.get(HTTP_HOST + 'api/guadanStatistics/GetGuadanStatistics')
|
||||
.then((res) => {
|
||||
this.guadanStatistics = res.data.guadanStatistics;
|
||||
})
|
||||
|
||||
@@ -429,7 +429,7 @@
|
||||
},
|
||||
methods: {
|
||||
getActivityList() {
|
||||
axios.post('/api/activity/GetList?page=1&pageSize=500', { kind: 0, subject: "" })
|
||||
axios.post(HTTP_HOST + 'api/activity/GetList?page=1&pageSize=500', { kind: 0, subject: "" })
|
||||
.then((res) => {
|
||||
this.activityList = res.data.list
|
||||
})
|
||||
@@ -467,7 +467,7 @@
|
||||
},
|
||||
getGuadanOrderById() {
|
||||
if (this.guadanorder.order_form.uuid) {
|
||||
axios.get('/api/guadan/getorderbyid', {
|
||||
axios.get(HTTP_HOST + 'api/guadan/getorderbyid', {
|
||||
params: {
|
||||
orderId: this.guadanorder.order_form.uuid
|
||||
}
|
||||
@@ -486,7 +486,7 @@
|
||||
},
|
||||
getGuadanOrderGuestByOrderNo() {
|
||||
if (this.guadanorder.order_form.orderNo) {
|
||||
axios.get('/api/guadanorderguest/getbyorderno', {
|
||||
axios.get(HTTP_HOST + 'api/guadanorderguest/getbyorderno', {
|
||||
params: {
|
||||
orderNo: this.guadanorder.order_form.orderNo
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
},
|
||||
methods: {
|
||||
getStatusList() {
|
||||
axios.get('/api/region/bed/status/list')
|
||||
axios.get(HTTP_HOST + 'api/region/bed/status/list')
|
||||
.then((res) => {
|
||||
this.items = res.data
|
||||
this.loading = false;
|
||||
@@ -73,7 +73,7 @@
|
||||
})
|
||||
},
|
||||
deleteStatus(item) {
|
||||
axios.post('/api/region/bed/status/delete', null, {
|
||||
axios.post(HTTP_HOST + 'api/region/bed/status/delete', null, {
|
||||
params: { code: item.code }
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
@@ -316,7 +316,7 @@
|
||||
unoccupied: this.filter.unoccupied,
|
||||
gender: this.filter.Gender,
|
||||
};
|
||||
axios.post('/api/region/list', payload)
|
||||
axios.post(HTTP_HOST + 'api/region/list', payload)
|
||||
.then((res) => {
|
||||
this.regions = res.data.regions;
|
||||
this.summary = res.data.summary; // 保存後端統計
|
||||
@@ -347,7 +347,7 @@
|
||||
console.log(this.filter.Gender);
|
||||
},
|
||||
getRegionWithRoom() {
|
||||
axios.get('/api/region/regionwithroom')
|
||||
axios.get(HTTP_HOST + 'api/region/regionwithroom')
|
||||
.then((res) => {
|
||||
this.filter.areas = res.data;
|
||||
})
|
||||
|
||||
@@ -578,7 +578,7 @@
|
||||
this.expandAllFlag = false;
|
||||
},
|
||||
async loadRegions() {
|
||||
const res = await axios.post('/api/region/getRegionList');
|
||||
const res = await axios.post(HTTP_HOST + 'api/region/getRegionList');
|
||||
this.regions = res.data;
|
||||
this.flatRegions = this.flatten(res.data);
|
||||
if (this.currentSelectRoom) {
|
||||
@@ -586,7 +586,7 @@
|
||||
}
|
||||
},
|
||||
loadRegionType() {
|
||||
axios.post('/api/region/getRegionType')
|
||||
axios.post(HTTP_HOST + 'api/region/getRegionType')
|
||||
.then(res => {
|
||||
this.regionTypes = res.data
|
||||
});
|
||||
@@ -799,7 +799,7 @@
|
||||
});
|
||||
},
|
||||
confirmDeleteBed(bed) {
|
||||
axios.post('/api/region/bed/delete', null, {
|
||||
axios.post(HTTP_HOST + 'api/region/bed/delete', null, {
|
||||
params: { uuid: bed.uuid }
|
||||
}) // 假設後端吃的是 id
|
||||
.then(() => {
|
||||
@@ -840,7 +840,7 @@
|
||||
async saveEditBed() {
|
||||
|
||||
try {
|
||||
await axios.post('/api/region/bed/update', this.room_bed.newBedForm);
|
||||
await axios.post(HTTP_HOST + 'api/region/bed/update', this.room_bed.newBedForm);
|
||||
this.room_bed.showBedModal = false;
|
||||
|
||||
const updated = this.room_bed.newBedForm;
|
||||
@@ -882,7 +882,7 @@
|
||||
},
|
||||
getBedStatus() {
|
||||
//獲取床位狀態
|
||||
axios.get('/api/region/bed/status/list')
|
||||
axios.get(HTTP_HOST + 'api/region/bed/status/list')
|
||||
.then((res) => {
|
||||
this.room_bed.bed_status = res.data;
|
||||
})
|
||||
@@ -907,7 +907,7 @@
|
||||
});
|
||||
return;
|
||||
}
|
||||
axios.post('/api/region/room/create', this.room.room_form)
|
||||
axios.post(HTTP_HOST + 'api/region/room/create', this.room.room_form)
|
||||
.then((res) => {
|
||||
this.room.showCreateRoomDialog = false;
|
||||
this.currentSelectRegion.rooms.push(res.data);
|
||||
@@ -924,7 +924,7 @@
|
||||
},
|
||||
async roomUpdate() {
|
||||
try {
|
||||
const res = await axios.post('/api/region/room/update', this.room.room_form);
|
||||
const res = await axios.post(HTTP_HOST + 'api/region/room/update', this.room.room_form);
|
||||
this.$refs.messageModal.open({
|
||||
message: '客房資料更新成功'
|
||||
});
|
||||
@@ -950,7 +950,7 @@
|
||||
},
|
||||
|
||||
roomDelete() {
|
||||
axios.post('/api/region/room/delete', { uuid: this.currentSelectRoom.uuid })
|
||||
axios.post(HTTP_HOST + 'api/region/room/delete', { uuid: this.currentSelectRoom.uuid })
|
||||
.then((res) => {
|
||||
const region = this.findRegionById(this.regions, this.currentSelectRoom.regionUuid)//當前room所在的region
|
||||
if (region) {
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
},
|
||||
methods: {
|
||||
getRegionTypeList() {
|
||||
axios.post('/api/regiontype/getreiontypelist')
|
||||
axios.post(HTTP_HOST + 'api/regiontype/getreiontypelist')
|
||||
.then((res) => {
|
||||
this.items = res.data;
|
||||
})
|
||||
@@ -71,7 +71,7 @@
|
||||
'title': '刪除提示',
|
||||
'message': `確定要刪除 ${item.name} ?`,
|
||||
onConfirm: () => {
|
||||
axios.post('/api/regiontype/delete',null, {
|
||||
axios.post(HTTP_HOST + 'api/regiontype/delete',null, {
|
||||
params: { uuid: item.uuid }
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
Reference in New Issue
Block a user