神祖牌位管理模組,掛單模組前端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>
|
||||
Reference in New Issue
Block a user