|
|
@@ -11,26 +11,44 @@
|
|
|
</a-form-item>
|
|
|
<a-form-item>
|
|
|
<a-space>
|
|
|
- <a-button type="primary" :loading="loading" @click="handleQuery">查询</a-button>
|
|
|
- <a-button @click="resetQuery">重置</a-button>
|
|
|
- <a-button v-hasPermi="[moduleConfig.perm + ':add']" type="primary" @click="openForm()">新增</a-button>
|
|
|
- <a-button v-hasPermi="[moduleConfig.perm + ':export']" @click="handleExport">导出</a-button>
|
|
|
+ <a-button type="primary" :loading="loading" @click="handleQuery"><BearJiaIcon icon="SearchOutlined"/>查询</a-button>
|
|
|
+ <a-button @click="resetQuery"><BearJiaIcon icon="LoadingOutlined"/>重置</a-button>
|
|
|
</a-space>
|
|
|
</a-form-item>
|
|
|
</a-form>
|
|
|
</a-card>
|
|
|
|
|
|
- <a-card :bordered="false" class="section">
|
|
|
- <a-table :columns="columns" :data-source="rows" :loading="loading" :pagination="pagination" row-key="id" :scroll="tableScroll" @change="handleTableChange">
|
|
|
+ <a-card ref="tableCardRef" :bordered="false" class="section">
|
|
|
+ <TableToolbar
|
|
|
+ :columns="columns"
|
|
|
+ :selected-columns="selectedColumnKeys"
|
|
|
+ :loading="loading"
|
|
|
+ :export-config="exportConfig"
|
|
|
+ @columnSettingsChange="handleColumnSettingsChange"
|
|
|
+ @refresh="handleQuery"
|
|
|
+ @fullscreen="handleFullscreen"
|
|
|
+ @export="handleExport"
|
|
|
+ @reset="handleTableReset"
|
|
|
+ >
|
|
|
+ <template #left>
|
|
|
+ <a-button v-hasPermi="[moduleConfig.perm + ':add']" type="primary" @click="openForm()"><BearJiaIcon icon="plus-outlined"/>新增</a-button>
|
|
|
+ <a-button v-hasPermi="[moduleConfig.perm + ':remove']" danger type="primary" :disabled="selectedRowKeys.length <= 0" @click="handleBatchDelete"><BearJiaIcon icon="delete-outlined"/>删除</a-button>
|
|
|
+ <a-button v-hasPermi="[moduleConfig.perm + ':export']" @click="handleExport"><BearJiaIcon icon="export-outlined"/>导出</a-button>
|
|
|
+ </template>
|
|
|
+ </TableToolbar>
|
|
|
+ <a-table :columns="displayColumns" :data-source="rows" :loading="loading" :pagination="pagination" row-key="id" :row-selection="rowSelection" :size="tableConfigStore.size" :scroll="tableScroll" @change="handleTableChange">
|
|
|
<template #bodyCell="{ column, record }">
|
|
|
<a-switch v-if="isSwitchColumn(column)" :checked="record[column.dataIndex] === switchCheckedValue(column)" disabled size="small" />
|
|
|
<template v-else-if="column.key === 'operation'">
|
|
|
- <a-space>
|
|
|
- <a v-hasPermi="[moduleConfig.perm + ':edit']" @click="openForm(record)">编辑</a>
|
|
|
- <a-popconfirm :title="'确认删除该' + moduleConfig.title + '?'" @confirm="removeRecord(record)">
|
|
|
- <a v-hasPermi="[moduleConfig.perm + ':remove']" class="danger-link">删除</a>
|
|
|
- </a-popconfirm>
|
|
|
- </a-space>
|
|
|
+ <TableActionBar :record="record" :has-view="false" :has-edit="true" :has-delete="true">
|
|
|
+ <template #edit>
|
|
|
+ <a v-hasPermi="[moduleConfig.perm + ':edit']" class="action-btn edit-btn" @click="openForm(record)"><BearJiaIcon icon="edit-outlined"/>修改</a>
|
|
|
+ </template>
|
|
|
+ <template #delete>
|
|
|
+ <a-divider type="vertical"/>
|
|
|
+ <a v-hasPermi="[moduleConfig.perm + ':remove']" class="action-btn delete-btn" @click="handleDeleteRecord(record)"><BearJiaIcon icon="delete-outlined"/>删除</a>
|
|
|
+ </template>
|
|
|
+ </TableActionBar>
|
|
|
</template>
|
|
|
</template>
|
|
|
</a-table>
|
|
|
@@ -62,10 +80,14 @@
|
|
|
|
|
|
<script setup>
|
|
|
import { computed, reactive, ref } from 'vue';
|
|
|
-import { message } from 'ant-design-vue';
|
|
|
+import { message, Modal } from 'ant-design-vue';
|
|
|
import BearJiaUtil from '@/utils/BearJiaUtil';
|
|
|
import { listStation } from '@/api/config/station';
|
|
|
import { listStationDevice } from '@/api/config/stationDevice';
|
|
|
+import TableActionBar from '@/components/TableActionBar/index.vue';
|
|
|
+import TableToolbar from '@/components/BearJiaProTable/TableToolbar.vue';
|
|
|
+import { useTableConfigStore } from '@/stores/tableConfig';
|
|
|
+import { BearJiaIcon } from '@/utils/BearJiaIcon.js';
|
|
|
|
|
|
const props = defineProps({ moduleConfig: { type: Object, required: true }, api: { type: Object, required: true } });
|
|
|
|
|
|
@@ -75,6 +97,10 @@ const stationOptions = ref([]);
|
|
|
const allDevices = ref([]);
|
|
|
const formOpen = ref(false);
|
|
|
const formRef = ref();
|
|
|
+const selectedRowKeys = ref([]);
|
|
|
+const tableCardRef = ref();
|
|
|
+const selectedColumnKeys = ref([]);
|
|
|
+const tableConfigStore = useTableConfigStore();
|
|
|
const queryParams = reactive({ pageNum: 1, pageSize: 10, stationId: undefined });
|
|
|
const pagination = reactive({ current: 1, pageSize: 10, total: 0, showSizeChanger: true });
|
|
|
const form = reactive({});
|
|
|
@@ -86,9 +112,23 @@ const searchFields = computed(() => props.moduleConfig.search.filter((name) => n
|
|
|
const columns = computed(() => [
|
|
|
{ title: 'ID', dataIndex: 'id', width: 80 },
|
|
|
...props.moduleConfig.columns.map((name) => ({ title: name === 'stationName' ? '场站' : fieldMap.value.get(name)?.[1] || name, dataIndex: name, width: 140, ellipsis: true })),
|
|
|
- { title: '操作', key: 'operation', width: 130, fixed: 'right' }
|
|
|
+ { title: '操作', key: 'operation', dataIndex: 'operation', width: 200, fixed: 'right' }
|
|
|
]);
|
|
|
-const tableScroll = computed(() => ({ x: columns.value.reduce((sum, col) => sum + (col.width || 140), 0) }));
|
|
|
+const storageKey = 'station-config-columns-' + props.moduleConfig.api;
|
|
|
+const readSavedColumns = () => {
|
|
|
+ try {
|
|
|
+ const saved = JSON.parse(localStorage.getItem(storageKey) || 'null');
|
|
|
+ if (Array.isArray(saved) && saved.length > 0) {
|
|
|
+ const valid = saved.filter((k) => columns.value.some((c) => c.dataIndex === k));
|
|
|
+ if (valid.length > 0) return valid;
|
|
|
+ }
|
|
|
+ } catch (e) { /* 忽略存储解析错误 */ }
|
|
|
+ return columns.value.map((c) => c.dataIndex);
|
|
|
+};
|
|
|
+selectedColumnKeys.value = readSavedColumns();
|
|
|
+const displayColumns = computed(() => columns.value.filter((col) => selectedColumnKeys.value.includes(col.dataIndex)));
|
|
|
+const tableScroll = computed(() => ({ x: displayColumns.value.reduce((sum, col) => sum + (col.width || 140), 0) + 40 }));
|
|
|
+const exportConfig = { enabled: true };
|
|
|
const rules = computed(() => ({
|
|
|
...(hasStation.value ? { stationId: [{ required: true, message: '请选择所属场站', trigger: 'change' }] } : {}),
|
|
|
...Object.fromEntries(props.moduleConfig.fields.filter((item) => item[3]).map((item) => [item[0], [{ required: true, message: '请输入' + item[1], trigger: item[2] === 'select' || item[2] === 'device' || item[2] === 'switch' ? 'change' : 'blur' }]]))
|
|
|
@@ -96,6 +136,10 @@ const rules = computed(() => ({
|
|
|
const deviceOptions = computed(() => allDevices.value
|
|
|
.filter((item) => !form.stationId || String(item.stationId) === String(form.stationId))
|
|
|
.map((item) => ({ label: item.deviceName || item.name || item.id, value: item.id, raw: item })));
|
|
|
+const rowSelection = computed(() => ({
|
|
|
+ selectedRowKeys: selectedRowKeys.value,
|
|
|
+ onChange: (keys) => { selectedRowKeys.value = keys; }
|
|
|
+}));
|
|
|
|
|
|
const toOptions = (items = []) => items.map((item) => ({ label: item[0], value: item[1] }));
|
|
|
const isSwitchColumn = (column) => fieldMap.value.get(column.dataIndex)?.[2] === 'switch';
|
|
|
@@ -164,12 +208,51 @@ const submitForm = async () => {
|
|
|
formOpen.value = false;
|
|
|
handleQuery();
|
|
|
};
|
|
|
-const removeRecord = async (record) => {
|
|
|
- await props.api.del(record.id);
|
|
|
- message.success('删除成功');
|
|
|
- handleQuery();
|
|
|
+const handleDeleteRecord = (record) => {
|
|
|
+ Modal.confirm({
|
|
|
+ title: '确认删除',
|
|
|
+ content: `确认删除该${moduleConfig.title}?`,
|
|
|
+ onOk: async () => {
|
|
|
+ await props.api.del(record.id);
|
|
|
+ message.success('删除成功');
|
|
|
+ handleQuery();
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+const handleBatchDelete = () => {
|
|
|
+ if (selectedRowKeys.value.length <= 0) {
|
|
|
+ message.warning('请至少选择一条数据');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Modal.confirm({
|
|
|
+ title: '确认删除',
|
|
|
+ content: `确认删除选中的 ${selectedRowKeys.value.length} 条数据?`,
|
|
|
+ onOk: async () => {
|
|
|
+ await props.api.del(selectedRowKeys.value);
|
|
|
+ message.success('删除成功');
|
|
|
+ selectedRowKeys.value = [];
|
|
|
+ handleQuery();
|
|
|
+ }
|
|
|
+ });
|
|
|
};
|
|
|
const handleExport = () => BearJiaUtil.download('config/' + props.moduleConfig.api + '/export', queryParams, props.moduleConfig.exportName);
|
|
|
+const handleColumnSettingsChange = (keys) => {
|
|
|
+ selectedColumnKeys.value = keys;
|
|
|
+ localStorage.setItem(storageKey, JSON.stringify(keys));
|
|
|
+};
|
|
|
+const handleFullscreen = (isFullscreen) => {
|
|
|
+ const el = tableCardRef.value?.$el || tableCardRef.value;
|
|
|
+ if (isFullscreen) {
|
|
|
+ el?.requestFullscreen?.();
|
|
|
+ } else {
|
|
|
+ document.exitFullscreen?.();
|
|
|
+ }
|
|
|
+};
|
|
|
+const handleTableReset = () => {
|
|
|
+ selectedColumnKeys.value = columns.value.map((c) => c.dataIndex);
|
|
|
+ localStorage.removeItem(storageKey);
|
|
|
+ handleQuery();
|
|
|
+};
|
|
|
|
|
|
loadStations();
|
|
|
loadDevices();
|
|
|
@@ -181,6 +264,5 @@ handleQuery();
|
|
|
.section { margin-top: 12px; }
|
|
|
.query-select { width: 180px; }
|
|
|
.full-input { width: 100%; }
|
|
|
- .danger-link { color: #ff4d4f; }
|
|
|
}
|
|
|
</style>
|