<template>
  <a-form ref="formRef" :model="form" :rules="rules" layout="vertical" class="height100">
    <a-row :gutter="20" class="height100">
      <a-col :span="16" class="height100 oy" style="border-right: 1px solid rgba(197, 207, 209, 0.4)">
        <a-row :gutter="16">
          <a-col :span="19">
            <a-form-item label="标题:" name="newsTitle">
              <a-input v-model:value="form.newsTitle" allow-clear placeholder="请输入标题" />
            </a-form-item>
            <a-form-item label="摘要:" name="newsSummary">
              <a-textarea v-model:value="form.newsSummary" allow-clear :rows="3" placeholder="请输入摘要" />
            </a-form-item>
          </a-col>
          <a-col :span="5" class="pick">
            <a-form-item label="缩略图:">
              <a-upload
                name="file"
                :multiple="false"
                v-model:file-list="form.iconList"
                :default-file-list="form.iconList"
                :maxCount="1"
                :action="fileUploadUrl"
                list-type="picture-card"
                :headers="headers"
                :before-upload="beforeUpload"
                accept=".jpeg,.jpg,.png,.tif,.jfif,.webp,.pjp,.apng,.pjpeg,.avif,.ico,.tiff,.bmp,.xbm,.jxl,.jpeg,.svgz,.gif,.svg"
                @preview="handlePreviewPhoto"
                @download="downloadPhoto"
                @change="coverFileIdChange"
                :showUploadList="{
                  showDownloadIcon: true
                }"
              >
                <plus-outlined style="font-size: 28px; font-weight: 200" v-if="form.iconList.length == 0" />
              </a-upload>
            </a-form-item>
          </a-col>
        </a-row>
        <a-form-item label="内容:" name="newsContent">
          <tinymce-editor v-model:value="form.newsContent" :init="newsContentEditConfig" />
        </a-form-item>
        <a-form-item label="附件" name="fileIdList">
          <div class="file-box">
            <a-upload
              name="file"
              :multiple="true"
              :action="fileUploadUrl"
              :headers="headers"
              list-type="file"
              v-model:file-list="form.fileList"
              @change="handleFileChange"
            >
              <a class="file-btn"> 上传附件 </a>
              <template #itemRender="{ file, fileList }">
                <div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
                  <div class="ant-upload-list-item-info">
                    <span class="ant-upload-span">
                      <div
                        class="ant-upload-text-icon"
                        :class="[{ 'ant-upload-text-icon-pdf': file.type == 'application/pdf' || file.fileSuffix == 'pdf' }]"
                      >
                        <span class="ant-upload-text-icon-index">{{ fileList.indexOf(file) + 1 }}.</span>
                        <paper-clip-outlined class="actions-icon" v-if="!(file.type == 'application/pdf' || file.fileSuffix == 'pdf')" />
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          width="20"
                          height="20"
                          viewBox="0 0 20 20"
                          fill="none"
                          v-if="file.type == 'application/pdf' || file.fileSuffix == 'pdf'"
                        >
                          <g clip-path="url(#clip0_1962_37183)">
                            <path
                              d="M3.75 7.5H16.25C16.3594 7.5 16.4678 7.52155 16.5689 7.56343C16.67 7.60531 16.7619 7.6667 16.8393 7.74408C16.9166 7.82146 16.978 7.91333 17.0199 8.01443C17.0618 8.11553 17.0833 8.2239 17.0833 8.33333V15.4167C17.0833 15.6377 16.9955 15.8496 16.8393 16.0059C16.683 16.1622 16.471 16.25 16.25 16.25H3.75V18.3333C3.75 18.3881 3.76078 18.4422 3.78172 18.4928C3.80266 18.5433 3.83335 18.5893 3.87204 18.628C3.91073 18.6667 3.95666 18.6973 4.00722 18.7183C4.05777 18.7392 4.11195 18.75 4.16667 18.75H18.3333C18.4438 18.75 18.5498 18.7061 18.628 18.628C18.7061 18.5498 18.75 18.4438 18.75 18.3333V6.03167L18.5529 5.83333H16.0817C15.5738 5.83333 15.0867 5.63158 14.7276 5.27244C14.3684 4.91331 14.1667 4.42622 14.1667 3.91833V1.41917L13.9983 1.25H4.16667C4.11195 1.25 4.05777 1.26078 4.00722 1.28172C3.95666 1.30266 3.91073 1.33335 3.87204 1.37204C3.83335 1.41073 3.80266 1.45666 3.78172 1.50722C3.76078 1.55777 3.75 1.61195 3.75 1.66667V7.5ZM2.5 16.25H0.833333C0.61232 16.25 0.400358 16.1622 0.244078 16.0059C0.0877974 15.8496 0 15.6377 0 15.4167L0 8.33333C0 8.2239 0.0215548 8.11553 0.0634337 8.01443C0.105313 7.91333 0.166696 7.82146 0.244078 7.74408C0.32146 7.6667 0.413326 7.60531 0.51443 7.56343C0.615535 7.52155 0.723898 7.5 0.833333 7.5H2.5V1.66667C2.5 1.22464 2.67559 0.800716 2.98816 0.488155C3.30072 0.175595 3.72464 0 4.16667 0H14.5187L20 5.51667V18.3333C20 18.7754 19.8244 19.1993 19.5118 19.5118C19.1993 19.8244 18.7754 20 18.3333 20H4.16667C3.72464 20 3.30072 19.8244 2.98816 19.5118C2.67559 19.1993 2.5 18.7754 2.5 18.3333V16.25ZM1.72792 9.22833V14.5833H2.60542V12.5283H3.93292C5.23792 12.5283 5.89042 11.9733 5.89042 10.8708C5.89042 9.77583 5.23792 9.22833 3.94792 9.22833H1.72792ZM2.60542 9.97833H3.88042C4.26292 9.97833 4.54792 10.0458 4.72792 10.1883C4.90792 10.3233 5.00542 10.5483 5.00542 10.8708C5.00542 11.1933 4.91542 11.4258 4.73542 11.5683C4.55542 11.7033 4.27042 11.7783 3.88042 11.7783H2.60542V9.97833ZM6.64042 9.22833V14.5833H8.59792C9.46792 14.5833 10.1204 14.3433 10.5704 13.8633C10.9979 13.4058 11.2154 12.7533 11.2154 11.9058C11.2154 11.0508 10.9979 10.3983 10.5704 9.94833C10.1204 9.46833 9.46792 9.22833 8.59792 9.22833H6.64042ZM7.51792 9.97833H8.43292C9.10042 9.97833 9.58792 10.1283 9.89542 10.4358C10.1954 10.7358 10.3454 11.2308 10.3454 11.9058C10.3454 12.5658 10.1954 13.0533 9.89542 13.3683C9.58792 13.6758 9.10042 13.8333 8.43292 13.8333H7.51792V9.97833ZM12.0404 9.22833V14.5833H12.9179V12.2133H15.5354V11.4633H12.9179V9.97833H15.6929V9.22833H12.0404Z"
                              fill="#EA4318"
                            />
                          </g>
                          <defs>
                            <clipPath id="clip0_1962_37183">
                              <rect width="20" height="20" fill="white" />
                            </clipPath>
                          </defs>
                        </svg>
                      </div>
                      <a class="ant-upload-list-item-name">
                        <span>{{ file.name }}</span>
                        <span class="ant-upload-list-item-name-size">{{ file?.sizeInfo }}</span>
                      </a>
                      <span class="ant-upload-list-item-card-actions">
                        <a-space>
                          <eye-outlined class="actions-icon" title="预览" @click="preview(file)" />
                          <cloud-download-outlined class="actions-icon" title="下载" @click="downloadFile(file)" />
                          <delete-outlined @click="remove(file)" title="删除" style="color: red" class="actions-icon" />
                        </a-space>
                      </span>
                    </span>
                  </div>
                </div>
              </template>
            </a-upload>
          </div>
        </a-form-item>
      </a-col>
      <a-col :span="8" class="height100 oy">
        <a-form-item label="所属分类:" name="newsCategoryId">
          <a-tree-select
            v-model:value="form.newsCategoryId"
            style="width: 100%"
            showSearch
            :tree-data="typeList"
            treeNodeFilterProp="categoryName"
            :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
            placeholder="请选择所属分类"
            :fieldNames="{ children: 'children', label: 'categoryName', key: 'categoryId', value: 'categoryId' }"
            allow-clear
            tree-default-expand-all
          />
        </a-form-item>
        <a-form-item label="新闻作者:" name="showPublishUser">
          <a-input v-model:value="form.showPublishUser" allow-clear placeholder="请输入新闻作者" />
        </a-form-item>
        <a-form-item label="摄影作者:" name="showPhotoUser">
          <a-input v-model:value="form.showPhotoUser" allow-clear placeholder="请输入摄影作者" />
        </a-form-item>
        <a-form-item label="新闻状态:" name="newsStatus">
          <a-select v-model:value="form.newsStatus" placeholder="请选择新闻状态" allowClear>
            <a-select-option :value="1">草稿</a-select-option>
            <a-select-option :value="2">发布</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="是否置顶:" name="newsTopFlag">
          <a-select v-model:value="form.newsTopFlag" placeholder="请选择是否置顶" allowClear>
            <a-select-option value="Y">置顶</a-select-option>
            <a-select-option value="N">不置顶</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="新闻类型:" name="newsType">
          <a-select v-model:value="form.newsType" placeholder="请选择新闻类型" allowClear>
            <a-select-option :value="10">文本文章</a-select-option>
            <a-select-option :value="20">外部链接</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="外部链接地址:" name="linkUrl" v-if="form.newsType == 20">
          <a-input v-model:value="form.linkUrl" allow-clear placeholder="请输入外部链接地址" />
        </a-form-item>
        <a-form-item label="发布时间:" name="showPublishTime">
          <a-date-picker
            v-model:value="form.showPublishTime"
            format="YYYY-MM-DD HH:mm:ss"
            style="width: 100%"
            allowClear
            showTime
            valueFormat="YYYY-MM-DD HH:mm:ss"
            placeholder="请选择发布时间"
          />
        </a-form-item>
        <a-form-item label="排序:" name="newsSort">
          <a-input-number
            v-model:value="form.newsSort"
            :min="0"
            style="width: 100%"
            placeholder="请输入排序"
            allow-clear
            autocomplete="off"
          />
        </a-form-item>
      </a-col>
    </a-row>

    <!-- 图标预览弹框 -->
    <a-modal :visible="previewVisible" :footer="null" @cancel="previewVisible = false">
      <img alt="example" style="width: 100%" :src="previewImage" />
    </a-modal>
  </a-form>
</template>

<script setup name="NewForm">
import { onMounted, reactive, ref } from 'vue';
import { getToken } from '@/utils/token-util';
import { API_BASE_PREFIX } from '@/config/setting';
import { message, Upload } from 'ant-design-vue/es';
import { FileApi, FileUploadUrl as fileUploadUrlPrefix } from '@/views/system/backend/file/api/FileApi';
import { NewTypeApi } from '../api/NewTypeApi';
import { compressAccurately, imagetoCanvas } from 'image-conversion';

const props = defineProps({
  // 表单数据
  form: Object,
  isUpdate: Boolean,
  designId: String
});

const formRef = ref();

// 上传文件的url
const fileUploadUrl = ref(`${API_BASE_PREFIX}${fileUploadUrlPrefix}?secretFlag=N`);
// 上传文件时候要带header
const headers = ref({
  Authorization: getToken()
});

// 验证规则
const rules = reactive({
  newsTitle: [{ required: true, message: '请输入标题', type: 'string', trigger: 'blur' }],
  newsCategoryId: [{ required: true, message: '请选择所属分类', type: 'string', trigger: 'change' }],
  newsContent: [{ required: true, message: '请输入内容', type: 'string', trigger: 'blur' }],
  showPublishUser: [{ required: true, message: '请输入新闻作者', type: 'string', trigger: 'blur' }],
  showPhotoUser: [{ required: true, message: '请输入摄影作者', type: 'string', trigger: 'blur' }],
  newsStatus: [{ required: true, message: '请选择新闻状态', type: 'number', trigger: 'change' }],
  newsType: [{ required: true, message: '请选择新闻类型', type: 'number', trigger: 'change' }],
  newsTopFlag: [{ required: true, message: '请选择是否置顶', type: 'string', trigger: 'change' }],
  linkUrl: [{ required: true, message: '请输入外部链接', type: 'string', trigger: 'blur' }],
  showPublishTime: [{ required: true, message: '请选择发布时间', type: 'string', trigger: 'blur' }],
  newsSort: [{ required: true, message: '请输入排序', type: 'number', trigger: 'blur' }]
});

const typeList = ref([]);

// 是否展示图片预览
const previewVisible = ref(false);
// 图片地址
const previewImage = ref(null);

const imgCompLoading = ref(false);

onMounted(() => {
  getTypeList();
});

const getTypeList = async () => {
  const res = await NewTypeApi.treeList({ designId: props.designId });
  typeList.value = res.data;
};

//上传之前的回调
const beforeUpload = file => {
  const isJpgOrPng =
    file.type === 'image/jpeg' ||
    file.type === 'image/jpg' ||
    file.type === 'image/png' ||
    file.type === 'image/tif' ||
    file.type === 'image/jfif' ||
    file.type === 'image/webp' ||
    file.type === 'image/pjp' ||
    file.type === 'image/apng' ||
    file.type === 'image/pjpeg' ||
    file.type === 'image/avif' ||
    file.type === 'image/ico' ||
    file.type === 'image/tiff' ||
    file.type === 'image/bmp' ||
    file.type === 'image/xbm' ||
    file.type === 'image/jxl' ||
    file.type === 'image/svgz' ||
    file.type === 'image/gif' ||
    file.type === 'image/svg';
  if (!isJpgOrPng) {
    message.error('只能上传图片!');
    return Upload.LIST_IGNORE; //阻止列表展现
  }
  const isLt5M = file.size / 1024 / 1024 < 5;
  if (!isLt5M) {
    message.error('图片大小不能超过5MB!');
  }
  return isJpgOrPng && isLt5M;
};

// 点击预览图片
const handlePreviewPhoto = async file => {
  previewImage.value = file.url || file.preview || file.thumbUrl;
  previewVisible.value = true;
};

//下载图片
const downloadPhoto = file => {
  let id = file.response ? file.response.data.fileId : file.uid;
  FileApi.download({ token: getToken(), fileId: id });
};

const coverFileIdChange = info => {
  if (info.file.status === 'done') {
    // 设置临时fileList的值
    props.form.iconList = [info.file];
    // 将文件属性名和文件编码存入数组中
    message.success(`${info.file.name} 图片上传成功`);
  } else if (info.file.status === 'error') {
    message.error(`${info.file.name} 图片上传失败`);
  }
};

/**
 * 上传文件改变时的状态
 *
 * @param info 组件回调原有参数
 * @param fieldCode 文件表单字段名称
 * @author fengshuonan
 * @date 2021/12/29 14:25:18
 */
const handleFileChange = info => {
  if (info.file.status === 'done') {
    info.file.fileId = info.file.response.data.fileId;
    info.file.sizeInfo = info.file.response.data.fileSizeInfo;
    message.success(`${info.file.name} 图片上传成功`);
    if (!props.form?.fileIdList) props.form.fileIdList = [];
    props.form.fileIdList.push(info.file.response.data.fileId);
  }
};

// 预览
const preview = file => {
  let url = `${API_BASE_PREFIX}/documentPreview?fileId=${file.fileId}&token=${getToken()}`;
  window.open(url, '_blank');
};

// 下载
const downloadFile = file => {
  FileApi.download({ token: getToken(), fileId: file.fileId });
};

// 删除文件
const remove = file => {
  let fileId = file.fileId;
  if (fileId) {
    let findIndex = props.form.fileList.findIndex(item => item.fileId === fileId);
    if (findIndex !== -1) {
      props.form.fileList.splice(findIndex, 1);
      props.form.attachmefileIdListntList.splice(findIndex, 1);
    }
  }
};

// 新闻富文本编辑器配置
const newsContentEditConfig = ref({
  height: 700,
  convert_urls: false,
  paste_data_images: true,
  images_upload_handler: (blobInfo, success, error) => {
    imgCompLoading.value = true;
    // 压缩图片后上传
    let fileBlob = blobInfo.blob();
    // 压缩控制在2MB 2048KB
    const comSize = Math.ceil(fileBlob.size / 1024) > 2048 ? 2048 : Math.ceil(fileBlob.size / 1024);

    const img = new Image();
    img.src = blobInfo.blobUri();
    img.onload = function () {
      // 配置绘制选项
      const options = {
        width: img.width,
        height: img.height,
        quality: 0.8
      };
      // 开始绘制
      imagetoCanvas(img, options)
        .then(canvas => {
          canvas.toBlob(blob => {
            //开始压缩
            compressAccurately(blob, comSize)
              .then(blob => {
                const file = new File([blob], fileBlob.name, { type: fileBlob.type });

                // 使用 axios 上传，实际开发这段建议写在 api 中再调用 api
                const formData = new FormData();
                formData.append('file', file);
                formData.append('fileOriginName', blobInfo.filename());
                imgCompLoading.value = true;
                FileApi.commonUpload('N', formData)
                  .then(res => {
                    if (res.success) {
                      success(res.data.fileUrl);
                    } else {
                      error(res.message);
                    }
                  })
                  .catch(e => {
                    error(e.message);
                  })
                  .finally(() => {
                    imgCompLoading.value = false;
                  });
              })
              .catch(e => {
                console.error('压缩失败', e);
              });
          });
        })
        .catch(e => {
          console.error('绘制失败', e);
        });
    };
  }
});
</script>

<style scoped lang="less">
.file-box {
  position: relative;
}

.file-btn {
  position: absolute;
  top: -35px;
  right: 0;
}

:deep(.ant-upload-list-file-container:first-child) {
  margin-top: -30px !important;
}

.ant-upload-span {
  max-width: calc(100% - 75px);
  display: flex;
  align-items: center;

  .actions-icon {
    font-size: 16px;
    cursor: pointer;
    color: #00000073;
  }
}

.ant-upload-list-item {
  height: 40px !important;
  line-height: 40px;
}

.ant-upload-list-item-name {
  color: #60666b;
  width: auto;
  max-width: calc(100% - 75px) !important;
  font-size: 16px;
  line-height: 40px !important;
}

.ant-upload-list-item-name-size {
  margin-left: 10px;
  font-size: 14px;
  color: #898e91;
}

.ant-upload-list-item-info {
  margin-left: 40px;
}

.ant-upload-text-icon-index {
  margin-right: 5px;
  font-size: 16px;
  color: #898e91;
}

.ant-upload-text-icon-pdf {
  display: flex;
  align-items: center;
  justify-content: center;
}

.ant-upload-list-item-info .ant-upload-text-icon .anticon {
  top: 12px !important;
}
.ant-upload-list-item-card-actions {
  .ant-space {
    line-height: 45px !important;
  }
}

.ant-upload-list-item-card-actions {
  margin-left: 10px;
  width: 65px;
  height: 40px;
  line-height: 40px;
  position: relative;
}
.clear-icon {
  cursor: pointer;
  color: #898e91;

  &:hover {
    color: #60666b;
  }
}
:deep(.ant-upload.ant-upload-select-picture-card) {
  width: 125px;
  height: 125px;
  background-color: #fff;
  border: 1px solid var(--border-color-base);
}
:deep(.ant-upload-list-picture-card-container) {
  width: 125px;
  height: 125px;
}
.pick {
  :deep(.ant-form-item) {
    margin-bottom: 18px;
  }
  :deep(.ant-form-item-has-error) {
    margin-bottom: -6px !important;
  }
}
</style>
