| | |
| | | </Option> |
| | | </Select> |
| | | </FormItem> |
| | | <FormItem label="审核情况" prop="audit"> |
| | | <Select |
| | | v-model="searchForm.audit" |
| | | placeholder="请选择审核情况" |
| | | style="width: 180px" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | > |
| | | <Option |
| | | v-for="item in auditSelect" |
| | | :value="item.value" |
| | | :key="item.id" |
| | | > |
| | | {{ item.label }} |
| | | </Option> |
| | | </Select> |
| | | </FormItem> |
| | | <FormItem label="报名开始时间" prop="reportStartTime"> |
| | | <DatePicker |
| | | :value="searchForm.reportStartTime" |
| | |
| | | size="small" |
| | | @click="openMembersModal(row)" |
| | | >报名人员</Button> |
| | | <Button |
| | | type="success" |
| | | size="small" |
| | | :disabled="row.auditStatus !== 0" |
| | | @click="openAuditModal(row)" |
| | | >审核活动</Button> |
| | | </div> |
| | | </template> |
| | | </Table> |
| | |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="活动地点" prop="activityLocation"> |
| | | <Col span="12" v-if="activityFrom.activityType === 'offline'"> |
| | | <FormItem label="活动地点" prop="activityLocation" > |
| | | <Input |
| | | v-model="activityFrom.activityLocation" |
| | | placeholder="请输入活动地点" |
| | |
| | | </Col> |
| | | <Col span="24"> |
| | | <FormItem label="活动内容:" prop="activityContent"> |
| | | <editor ref="editor" @input="getReason" /> |
| | | |
| | | <!-- 基于elementUi的上传组件 el-upload begin--> |
| | | <Upload |
| | | :show-upload-list="false" |
| | | ref="upload" |
| | | style="display: none" |
| | | :before-upload="handleUploadEdit" |
| | | :format="['jpg','jpeg','png','gif','mp4','mov']" |
| | | :max-size="20480" |
| | | action="" |
| | | accept="image/*,video/*" |
| | | > |
| | | </Upload> |
| | | <!-- 基于elementUi的上传组件 el-upload end--> |
| | | <quill-editor |
| | | v-model="activityFrom.activityContent" |
| | | ref="QuillEditor" |
| | | class="editor" |
| | | :options="editorOption" |
| | | @blur="onEditorBlur($event)" |
| | | @focus="onEditorFocus($event)" |
| | | @ready="onEditorReady($event)" |
| | | > |
| | | </quill-editor> |
| | | </FormItem> |
| | | </Col> |
| | | </Row> |
| | |
| | | </Modal> |
| | | |
| | | |
| | | <Modal |
| | | v-model="auditModelShow" |
| | | :title="modelTitle" |
| | | @on-cancel="closeAuditModel" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <div class="detail-container"> |
| | | <Row :gutter="16"> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动名称:</label> |
| | | <span>{{ activityInfo.activityName || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动类型:</label> |
| | | <span>{{activityInfo.activityType === 'online' ? '线上':'线下'}}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>报名时间段:</label> |
| | | <span>{{ activityInfo.reportStartTime }} - {{ activityInfo.reportEndTime }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动时间段:</label> |
| | | <span>{{ activityInfo.startTime }} - {{ activityInfo.endTime }}</span> |
| | | </div> |
| | | </Col> |
| | | |
| | | <Col span="24" v-if="coverType === '输入文字封面'"> |
| | | <div class="detail-item"> |
| | | <label>封面文字:</label> |
| | | <span>{{ activityInfo.cover || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="24" v-if="coverType === '选择文件封面'"> |
| | | <div class="detail-item"> |
| | | <label>上传封面:</label> |
| | | <span>{{ activityInfo.cover }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>人数限制:</label> |
| | | <span>{{ activityInfo.limitUserNum || '无限制' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动地点:</label> |
| | | <span>{{ activityInfo.activityLocation || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="24"> |
| | | <div class="detail-item"> |
| | | <label>活动内容:</label> |
| | | <div |
| | | class="activity-content" |
| | | v-html="activityInfo.activityContent || '无内容'" |
| | | ref="“activityHTMLContent" |
| | | ></div> |
| | | </div> |
| | | </Col> |
| | | <Col span="24"> |
| | | <Form :model="auditForm" :rules="auditRules" ref="auditForm" class="audit-form"> |
| | | <FormItem label="审核结果:" prop="audit"> |
| | | <RadioGroup v-model="auditForm.audit"> |
| | | <Radio label="1">通过</Radio> |
| | | <Radio label="2">未通过</Radio> |
| | | </RadioGroup> |
| | | </FormItem> |
| | | <FormItem label="审核备注:" prop="remarks"> |
| | | <Input |
| | | v-model="auditForm.remarks" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请输入审核备注(选填)" |
| | | :disabled="!auditForm.audit" |
| | | /> |
| | | </FormItem> |
| | | </Form> |
| | | </Col> |
| | | </Row> |
| | | </div> |
| | | |
| | | <!-- 审核表单 --> |
| | | |
| | | |
| | | <div slot="footer"> |
| | | <Button @click="closeAuditModel">关闭</Button> |
| | | <Button |
| | | type="primary" |
| | | @click="handleAuditSubmit(activityInfo.id)" |
| | | :disabled="!auditForm.audit" |
| | | >提交审核</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | |
| | | <!-- 图片预览模态框 --> |
| | | <Modal v-model="previewVisible" title="图片预览" footer-hide> |
| | | <img :src="previewImageUrl" style="width: 100%"> |
| | |
| | | addActivity, |
| | | editActivity, |
| | | delActivityById, |
| | | delActivityBatch, |
| | | activityChangeStatus, |
| | | activityChangeRecommend, |
| | | activityMembersPage |
| | | activityMembersPage, |
| | | auditActivity |
| | | } from "@/api/activity.js" |
| | | import Editor from '@/components/editor/index.vue' |
| | | import { uploadFileByLmk, delByKey } from "@/api/common.js" |
| | | |
| | | import { quillEditor } from 'vue-quill-editor' |
| | | import 'quill/dist/quill.core.css'; |
| | | import 'quill/dist/quill.snow.css'; |
| | | import 'quill/dist/quill.bubble.css'; |
| | | |
| | | import * as Quill from 'quill' //引入编辑器 |
| | | import VideoBlot from './video.js'; |
| | | |
| | | const toolbarOptions = [ |
| | | ['bold', 'italic', 'underline', 'strike'], // 加粗,斜体,下划线,删除线 |
| | | ['blockquote', 'code-block'], //引用,代码块 |
| | | [{ 'header': 1 }, { 'header': 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'], // 清除样式, |
| | | ['link'], |
| | | ['myUploadBtn'], |
| | | ] |
| | | |
| | | // toolbar标题 |
| | | const titleConfig = [ |
| | | { Choice: '.ql-insertMetric', title: '跳转配置' }, |
| | | { Choice: '.ql-bold', title: '加粗' }, |
| | | { Choice: '.ql-italic', title: '斜体' }, |
| | | { Choice: '.ql-underline', title: '下划线' }, |
| | | { Choice: '.ql-header', title: '段落格式' }, |
| | | { Choice: '.ql-strike', title: '删除线' }, |
| | | { Choice: '.ql-blockquote', title: '块引用' }, |
| | | { Choice: '.ql-code', title: '插入代码' }, |
| | | { Choice: '.ql-code-block', title: '插入代码段' }, |
| | | { Choice: '.ql-font', title: '字体' }, |
| | | { Choice: '.ql-size', title: '字体大小' }, |
| | | { Choice: '.ql-list[value="ordered"]', title: '编号列表' }, |
| | | { Choice: '.ql-list[value="bullet"]', title: '项目列表' }, |
| | | { Choice: '.ql-direction', title: '文本方向' }, |
| | | { Choice: '.ql-header[value="1"]', title: 'h1' }, |
| | | { Choice: '.ql-header[value="2"]', title: 'h2' }, |
| | | { Choice: '.ql-align', title: '对齐方式' }, |
| | | { Choice: '.ql-color', title: '字体颜色' }, |
| | | { Choice: '.ql-background', title: '背景颜色' }, |
| | | { Choice: '.ql-image', title: '图像' }, |
| | | { Choice: '.ql-video', title: '视频' }, |
| | | { Choice: '.ql-link', title: '添加链接' }, |
| | | { Choice: '.ql-formula', title: '插入公式' }, |
| | | { Choice: '.ql-clean', title: '清除字体格式' }, |
| | | { Choice: '.ql-script[value="sub"]', title: '下标' }, |
| | | { Choice: '.ql-script[value="super"]', title: '上标' }, |
| | | { Choice: '.ql-indent[value="-1"]', title: '向左缩进' }, |
| | | { Choice: '.ql-indent[value="+1"]', title: '向右缩进' }, |
| | | { Choice: '.ql-header .ql-picker-label', title: '标题大小' }, |
| | | { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' }, |
| | | { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' }, |
| | | { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' }, |
| | | { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' }, |
| | | { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' }, |
| | | { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' }, |
| | | { Choice: '.ql-header .ql-picker-item:last-child', title: '标准' }, |
| | | { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' }, |
| | | { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' }, |
| | | { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' }, |
| | | { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' }, |
| | | { Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' }, |
| | | { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' }, |
| | | { Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' }, |
| | | { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' } |
| | | ] |
| | | |
| | | export default { |
| | | name: "ActivityManagement", |
| | | components: {Editor}, |
| | | components: { quillEditor}, |
| | | data() { |
| | | return { |
| | | infoModelShow:false, |
| | | auditForm: { |
| | | activityId: '', |
| | | audit: null, |
| | | remarks: '' |
| | | }, |
| | | auditRules: { |
| | | audit: [ |
| | | {required: true, message: '请选择审核结果', trigger: 'change'} |
| | | ] |
| | | }, |
| | | infoModelShow: false, |
| | | auditModelShow: false, |
| | | |
| | | loading: false, |
| | | membersLoading: false, |
| | |
| | | |
| | | // 搜索表单 |
| | | searchForm: { |
| | | audit: '', |
| | | activityName: '', |
| | | activityType: '', |
| | | reportStartTime: '', |
| | |
| | | |
| | | // 活动类型选项 |
| | | typeSelect: [ |
| | | { id: 1, value: 'online',label:'线上' }, |
| | | { id: 2, value: 'offline',label:'线下' } |
| | | {id: 1, value: 'online', label: '线上'}, |
| | | {id: 2, value: 'offline', label: '线下'} |
| | | ], |
| | | auditSelect: [ |
| | | {id: 1, value: '1', label: '已审核'}, |
| | | {id: 2, value: '0', label: '未审核'} |
| | | ], |
| | | |
| | | // 封面类型选项 |
| | | coverTypeOptions: [ |
| | | { id: 1, value: '输入文字封面' }, |
| | | { id: 2, value: '选择文件封面' } |
| | | {id: 1, value: '输入文字封面'}, |
| | | {id: 2, value: '选择文件封面'} |
| | | ], |
| | | coverType: '', |
| | | file: null, |
| | |
| | | // 表单验证规则 |
| | | rules: { |
| | | activityName: [ |
| | | { required: true, message: '请输入活动名称', trigger: 'blur' }, |
| | | { max: 50, message: '长度不能超过50个字符', trigger: 'blur' } |
| | | {required: true, message: '请输入活动名称', trigger: 'blur'}, |
| | | {max: 50, message: '长度不能超过50个字符', trigger: 'blur'} |
| | | ], |
| | | activityType: [ |
| | | { required: true, message: '请选择活动类型', trigger: 'change' } |
| | | {required: true, message: '请选择活动类型', trigger: 'change'} |
| | | ], |
| | | reportTime: [ |
| | | { type: 'array', required: true, message: '请选择报名时间段', trigger: 'change' }, |
| | | { validator: this.validateReportTime, trigger: 'change' } |
| | | {type: 'array', required: true, message: '请选择报名时间段', trigger: 'change'}, |
| | | {validator: this.validateReportTime, trigger: 'change'} |
| | | ], |
| | | time: [ |
| | | { type: 'array', required: true, message: '请选择活动时间段', trigger: 'change' }, |
| | | { validator: this.validateActivityTime, trigger: 'change' } |
| | | {type: 'array', required: true, message: '请选择活动时间段', trigger: 'change'}, |
| | | {validator: this.validateActivityTime, trigger: 'change'} |
| | | ], |
| | | cover: [ |
| | | { required: true, message: '请输入封面内容', trigger: 'blur' } |
| | | {required: true, message: '请输入封面内容', trigger: 'blur'} |
| | | ], |
| | | coverType: [ |
| | | { required: true, message: '请选择封面类型', trigger: 'blur' } |
| | | {required: true, message: '请选择封面类型', trigger: 'blur'} |
| | | ], |
| | | limitUserNum: [ |
| | | { required: true, type: 'number', message: '请输入人数限制', trigger: 'blur' }, |
| | | { type: 'number', min: 1, message: '人数不能少于1人', trigger: 'blur' } |
| | | {required: true, type: 'number', message: '请输入人数限制', trigger: 'blur'}, |
| | | {type: 'number', min: 1, message: '人数不能少于1人', trigger: 'blur'} |
| | | ], |
| | | activityLocation: [ |
| | | { required: true, message: '请输入活动地点', trigger: 'blur' }, |
| | | { max: 100, message: '长度不能超过100个字符', trigger: 'blur' } |
| | | {required: true, message: '请输入活动地点', trigger: 'blur'}, |
| | | {max: 100, message: '长度不能超过100个字符', trigger: 'blur'} |
| | | ], |
| | | activityContent: [ |
| | | { required: true, message: '请输入活动内容', trigger: 'blur' } |
| | | {required: false, message: '请输入活动内容', trigger: 'blur'} |
| | | ] |
| | | }, |
| | | |
| | |
| | | width: 100, |
| | | align: 'center', |
| | | render: (h, params) => { |
| | | return h('Tag', { |
| | | }, params.row.activityType === 'online' ? '线上' : '线下') |
| | | return h('Tag', {}, params.row.activityType === 'online' ? '线上' : '线下') |
| | | } |
| | | }, |
| | | { |
| | |
| | | } |
| | | }, |
| | | { |
| | | title: '审核状态', |
| | | key: 'auditStatus', |
| | | width: 100, |
| | | align: 'center', |
| | | render: (h, params) => { |
| | | const status = params.row.auditStatus; |
| | | let tagText, tagColor; |
| | | |
| | | // 根据状态设置文案和颜色 |
| | | switch (status) { |
| | | case 0: |
| | | tagText = '审核中'; |
| | | tagColor = 'orange'; // 橙色表示进行中 |
| | | break; |
| | | case 1: |
| | | tagText = '已通过'; |
| | | tagColor = 'green'; // 绿色表示通过 |
| | | break; |
| | | case 2: |
| | | tagText = '未通过'; |
| | | tagColor = 'red'; // 红色表示拒绝 |
| | | break; |
| | | default: |
| | | tagText = '未知状态'; |
| | | tagColor = 'default'; // 默认灰色 |
| | | } |
| | | |
| | | return h('Tag', { |
| | | props: { |
| | | color: tagColor, |
| | | }, |
| | | }, tagText); |
| | | }, |
| | | }, |
| | | { |
| | | title: '状态', |
| | | key: 'status', |
| | | width: 100, |
| | |
| | | render: (h, params) => { |
| | | const status = params.row.status; |
| | | const statusMap = { |
| | | 'noStart': { text: '未开始', color: 'default' }, |
| | | 'report': { text: '报名中', color: 'green' }, |
| | | 'inProgress':{ text:'进行中',color:'cyan'}, |
| | | 'end': { text: '已结束', color: 'red' } |
| | | 'noStart': {text: '未开始', color: 'default'}, |
| | | 'report': {text: '报名中', color: 'green'}, |
| | | 'inProgress': {text: '进行中', color: 'cyan'}, |
| | | 'end': {text: '已结束', color: 'red'} |
| | | }; |
| | | const currentStatus = statusMap[status] || { text: status, color: 'default' }; |
| | | const currentStatus = statusMap[status] || {text: status, color: 'default'}; |
| | | return h('Tag', { |
| | | props: { |
| | | color: currentStatus.color |
| | | } |
| | | }, currentStatus.text); |
| | | } |
| | | }, |
| | | { |
| | | title: '活动报名时间段', |
| | | key: 'activityReportTimeRange', |
| | | width: 300, |
| | | render: (h, params) => { |
| | | return h('div', [ |
| | | h('div', `开始: ${this.formatDate(params.row.reportStartTime)}`), |
| | | h('div', `结束: ${this.formatDate(params.row.reportEndTime)}`) |
| | | ]) |
| | | } |
| | | }, |
| | | { |
| | |
| | | render: (h, params) => { |
| | | return h('Tag', { |
| | | props: { |
| | | color: params.row.disabled ? 'red' : 'green' |
| | | color: params.row.disabled ? 'green' : 'red' //true 正常 false被禁用 |
| | | } |
| | | }, params.row.disabled ? '禁用' : '正常') |
| | | }, params.row.disabled ? '正常' : '禁用') |
| | | } |
| | | } |
| | | ], |
| | |
| | | |
| | | // 模态框控制 |
| | | modelShow: false, |
| | | modelTitle: '' |
| | | modelTitle: '', |
| | | |
| | | //编辑器配置 |
| | | // 富文本编辑器配置 |
| | | Quill:'', |
| | | defaultValue: '', |
| | | editorOption: { |
| | | placeholder: '请在这里输入', |
| | | theme: 'snow', //主题 snow/bubble |
| | | modules: { |
| | | history: { |
| | | delay: 1000, |
| | | maxStack: 50, |
| | | userOnly: false |
| | | }, |
| | | toolbar: { |
| | | container: toolbarOptions, |
| | | handlers: { |
| | | myUploadBtn: this.myMethod, |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | }, |
| | | // 在组件创建前注册 |
| | | beforeCreate() { |
| | | Quill.register(VideoBlot, true); |
| | | }, |
| | | mounted() { |
| | | //初始化 |
| | | this.Quill=this.$refs.QuillEditor.quill |
| | | this.init() |
| | | this.initTitle() |
| | | this.initButton(); |
| | | }, |
| | | methods: { |
| | | detail(row){ |
| | | this.modelTitle = '活动详情' |
| | | this.infoModelShow = true |
| | | this.activityInfo = row |
| | | myMethod(){ |
| | | this.$refs.upload.handleClick(); |
| | | }, |
| | | // 获取富文本编辑器的内容 |
| | | getReason(content) { |
| | | this.activityFrom.activityContent = content |
| | | }, |
| | | // 初始化数据 |
| | | init() { |
| | | this.getActivityList() |
| | | initButton(){ |
| | | const editorButton = document.querySelector('.ql-myUploadBtn') |
| | | editorButton.innerHTML = '<svg t="1751966766109" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1530" fill="currentColor" style="width: 1em; height: 1em; vertical-align: middle;"><path d="M1024 693.248q0 25.6-8.704 48.128t-24.576 40.448-36.864 30.208-45.568 16.384l1.024 1.024-17.408 0-4.096 0-4.096 0-675.84 0q-5.12 1.024-16.384 1.024-39.936 0-74.752-15.36t-60.928-41.472-40.96-60.928-14.848-74.752 14.848-74.752 40.96-60.928 60.928-41.472 74.752-15.36l1.024 0q-1.024-8.192-1.024-15.36l0-16.384q0-72.704 27.648-137.216t75.776-112.128 112.128-75.264 136.704-27.648 137.216 27.648 112.64 75.264 75.776 112.128 27.648 137.216q0 37.888-8.192 74.24t-22.528 69.12q5.12-1.024 10.752-1.536t10.752-0.512q27.648 0 52.736 10.752t43.52 29.696 29.184 44.032 10.752 53.76zM665.6 571.392q20.48 0 26.624-4.608t-8.192-22.016q-14.336-18.432-31.744-48.128t-36.352-60.416-38.4-57.344-37.888-38.912q-18.432-13.312-27.136-14.336t-25.088 12.288q-18.432 15.36-35.84 38.912t-35.328 50.176-35.84 52.224-36.352 45.056q-18.432 18.432-13.312 32.768t25.6 14.336l16.384 0q9.216 0 19.968 0.512t20.992 0.512l17.408 0q14.336 1.024 18.432 9.728t4.096 24.064q0 17.408-0.512 30.72t-0.512 25.6-0.512 25.6-0.512 30.72q0 7.168 1.536 15.36t5.632 15.36 12.288 11.776 21.504 4.608l23.552 0q9.216 0 27.648 1.024 24.576 0 28.16-12.288t3.584-38.912q0-23.552 0.512-42.496t0.512-51.712q0-23.552 4.608-36.352t19.968-12.8q11.264 0 32.256-0.512t32.256-0.512z" p-id="1531"></path></svg>' |
| | | }, |
| | | |
| | | // 获取活动列表 |
| | | getActivityList() { |
| | | this.loading = true |
| | | getActivityList(this.searchForm).then(res => { |
| | | this.loading = false |
| | | if (res.code === 200) { |
| | | // 为每一行添加loading状态 |
| | | this.activityList = res.data.map(item => ({ |
| | | ...item, |
| | | recommendLoading: false, |
| | | statusLoading: false |
| | | })) |
| | | this.total = res.total |
| | | } |
| | | }).catch(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | |
| | | // 搜索活动 |
| | | handleSearch(type, value) { |
| | | if (type === 'reportStart') { |
| | | this.searchForm.reportStartTime = value |
| | | } else if (type === 'reportEnd') { |
| | | this.searchForm.reportEndTime = value |
| | | } |
| | | |
| | | this.searchForm.pageNumber = 1 |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 重置搜索 |
| | | resetSearch() { |
| | | this.$refs.searchForm.resetFields() |
| | | this.searchForm.pageNumber = 1 |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 改变页码 |
| | | changePage(page) { |
| | | this.searchForm.pageNumber = page |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 改变每页条数 |
| | | changePageSize(pageSize) { |
| | | this.searchForm.pageNumber = 1 |
| | | this.searchForm.pageSize = pageSize |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 表格选择变化 |
| | | showSelect(selection) { |
| | | this.selectList = selection.map(item => item.id) |
| | | this.selectCount = selection.length |
| | | }, |
| | | |
| | | // 打开新增模态框 |
| | | openAdd() { |
| | | this.modelTitle = '新增活动' |
| | | this.modelShow = true |
| | | this.coverType = '输入文字封面' |
| | | this.file = null |
| | | this.$refs.form.resetFields() |
| | | this.activityFrom.id = '' |
| | | }, |
| | | |
| | | // 打开编辑模态框 |
| | | openEdit(row) { |
| | | this.modelTitle = '编辑活动' |
| | | this.modelShow = true |
| | | this.$nextTick(() => { |
| | | this.$refs.form.resetFields() |
| | | // 填充表单数据 |
| | | this.activityFrom = { |
| | | id: row.id, |
| | | activityName: row.activityName, |
| | | activityType: row.activityType, |
| | | reportTime: [ |
| | | this.formatDate(row.reportStartTime, 'YYYY-MM-DD HH:mm:ss'), |
| | | this.formatDate(row.reportEndTime, 'YYYY-MM-DD HH:mm:ss') |
| | | ], |
| | | time: [ |
| | | this.formatDate(row.startTime, 'YYYY-MM-DD HH:mm:ss'), |
| | | this.formatDate(row.endTime, 'YYYY-MM-DD HH:mm:ss') |
| | | ], |
| | | activityContent: row.activityContent, |
| | | cover: row.cover, |
| | | coverType: row.coverType, |
| | | status: row.status, |
| | | reportStartTime: row.reportStartTime, |
| | | reportEndTime: row.reportEndTime, |
| | | startTime: row.startTime, |
| | | endTime: row.endTime, |
| | | recommend: row.recommend, |
| | | limitUserNum: row.limitUserNum, |
| | | activityLocation: row.activityLocation |
| | | } |
| | | this.$refs.editor.setContent(this.activityFrom.activityLocation) |
| | | // 设置封面类型 |
| | | this.coverType = row.coverType === 'text' ? '输入文字封面' : '选择文件封面' |
| | | }) |
| | | }, |
| | | infoModelClose(){ |
| | | this.infoModelShow = false |
| | | }, |
| | | // 关闭模态框 |
| | | modelClose() { |
| | | this.modelShow = false |
| | | this.file = null |
| | | this.submitLoading = false |
| | | this.handleRemove(); |
| | | this.$refs.form.resetFields() |
| | | }, |
| | | |
| | | // 保存或更新活动 |
| | | saveOrUpdate() { |
| | | // 设置封面类型 |
| | | this.activityFrom.coverType = this.coverType === '输入文字封面' ? '文字' : |
| | | this.file ? this.getFileCategory(this.file.type) : |
| | | this.activityFrom.coverType |
| | | this.$refs.form.validate(valid => { |
| | | if (valid) { |
| | | this.submitLoading = true |
| | | |
| | | // 处理时间数据 |
| | | if (this.activityFrom.reportTime && this.activityFrom.reportTime.length === 2) { |
| | | this.activityFrom.reportStartTime = this.formatDate(this.activityFrom.reportTime[0], 'YYYY-MM-DD HH:mm:ss') |
| | | this.activityFrom.reportEndTime = this.formatDate(this.activityFrom.reportTime[1], 'YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | |
| | | if (this.activityFrom.time && this.activityFrom.time.length === 2) { |
| | | this.activityFrom.startTime = this.formatDate(this.activityFrom.time[0], 'YYYY-MM-DD HH:mm:ss') |
| | | this.activityFrom.endTime = this.formatDate(this.activityFrom.time[1], 'YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | |
| | | const api = this.activityFrom.id ? editActivity : addActivity |
| | | api(this.activityFrom).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose() |
| | | this.getActivityList() |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 删除活动 |
| | | delById(row) { |
| | | this.$Modal.confirm({ |
| | | title: '确认删除', |
| | | content: `确定要删除活动 "${row.activityName}" 吗?`, |
| | | onOk: () => { |
| | | delActivityById(row.id).then(res => { |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.getActivityList() |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 批量删除 |
| | | delBatch() { |
| | | if (this.selectCount === 0) { |
| | | this.$Message.warning('请至少选择一条数据') |
| | | return |
| | | } |
| | | |
| | | this.$Modal.confirm({ |
| | | title: '确认删除', |
| | | content: `确定要删除选中的 ${this.selectCount} 条数据吗?`, |
| | | onOk: () => { |
| | | delActivityBatch({ ids: this.selectList }).then(res => { |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.selectList = [] |
| | | this.selectCount = 0 |
| | | this.getActivityList() |
| | | } else { |
| | | this.$Message.error(res.msg || '删除失败') |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 改变推荐状态 |
| | | changeRecommend(row, action) { |
| | | row.recommendLoading = true |
| | | const recommend = action === '推荐' |
| | | |
| | | activityChangeRecommend({ |
| | | id: row.id, |
| | | recommend: recommend |
| | | }).then(res => { |
| | | row.recommendLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | row.recommend = recommend |
| | | } |
| | | }).catch(() => { |
| | | row.recommendLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 改变活动状态 |
| | | changeStatus(row, action) { |
| | | row.statusLoading = true |
| | | const publish = action === '发布' |
| | | |
| | | activityChangeStatus({ |
| | | id: row.id, |
| | | publish: publish |
| | | }).then(res => { |
| | | row.statusLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | row.publish = publish |
| | | } |
| | | }).catch(() => { |
| | | row.statusLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 打开报名人员模态框 |
| | | openMembersModal(row) { |
| | | this.membersModelTitle = `${row.activityName} - 报名人员` |
| | | this.membersModelShow = true |
| | | this.memberForm.id = row.id |
| | | this.memberForm.pageNumber = 1 |
| | | this.activityMembersPage() |
| | | }, |
| | | |
| | | // 获取报名人员列表 |
| | | activityMembersPage() { |
| | | this.membersLoading = true |
| | | activityMembersPage(this.memberForm).then(res => { |
| | | this.membersLoading = false |
| | | if (res.code === 200) { |
| | | this.membersList = res.data |
| | | this.memberTotal = res.total |
| | | } |
| | | }).catch(() => { |
| | | this.membersLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 改变报名人员页码 |
| | | memberChangePage(page) { |
| | | this.memberForm.pageNumber = page |
| | | this.activityMembersPage() |
| | | }, |
| | | |
| | | // 改变报名人员每页条数 |
| | | memberChangePageSize(pageSize) { |
| | | this.memberForm.pageNumber = 1 |
| | | this.memberForm.pageSize = pageSize |
| | | this.activityMembersPage() |
| | | }, |
| | | |
| | | // 关闭报名人员模态框 |
| | | membersModelClose() { |
| | | this.membersModelShow = false |
| | | }, |
| | | |
| | | // 封面类型变化处理 |
| | | handleCoverTypeChange(type) { |
| | | if (type === '选择文件封面') { |
| | | this.activityFrom.cover = '' |
| | | } else { |
| | | this.file = null |
| | | initTitle() { |
| | | document.getElementsByClassName('ql-editor')[0].dataset.placeholder = '' |
| | | for (let item of titleConfig) { |
| | | let tip = document.querySelector('.quill-editor ' + item.Choice) |
| | | if (!tip) continue |
| | | tip.setAttribute('title', item.title) |
| | | } |
| | | }, |
| | | |
| | | // 文件上传前处理 |
| | | handleBeforeUpload(file) { |
| | | const fileType = file.type |
| | | const isImage = fileType.includes('image') |
| | | const isVideo = fileType.includes('video') |
| | | // 失去焦点 |
| | | onEditorBlur(editor) { |
| | | }, |
| | | |
| | | if (!isImage && !isVideo) { |
| | | this.$Message.error('请上传图片或视频文件') |
| | | return false |
| | | } |
| | | // 获得焦点 |
| | | onEditorFocus(editor) { |
| | | |
| | | if (file.size > 20 * 1024 * 1024) { |
| | | this.$Message.error('文件大小不能超过20MB') |
| | | return false |
| | | } |
| | | }, |
| | | |
| | | this.file = file |
| | | this.uploadFile() |
| | | // 开始 |
| | | onEditorReady(editor) { |
| | | }, |
| | | handleUploadEdit(file){ |
| | | const fileType = file.type |
| | | const isImage = fileType.includes('image') |
| | | const isVideo = fileType.includes('video') |
| | | |
| | | if (!isImage && !isVideo) { |
| | | this.$Message.error('请上传图片或视频文件') |
| | | return false |
| | | }, |
| | | |
| | | // 上传文件 |
| | | uploadFile() { |
| | | if (!this.file) return |
| | | |
| | | this.submitLoading = true |
| | | const formData = new FormData() |
| | | formData.append('file', this.file) |
| | | |
| | | uploadFileByLmk(formData).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.activityFrom.cover = res.data.fileKey |
| | | this.$Message.success('上传成功') |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 删除文件 |
| | | handleRemove() { |
| | | //点击关闭窗口时确保文件已被清除 |
| | | if(this.file === null){ |
| | | return; |
| | | } |
| | | if (!this.activityFrom.cover) { |
| | | this.file = null |
| | | return |
| | | } |
| | | delByKey(this.activityFrom.cover).then(res => { |
| | | if (res.code === 200) { |
| | | this.file = null |
| | | this.activityFrom.cover = '' |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 预览图片 |
| | | previewImage(url) { |
| | | this.previewImageUrl = url |
| | | this.previewVisible = true |
| | | }, |
| | | |
| | | // 获取文件分类 |
| | | getFileCategory(mimeType) { |
| | | const typeMap = { |
| | | 'image': 'image', |
| | | 'video': 'video', |
| | | 'audio': 'audio', |
| | | 'application': 'application' |
| | | } |
| | | |
| | | const typePrefix = mimeType.split('/')[0] |
| | | return typeMap[typePrefix] || 'unknown' |
| | | }, |
| | | |
| | | // 格式化日期 |
| | | formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') { |
| | | if (!date) return ''; |
| | | |
| | | const d = new Date(date); |
| | | if (isNaN(d.getTime())) return ''; |
| | | |
| | | const padZero = (num) => String(num).padStart(2, '0'); // 更可靠的补零方法 |
| | | |
| | | const year = d.getFullYear(); |
| | | const month = padZero(d.getMonth() + 1); // 月份 0-11 → +1 |
| | | const day = padZero(d.getDate()); |
| | | const hours = padZero(d.getHours()); |
| | | const minutes = padZero(d.getMinutes()); |
| | | const seconds = padZero(d.getSeconds()); |
| | | return format |
| | | .replace('YYYY', year) |
| | | .replace('MM', month) |
| | | .replace('DD', day) |
| | | .replace('HH', hours) |
| | | .replace('mm', minutes) |
| | | .replace('ss', seconds); |
| | | }, |
| | | |
| | | // 验证报名时间 |
| | | validateReportTime(rule, value, callback) { |
| | | if (!value || value.length !== 2) { |
| | | callback(new Error('请选择完整的报名时间段')) |
| | | return |
| | | } |
| | | |
| | | const [start, end] = value |
| | | if (new Date(start) >= new Date(end)) { |
| | | callback(new Error('报名结束时间必须晚于开始时间')) |
| | | return |
| | | } |
| | | |
| | | if (this.activityFrom.time && this.activityFrom.time.length === 2) { |
| | | const activityStart = this.activityFrom.time[0] |
| | | if (new Date(end) > new Date(activityStart)) { |
| | | callback(new Error('报名结束时间不能晚于活动开始时间')) |
| | | return |
| | | } |
| | | } |
| | | |
| | | callback() |
| | | }, |
| | | |
| | | // 验证活动时间 |
| | | validateActivityTime(rule, value, callback) { |
| | | if (!value || value.length !== 2) { |
| | | callback(new Error('请选择完整的活动时间段')) |
| | | return |
| | | } |
| | | |
| | | const [start, end] = value |
| | | if (new Date(start) >= new Date(end)) { |
| | | callback(new Error('活动结束时间必须晚于开始时间')) |
| | | return |
| | | } |
| | | |
| | | if (this.activityFrom.reportTime && this.activityFrom.reportTime.length === 2) { |
| | | const reportEnd = this.activityFrom.reportTime[1] |
| | | if (new Date(reportEnd) > new Date(start)) { |
| | | callback(new Error('活动开始时间必须晚于报名结束时间')) |
| | | return |
| | | } |
| | | } |
| | | |
| | | callback() |
| | | } |
| | | } |
| | | |
| | | if (file.size > 20 * 1024 * 1024) { |
| | | this.$Message.error('文件大小不能超过20MB') |
| | | return false |
| | | } |
| | | |
| | | this.file = file |
| | | this.uploadFile2() |
| | | return false |
| | | }, |
| | | // 上传文件 |
| | | uploadFile2() { |
| | | if (!this.file) return |
| | | |
| | | this.submitLoading = true |
| | | const formData = new FormData() |
| | | formData.append('file', this.file) |
| | | uploadFileByLmk(formData).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | let url = res.data.url; |
| | | let fileKey = res.data.fileKey; |
| | | let fileType = this.getFileType(this.file); |
| | | |
| | | const range = this.Quill.getSelection(); |
| | | const index = range ? range.index : this.Quill.getLength(); |
| | | |
| | | |
| | | if (fileType === 'video') { |
| | | this.Quill.insertEmbed(index, 'video', { |
| | | url:url, |
| | | controls:'controls', |
| | | width:'100%', |
| | | height:'auto' |
| | | }); |
| | | } else if (fileType === 'image') { |
| | | this.Quill.insertEmbed(index, "image", url); |
| | | } else { |
| | | // 如果不是图片或视频,可以处理其他类型或给出提示 |
| | | this.$Message.warning('不支持的文件类型'); |
| | | return; |
| | | } |
| | | console.log(this.activityFrom.activityContent) |
| | | this.Quill.setSelection(index + 1); |
| | | this.$Message.success('上传成功') |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | }, |
| | | getFileType(file) { |
| | | // 获取文件类型或扩展名 |
| | | let type, extension; |
| | | |
| | | if (file instanceof File) { |
| | | // 如果是File对象 |
| | | type = file.type; |
| | | const name = file.name.toLowerCase(); |
| | | extension = name.substring(name.lastIndexOf('.') + 1); |
| | | } else if (typeof file === 'string') { |
| | | // 如果是字符串(文件名或URL) |
| | | const name = file.toLowerCase(); |
| | | extension = name.substring(name.lastIndexOf('.') + 1); |
| | | |
| | | // 尝试从URL中提取MIME类型(如果有) |
| | | const mimeMatch = file.match(/^data:(.+?);/); |
| | | if (mimeMatch) { |
| | | type = mimeMatch[1]; |
| | | } |
| | | } else { |
| | | return 'unknown'; |
| | | } |
| | | |
| | | // 常见图片和视频的MIME类型 |
| | | const imageTypes = [ |
| | | 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/bmp', 'image/svg+xml' |
| | | ]; |
| | | |
| | | const videoTypes = [ |
| | | 'video/mp4', 'video/webm', 'video/ogg', 'video/quicktime', 'video/x-msvideo', 'video/x-matroska' |
| | | ]; |
| | | |
| | | // 检查MIME类型 |
| | | if (type) { |
| | | if (imageTypes.includes(type)) return 'image'; |
| | | if (videoTypes.includes(type)) return 'video'; |
| | | } |
| | | |
| | | // 常见图片和视频的扩展名 |
| | | const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg']; |
| | | const videoExtensions = ['mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv']; |
| | | |
| | | // 检查文件扩展名 |
| | | if (extension) { |
| | | if (imageExtensions.includes(extension)) return 'image'; |
| | | if (videoExtensions.includes(extension)) return 'video'; |
| | | } |
| | | |
| | | return 'unknown'; |
| | | }, |
| | | |
| | | handleAuditSubmit(activityId) { |
| | | console.log(this.auditForm) |
| | | this.$refs.auditForm.validate(valid => { |
| | | if (valid) { |
| | | const form = { |
| | | activityId: activityId, |
| | | audit: this.auditForm.audit, |
| | | remarks: this.auditForm.remarks, |
| | | } |
| | | // 提交时 auditForm.audit 已经是数字类型(0 或 1) |
| | | auditActivity(form).then(res => { |
| | | if (res.code === 200) { |
| | | // 为每一行添加loading状态 |
| | | this.$Message.success(res.msg); |
| | | this.getActivityList(); |
| | | this.closeAuditModel(); |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | |
| | | |
| | | }, |
| | | openAuditModal(row) { |
| | | this.modelTitle = '活动审核' |
| | | this.auditModelShow = true |
| | | this.activityInfo = row |
| | | }, |
| | | closeAuditModel() { |
| | | this.$refs.auditForm.resetFields(); |
| | | this.auditModelShow = false |
| | | }, |
| | | escapeStringHTML(str) { |
| | | if (!str) return str; |
| | | str = str.replace(/</g, '<'); |
| | | str = str.replace(/>/g, '>'); |
| | | return str; |
| | | }, |
| | | // 提交 |
| | | detail(row) { |
| | | this.modelTitle = '活动详情' |
| | | this.infoModelShow = true |
| | | this.activityInfo = row |
| | | this.activityInfo.activityContent = this.escapeStringHTML(this.activityInfo.activityContent); |
| | | this.$nextTick(() => { |
| | | this.processVideos(); |
| | | }); |
| | | |
| | | }, |
| | | processVideos() { |
| | | const videos = this.$el.querySelectorAll('video'); |
| | | videos.forEach(video => { |
| | | // 确保视频元素有必要的属性 |
| | | video.setAttribute('controls', ''); |
| | | video.setAttribute('playsinline', ''); // 针对移动端 |
| | | video.load(); |
| | | }); |
| | | }, |
| | | // 获取富文本编辑器的内容 |
| | | // 初始化数据 |
| | | init() { |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 获取活动列表 |
| | | getActivityList() { |
| | | this.loading = true |
| | | getActivityList(this.searchForm).then(res => { |
| | | this.loading = false |
| | | if (res.code === 200) { |
| | | // 为每一行添加loading状态 |
| | | this.activityList = res.data.map(item => ({ |
| | | ...item, |
| | | recommendLoading: false, |
| | | statusLoading: false |
| | | })) |
| | | this.total = res.total |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }).catch(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | |
| | | // 搜索活动 |
| | | handleSearch(type, value) { |
| | | if (type === 'reportStart') { |
| | | this.searchForm.reportStartTime = value |
| | | } else if (type === 'reportEnd') { |
| | | this.searchForm.reportEndTime = value |
| | | } |
| | | |
| | | this.searchForm.pageNumber = 1 |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 重置搜索 |
| | | resetSearch() { |
| | | this.$refs.searchForm.resetFields() |
| | | this.searchForm.pageNumber = 1 |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 改变页码 |
| | | changePage(page) { |
| | | this.searchForm.pageNumber = page |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 改变每页条数 |
| | | changePageSize(pageSize) { |
| | | this.searchForm.pageNumber = 1 |
| | | this.searchForm.pageSize = pageSize |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | // 表格选择变化 |
| | | showSelect(selection) { |
| | | this.selectList = selection.map(item => item.id) |
| | | this.selectCount = selection.length |
| | | }, |
| | | |
| | | // 打开新增模态框 |
| | | openAdd() { |
| | | this.modelTitle = '新增活动' |
| | | this.modelShow = true |
| | | this.coverType = '输入文字封面' |
| | | this.file = null |
| | | this.$refs.form.resetFields() |
| | | this.activityFrom.id = '' |
| | | }, |
| | | |
| | | // 打开编辑模态框 |
| | | openEdit(row) { |
| | | this.modelTitle = '编辑活动' |
| | | this.modelShow = true |
| | | this.$nextTick(() => { |
| | | this.$refs.form.resetFields() |
| | | console.log(row) |
| | | // 填充表单数据 |
| | | this.activityFrom = { |
| | | id: row.id, |
| | | activityName: row.activityName, |
| | | activityType: row.activityType, |
| | | reportTime: [ |
| | | this.formatDate(row.reportStartTime, 'YYYY-MM-DD HH:mm:ss'), |
| | | this.formatDate(row.reportEndTime, 'YYYY-MM-DD HH:mm:ss') |
| | | ], |
| | | time: [ |
| | | this.formatDate(row.startTime, 'YYYY-MM-DD HH:mm:ss'), |
| | | this.formatDate(row.endTime, 'YYYY-MM-DD HH:mm:ss') |
| | | ], |
| | | activityContent: row.activityContent, |
| | | cover: row.cover, |
| | | coverType: row.coverType, |
| | | status: row.status, |
| | | reportStartTime: row.reportStartTime, |
| | | reportEndTime: row.reportEndTime, |
| | | startTime: row.startTime, |
| | | endTime: row.endTime, |
| | | recommend: row.recommend, |
| | | limitUserNum: row.limitUserNum, |
| | | activityLocation: row.activityLocation |
| | | } |
| | | // 设置封面类型 |
| | | this.coverType = row.coverType === 'text' ? '输入文字封面' : '选择文件封面' |
| | | }) |
| | | }, |
| | | |
| | | infoModelClose() { |
| | | this.infoModelShow = false |
| | | }, |
| | | // 关闭模态框 |
| | | modelClose() { |
| | | this.modelShow = false |
| | | this.file = null |
| | | this.submitLoading = false |
| | | this.handleRemove(); |
| | | this.$refs.form.resetFields() |
| | | }, |
| | | |
| | | // 保存或更新活动 |
| | | saveOrUpdate() { |
| | | // 设置封面类型 |
| | | this.activityFrom.coverType = this.coverType === '输入文字封面' ? 'text' : |
| | | this.file ? this.getFileCategory(this.file.type) : |
| | | this.activityFrom.coverType |
| | | |
| | | this.$refs.form.validate(valid => { |
| | | if (valid) { |
| | | this.submitLoading = true |
| | | |
| | | // 处理时间数据 |
| | | if (this.activityFrom.reportTime && this.activityFrom.reportTime.length === 2) { |
| | | this.activityFrom.reportStartTime = this.formatDate(this.activityFrom.reportTime[0], 'YYYY-MM-DD HH:mm:ss') |
| | | this.activityFrom.reportEndTime = this.formatDate(this.activityFrom.reportTime[1], 'YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | |
| | | if (this.activityFrom.time && this.activityFrom.time.length === 2) { |
| | | this.activityFrom.startTime = this.formatDate(this.activityFrom.time[0], 'YYYY-MM-DD HH:mm:ss') |
| | | this.activityFrom.endTime = this.formatDate(this.activityFrom.time[1], 'YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | |
| | | const api = this.activityFrom.id ? editActivity : addActivity |
| | | api(this.activityFrom).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose() |
| | | this.getActivityList() |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 删除活动 |
| | | delById(row) { |
| | | this.$Modal.confirm({ |
| | | title: '确认删除', |
| | | content: `确定要删除活动 "${row.activityName}" 吗?`, |
| | | onOk: () => { |
| | | //TODO 先判断活动是否发布,发布则需要先下架 |
| | | |
| | | delActivityById(row.id).then(res => { |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.getActivityList() |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 批量删除 |
| | | delBatch() { |
| | | //TODO 先判断活动是否发布,发布则需要先下架 |
| | | if (this.selectCount === 0) { |
| | | this.$Message.warning('请至少选择一条数据') |
| | | return |
| | | } |
| | | |
| | | this.$Modal.confirm({ |
| | | title: '确认删除', |
| | | content: `确定要删除选中的 ${this.selectCount} 条数据吗?`, |
| | | onOk: () => { |
| | | delActivityBatch(this.selectList).then(res => { |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.selectList = [] |
| | | this.selectCount = 0 |
| | | this.getActivityList() |
| | | } else { |
| | | this.$Message.error(res.msg || '删除失败') |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 改变推荐状态 |
| | | changeRecommend(row, action) { |
| | | row.recommendLoading = true |
| | | const recommend = action === '推荐' |
| | | |
| | | activityChangeRecommend({ |
| | | id: row.id, |
| | | recommend: recommend |
| | | }).then(res => { |
| | | row.recommendLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | row.recommend = recommend |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }).catch(() => { |
| | | row.recommendLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 改变活动状态 |
| | | changeStatus(row, action) { |
| | | //判断是否存在审核记录 |
| | | if (row.audit === null) { |
| | | this.$Message.error("发布前请先审核!") |
| | | return |
| | | } |
| | | |
| | | row.statusLoading = true |
| | | const publish = action === '发布' |
| | | |
| | | activityChangeStatus({ |
| | | id: row.id, |
| | | publish: publish |
| | | }).then(res => { |
| | | row.statusLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | row.publish = publish |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }).catch(() => { |
| | | row.statusLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 打开报名人员模态框 |
| | | openMembersModal(row) { |
| | | this.membersModelTitle = `${row.activityName} - 报名人员` |
| | | this.membersModelShow = true |
| | | this.memberForm.id = row.id |
| | | this.memberForm.pageNumber = 1 |
| | | this.activityMembersPage() |
| | | }, |
| | | |
| | | // 获取报名人员列表 |
| | | activityMembersPage() { |
| | | this.membersLoading = true |
| | | activityMembersPage(this.memberForm).then(res => { |
| | | this.membersLoading = false |
| | | if (res.code === 200) { |
| | | this.membersList = res.data |
| | | this.memberTotal = res.total |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }).catch(() => { |
| | | this.membersLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 改变报名人员页码 |
| | | memberChangePage(page) { |
| | | this.memberForm.pageNumber = page |
| | | this.activityMembersPage() |
| | | }, |
| | | |
| | | // 改变报名人员每页条数 |
| | | memberChangePageSize(pageSize) { |
| | | this.memberForm.pageNumber = 1 |
| | | this.memberForm.pageSize = pageSize |
| | | this.activityMembersPage() |
| | | }, |
| | | |
| | | // 关闭报名人员模态框 |
| | | membersModelClose() { |
| | | this.membersModelShow = false |
| | | }, |
| | | |
| | | // 封面类型变化处理 |
| | | handleCoverTypeChange(type) { |
| | | if (type === '选择文件封面') { |
| | | this.activityFrom.cover = '' |
| | | } else { |
| | | this.file = null |
| | | } |
| | | }, |
| | | // 文件上传前处理 |
| | | handleBeforeUpload(file) { |
| | | const fileType = file.type |
| | | const isImage = fileType.includes('image') |
| | | const isVideo = fileType.includes('video') |
| | | |
| | | if (!isImage && !isVideo) { |
| | | this.$Message.error('请上传图片或视频文件') |
| | | return false |
| | | } |
| | | |
| | | if (file.size > 20 * 1024 * 1024) { |
| | | this.$Message.error('文件大小不能超过20MB') |
| | | return false |
| | | } |
| | | |
| | | this.file = file |
| | | this.uploadFile() |
| | | return false |
| | | }, |
| | | // 上传文件 |
| | | uploadFile() { |
| | | if (!this.file) return |
| | | |
| | | this.submitLoading = true |
| | | const formData = new FormData() |
| | | formData.append('file', this.file) |
| | | |
| | | uploadFileByLmk(formData).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.activityFrom.cover = res.data.fileKey |
| | | this.$Message.success('上传成功') |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 删除文件 |
| | | handleRemove() { |
| | | //点击关闭窗口时确保文件已被清除 |
| | | if (this.file === null) { |
| | | return; |
| | | } |
| | | if (!this.activityFrom.cover) { |
| | | this.file = null |
| | | return |
| | | } |
| | | delByKey(this.activityFrom.cover).then(res => { |
| | | if (res.code === 200) { |
| | | this.file = null |
| | | this.activityFrom.cover = '' |
| | | }else{ |
| | | this.$Message.error(res.msg) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 预览图片 |
| | | previewImage(url) { |
| | | this.previewImageUrl = url |
| | | this.previewVisible = true |
| | | }, |
| | | |
| | | // 获取文件分类 |
| | | getFileCategory(mimeType) { |
| | | const typeMap = { |
| | | 'image': 'image', |
| | | 'video': 'video', |
| | | 'audio': 'audio', |
| | | 'application': 'application' |
| | | } |
| | | |
| | | const typePrefix = mimeType.split('/')[0] |
| | | return typeMap[typePrefix] || 'unknown' |
| | | }, |
| | | |
| | | // 格式化日期 |
| | | formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') { |
| | | if (!date) return ''; |
| | | |
| | | const d = new Date(date); |
| | | if (isNaN(d.getTime())) return ''; |
| | | |
| | | const padZero = (num) => String(num).padStart(2, '0'); // 更可靠的补零方法 |
| | | |
| | | const year = d.getFullYear(); |
| | | const month = padZero(d.getMonth() + 1); // 月份 0-11 → +1 |
| | | const day = padZero(d.getDate()); |
| | | const hours = padZero(d.getHours()); |
| | | const minutes = padZero(d.getMinutes()); |
| | | const seconds = padZero(d.getSeconds()); |
| | | return format |
| | | .replace('YYYY', year) |
| | | .replace('MM', month) |
| | | .replace('DD', day) |
| | | .replace('HH', hours) |
| | | .replace('mm', minutes) |
| | | .replace('ss', seconds); |
| | | }, |
| | | |
| | | // 验证报名时间 |
| | | validateReportTime(rule, value, callback) { |
| | | if (!value || value.length !== 2) { |
| | | callback(new Error('请选择完整的报名时间段')) |
| | | return |
| | | } |
| | | |
| | | const [start, end] = value |
| | | if (new Date(start) >= new Date(end)) { |
| | | callback(new Error('报名结束时间必须晚于开始时间')) |
| | | return |
| | | } |
| | | |
| | | if (this.activityFrom.time && this.activityFrom.time.length === 2) { |
| | | const activityStart = this.activityFrom.time[0] |
| | | if (new Date(end) > new Date(activityStart)) { |
| | | callback(new Error('报名结束时间不能晚于活动开始时间')) |
| | | return |
| | | } |
| | | } |
| | | |
| | | callback() |
| | | }, |
| | | |
| | | // 验证活动时间 |
| | | validateActivityTime(rule, value, callback) { |
| | | if (!value || value.length !== 2) { |
| | | callback(new Error('请选择完整的活动时间段')) |
| | | return |
| | | } |
| | | |
| | | const [start, end] = value |
| | | if (new Date(start) >= new Date(end)) { |
| | | callback(new Error('活动结束时间必须晚于开始时间')) |
| | | return |
| | | } |
| | | |
| | | if (this.activityFrom.reportTime && this.activityFrom.reportTime.length === 2) { |
| | | const reportEnd = this.activityFrom.reportTime[1] |
| | | if (new Date(reportEnd) > new Date(start)) { |
| | | callback(new Error('活动开始时间必须晚于报名结束时间')) |
| | | return |
| | | } |
| | | } |
| | | |
| | | callback() |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .quill-editor { |
| | | |
| | | } |
| | | |
| | | .ql-editor .ql-video { |
| | | width: 50%; |
| | | height: auto; /* 根据你的需求调整高度 */ |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .activity-management { |
| | | .search-form { |
| | | padding: 16px; |
| | |
| | | min-height: 100px; |
| | | margin-top: 8px; |
| | | } |
| | | /* |
| | | 文字大小 |
| | | */ |
| | | .ql-snow .ql-picker.ql-size{ |
| | | width: 70px; // 菜单栏占比宽度 |
| | | } |
| | | /* |
| | | 字体 |
| | | */ |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before { |
| | | content: "黑体"; |
| | | font-family: "SimHei"; |
| | | } |
| | | |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before { |
| | | content: "微软雅黑"; |
| | | font-family: "Microsoft YaHei"; |
| | | } |
| | | |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before { |
| | | content: "楷体"; |
| | | font-family: "KaiTi"; |
| | | } |
| | | |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before { |
| | | content: "仿宋"; |
| | | font-family: "FangSong"; |
| | | } |
| | | |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before { |
| | | content: "Arial"; |
| | | font-family: "Arial"; |
| | | } |
| | | |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before { |
| | | content: "Times New Roman"; |
| | | font-family: "Times New Roman"; |
| | | } |
| | | |
| | | .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before, |
| | | .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before { |
| | | content: "sans-serif"; |
| | | font-family: "sans-serif"; |
| | | } |
| | | |
| | | .ql-font-SimSun { |
| | | font-family: "SimSun"; |
| | | } |
| | | |
| | | .ql-font-SimHei { |
| | | font-family: "SimHei"; |
| | | } |
| | | |
| | | .ql-font-Microsoft-YaHei { |
| | | font-family: "Microsoft YaHei"; |
| | | } |
| | | |
| | | .ql-font-KaiTi { |
| | | font-family: "KaiTi"; |
| | | } |
| | | |
| | | .ql-font-FangSong { |
| | | font-family: "FangSong"; |
| | | } |
| | | |
| | | .ql-font-Arial { |
| | | font-family: "Arial"; |
| | | } |
| | | |
| | | .ql-font-Times-New-Roman { |
| | | font-family: "Times New Roman"; |
| | | } |
| | | |
| | | .ql-font-sans-serif { |
| | | font-family: "sans-serif"; |
| | | } |
| | | </style> |