form-content.vue 4.49 KB
<script setup lang="ts">
  import { Form, FormItem, Input, InputGroup, InputNumber, Select, Button, Cascader, Textarea } from '@arco-design/web-vue';
  import InputUpload from '@/components/input-upload/index.vue';
  import { useVModel } from '@vueuse/core';
  import { computed, onMounted, ref } from 'vue';
  import { FormInstance } from '@arco-design/web-vue/es/form';
  import { SystemConfig } from '@/types/system-config';
  import { nanoid } from 'nanoid';
  import useConfigApi from '@/http/config';
  import { get, set } from 'lodash';
  import { arrayToTree } from '@/utils';

  const props = defineProps<{ modelValue: SystemConfig; hideKeyBtn?: boolean; lockField?: string[]; submit?: () => Promise<any> }>();
  const emit = defineEmits(['update:modelValue']);

  const isLock = (field: string): boolean => props.lockField !== undefined && props.lockField?.indexOf(field) !== -1;

  const formRef = ref<FormInstance>();
  const formValue = useVModel(props, 'modelValue', emit);
  const formRule = {
    'name': [{ required: true, message: '请输入名称' }],
    'identifier': [{ required: true, message: '请输入唯一标识' }],
    'status': [{ required: true, message: '请选择状态' }],
    'expand.type': [{ required: true, message: '请选择类型' }],
  };

  const treeOption = ref<SystemConfig[]>([]);
  const treeOptionField = { value: 'id', label: 'name', children: 'children' };

  const onSubmit = async () => {
    const error = await formRef.value?.validate();
    return error ? Promise.reject(error) : props.submit?.();
  };

  defineExpose({ onSubmit });

  onMounted(() => {
    useConfigApi
      .get({ setColumn: ['id', 'name', 'parent_id'], fetchType: 'all', parent_id: '', sortBy: 'weight', sortType: 'desc' })
      .then(({ data }) => set(treeOption, 'value', [{ id: 0, name: '顶级' }, ...arrayToTree(data, 0, { removeEmpty: true })]));
  });

  const contentType = computed({
    get: () => get(formValue.value, 'expand.type', 'none'),
    set: (value) => set(formValue.value, 'expand.type', value),
  });
</script>

<template>
  <Form ref="formRef" :model="formValue" :rules="formRule" auto-label-width>
    <FormItem label="挂载点" field="parent_id" show-colon :disabled="true">
      <Cascader v-model="formValue.parent_id" :options="treeOption" :field-names="treeOptionField" :check-strictly="true" />
    </FormItem>
    <FormItem label="名称" field="name" show-colon>
      <Input v-model="formValue.name" placeholder="请输入" />
    </FormItem>
    <FormItem label="标识" field="identifier" show-colon :disabled="isLock('identifier')">
      <InputGroup style="width: 100%">
        <Input v-model="formValue.identifier" placeholder="请输入" />
        <Button v-if="!hideKeyBtn" @click="() => set(formValue, 'identifier', nanoid())">生成</Button>
      </InputGroup>
    </FormItem>
    <FormItem label="状态" field="status" show-colon>
      <Select v-model="formValue.status" :options="useConfigApi.statusOptions" placeholder="请选择" />
    </FormItem>
    <FormItem label="权重" field="weight" show-colon>
      <InputNumber v-model="formValue.weight" :min="0" :max="200" :step="1" />
    </FormItem>
    <FormItem label="类型" field="expand.type" show-colon>
      <Cascader v-model="contentType" :options="useConfigApi.contentOptions" @change="() => set(formValue, 'content', '')" />
    </FormItem>
    <FormItem
      v-if="contentType !== 'none'"
      label="内容"
      field="content"
      :show-colon="true"
      :rules="[{ required: true, message: '缺少内容' }]"
    >
      <InputUpload v-if="contentType === 'image'" v-model="formValue.content" accept="image/*" />
      <InputUpload v-if="contentType === 'audio'" v-model="formValue.content" accept="audio/*" />
      <InputUpload v-if="contentType === 'video'" v-model="formValue.content" accept="video/*" />
      <InputUpload v-if="contentType === 'file'" v-model="formValue.content" accept="*" />
      <Input v-if="contentType === 'input'" v-model="formValue.content" :max-length="64" placeholder="请输入" />
      <Textarea
        v-if="contentType === 'textarea'"
        v-model="formValue.content"
        placeholder="请输入"
        :auto-size="{ minRows: 4, maxRows: 4 }"
        :max-length="800"
        :show-word-limit="true"
      />
    </FormItem>
    <FormItem label="备注" field="remark" :show-colon="true">
      <Textarea v-model="formValue.remark" :auto-size="{ minRows: 4, maxRows: 4 }" :max-length="400" :show-word-limit="true" />
    </FormItem>
  </Form>
</template>

<style scoped lang="less"></style>