| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <template>
- <BsSubTableInput
- :table-options="tableOptions"
- :value="value"
- :is-show-add-btn="false"
- :is-show-batch-delete-btn="false"
- :opt-btn-slots="batchTableOptBtnSlots"
- :is-edit-row="false"
- @sub-table-input-change="handleTableChange"
- ref="subTableRef"
- >
- <template #custom1>
- <div class="w-full flex items-center justify-center">
- <FileUpload listType="text" :showUploadList="false" @change="handleChange" class="w-full file-btn">
- <template #customUploadBtnSlot>
- <a-button type="text" style="width: 100%">
- <template #icon>
- <upload-outlined />
- </template>
- <span>上传文件</span></a-button
- >
- </template>
- </FileUpload>
- </div>
- </template>
- <template #custom2>
- <a-button type="text" style="width: 100%" :disabled="!isSelectedData" @click="handleDeleteBatch">
- <template #icon> <DeleteOutlined /></template>
- <span>批量删除</span>
- </a-button>
- </template>
- </BsSubTableInput>
- </template>
- <script setup>
- import { computed, h, ref, watch } from 'vue';
- import { BsSubTableInput, useBsTable } from '/@/components/BsUi/index.js';
- import { DISPLAY_STATE } from '/@/components/BsUi/constant.js';
- import FileUpload from '/@/components/support/file-upload/index.vue';
- import { cloneDeep, isEmpty, uniqBy } from 'lodash';
- import { DeleteOutlined } from '@ant-design/icons-vue';
- const props = defineProps({
- value: {
- type: Array,
- default: () => [],
- },
- });
- const subTableRef = ref(null);
- const isSelectedData = computed(() => {
- return isEmpty(subTableRef.value?.selectedData) ? false : subTableRef.value?.selectedData.length !== 0;
- });
- const rowKey = computed(() => {
- return tableOptions.gridOptions?.rowKey || 'fileId';
- });
- const emits = defineEmits(['change', 'update:value']);
- const batchTableOptBtnSlots = ref(['custom1', 'custom2']);
- const { tableOptions, refreshTable } = useBsTable({
- tableOptions: {
- gridOptions: {
- loading: false,
- columns: [
- {
- field: 'fileId',
- width: '80px',
- align: 'center',
- title: 'ID',
- },
- {
- field: 'fileName',
- title: '文件名称',
- },
- {
- field: 'fileType',
- width: '100px',
- title: '文件类型',
- cellRender: {
- name: 'CellFileType',
- },
- },
- {
- field: 'fileSize',
- width: '150px',
- title: '文件大小(M)',
- align: 'center',
- slots: {
- default: ({ row }) => (Number(row.fileSize) / (1024 * 1024)).toFixed(3),
- },
- },
- {
- fixed: 'right',
- cellRender: {
- name: 'CellOption',
- extraProps: {
- buttons: [
- {
- title: '预览',
- code: 'view',
- display: ({ row }) => {
- return DISPLAY_STATE.VISIBLE;
- },
- disabled({ row }) {
- return false;
- },
- onClick({ row }) {},
- extraProps: {},
- },
- {
- title: '删除',
- code: 'delete',
- display: ({ row }) => {
- return DISPLAY_STATE.VISIBLE;
- },
- disabled({ row }) {
- return false;
- },
- onClick({ row }) {
- handleDelete(row);
- },
- extraProps: {
- danger: true,
- },
- },
- ],
- },
- },
- },
- ],
- data: [],
- rowKey: 'fileId',
- },
- request: loadTable,
- },
- });
- const handleChange = (files) => {
- const oldFiles = [...files, ...props.value];
- const newFiles = cloneDeep(uniqBy(oldFiles, rowKey.value));
- emits('update:value', newFiles);
- emits('change', newFiles);
- };
- async function loadTable() {
- return {
- list: props.value,
- total: props.value.length,
- };
- }
- const handleDeleteBatch = () => {
- subTableRef.value.deleteBatch();
- };
- function handleDelete(row) {
- const delIndex = props.value.findIndex((v) => v[rowKey.value] === row[rowKey.value]);
- subTableRef.value.deleteRow(delIndex);
- }
- function handleTableChange(value) {
- emits('update:value', value);
- emits('change', value);
- }
- watch(
- () => props.value,
- (newVal) => {
- refreshTable();
- },
- {
- immediate: true,
- }
- );
- </script>
- <style scoped lang="scss">
- .file-btn {
- :deep(.ant-upload-wrapper) {
- display: block;
- flex: 1;
- }
- :deep(.ant-upload) {
- display: block;
- flex: 1;
- }
- }
- </style>
|