123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 |
- <template>
- <div class="systemNotifyModel">
- <div class="m-core">
- <el-form
- :model="form"
- :rules="rules"
- ref="form"
- label-width="110px"
- style="width: 100%"
- >
- <el-form-item label="标题" prop="title">
- <el-input v-model.trim="form.title" placeholder="请输入标题"></el-input>
- </el-form-item>
- <el-form-item label="排序值">
- <el-input
- v-model.trim="form.order"
- placeholder="请输入排序值"
- type="number"
- ></el-input>
- </el-form-item>
- <el-form-item prop="subType" label="类型">
- <el-select v-model="form.subType" clearable placeholder="帮助类型">
- <el-option
- v-for="item in typeList"
- :key="item.id"
- :label="item.name"
- :value="item.id"
- ></el-option>
- </el-select>
- </el-form-item>
- <!-- <el-form-item label="自动开启时间" prop="actionTime" :rules="[{required: true, message: '请选择自动开启时间范围', trigger: 'change'}]">
- <el-date-picker style="width:400px;"
- v-model="form.actionTime"
- :clearable="false"
- type="datetimerange"
- range-separator="至"
- :picker-options="{ firstDayOfWeek: 1 }"
- start-placeholder="开始日期"
- end-placeholder="结束日期">
- </el-date-picker>
- </el-form-item> -->
- <el-form-item
- label="内容"
- prop="content"
- v-if="outUrlRadio == 0"
- :rules="[{ required: true, message: '请编辑内容', trigger: 'blur' }]"
- >
- <quill-editor
- class="ql-editor"
- style="margin-top: -17px"
- v-model="form.content"
- ref="myQuillEditor"
- :options="editorOption"
- @change="onEditorChange($event)"
- ></quill-editor>
- <el-upload
- class="ivu-upload"
- :show-upload-list="false"
- :on-success="handleSuccess"
- accept=".jpg, .jpeg, .png, .gif"
- :max-size="2048"
- multiple
- :action="ossUploadUrl"
- :data="dataObj"
- :before-upload="beforeImgUpload"
- >
- <Button icon="ios-cloud-upload-outline"></Button>
- </el-upload>
- </el-form-item>
- <el-form-item>
- <el-button @click="onSubmit('form')" type="primary"
- >立即{{ pageType == "create" ? "创建" : "修改" }}</el-button
- >
- <el-button @click="onReSet('form')">重置</el-button>
- <!-- <el-button @click="onLook">预览</el-button> -->
- </el-form-item>
- </el-form>
- </div>
- <el-dialog
- title="插入视频"
- :append-to-body="true"
- width="500px"
- @close="onDialogClose('diologForm')"
- :visible.sync="dialogFormVisible"
- >
- <el-form :model="dialogForm" ref="diologForm" :rules="dialogFormRules">
- <el-form-item
- label="封面图地址"
- prop="poster"
- :rules="[
- {
- required: uploadType == 2 ? true : false,
- message: '请上传封面图',
- trigger: 'blur',
- },
- ]"
- label-width="120px"
- >
- <el-upload
- class="avatar-uploader"
- style="line-height: 0; display: inline-block"
- :action="ossUploadUrl"
- :data="dataObj"
- :show-file-list="false"
- v-loading="uploadImgLoading"
- accept=".jpg, .jpeg, .png, .gif"
- :on-success="handleImgSuccess"
- :on-error="handleUploadImgError"
- :before-upload="beforeImgUpload"
- >
- <img v-if="dialogForm.poster" :src="dialogForm.poster" class="avatar" />
- <i v-else class="el-icon-plus avatar-uploader-icon"></i>
- </el-upload>
- </el-form-item>
- <el-form-item label="视频类型" label-width="120px">
- <el-radio-group v-model="formRadio">
- <el-radio :label="1">外部链接</el-radio>
- <el-radio :label="2">上传</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item
- v-if="formRadio == 1"
- label="视频地址"
- label-width="120px"
- prop="url"
- >
- <el-input
- v-model="dialogForm.url"
- style="width: 100%"
- autocomplete="off"
- ></el-input>
- </el-form-item>
- <el-form-item
- v-if="formRadio == 2"
- label="上传视频"
- label-width="120px"
- prop="videoUrl"
- >
- <el-upload
- class="upload-demo"
- style="display: inline-block"
- v-loading="uploadLoading"
- :action="ossUploadUrl"
- :data="dataObj"
- :before-upload="beforeUpload"
- :on-success="handleUploadSuccess"
- :on-error="handleUploadError"
- :show-file-list="false"
- accept=".mp4"
- :file-list="fileList"
- :on-exceed="handleExceed"
- >
- <video
- style="width: 120px; height: 120px"
- v-if="dialogForm.videoUrl"
- type="video/mp4"
- preload="auto"
- :src="dialogForm.videoUrl"
- ></video>
- <i v-else class="el-icon-plus avatar-uploader-icon"></i>
- </el-upload>
- <p class="imageSize">
- <!-- 广告管理 & 广告类型为 视频 -->
- <span v-if="uploadType == 2 && type == 8"
- >上传视频尺寸建议:1242px * 2208px;</span
- ><br />
- 只能上传mp4文件, 且不超过100M
- </p>
- </el-form-item>
- </el-form>
- <div slot="footer" class="dialog-footer">
- <el-button @click="dialogFormVisible = false">取 消</el-button>
- <el-button type="primary" @click="onVideoComfirm('diologForm')">确 定</el-button>
- </div>
- </el-dialog>
- <el-dialog
- width="375px"
- title="预览"
- :append-to-body="true"
- :visible.sync="lookVisible"
- >
- <div class="sd-container">
- <h2>{{ dataInfo.title }}</h2>
- <div class="titleInfo">
- <p>{{ typeCheck(dataInfo.type) }}</p>
- <p>{{ dataInfo.updateTime }}</p>
- </div>
- <div class="msgWrap quill-editor ql-editor" v-html="dataInfo.content"></div>
- </div>
- </el-dialog>
- </div>
- </template>
- <script>
- import { policy } from "@/api/appTenant";
- import { newsQueryId, newsAdd, newsUpdate } from "@/api/contentManager";
- import { getToken } from "@/utils/auth";
- import { vaildStudentUrl } from "@/utils/validate";
- import "quill/dist/quill.core.css";
- import "quill/dist/quill.snow.css";
- import "quill/dist/quill.bubble.css";
- import Quill from "quill";
- import { quillEditor } from "vue-quill-editor";
- // 工具栏配置
- const toolbarOptions = [
- ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
- ["blockquote", "code-block"], // 引用 代码块
- [{ header: 1 }, { header: 2 }], // 1、2 级标题
- [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
- [{ script: "sub" }, { script: "super" }], // 上标/下标
- [{ indent: "-1" }, { indent: "+1" }], // 缩进
- // [{'direction': 'rtl'}], // 文本方向
- [{ size: ["small", false, "large", "huge"] }], // 字体大小
- [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
- [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
- [{ font: [] }], // 字体种类
- [{ align: [] }], // 对齐方式
- ["clean"], // 清除文本格式
- ["image", "video"], // 链接、图片、视频
- // ["link", "image", "video"] // 链接、图片、视频
- ];
- // 标题
- const titleConfig = {
- "ql-bold": "加粗",
- "ql-color": "颜色",
- "ql-font": "字体",
- "ql-code": "插入代码",
- "ql-italic": "斜体",
- // 'ql-link': '添加链接',
- "ql-background": "背景颜色",
- "ql-size": "字体大小",
- "ql-strike": "删除线",
- "ql-script": "上标/下标",
- "ql-underline": "下划线",
- "ql-blockquote": "引用",
- "ql-header": "标题",
- "ql-indent": "缩进",
- "ql-list": "列表",
- "ql-align": "文本对齐",
- "ql-direction": "文本方向",
- "ql-code-block": "代码块",
- "ql-formula": "公式",
- "ql-image": "图片",
- "ql-video": "视频",
- "ql-clean": "清除字体样式",
- "ql-upload": "文件",
- };
- // 这里引入修改过的video模块并注册
- import Video from "../../quill/video.js";
- import dayjs from "dayjs";
- Quill.register(Video, true);
- export default {
- props: ["options", "typeList"],
- name: "contentOperation",
- components: {
- quillEditor,
- },
- data() {
- let that = this;
- const query = this.options;
- return {
- uploadType: 1, // 上传类型
- uploadStatus: false,
- type: query.type,
- pageType: query.pageType,
- organId: null,
- // headers: {
- // Authorization: getToken()
- // },
- content: null,
- dialogFormVisible: false,
- formRadio: 1,
- lookVisible: false,
- dataInfo: {
- title: "",
- type: query.type,
- updateTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
- content: null,
- },
- editorIndex: 0, // 光标位置
- editorOption: {
- placeholder: "请输入内容",
- modules: {
- toolbar: {
- container: toolbarOptions,
- handlers: {
- image: function (value) {
- if (value) {
- // 调用iview图片上传
- document.querySelector(".ivu-upload .el-upload").click();
- } else {
- this.quill.format("image", false);
- }
- },
- video: function (value) {
- if (value) {
- that.dialogFormVisible = true;
- let editor = that.$refs.myQuillEditor.quill;
- // 光标所在位置
- that.editorIndex = editor.getSelection().index;
- } else {
- this.quill.format("image", false);
- }
- },
- },
- },
- },
- },
- dialogForm: {
- poster: null,
- url: null,
- videoUrl: null,
- },
- uploadLoading: false,
- uploadImgLoading: false,
- fileList: [],
- dialogFormRules: {
- url: [{ required: true, message: "请输入视频地址", trigger: "blur" }],
- videoUrl: [{ required: true, message: "请上传视频", trigger: "blur" }],
- },
- outUrlRadio: 0, // 是否使用外部连接,默认不使用
- form: {
- title: null,
- order: null,
- linkUrl: null,
- type: query.type,
- status: 0,
- content: null,
- organIdList: [],
- },
- rules: {
- title: [
- { required: true, message: "请输入标题", trigger: "blur" },
- {
- min: 2,
- max: 30,
- message: "长度在 2 到 30 个字符",
- trigger: "blur",
- },
- ],
- organIdList: [{ required: true, message: "请选择分部", trigger: "change" }],
- },
- imageSize: null,
- dataObj: {
- policy: "",
- signature: "",
- key: "",
- KSSAccessKeyId: "",
- // dir: "",
- acl: "public-read",
- name: "",
- // bucket_name: props.bucket_name
- },
- // ossUploadUrl: "https://ks3-cn-beijing.ksyuncs.com/" + "news-info",
- ossUploadUrl: `https://gyt.ks3-cn-beijing.ksyuncs.com`,
- bucket_name: "gyt",
- };
- },
- mounted() {
- this.$store.dispatch("setBranchs");
- this.init();
- },
- methods: {
- init() {
- this.getList();
- this.addQuillTitle();
- // this.form.type
- let tempTitle = {
- 1: "468px * 552px;图片不能超过 2M;",
- 2: "456px * 288px; 图片不能超过 2M;",
- 3: "686px * 140px; 图片不能超过 2M;",
- 4: "图片不能超过 2M;",
- 5: "图片不能超过 2M;",
- 6: "图片不能超过 2M;",
- 7: "图片不能超过 2M;",
- 8: "1242px * 2208px; 图片不能超过 2M;",
- };
- this.imageSize = tempTitle[this.form.type];
- this.$refs["form"].clearValidate();
- },
- onVideoComfirm(formName) {
- this.$refs[formName].validate((valid) => {
- if (valid) {
- let dialogForm = this.dialogForm;
- // 编辑器输入视频
- // 获取富文本组件实例
- let quill = this.editor;
- // 插入图片,res为服务器返回的图片链接地址
- const params = {
- poster: dialogForm.poster,
- url: this.formRadio == 1 ? dialogForm.url : dialogForm.videoUrl,
- };
- quill.insertEmbed(this.editorIndex, "video", params);
- // 调整光标到最后
- quill.setSelection(this.editorIndex + 1, { preload: false });
- this.dialogFormVisible = false;
- this.dialogForm = {
- poster: null,
- url: null,
- videoUrl: null,
- };
- } else {
- return false;
- }
- });
- },
- onDialogClose(diologForm) {
- this.dialogForm = {
- poster: null,
- url: null,
- videoUrl: null,
- };
- this.$refs[diologForm].resetFields();
- },
- addQuillTitle() {
- const oToolBar = document.querySelector(".ql-toolbar"),
- aButton = oToolBar.querySelectorAll("button"),
- aSelect = oToolBar.querySelectorAll("select");
- aButton.forEach(function (item) {
- if (item.className === "ql-script") {
- item.value === "sub" ? (item.title = "下标") : (item.title = "上标");
- } else if (item.className === "ql-indent") {
- item.value === "+1" ? (item.title = "向右缩进") : (item.title = "向左缩进");
- } else {
- item.title = titleConfig[item.classList[0]];
- }
- });
- aSelect.forEach(function (item) {
- item.parentNode.title = titleConfig[item.classList[0]];
- });
- },
- onSubmit(formName) {
- this.$refs[formName].validate(async (valid) => {
- if (valid) {
- let { organIdList, linkUrl, content, ...rest } = this.form;
- if (this.outUrlRadio == 1) {
- content = null;
- } else {
- linkUrl = null;
- }
- let form = {
- ...rest,
- linkUrl,
- content,
- organIdList: organIdList ? organIdList.join(",") : null,
- };
- if (this.pageType == "create") {
- if (form.id) {
- // 判断有没有Id,如果有则删除
- delete form.id;
- }
- // return false
- await newsAdd(form).then((res) => {
- this.messageTips("添加", res);
- });
- } else if (this.pageType == "update") {
- await newsUpdate(form).then((res) => {
- this.messageTips("修改", res);
- });
- }
- } else {
- this.$nextTick(() => {
- let isError = document.getElementsByClassName("is-error");
- isError[0].scrollIntoView({
- block: "center",
- behavior: "smooth",
- });
- });
- return false;
- }
- });
- },
- messageTips(title, res) {
- if (res.code == 200) {
- this.$message.success(title + "成功");
- this.$listeners.submited();
- this.$listeners.close();
- } else {
- this.$message.error(res.msg);
- }
- },
- handleSuccess(res) {
- // 获取富文本组件实例
- this.uploadImgLoading = false;
- let quill = this.editor;
- // 如果上传成功
- let url = this.ossUploadUrl + "/" + this.dataObj.key;
- if (url) {
- // 获取光标所在位置
- let length = quill.getSelection().index;
- // 插入图片,res为服务器返回的图片链接地址
- quill.insertEmbed(length, "image", url);
- // 调整光标到最后
- quill.setSelection(length + 1);
- } else {
- // 提示信息,需引入Message
- this.$message.error("图片插入失败");
- }
- },
- onReSet(formName) {
- this.form = {
- title: null,
- order: null,
- linkUrl: null,
- type: this.type,
- status: 1,
- content: null,
- organIdList: [],
- };
- this.$refs[formName].resetFields();
- },
- onLook() {
- // 预览
- let dataInfo = this.dataInfo;
- dataInfo.title = this.form.title;
- dataInfo.content = this.form.content;
- // 处理图片显示问题
- setTimeout(() => {
- let imgNode = document.querySelectorAll(".msgWrap img");
- if (imgNode.length > 0) {
- imgNode.forEach((item) => {
- item.style.width = "100%";
- });
- }
- let videoNode = document.querySelectorAll(".msgWrap .ql-video");
- if (videoNode.length > 0) {
- videoNode.forEach((item) => {
- item.style.width = "100%";
- item.style.height = "195px";
- });
- }
- }, 500);
- this.lookVisible = true;
- },
- async getList() {
- if (this.pageType == "create") {
- return;
- } else {
- await newsQueryId({ id: this.options.id }).then((res) => {
- if (res.code == 200) {
- let result = res.data;
- let organ = result.organIdList ? result.organIdList.split(",") : [];
- // 是否使用外部链接
- if (result.linkUrl) {
- this.outUrlRadio = 1;
- } else {
- this.outUrlRadio = 0;
- }
- this.form = {
- id: result.id,
- title: result.title,
- order: result.order,
- linkUrl: result.linkUrl,
- type: result.type,
- status: result.status,
- organIdList: organ.map((item) => {
- return +item;
- }),
- content: result.content,
- subType: result.subType,
- };
- this.dataInfo.updateTime = result.updateTime;
- }
- });
- }
- },
- handleUploadImgError(file) {
- this.uploadImgLoading = false;
- this.$message.error("上传失败");
- },
- handleImgSuccess(res, file) {
- this.uploadImgLoading = false;
- let url = this.ossUploadUrl + "/" + this.dataObj.key;
- if (url) {
- this.dialogForm.poster = url;
- } else {
- this.$message.error("上传失败");
- }
- },
- async beforeImgUpload(file) {
- const imageType = {
- "image/png": true,
- "image/jpeg": true,
- };
- const isImage = imageType[file.type];
- const isLt2M = file.size / 1024 / 1024 < 2;
- isImage, isLt2M;
- if (!isImage) {
- this.$message.error("只能上传图片格式!");
- }
- if (!isLt2M) {
- this.$message.error("上传图片大小不能超过 2MB!");
- }
- if (isImage && isLt2M) {
- this.uploadImgLoading = true;
- }
- try {
- let fileName = file.name.replaceAll(" ", "_");
- let key = new Date().getTime() + fileName;
- let obj = {
- filename: fileName,
- bucketName: this.bucket_name,
- postData: {
- filename: fileName,
- acl: "public-read",
- key: key,
- unknowValueField: [],
- },
- };
- const res = await policy(obj);
- this.dataObj = {
- policy: res.data.policy,
- signature: res.data.signature,
- key: key,
- KSSAccessKeyId: res.data.kssAccessKeyId,
- // dir: "",
- acl: "public-read",
- name: fileName,
- // bucket_name: props.bucket_name
- };
- } catch (e) {
- console.log(e);
- return false;
- }
- return isImage && isLt2M;
- },
- typeCheck(type) {
- let params = {
- 1: "精彩活动",
- 2: "热门资讯",
- 4: "专项训练",
- 7: "知识库",
- 19: "系统通知",
- };
- return params[type] ? params[type] : "管乐迷";
- },
- typeIndex(type) {
- let tempTitle = {
- 1: 0,
- 2: 1,
- 3: 4,
- 4: 2,
- 5: 3,
- 6: 5,
- 7: 6,
- 8: 7,
- 19: 8,
- };
- return tempTitle[type];
- },
- onEditorChange({ quill, html, text }) {
- this.form.content = html;
- },
- async beforeUpload(file) {
- // const isJPG = file.type === 'image/jpeg';
- const isLt2M = file.size / 1024 / 1024 < 100;
- // if (!isJPG) {
- // this.$message.error('上传头像图片只能是 JPG 格式!');
- // }
- if (!isLt2M) {
- this.$message.error("上传视频大小不能超过 100MB!");
- }
- this.uploadLoading = true;
- try {
- let fileName = file.name.replaceAll(" ", "_");
- let key = new Date().getTime() + fileName;
- let obj = {
- filename: fileName,
- bucketName: this.bucket_name,
- postData: {
- filename: fileName,
- acl: "public-read",
- key: key,
- unknowValueField: [],
- },
- };
- const res = await policy(obj);
- this.dataObj = {
- policy: res.data.policy,
- signature: res.data.signature,
- key: key,
- KSSAccessKeyId: res.data.kssAccessKeyId,
- // dir: "",
- acl: "public-read",
- name: fileName,
- // bucket_name: props.bucket_name
- };
- } catch (e) {
- console.log(e);
- return false;
- }
- return isLt2M;
- },
- handleUploadError(file) {
- this.uploadLoading = false;
- this.$message.error("上传视频失败");
- },
- handleUploadSuccess(file, fileList) {
- this.uploadLoading = false;
- let url = this.ossUploadUrl + "/" + this.dataObj.key;
- if (url) {
- this.$message.success("上传视频成功");
- this.dialogForm.videoUrl = url;
- } else {
- this.$message.error("上传视频失败");
- }
- },
- handleExceed(files, fileList) {
- this.$message.error("您已上传过视频");
- },
- },
- computed: {
- editor() {
- return this.$refs.myQuillEditor.quill;
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .systemNotifyModel {
- min-width: 100%;
- }
- .el-input {
- width: 400px;
- }
- ::v-deep .el-select {
- width: 400px !important;
- .el-input {
- width: 400px;
- }
- .el-select-dropdown {
- width: 400px;
- }
- }
- ::v-deep .ql-editor {
- min-height: 300px;
- padding: 0;
- }
- ::v-deep .ql-container .ql-editor {
- max-height: 500px;
- padding: 15px;
- }
- .el-row {
- margin-top: 40px;
- }
- .el-col {
- display: flex;
- align-items: center;
- margin-bottom: 20px;
- justify-content: flex-end;
- margin-right: 50%;
- }
- .el-input-group {
- width: 200px;
- margin: 0 20px;
- }
- ::v-deep .el-tree-node__content {
- height: 40px !important;
- }
- ::v-deep .avatar-uploader .el-upload,
- ::v-deep .upload-demo .el-upload {
- border-radius: 6px;
- cursor: pointer;
- position: relative;
- overflow: hidden;
- }
- .avatar-uploader .el-upload:hover {
- border-color: #409eff;
- }
- .avatar-uploader-icon {
- border: 1px dashed #d9d9d9;
- font-size: 28px;
- color: #8c939d;
- width: 120px;
- height: 120px;
- line-height: 120px;
- text-align: center;
- }
- .avatar {
- width: 120px;
- height: 120px;
- display: block;
- }
- .ivu-upload {
- display: none;
- }
- .sd-container {
- // padding: 15px;
- h2 {
- height: auto;
- font-weight: 500;
- color: rgba(68, 68, 68, 1);
- line-height: 37px;
- font-size: 26px;
- margin-bottom: 10px;
- }
- .titleInfo {
- height: 15px;
- line-height: 15px;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- color: #444;
- margin-bottom: 25px;
- }
- .imgWrap {
- /* width: 100;
- height: 1.45rem; */
- margin-bottom: 0.15rem;
- p {
- font-size: 0.16rem;
- font-family: PingFangSC;
- font-weight: 400;
- color: rgba(68, 68, 68, 1);
- line-height: 0.28rem;
- text-indent: 0.32rem;
- }
- img {
- width: 100%;
- }
- }
- }
- .imageSize {
- color: red;
- line-height: 1.5;
- }
- </style>
|