<!-- 用户编辑弹窗 -->
<template>
  <ele-modal
    width="980px"
    :visible="visible"
    :confirm-loading="loading"
    :maxable="maxAble"
    :title="isUpdate ? '编辑文章' : '添加文章'"
    :body-style="{ paddingBottom: '8px' }"
    @update:visible="updateVisible"
    :maskClosable="false"
    @ok="save"
  >
    <a-form
      ref="formRef"
      :model="form"
      :rules="rules"
      :label-col="{ md: { span: 8 }, sm: { span: 24 } }"
      :wrapper-col="{ md: { span: 24 }, sm: { span: 24 } }"
      layout="vertical"
    >
      <a-form-item label="文章分类" name="categoryId">
        <category-select
          :data="categoryList"
          placeholder="请选择文章分类"
          v-model:value="form.categoryId"
        />
      </a-form-item>
      <a-form-item label="文章标题" name="title">
        <a-input
          allow-clear
          :maxlength="100"
          placeholder="请输入文章标题"
          v-model:value="form.title"
        />
      </a-form-item>
      <a-form-item label="封面图" name="images">
        <SelectFile
          :placeholder="`请选择图片`"
          :limit="1"
          :data="images"
          @done="chooseFile"
          @del="onDeleteItem"
        />
      </a-form-item>
      <a-form-item label="文章内容" name="content">
        <!-- 编辑器 -->
        <tinymce-editor
          ref="editorRef"
          class="content"
          v-model:value="content"
          :disabled="disabled"
          :init="config"
          placeholder="图片直接粘贴自动上传"
          @paste="onPaste"
        />
      </a-form-item>
      <a-form-item label="摘要">
        <a-textarea
          :rows="4"
          :maxlength="200"
          show-count
          placeholder="请输入文章摘要"
          @focus="onComments"
          v-model:value="form.comments"
        />
      </a-form-item>
      <a-form-item label="文章来源" name="source">
        <source-select
          v-model:value="form.source"
        />
      </a-form-item>
      <a-form-item label="虚拟阅读量" name="virtualViews" :extra="`用户看到的阅读量(${form.actualViews + form.virtualViews}) = 实际阅读量(${form.actualViews}) + 虚拟阅读量(${form.virtualViews})`">
        <a-input-number
          :min="0"
          class="ele-fluid"
          placeholder="请输入虚拟阅读量"
          v-model:value="form.virtualViews"
        />
      </a-form-item>
      <a-form-item label="上传附件（选填）" name="files">
        <SelectFile
          :placeholder="`请选择图片`"
          :limit="9"
          :data="files"
          @done="chooseFile2"
          @del="onDeleteItem2"
        />
<!--        <a-upload-->
<!--          v-model:file-list="fileList"-->
<!--          :max-count="1"-->
<!--          class="upload-list-inline"-->
<!--          list-type="picture"-->
<!--          :before-upload="beforeUpload"-->
<!--        >-->
<!--          <a-button>-->
<!--            <UploadOutlined />-->
<!--            上传附件-->
<!--          </a-button>-->
<!--        </a-upload>-->
      </a-form-item>
      <a-form-item label="排序" name="sortNumber">
        <a-input-number
          :min="0"
          :max="99999"
          class="ele-fluid"
          placeholder="请输入排序号"
          v-model:value="form.sortNumber"
        />
      </a-form-item>
      <a-form-item label="创建时间" name="createTime" v-if="isUpdate">
        <a-date-picker
          v-model:value="form.createTime"
          show-time
          placeholder="Select Time"
          value-format="YYYY-MM-DD HH:mm:ss"
          class="ele-fluid"
        />
      </a-form-item>
      <a-form-item label="展现方式" name="showType">
        <a-radio-group v-model:value="form.showType">
          <a-radio :value="10">小图模式(300 * 188)</a-radio>
          <a-radio :value="20">大图模式(750 * 455)</a-radio>
        </a-radio-group>
      </a-form-item>
    </a-form>

  </ele-modal>
</template>

<script lang="ts" setup>
import { ref, reactive, watch, computed } from "vue";
import { Form, message, Modal } from "ant-design-vue";
import { useUserStore } from "@/store/modules/user";
import type { Article } from "@/api/cms/article/model";
import {addArticle, getArticle, updateArticle} from "@/api/cms/article";
import { FILE_SERVER, FILE_THUMBNAIL } from "@/config/setting";
import { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import {uploadFile, uploadOss} from "@/api/system/file";
import TinymceEditor from "@/components/TinymceEditor/index.vue";
import { FormInstance, Rule, RuleObject } from "ant-design-vue/es/form";
import CategorySelect from "./category-select.vue";
import { ArticleCategory } from "@/api/cms/category/model";
import SourceSelect from "../dictionary/source-select.vue";
import useFormData from "@/utils/use-form-data";
import {htmlToText, uuid} from "ele-admin-pro";
import {isImage} from "@/utils/common";
import {DocsBook} from "@/api/cms/docs-book/model";
import {FileRecord} from "@/api/system/file/model";

const useForm = Form.useForm;
const props = defineProps<{
  // 弹窗是否打开
  visible: boolean;
  categoryId?: number;
  // 修改回显的数据
  data?: Article | null;
  categoryList?: any;
}>();

const emit = defineEmits<{
  (e: "done"): void;
  (e: "update:visible", visible: boolean): void;
}>();

// 是否是修改
const isUpdate = ref(false);
const disabled = ref(false);
// 是否显示最大化切换按钮
const maxAble = ref(true);
// 选项卡位置
const activeKey = ref("1");
// 已上传数据
const images = ref<ItemType[]>([]);
// 附件
const fileList = ref<any[]>([]);
const files = ref<ItemType[]>([]);

// 当前用户信息
const userStore = useUserStore();
const loginUser = computed(() => userStore.info ?? {});
// 编辑器内容，双向绑定
const content = ref<any>('');
const uploadImgContent = ref<string>('');
const formRef = ref<FormInstance | null>(null);

// 已上传数据, 可赋初始值用于回显
const avatar = ref(<any>[]);
// 提交状态
const loading = ref(false);
// 表单数据
const { form, resetFields, assignFields } = useFormData<Article>({
  articleId: undefined,
  // 封面图
  image: '',
  // 文章标题
  title: '',
  type: undefined,
  // 展现方式
  showType: 10,
  // 文章来源
  source: undefined,
  // 文章类型
  categoryId: undefined,
  // 文章内容
  content: '',
  // 虚拟阅读量
  virtualViews: 0,
  // 实际阅读量
  actualViews: 0,
  // 用户ID
  userId: undefined,
  // 所属门店ID
  shopId: undefined,
  files: '',
  // 排序
  sortNumber: 100,
  // 备注
  comments: undefined,
  // 状态
  status: 0,
  // 创建时间
  createTime: '',
  // 更新时间
  updateTime: ''
});

/* 更新visible */
const updateVisible = (value: boolean) => {
  emit("update:visible", value);
};

// 表单验证规则
const rules = reactive<Record<string, Rule[]>>({
  title: [
    {
      required: true,
      type: "string",
      message: "请输入文章标题",
      trigger: "blur"
    }
  ],
  content: [
    {
      required: true,
      type: "string",
      message: "请输入文章内容",
      trigger: "blur",
      validator: async (_rule: RuleObject, value: string) => {
        if (content.value == "") {
          return Promise.reject("请输入文字内容");
        }
        return Promise.resolve();
      }
    }
  ],
  categoryId: [
    {
      required: true,
      type: "number",
      message: "请选择文章分类",
      trigger: "blur"
    }
  ],
  // images: [
  //   {
  //     required: true,
  //     type: "string",
  //     message: "请上传文章封面图",
  //     trigger: "blur",
  //     validator: async (_rule: RuleObject, value: string) => {
  //       if (images.value.length == 0) {
  //         return Promise.reject('请上传封面图');
  //       }
  //       return Promise.resolve();
  //     }
  //   }
  // ],
  sortNumber: [
    {
      required: true,
      type: "number",
      message: "请输入排序",
      trigger: "blur"
    }
  ],
  source: [
    {
      required: false,
      type: "string",
      message: "请输入文章来源",
      trigger: "blur"
    }
  ]
});

const onComments = () => {
  if (form.comments == undefined) {
    form.comments = htmlToText(content.value)
    form.comments = form.comments.slice(0, 120)
  }
}

const chooseFile = (data: FileRecord) => {
  images.value.push({
    uid: data.id,
    url: data.path,
    status: 'done'
  });
  form.image = data.path;
}

const onDeleteItem = (index: number) => {
  images.value.splice(index,1)
  form.image = '';
}

const chooseFile2 = (data: FileRecord) => {
  files.value.push({
    uid: data.id,
    url: data.path,
    status: 'done'
  });
}

const onDeleteItem2 = (index: number) => {
  files.value.splice(index,1)
}

/* 上传事件 */
const uploadHandler = (file: File) => {
  const item: ItemType = {
    file,
    uid: (file as any).uid,
    name: file.name
  };
  if (!file.type.startsWith('image')) {
    message.error('只能选择图片');
    return;
  }
  if (file.size / 1024 / 1024 > 2) {
    message.error('大小不能超过 2MB');
    return;
  }
  onUpload(item);
};

// 上传文件
const onUpload = (item) => {
  const { file } = item;
  uploadFile(file)
    .then((data) => {
      images.value.push({
        uid: data.id,
        url: data.url,
        status: 'done'
      });
      form.image = data.url;
      message.success('上传成功');
    })
    .catch((e) => {
      message.error(e.message);
    });
};

const editorRef = ref<InstanceType<typeof TinymceEditor> | null>(null);
const config = ref({
  height: 450,
  images_upload_handler: (blobInfo, success, error) => {
    const file = blobInfo.blob();
    const formData = new FormData();
    formData.append('file', file, file.name);
    uploadOss(file).then(res => {
      success(res.path)
    }).catch((msg) => {
      error(msg);
    })
  },
  // 自定义文件上传(这里使用把选择的文件转成 blob 演示)
  file_picker_callback: (callback: any, _value: any, meta: any) => {
    const input = document.createElement('input');
    input.setAttribute('type', 'file');
    // 设定文件可选类型
    if (meta.filetype === 'image') {
      input.setAttribute('accept', 'image/*');
    } else if (meta.filetype === 'media') {
      input.setAttribute('accept', 'video/*,.pdf');
    }
    input.onchange = () => {
      const file = input.files?.[0];
      if (!file) {
        return;
      }
      if (meta.filetype === 'media') {
        if (file.size / 1024 / 1024 > 200) {
          editorRef.value?.alert({ content: '大小不能超过 200MB' });
          return;
        }
        if(file.type.startsWith('application/pdf')){
          uploadOss(file).then(res => {
            const addPath = `<a href="${res.downloadUrl}" target="_blank">${res.name}</a>`;
            content.value = content.value + addPath
          })
          return;
        }
        if (!file.type.startsWith('video/')) {
          editorRef.value?.alert({ content: '只能选择视频文件' });
          return;
        }
        uploadOss(file).then(res => {
          callback(res.path)
        });
      }
      // const reader = new FileReader();
      // reader.onload = (e) => {
      //   if (e.target?.result != null) {
      //     const blob = new Blob([e.target.result], { type: file.type });
      //     callback(URL.createObjectURL(blob));
      //   }
      // };
      // reader.readAsArrayBuffer(file);
    };
    input.click();
  }
});

/* 粘贴图片上传服务器并插入编辑器 */
const onPaste = (e) => {
  const items = (e.clipboardData || e.originalEvent.clipboardData).items;
  let hasFile = false;
  for (let i = 0; i < items.length; i++) {
    if (items[i].type.indexOf('image') !== -1) {
      let file = items[i].getAsFile();
      const item: ItemType = {
        file,
        uid: (file as any).lastModified,
        name: file.name
      };
      uploadFile(<File>item.file)
        .then((result) => {
          const addPath = `<p><img class="content-img" src="${result.url}"></p>`;
          content.value = content.value + addPath
        })
        .catch((e) => {
          message.error(e.message);
        });
      hasFile = true;
    }
  }
  if (hasFile) {
    e.preventDefault();
  }
}

// 文件上传事件
// const beforeUpload = (file: File) => {
//   const item: ItemType = {
//     file,
//     uid: (file as any).uid,
//     name: file.name
//   }
//   if (!file.type.startsWith("image")) {
//     if (file.size / 1024 / 1024 > 100) {
//       message.error("大小不能超过 100MB");
//       return;
//     }
//   }
//   onUploadFile(item);
// };

// const onUploadFile = (d: ItemType) => {
//   uploadOss(<File>d.file)
//     .then((result) => {
//       files.value.push({
//         uid: result.id,
//         url: result.path,
//         name: isImage(result.path) ? 'image' : result.name,
//         status: "done"
//       });
//       message.success("上传成功");
//     })
//     .catch((e) => {
//       message.error(e.message);
//     });
// };

/* 保存编辑 */
const save = () => {
  if (!formRef.value) {
    return;
  }
  formRef.value
    .validate()
    .then(() => {
      loading.value = true;
      const formData = {
        ...form,
        content: content.value,
        files: JSON.stringify(files.value)
      };
      const saveOrUpdate = isUpdate.value ? updateArticle : addArticle;
      saveOrUpdate(formData)
        .then((msg) => {
          loading.value = false;
          message.success(msg);
          updateVisible(false);
          emit("done");
        })
        .catch((e) => {
          loading.value = false;
          message.error(e.message);
        });
    })
    .catch(() => {
    });
};

watch(
  () => props.visible,
  (visible) => {
    if (visible) {
      form.categoryId = props.categoryId;
      content.value = '';
      if (props.data) {
        loading.value = false;
        assignFields({
          ...props.data
        });
        images.value = [];
        files.value = [];
        fileList.value = [];
        if(props.data.image){
          images.value.push({
            uid: 1,
            url: props.data.image,
            status: 'done'
          });
        }
        if(props.data.files){
          files.value = JSON.parse(props.data.files)
          fileList.value = JSON.parse(props.data.files)
        }
        if(props.data.articleId){
          getArticle(props.data.articleId).then(data => {
            content.value = data.content;
          })
        }
        isUpdate.value = true;
      } else {
        isUpdate.value = false;
        images.value = [];
        files.value = [];
        content.value = '';
      }
    } else {
      resetFields();
      formRef.value?.clearValidate();
    }
  }
);
</script>
<style lang="less">
.tab-pane {
  min-height: 300px;
}

.form-item-help {
  font-size: 12px;
  // line-height: 2;
  line-height: 1.5;
  padding-top: 4px;
  min-height: 22px;
  // margin-top: -2px;
  transition: color 0.3s cubic-bezier(0.215, 0.61, 0.355, 1);

  a {
    margin: 0 3px;
  }

  .extra,
  small {
    color: rgba(0, 0, 0, 0.45);
    font-size: 12.5px !important;
  }

  .extra {
    margin-bottom: 4px !important;
  }
}
</style>
