| | |
| | | <el-button v-permission="'config:visit-reasons:create'" type="primary" @click="openCreate">新增</el-button> |
| | | </div> |
| | | |
| | | <el-table :data="rows" v-loading="loading" stripe border> |
| | | <el-table-column label="序号" width="72" type="index" :index="indexMethod" /> |
| | | <el-table-column prop="reasonName" label="来访事由" min-width="220" show-overflow-tooltip /> |
| | | <el-table-column label="创建时间" width="180"> |
| | | <template #default="{ row }">{{ formatTime(row.createTime) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="160" fixed="right"> |
| | | <template #default="{ row }"> |
| | | <div class="table-ops"> |
| | | <el-button v-permission="'config:visit-reasons:update'" type="primary" link @click="openEdit(row)">编辑</el-button> |
| | | <el-button v-permission="'config:visit-reasons:delete'" type="danger" link @click="confirmDelete(row)">删除</el-button> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="table-wrap"> |
| | | <el-table :data="rows" v-loading="loading" stripe border height="100%"> |
| | | <el-table-column label="序号" width="72" type="index" :index="indexMethod" /> |
| | | <el-table-column prop="reasonName" label="来访事由" min-width="220" show-overflow-tooltip /> |
| | | <el-table-column prop="sortOrder" label="排序" width="100" /> |
| | | <el-table-column label="创建时间" width="180"> |
| | | <template #default="{ row }">{{ formatTime(row.createTime) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="160" fixed="right"> |
| | | <template #default="{ row }"> |
| | | <div class="table-ops"> |
| | | <el-button |
| | | v-if="!isOtherReason(row)" |
| | | v-permission="'config:visit-reasons:update'" |
| | | type="primary" |
| | | link |
| | | @click="openEdit(row)" |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | v-if="!isOtherReason(row)" |
| | | v-permission="'config:visit-reasons:delete'" |
| | | type="primary" |
| | | link |
| | | @click="confirmDelete(row)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <el-pagination |
| | | class="pager" |
| | | background |
| | | layout="prev, pager, next" |
| | | layout="sizes, prev, pager, next" |
| | | :total="total" |
| | | :page-size="size" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | v-model:current-page="page" |
| | | @current-change="load" |
| | | @size-change="onSizeChange" |
| | | /> |
| | | |
| | | <el-dialog v-model="dlg" :title="dlgTitle" width="460px" destroy-on-close> |
| | | <el-form :model="form" label-width="92px"> |
| | | <el-form-item label="来访事由" required> |
| | | <el-input v-model="form.reasonName" maxlength="128" show-word-limit placeholder="请输入来访事由" /> |
| | | <el-input v-model="form.reasonName" maxlength="15" placeholder="请输入15个字以内" /> |
| | | </el-form-item> |
| | | <el-form-item label="排序" required> |
| | | <el-input-number |
| | | v-model="form.sortOrder" |
| | | :min="0" |
| | | :max="999999" |
| | | :step="10" |
| | | :controls="false" |
| | | placeholder="请输入排序数字" |
| | | class="w-full" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | import { onMounted, reactive, ref } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import http from "../api/http"; |
| | | import { normalizeFormData } from "../utils/formHelper"; |
| | | |
| | | type Row = { |
| | | id: number; |
| | | uuid: string; |
| | | reasonCode?: string; |
| | | reasonName: string; |
| | | sortOrder: number; |
| | | createTime: string; |
| | | }; |
| | | |
| | |
| | | const form = reactive({ |
| | | uuid: "", |
| | | reasonName: "", |
| | | sortOrder: 0, |
| | | }); |
| | | |
| | | function indexMethod(i: number) { |
| | |
| | | function formatTime(s: string) { |
| | | if (!s) return ""; |
| | | return s.replace("T", " ").slice(0, 19); |
| | | } |
| | | |
| | | function isOtherReason(row: Row) { |
| | | return row.reasonCode === "OTHER" || row.reasonName === "其他"; |
| | | } |
| | | |
| | | async function load() { |
| | |
| | | editingId.value = null; |
| | | form.uuid = ""; |
| | | form.reasonName = ""; |
| | | form.sortOrder = rows.value.reduce((max, row) => Math.max(max, Number(row.sortOrder) || 0), 0) + 10; |
| | | dlg.value = true; |
| | | } |
| | | |
| | | function onSizeChange(nextSize: number) { |
| | | size.value = nextSize; |
| | | page.value = 1; |
| | | load(); |
| | | } |
| | | |
| | | function openEdit(row: Row) { |
| | | if (isOtherReason(row)) { |
| | | return; |
| | | } |
| | | dlgTitle.value = "编辑来访事由"; |
| | | editingId.value = row.id; |
| | | form.uuid = row.uuid; |
| | | form.reasonName = row.reasonName || ""; |
| | | form.sortOrder = Number(row.sortOrder) || 0; |
| | | dlg.value = true; |
| | | } |
| | | |
| | |
| | | ElMessage.warning("请填写来访事由"); |
| | | return; |
| | | } |
| | | if (form.sortOrder == null || Number(form.sortOrder) < 0) { |
| | | ElMessage.warning("请输入排序数字"); |
| | | return; |
| | | } |
| | | saving.value = true; |
| | | try { |
| | | // 处理表单数据:字符串 null/undefined 转为空字符串 |
| | | const normalized = normalizeFormData({ |
| | | reasonName: form.reasonName, |
| | | sortOrder: Number(form.sortOrder) || 0, |
| | | }); |
| | | |
| | | if (editingId.value == null) { |
| | | await http.post("/config/visit-reasons/manage", { reasonName }); |
| | | await http.post("/config/visit-reasons/manage", normalized); |
| | | ElMessage.success("已新增"); |
| | | page.value = 1; |
| | | } else { |
| | | await http.put(`/config/visit-reasons/manage/${editingId.value}`, { |
| | | uuid: form.uuid, |
| | | reasonName, |
| | | ...normalized, |
| | | }); |
| | | ElMessage.success("已保存"); |
| | | } |
| | |
| | | } |
| | | |
| | | function confirmDelete(row: Row) { |
| | | if (isOtherReason(row)) { |
| | | return; |
| | | } |
| | | ElMessageBox.confirm(`确认删除来访事由「${row.reasonName}」?`, "删除确认", { type: "warning" }) |
| | | .then(async () => { |
| | | try { |
| | |
| | | <style scoped> |
| | | .page { |
| | | padding: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: calc(100vh - 190px); |
| | | min-height: 420px; |
| | | } |
| | | .header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | flex: none; |
| | | } |
| | | .section-title { |
| | | font-size: 16px; |
| | |
| | | border-left: 3px solid #409eff; |
| | | color: #303133; |
| | | } |
| | | .table-wrap { |
| | | flex: 1; |
| | | min-height: 0; |
| | | } |
| | | .pager { |
| | | margin-top: 12px; |
| | | justify-content: flex-end; |
| | | flex: none; |
| | | } |
| | | </style> |