[ 项目开发 1.0 ] 新闻网站的开发流程和注意事项

目录

[一. 功能分析](#一. 功能分析)

(1)后台管理

[5. 系统信息设置](#5. 系统信息设置)

[6. 新闻类型管理](#6. 新闻类型管理)

[7. 新闻内容管理](#7. 新闻内容管理)

[8. 新闻统计(echars组件)](#8. 新闻统计(echars组件))

[9. 用户审核封禁](#9. 用户审核封禁)

[10. 评论审核](#10. 评论审核)

[11. 敏感词管理](#11. 敏感词管理)

(2)前台显示

(3)用户功能

[1. 用户注册](#1. 用户注册)

[2. 用户登录](#2. 用户登录)

[3. 对新闻评论 点赞 收藏](#3. 对新闻评论 点赞 收藏)

[4. 用户个人中心](#4. 用户个人中心)

[二. 数据库设计](#二. 数据库设计)

[三. 核心注意事项](#三. 核心注意事项)

[1. 新闻列表查询](#1. 新闻列表查询)

[(1). 标签](#(1). 标签)

[(2). concat 关键字](#(2). concat 关键字)

[(3). 开关组件](#(3). 开关组件)

[2. 新增新闻界面](#2. 新增新闻界面)

[(1) 两次封装](#(1) 两次封装)

[(2) 解决无法显示发布状态](#(2) 解决无法显示发布状态)

(3)实现转载和原创的不同显示

[(4) 文件上传(图片)](#(4) 文件上传(图片))

[4.1 前端提交文件 使用elementUI组件提交文件](#4.1 前端提交文件 使用elementUI组件提交文件)

把之前所有添加过样式的vue中都添加上scope

[4.2 后端接收文件 使用spring+Apache文件上传组件](#4.2 后端接收文件 使用spring+Apache文件上传组件)

[4.3 储存文件 将文件储存在服务器中, 只返回图片在服务器中的地址,在数据库中只存储地址](#4.3 储存文件 将文件储存在服务器中, 只返回图片在服务器中的地址,在数据库中只存储地址)

(5)阿里云OSS对象存储

(6)springboot集成oss


实际开发涉及多个部分,是一项复杂的工程, 需要协同完成, 例如:

(产品部)市场调研---需求分析---产品设计---开发 (研发部 技术选型 分工)---软件测试---运维

一. 功能分析

后台管理---前台显示---用户功能

(1)后台管理

  1. 前后端项目搭建

  2. 管理员登录

  3. 管理员管理(权限)

  4. 修改密码

5. 系统信息设置

用途: 维护平台信息, 数据库中只有一条记录 ,只做修改操作

维护的信息: 系统名称 logo(图片) 公司名称 电话 地址 备案号 操作人 操作时间

6. 新闻类型管理

类型(一级)

状态(启用/停用)

7. 新闻内容管理

标题 摘要 封面图 类型 内容 分类(转载/原创) 评论(是否支持) 发布状态(是否发布)

8. 新闻统计(echars组件)

统计数据(柱状图 折线图 饼状体) 地图...

9. 用户审核封禁

10. 评论审核

11. 敏感词管理

(2)前台显示

  1. 首页:

按分类显示新闻

系统信息

友情链接

  1. 新闻详细页面:

新闻基本内容

点赞 收藏 评论

(3)用户功能

1. 用户注册

账号 密码 头像 昵称 性别 手机号 状态(启用 禁用) 注册时间

2. 用户登录

3. 对新闻评论 点赞 收藏

4. 用户个人中心

修改个人信息

查看个人评论

查看浏览记录

二. 数据库设计

  1. admin 管理员表

  2. menu 菜单表

  3. admin_menu 权限表

  4. news_ type 新闻类型表

id name status(0-启用 1-停用 ) adminid oper_time

  1. news 新闻表

id title(标题) digest(摘要) img(封面图) content(数据库text类型) typeid(新闻类型)

type(0-原创, 1-转载) link(转载链接) commenttype(是否支持评论 0-支持评论, 1-不支持)

status(发布状态 0-未发布, 1-已发布 ) adminid (操作人) oper_time(操作时间)

  1. systeminfo 系统信息表

id name logo(varchar 100 给个地址) company_name phone address

filing_number(备案号) adminid oper_time

系统信息只有一条护具,可以在数据库中直接初始化一条,后期做的都是修改操作

  1. link 友情链接表

id name status(0-启用,1-停用) adminid oper_time

  1. sensitivewords敏感词表

id name adminid oper_time

  1. user用户表

id,email(账号), password,img(头像),nick_name,gender,phone,status(0-正常,1-禁用), reg-time

三. 核心注意事项

1. 新闻列表查询

(1). <where> 标签

<where>是mybatis中的动态sql标签, 一旦where标签内部有条件成立,会自动添加where关键字, 同时可以去除where后面紧跟的关键字(例如 and)

当有前提的判断条件时(一般写法)

where a.type = 1

<if test="account!=''">

and a.account=#{account}

</if>

<if test="phone!=''">

and a.phone=#{phone}

</if>

当没有前提的判断条件时 早期的解决方法 where 1 = 1 (没有使用where标签)

where 1 = 1

<if test="title!=''">

n.title like concat('%',#{title},'%')

</if>

在mybatis 之后(使用了where标签)

<where>

<if test="title!=''">

n.title like concat('%',#{title},'%')

</if>

</where>

(2). concat 关键字

模糊查询中需要使用concat(字符串连接函数)

n.title like concat('%',#{title},'%')

XML 复制代码
<select id="findNewsList" resultMap="newsMap">
        select
            n.id,
            n.title,
            n.img,
            t.name,
            n.status,
            n.type,
            a.account,
            n.oper_time
        from
            news n
                left join news_type t
                          on n.typeid = t.id
                left join admin a
                          on n.adminid = a.id
        <where>
            <if test="title!=''">
                n.title like concat('%',#{title},'%')
            </if>

        </where>
    </select>

(3). 开关组件

可以添加在需要修改状态的地方 例如 新闻的发布状态

XML 复制代码
<template slot-scope="scope"  >
				     <el-switch
					   v-model="scope.row.status"
					   active-color="#13ce66"
					   inactive-color="#ff4949"
					   active-text="已发布"
					   inactive-text="未发布"
					   :active-value="1"
					   :inactive-value="0" @change="changeStatus(scope.row)">
				     </el-switch>
				   </template>

2. 新增新闻界面

(1) 两次封装

news中封装了newstype,newstype中封装了id ,为了避免冗余, 需要这么写

<el-form-item label="新闻类型">

<el-select placeholder="请选择" v-model="form.newsType.id">

<el-option

v-for="newsType in newsTypeList"

:key="newsType.id"

:label="newsType.name"

:value="newsType.id">

</el-option>

</el-select>

</el-form-item>

form:{//默认封装到后端的news类里面

title:"",

digest:"",

newsType:{
id:""
},

img:"",//向后端提交的图片地址

type:0,

link:"",

commenttype:0,

content:"",

status:0

}

(2) 解决无法显示发布状态

原因: 数据类型不匹配(字符串和整数),导致前端不显示

方法一: 在label前面加冒号 ": " ,可以将字符串的0转为整数的0

<el-form-item label="是否发布">

<el-radio v-model="form.status" :label="0">发布</el-radio>

<el-radio v-model="form.status" :label="1">未发布</el-radio>

</el-form-item>

方法二: 把form表单中type 的0 加上引号 " ",这样也能接收到字符串0

form:{//默认封装到后端的news类里面

title:"",

digest:"",

newsType:{

id:""

},

img:"",//向后端提交的图片地址

type:"0",

link:"",

commenttype:0,

content:"",

status:0

}

(3)实现转载和原创的不同显示

点击转载时出现链接,点击原创时出现文本内容

方法: v-show 例如 v-show= "form.type==0"

v-if 和 v-else 如下:

html 复制代码
<el-form-item label="类型">
				<el-radio v-model="form.type" :label="0">原创</el-radio>
				<el-radio  v-model="form.type" :label="1">转载</el-radio>
			  </el-form-item>
			  
			  <el-form-item label="新闻内容" v-if="form.type==0">
				<mavon-editor ref="md" v-model="form.content" :toolbars="toolbars" @imgAdd="imgAdd" />
			  </el-form-item>
			  
			  <el-form-item label="链接转载" v-if="form.type==1">
				<el-input v-model="form.link" style="width: 500px"></el-input>
			  </el-form-item>

(4) 文件上传(图片)

4.1 前端提交文件 使用elementUI组件提交文件

<el-form-item label="封面图">

<!-- 使用elementUI文件上传组件 而不是axios组件发送请求

地址不能自动不全,不能自动携带token-->

<el-upload

class="avatar-uploader"

:action="serverAdd" 后端服务器地址,这里直接填入拼接后的地址

:headers="{token:token}"

:show-file-list="false"

:on-success="handleAvatarSuccess"

:before-upload="beforeAvatarUpload">

<img v-if="imgUrl" :src="imgUrl" class="avatar">

<i v-else class="el-icon-plus avatar-uploader-icon"></i>

</el-upload>

</el-form-item>

<style scoped >

/*加上 scoped 目的是作用在当前vue文件中*/

.avatar-uploader .el-upload {

border: 1px dashed #d9d9d9;

border-radius: 6px;

cursor: pointer;

position: relative;

overflow: hidden;

}

.avatar-uploader .el-upload:hover {

border-color: #409EFF;

}

.avatar-uploader-icon {

font-size: 28px;

color: #8c939d;

width: 80px;

height: 80px;

line-height: 80px;

text-align: center;

}

.avatar {

width: 80px;

height: 80px;

display: block;

}

</style>
return{

//新增对话框默认是关闭的

dialogVisible:false,

newsTypeList:[],

imgUrl:"",//前端临时显示用的

token**:sessionStorage.getItem("token"),//临时存储中拿到token**

serverAdd:this.serverAddress+"api/newsCtl/uploadImg" ,

form:{//默认封装到后端的news类里面

title:"",

digest:"",

newsType:{

id:""

},

img:"",//向后端提交的图片地址

type:0,

link:"",

commenttype:0,

content:"",

status:0

}

}

把之前所有添加过样式的vue中都添加上scope

//图片上传成功后会自动调用 在前端临时显示图片 resp用来接收后端响应的数据
handleAvatarSuccess(resp, file) {
this.imgUrl = URL.createObjectURL(file.raw);
this.form.img = resp.data;
alert(this.form.img);
},
//文件上传前调用 文件格式验证
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;

if (!isJPG) {
this.message.error('上传头像图片只能是 JPG 格式!'); } if (!isLt2M) { this.message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
}

4.2 后端接收文件 使用spring+Apache文件上传组件

添加apache 文件上传组件依赖

<!-- 文件上传组件 -->

<dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

<version>1.3.3</version>

</dependency>

添加spring文件解析类

package com.ffyc.news.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.multipart.commons.CommonsMultipartResolver;

@Configuration

public class MultipartConfig {

/**

* 文件上传配置

* @return

*/

@Bean

public CommonsMultipartResolver multipartConfigElement() {

CommonsMultipartResolver multipartresolver = new CommonsMultipartResolver();

multipartresolver.setMaxUploadSize(1024*1024*5);

return multipartresolver;

}

}

java 复制代码
 /**
     * 接收上传的文件,post请求 上传到阿里云
     * 使用CommonsMultipartFile 直接接收到文件
     */
    @PostMapping(path = "/uploadImg")
    public  Result uploadImg(@RequestParam("file")CommonsMultipartFile commonsMultipartFile) throws IOException {
        /*System.out.println(commonsMultipartFile.getName());
        System.out.println(commonsMultipartFile.getOriginalFilename());*/
        /*InputStream inputStream =commonsMultipartFile.getInputStream();//把文件写入自己的服务器地址
        File file = new File("D:\\development\\apache-tomcat-9.0.43\\webapps\\ROOT"+commonsMultipartFile.getOriginalFilename());
        commonsMultipartFile.transferTo(file);//把文件输入到指定文件*/

        InputStream inputStream = commonsMultipartFile.getInputStream();
        //使用阿里云oss对象存储
        //为了避免上传的文件重名,重新生成一个文件名
        String newFileName = new Date().getTime()+commonsMultipartFile.getOriginalFilename();
        //连接oss
        OSS ossClient = new OSSClientBuilder().build("https://"+endpoint, accessKeyId, accessKeySecret);
        //上传文件
        ossClient.putObject(bucketName, newFileName, commonsMultipartFile.getInputStream());
        //拼接文件在oss中访问地址
        String url = "https://"+bucketName+"."+endpoint+"/"+newFileName;
        Result  result = new Result(200,"上传成功",url);
        return  result;
    }

代码直接由阿里云提供, 不需要自己手写,仅理解即可,具体步骤看

(5)阿里云OSS对象存储

(6)springboot集成oss

4.3 储存文件 将文件储存在服务器中, 只返回图片在服务器中的地址,在数据库中只存储地址

原来: base64 格式字符串 ---->数据库

markdown上传图片

<el-form-item label="新闻内容" v-if="form.type==0">

<mavon-editor ref="md" v-model="form.content" :toolbars="toolbars" @imgAdd="imgAdd" />

</el-form-item>

//添加图片

imgAdd (pos, file) {

var formdata = new FormData();

formdata.append('file', file);//前端封装图片数据 'file'向后端传递的 name

this.$http({ //调用 java 后端上传图片到服务器端

url:this.serverAdd,//自定义后端服务器地址,后端同文件上传功能

data: formdata, method:"post", headers: { 'Content-Type': 'multipart/form-data','token':this.token} }).then((resp) => {//resp 后端响应数据

//将服务器返回的图片地址插入到编辑器内

this.refs.md.img2Url(pos, resp.data.data);

})

}

在新闻显示页面,添加封面图(与新增新闻的封面图不一样)

<el-table-column prop="img" label="封面图">

<template slot-scope="scope">

<img :src="scope.row.img" style="width: 50px; height: 50px;"/>

</template>

</el-table-column>

(5)阿里云OSS对象存储

访问阿里云官网

https://www.aliyun.com/

点击控制台

支付宝扫码登录,进入控制台, 没有账号注册账号

进入产品列表

选择oss对象存储

开通oss对象存储功能

完成实名认证

进入bucket列表

创建Bucket列表

创建成功,点击名称进入

测试上传文件

到此阿里云oss功能开通测试成功

(6)springboot集成oss

添加依赖

<!--阿里云oss依赖坐标-->

<dependency>

<groupId>com.aliyun.oss</groupId>

<artifactId>aliyun-sdk-oss</artifactId>

<version>3.15.1</version>

</dependency>

spring配置文件配置

aliyun:

oss:

endpoint: 你自己阿里云账户的endpoint,例如:oss-cn-beijing.aliyuncs.com

accessKeyId: 你自己阿里云账户的accessKeyId

accessKeySecret: 你自己阿里云账户的accessKeySecret

bucketName: 你自己阿里云账户的bucketName

获取accessKeyId

在使用的类中获取配置属性值

@Value("${aliyun.oss.endpoint}")

private String endpoint;

@Value("${aliyun.oss.accessKeyId}")

private String accessKeyId;

@Value("${aliyun.oss.accessKeySecret}")

private String accessKeySecret;

@Value("${aliyun.oss.bucketName}")

private String bucketName;

代码实现

@PostMapping(path = "/uploadFile")

public CommonResult uploadFile(@RequestParam("file")

CommonsMultipartFile multipartFile) throws IOException {

//为了避免上传的文件重名,重新生成一个文件名

String newFileName = new

Date().getTime()+multipartFile.getOriginalFilename();

//连接oss

OSS ossClient = new

OSSClientBuilder().build("https://"+endpoint, accessKeyId,

accessKeySecret);

//长传文件

ossClient.putObject(bucketName, newFileName,

multipartFile.getInputStream());

//拼接文件在oss中访问地址

String url =

"https://"+bucketName+"."+endpoint+"/"+newFileName;

return new CommonResult(200, url,"操作成功");

}

上传成功

相关推荐
hjhcos2 小时前
【SQL server】不同平台相同数据库之间某个平台经常性死锁
数据库
吴名氏.2 小时前
电子书《21天学通Java(第5版)》
java·开发语言·21天学通java
tanxiaomi2 小时前
RocketMQ微服务架构实践:从入门到精通完整指南
数据库·rocketmq
ruleslol2 小时前
SpringBoot面试题09-SpringBoot启动流程
spring boot
羑悻的小杀马特2 小时前
openGauss 数据库快速上手评测:从 Docker 安装到SQL 实战
数据库·sql·docker·opengauss
德迅云安全-小潘2 小时前
SQL:从数据基石到安全前线的双重审视
数据库·sql·安全
Databend2 小时前
Databend SQL nom Parser 性能优化
数据库
曼巴UE52 小时前
UE5 C++ JSON 最简单,麻烦的方式,直接读存(一)
java·服务器·前端