1.后端代码的实现:
1.1controller层
@PostMapping("/save")
public ResultData saveNotice(@RequestAttribute Long _userId,@RequestBody OperationMaintenance operationMaintenance ) throws IOException {
try {
operationMaintenanceService.saveData(_userId, operationMaintenance);
return ResultData.success();
} catch (CustomTitleExistsException e) {
// 捕获自定义异常,并返回错误响应
return ResultData.fail(e.getMessage());
} catch (Exception e) {
// 捕获其他异常,并返回错误响应
return ResultData.fail("运维标题已存在");
}
}
1.2serviceimpl层
@Override
public void saveData(Long _userId, OperationMaintenance operationMaintenance) throws IOException {
if (isTitleExists(operationMaintenance.getTitle())) {
throw new CustomTitleExistsException("运维标题已存在,请重新输入");
}else {
operationMaintenance.setId(_userId);
operationMaintenance.setCreateUserId(_userId);
operationMaintenance.setCreateTime(LocalDateTime.now());
operationMaintenanceMapper.insert(operationMaintenance);
}
}
@Override
public Boolean isTitleExists(String title) throws IOException {
OperationMaintenance existing = operationMaintenanceMapper.findByTitle(title);
return existing != null;
}
1.3xml中的sql实现
<select id="findByTitle" resultType="com.todod.model.OperationMaintenance">
SELECT * FROM operation_maintenance om WHERE om.om_title = #{title}
</select>
1.4自定义异常类:
public class CustomTitleExistsException extends RuntimeException{
public CustomTitleExistsException(String message) {
super(message);
}
}
1.5返回结果类:
private static final String OK = "ok";
private static final String ERROR = "error";
private static final String fail = "运维标题存在,请重新输入";
public static final int OK_CODE = 20000; // 成功
public static final int ERROR_CODE = 50000; // 系统异常
public static final int PARAM_ERROR_CODE = 50002; // 参数错误
public static final int METHOD_NOT_SUPPORTED = 50003; // 请求方式不正确
public static final int REQUEST_INTERFACE_ERROE_CODE = 50004; // 接口请求异常
public static final int ESTIMATE_ERROR_CODE = 50100; // 自定义异常
public static final int USER_NOT_LOGIN = 50101; // 用户未登录
public static final int USER_LOGIN_EXPIRED = 50102; // 用户登陆超时
public static final int USER_LOGIN_AcountError = 50103; // 用户名或密码错误
public static final int USER_LOGIN_StateError = 50104; // 用户状态禁用
public static final int INTERFACE_ERROR = 50105; // 接口请求异常
public static final int SINGLE_LOGIN_ERROR = 50106; // 单用户登陆异常
public static final int USER_UPLOAD_PASSWORD = 50107; // 强制用户修改密码
/**
* 响应结果
*/
private int code;
/**
* 响应消息
*/
private String msg;
/**
* 响应消息
*/
private Object data;
public ResultData() {
}
public ResultData(int code, String msg) {
super();
this.code = code;
this.msg = msg;
}
public ResultData(int code, String msg, Object data) {
super();
this.code = code;
this.msg = msg;
this.data = data;
}
public static ResultData fail(String message) {
return new ResultData(PARAM_ERROR_CODE, fail);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public static ResultData success() {
return new ResultData(OK_CODE, OK);
}
public static ResultData success(String msg) {
return new ResultData(OK_CODE, msg);
}
public static ResultData success(String msg, Object data) {
return new ResultData(OK_CODE, msg, data);
}
public static ResultData error() {
return new ResultData(ERROR_CODE, ERROR);
}
public static ResultData error(String msg) {
return new ResultData(ERROR_CODE, msg);
}
public static ResultData error(String msg, Object data) {
return new ResultData(ERROR_CODE, msg, data);
}
public static ResultData error(int code, String msg) {
return new ResultData(code, msg);
}
public static ResultData error(int code, String msg, Object data) {
return new ResultData(code, msg, data);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
2.前端代码的实现:
2.1添加数据页面:
<template>
<div style="width:100%;height:auto; margin:0 auto;">
<el-form :model="form" label-width="100px" label-position="left">
<el-row :gutter="20">
<el-col :span="24">
<el-form-item>
<div slot="label">项目名称<font color="red">*</font></div>
<el-select v-model="form.dirId" clearable style="width:100%;" @change="selectGoodsByGroupId($event)">
<el-option v-for="item in symbols" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item>
<div slot="label">运维标题<font color="red">*</font></div>
<el-input v-model="form.title" placeholder="运维标题" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item>
<div slot="label" >运维人员<font color="red">*</font></div>
<el-select v-model="form.staffId" clearable style="width:100%;" @change="selectGoodsByGroupId($event)">
<el-option v-for="item in symbols2" :key="item.id" :label="item.nickName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<div slot="label">运维日期<font color="red">*</font></div>
<el-date-picker
v-model="form.itemTime"
value-format="yyyy-MM-dd"
class="filter-item"
type="daterange"
range-separator="至"
start-placeholder="运维开始日期"
end-placeholder="运维结束日期"
style="width: 100%;"
:clearable="false"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="内容">
<el-input v-model="form.content" type="textarea" :autosize="{ minRows: 3, maxRows: 6}" />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.message" type="textarea" :autosize="{ minRows: 3, maxRows: 6}" />
</el-form-item>
<el-form-item label="检测报告" prop="gysId">
<el-upload
class="upload-demo"
accept=".jpg,.png,.jpeg,.bmp,.gif,.svg,.mp4,.avi,.wmv,.mpg,.rmvb,.flv,.doc,.docx,.xlsx"
:on-change="handleChange"
:action="uploadpath"
:headers="uoloadheaders"
:on-success="handleAvatarSuccess"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:file-list="fileList"
:before-upload="beforeAvatarUpload"
name="uploadfile_ant"
>
<el-button size="small" icon="el-icon-upload" type="primary">选择文件</el-button>
<span style="color:red;"> 上传文件不超过100MB</span>
</el-upload>
</el-form-item>
<el-form-item label="回复文档" prop="gysId">
<el-upload
class="upload-demo"
accept=".jpg,.png,.jpeg,.bmp,.gif,.svg,.mp4,.avi,.wmv,.mpg,.rmvb,.flv,.doc,.docx,.xlsx"
:on-change="handleChange2"
:action="uploadpath2"
:headers="uoloadheaders"
:on-success="handleAvatarSuccess2"
:on-remove="handleRemove2"
:on-exceed="handleExceed2"
:file-list="fileList2"
:before-upload="beforeAvatarUpload2"
name="uploadfile_ant"
>
<el-button size="small" icon="el-icon-upload" type="primary">选择文件</el-button>
<span style="color:red;"> 上传文件不超过100MB</span>
</el-upload>
</el-form-item>
</el-form>
<div style="text-align:center;">
<el-button type="primary" @click="save()">保存</el-button>
<el-button type="danger" @click="closePage">取消</el-button>
</div>
</div>
</template>
<script>
import { saveData } from '@/api/operationMaintenance'
import { getAllList ,} from '@/api/maApplicationInfo'
import { Message } from 'element-ui'
import {getUserList,getId} from '@/api/user'
import { getDictListByCode } from '@/api/dict'
import tool from '@/utils/tool'
export default {
inject: ['getList'],
data() {
return {
form: {},
uploadpath: '',
uploadpath2: '',
types: [],
batchCode:'',
symbols: [],
symbols2:[],
symbols3:[],
uoloadheaders: {},
fileData: '', // 文件上传数据(多文件合一)
fileList: [],
fileList2: [] // upload多文件数组
}
},
created() {
this.getproject()
this.getStateList('YW_OPEX_STATUS')
},
methods: {
getStateList(code){
getDictListByCode(code).then(response => {
if(code === 'YW_OPEX_STATUS'){
this.symbols3 = response.data
}
})
},
getproject(){
getAllList().then(response=> {
this.symbols = response.data
})
getUserList().then(response=>{
this.symbols2 = response.data
})
this.batchCode = ''
getId().then(res => {
this.batchCode = res.data
let address = process.env.NODE_ENV == 'development' ? process.env.VUE_APP_URL_RECON : process.env.VUE_APP_BASE_API;
var path = '/inspectionReport/uploadFile'
var path2 = '/replayDocument/uploadFile'
this.uploadpath = address + path
this.uploadpath2 = address + path2
this.uoloadheaders = {
'X-TOKEN' : tool.getCookie('X-Token'),
'client-url':location.href,
'applicationId':this.applicationId
}
})
},
selectGoodsByGroupId(val) { // 根据设备组id获取相应的商品
if (val != null && val !== '' && val !== undefined) {
for (var i = 0; i < this.symbols.length; i++) {
if (this.symbols[i].id === val) {
this.form.userId = this.symbols[i].customerMid
}
}
}
},
save(){
if (!this.form.dirId) {
this.$message.error('项目名称称不能为空')
return
} else if (!this.form.title) {
this.$message.error('运维标题不能为空')
return
} else if (!this.form.staffId) {
this.$message.error('运维人员不能为空')
return
} else if (!this.form.itemTime) {
this.$message.error('运维日期不能为空')
return
} else {
this.form.startTime = this.form.itemTime[0]
this.form.endTime = this.form.itemTime[1]
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
saveData(this.form).then(response => {
console.log(response.code)
Message({
message: '新增成功',
type: 'success',
duration: 5 * 1000,
})
this.$emit('update:visible', false)
loading.close()
this.getList()
}).catch(response => {
loading.close()
this.getList()
})
}
},
handleChange(file, fileList) {
let fileName = file.name;
let uid = file.uid
let pos = fileName.lastIndexOf(".");
let lastName = fileName.substring(pos, fileName.length);
var suffix = '.jpg,.png,.jpeg,.bmp,.gif,.svg,.mp4,.avi,.wmv,.mpg,.rmvb,.flv,.doc,.docx,.xlsx'
if (suffix.indexOf(lastName.toLowerCase()) === -1) {
this.$message.error("文件必须为.jpg,.png,.jpeg,.bmp,.gif,.svg,.mp4,.avi,.wmv,.mpg,.rmvb,.flv,.doc,.docx,.xlsx类型");
for(var i = 0;i<fileList.length;i++) {
if(fileList[i].uid == uid) {
fileList.splice(i,1)
}
}
return;
}
const existFile = fileList.slice(0, fileList.length - 1).find(f => f.name === file.name)
if (existFile) {
this.$message.error('当前文件已经存在!')
fileList.pop()
}
this.fileList = fileList
},
handleChange2(file, fileList2) {
let fileName = file.name;
let uid = file.uid
let pos = fileName.lastIndexOf(".");
let lastName = fileName.substring(pos, fileName.length);
var suffix = '.jpg,.png,.jpeg,.bmp,.gif,.svg,.mp4,.avi,.wmv,.mpg,.rmvb,.flv,.doc,.docx,.xlsx'
if (suffix.indexOf(lastName.toLowerCase()) === -1) {
this.$message.error("文件必须为.jpg,.png,.jpeg,.bmp,.gif,.svg,.mp4,.avi,.wmv,.mpg,.rmvb,.flv,.doc,.docx,.xlsx类型");
for(var i = 0;i<fileList2.length;i++) {
if(fileList2[i].uid == uid) {
fileList2.splice(i,1)
}
}
return;
}
const existFile = fileList2.slice(0, fileList2.length - 1).find(f => f.name === file.name)
if (existFile) {
this.$message.error('当前文件已经存在!')
fileList2.pop()
}
this.fileList2 = fileList2
},
handleAvatarSuccess(res, file) {
this.uploadLoading = false
if (res.code === 20000) {
this.form.reportId= res.data.id
this.upVisible = false
Message({
message: '上传成功',
type: 'success',
duration: 5 * 1000
})
} else {
this.upVisible = true
Message({
message: res.msg,
type: 'error',
duration: 5 * 1000
})
}
},
handleAvatarSuccess2(res, file) {
this.uploadLoading = false
if (res.code === 20000) {
this.form.fileId= res.data.id
this.upVisible = false
Message({
message: '上传成功',
type: 'success',
duration: 5 * 1000
})
} else {
this.upVisible = true
Message({
message: res.msg,
type: 'error',
duration: 5 * 1000
})
}
},
handleRemove(file, fileList) {
this.fileList = fileList
},
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
},
beforeAvatarUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 100
if (!isLt2M) {
this.$message.error('上传文件大小不能超过100MB!')
}
return isLt2M
},
handleRemove2(file, fileList2) {
this.fileList2 = fileList2
},
handleExceed2(files, fileList2) {
this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList2.length} 个文件`)
},
beforeAvatarUpload2(file) {
const isLt2M = file.size / 1024 / 1024 < 100
if (!isLt2M) {
this.$message.error('上传文件大小不能超过100MB!')
}
return isLt2M
},
closePage() {
this.$emit('update:visible', false)
},
}
}
</script>
2.2相关js
import request from '@/utils/request'
export function getInitialLoading() {
return request({
url: '/operationMaintenance/getInitialLoading',
method: 'post'
})
}
export function getAgainLoading(data) {
return request({
url: '/operationMaintenance/getAgainLoading',
method: 'post',
params: data
})
}
export function getPage(data) {
return request({
url: '/operationMaintenance/getPage',
method: 'post',
data
})
}
export function saveData(data) {
return request({
url: '/operationMaintenance/save',
method: 'post',
data
})
}
export function edit(data) {
return request({
url: '/operationMaintenance/edit',
method: 'post',
data
})
}
export function remove(data) {
return request({
url: '/operationMaintenance/delete',
method: 'post',
params: data
})
}
export function getInfo(data) {
return request({
url: '/operationMaintenance/getInfo',
method: 'get',
params: data
})
}
export function getXiangMuList(data) {
return request({
url: '/operationMaintenance/getXiangMuList',
method: 'post',
data
})
}
export function getSelectedPage(data) {
return request({
url: '/operationMaintenance/getSelectedPage',
method: 'post',
data
})
}
export function getSelected2Page(data) {
return request({
url: '/operationMaintenance/getSelected2Page',
method: 'post',
data
})
}
export function getAllList() {
return request({
url: '/operationMaintenance/getAllList',
method: 'post'
})
}
export function downloadFile(paran) {
return request({
url: '/inspectionReport/downLoad',
method: 'post',
params: paran,
responseType: 'blob'
})
}
export function downloadFile2(paran) {
return request({
url: '/replayDocument/downLoad',
method: 'post',
params: paran,
responseType: 'blob'
})
}
// 下载文件
export function downloadById(data) {
return request({
url: '/inspectionReport/downLoad',
method: 'post',
params: data,
responseType: 'blob'
})
}
export function getTreeData() {
return request({
url: '/operationMaintenance/getTreePartData',
method: 'post'
})
}
3.request.js
import axios from 'axios'
import { Message } from 'element-ui'
import router from '.././router'
import tool from './tool'
const otherReq = ['downLoad', 'downloadTemplate','problemTemplate']
let address = process.env.NODE_ENV == 'development' ? process.env.VUE_APP_URL_RECON : process.env.VUE_APP_BASE_API;
// create an axios instance
const service = axios.create({
baseURL: address, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: -1 // request timeout
})
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
let token = tool.getCookie('X-Token');
config.headers['X-TOKEN'] = token
config.headers['client-url'] = location.href
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
const res = response.data
var url = response.request.responseURL
var split = url.split('/')
var laststr = split[split.length - 1]
var lastUrl = laststr.split('?')[0]
if (lastUrl === 'flow') {
return response
}
if (otherReq.indexOf(lastUrl) !== -1) {
return response
}
if (url.indexOf('/data-source/data/') !== -1) {
return response.data
}
// if the custom code is not 20000, it is judged as an error.
if (res.code !== 20000) {
if (res.code === 50101 || res.code === 50102) {
if (url.indexOf('/getFillByTask') !== -1) {
let data = JSON.parse(response.config.data)
let taskId = data.taskId;
router.push({ path: '/loginShare', query: { id: taskId } })
} else {
// 获取登录页访问地址
let ypt = process.env.NODE_ENV == 'development' ? process.env.VUE_APP_HOME_URL : process.env.VUE_APP_HOME_URL_PROD;
// 如果当前路由不是登录页,跳转到登录页
if (window.location.href.indexOf(ypt) === -1) {
window.localStorage.clear();
tool.clearAllCookie()
localStorage.stop = true;
let ypt = process.env.NODE_ENV == 'development' ? process.env.VUE_APP_HOME_URL : process.env.VUE_APP_HOME_URL_PROD;
window.location.href = ypt
}
}
}else if (res.code === 50002) { //
Message({
message: res.msg || 'Error',
type: 'error',
duration: 5 * 1000
})
}
else if (res.code === 50107) { // 修改密码
router.push({
name: 'uploadPassword', params: { token: res.data.token }
})
} else if (res.code === 99999) { // 未授权
router.push({ path: '/empower/empower' })
} else if (res.code === 50000) { // 未授权
Message({
message: res.msg || 'Error',
type: 'error',
duration: 5 * 1000
})
}
// Message({
// message: res.msg || 'Error',
// type: 'error',
// duration: 5 * 1000
// })
return Promise.reject(new Error(res.msg || 'Error'))
} else {
return res
}
},
error => {
console.log('err' + error) // for debug
Message({
message: error.msg || 'Error',
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
3.课外知识:
后端打包命令:mvn clean package;
前段打包命令:npm run build;