123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- <template>
- <Modal
- width="800px"
- title="媒体库"
- :open="visible"
- @ok="okHandler"
- :afterClose="afterClose"
- @cancel="emit('update:visible', false)"
- okText="确定"
- cancelText="取消"
- class="model-table"
- >
- <div>
- <div className="model-header">
- <p class="header-desc">
- 已选择数据<span>( {{ rowSelection.selectedRowKeys.length }} )</span>
- </p>
- <Search
- v-if="Object.keys(allData).length"
- className="content-header-search"
- placeholder="输入名称搜索"
- v-model:value="params.name"
- allow-clear
- style="width: 244px"
- />
- </div>
- <div class="table-layout">
- <Table
- v-if="Object.keys(allData).length"
- :row-key="(record: Material) => record.id"
- :columns="cloumns"
- :rowSelection="rowSelection"
- :data-source="origin.list"
- :pagination="{ ...origin, current: origin.pageNum }"
- @change="handleTableChange"
- >
- <template #bodyCell="{ column, record }">
- <template v-if="column.key === 'size'">
- {{ getSizeStr(record.size) }}
- </template>
- </template>
- </Table>
- <div style="padding: 1px" v-else>
- <Empty
- description="暂无结果"
- :image="Empty.PRESENTED_IMAGE_SIMPLE"
- className="ant-empty ant-empty-normal"
- />
- </div>
- </div>
- </div>
- </Modal>
- </template>
- <script lang="ts" setup>
- import { Modal, Input, Table, Empty, TableProps } from "ant-design-vue";
- import { computed, reactive, ref, watch } from "vue";
- import { createLoadPack, debounce, debounceStack, getSizeStr } from "@/utils";
- import type { PagingResult, Scene } from "@/api";
- import {
- fetchMaterialGroups,
- fetchMaterialPage,
- Material,
- MaterialGroup,
- MaterialPageProps,
- } from "@/api/material";
- import Message from "bill/components/message/message.vue";
- const props = defineProps<{
- format?: string[];
- maxSize?: number;
- visible: boolean;
- count?: number;
- afterClose?: () => void;
- }>();
- const emit = defineEmits<{
- (e: "update:visible", v: boolean): void;
- (e: "selectMaterials", v: Material[]): void;
- }>();
- const Search = Input.Search;
- const params = reactive({ pageNum: 1, pageSize: 12 }) as MaterialPageProps;
- const origin = ref<PagingResult<Material[]>>({
- list: [],
- pageNum: 1,
- pageSize: 12,
- total: 0,
- });
- const groups = ref<MaterialGroup[]>([]);
- const selectKeys = ref<Material["id"][]>([]);
- const allData: Record<Material["id"], Material> = reactive({});
- const rowSelection: any = ref({
- selectedRowKeys: selectKeys,
- onChange: (ids: number[]) => {
- const otherPageKeys = selectKeys.value.filter(
- (key) => !origin.value.list.some((item) => key === item.id)
- );
- const newKeys = Array.from(new Set([...otherPageKeys, ...ids]));
- if (!props.count || props.count >= newKeys.length) {
- selectKeys.value = newKeys;
- } else {
- Message.error(`最多选择${props.count}项`);
- }
- },
- getCheckboxProps: (record: Material) => {
- return {
- disabled:
- (props.format && !props.format.includes(record.format)) ||
- (props.maxSize && record.size > props.maxSize),
- };
- },
- });
- const cloumns = computed(() => [
- {
- width: "400px",
- title: "图片名称",
- dataIndex: "name",
- key: "name",
- },
- {
- title: "格式",
- dataIndex: "format",
- key: "format",
- },
- {
- title: "大小",
- dataIndex: "size",
- key: "size",
- },
- {
- title: "分组",
- dataIndex: "group",
- key: "group",
- filters: groups.value.map((g) => ({
- text: g.name,
- value: g.id,
- })),
- },
- ]);
- const fetchData = createLoadPack(() =>
- Promise.all([fetchMaterialGroups(), fetchMaterialPage(params)])
- );
- watch(
- params,
- debounceStack(
- fetchData,
- ([group, pag]) => {
- groups.value = group;
- origin.value = pag;
- pag.list.forEach((item) => (allData[item.id] = item));
- },
- 160
- ),
- { immediate: true, deep: true }
- );
- const okHandler = () => {
- emit(
- "selectMaterials",
- selectKeys.value.map((id) => allData[id])
- );
- };
- const handleTableChange: TableProps["onChange"] = (pag, filters) => {
- params.pageSize = pag.pageSize!;
- params.pageNum = pag.current!;
- params.groupIds = filters.group as number[];
- };
- </script>
- <style lang="less" scoped>
- .model-header {
- display: flex;
- justify-content: space-between;
- padding-bottom: 24px;
- align-items: center;
- }
- .table-layout {
- max-height: 500px;
- overflow-y: auto;
- }
- </style>
- <style lang="less">
- .model-header .header-desc {
- margin-bottom: 0;
- }
- .ant-modal-root .ant-table-tbody > tr > td {
- word-break: break-all;
- }
- </style>
|