New file |
| | |
| | | <template> |
| | | <div class="news-management"> |
| | | <Card> |
| | | <!-- 搜索表单 --> |
| | | <Form |
| | | ref="searchForm" |
| | | @keydown.enter.native="handleSearch" |
| | | :model="searchForm" |
| | | inline |
| | | :label-width="80" |
| | | class="search-form" |
| | | > |
| | | <FormItem label="标题" prop="title"> |
| | | <Input |
| | | type="text" |
| | | v-model="searchForm.title" |
| | | placeholder="请输入标题名称" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | style="width: 180px" |
| | | /> |
| | | </FormItem> |
| | | <FormItem label="是否发布" prop="publish"> |
| | | <Select |
| | | v-model="searchForm.publish" |
| | | placeholder="请选择" |
| | | style="width: 180px" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | > |
| | | <Option |
| | | v-for="item in typeSelect" |
| | | :value="item.value" |
| | | :key="item.id" |
| | | > |
| | | {{ item.label }} |
| | | </Option> |
| | | </Select> |
| | | </FormItem> |
| | | <Button |
| | | @click="handleSearch" |
| | | type="primary" |
| | | icon="ios-search" |
| | | class="search-btn" |
| | | >搜索</Button> |
| | | <Button |
| | | @click="resetSearch" |
| | | icon="md-refresh" |
| | | style="margin-left: 8px" |
| | | >重置</Button> |
| | | </Form> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <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="newsList" |
| | | ref="table" |
| | | @on-selection-change="showSelect" |
| | | class="news-table" |
| | | > |
| | | <!-- 封面展示插槽 --> |
| | | <!-- 操作按钮插槽 --> |
| | | <template slot-scope="{ row }" slot="action"> |
| | | <div class="action-btns"> |
| | | <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> |
| | | </div> |
| | | </template> |
| | | </Table> |
| | | |
| | | <!-- 分页 --> |
| | | <Row type="flex" justify="end" class="page-footer"> |
| | | <Page |
| | | :current="searchForm.pageNumber" |
| | | :total="total" |
| | | :page-size="searchForm.pageSize" |
| | | @on-change="changePage" |
| | | @on-page-size-change="changePageSize" |
| | | :page-size-opts="[10, 20, 50]" |
| | | size="small" |
| | | show-total |
| | | show-elevator |
| | | show-sizer |
| | | ></Page> |
| | | </Row> |
| | | |
| | | <!-- 新闻编辑/新增模态框 --> |
| | | <Modal |
| | | v-model="modelShow" |
| | | :title="modelTitle" |
| | | @on-cancel="modelClose" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <Form ref="form" :model="newsForm" :label-width="100" :rules="rules"> |
| | | <Row :gutter="16"> |
| | | <Col span="12"> |
| | | <FormItem label="标题" prop="title"> |
| | | <Input |
| | | v-model="newsForm.title" |
| | | placeholder="请输入标题名称" |
| | | clearable |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24"> |
| | | <FormItem label="新闻内容:" prop="content"> |
| | | <editor ref="editor" @input="getReason" /> |
| | | </FormItem> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | |
| | | <div slot="footer"> |
| | | <Button @click="modelClose">取消</Button> |
| | | <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">提交</Button> |
| | | </div> |
| | | </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>{{ newsInfo.title || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>是否发布:</label> |
| | | <span>{{newsInfo.publish ? '已发布':'未发布'}}</span> |
| | | </div> |
| | | </Col> |
| | | |
| | | <Col span="12"> |
| | | <div class="detail-item" v-if="newsInfo.publish"> |
| | | <label>发布时间:</label> |
| | | <span>{{ newsInfo.publishDate}}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="24"> |
| | | <div class="detail-item"> |
| | | <label>新闻内容:</label> |
| | | <div |
| | | class="news-content" |
| | | v-html="newsInfo.content || '无内容'" |
| | | ></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 Editor from '@/components/editor/index.vue' |
| | | import { getNews,editNews,addNews,publish,delById } from '@/api/news.js' |
| | | export default { |
| | | name: "newsManagement", |
| | | components: {Editor}, |
| | | data(){ |
| | | return{ |
| | | // 图片预览 |
| | | previewVisible: false, |
| | | previewImageUrl: '', |
| | | |
| | | modelShow:false, |
| | | modelTitle:'', |
| | | submitLoading:false, |
| | | infoModelShow:false, |
| | | //表头 |
| | | columns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: '标题', |
| | | key: 'title', |
| | | minWidth: 120, |
| | | 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: 'publishDate', |
| | | width: 300, |
| | | align: 'center', |
| | | render: (h, { row }) => { |
| | | // 如果 publishDate 为 null 或 undefined,显示 "未发布" |
| | | if (row.publishDate == null) { |
| | | return h('span', { style: { color: '#999' } }, '暂无'); |
| | | } |
| | | // 否则正常显示日期 |
| | | return h('span', row.publishDate); |
| | | }, |
| | | }, |
| | | { |
| | | title: '操作', |
| | | slot: 'action', |
| | | width: 280, |
| | | align: 'center', |
| | | fixed: 'right' |
| | | } |
| | | ], |
| | | |
| | | newsList:[], |
| | | total:0, |
| | | newsForm:{ |
| | | id:'', |
| | | title:'', |
| | | content:'', |
| | | publish:0, |
| | | }, |
| | | newsInfo:{ |
| | | title:'', |
| | | publish:false, |
| | | publishDate:'', |
| | | content:'' |
| | | }, |
| | | rules: { |
| | | title: [ |
| | | { required: true, message: '请输入标题', trigger: 'blur' }, |
| | | { max: 50, message: '长度不能超过50个字符', trigger: 'blur' } |
| | | ], |
| | | publish: [ |
| | | { required: true, message: '请选择是否发布', trigger: 'blur' }, |
| | | ], |
| | | content: [ |
| | | { required: true, message: '请输入新闻内容', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | selectList:[], |
| | | selectCount:0, |
| | | |
| | | loading:false, |
| | | |
| | | searchForm: { |
| | | title: '', |
| | | publish: 0, |
| | | pageNumber: 1, |
| | | pageSize: 10 |
| | | }, |
| | | typeSelect:[ |
| | | { |
| | | id:1, |
| | | label:'未发布', |
| | | value:0 |
| | | }, |
| | | { |
| | | id:2, |
| | | label:'已发布', |
| | | value:1 |
| | | } |
| | | |
| | | ] |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getNewsList(); |
| | | }, |
| | | methods:{ |
| | | getNewsList(){ |
| | | this.loading = true |
| | | getNews(this.searchForm).then(res =>{ |
| | | this.loading = false |
| | | if (res.code === 200) { |
| | | // 为每一行添加loading状态 |
| | | this.newsList = res.data.map(item => ({ |
| | | ...item, |
| | | })) |
| | | this.total = res.total |
| | | } |
| | | }).catch(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | getReason(content) { |
| | | this.newsForm.content = content |
| | | }, |
| | | saveOrUpdate(){ |
| | | this.$refs.form.validate(valid => { |
| | | if (valid) { |
| | | this.submitLoading = true |
| | | const submitData = { |
| | | ...this.newsForm, |
| | | publish: this.newsForm.publish !== 0, // true → 1, false → 0 |
| | | }; |
| | | if (this.newsForm.id){ |
| | | editNews(submitData).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose() |
| | | this.getNewsList() |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | }else { |
| | | addNews(submitData).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose() |
| | | this.getNewsList() |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | } |
| | | |
| | | } |
| | | }) |
| | | }, |
| | | infoModelClose(){ |
| | | this.infoModelShow = false; |
| | | }, |
| | | modelClose(){ |
| | | this.modelShow = false; |
| | | }, |
| | | changePage(page) { |
| | | this.searchForm.pageNumber = page |
| | | this.getNewsList() |
| | | }, |
| | | // 改变每页条数 |
| | | changePageSize(pageSize) { |
| | | this.searchForm.pageNumber = 1 |
| | | this.searchForm.pageSize = pageSize |
| | | this.getNewsList() |
| | | }, |
| | | |
| | | delById(row){ |
| | | delById(row.id).then(res =>{ |
| | | if (res.code === 200){ |
| | | this.$Message.success(res.msg); |
| | | this.getNewsList(); |
| | | } |
| | | |
| | | }) |
| | | }, |
| | | openEdit(row){ |
| | | this.modelTitle = '修改新闻'; |
| | | this.modelShow = true; |
| | | this.$refs.form.resetFields(); |
| | | this.newsForm.title = row.title; |
| | | this.newsForm.content = row.content; |
| | | this.newsForm.id = row.id; |
| | | this.$refs.editor.setContent(this.newsForm.content) |
| | | }, |
| | | openAdd(){ |
| | | this.modelTitle = '新增新闻'; |
| | | this.modelShow = true; |
| | | this.$refs.form.resetFields() |
| | | this.newsForm.id = ''; |
| | | |
| | | }, |
| | | detail(row){ |
| | | this.modelTitle = '活动详情' |
| | | this.infoModelShow = true |
| | | this.newsInfo = row |
| | | }, |
| | | changeStatus(row,action){ |
| | | row.statusLoading = true; |
| | | |
| | | publish(row.id).then(res =>{ |
| | | row.statusLoading = false |
| | | if (res.code === 200){ |
| | | this.$Message.success(res.msg); |
| | | this.getNewsList(); |
| | | } |
| | | }).catch(() => { |
| | | row.statusLoading = false |
| | | }) |
| | | }, |
| | | // 表格选择变化 |
| | | showSelect(selection) { |
| | | this.selectList = selection.map(item => item.id) |
| | | this.selectCount = selection.length |
| | | }, |
| | | |
| | | delBatch(){ |
| | | |
| | | }, |
| | | handleSearch(type, value){ |
| | | this.searchForm.pageNumber = 1 |
| | | this.getNewsList() |
| | | }, |
| | | resetSearch(){ |
| | | this.$refs.searchForm.resetFields() |
| | | this.searchForm.pageNumber = 1 |
| | | this.getNewsList() |
| | | }, |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .activity-management { |
| | | .search-form { |
| | | padding: 16px; |
| | | background: #f8f8f9; |
| | | border-radius: 4px; |
| | | margin-bottom: 16px; |
| | | |
| | | .ivu-form-item { |
| | | margin-bottom: 16px; |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .search-btn { |
| | | margin-left: 8px; |
| | | } |
| | | } |
| | | } |
| | | .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); |
| | | } |
| | | } |
| | | |
| | | .news-content { |
| | | border: 1px solid #dcdee2; |
| | | border-radius: 4px; |
| | | padding: 12px; |
| | | min-height: 100px; |
| | | margin-top: 8px; |
| | | } |
| | | .news-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); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .action-btns { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | justify-content: center; |
| | | |
| | | .ivu-btn { |
| | | margin: 4px; |
| | | font-size: 12px; |
| | | padding: 2px 6px; |
| | | min-width: 60px; |
| | | } |
| | | } |
| | | } |
| | | </style> |