| | |
| | | <template> |
| | | <div> |
| | | <card> |
| | | <div class="activity-management"> |
| | | <Card> |
| | | <!-- 搜索表单 --> |
| | | <Form |
| | | ref="searchForm" |
| | | @keydown.enter.native="handleSearch" |
| | | :model="searchForm" |
| | | inline |
| | | :label-width="70" |
| | | :label-width="80" |
| | | class="search-form" |
| | | > |
| | | <Form-item label="活动名" prop="activityName"> |
| | | <FormItem label="活动名称" prop="activityName"> |
| | | <Input |
| | | type="text" |
| | | v-model="searchForm.activityName" |
| | | placeholder="请输入活动名称" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | style="width: 180px" |
| | | /> |
| | | </Form-item> |
| | | <Form-item label="活动类型" prop="activityType"> |
| | | </FormItem> |
| | | <FormItem label="活动类型" prop="activityType"> |
| | | <Select |
| | | v-model="searchForm.activityType" |
| | | style="width:260px" |
| | | class="custom-select" |
| | | placeholder="请选择活动类型" |
| | | style="width: 180px" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | |
| | | :value="item.value" |
| | | :key="item.id" |
| | | > |
| | | {{ item.value }} |
| | | {{ item.label }} |
| | | </Option> |
| | | </Select> |
| | | </Form-item> |
| | | <Form-item label="活动报名开始时间" prop="reportStartTime"> |
| | | <DatePicker :value="searchForm.reportStartTime" |
| | | type="datetime" placeholder="选择日期" |
| | | @on-change="handleSearch('reportStart',$event)" |
| | | @on-clear="handleSearch" |
| | | ></DatePicker> |
| | | </Form-item> |
| | | <Form-item label="活动报名结束时间" prop="reportEndTime"> |
| | | <DatePicker :value="searchForm.reportEndTime" |
| | | type="datetime" placeholder="选择日期" |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch('reportEnd',$event)"></DatePicker> |
| | | </Form-item> |
| | | <!-- <Form-item label="状态" prop="status">--> |
| | | <!-- <Input--> |
| | | <!-- type="text"--> |
| | | <!-- v-model="searchForm.status"--> |
| | | <!-- clearable--> |
| | | <!-- @on-clear="handleSearch"--> |
| | | <!-- @on-change="handleSearch"--> |
| | | <!-- style="width: 160px"--> |
| | | <!-- />--> |
| | | <!-- </Form-item>--> |
| | | </FormItem> |
| | | <FormItem label="报名开始时间" prop="reportStartTime"> |
| | | <DatePicker |
| | | :value="searchForm.reportStartTime" |
| | | type="datetime" |
| | | placeholder="选择开始时间" |
| | | style="width: 180px" |
| | | @on-change="handleSearch('reportStart', $event)" |
| | | @on-clear="handleSearch" |
| | | ></DatePicker> |
| | | </FormItem> |
| | | <FormItem label="报名结束时间" prop="reportEndTime"> |
| | | <DatePicker |
| | | :value="searchForm.reportEndTime" |
| | | type="datetime" |
| | | placeholder="选择结束时间" |
| | | style="width: 180px" |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch('reportEnd', $event)" |
| | | ></DatePicker> |
| | | </FormItem> |
| | | <Button |
| | | @click="handleSearch" |
| | | type="primary" |
| | | icon="ios-search" |
| | | class="search-btn" |
| | | >搜索</Button |
| | | > |
| | | >搜索</Button> |
| | | <Button |
| | | @click="resetSearch" |
| | | icon="md-refresh" |
| | | style="margin-left: 8px" |
| | | >重置</Button> |
| | | </Form> |
| | | <Row class="operation padding-row"> |
| | | <Button @click="openAdd" type="info">添加</Button> |
| | | <Button @click="delBatch" type="error">批量删除</Button> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <Row class="operation"> |
| | | <Button @click="openAdd" type="primary" icon="md-add">新增活动</Button> |
| | | <Button @click="delBatch" type="error" icon="md-trash" :disabled="selectCount === 0">批量删除</Button> |
| | | </Row> |
| | | |
| | | <!-- 活动表格 --> |
| | | <Table |
| | | :loading="loading" |
| | | border |
| | | :columns="columns" |
| | | :data="activityList" |
| | | ref="table" |
| | | sortable="custom" |
| | | @on-sort-change="changeSort" |
| | | @on-selection-change="showSelect" |
| | | class="activity-table" |
| | | > |
| | | <template slot-scope="{ row }" slot="url"> |
| | | <!-- 封面展示插槽 --> |
| | | <template slot-scope="{ row }" slot="url"> |
| | | <div class="media-container"> |
| | | <!-- 图片类型 --> |
| | | <template v-if="row.coverType === '图片'"> |
| | | <img width="300" height="300" |
| | | :src="row.url" |
| | | alt="封面" |
| | | class="thumbnail" |
| | | @click="previewImage(row.url)" |
| | | @error="handleImageError" |
| | | > |
| | | <template v-if="row.coverType === 'image'"> |
| | | <img |
| | | :src="row.url" |
| | | alt="活动封面" |
| | | class="thumbnail" |
| | | @click="previewImage(row.url)" |
| | | > |
| | | </template> |
| | | <!-- 视频类型 --> |
| | | <template v-else-if="row.coverType === '视频'"> |
| | | <video width="300" |
| | | height="300" |
| | | :src="row.url" |
| | | class="video-player" |
| | | controls |
| | | @error="handleVideoError" |
| | | ></video> |
| | | <template v-else-if="row.coverType === 'video'"> |
| | | <video |
| | | :src="row.url" |
| | | class="video-player" |
| | | controls |
| | | ></video> |
| | | </template> |
| | | <!-- 文字类型 --> |
| | | <template v-else-if="row.coverType === text"> |
| | | {{ row.cover || '暂无文字内容' }} |
| | | <template v-else> |
| | | <div class="text-cover">{{ row.cover || '暂无封面内容' }}</div> |
| | | </template> |
| | | </div> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="action"> |
| | | <Button type="info" size="small" style="margin-right: 5px" @click="changeRecommend(row,row.recommend === true ? '取消推荐' : '推荐')"> |
| | | {{ row.recommend === true ? '取消推荐' : '推荐' }} |
| | | </Button> |
| | | <Button type="info" size="small" style="margin-right: 5px" @click="changeStatus(row,row.status === '已发布' ? '下架' : '发布')"> |
| | | {{ row.status === '已发布' ? '下架' : '发布' }} |
| | | </Button> |
| | | <Button type="info" size="small" style="margin-right: 5px" @click="openEdit(row)">编辑标签</Button> |
| | | <Button type="error" size="small" style="margin-right: 5px" @click="delById(row)">删除</Button> |
| | | <Button type="info" size="small" style="margin-right: 5px" @click="openMembersModal(row)"> |
| | | 报名人员列表 |
| | | </Button> |
| | | |
| | | <!-- 操作按钮插槽 --> |
| | | <template slot-scope="{ row }" slot="action"> |
| | | <div class="action-btns"> |
| | | <Button |
| | | type="primary" |
| | | size="small" |
| | | @click="changeRecommend(row, row.recommend ? '取消推荐' : '推荐')" |
| | | :loading="row.recommendLoading" |
| | | > |
| | | {{ row.recommend ? '取消推荐' : '推荐' }} |
| | | </Button> |
| | | <Button |
| | | type="primary" |
| | | size="small" |
| | | @click="changeStatus(row, row.publish ? '下架' : '发布')" |
| | | :loading="row.statusLoading" |
| | | > |
| | | {{ row.publish ? '下架' : '发布' }} |
| | | </Button> |
| | | <Button |
| | | type="info" |
| | | size="small" |
| | | @click="detail(row)" |
| | | >详情</Button> |
| | | <Button |
| | | type="info" |
| | | size="small" |
| | | @click="openEdit(row)" |
| | | >编辑</Button> |
| | | <Button |
| | | type="error" |
| | | size="small" |
| | | @click="delById(row)" |
| | | >删除</Button> |
| | | <Button |
| | | type="success" |
| | | size="small" |
| | | @click="openMembersModal(row)" |
| | | >报名人员</Button> |
| | | </div> |
| | | </template> |
| | | </Table> |
| | | <Row type="flex" justify="end" class="mt_10"> |
| | | |
| | | <!-- 分页 --> |
| | | <Row type="flex" justify="end" class="page-footer"> |
| | | <Page |
| | | :current="searchForm.pageNumber" |
| | | :total="total" |
| | |
| | | ></Page> |
| | | </Row> |
| | | |
| | | |
| | | <!-- 活动编辑/新增模态框 --> |
| | | <Modal |
| | | v-model="modelShow" |
| | | :title="modelTitle" |
| | | @close="modelClose()" |
| | | @on-cancel="modelClose" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <Form ref="form" :model="activityFrom" :label-width="70" :rules="rules" > |
| | | <Form ref="form" :model="activityFrom" :label-width="100" :rules="rules"> |
| | | <Row :gutter="16"> |
| | | <Col span="12"> |
| | | <FormItem label="活动名称" prop="activityName"> |
| | | <Input |
| | | type="text" |
| | | v-model="activityFrom.activityName" |
| | | placeholder="请输入活动名称" |
| | | clearable |
| | | style="width: 300px" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="活动类型" prop="activityType" > |
| | | <FormItem label="活动类型" prop="activityType" :label-width="100"> |
| | | <Select |
| | | v-model="activityFrom.activityType" |
| | | class="custom-select" |
| | | placeholder="请选择活动类型" |
| | | clearable |
| | | style="width: 100px;" |
| | | > |
| | | <Option |
| | | v-for="item in typeSelect" |
| | | :value="item.value" |
| | | :key="item.id" |
| | | > |
| | | {{ item.value }} |
| | | {{ item.label }} |
| | | </Option> |
| | | </Select> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="报名时间段" prop="reportTime"> |
| | | <DatePicker v-model="activityFrom.reportTime" style="width: 300px" |
| | | :value="activityFrom.reportTime" |
| | | @on-change="activityFrom.reportTime =$event" |
| | | format="yyyy-MM-dd HH:mm:ss" |
| | | type="datetimerange" placeholder="请选择"></DatePicker> |
| | | <DatePicker |
| | | v-model="activityFrom.reportTime" |
| | | type="datetimerange" |
| | | format="yyyy-MM-dd HH:mm" |
| | | placeholder="请选择报名时间段" |
| | | style="width: 100%" |
| | | ></DatePicker> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="活动时间段" prop="time"> |
| | | <DatePicker v-model="activityFrom.time" style="width: 300px" |
| | | :value="activityFrom.time" |
| | | @on-change="activityFrom.time =$event" |
| | | format= "yyyy-MM-dd HH:mm:ss" |
| | | type="datetimerange" placeholder="请选择"></DatePicker> |
| | | <DatePicker |
| | | v-model="activityFrom.time" |
| | | type="datetimerange" |
| | | format="yyyy-MM-dd HH:mm" |
| | | placeholder="请选择活动时间段" |
| | | style="width: 100%" |
| | | ></DatePicker> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24"> |
| | | <FormItem label="封面" prop="cover"> |
| | | <Col span="12"> |
| | | <FormItem label="封面类型" prop="coverType" :labelWidth="100"> |
| | | <Select |
| | | v-model="coverType" |
| | | class="custom-select" |
| | | clearable |
| | | style="width: 150px;" |
| | | placeholder="请选择封面类型" |
| | | @on-change="handleCoverTypeChange" |
| | | > |
| | | <Option |
| | | v-for="item in coverTypeOptions" |
| | |
| | | {{ item.value }} |
| | | </Option> |
| | | </Select> |
| | | <template> |
| | | <div v-if="coverTypeJudgment('text')"> |
| | | <template> |
| | | <Input |
| | | type="text" |
| | | v-model="activityFrom.cover" |
| | | clearable |
| | | style="width: 300px" |
| | | placeholder="输入文本或选择文件" |
| | | /> |
| | | </template> |
| | | </div> |
| | | <div v-if="coverTypeJudgment('file')"> |
| | | <Upload |
| | | :before-upload="handleBeforeUpload" |
| | | action=""> |
| | | <Button icon="ios-cloud-upload-outline">上传</Button> |
| | | </Upload> |
| | | <div v-if="file !== null"> |
| | | Upload file: {{ file.name }} |
| | | <Button type="text" @click="handleRemove" :loading="loadingStatus"> |
| | | {{ loadingStatus ? '上传中' : '删除' }} |
| | | </Button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </FormItem> |
| | | </Col> |
| | | |
| | | |
| | | |
| | | <Col span="24"> |
| | | <FormItem label="活动内容" prop="activityContent"> |
| | | <Input v-model="activityFrom.activityContent" type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="输入" /> |
| | | </FormItem> |
| | | </Col> |
| | | </ROW> |
| | | <Col span="24" v-if="coverType === '输入文字封面'"> |
| | | <FormItem label="封面文字" prop="cover"> |
| | | <Input |
| | | v-model="activityFrom.cover" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请输入封面文字" |
| | | style="width: 50%" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24" v-if="coverType === '选择文件封面'"> |
| | | <FormItem label="上传封面" prop="cover"> |
| | | <Upload |
| | | :before-upload="handleBeforeUpload" |
| | | :format="['jpg','jpeg','png','gif','mp4','mov']" |
| | | :max-size="20480" |
| | | action="" |
| | | accept="image/*,video/*" |
| | | > |
| | | <Button icon="ios-cloud-upload-outline">上传封面文件</Button> |
| | | <div class="upload-tip">支持图片或视频文件,最大20MB</div> |
| | | </Upload> |
| | | <div v-if="file" class="upload-file-info"> |
| | | 已选文件: {{ file.name }} |
| | | <Button type="text" @click="handleRemove">删除</Button> |
| | | </div> |
| | | </FormItem> |
| | | </Col> |
| | | <!-- 这两个表单项在同一Row内,会显示在同一行 --> |
| | | <Col span="12"> |
| | | <FormItem label="人数限制" prop="limitUserNum"> |
| | | <InputNumber |
| | | v-model="activityFrom.limitUserNum" |
| | | :min="1" |
| | | placeholder="请输入最大人数" |
| | | style="width: 100%" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="活动地点" prop="activityLocation"> |
| | | <Input |
| | | v-model="activityFrom.activityLocation" |
| | | placeholder="请输入活动地点" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24"> |
| | | <FormItem label="活动内容:" prop="activityContent"> |
| | | <editor ref="editor" @input="getReason" /> |
| | | </FormItem> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | |
| | | <div slot="footer"> |
| | | <Button type="text" @click="modelClose">取消</Button> |
| | | <Button @click="modelClose">取消</Button> |
| | | <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">提交</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | |
| | | <!-- 报名人员模态框 --> |
| | | <Modal |
| | | v-model="membersModelShow" |
| | | :title="membersModelTitle" |
| | | @close="membersModelClose()" |
| | | width="1000"> |
| | | @on-cancel="membersModelClose" |
| | | width="1000" |
| | | class="members-modal" |
| | | > |
| | | <Table |
| | | :loading="membersLoading" |
| | | border |
| | | :columns="membersColumns" |
| | | :data="membersList" |
| | | ref="table" |
| | | > |
| | | </Table> |
| | | <Row type="flex" justify="end" class="mt_10"> |
| | | class="members-table" |
| | | ></Table> |
| | | <Row type="flex" justify="end" class="page-footer"> |
| | | <Page |
| | | :current="memberForm.pageNumber" |
| | | :total="memberTotal" |
| | |
| | | </Row> |
| | | </Modal> |
| | | |
| | | <Modal |
| | | v-model="infoModelShow" |
| | | :title="modelTitle" |
| | | @on-cancel="infoModelClose" |
| | | 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> |
| | | |
| | | </card> |
| | | <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 || '无内容'" |
| | | ></div> |
| | | </div> |
| | | </Col> |
| | | </Row> |
| | | </div> |
| | | |
| | | <div slot="footer"> |
| | | <Button @click="infoModelClose">关闭</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | |
| | | <!-- 图片预览模态框 --> |
| | | <Modal v-model="previewVisible" title="图片预览" footer-hide> |
| | | <img :src="previewImageUrl" style="width: 100%"> |
| | | </Modal> |
| | | </Card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import JsonExcel from "vue-json-excel"; |
| | | |
| | | import {getActivityList,addActivity,editActivity,delActivityById,activityChangeStatus,activityChangeRecommend,activityMembersPage} from "@/api/activity.js" |
| | | import {uploadFileByLmk,delByKey,getUrl} from "@/api/common.js" |
| | | |
| | | |
| | | import { |
| | | getActivityList, |
| | | addActivity, |
| | | editActivity, |
| | | delActivityById, |
| | | activityChangeStatus, |
| | | activityChangeRecommend, |
| | | activityMembersPage |
| | | } from "@/api/activity.js" |
| | | import Editor from '@/components/editor/index.vue' |
| | | import { uploadFileByLmk, delByKey } from "@/api/common.js" |
| | | export default { |
| | | name:"activity", |
| | | components:{ |
| | | "download-excel": JsonExcel, |
| | | }, |
| | | data(){ |
| | | return{ |
| | | loading: false, // 表单加载状态 |
| | | typeSelect:[ |
| | | { |
| | | id:1, |
| | | value:'线上' |
| | | }, |
| | | { |
| | | id:2, |
| | | value:'线下' |
| | | } |
| | | ], |
| | | coverTypeOptions:[ |
| | | { |
| | | id:1, |
| | | value: '输入文字封面' |
| | | }, |
| | | { |
| | | id:2, |
| | | value: '选择文件封面' |
| | | }, |
| | | ], |
| | | membersLoading:false, //参加活动人员表单 |
| | | membersModelTitle:'', |
| | | membersModelShow:false, |
| | | membersList:[], |
| | | membersColumns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title:'用户名', |
| | | key: 'username', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | }, |
| | | { |
| | | title:'昵称', |
| | | key: 'nickName', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | }, |
| | | { |
| | | title:'性别', |
| | | key: 'sex', |
| | | tooltip: true, |
| | | render: (h, params) => { |
| | | const sexText = params.row.sex === 1 ? '男' : '女'; |
| | | return h('span', sexText); |
| | | } |
| | | }, |
| | | { |
| | | title:'地址', |
| | | key: 'region', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | }, |
| | | { |
| | | title:'状态', |
| | | key: 'disabled', |
| | | tooltip: true, |
| | | render: (h, params) => { |
| | | const sexText = params.row.disabled === true ? '禁用' : '正常'; |
| | | return h('span', sexText); |
| | | } |
| | | }, |
| | | ], |
| | | memberForm:{ |
| | | id:'', |
| | | pageNumber: 1, // 当前页数 |
| | | pageSize: 10, // 页面大小 |
| | | }, |
| | | memberTotal:0, |
| | | name: "ActivityManagement", |
| | | components: {Editor}, |
| | | data() { |
| | | return { |
| | | infoModelShow:false, |
| | | |
| | | coverType:'', |
| | | //查询活动列表请求参数 |
| | | searchForm:{ |
| | | activityName:'',// 活动名称 |
| | | activityType:'',// 活动类型 |
| | | recommend:'',// 推荐 |
| | | reportStartTime:'',// 活动报名时间 |
| | | reportEndTime:'',// 活动结束时间 |
| | | pageNumber: 1, // 当前页数 |
| | | pageSize: 10, // 页面大小 |
| | | loading: false, |
| | | membersLoading: false, |
| | | submitLoading: false, |
| | | |
| | | // 搜索表单 |
| | | searchForm: { |
| | | activityName: '', |
| | | activityType: '', |
| | | reportStartTime: '', |
| | | reportEndTime: '', |
| | | pageNumber: 1, |
| | | pageSize: 10 |
| | | }, |
| | | |
| | | // 活动列表数据 |
| | | activityList: [], |
| | | total: 0, |
| | | selectList: [], |
| | | selectCount: 0, |
| | | |
| | | // 活动类型选项 |
| | | typeSelect: [ |
| | | { id: 1, value: 'online',label:'线上' }, |
| | | { id: 2, value: 'offline',label:'线下' } |
| | | ], |
| | | |
| | | //活动列表表头 |
| | | // 封面类型选项 |
| | | coverTypeOptions: [ |
| | | { id: 1, value: '输入文字封面' }, |
| | | { id: 2, value: '选择文件封面' } |
| | | ], |
| | | coverType: '', |
| | | file: null, |
| | | |
| | | // 活动表单 |
| | | activityFrom: { |
| | | id: '', |
| | | activityName: '', |
| | | activityType: '', |
| | | reportTime: [], |
| | | time: [], |
| | | activityContent: '', |
| | | cover: '', |
| | | coverType: '', |
| | | status: '', |
| | | reportStartTime: '', |
| | | reportEndTime: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | recommend: false, |
| | | limitUserNum: 0, |
| | | activityLocation: '', |
| | | }, |
| | | activityInfo: { |
| | | id: '', |
| | | activityName: '', |
| | | activityType: '', |
| | | reportTime: [], |
| | | time: [], |
| | | activityContent: '', |
| | | cover: '', |
| | | coverType: '', |
| | | status: '', |
| | | reportStartTime: '', |
| | | reportEndTime: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | recommend: false, |
| | | limitUserNum: 0, |
| | | activityLocation: '', |
| | | }, |
| | | |
| | | // 表单验证规则 |
| | | rules: { |
| | | activityName: [ |
| | | { required: true, message: '请输入活动名称', trigger: 'blur' }, |
| | | { max: 50, message: '长度不能超过50个字符', trigger: 'blur' } |
| | | ], |
| | | activityType: [ |
| | | { required: true, message: '请选择活动类型', trigger: 'change' } |
| | | ], |
| | | reportTime: [ |
| | | { 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' } |
| | | ], |
| | | cover: [ |
| | | { required: true, message: '请输入封面内容', trigger: 'blur' } |
| | | ], |
| | | coverType: [ |
| | | { required: true, message: '请选择封面类型', trigger: 'blur' } |
| | | ], |
| | | limitUserNum: [ |
| | | { 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' } |
| | | ], |
| | | activityContent: [ |
| | | { required: true, message: '请输入活动内容', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | // 表格列配置 |
| | | columns: [ |
| | | { |
| | | type: 'selection', |
| | |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title:'活动名', |
| | | title: '活动名称', |
| | | key: 'activityName', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | minWidth: 120, |
| | | tooltip: true |
| | | }, |
| | | { |
| | | title:'活动类型', |
| | | title: '活动类型', |
| | | key: 'activityType', |
| | | tooltip: true, |
| | | }, |
| | | // { |
| | | // title:'状态', |
| | | // key: 'status', |
| | | // tooltip: true, |
| | | // }, |
| | | { |
| | | title:'推荐', |
| | | key: 'recommend', |
| | | |
| | | tooltip: true, |
| | | width: 100, |
| | | align: 'center', |
| | | render: (h, params) => { |
| | | const sexText = params.row.recommend === true ? '是' : '否'; |
| | | return h('span', sexText); |
| | | return h('Tag', { |
| | | }, params.row.activityType === 'online' ? '线上' : '线下') |
| | | } |
| | | }, |
| | | { |
| | | title:'活动报名开始时间', |
| | | key: 'reportStartTime', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | title: '推荐', |
| | | key: 'recommend', |
| | | width: 80, |
| | | align: 'center', |
| | | render: (h, params) => { |
| | | return h('Tag', { |
| | | props: { |
| | | color: params.row.recommend ? 'green' : 'default' |
| | | } |
| | | }, params.row.recommend ? '是' : '否') |
| | | } |
| | | }, |
| | | { |
| | | title:'活动报名结束时间', |
| | | key: 'reportEndTime', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | title: '发布', |
| | | key: 'publish', |
| | | width: 100, |
| | | align: 'center', |
| | | render: (h, params) => { |
| | | return h('Tag', { |
| | | props: { |
| | | color: params.row.publish ? 'green' : 'default' |
| | | } |
| | | }, params.row.publish ? '已发布' : '未发布') |
| | | } |
| | | }, |
| | | { |
| | | title:'活动开始时间', |
| | | key: 'reportEndTime', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | title: '状态', |
| | | key: 'status', |
| | | width: 100, |
| | | align: 'center', |
| | | 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' } |
| | | }; |
| | | const currentStatus = statusMap[status] || { text: status, color: 'default' }; |
| | | return h('Tag', { |
| | | props: { |
| | | color: currentStatus.color |
| | | } |
| | | }, currentStatus.text); |
| | | } |
| | | }, |
| | | { |
| | | title:'活动结束时间', |
| | | key: 'reportEndTime', |
| | | minWidth: 60, |
| | | tooltip: true, |
| | | title: '活动时间段', |
| | | key: 'activityTimeRange', |
| | | width: 300, |
| | | render: (h, params) => { |
| | | return h('div', [ |
| | | h('div', `开始: ${this.formatDate(params.row.startTime)}`), |
| | | h('div', `结束: ${this.formatDate(params.row.endTime)}`) |
| | | ]) |
| | | } |
| | | }, |
| | | { |
| | | title:'封面', |
| | | title: '封面', |
| | | key: 'url', |
| | | slot:"url", |
| | | minWidth: 400, |
| | | tooltip: true, |
| | | slot: 'url', |
| | | width: 150, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title:'封面类型', |
| | | title: '封面类型', |
| | | key: 'coverType', |
| | | tooltip: true, |
| | | width: 100, |
| | | align: 'center', |
| | | render: (h, params) => { |
| | | const typeMap = { |
| | | text: '文本', |
| | | video: '视频', |
| | | image: '图片' |
| | | }; |
| | | const text = typeMap[params.row.coverType] || params.row.coverType; |
| | | return h('span', text); |
| | | } |
| | | }, |
| | | { |
| | | title:'最大报名人数限制', |
| | | title: '人数限制', |
| | | key: 'limitUserNum', |
| | | tooltip: true, |
| | | width: 100, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title:'活动地点', |
| | | title: '活动地点', |
| | | key: 'activityLocation', |
| | | tooltip: true, |
| | | }, |
| | | { |
| | | title:'活动详细内容', |
| | | key: 'activityContent', |
| | | tooltip: true, |
| | | minWidth: 120, |
| | | tooltip: true |
| | | }, |
| | | { |
| | | title: '操作', |
| | | key: 'action', |
| | | slot: 'action', |
| | | minWidth: 100, |
| | | align: 'center' |
| | | width: 280, |
| | | align: 'center', |
| | | fixed: 'right' |
| | | } |
| | | |
| | | ], |
| | | //活动列表数据 |
| | | activityList:[], |
| | | total:0, |
| | | selectCount: 0, // 已选数量 |
| | | selectList: [], // 已选数据列表 |
| | | |
| | | //活动对话框--- |
| | | |
| | | modelShow:false, |
| | | submitLoading:false, |
| | | modelTitle:'', |
| | | activityFrom:{ |
| | | id:'', |
| | | activityName:'', |
| | | activityType:'', |
| | | reportTime:[], |
| | | time:[], |
| | | activityContent:'', // 活动内容 |
| | | cover:'', //image/2025052014565362541.jpg |
| | | coverType:'', |
| | | status:'', //活动状态 |
| | | reportStartTime:'', |
| | | reportEndTime:'', |
| | | startTime:'', |
| | | endTime:'', |
| | | recommend:'', |
| | | |
| | | // 报名条件 |
| | | // 报名费用 |
| | | // 报名人员相关 |
| | | membersModelShow: false, |
| | | membersModelTitle: '', |
| | | membersList: [], |
| | | memberForm: { |
| | | id: '', |
| | | pageNumber: 1, |
| | | pageSize: 10 |
| | | }, |
| | | |
| | | rules: { |
| | | activityName: {required: true, message: "活动名称", trigger: "blur"}, |
| | | activityType: {required: true, message: "活动类型", trigger: "blur"}, |
| | | reportTime: [{type: 'array', |
| | | required: true, |
| | | message: "报名日期", trigger: "change" |
| | | memberTotal: 0, |
| | | membersColumns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | // 获取活动时间(通过闭包访问表单数据) |
| | | const activityTime = this.activityFrom.time; |
| | | |
| | | // 解析时间(增强健壮性) |
| | | const parseTime = (timeStr) => { |
| | | const date = new Date(timeStr); |
| | | return isNaN(date.getTime()) ? NaN : date.getTime(); |
| | | }; |
| | | |
| | | const reportStart = parseTime(value[0]); |
| | | const reportEnd = parseTime(value[1]); |
| | | const activityStart = parseTime(activityTime[0]); |
| | | const activityEnd = parseTime(activityTime[1]); |
| | | // 核心验证逻辑 |
| | | if (reportStart > activityStart || reportEnd > activityStart) { |
| | | callback(new Error('报名时间段必须在活动开始时间前')); |
| | | } else { |
| | | callback(); |
| | | { |
| | | title: '用户名', |
| | | key: 'username', |
| | | minWidth: 100 |
| | | }, |
| | | { |
| | | title: '昵称', |
| | | key: 'nickName', |
| | | minWidth: 100 |
| | | }, |
| | | { |
| | | title: '性别', |
| | | key: 'sex', |
| | | width: 80, |
| | | render: (h, params) => { |
| | | return h('Tag', { |
| | | props: { |
| | | color: params.row.sex === 1 ? 'blue' : 'magenta' |
| | | } |
| | | }, |
| | | trigger: 'change' |
| | | }, params.row.sex === 1 ? '男' : '女') |
| | | } |
| | | ], |
| | | // time: [{type: 'array', |
| | | // required: true, |
| | | // fields: { |
| | | // 0: {type: 'date', required: true, message: '请选择起止日期'}, |
| | | // 1: {type: 'date', required: true, message: '请选择起止日期'} |
| | | // } |
| | | // }], |
| | | time: [{type: 'array', |
| | | required: true, |
| | | message: "活动日期", trigger: "change" |
| | | }], |
| | | activityContent: {required: true, message: "活动内容", trigger: "blur"}, |
| | | cover: {required: true, message: "封面", trigger: "blur"}, |
| | | }, |
| | | // 上传 |
| | | file: null, |
| | | loadingStatus: false, |
| | | text:'文字', |
| | | }, |
| | | { |
| | | title: '地区', |
| | | key: 'region', |
| | | minWidth: 120 |
| | | }, |
| | | { |
| | | title: '状态', |
| | | key: 'disabled', |
| | | width: 100, |
| | | render: (h, params) => { |
| | | return h('Tag', { |
| | | props: { |
| | | color: params.row.disabled ? 'red' : 'green' |
| | | } |
| | | }, params.row.disabled ? '禁用' : '正常') |
| | | } |
| | | } |
| | | ], |
| | | |
| | | // 图片预览 |
| | | previewVisible: false, |
| | | previewImageUrl: '', |
| | | |
| | | // 模态框控制 |
| | | modelShow: false, |
| | | modelTitle: '' |
| | | } |
| | | }, |
| | | mounted(){ |
| | | this.init(); |
| | | mounted() { |
| | | this.init() |
| | | }, |
| | | methods:{ |
| | | activityMembersPage(){ |
| | | this.membersLoading = true; |
| | | activityMembersPage(this.memberForm).then(res =>{ |
| | | this.membersLoading = false; |
| | | if (res.code === 200){ |
| | | this.membersList = res.data; |
| | | this.memberTotal = res.total; |
| | | } |
| | | }); |
| | | methods: { |
| | | detail(row){ |
| | | this.modelTitle = '活动详情' |
| | | this.infoModelShow = true |
| | | this.activityInfo = row |
| | | }, |
| | | openMembersModal(row){ |
| | | this.memberForm.id = row.id |
| | | this.membersModelTitle = "报名人员" |
| | | this.membersModelShow = true; |
| | | this.activityMembersPage(); |
| | | // 获取富文本编辑器的内容 |
| | | getReason(content) { |
| | | this.activityFrom.activityContent = content |
| | | }, |
| | | membersModelClose(){ |
| | | this.membersModelShow = false; |
| | | // 初始化数据 |
| | | init() { |
| | | this.getActivityList() |
| | | }, |
| | | |
| | | changeRecommend(row,recommend){ |
| | | const form = { |
| | | ...this.activityFrom |
| | | }; |
| | | form.id = row.id; |
| | | if (recommend === "取消推荐"){ |
| | | form.recommend = false |
| | | }else if (recommend ==="推荐"){ |
| | | form.recommend = true |
| | | } |
| | | |
| | | activityChangeRecommend(form).then(res =>{ |
| | | if (res.code === 200){ |
| | | this.getActivityList(); |
| | | } |
| | | }) |
| | | }, |
| | | changeStatus(row,status){ |
| | | const form = { |
| | | ...this.activityFrom |
| | | }; |
| | | form.id = row.id; |
| | | if (status === "发布"){ |
| | | form.status = "已发布" |
| | | }else if (status ==="下架"){ |
| | | form.status = "已下架" |
| | | } |
| | | |
| | | activityChangeStatus(form).then(res =>{ |
| | | if (res.code === 200){ |
| | | this.getActivityList(); |
| | | } |
| | | }) |
| | | }, |
| | | coverTypeJudgment(type){ |
| | | if (this.coverType === '输入文字封面' && type === 'text'){ |
| | | this.activityFrom.coverType = this.text; |
| | | return true; |
| | | } |
| | | if (this.coverType === '选择文件封面' && type === 'file'){ |
| | | return true; |
| | | } |
| | | return false |
| | | }, |
| | | //自动上传 false |
| | | handleBeforeUpload (file) { |
| | | const fileCategory = this.getFileCategory(file.type); |
| | | console.log('文件分类:', fileCategory); // 输出:图片/视频/文档 等 |
| | | // 2. 你的其他逻辑(如类型验证) |
| | | if (fileCategory === '未知') { |
| | | this.$Message.error('不支持的文件类型'); |
| | | return false; |
| | | } |
| | | this.file = file; |
| | | this.activityFrom.coverType = fileCategory; |
| | | this.upload(); |
| | | return false |
| | | }, |
| | | getFileCategory(mimeType) { |
| | | // MIME类型前缀映射表 |
| | | const mimeMap = { |
| | | 'jpg' : '图片', |
| | | 'image': '图片', // image/jpeg, image/png 等 |
| | | 'video': '视频', // video/mp4, video/quicktime 等 |
| | | 'audio': '音频', // audio/mpeg, audio/wav 等 |
| | | 'application': '文档' // application/pdf, application/msword 等 |
| | | }; |
| | | |
| | | // 获取类型前缀(如 image/png → image) |
| | | const typePrefix = mimeType.split('/')[0]; |
| | | |
| | | // 返回对应分类或未知 |
| | | return mimeMap[typePrefix] || '未知'; |
| | | }, |
| | | |
| | | //上传图片接口 |
| | | upload () { |
| | | this.submitLoading = true; |
| | | this.loadingStatus = true; |
| | | const formData = new FormData() |
| | | formData.append('file', this.file) |
| | | uploadFileByLmk(formData).then(res =>{ |
| | | this.loadingStatus = false; |
| | | this.submitLoading = false; |
| | | if (res.code === 200){ |
| | | this.activityFrom.cover = res.data.fileKey; |
| | | this.$Message.success(res.msg) |
| | | } |
| | | }) |
| | | }, |
| | | handleRemove(){ |
| | | this.file = null |
| | | this.loadingStatus = true; |
| | | delByKey(this.activityFrom.cover).then(res =>{ |
| | | this.loadingStatus = false; |
| | | if (res.code === 200){ |
| | | this.activityFrom.cover = null; |
| | | } |
| | | }) |
| | | |
| | | }, |
| | | |
| | | // 获得客户表格信息 |
| | | getActivityList(){ |
| | | this.loading = true; |
| | | getActivityList(this.searchForm).then(res =>{ |
| | | this.loading = false; |
| | | // 获取活动列表 |
| | | getActivityList() { |
| | | this.loading = true |
| | | getActivityList(this.searchForm).then(res => { |
| | | this.loading = false |
| | | if (res.code === 200) { |
| | | this.activityList = res.data; |
| | | this.total = res.total; |
| | | // 为每一行添加loading状态 |
| | | this.activityList = res.data.map(item => ({ |
| | | ...item, |
| | | recommendLoading: false, |
| | | statusLoading: false |
| | | })) |
| | | this.total = res.total |
| | | } |
| | | }).catch(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | init(){ |
| | | this.getActivityList(); |
| | | }, |
| | | changeSort(){ |
| | | |
| | | // 搜索活动 |
| | | handleSearch(type, value) { |
| | | if (type === 'reportStart') { |
| | | this.searchForm.reportStartTime = value |
| | | } else if (type === 'reportEnd') { |
| | | this.searchForm.reportEndTime = value |
| | | } |
| | | |
| | | this.searchForm.pageNumber = 1 |
| | | this.getActivityList() |
| | | }, |
| | | showSelect(){ |
| | | this.selectList = e.map(d => d.id); |
| | | this.selectCount = e.length; |
| | | |
| | | // 重置搜索 |
| | | resetSearch() { |
| | | this.$refs.searchForm.resetFields() |
| | | this.searchForm.pageNumber = 1 |
| | | this.getActivityList() |
| | | }, |
| | | // |
| | | openEdit(row){ |
| | | console.log(row) |
| | | |
| | | // 改变页码 |
| | | 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.modelTitle = "编辑活动" |
| | | |
| | | this.activityFrom.id = row.id; |
| | | this.activityFrom.activityName = row.activityName; |
| | | this.activityFrom.activityType = row.activityType; |
| | | this.activityFrom.activityContent = row.activityContent; |
| | | // this.activityFrom.cover = row.cover; |
| | | //判断封面类型赋值给前端 |
| | | if (row.coverType === this.text){ |
| | | this.coverType = '输入文字封面' |
| | | this.activityFrom.cover = row.cover |
| | | this.activityFrom.coverType = row.coverType |
| | | }else{ |
| | | this.coverType = '选择文件封面' |
| | | this.activityFrom.cover = row.cover |
| | | this.activityFrom.coverType = row.coverType |
| | | } |
| | | |
| | | //转换格式 |
| | | this.activityFrom.reportTime= |
| | | this.formatDate(new Date(row.reportStartTime))+' - '+ this.formatDate(new Date(row.reportEndTime)); |
| | | //转化格式 |
| | | this.activityFrom.time = |
| | | this.formatDate(new Date(row.startTime))+' - '+ this.formatDate(new Date(row.endTime)); |
| | | this.coverType = '输入文字封面' |
| | | this.file = null |
| | | this.$refs.form.resetFields() |
| | | this.activityFrom.id = '' |
| | | }, |
| | | validateDateTime(dateTimeString) { |
| | | const dateTimeRegex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) ([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/; |
| | | return dateTimeRegex.test(dateTimeString); |
| | | }, |
| | | saveOrUpdate(){ |
| | | //判断正则格式 ,全部转换成本地时间 并且转换为指定格式 |
| | | if (!this.validateDateTime(this.activityFrom.reportTime[0])){ |
| | | this.activityFrom.reportStartTime = this.formatDate(this.activityFrom.reportTime[0]); |
| | | }else { |
| | | this.activityFrom.reportStartTime = this.activityFrom.reportTime[0] |
| | | } |
| | | if (!this.validateDateTime(this.activityFrom.reportTime[1])){ |
| | | this.activityFrom.reportEndTime =this.formatDate(this.activityFrom.reportTime[1]); |
| | | }else { |
| | | this.activityFrom.reportEndTime = this.activityFrom.reportTime[1] |
| | | } |
| | | if (!this.validateDateTime(this.activityFrom.time[0])){ |
| | | this.activityFrom.startTime = this.formatDate(this.activityFrom.time[0]); |
| | | }else { |
| | | this.activityFrom.startTime = this.activityFrom.time[0] |
| | | } |
| | | if (!this.validateDateTime(this.activityFrom.time[1])){ |
| | | this.activityFrom.endTime = this.formatDate(this.activityFrom.time[1]); |
| | | }else { |
| | | this.activityFrom.endTime = this.activityFrom.time[1] |
| | | } |
| | | |
| | | // 打开编辑模态框 |
| | | 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.id) { |
| | | editActivity(this.activityFrom).then(res =>{ |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose(); |
| | | this.getActivityList(); |
| | | } |
| | | }) |
| | | }else { |
| | | addActivity(this.activityFrom).then(res => { |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose(); |
| | | this.getActivityList(); |
| | | } |
| | | }) |
| | | |
| | | // 处理时间数据 |
| | | 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') |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | formatDate(date) { |
| | | if (date !== null && date !== undefined && date !== ''){ |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, '0'); // 补零 |
| | | const day = String(date.getDate()).padStart(2, '0'); |
| | | const hour = String(date.getHours()).padStart(2, '0'); |
| | | const minutes = String(date.getMinutes()).padStart(2, '0'); |
| | | const second = String(date.getSeconds()).padStart(2, '0'); |
| | | return `${year}-${month}-${day} ${hour}:${minutes}:${second}`; |
| | | } |
| | | return null |
| | | }, |
| | | // 搜索 |
| | | handleSearch(type,$event){ |
| | | if(type === 'reportStart'){ |
| | | this.searchForm.reportStartTime = $event; |
| | | }else if(type === 'reportEnd'){ |
| | | this.searchForm.reportEndTime = $event; |
| | | } |
| | | |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = 10; |
| | | this.getActivityList(); |
| | | 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 |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | // 关闭弹窗 |
| | | modelClose() { |
| | | this.file = null |
| | | this.submitLoading = false |
| | | this.modelShow = false |
| | | this.coverType = null |
| | | this.$refs.form.resetFields() |
| | | }, |
| | | openAdd(){ |
| | | this.modelTitle = "新增活动" |
| | | this.modelShow = true |
| | | }, |
| | | // 删除 |
| | | delById(row){ |
| | | delActivityById(row.id).then(res =>{ |
| | | if (res.code === 200){ |
| | | this.$Message.success(res.msg) |
| | | this.getActivityList(); |
| | | |
| | | // 删除活动 |
| | | 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("您还未选择要删除的数据"); |
| | | 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 |
| | | } |
| | | }, |
| | | |
| | | // 文件上传前处理 |
| | | 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('上传成功') |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | }, |
| | | |
| | | // 删除文件 |
| | | handleRemove() { |
| | | //点击关闭窗口时确保文件已被清除 |
| | | if(this.file === null){ |
| | | return; |
| | | } |
| | | this.$Modal.confirm({ |
| | | title: "确认删除", |
| | | content: "您确认要删除所选的 " + this.selectCount + " 条数据?", |
| | | loading: true, |
| | | onOk: () => { |
| | | |
| | | if (!this.activityFrom.cover) { |
| | | this.file = null |
| | | return |
| | | } |
| | | delByKey(this.activityFrom.cover).then(res => { |
| | | if (res.code === 200) { |
| | | this.file = null |
| | | this.activityFrom.cover = '' |
| | | } |
| | | }); |
| | | }) |
| | | }, |
| | | // 页码 |
| | | changePage(v){ |
| | | this.searchForm.pageNumber = v |
| | | this.getActivityList() |
| | | }, |
| | | // 修改size |
| | | changePageSize(v){ |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = v; |
| | | this.getActivityList() |
| | | }, |
| | | memberChangePage(v){ |
| | | this.memberForm.pageNumber = v |
| | | this.activityMembersPage(); |
| | | }, |
| | | // 修改size |
| | | memberChangePageSize(v){ |
| | | this.memberForm.pageNumber = 1; |
| | | this.memberForm.pageSize = v; |
| | | this.activityMembersPage(); |
| | | }, |
| | | handleImageError(){ |
| | | |
| | | // 预览图片 |
| | | previewImage(url) { |
| | | this.previewImageUrl = url |
| | | this.previewVisible = true |
| | | }, |
| | | handleVideoError(){ |
| | | |
| | | // 获取文件分类 |
| | | getFileCategory(mimeType) { |
| | | const typeMap = { |
| | | 'image': 'image', |
| | | 'video': 'video', |
| | | 'audio': 'audio', |
| | | 'application': 'application' |
| | | } |
| | | |
| | | const typePrefix = mimeType.split('/')[0] |
| | | return typeMap[typePrefix] || 'unknown' |
| | | }, |
| | | previewImage(){ |
| | | |
| | | // 格式化日期 |
| | | 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> |
| | | .export { |
| | | margin: 10px 20px 10px 0; |
| | | } |
| | | .export-excel-wrapper { |
| | | display: inline; |
| | | } |
| | | .order-tab { |
| | | width: 950px; |
| | | height: 36px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | background-color: #f0f0f0; |
| | | padding: 0 10px; |
| | | margin-bottom: 10px; |
| | | div { |
| | | text-align: center; |
| | | padding: 4px 12px; |
| | | .activity-management { |
| | | .search-form { |
| | | padding: 16px; |
| | | background: #f8f8f9; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | margin-bottom: 16px; |
| | | |
| | | .ivu-form-item { |
| | | margin-bottom: 16px; |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .search-btn { |
| | | margin-left: 8px; |
| | | } |
| | | } |
| | | .current { |
| | | background-color: #ffffff; |
| | | |
| | | .operation { |
| | | margin-bottom: 16px; |
| | | |
| | | .ivu-btn { |
| | | margin-right: 8px; |
| | | } |
| | | } |
| | | |
| | | .activity-table { |
| | | .media-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100px; |
| | | |
| | | .thumbnail { |
| | | max-width: 100%; |
| | | max-height: 100%; |
| | | object-fit: contain; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); |
| | | } |
| | | } |
| | | |
| | | .video-player { |
| | | max-width: 100%; |
| | | max-height: 100px; |
| | | background: #000; |
| | | } |
| | | |
| | | .text-cover { |
| | | padding: 8px; |
| | | background: #f8f8f9; |
| | | border-radius: 4px; |
| | | max-width: 100%; |
| | | word-break: break-all; |
| | | } |
| | | } |
| | | |
| | | .action-btns { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | justify-content: center; |
| | | |
| | | .ivu-btn { |
| | | margin: 4px; |
| | | font-size: 12px; |
| | | padding: 2px 6px; |
| | | min-width: 60px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .page-footer { |
| | | margin-top: 16px; |
| | | padding: 8px 0; |
| | | } |
| | | |
| | | .members-modal { |
| | | .members-table { |
| | | margin-bottom: 16px; |
| | | } |
| | | } |
| | | |
| | | .upload-file-info { |
| | | margin-top: 8px; |
| | | padding: 8px; |
| | | background: #f8f8f9; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .upload-tip { |
| | | font-size: 12px; |
| | | color: #999; |
| | | margin-top: 4px; |
| | | } |
| | | } |
| | | .detail-container { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .detail-item { |
| | | margin-bottom: 18px; |
| | | line-height: 1.5; |
| | | |
| | | label { |
| | | display: inline-block; |
| | | width: 100px; |
| | | color: #666; |
| | | font-weight: bold; |
| | | vertical-align: top; |
| | | } |
| | | |
| | | span { |
| | | display: inline-block; |
| | | width: calc(100% - 110px); |
| | | } |
| | | } |
| | | |
| | | .activity-content { |
| | | border: 1px solid #dcdee2; |
| | | border-radius: 4px; |
| | | padding: 12px; |
| | | min-height: 100px; |
| | | margin-top: 8px; |
| | | } |
| | | </style> |