<script lang="ts" setup>
|
import type { FormInstance } from 'ant-design-vue';
|
|
import { computed, nextTick, reactive, ref, toRefs, unref, watch } from 'vue';
|
|
import { ModalClose } from '@jnpf/ui/modal';
|
|
import { $t } from '@vben/locales';
|
|
import { globalShareState } from '@vben-core/shared/global-state';
|
|
import { PlusOutlined, RedoOutlined } from '@ant-design/icons-vue';
|
import { Modal as AModal, Table } from 'ant-design-vue';
|
|
import I18nForm from './I18nFormModal.vue';
|
|
interface State {
|
columns: any[];
|
list: any[];
|
listQuery: any;
|
loading: boolean;
|
selectedRowKeys: any[];
|
selectedRows: any[];
|
total: number;
|
}
|
|
defineOptions({ inheritAttrs: false, name: 'I18nModal' });
|
const props = defineProps({
|
value: { default: '' },
|
});
|
const emit = defineEmits(['update:value', 'change']);
|
defineExpose({ openModal });
|
const { getBaseLangList } = globalShareState.getApi();
|
const i18nFormModalRef = ref(null);
|
const innerValue = ref<string | undefined>(undefined);
|
const selectRow = ref<any>(null);
|
const visible = ref(false);
|
const formElRef = ref<FormInstance>();
|
const tableElRef = ref<any>(null);
|
const indexColumn = {
|
align: 'center',
|
customRender: ({ index }) => index + 1,
|
dataIndex: 'index',
|
key: 'index',
|
title: $t('component.table.index'),
|
width: 50,
|
};
|
const state = reactive<State>({
|
columns: [],
|
loading: false,
|
selectedRowKeys: [],
|
selectedRows: [],
|
total: 0,
|
list: [],
|
listQuery: {
|
currentPage: 1,
|
keyword: '',
|
pageSize: 20,
|
type: 0,
|
},
|
});
|
const { list, listQuery } = toRefs(state);
|
|
const getFormClass = computed(() => {
|
return ['jnpf-basic-form', `jnpf-basic-form--compact`, 'search-form'];
|
});
|
const getPagination = computed<any>(() => {
|
return {
|
current: state.listQuery.currentPage,
|
defaultPageSize: state.listQuery.pageSize,
|
pageSize: state.listQuery.pageSize,
|
pageSizeOptions: ['20', '50', '80', '100'],
|
showQuickJumper: true,
|
showSizeChanger: true,
|
showTotal: (total) => $t('component.table.total', { total }),
|
size: 'small',
|
total: state.total,
|
};
|
});
|
const getRowSelection = computed<any>(() => ({
|
onChange: setSelectedRowKeys,
|
selectedRowKeys: state.selectedRowKeys,
|
type: 'radio',
|
}));
|
const getScrollY = computed(() => window.innerHeight * 0.7 - 52 - 38 - 44);
|
const getTableBindValues: any = computed(() => {
|
return {
|
class: 'jnpf-basic-table',
|
columns: state.columns,
|
loading: state.loading,
|
pagination: unref(getPagination),
|
rowKey: 'code',
|
rowSelection: unref(getRowSelection),
|
customRow,
|
scroll: { y: unref(getScrollY) },
|
size: 'small',
|
};
|
});
|
|
watch(
|
() => unref(props.value),
|
(val) => {
|
setValue(val);
|
},
|
{ immediate: true },
|
);
|
|
function customRow(record: Recordable) {
|
return {
|
onClick: (e: Event) => {
|
e?.stopPropagation();
|
const tr: HTMLElement = (e as MouseEvent).composedPath?.().find((dom: any) => dom.tagName === 'TR') as HTMLElement;
|
if (!tr) return;
|
// 找到radio,检查是否为disabled
|
const radio = tr.querySelector('input[type=radio]');
|
if (!radio || radio.hasAttribute('disabled')) return;
|
state.selectedRowKeys = [record[unref(getTableBindValues).rowKey]];
|
state.selectedRows.push(record);
|
},
|
};
|
}
|
function setValue(value) {
|
innerValue.value = value;
|
}
|
function getForm() {
|
const form = unref(formElRef);
|
if (!form) {
|
throw new Error('form is null!');
|
}
|
return form;
|
}
|
async function openModal() {
|
visible.value = true;
|
nextTick(() => {
|
handleReset();
|
state.selectedRowKeys = innerValue.value ? [innerValue.value] : [];
|
state.selectedRows = [];
|
const tableEl = tableElRef.value?.$el;
|
const bodyEl = tableEl.querySelector('.ant-table-body');
|
bodyEl!.style.height = `${unref(getScrollY)}px`;
|
});
|
}
|
function handleCancel() {
|
visible.value = false;
|
}
|
function handleClear() {
|
state.selectedRowKeys = [];
|
state.selectedRows = [];
|
innerValue.value = '';
|
}
|
function handleSubmit() {
|
if (!state.selectedRowKeys.length && !state.selectedRows.length) {
|
emit('update:value', '');
|
emit('change', '', null);
|
handleCancel();
|
return;
|
}
|
if (!state.selectedRows.length || innerValue.value === state.selectedRows[0].code) return handleCancel();
|
selectRow.value = state.selectedRows[0];
|
innerValue.value = unref(selectRow).code;
|
emit('update:value', unref(selectRow).code);
|
emit('change', unref(selectRow).code, unref(selectRow));
|
handleCancel();
|
}
|
function handleSearch() {
|
state.listQuery.currentPage = 1;
|
state.listQuery.pageSize = 20;
|
initData();
|
}
|
function handleReset() {
|
getForm().resetFields();
|
state.listQuery.keyword = '';
|
handleSearch();
|
}
|
function initData() {
|
state.loading = true;
|
getBaseLangList(state.listQuery)
|
.then((res) => {
|
state.list = res.data.list;
|
state.total = res.data.pagination.total;
|
const columns = res.data.tableHead ? res.data.tableHead.map((item) => ({ dataIndex: item.prop, key: item.prop, title: item.label })) : [];
|
state.columns = [indexColumn, ...columns];
|
state.loading = false;
|
})
|
.catch(() => {
|
state.loading = false;
|
});
|
}
|
function handleTableChange(pagination) {
|
state.listQuery.currentPage = pagination.current;
|
state.listQuery.pageSize = pagination.pageSize;
|
initData();
|
}
|
function setSelectedRowKeys(selectedRowKeys, selectedRows) {
|
state.selectedRowKeys = selectedRowKeys;
|
state.selectedRows = selectedRows;
|
}
|
function addHandle() {
|
const i18nModal = unref(i18nFormModalRef) as any;
|
i18nModal?.openModal();
|
}
|
function reload(isRelease) {
|
if (isRelease) initData();
|
}
|
</script>
|
|
<template>
|
<AModal v-model:open="visible" :title="$t('common.selectI18nCode')" :width="800" class="common-container-modal" :mask-closable="false">
|
<template #closeIcon>
|
<ModalClose :can-fullscreen="false" @cancel="handleCancel" />
|
</template>
|
<template #footer>
|
<a-button type="error" @click="handleClear()">{{ $t('common.cleanText') }}</a-button>
|
<a-button @click="handleCancel()">{{ $t('common.cancelText') }}</a-button>
|
<a-button type="primary" @click="handleSubmit()">{{ $t('common.okText') }}</a-button>
|
</template>
|
<div class="i18n-search-box jnpf-common-search-box-modal">
|
<a-form :colon="false" label-align="right" :model="listQuery" ref="formElRef" :class="getFormClass">
|
<a-row :gutter="10">
|
<a-col :span="8">
|
<a-form-item :label="$t('common.keyword')" name="keyword">
|
<a-input v-model:value="listQuery.keyword" :placeholder="$t('common.enterKeyword')" allow-clear @press-enter="handleSearch" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="8">
|
<a-form-item label="">
|
<a-button type="primary" class="mr-2" @click="handleSearch">{{ $t('common.queryText') }}</a-button>
|
<a-button @click="handleReset">{{ $t('common.resetText') }}</a-button>
|
</a-form-item>
|
</a-col>
|
</a-row>
|
</a-form>
|
<div class="i18n-search-box-right">
|
<a-tooltip placement="top">
|
<template #title>
|
<span>{{ $t('common.addText') }}</span>
|
</template>
|
<PlusOutlined class="i18n-search-box-right-icon" @click="addHandle" />
|
</a-tooltip>
|
<a-tooltip placement="top">
|
<template #title>
|
<span>{{ $t('common.redo') }}</span>
|
</template>
|
<RedoOutlined class="i18n-search-box-right-icon" @click="initData" />
|
</a-tooltip>
|
</div>
|
</div>
|
<Table :data-source="list" v-bind="getTableBindValues" @change="handleTableChange" ref="tableElRef" />
|
</AModal>
|
<I18nForm ref="i18nFormModalRef" @reload="reload" />
|
</template>
|
|
<style lang="scss" scoped>
|
.i18n-search-box {
|
position: relative;
|
padding: 10px 10px 0;
|
|
.i18n-search-box-right {
|
position: absolute;
|
top: 15px;
|
right: 10px;
|
|
.i18n-search-box-right-icon {
|
width: 18px;
|
height: 18px;
|
margin-left: 10px;
|
font-size: 18px;
|
cursor: pointer;
|
}
|
}
|
}
|
|
.jnpf-basic-table {
|
:deep(.ant-table-pagination) {
|
&.ant-pagination {
|
padding: 0 10px 10px;
|
margin: 10px 0 0;
|
|
.ant-select.ant-select-in-form-item {
|
width: auto;
|
}
|
}
|
}
|
}
|
</style>
|