合同功能开发

This commit is contained in:
huangdeliang 2020-10-23 20:45:24 +08:00
parent a23a02ab60
commit d69e56371b
10 changed files with 276 additions and 106 deletions
doc
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model
ruoyi-framework/src/main/java/com/ruoyi/framework/config
ruoyi-ui

BIN
doc/contract.pdf Normal file

Binary file not shown.

@ -1,30 +1,32 @@
package com.ruoyi.web.controller.common;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.Contract;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 通用请求处理
*
*
* @author ruoyi
*/
@RestController
public class CommonController
{
public class CommonController {
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
@Autowired
@ -32,17 +34,14 @@ public class CommonController
/**
* 通用下载请求
*
*
* @param fileName 文件名称
* @param delete 是否删除
* @param delete 是否删除
*/
@GetMapping("common/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{
try
{
if (!FileUtils.isValidFilename(fileName))
{
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
try {
if (!FileUtils.isValidFilename(fileName)) {
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
}
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
@ -53,13 +52,10 @@ public class CommonController
response.setHeader("Content-Disposition",
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete)
{
if (delete) {
FileUtils.deleteFile(filePath);
}
}
catch (Exception e)
{
} catch (Exception e) {
log.error("下载文件失败", e);
}
}
@ -68,10 +64,8 @@ public class CommonController
* 通用上传请求
*/
@PostMapping("/common/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception
{
try
{
public AjaxResult uploadFile(MultipartFile file) throws Exception {
try {
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称
@ -81,9 +75,7 @@ public class CommonController
ajax.put("fileName", fileName);
ajax.put("url", url);
return ajax;
}
catch (Exception e)
{
} catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}
@ -92,8 +84,7 @@ public class CommonController
* 本地资源通用下载
*/
@GetMapping("/common/download/resource")
public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception
{
public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 本地资源路径
String localPath = RuoYiConfig.getProfile();
// 数据库资源地址
@ -106,4 +97,18 @@ public class CommonController
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));
FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
/**
* 合同签单
*/
@PostMapping("/common/contract")
public AjaxResult signContract(@RequestBody Contract contract) throws Exception {
try {
AjaxResult ajax = AjaxResult.success();
ajax.put("result", "hi");
return ajax;
} catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}
}

@ -0,0 +1,25 @@
package com.ruoyi.common.core.domain.model;
public class Contract {
private String name;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}

@ -97,7 +97,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
// 过滤请求
.authorizeRequests()
// 对于登录login 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/captchaImage").anonymous()
.antMatchers(
"/login",
"/captchaImage",
"/common/contract"
).anonymous()
.antMatchers(
HttpMethod.GET,
"/*.html",

@ -42,6 +42,7 @@
"dependencies": {
"@riophae/vue-treeselect": "0.4.0",
"axios": "0.18.1",
"base-64": "^1.0.0",
"clipboard": "2.0.4",
"core-js": "3.6.5",
"dayjs": "^1.9.1",

@ -3,7 +3,6 @@ import Vue from 'vue'
import Cookies from 'js-cookie'
import 'normalize.css/normalize.css' // a modern alternative to CSS resets
import Element from 'element-ui'
import './assets/styles/element-variables.scss'
@ -16,9 +15,19 @@ import permission from './directive/permission'
import './assets/icons' // icon
import './permission' // permission control
import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config";
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree, toThousands } from "@/utils/ruoyi";
import {getDicts} from "@/api/system/dict/data";
import {getConfigKey} from "@/api/system/config";
import {
addDateRange,
download,
handleTree,
parseTime,
resetForm,
searchToParams,
selectDictLabel,
selectDictLabels,
toThousands
} from "@/utils/ruoyi";
import Pagination from "@/components/Pagination";
//自定义表格工具扩展
import RightToolbar from "@/components/RightToolbar"
@ -34,13 +43,14 @@ Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
Vue.prototype.toThousands = toThousands
Vue.prototype.searchToParams = searchToParams
Vue.prototype.msgSuccess = function (msg) {
this.$message({ showClose: true, message: msg, type: "success" });
this.$message({showClose: true, message: msg, type: "success"});
}
Vue.prototype.msgError = function (msg) {
this.$message({ showClose: true, message: msg, type: "error" });
this.$message({showClose: true, message: msg, type: "error"});
}
Vue.prototype.msgInfo = function (msg) {

@ -1,64 +1,64 @@
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(res => {
// 拉取user_info
const roles = res.roles
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
// 测试 默认静态页面
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
})
.catch(err => {
store.dispatch('FedLogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else {
next()
// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
// if (hasPermission(store.getters.roles, to.meta.roles)) {
// next()
// } else {
// next({ path: '/401', replace: true, query: { noGoBack: true }})
// }
// 可删 ↑
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/contract']
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(res => {
// 拉取user_info
const roles = res.roles
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
// 测试 默认静态页面
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
})
.catch(err => {
store.dispatch('FedLogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else {
next()
// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
// if (hasPermission(store.getters.roles, to.meta.roles)) {
// next()
// } else {
// next({ path: '/401', replace: true, query: { noGoBack: true }})
// }
// 可删 ↑
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})

@ -123,6 +123,11 @@ export const constantRoutes = [
meta: { title: '修改生成配置' }
}
]
},
{
path: '/contract',
hidden: true,
component: (resolve) => require(['@/views/custom/contract'], resolve),
}
]

@ -161,6 +161,19 @@ export function toThousands(num) {
result = ',' + num.slice(-3) + result;
num = num.slice(0, num.length - 3);
}
if (num) { result = num + result; }
if (num) {
result = num + result;
}
return result;
}
export function searchToParams(paramStr) {
if (!paramStr) {
return {}
}
return paramStr.split('&').reduce((obj, cur) => {
const tarObj = cur.split('=');
obj[tarObj[0]] = tarObj[1];
return obj;
}, {})
}

@ -0,0 +1,107 @@
<template>
<div class="dashboard-editor-container">
<panel-group @handleSetLineChartData="handleSetLineChartData"/>
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<line-chart :chart-data="lineChartData"/>
</el-row>
<!-- <el-row :gutter="32">-->
<!-- <el-col :xs="24" :sm="24" :lg="8">-->
<!-- <div class="chart-wrapper">-->
<!-- <raddar-chart />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- <el-col :xs="24" :sm="24" :lg="8">-->
<!-- <div class="chart-wrapper">-->
<!-- <pie-chart />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- <el-col :xs="24" :sm="24" :lg="8">-->
<!-- <div class="chart-wrapper">-->
<!-- <bar-chart />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- </el-row>-->
</div>
</template>
<script>
import PanelGroup from '@/views/dashboard/PanelGroup'
import LineChart from '@/views/dashboard/LineChart'
import RaddarChart from '@/views/dashboard/RaddarChart'
import PieChart from '@/views/dashboard/PieChart'
import BarChart from '@/views/dashboard/BarChart'
import Base64 from 'base-64';
import {searchToParams} from "../../../utils/ruoyi";
const lineChartData = {
newVisitis: {
expectedData: [100, 120, 161, 134, 105, 160, 165],
actualData: [120, 82, 91, 154, 162, 140, 145]
},
messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140],
actualData: [180, 160, 151, 106, 145, 150, 130]
},
purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100],
actualData: [120, 90, 100, 138, 142, 130, 130]
},
shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160],
actualData: [120, 82, 91, 154, 162, 140, 130]
}
}
let params = window.location.search.substring(1);
if(params){
params = Base64.decode( window.location.search.substring(1))
params = searchToParams((params));
}
console.log(params)
export default {
name: 'Index',
components: {
PanelGroup,
LineChart,
RaddarChart,
PieChart,
BarChart
},
data() {
return {
lineChartData: lineChartData.newVisitis
}
},
methods: {
handleSetLineChartData(type) {
this.lineChartData = lineChartData[type]
}
}
}
</script>
<style lang="scss" scoped>
.dashboard-editor-container {
padding: 32px;
background-color: rgb(240, 242, 245);
position: relative;
.chart-wrapper {
background: #fff;
padding: 16px 16px 0;
margin-bottom: 32px;
}
}
@media (max-width: 1024px) {
.chart-wrapper {
padding: 8px;
}
}
</style>