Newer
Older
smart-metering-front / src / views / system / notice / noteAdd.vue
liyaguang on 16 Dec 2022 11 KB feat: 文件,图片预览
<!-- 新增通知公告弹窗 -->
<script lang="ts" setup name="addNotice">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import dayjs from 'dayjs'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { addNoticeApi, uploadApi } from '@/api/system/notice'
import { getPhotoUrl } from '@/api/system/tool'
import useUserStore from '@/store/modules/user'
import '@wangeditor/editor/dist/css/style.css' // 引入 css
const emits = defineEmits(['resetData'])
const userInfo = useUserStore()
const ruleFormRef = ref<FormInstance>() // from组件
const ruleForm = reactive({
  noticeNo: '', // 通知公告编号
  noticePublisher: '', // 发布人
  noticeCompany: '', // 发布单位
  noticeTime: '', // 发布时间
  noticeSketch: '', // 内容简述
  noticeContent: '', // 发布内容
  minioFileName: '', // 上传文件名
  noticeTitle: '', // 标题
}) // 表单
const rules = ref<FormRules>({
  noticeTitle: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
  noticeSketch: [{ required: true, message: '内容简述不能为空', trigger: 'blur' }],
  noticeContent: [{ required: true, message: '发布内容不能为空', trigger: 'blur' }],
}) // 表单验证规则
const dialogVisible = ref<boolean>(false) // 弹窗显示
// 弹窗初始化
const initDialog = () => {
  dialogVisible.value = true
  ruleForm.noticePublisher = userInfo.$state.name
  ruleForm.noticeCompany = userInfo.$state.deptName
  ruleForm.noticeTime = dayjs().format('YYYY-MM-DD')
}
defineExpose({ initDialog })
// 关闭弹窗
const close = () => {
  dialogVisible.value = false
  emits('resetData')
}
// 提交
const submitForm = async (formEl: FormInstance | undefined) => {
  console.log(ruleForm.noticeContent)
  if (!formEl) { return }
  await formEl.validate((valid, fields) => {
    if (valid) {
      ruleForm.noticeTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
      addNoticeApi(ruleForm).then((res) => {
        if (res.code === 200) {
          close()
          ElMessage.success('发布成功')
        }
        else {
          ElMessage.error(res.message)
        }
      })
    }
  })
}
// 取消
const resetForm = (formEl: FormInstance | undefined) => {
  // if (!formEl) { return }
  formEl?.resetFields()
  dialogVisible.value = false
  emits('resetData')
}
const fileRef = ref() // 文件上传input
const onFileChange = (event: any) => {
  // 原生上传图片
  // console.log(event.target.files)
  // if (event.target.files[0].type === 'application/pdf') {
  if (event.target.files?.length !== 0) {
    // 创建formdata对象
    const fd = new FormData()
    fd.append('multipartFile', event.target.files[0])
    uploadApi(fd).then((res) => {
      if (res.code === 200) {
        ruleForm.minioFileName = res.data[0]
        ElMessage.success('上传成功')
      }
      else {
        ElMessage.error(res.message)
      }
    })
  }
  // }
  // else {
  //   ElMessage.error('请上传pdf格式')
  // }
}
const upload = () => {
  fileRef.value.click()
}
// 富文本实例对象
const editorRef = shallowRef()
// 菜单配置
const toolbarConfig = ref({})
// 编辑器配置
const editorConfig = ref({
  placeholder: '请输入内容...',
  MENU_CONF: {
    // 配置上传图片
    uploadImage: {
      server: 'http://111.198.10.15:21409/minio/file/upload', // 配置图片上传地址
      maxFileSize: 2 * 1024 * 1024, // 10M  图片大小限制
      fieldName: 'img', // 上传类型
      allowedFileTypes: [], // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
      // 自定义上传参数,传递图片时需要带一些参数过去写在这。参数会被添加到 formData 中,一起上传到服务端。
      // meta: {
      //   image_class_id: "2",
      //   file_type: "1",
      // },
      // 自定义设置请求头,比如添加token之类的
      // headers: {
      //     Accept: 'text/x-json',
      //     otherKey: 'xxx'
      // },
      // 上传进度的回调函数,可以用来显示进度条
      onProgress(progress: any) {
        // progress 是 0-100 的数字
        console.log('progress', progress)
      },
      // // 单个文件上传成功之后
      // onSuccess(file, res) {
      //     console.log(`${file.name} 上传成功`, res)
      // },

      // 单个文件上传失败
      onFailed(file: any, res: any) {
        console.log(`${file.name} 上传失败`, res)
      },

      // 上传错误,或者触发 timeout 超时
      onError(file: any, err: any, res: any) {
        console.log(`${file.name} 上传出错`, err, res)
      },

      // 插入图片到富文本编辑器回显
      customInsert(res: any, insertFn: any) {
        console.log()
        // res 即服务端的返回结果
        getPhotoUrl(res.data[0]).then((res) => {
          const url = res.data
          const alt = ''
          const href = res.data
          // 从 res 中找到 url alt href ,然后插入图片
          insertFn(url, alt, href)
        })
      },
    },
    // 配置上传视频
    uploadVideo: {
      server: 'http://111.198.10.15:21409/minio/file/upload', // 配置视频上传地址
      maxFileSize: 5 * 1024 * 1024, // 5M  视频大小限制
      fieldName: 'your-custom-name', // 上传类型
      // 最多可上传几个文件,默认为 5
      maxNumberOfFiles: 3,
      allowedFileTypes: [], // 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []
      // 自定义上传参数,传递图片时需要带一些参数过去写在这。参数会被添加到 formData 中,一起上传到服务端。
      // meta: {
      //   type: 1,
      // },
      // 自定义设置请求头,比如添加token之类的
      // headers: {
      //     Accept: 'text/x-json',
      //     otherKey: 'xxx'
      // },
      metaWithUrl: false, // 将 meta 拼接到 url 参数中,默认 false
      withCredentials: true, // 跨域是否传递 cookie ,默认为 false
      // 上传之前触发
      onBeforeUpload(file: any) {
        // file 选中的文件,格式如 { key: file }
        return file
        // 可以 return
        // 1. return file 或者 new 一个 file ,接下来将上传
        // 2. return false ,不上传这个 file
      },

      // 上传进度的回调函数,可以用来显示进度条
      onProgress(progress: any) {
        // progress 是 0-100 的数字
        console.log('progress', progress)
      },

      // // 单个文件上传成功之后
      onSuccess(file: any, res: any) {
        console.log(`${file.name} 上传成功`, res)
      },

      // 单个文件上传失败
      onFailed(file: any, res: any) {
        console.log(`${file.name} 上传失败`, res)
      },

      // 上传错误,或者触发 timeout 超时
      onError(file: any, err: any, res: any) {
        console.log(`${file.name} 上传出错`, err, res)
      },

      // 插入图片到富文本编辑器回显
      customInsert(res: any, insertFn: any) {
        console.log(res, '视频插入')
        // res 即服务端的返回结果
        // let url = res.data.url;
        // let poster = res.data.poster;
        // 从 res 中找到 url poster ,然后插入
        // 参数url是视频地址,poster是视频封面图片,后端如果不返回,可以考虑写死一个固定的封面图
        getPhotoUrl(res.data[0]).then((res) => {
          const url = res.data
          // 从 res 中找到 url alt href ,然后插入图片
          insertFn(url, '')
        })
      },
    },
  },
})
const onCreated = (editor: any) => {
  editorRef.value = editor
  nextTick(() => {
    editorRef.value = editor // 一定要用 Object.seal() ,否则会报错
  })
}
const look = () => {
  console.log(ruleForm.noticeContent)
}
const minioFileUrl = ref('')
watch(() => ruleForm.minioFileName, (newVal) => {
  if (newVal) {
    getPhotoUrl(newVal).then((res) => {
      minioFileUrl.value = res.data
    })
  }
})
</script>

<template>
  <el-dialog v-if="dialogVisible" v-model="dialogVisible" title="添加公告" width="50%" append-to-body class="container">
    <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-position="right" label-width="110px">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="通知公告编号" prop="noticeNo">
            <el-input v-model.trim="ruleForm.noticeNo" placeholder="系统自动生成" disabled />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="发布人" prop="noticePublisher">
            <el-input v-model.trim="ruleForm.noticePublisher" disabled />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="发布单位" prop="noticeCompany">
            <el-input v-model.trim="ruleForm.noticeCompany" disabled />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="发布时间" prop="noticeTime">
            <el-input v-model.trim="ruleForm.noticeTime" disabled />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="标题" prop="noticeTitle">
        <el-input v-model.trim="ruleForm.noticeTitle" />
      </el-form-item>
      <el-form-item label="内容简述" prop="noticeSketch">
        <el-input v-model.trim="ruleForm.noticeSketch" />
      </el-form-item>
      <el-form-item label="发布内容" prop="noticeContent">
        <div style="border: 1px solid #dcdfe6;width: 100%;border-radius: 4px;">
          <toolbar
            style="border-bottom: 1px solid #dcdfe6;width: 100%;border-radius: 4px;"
            :editor="editorRef"
            :default-config="toolbarConfig"
            mode="default"
          />
          <editor
            v-model="ruleForm.noticeContent"
            style="height: 150px; overflow-y: hidden;"
            :default-config="editorConfig"
            mode="default"
            @onCreated="onCreated"
          />
        </div>
        <!-- <el-input v-model.trim="ruleForm.noticeContent" :rows="4" type="textarea" /> -->
      </el-form-item>
      <el-form-item label="附件" prop="minioFileName">
        <el-link v-if="ruleForm.minioFileName" :href="minioFileUrl" type="primary" target="_blank">
          {{ ruleForm.minioFileName }}
        </el-link>
        <el-button type="primary" :style="{ 'margin-left': ruleForm.minioFileName === '' ? '0px' : '20px' }" @click="upload">
          {{ ruleForm.minioFileName === '' ? '上传' : '更换附件' }}
        </el-button>
        <input v-show="false" ref="fileRef" type="file" accept="pdf/*" @change="onFileChange">
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm(ruleFormRef)">
          发布
        </el-button>
        <el-button @click="resetForm(ruleFormRef)">
          关闭
        </el-button>
      </el-form-item>
    </el-form>
  </el-dialog>
</template>

<style lang="scss" scoped>
.container {
  ::v-deep {
    .w-e-bar {
      padding: 0;

      .w-e-bar-item {
        padding: 0;
        height: 30px;
      }

      .w-e-bar-divider {
        margin: 0;
        display: none;
        width: 0;
        height: 0;
      }
    }
  }
}
</style>