form-page-content.vue 4.5 KB
<script setup lang="ts">
  import { Col, Form, FormItem, Input, InputNumber, Row, Select, Layout, LayoutContent, LayoutSider } from '@arco-design/web-vue';
  import { onBeforeUnmount, ref, shallowRef } from 'vue';
  import { FieldRule, FormInstance } from '@arco-design/web-vue/es/form';
  import ImageUpload from '@/components/image-upload/index.vue';
  import useBannerApi from '@/http/bannner';

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
  import { Boot } from '@wangeditor/editor';
  import '@/views/operation/notification/module';
  import { AttributeData } from '@/types/global';
  import { pick } from 'lodash';
  import { promiseToBoolean } from '@/utils';
  import RoleSelect from '@/views/operation/banner/components/role-select.vue';

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

  const formRef = ref<FormInstance>();
  const editorRef = shallowRef();

  Boot.setEditorConfig({ readOnly: false });

  const onCreateEditor = (editor: unknown) => {
    editorRef.value = editor;
  };

  onBeforeUnmount(() => {
    const editor = editorRef.value;
    if (editor == null) return;
    editor.destroy();
  });

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

  const formRule = {
    link_type: [{ required: true, message: '请选择关联类型' }],
    link_id: [{ type: 'number', min: 1, required: true, message: '请选择关联对象' }],
    title: [{ required: true, message: '请输入名称' }],
    content: [{ required: true, message: '请输入推荐语' }],
  } as Record<string, FieldRule[]>;

  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" :model="formVal" :rules="formRule" style="width: 1321px" 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="6" style="height: 32px" />
        </FormItem>
      </Col>
      <Col flex="420px">
        <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>
      <Col :span="24" style="margin-top: 16px; margin-bottom: -24px">
        <Toolbar style="border-top: 1px solid #ccc; border-bottom: 1px solid #ccc" :editor="editorRef" />
        <Layout>
          <LayoutContent>
            <Editor v-model="formVal.content" style="height: 400px" @on-created="onCreateEditor" />
          </LayoutContent>
          <LayoutSider class="rich" :width="420">
            <!-- eslint-disable vue/no-v-html -->
            <div class="content" v-html="formVal.content" />
            <!--eslint-enable-->
          </LayoutSider>
        </Layout>
      </Col>
    </Row>
  </Form>
</template>

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

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

  .rich {
    box-shadow: unset;
    border-left: 1px solid #e8e8e8;

    .content {
      overflow-y: auto;
      height: 400px;
      padding: 0 10px;

      :deep(img) {
        height: auto !important;
        max-width: 100%;
        object-fit: contain;
      }

      :deep(video) {
        max-width: 100%;
        height: auto !important;
        display: block;
        margin: 0 auto;
      }
    }
  }
</style>