#pic_center =400x
系列文章:
get请求 普通参数
后端:
@GetMapping("/testGet")
@ResponseBody
public Result testGet(String name, String age) {
System.out.println(name);
System.out.println(age);
Result result = new Result().setCode("200").setMsg("查询成功").setData(name);
return result ;
}
前端
testGet() {
const name="ds"
const age="12"
this.$axios({
method: 'get',
url: "http://localhost:8080/SingleRegression/testGet",
params: {name, age}
}
).then(res=> {
console.log(res)
})
},
postman测试
post请求普通string
testPost() {
// let age = []
// let names = []
//
// for(let i=0; i< 10; ++i) {
// age.push(i)
// names.push("aaa"+i)
// }
const age=12
const names="zhuyuanzhang"
this.$axios(
{
method: 'post',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: "http://localhost:8080/SingleRegression/testPost",
data: this.$qs.stringify({
age:age, names: names
})
}
).then( res => {
console.log(res)
})
}
前端需要使用qs.stringify
并且设置Content-type.使得发送到后端的数据以键值对
形式发送
axios发送post请求,默认请求头类型是content-type类型是’application/json;charset=utf-8’.发给后端是json
形式
axios配置请求头content-type
@GetMapping("/testGet")
@ResponseBody
public Result testGet(String name, String age) {
System.out.println(name);
System.out.println(age);
Result result = new Result().setCode("200").setMsg("查询成功").setData(name);
return result ;
}
post请求传递数组
方式一:将数组转换为字符串,后端在解析字符串
注意点:前端必须使用qs.stringify
,否则就400或者无法接受到参数
一旦使用qs.stringify 请求的content-type就不是默认的json形式,而是application/x-www-form-urlencoded
testPost() {
let age = []
let names = []
for(let i=0; i< 10; ++i) {
age.push(i)
names.push("aaa"+i)
}
age = age.join()//,分割
names = names.join();
this.$axios(
{
method: 'post',
url: "http://localhost:8080/SingleRegression/testPost",
data:
this.$qs.stringify(
{ "age":age, "names": names}
)
}
).then( res => {
console.log(res)
})
},
@PostMapping("/testPost")
@ResponseBody
public Result testPost(@RequestParam String names, @RequestParam String age) {
String nameArr[] = names.split(",");
String ageArr[] = age.split(",");
// aaa0 aaa1 aaa2 aaa3 aaa4 aaa5 aaa6 aaa7 aaa8 aaa9
for(String i: nameArr) {
System.out.print(i+" ");
}
System.out.println();
// 0 1 2 3 4 5 6 7 8 9
for (String i : ageArr) {
System.out.print(i+" ");
}
Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
return result ;
}
我的疑问:不进行qs为什么就是400??
后端用 public Result testPost(@RequestParam String names, @RequestParam String age)
Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter ‘names’ is not present]
下面的方式并未获取成功(请求正常通过,后端接收数据为Null),可能不知道前端是如何传递以及前端的content-type
testPost() {
let age = []
let names = []
for(let i=0; i< 10; ++i) {
age.push(i)
names.push("aaa"+i)
}
this.$axios(
{
method: 'post',
url: "http://localhost:8080/SingleRegression/testPost",
data:
this.$qs.stringify(
{ age:age, names: names}
)
}
).then( res => {
console.log(res)
})
},
@PostMapping("/testPost")
@ResponseBody
// 这样并不能接收到names[] age[]
public Result testPost(@RequestParam(value = "names[]", required = false) List<String>names,@RequestParam(value = "age", required = false) List<Integer> age) {
// 两者都是空值null
System.out.println(names);
System.out.println(age);
Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
return result ;
}
下面方式也未成功,前端请求发送失败400/415。
进行qs.stringify415,不进行是400
testPost() {
let age = []
let names = []
for(let i=0; i< 10; ++i) {
age.push(i)
names.push("aaa"+i)
}
this.$axios(
{
method: 'post',
url: "http://localhost:8080/SingleRegression/testPost",
data:
// this.$qs.stringify(
{ age:age, names: names}
// )
}
).then( res => {
console.log(res)
})
}
@PostMapping("/testPost")
@ResponseBody
public Result testPost(@RequestBody String[] names,@RequestBody String[] age) {
System.out.println(names);
System.out.println(age);
Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
return result ;
}
方式二:采用对象封装
后台接收数组
注意: 这里并没有进行qs.stringify
因为@RequestyBody一般用于处理非Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。
详解get与post请求方式、content-type与responseType、@Requestbody与@Requestparam的使用场景
testPost() {
let age = []
let names = []
for(let i=0; i< 10; ++i) {
age.push(i)
names.push("aaa"+i)
}
this.$axios(
{
method: 'post',
url: "http://localhost:8080/SingleRegression/testPost",
data: { "age":age, "names":names}
}
).then( res => {
console.log(res)
})
},
public class Test {
private List<String> names;
private List<Integer> age;
...
@PostMapping("/testPost")
@ResponseBody
public Result testPost(@RequestBody Test test) {
//[aaa0, aaa1, aaa2, aaa3, aaa4, aaa5, aaa6, aaa7, aaa8, aaa9]
System.out.println(test.getNames());
//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println(test.getAge());
Result result = new Result().setCode("200").setMsg("查询成功").setData(test);
return result ;
}
由于是发送 json 数据 后台封装到对象 所以采用 raw 类型
方式三
不建议,url长度是有限的,放数组会超过限制
前端目前不知道把参数放在url中
@PostMapping("/testPost")
@ResponseBody
public Result testPost(@RequestParam("names")List<String>names, @RequestParam("age")List<Integer>age) {
System.out.println(age.size());
Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
return result ;
}
###如何既有@RequestBody 又有@RequestParmas
vue【axios】get/post请求params/data传参总结
文件类型
单文件
接受单个文件,使用@Request Parma
// 上传文件接受
@ApiOperation(value = "用户上传文件上传文件接收")
@PostMapping("/uploadDataFile")
public Result acceptDataFile(@RequestParam("file") MultipartFile file) {
String filename = file.getOriginalFilename();
System.out.println(filename);
}
}
前端分为手动上传、自动上传
自动上传 this.$refs.upload.submit();实现上传
<el-upload
ref="upload" :limit="1"
:auto-upload="false"
action="http://localhost:40822/api/xjtu/singleRegression/uploadDataFile"
drag :multiple="false" :file-list="fileList"
:on-change="handleChange" accept=".xlsx, .xls"
:on-exceed="handleFileCountExceed"
:before-remove="beforeRemoveFile"
:before-upload="handleBeforeUpload">
<i class="el-icon-upload"></i>
<div >将文件拖到此处,或<em>点击上传</em></div>
<div slot="tip">上传Excel格式文件</div>
</el-upload>
<el-button type="primary" @click="confirmUpload()">确认上传</el-button>
handleFileCountExceed(files, fileList) {
this.$message.warning(
`只能上传 1 个文件,本次选择了 ${files.length} 个文件`
)
},
//移除文佳提示
beforeRemoveFile(file, fileList) {
return this.$confirm(`确定移除 ${file.name}?`);
},
handlePreview(file) {
console.log(file);
},
handleBeforeUpload(file) {
const uploadLimit = 1
const uploadTypes = ['xlsx', 'xlx', 'XLSX', 'XLX']
const filetype = file.name.replace(/.+\./, '')
const isRightSize = (file.size || 0) / 1024 / 1024 < uploadLimit
if (!isRightSize) {
this.$message.error('文件大小超过 ' + uploadLimit + 'MB')
return false
}
if (uploadTypes.indexOf(filetype.toLowerCase()) === -1) {
this.$message.warning({
message: '请上传后缀名为 xlsx, xlx, XLSX, XLX 的文件'
})
return false
}
return true
},
// 文件上传
submitUpload() {
this.$refs.upload.submit();
},
//文件改变
handleChange(file, fileList) {
this.uploadFileForm.files = file.raw
this.fileList = fileList;
},
// 确认上传
confirmUpload() {
if(this.fileList.length<1) {
this.$message.error("你还没有选择文件!!")
return false
}
let param = new FormData();
param.append("file", this.uploadFileForm.files)
// this.fileList.forEach(
// (val, index) => {
// param.append("file", val.raw);
// }
// );
// acceptDataFile(param).then(res => {
// if (res.code === 200) {
// this.$message.info({
// message: "上传成功!",
// duration: 1000
// })
// }
// })
console.log(FileList)
this.$message.info("正在上传")
this.$refs.upload.submit();
this.submitUpload()
this.stepActive = 1
},
文件+参数
方式一: 文件,参数分开,参数一个一个接收
后端 MultipartFile sourceFile,String testName,这里的sourceFile,testName要与前端对应
@ApiOperation(value = "文件数据进行一元回归测试")
@PostMapping("/testFileData")
public Result doFileData( MultipartFile sourceFile,String testName){
System.out.println("*******************************************");
System.out.println(sourceFile.getName());
System.out.println(testName);
return Result.ok(null);
}
// 用表单来初始化
const param = new FormData();
param.append("sourceFile",this.uploadFileForm.files)
param.append("testName", allData.testName)
testFileData(param).then(res=> {
console.log(res)
})
需要设置 ‘content-type’: ‘multipart/form-data’
export function testFileData(dataInfo) {
return request({
url: `${BASE_URL}/singleRegression/testFileData`,
method: 'post',
data: dataInfo,
headers: {
'content-type': 'multipart/form-data'
}
})
}
方式二: 将接受的文件封装在对象内部
如对象的形式
@ApiModelProperty("自变量名称")
private String variableName;
@ApiModelProperty("因变量名称")
private String dependentVariableName;
// 上传的文件
@ApiModelProperty("源数据文件")
private MultipartFile sourceFile;
controller层用实体对象接受
@ApiOperation(value = "文件数据进行一元回归测试")
@PostMapping("/testFileData")
public Result doFileData(SingleRegressionVo singleRegressionVo){
System.out.println(singleRegressionVo.getSourceFile().getName());
System.out.println(singleRegressionVo);
return Result.ok(null);
}
const param = new FormData();
//这里只传递了实体部分参数testName, sourceFile
param.append("sourceFile",this.uploadFileForm.files)
param.append("testName", allData.testName)
// 这里请求同方式一 设置 'content-type': 'multipart/form-data'
testFileData(param).then(res=> {
console.log(res)
})
文件单独,其余参数封装实体对象
@ApiOperation(value = "文件数据进行一元回归测试")
@PostMapping("/testFileData")
public Result doFileData(SingleRegressionVo singleRegressionVo, MultipartFile sourceFile){
System.out.println(singleRegressionVo);
System.out.println(sourceFile.getName());
return Result.ok(null);
}
const param = new FormData();
// param.append("allData", JSON.stringify(allData));
// 名称前后端要对应
param.append("sourceFile",this.uploadFileForm.files)
param.append("testName", allData.testName)
testFileData(param).then(res=> {
console.log(res)
})
Java 后端接收MultipartFile类型文件接口(带参与不带参)
前端文件上传及后端接收(el-upload标签的使用)
文件保存
http请求参数方式类型Query String Parameters、Form Data、Request Payload的使用记录以及qs的使用
http请求参数方式类型Query String Parameters、Form Data、Request Payload的使用记录以及qs的使用
本地打开TXT加载
<div >
txt
<input type="file" @change="loadTextFromFile">
<div>
<p v-html="resultTxt"></p>
</div>
</div>
//txt文件读取
loadTextFromFile: function(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = e => this.$emit("load", this.dealNum(e.target.result));
reader.readAsText(file,"utf-8");
},
dealNum(item){
let word = item.replace(/\n|\r\n/g,"<br/>")
// console.log(word)
// console.log(typeof (word))
this.resultTxt += word
},
后端
@RequestMapping
标志类、方法的请求路径
- value属性:是个字符串数组,数组中每个字符串是请求地址,
如 @RequestMapping( value = {“/testRequestMapping”, “/test”} ) 表示/testRequestMapping以及/test都可以访问方法testRequestMapping()
@RequestMapping( value = {"/testRequestMapping", "/test"} )
public String testRequestMapping(){
return "success";
}
- method属性:是个RequestMethod类型数组,数组中每个元素是一种请求方式
如下 请求方式get/post都可以
@RequestMapping( value = {"/testRequestMapping", "/test"}, method = {RequestMethod.GET, RequestMethod.POST} )
public String testRequestMapping(){
return "success";
}
如果请求地址与value匹配,但是不与method匹配,会报错
405 Request method ‘XXXT’ not supported
- 派生注解
- get请求的映射–>@GetMapping
- post请求的映射–>@PostMapping
- put请求的映射–>@PutMapping
- delete请求的映射–>@DeleteMapping
备注:目前浏览器只支持 get、post,不支持put、delete
- 路径参数
<a th:href="@{/testRest/1/admin}">测试路径中的占位符-->/testRest</a><br>
@RequestMapping("/testRest/{id}/{username}")
public String testRest(@PathVariable("id") String id, @PathVariable("username")String username){
System.out.println("id:"+id+",username:"+username);
return "success"; }//最终输出的内容为-->id:1,username:admin
获取参数
三种方式获取
HttpServletRequest
@RequestParam 只接受url里面的数据
@RequestBody 只接受body中数据
HttpServletRequest
封装了当前请求的请求报文对象
@RequestMapping("/testParam") public String testParam(HttpServletRequest request){
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username:"+username+",password:"+password);
return "success";
}
通过控制器方法的形参获取请求参数
形参名称和前端参数名称相同,在DispatchServlet会将名称匹配的值赋值给形参
<a th:href="@{/testParam(username='admin',password=123456)}">测试获取请求参数-- >/testParam</a><br>
@RequestMapping("/testParam")
public String testParam(String username, String password){
System.out.println("username:"+username+",password:"+password);
return "success";
}
如何传递数组?
@RequestParam
参数来自url,一般用于get请求
@RequestMapping("/list1")
public String test1(int userId) {
return "list";
}
@RequestMapping("/list2")
public String test2(@RequestParam int userId) {
return "list";
}
不加@RequestParam
- 要求前端参数和后端控制器的形参名相同
- 改参数不是非必传
加@RequestParam - 通过@RequestParam(“userId”) 或 @RequestParam(value=“userId”)使得前端参数和后端形参名称可以不一致
- 参数是必传的, 可以通过@RequestParam(required=false)设置为非必传
- @RequestParam(defaultValue = “0”)指定参数默认值
@RequestBody
@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。通常用于接收POST、DELETE等类型的请求数据,GET类型也可以适用。
application/x-www-form-urlencoded与application/json
application/x-www-form-urlencoded:
这个是表单默认的编码方式,当请求方式为get时候,浏览器用x-www-form-urlencoded的编码方式把表单数据转换成一个字串(key=value),然后把这个字串append到url后面,用?分割,加载这个新的url。 当请求方式为post时候,浏览器把表单数据封装到http body中,然后发送到server
数据以键值对形式存在,键与值使用=连接,键值对之间使用&连接。不支持非字母数字(即不支持二进制数据,二进制数据应该使用multipart/form-data代替)
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/POST
application/json
这个编码方式就是将数据转换成json格式(json字符串),所以这就是为什么HttpServletRequest拿值为null、用@RequestParam获取为null的真凶
contentType:"application/x-www-form-urlencoded;charset=utf-8"你可以通过key去取value,就不会出现HttpServletRequest拿值为null、用@RequestParam获取为null的问题了。
前端传过给后台的数据是一个对象,那我们还是使用application/json传递
,用@RequestBody
获取,然后再用map对json数据进行一个拆分存储,方标使用
关于springmvc controller 获取前端转过来的值为null的那些坑
后端向前端传输文件
response.setContentType("text/html;charset=“utf-8”); 览器会将文件解析为text文件,
response.setContentType(“application/vnd.ms-excel”); 返回文件类型为Excel表格时
如果仅设置这一项就开始向前端返回文件时,文件名则为当前发送数据的Java类+setContentType(“”)中对应的文件后缀名,所以我们还需要设置发送时的文件名称:
response.setHeader(“content-disposition”,“attachment;filename=” + fileName);
FileInputStream in = null;
ServletOutputStream out = null;
// in = new FileInputStream(picPath + "/result.png");
in = new FileInputStream("E:\\code\\experiment\\back\\formal\\data\\statisticalAnalysis\\singleRegression\\target\\6\\2022-08-22-21-05-33"+"\\result.png");
System.out.println(picPath);
response.setContentType("application/octet-stream;charset=utf-8");
response.setHeader("Content-disposition", "attachment;filename=result.png");
out = response.getOutputStream();
int len = 0;
byte[] buffer = new byte[2 * 1024];
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.flush();
if(in!=null){
in.close();
}
传递的 responseType要是blob类型responseType: ‘blob’,
然后走window.URL.createObjectURL将其返回的数据处理一下window.URL.createObjectURL(res),
将处理好的数据放在img便签里面就成功了。
// 查看实验结果
@GetMapping("/getResultPic")
public void getTestResult(HttpServletResponse response, @RequestParam(value = "picPath") String picPath) throws Exception {
System.out.println(picPath);
String fileUrl = picPath;
// 读取路径下的文件
File file = new File(fileUrl);
if (!file.exists()) {
throw new Exception("文件不存在");
}
File picFile = null;
for (File f : file.listFiles()) {
//根据路径获取文件
picFile = new File(f.getPath());
//获取文件后缀名格式
String ext = picFile.getName().substring(picFile.getName().indexOf("."));
//判断图片格式,设置相应的输出文件格式
if (ext.equals("jpg")) {
response.setContentType("image/jpeg");
} else if (ext.equals("JPG")) {
response.setContentType("image/jpeg");
} else if (ext.equals("png")) {
response.setContentType("image/png");
} else if (ext.equals("PNG")) {
response.setContentType("image/png");
}
}
//读取指定路径下面的文件
InputStream in = new FileInputStream(picFile);
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
//创建存放文件内容的数组
byte[] buff = new byte[1024];
//所读取的内容使用n来接收
int n;
//当没有读取完时,继续读取,循环
while ((n = in.read(buff)) != -1) {
//将字节数组的数据全部写入到输出流中
outputStream.write(buff, 0, n);
}
//强制将缓存区的数据进行输出
outputStream.flush();
//关流
outputStream.close();
in.close();
}
js代码里面 或者 html里面用"v-bind:“或”:属性名"绑定路径的时候使用
require('@/assets/home/imgName.png')
// 查看实验结果
@GetMapping("/getResultPic")
public void getTestResult(HttpServletResponse response, @RequestParam(value = "picPath") String picPath) throws Exception {
System.out.println(picPath);
FileInputStream in = null;
ServletOutputStream out = null;
String filePath = picPath+"/result.png";
in = new FileInputStream(filePath);
response.setContentType(MediaType.IMAGE_PNG_VALUE);
response.setHeader("Content-disposition", "attachment;filename=result.png");
IOUtils.copy(in, response.getOutputStream());
}
postman
在postman中通过post方式请求需要关注的四要素包含:请求地址(url)+请求方法(post)+请求头域(Headers)+参数
请求地址的组成:http(协议类型)+服务器地址(域名)+接口地址(存放文件路径)+请求参数(手动在params中填写时,会自动填充这里)
请求方法选:post
请求头域:选择接口文档中Content-Type类型
参数填写:填写接口文档中的参数值
原文链接:https://blog.csdn.net/weixin_49044678/article/details/117030810
form-data
等价于http请求中的content-type=multipart/form-data
,可以上传多文件,键值对。文件可以上传多个
x-www-form-urlencoded
等价于http请求中的content-type=application/x-www-from-urlencoded
会将表单内的数据转换为键值对
会隐藏url
raw
可以上传任意格式的文本,如txt, json,xml,html
binary
相当于Content-Type:application/octet-stream
只能上传二进制数据,通常上传文件,无键值对所以只能上传一个文件
传递参数的错误
Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported]
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported]
参考博客
错误的代码:
后端
@PostMapping("/testPost")
@ResponseBody
public Result testPost(@RequestBody String[] names, @RequestBody String[] age) {
// String names = request.getParameter("names");
// String age = request.getParameter("age");
System.out.println();
System.out.println(names);
System.out.println(age);
Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
return result ;
}
前端
testPost() {
let age = []
let names = []
for(let i=0; i< 10; ++i) {
age.push(i)
names.push("aaa"+i)
}
this.$axios(
{
method: 'post',
// headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: "http://localhost:8080/SingleRegression/testPost",
data:
{ "age":age, "names": names}
}
).then( res => {
console.log(res)
})
}
错误原因及解决方法:
@RequestBody注解后 ,只能解析json类型的数据,而我的前后端传递的是数组,应该无法解析数组形式。
当把参数改成非数组形式的,如下正常的字符串,可以正常解析
默认情况下,使用axios请求默认数据类型是json,而使用@requestBody注解只解析json,这里把age和names进行了封装
我后端使用两个@requestBody解析,得到的结果一样(age=12&names=zhuyuanzhang),都是封装后的
@PostMapping("/testPost")
@ResponseBody
public Result testPost(@RequestBody String names, @RequestBody String age) {
// String names = request.getParameter("names");
// String age = request.getParameter("age");
System.out.println();
//输出结果相同
System.out.println(names);// age=12&names=zhuyuanzhang
System.out.println(age);// age=12&names=zhuyuanzhang
Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
return result ;
}
前端
testPost() {
const age="12"
const names="zhuyuanzhang"
this.$axios(
{
method: 'post',
// headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: "http://localhost:8080/SingleRegression/testPost",
data: this.$qs.stringify(
{ "age":age, "names": names}
)
}
).then( res => {
console.log(res)
})
}
@PostMapping("/testPost")
@ResponseBody
// 自动封装对象,对象中的属性如age会自动赋值
// Test{names='zhuyuanzhang', age=12}
public Result testPost(@RequestBody Test test) {
Result result = new Result().setCode("200").setMsg("查询成功").setData(test);
System.out.println(test);
return result ;
}
// Test{names='null', age=0}
public Result testPost( Test test) {
Result result = new Result().setCode("200").setMsg("查询成功").setData(test);
System.out.println(test);
return result ;
}
##传递数组
<template>
<div class="single-container">
<div class="step">
<el-steps :active="0" align-center>
<!-- <el-step title="+新增实验" finish-status="success"></el-step>-->
<el-step title="导入数据" description="输入数据或者导入文件"></el-step>
<el-step title="进行回归测试" description=""></el-step>
<el-step title="结果可视化" description=""></el-step>
<el-step title="导入数据库" description="选择是否保留到数据库"></el-step>
</el-steps>
</div>
<div class="header">
<div class="left">
<el-input v-model="experimentName" placeholder="搜索实验名称" clearable prefix-icon="el-icon-search"
@keyup.enter="searchExperiment">
</el-input>
</div>
<div class="right">
<el-button type="primary" icon="el-icon-plus" @click="addExperiment">新增实验</el-button>
</div>
</div>
<!-- 进行回归测试的界面-->
<div class="test-contain" >
<el-row >
<el-col :span="12" :offset="2" style="color: #20a0ff">
<el-form label-width="350px" style="padding-top: 50px" >
<el-form-item label="数据上传方式">
<el-switch @change="uploadMethodRadioChange()" v-model="this.uploadMethodRadio"
active-color="#409EFF" inactive-color="#C0CCDA"
active-text="人工输入" inactive-text="文件上传" :active-value=true :inactive-value=false>
</el-switch>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row style="height: 100%">
<el-col :span="12" :offset="2" >
<el-form label-width="350px" style="padding-top: 50px"
v-show="this.uploadMethodRadio" :model="formData">
<el-form-item label="实验名称" >
<el-input placeholder="请输入实验名称" v-model="experimentName" ></el-input>
</el-form-item>
<el-form-item label="自变量名称">
<el-input placeholder="输入自变量名称" v-model="formData.variableName"></el-input>
</el-form-item>
<el-form-item label="因变量名称">
<el-input placeholder="输入因变量名称" v-model="formData.dependentVariableName"></el-input>
</el-form-item>
<el-form-item label="测试数据量">
<el-select placeholder="请选择测试数据量" v-model="formData.experimentDataCount"
@change ="onSelectChange">
<el-option v-for="(item) in selectCount.experimentData" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" >下一步</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row style="height: 100%">
<el-col :span="10" :offset="7" >
<el-form label-width="100px" style="padding-top: 50px" >
<el-upload v-show="!this.uploadMethodRadio"
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
multiple
:limit="3"
:on-exceed="handleExceed"
:file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
</el-form>
</el-col>
</el-row>
<!-- 表单数据选择-->
</div>
<div class="data-contain">
<el-row>
<el-form>
<el-form-iteml v-for="(item, index) in experimentDataArray" :key="index">
<el-col :span="5" :offset="6"><el-input placeholder="输入因变" ></el-input> </el-col>
<el-col :span="5" > <el-input placeholder="输名称"></el-input></el-col>
</el-form-iteml>
</el-form>
</el-row>
</div>
<!--测试历史记录列表-->
<div class="table-container" v-show="false">
<el-table :data="testRecordData" style="width: 100%">
<el-table-column prop="id" label="实验ID">
<template slot-scope="scope">
<span style="margin-left: 10px">{
{ scope.row.id }}</span>
</template>
</el-table-column>
<el-table-column prop="id" label="实验时间">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{
{ scope.row.testTime }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="实验名称">
<template slot-scope="scope">
<span style="margin-left: 10px">{
{ scope.row.testName }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="实验状态">
<template slot-scope="scope">
<el-tag v-show="scope.row.testStatus ===0 ">未开始</el-tag>
<el-tag type="success" v-show="scope.row.testStatus ===1 ">已完成</el-tag>
<el-tag type="warning" v-show="scope.row.testStatus ===2 ">进行中</el-tag>
<el-tag type="danger" v-show="scope.row.testStatus ===3 ">失败</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="300">
<template slot-scope="scope">
<el-button type="primary" plain icon="el-icon-search" size="small"
@click="openDetail(scope.row)">
查看
</el-button>
<el-popconfirm title="确定删除吗?" @onConfirm="deleteExperiment(scope.row)">
<el-button type="danger" plain icon="el-icon-delete" slot="reference" size="small">
删除
</el-button>
</el-popconfirm>
<el-button plain icon="el-icon-document" size="small" @click="outData(scope.row)">导出
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination background layout="total, prev, pager, next, jumper" :total="tableDataInfo.tableData.length"
:current-page.sync="paginationOptions.currentPage" :page-size="paginationOptions.pageSize">
</el-pagination>
</div>
</div>
<el-dialog title="一元回归实验参数" :visible.sync="formDialogVisible" width="70%" top="50px"
custom-class="form-dialog-container" @close="clearOptions">
<div class="form-dialog">
<div class="left">
<div class="experiment-name item">
<div class="label">实验名称:</div>
<div class="value">
<el-input v-model="formData.experimentName" placeholder="输入实验名称" size="small">
</el-input>
</div>
</div>
<div class="experiment-name item">
<div class="label">自变量名称:</div>
<div class="value">
<el-input v-model="formData.variableName" placeholder="输入自变量名称" size="small">
</el-input>
</div>
</div>
<div class="experiment-name item">
<div class="label">因变量名称:</div>
<div class="value">
<el-input v-model="formData.dependentVariableName" placeholder="输入因变量名称" size="small">
</el-input>
</div>
</div>
<div class="res-count item">
<div class="label">测试数据量:</div>
<div class="value">
<el-select v-model="formData.experimentDataCount" placeholder="测试数据量" size="small"
@change ="onSelectChange" >
<el-option v-for="(item) in selectCount.experimentData" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</div>
</div>
<div class="factor-level-table">
<div class="right">
<div class="top">
<div style="width: 320px">
<div style="width: 160px; float:left;"><input type="text" v-model.number="this.formData.variableName"></div>
<div style="width: 160px; float:right; "><input type="text" v-model.number="this.formData.dependentVariableName"></div>
<div style="width: 100%; height: 15px; margin: 5px; float:right;"></div>
</div>
</div>
<div class="list" v-for="(item, index) in experimentDataArray" :key="index">
<div class="list-item" v-for="(val, index) in item" :key="index">
<input type="number" v-model.number="val.value">
</div>
</div>
</div>
</div>
<div class="create-table item">
<div class="label"></div>
<div class="value">
<el-button type="primary" @click="createTable">进行一元回归
</el-button>
</div>
</div>
</div>
</div>
<!-- <span slot="footer" class="dialog-footer">-->
<!-- <el-button @click="cancel">-->
<!-- 取 消</el-button>-->
<!-- <el-button type="primary" @click="handleSure">确 定-->
<!-- </el-button>-->
<!-- </span>-->
</el-dialog>
</div>
</template>
<script>
const letterMap = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'];
export default {
data() {
return {
//用户信息
userInfo: {
userId: '1'
},
//输入上传方式
uploadMethodRadio: true,
//测试状态 0尚未开始,1进行中,2已完成 3失败'
testStatusList: [
{
type: 'success', label: '已完成'},
{
type: 'info', label: '未开始'},
{
type: 'warning', label: '失败'}
],
//测试记录表数据
testRecordData: [
{
testTime: '2022-5-9',
testName: '温度湿度一元回归',
}
],
// 搜索实验名称
experimentName: '',
// 新增弹窗visible
formDialogVisible: false,
// 实验表弹窗
experimentResultVisible: false,
//下拉列表实验数据量
selectCount: {
experimentData: 10
},
formData: {
// 实验名称
experimentName: '',
// 数据量数
experimentDataCount: 10,
// 自变量
variableCount: 1,
variableName: '自变量1',
// 因变量
dependentVariableName: '因变量'
},
//测试数据
experimentDataArray:[],
sampleData:{
},
// 实验表单数据
tableDataInfo: {
tableHeader: [
'id', '自变量', '因变量'
],
tableData: [
[
"1",
"1",
"8",
],
[
"2",
"2",
"16"
],
]
},
// 当前选择的实验数据
currentExperimentData: {
name: '',
id: '',
tableDataInfo: {
tableHeader: [],
tableData: []
}
},
// 分页配置
paginationOptions: {
// 每页条数
pageSize: 10,
currentPage: 1,
},
}
},
created() {
this.getRecordData()
},
computed: {
// 当前页的表格数据
currentPageData() {
const {
currentPage, pageSize} = this.paginationOptions;
const start = (currentPage - 1) * pageSize;
const end = (currentPage) * pageSize;
const result = this.tableDataInfo.tableData.slice(start, end)
return result
},
// // 因子映射
factorMap() {
return letterMap.map(item => {
return {
label: item }
})
},
// 因子列表
factorList() {
return this.factorMap.slice(0, Number(this.formData.experimentDataCount))
},
},
methods: {
getRecordData() {
this.$http({
method: 'get',
url: 'SingleRegression/find',
params: {
userId: this.userInfo.userId,
offset: (this.paginationOptions.currentPage - 1) * (this.paginationOptions.pageSize),
limit: this.paginationOptions.pageSize
}
}).then(res => {
if (res.data.code != 200) {
this.$message.error('出错啦')
} else {
this.testRecordData = res.data.data
// console.log(this.testRecordData)
}
})
},
uploadMethodRadioChange() {
this.uploadMethodRadio = !this.uploadMethodRadio
},
// 点击新增实验
addExperiment() {
this.formDialogVisible = true;
},
// 监听实验数据量变化
onSelectChange(val) {
const result = [];
const rowCount = this.formData.experimentDataCount;
const arrRow = this.factorList.slice(0, rowCount);
const colCount = this.formData.variableCount + 1;
const arrCol = this.factorList.slice(0, colCount);
console.log(arrRow)
for (let i = 0; i < rowCount; ++ i) {
if(!result[i]){
result[i]=[]
}
for(let j = 0; j < colCount; ++ j){
result[i].push(
{
index: arrRow[i].label + arrCol[j].label,
value: '',
}
)
}
}
this.experimentDataArray = result;
},
createTable() {
const dataRow = this.experimentDataArray.length;
const dataCol = this.formData.variableCount +1
const xData = [];
const yData = [];
for (let i = 0 ; i < dataRow ; ++ i){
for (let j = 0; j< dataCol -1 ; ++ j) {
xData.push(this.experimentDataArray[i][j].value);
}
yData.push(this.experimentDataArray[i][dataCol-1].value)
}
const allData = {
variableNameArray: [],
dependentVariableName: this.formData.dependentVariableName,
xData: xData,
yData: yData
}
this.sampleData = allData;
this.$message('正在进行测试');
console.log(this.sampleData)
},
// 清空配置
clearOptions() {
},
// 查看按钮
openDetail(row) {
// this.experimentResultVisible = true;
// this.currentExperimentData = Object.assign({}, row)
},
// 删除实验
deleteExperiment(row) {
},
// 修改后的保存
saveTable() {
},
// 导出
outData(row) {
},
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
}
}
}
</script>
<style lang='less' scoped>
.step {
width: 100%;
align-content: center;
padding: 20px;
height: auto;
}
.single-container {
width: 100%;
padding: 20px;
background: #f3f4f6;
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px;
background: #fff;
}
.table-container {
margin-top: 20px;
padding: 20px;
background: #fff;
.el-table {
height: 50vh;
overflow: auto;
/deep/ .el-button {
margin-left: 8px;
}
}
.test-contain {
display: flex;
padding: 20px;
margin-top: 50px;
background: #ffffff;
margin-bottom: 20px;
justify-content: space-between;
}
.pagination-container {
margin-top: 20px;
text-align: right;
}
}
}
</style>
<style lang="less">
.form-dialog-container {
.el-dialog__body {
paddin-top: 0;
.form-dialog {
display: flex;
.left {
flex: 0 0 50%;
.item {
display: flex;
align-items: center;
margin-top: 14px;
.label {
width: 100px;
text-align: right;
}
.value {
width: 160px;
margin-left: 20px;
}
}
.factor-level-table {
display: flex;
margin-top: 14px;
.left {
flex: 0 0 60px;
margin-left: 54px;
.top {
// border-bottom: 1px solid rgb(118, 118, 118);
margin-bottom: 14px;
}
.list {
input {
width: 60px;
}
}
}
.right {
flex: 1 1 200px;
overflow: auto;
margin-right: 10px;
.top {
margin-bottom: 14px;
}
.list {
display: flex;
.list-item {
input {
width: 160px;
}
}
}
}
}
}
.right {
flex: 1 1 50%;
max-height: 50vh;
overflow: auto;
.right-table {
.table-row {
display: flex;
.table-cell {
width: 60px;
border: 1px solid #000;
input {
width: 60px;
border: none;
border-right: 1px solid #000;
}
}
}
}
}
}
}
}
.detail-dialog-container {
.result-table {
.table-row {
display: flex;
.table-cell {
width: 60px;
border: 1px solid #000;
input {
width: 60px;
border: none;
border-right: 1px solid #000;
}
}
}
}
}
</style>