form-list-content.vue 5.54 KB
<script setup lang="ts">
  import {
    Col,
    Form,
    FormItem,
    Input,
    InputNumber,
    Row,
    Select,
    Table,
    TableColumn,
    Avatar,
    Link,
    Space,
    Button,
    TableData,
  } from '@arco-design/web-vue';
  import { Banner, BannerLink } from '@/utils/model';
  import { computed, createVNode, ref } from 'vue';
  import useBannerApi from '@/http/bannner';
  import ImageUpload from '@/components/image-upload/index.vue';
  import { AnyObject } from '@/types/global';
  import { FormInstance } from '@arco-design/web-vue/es/form';
  import { createModalVNode } from '@/utils/createVNode';
  import FormListItemContent from '@/views/operation/banner/components/form-list-item-content.vue';
  import { cloneDeep, pick } from 'lodash';
  import { promiseToBoolean } from '@/utils';
  import RoleSelect from '@/views/operation/banner/components/role-select.vue';

  type FormType = Pick<Banner, 'name' | 'scope' | 'weight' | 'permission' | 'type' | 'cover' | 'content'>;

  const { scopeOption } = useBannerApi;

  const props = defineProps<{ init?: AnyObject; http: (params?: object) => Promise<any> }>();

  const formVal = ref<FormType>({
    name: '',
    scope: 1,
    weight: 0,
    permission: [],
    type: 3,
    cover: '',
    content: [],
    ...pick(props.init, ['name', 'scope', 'weight', 'permission ', 'type', 'cover', 'content']),
  });

  const formRule = computed(() => {
    return {
      name: [{ required: true, message: '请输入名称' }],
      scope: [{ required: true, message: '请选择展示位置' }],
      weight: [{ required: true, message: '请输入权重' }],
      permission: [{ required: true, message: '请选择浏览用户' }],
      type: [{ required: true, message: '请选择类型' }],
      cover: [{ required: true, message: '请选择封面' }],
      content: formVal.value.type === 1 ? [] : [{ required: true, message: '请输入链接地址' }],
    };
  });

  const handleChange = (data: []) => {
    formVal.value.content = data;
  };

  const onCreate = () => {
    const formRef = ref();
    createModalVNode(() => createVNode(FormListItemContent, { ref: formRef }), {
      title: '新增',
      titleAlign: 'center',
      onBeforeOk: () => formRef.value?.onSubmit(),
      onOk: () => formVal.value.content.push(formRef.value.getValue()),
    });
  };

  const onUpdate = (row: BannerLink, index: number) => {
    const formRef = ref();
    createModalVNode(() => createVNode(FormListItemContent, { init: cloneDeep(row), ref: formRef }), {
      title: '编辑',
      titleAlign: 'center',
      onBeforeOk: () => formRef.value?.onSubmit(),
      onOk: () => formVal.value.content.splice(index, 1, formRef.value.getValue()),
    });
  };

  const onDelete = (index: number) => {
    formVal.value.content.splice(index, 1);
  };

  const formRef = ref<FormInstance>();

  const onSubmit = async (): Promise<boolean> => {
    if (await formRef.value?.validate()) {
      // eslint-disable-next-line prefer-promise-reject-errors
      return Promise.reject(false);
    }
    return promiseToBoolean(props.http(formVal.value));
  };

  defineExpose({ onSubmit });
</script>

<template>
  <Form ref="formRef" style="width: 1100px" :model="formVal" :rules="formRule" auto-label-width label-align="right">
    <Row :gutter="16">
      <Col flex="auto">
        <FormItem label="名称" field="name" show-colon row-class="form-item">
          <Input v-model="formVal.name" :max-length="30" show-word-limit placeholder="请输入" />
        </FormItem>
        <FormItem label="展示位置" field="scope" show-colon row-class="form-item">
          <Select v-model="formVal.scope" :options="scopeOption" placeholder="请选择" />
        </FormItem>
        <FormItem label="权重" field="weight" show-colon row-class="form-item">
          <InputNumber v-model="formVal.weight" :min="0" :max="200" placeholder="请输入" />
        </FormItem>
        <FormItem label="浏览用户" field="permission" show-colon row-class="mb-0">
          <RoleSelect v-model="formVal.permission" :max-tag-count="4" style="height: 32px" />
        </FormItem>
      </Col>
      <Col flex="400px">
        <FormItem label="封面" field="cover" row-class="mb-0" hide-label>
          <ImageUpload v-model="formVal.cover" :width="380" :height="156" fit="fill" class="cover" />
        </FormItem>
      </Col>
    </Row>
  </Form>
  <Row style="margin: 16px 0">
    <Col :span="24">
      <Space>
        <Button type="primary" size="small" @click="onCreate">新增</Button>
      </Space>
    </Col>
  </Row>
  <Table
    style="width: 1100px"
    :bordered="true"
    :data="formVal.content as TableData[]"
    :show-header="false"
    :pagination="false"
    :draggable="{}"
    @change="handleChange"
  >
    <template #columns>
      <TableColumn data-index="cover" :width="50">
        <template #cell="{ record }">
          <Avatar :image-url="record.cover" fit="contain" shape="square" />
        </template>
      </TableColumn>
      <TableColumn data-index="title" :width="200" />
      <TableColumn data-index="content" :ellipsis="true" :tooltip="true" />
      <TableColumn :width="100">
        <template #cell="{ record, rowIndex }">
          <Space>
            <Link :hoverable="false" @click="onUpdate(record, rowIndex)">修改</Link>
            <Link :hoverable="false" @click="onDelete(rowIndex)">删除</Link>
          </Space>
        </template>
      </TableColumn>
    </template>
  </Table>
</template>

<style scoped lang="less">
  .form-item {
    margin-bottom: 10px !important;
  }

  :deep(.arco-upload-list-item) {
    margin-top: 0 !important;
  }
</style>