@RequestParam(value = "disable", required = false)

本文详细介绍了@RequestParam注解的使用方法,特别是如何通过设置required属性来处理请求参数为空的情况。当required设为false时,如果传入空值将报错;设为true时,则会将空值赋为null。

@RequestParam(value = "disable", required = false)

          设置false,如果传入空值会报错

           设置true,如果传入空值会赋值null

package com.joyintech.basicdata.mstquotemodelcfg.controller; import com.joyintech.basicdata.mstquotemodelcfg.service.MstQuoteModelCfgService; import com.joyintech.basicdata.mstquotemodelcfg.dao.entity.MstQuoteModelCfg; import com.psbc.pfpj.yoaf.response.RestResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** *@className MstQuoteModelCfgController *@description 债券一级投标报价模式配置 *@author 张立勃 *@date 2025/8/20 *@version 1.0 **/ @Api(tags = "债券一级投标报价模式配置") @RestController @RequestMapping(value = "/basic/mstquotemodelcfg") public class MstQuoteModelCfgController { @Resource private MstQuoteModelCfgService mstQuoteModelCfgService; @ApiOperation(value = "查看功能", notes = "查看功能") @GetMapping("/view") public RestResponse<MstQuoteModelCfg> viewById( @RequestParam(name = "id") @NotBlank(message = "id不能为空") String id, @RequestParam(name = "businesskey", required = false) String businesskey, @RequestParam(name = "businessno", required = false) String businessno) { return RestResponse.success(mstQuoteModelCfgService.viewById(id, businesskey, businessno),"查看功能成功"); } @ApiOperation(value = "新增更新功能", notes = "新增更新功能") @PostMapping("/save") public RestResponse<MstQuoteModelCfg> save( @RequestBody @NotNull(message = "MstQuoteModelCfg不能为空") MstQuoteModelCfg mstQuoteModelCfg) { return RestResponse.success(mstQuoteModelCfgService.saveData(mstQuoteModelCfg), "新增更新功能成功"); } @ApiOperation(value = "删除功能", notes = "删除功能") @PostMapping("/delete") public RestResponse<MstQuoteModelCfg> delete( @RequestBody @NotNull(message = "MstQuoteModelCfg不能为空") MstQuoteModelCfg mstQuoteModelCfg) { return RestResponse.success(mstQuoteModelCfgService.deleteData(mstQuoteModelCfg), "删除功能成功"); } } 后端代码如上:前端访问时报错{ "timestamp":1755746022491, "status":404, "error":"Not Found", "path":"/basic/mstquotemodelcfg/delete" }
08-22
<template> <div class="user-list"> <div class="search-bar"> <el-form :inline="true" :model="searchForm" class="demo-form-inline"> <el-form-item label="用户名"> <el-input v-model="searchForm.username" placeholder="请输入用户名" clearable /> </el-form-item> <el-form-item label="手机号"> <el-input v-model="searchForm.phone" placeholder="请输入手机号" clearable /> </el-form-item> <el-form-item label="用户类型"> <el-select v-model="searchForm.userType" placeholder="请选择" clearable> <el-option label="普通用户" value="normal" /> <el-option label="VIP用户" value="vip" /> <el-option label="企业用户" value="enterprise" /> </el-select> </el-form-item> <el-form-item label="状态"> <el-select v-model="searchForm.status" placeholder="请选择" clearable> <el-option label="正常" value="normal" /> <el-option label="禁用" value="disabled" /> <el-option label="待审核" value="pending" /> </el-select> </el-form-item> <el-form-item> <el-button type="primary" @click="handleSearch">查询</el-button> <el-button @click="resetSearch">重置</el-button> </el-form-item> </el-form> </div> <div class="operation-bar"> <el-button type="primary" @click="handleAdd"> <el-icon><Plus /></el-icon>新增用户 </el-button> <el-button type="danger" @click="handleBatchDelete" :disabled="!selectedUsers.length"> <el-icon><Delete /></el-icon>批量删除 </el-button> <el-button type="success" @click="handleExport"> <el-icon><Download /></el-icon>导出数据 </el-button> </div> <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange" border style="width: 100%" > <el-table-column type="selection" width="55" /> <el-table-column prop="username" label="用户名" /> <el-table-column prop="realName" label="真实姓名" /> <el-table-column prop="phone" label="手机号" /> <el-table-column prop="userType" label="用户类型"> <template #default="scope"> <el-tag :type="getUserTypeTag(scope.row.userType)"> {{ getUserTypeLabel(scope.row.userType) }} </el-tag> </template> </el-table-column> <el-table-column prop="status" label="状态"> <template #default="scope"> <el-tag :type="getStatusTag(scope.row.status)"> {{ getStatusLabel(scope.row.status) }} </el-tag> </template> </el-table-column> <el-table-column prop="createTime" label="创建时间" /> <el-table-column label="操作" width="250"> <template #default="scope"> <el-button type="primary" link @click="handleEdit(scope.row)"> 编辑 </el-button> <el-button type="success" link @click="handleViewFamily(scope.row)"> 家庭关系 </el-button> <el-button type="danger" link @click="handleDelete(scope.row)" v-if="scope.row.status !== 'disabled'" > 禁用 </el-button> <el-button type="success" link @click="handleEnable(scope.row)" v-else > 启用 </el-button> </template> </el-table-column> </el-table> <div class="pagination-container"> <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20, 50, 100]" :total="total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </div> <!-- 用户编辑对话框 --> <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增用户' : '编辑用户'" width="500px" > <el-form ref="userFormRef" :model="userForm" :rules="userRules" label-width="100px" > <el-form-item label="用户名" prop="username"> <el-input v-model="userForm.username" :disabled="dialogType === 'edit'" /> </el-form-item> <el-form-item label="真实姓名" prop="realName"> <el-input v-model="userForm.realName" /> </el-form-item> <el-form-item label="手机号" prop="phone"> <el-input v-model="userForm.phone" /> </el-form-item> <el-form-item label="用户类型" prop="userType"> <el-select v-model="userForm.userType" style="width: 100%"> <el-option label="普通用户" value="normal" /> <el-option label="VIP用户" value="vip" /> <el-option label="企业用户" value="enterprise" /> </el-select> </el-form-item> <el-form-item label="密码" prop="password" v-if="dialogType === 'add'"> <el-input v-model="userForm.password" type="password" show-password /> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="handleSubmit">确定</el-button> </span> </template> </el-dialog> </div> </template> <script setup> import { ref, reactive } from 'vue'; import { Plus, Delete, Download } from '@element-plus/icons-vue'; import { ElMessage, ElMessageBox } from 'element-plus'; import { searchUsers, addUser, updateUser, deleteUser, batchDeleteUsers, enableUser, disableUser } from '@/api/user'; // 搜索表单 const searchForm = reactive({ username: '', phone: '', userType: '', status: '' }); // 表格数据 const loading = ref(false); const userList = ref([]); const selectedUsers = ref([]); // 分页 const currentPage = ref(1); const pageSize = ref(10); const total = ref(0); // 对话框 const dialogVisible = ref(false); const dialogType = ref('add'); // 'add' 或 'edit' const userFormRef = ref(null); const userForm = reactive({ username: '', realName: '', phone: '', userType: 'normal', password: '' }); // 表单验证规则 const userRules = { username: [ { required: true, message: '请输入用户名', trigger: 'blur' }, { min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' } ], realName: [ { required: true, message: '请输入真实姓名', trigger: 'blur' } ], phone: [ { required: true, message: '请输入手机号', trigger: 'blur' }, { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' } ], userType: [ { required: true, message: '请选择用户类型', trigger: 'change' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, { min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' } ] }; // 用户类型标签 const getUserTypeTag = (type) => { const map = { normal: '', vip: 'success', enterprise: 'warning' }; return map[type]; }; const getUserTypeLabel = (type) => { const map = { normal: '普通用户', vip: 'VIP用户', enterprise: '企业用户' }; return map[type]; }; // 状态标签 const getStatusTag = (status) => { const map = { normal: 'success', disabled: 'danger', pending: 'warning' }; return map[status]; }; const getStatusLabel = (status) => { const map = { normal: '正常', disabled: '禁用', pending: '待审核' }; return map[status]; }; // 搜索 const handleSearch = async () => { loading.value = true; try { const response = await searchUsers({ ...searchForm, page: currentPage.value, pageSize: pageSize.value }); userList.value = response.data.data.records; total.value = response.data.data.total; } catch (error) { ElMessage.error('搜索失败,请稍后重试'); } finally { loading.value = false; } }; const resetSearch = () => { Object.keys(searchForm).forEach(key => { searchForm[key] = ''; }); handleSearch(); }; // 表格选择 const handleSelectionChange = (val) => { selectedUsers.value = val; }; // 分页 const handleSizeChange = (val) => { pageSize.value = val; handleSearch(); }; const handleCurrentChange = (val) => { currentPage.value = val; handleSearch(); }; // 新增用户 const handleAdd = () => { dialogType.value = 'add'; dialogVisible.value = true; Object.keys(userForm).forEach(key => { userForm[key] = ''; }); userForm.userType = 'normal'; }; // 编辑用户 const handleEdit = (row) => { dialogType.value = 'edit'; dialogVisible.value = true; Object.assign(userForm, row); }; // 提交表单 // 提交表单 const handleSubmit = () => { if (!userFormRef.value) return; userFormRef.value.validate(async (valid, fields) => { // 修改此处为 async 函数 if (valid) { try { if (dialogType.value === 'add') { await addUser(userForm); // 现在可以正常使用 await } else { await updateUser(userForm); } dialogVisible.value = false; ElMessage.success('操作成功'); handleSearch(); } catch (error) { ElMessage.error('操作失败,请稍后重试'); } } }); }; // 删除用户 const handleDelete = async (row) => { try { await ElMessageBox.confirm('确定要禁用该用户吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }); await disableUser(row.id); ElMessage.success('禁用成功'); handleSearch(); } catch (error) { if (error.name === 'CancelError') { // 用户取消操作 } else { ElMessage.error('禁用失败,请稍后重试'); } } }; // 启用用户 const handleEnable = async (row) => { try { await ElMessageBox.confirm('确定要启用该用户吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }); await enableUser(row.id); ElMessage.success('启用成功'); handleSearch(); } catch (error) { if (error.name === 'CancelError') { // 用户取消操作 } else { ElMessage.error('启用失败,请稍后重试'); } } }; // 批量删除用户 const handleBatchDelete = async () => { try { await ElMessageBox.confirm('确定要批量删除选中的用户吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }); const ids = selectedUsers.value.map(user => user.id); await batchDeleteUsers(ids); ElMessage.success('批量删除成功'); handleSearch(); } catch (error) { if (error.name === 'CancelError') { // 用户取消操作 } else { ElMessage.error('批量删除失败,请稍后重试'); } } }; // 导出数据 const handleExport = () => { // 这里可以实现导出数据的逻辑,例如生成Excel文件等 ElMessage.warning('导出数据功能待实现'); }; // 查看家庭关系 const handleViewFamily = (row) => { // 这里可以实现查看家庭关系的逻辑,例如跳转到家庭关系页面等 ElMessage.warning('查看家庭关系功能待实现'); }; </script> <style scoped> .user-list { padding: 20px; background: #fff; border-radius: 4px; } .search-bar { margin-bottom: 20px; padding: 20px; background: #f5f7fa; border-radius: 4px; } .operation-bar { margin-bottom: 20px; display: flex; gap: 10px; } .pagination-container { margin-top: 20px; display: flex; justify-content: flex-end; } :deep(.el-tag) { margin-right: 5px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } </style> import axios from 'axios' const baseURL = 'http://localhost:8080/api/home_health/user' const instance = axios.create({ baseURL, timeout: 5000 }) // 搜索用户 // 搜索用户 export const searchUsers = (params) => { return instance.get('/page', { params }) .then(response => { switch (response.status) { case 200: return response.data; case 400: throw new Error('Bad Request'); case 401: throw new Error('Unauthorized'); case 404: throw new Error('Not Found'); default: throw new Error(`Request failed with status code ${response.status}`); } }) .catch(error => { if (axios.isAxiosError(error)) { if (error.response) { console.error('Search users error:', error.response.data); } else if (error.request) { console.error('Search users error: No response received', error.request); } else { console.error('Search users error:', error.message); } } else { console.error('Search users error:', error); } throw error; }); }; // 新增用户 export const addUser = (user) => { return instance.post('/add', user); }; // 编辑用户 export const updateUser = (user) => { return instance.put('/update', user); }; // 删除用户 export const deleteUser = (id) => { return instance.delete(`/delete/${id}`); }; // 批量删除用户 export const batchDeleteUsers = (ids) => { return instance.delete('/batchDelete', { data: ids }); }; // 启用用户 export const enableUser = (id) => { // 假设这里需要更新用户状态为正常,具体根据后端逻辑调整 return instance.put('/enable', { id, status: 1 }); }; // 禁用用户 export const disableUser = (id) => { // 假设这里需要更新用户状态为禁用,具体根据后端逻辑调整 return instance.put('/disable', { id, status: 0 }); }; import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueDevTools from 'vite-plugin-vue-devtools' export default defineConfig({ plugins: [vue(), vueDevTools()], // 添加 vueDevTools 插件 server: { proxy: { '/api': { target: 'http://localhost:8080/api/home_health', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), }, }, }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) }, }, }) package com.itheima.springboot.pojo.entity; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; @Data @TableName("user") public class User implements Serializable { @TableId private Long id; private String username; // 登录账户名 private String realName; // 真实姓名 private String phone; // 手机号 @JsonIgnore // 避免密码泄露 private String password; @JsonIgnore // 避免盐值泄露 private String salt; // 密码盐值 private String userType; // 用户类型(normal/vip/enterprise) private String status; // 用户状态(normal/disabled/pending) private Integer role; // 权限级别 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date lastLoginTime; private String lastLoginIp; private String lastLoginDevice; private List<Family> families; // 家庭成员列表 // Getters and Setters // (保持原有内容不变) // Getters and Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getRole() { return role; } public void setRole(Integer role) { this.role = role; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getLastLoginTime() { return lastLoginTime; } public void setLastLoginTime(Date lastLoginTime) { this.lastLoginTime = lastLoginTime; } public String getLastLoginIp() { return lastLoginIp; } public void setLastLoginIp(String lastLoginIp) { this.lastLoginIp = lastLoginIp; } public String getLastLoginDevice() { return lastLoginDevice; } public void setLastLoginDevice(String lastLoginDevice) { this.lastLoginDevice = lastLoginDevice; } public String getRealName() { return realName; } public void setRealName(String realName) { this.realName = realName; } public List<Family> getFamilies() { return families; } public void setFamilies(List<Family> families) { this.families = families; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getUserType() { return userType; } public void setUserType(String userType) { this.userType = userType; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } } package com.itheima.springboot.controller; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.itheima.springboot.pojo.api.ApiResult; import com.itheima.springboot.pojo.dto.LoginRequest; import com.itheima.springboot.pojo.dto.LoginResponse; import com.itheima.springboot.pojo.entity.User; import com.itheima.springboot.service.UserService; import com.itheima.springboot.utils.ResultUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; import java.util.Map; @RestController @RequestMapping("/user") public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @PostMapping("/login") public ResultUtil<LoginResponse> login(@Valid @RequestBody LoginRequest request) { try { LoginResponse response = userService.login(request); return ResultUtil.success("登录成功", response); } catch (Exception e) { logger.error("登录失败: {}", e.getMessage(), e); return ResultUtil.error(e.getMessage()); } } // 新增用户 @PostMapping("/add") public ApiResult<User> addUser(@RequestBody User user) { try { boolean success = userService.save(user); if (success) { return ApiResult.success("新增成功", user); } else { return ApiResult.error("新增失败"); } } catch (Exception e) { logger.error("新增用户失败: {}", e.getMessage(), e); return ApiResult.error("新增用户时发生异常: " + e.getMessage()); } } // 删除用户 @DeleteMapping("/delete/{id}") public ApiResult<String> deleteUser(@PathVariable Long id) { try { boolean success = userService.removeById(id); if (success) { return ApiResult.success("删除成功"); } else { return ApiResult.error("删除失败"); } } catch (Exception e) { logger.error("删除用户失败: {}", e.getMessage(), e); return ApiResult.error("删除用户时发生异常: " + e.getMessage()); } } // 修改用户信息 @PutMapping("/update") public ApiResult<User> updateUser(@RequestBody User user) { try { boolean success = userService.updateById(user); if (success) { return ApiResult.success("修改成功", user); } else { return ApiResult.error("修改失败"); } } catch (Exception e) { logger.error("修改用户信息失败: {}", e.getMessage(), e); return ApiResult.error("修改用户信息时发生异常: " + e.getMessage()); } } // 查询单个用户信息 @GetMapping("/get/{id}") public ApiResult<User> getUser(@PathVariable Long id) { try { User user = userService.getById(id); if (user != null) { return ApiResult.success("查询成功", user); } else { return ApiResult.error("未找到该用户信息"); } } catch (Exception e) { logger.error("查询用户信息失败: {}", e.getMessage(), e); return ApiResult.error("查询用户信息时发生异常: " + e.getMessage()); } } // 查询所有用户信息 @GetMapping("/list") public ApiResult<List<User>> listUsers() { try { List<User> users = userService.list(); return ApiResult.success("查询成功", users); } catch (Exception e) { logger.error("查询所有用户信息失败: {}", e.getMessage(), e); return ApiResult.error("查询所有用户信息时发生异常: " + e.getMessage()); } } // 分页查询用户信息 @GetMapping("/page") public ApiResult<IPage<User>> pageUsers(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) { try { Page<User> page = new Page<>(pageNum, pageSize); IPage<User> userPage = userService.page(page, new QueryWrapper<>()); return ApiResult.success("查询成功", userPage); } catch (Exception e) { logger.error("分页查询用户信息失败: {}", e.getMessage(), e); return ApiResult.error("分页查询用户信息时发生异常: " + e.getMessage()); } } @DeleteMapping("/batchDelete") public ApiResult<String> batchDeleteUsers(@RequestBody List<Long> ids) { try { boolean success = userService.removeByIds(ids); if (success) { return ApiResult.success("批量删除成功"); } else { return ApiResult.error("批量删除失败"); } } catch (Exception e) { logger.error("批量删除用户失败: {}", e.getMessage(), e); return ApiResult.error("批量删除用户时发生异常: " + e.getMessage()); } } // 启用用户 @PutMapping("/enable") public ApiResult<String> enableUser(@RequestBody Map<String, Object> params) { Long id = Long.valueOf(params.get("id").toString()); String status = String.valueOf(Integer.valueOf(params.get("status").toString())); try { User user = userService.getById(id); user.setStatus(status); boolean success = userService.updateById(user); if (success) { return ApiResult.success("启用成功"); } else { return ApiResult.error("启用失败"); } } catch (Exception e) { logger.error("启用用户失败: {}", e.getMessage(), e); return ApiResult.error("启用用户时发生异常: " + e.getMessage()); } } // 禁用用户 @PutMapping("/disable") public ApiResult<String> disableUser(@RequestBody Map<String, Object> params) { Long id = Long.valueOf(params.get("id").toString()); String status = String.valueOf(Integer.valueOf(params.get("status").toString())); try { User user = userService.getById(id); user.setStatus(status); boolean success = userService.updateById(user); if (success) { return ApiResult.success("禁用成功"); } else { return ApiResult.error("禁用失败"); } } catch (Exception e) { logger.error("禁用用户失败: {}", e.getMessage(), e); return ApiResult.error("禁用用户时发生异常: " + e.getMessage()); } } }server: port: 8080 servlet: context-path: /api/home_health my-server: api-context-path: /api/home_health # MySQL与文件上传限制配置 spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/home_health?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai # 添加了时区设置 username: root password: 123456 mybatis-plus: configuration: map-underscore-to-camel-case: true # 开启驼峰命名转换 mapper-locations: classpath:mapper/*.xml posture: thresholds: shoulder-diff: 0.1 hunchback: 0.3
05-21
若依前后端分离框架,怎么实现上传glb文件。这是我的index.vue页面:<template> <div class="app-container"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form-item label="模型名称" prop="filename"> <el-input v-model="queryParams.filename" placeholder="请输入模型名称" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="编码" prop="productcode"> <el-input v-model="queryParams.productcode" placeholder="请输入编码" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="状态" prop="disabled"> <el-select v-model="queryParams.disabled" placeholder="全部状态" clearable style="width: 240px"> <!-- <el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />--> <el-option label="启用" :value="0"/> <el-option label="禁用" :value="1"/> </el-select> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> </el-form-item> </el-form> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:ct_modelmanage:add']" >新增</el-button> </el-col> <el-col :span="1.5"> <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['system:ct_modelmanage:edit']" >修改</el-button> </el-col> <el-col :span="1.5"> <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:ct_modelmanage:remove']" >删除</el-button> </el-col> <el-col :span="1.5"> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:ct_modelmanage:export']" >导出</el-button> </el-col> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> </el-row> <el-table v-loading="loading" :data="ct_modelmanageList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column label="模型图片" align="center" prop="fileimage" width="100"> <template slot-scope="scope"> <image-preview :src="scope.row.fileimage" :width="50" :height="50"/> </template> </el-table-column> <el-table-column label="模型名称" align="center" prop="name" /> <el-table-column label="文件名称" align="center" prop="filename" /> <el-table-column label="产品编码" align="center" prop="productcode" /> <el-table-column label="产品名称" align="center" prop="productname" /> <el-table-column label="创建时间" align="center" prop="created" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.created, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="状态" align="center" width="120" key="disabled"> <template slot-scope="scope"> <el-switch v-model="scope.row.disabled" :active-value="0" :inactive-value="1" @change="handleisabledChange(scope.row)"></el-switch> </template> </el-table-column> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200" fixed="right"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:ct_modelmanage:edit']" >修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:ct_modelmanage:remove']" >删除</el-button> </template> </el-table-column> </el-table> <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <!-- 添加或修改模型信息 对话框 --> <!-- <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>--> <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> <el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form-item label="模型名称" prop="name"> <el-input v-model="form.name" placeholder="请输入模型名称" /> </el-form-item> <el-form-item label="产品名称" prop="productname"> <el-input v-model="form.productname" placeholder="请输入产品名称" /> </el-form-item> <el-row> <el-col :span="24"> <el-form-item label="模型图片" prop="fileimage"> <!-- <image-upload v-model="form.fileimage"/>--> <ImageUpload :limit="1" ref="ImageUpload" v-model="form.fileimage"/> </el-form-item> </el-col> </el-row> <!-- <el-col :span="12">--> <!-- <el-form-item label="模型" prop="filetype">--> <!-- <file-upload v-model="form.filetype"/>--> <!-- </el-form-item>--> <!-- </el-col>--> <el-row> <el-col :span="24"> <el-form-item label="模型文件" prop="filepath"> <file-upload v-model="form.filepath" action="/common/upload" :headers="uploadHeaders" :data="{ fileType: 'model' }" :before-upload="beforeModelUpload" @onSuccess="handleFileSuccess" accept=".glb,.gltf" > <el-button type="primary">点击上传GLB/GLTF文件</el-button> <div slot="tip" class="el-upload__tip"> 支持格式: GLB/GLTF | 最大50MB </div> </file-upload> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="描述" prop="description"> <el-input v-model="form.description" type="textarea" placeholder="请输入描述" /> </el-form-item> </el-col> </el-row> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> </div> </template> <script> import { listCt_modelmanage, getCt_modelmanage, delCt_modelmanage, addCt_modelmanage, updateCt_modelmanage } from "@/api/ct/ct_modelmanage" export default { name: "Ct_modelmanage", dicts: ['sys_yes_no'], data() { return { uploadHeaders: { Authorization: 'Bearer ' + this.$store.getters.token }, // 遮罩层 loading: true, // 选中数组 ids: [], // 非单个禁用 single: true, // 非多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 模型信息表格数据 ct_modelmanageList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 查询参数 queryParams: { pageNum: 1, pageSize: 10, name: null, filename: null, productcode: null, productlevel: null, }, // 表单参数 form: { filepath: null }, // 表单校验 rules: { // 模型名称验证 name: [ { required: true, message: "模型名称不能为空", trigger: "blur" } ], //产品名称验证 productname: [ { required: true, message: "产品名称不能为空", trigger: "blur" } ], // 模型图片验证(必填 + 最多1张) fileimage: [ { required: true, message: "请上传模型图片(最多1张)", trigger: "change" }, { validator: (rule, value, callback) => { if (value && Array.isArray(value) && value.length > 1) { callback(new Error("最多上传1张图片")); } else { callback(); } }, trigger: "change" } ], filepath: [ { required: true, message: "请上传3D模型文件", trigger: "change", validator: (rule, value, callback) => { if (!value) { callback(new Error("请上传3D模型文件")); return; } else if (!value.toLowerCase().endsWith('.glb') && !value.toLowerCase().endsWith('.gltf')) { callback(new Error("只支持GLB/GLTF格式")); } else { callback(); } } } ] } } }, created() { this.getList() }, methods: { /** 查询模型信息 列表 */ getList() { this.loading = true listCt_modelmanage(this.queryParams).then(response => { this.ct_modelmanageList = response.rows this.total = response.total this.loading = false }) }, // 取消按钮 cancel() { this.open = false this.reset() }, // 表单重置 reset() { this.form = { id: null, name: null, fileimage: null, filepath: null, filename: null, filetype: null, filesize: null, description: null, products: null, productid: null, productname: null, productparentid: null, productcode: null, productlevel: null, created: null, isdelete: null, disabled: null } this.resetForm("form") }, /** 搜索按钮操作 */ handleQuery() { this.queryParams.pageNum = 1 this.getList() }, /** 重置按钮操作 */ resetQuery() { this.resetForm("queryForm") this.handleQuery() }, // 多选框选中数据 handleSelectionChange(selection) { this.ids = selection.map(item => item.id) this.single = selection.length !== 1 this.multiple = !selection.length }, /** 新增按钮操作 */ handleAdd() { this.reset() this.open = true this.title = "添加模型信息" }, /** 修改按钮操作 */ handleUpdate(row) { this.reset() const id = row.id || this.ids getCt_modelmanage(id).then(response => { this.form = response.data this.open = true this.title = "修改模型信息" }) }, /** 提交按钮 */ submitForm() { this.$refs["form"].validate(valid => { if (valid) { if (this.form.filepath && !this.form.filename) { this.form.filename = this.form.filepath.split('/').pop(); } if (this.form.id != null) { updateCt_modelmanage(this.form).then(response => { this.$modal.msgSuccess("修改成功") this.open = false this.getList() }) } else { addCt_modelmanage(this.form).then(response => { this.$modal.msgSuccess("新增成功") this.open = false this.getList() }) } } }) }, /** 删除按钮操作 */ handleDelete(row) { const ids = row.id || this.ids this.$modal.confirm('是否确认删除模型信息编号为"' + ids + '"的数据项?').then(function () { return delCt_modelmanage(ids) }).then(() => { this.getList() this.$modal.msgSuccess("删除成功") }).catch(() => { }) }, /** 导出按钮操作 */ handleExport() { this.download('system/ct_modelmanage/export', { ...this.queryParams }, `ct_modelmanage_${new Date().getTime()}.xlsx`) }, // // 文件上传前校验(专为3D模型优化) // beforeModelUpload(file) { // // 1. 校验文件类型 // const allowedExtensions = ['.glb', '.gltf']; // const extension = file.name.toLowerCase().slice( // ((file.name.lastIndexOf('.') - 1) >>> 0) + 2 // ); // // if (!allowedExtensions.includes('.' + extension)) { // this.$modal.msgError(`只支持上传GLB/GLTF格式文件,当前文件类型: ${extension}`); // return false; // } // // // 2. 校验文件大小 (50MB限制) // const maxSize = 50 * 1024 * 1024; // if (file.size > maxSize) { // const fileSize = (file.size / (1024 * 1024)).toFixed(2); // this.$modal.msgError( // `文件大小${fileSize}MB超过限制(50MB)` // ); // return false; // } // // return true; // }, // // 验证GLB文件头(可选) // async validateGlbHeader(file) { // return new Promise((resolve) => { // const reader = new FileReader(); // // reader.onload = (e) => { // try { // const header = new Uint8Array(e.target.result.slice(0, 4)); // const glbHeader = new TextDecoder().decode(header); // // if (glbHeader !== 'glTF') { // this.$modal.msgError("无效的GLB文件格式"); // resolve(false); // } else { // resolve(true); // } // } catch (error) { // this.$modal.msgError("文件读取失败"); // resolve(false); // } // }; // // reader.onerror = () => { // this.$modal.msgError("文件读取失败"); // resolve(false); // }; // // // 只读取文件前4个字节 // reader.readAsArrayBuffer(file.slice(0, 4)); // }); // }, // // 文件上传成功回调 // handleFileSuccess(response) { // this.form.filepath = response.url; // this.form.filename = response.originalFilename; // this.form.filetype = '3d-model'; // 标记为3D模型类型 // this.$modal.msgSuccess("3D模型上传成功"); // //自动设置文件类型 // const ext = this.form.filename.split('.').pop().toLowerCase(); // if (ext === 'glb' || ext === 'gltf') { // this.form.filetype = '3d-model'; // } // // this.$modal.msgSuccess("3D模型上传成功"); // // // 打印上传信息便于调试 // console.log("文件上传成功:", { // url: response.url, // filename: response.originalFilename, // size: response.size // }); // }, // 优化后的上传前校验方法 beforeModelUpload(file) { // 1. 获取文件扩展名(更可靠的方式) const extension = file.name.toLowerCase().split('.').pop(); // 2. 检查扩展名 if (!['glb', 'gltf'].includes(extension)) { this.$modal.msgError(`不支持的文件类型: ${extension},请上传GLB/GLTF格式`); return false; } // 3. 检查文件大小 const maxSizeMB = 50; const maxSizeBytes = maxSizeMB * 1024 * 1024; if (file.size > maxSizeBytes) { const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2); this.$modal.msgError(`文件大小(${fileSizeMB}MB)超过${maxSizeMB}MB限制`); return false; } // 4. 检查GLB文件头(可选但推荐) if (extension === 'glb') { return new Promise((resolve) => { const reader = new FileReader(); reader.onload = (e) => { try { // 检查前4个字节是否是'glTF' const header = new TextDecoder().decode(e.target.result.slice(0, 4)); resolve(header === 'glTF'); } catch (error) { resolve(false); } }; reader.onerror = () => resolve(false); // 只读取文件前4个字节 reader.readAsArrayBuffer(file.slice(0, 4)); }); } return true; }, // 文件上传成功回调(添加调试信息) handleFileSuccess(response) { console.log('上传响应:', response); if (response.code !== 200) { this.$modal.msgError(response.msg || "上传失败"); return; } this.form.filepath = response.url; this.form.filename = response.originalFilename; this.form.filetype = '3d-model'; this.$modal.msgSuccess("3D模型上传成功"); }, } } </script> 。这是后端代码:@Log(title = "文件上传", businessType = BusinessType.IMPORT) @PostMapping("/upload") public AjaxResult uploadFile( @RequestParam("file") MultipartFile file, @RequestParam(value = "fileType", required = false) String fileType) { try { // 1. 基本校验 if (file.isEmpty()) { return AjaxResult.error("上传文件不能为空"); } String originalFilename = file.getOriginalFilename(); long fileSize = file.getSize(); // 2. 模型文件特殊校验 if ("model".equals(fileType)) { // 支持GLB和GLTF格式 String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase(); if (!"glb".equals(extension) && !"gltf".equals(extension)) { return AjaxResult.error("模型文件必须为GLB或GLTF格式"); } // 文件大小限制(50MB) long maxSize = 50 * 1024 * 1024; if (fileSize > maxSize) { return AjaxResult.error("模型文件大小不能超过50MB"); } // 可选:GLB文件内容验证 if ("glb".equals(extension)) { byte[] header = new byte[4]; file.getInputStream().read(header); if (!"glTF".equals(new String(header, StandardCharsets.UTF_8))) { return AjaxResult.error("无效的GLB文件格式"); } } } // 3. 保存文件 String filePath = RuoYiConfig.getUploadPath(); String fileName = FileUploadUtils.upload(filePath, file); String url = serverConfig.getUrl() + fileName; // 4. 返回响应(添加更多调试信息) return AjaxResult.success("上传成功") .put("url", url) .put("fileName", fileName) .put("originalFilename", originalFilename) .put("fileSize", fileSize); } catch (Exception e) { log.error("文件上传失败", e); return AjaxResult.error("上传失败: " + e.getMessage()); } }。
06-24
<form id="fileForm" enctype="multipart/form-data" method="post" action="${ctx}/cdp/uploadCdp"> <div class="modal-content"> <div class="modal-header"> <h6 class="modal-title">File Upload</h6> <button type="button" class="close resetFile" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div class="card-body"> <table class="table table-hover table-striped formtable"> <tbody> <tr class="row col-md-12"> <td class="col-md-5 flex align-center"> Template Download: </td> <td class="col-md-7 align-center" id="gds01"> <a href="${ctx}/static/templates/FileName_LayerScan.xlsx" target="downloadFile">GDS NO Sample Template</a> <iframe style="display: none;" name="downloadFile"></iframe> </td> </tr> <tr class="row col-md-12"> <td class="col-md-5 flex align-center"> File input: </td> <td class="col-md-7 align-center"> <div class="input-group"> <input type="file" id="file" name="file" multiple=""/> <input type="hidden" name="etoUuidStr" value="${(tapeout.uuid)?if_exists}" id="mastUuidStr"> <input type="hidden" name="gdsUuid" value="" id="gdsUuid"> </div> </td> </tr> </tbody> </table> </div> </div> <div class="modal-footer col-md-12 pt-3"> <div class="col-lg-12 text-center"> <input type="button" class="btn btn-primary w-120" onclick="fileUpload()" value="Upload"/> <button type="button" class="btn btn-default w-120 ml-4 resetFile" data-dismiss="modal" id="closeFileUpload">Close </button> </div> </div> </div> <!-- /.modal-content --> </form> </div> <!-- /.modal-dialog --> </div> </div> </section> </div> <@js> <script> function exportDatabaseInfoFileList() { var OpcFileListTable = $('#gdsFileOpcTable').bootstrapTable('getData'); if (OpcFileListTable.length == 0) { layer.alert("No data for export !", {icon: 2}); return; } else { disableButton(); document.forms['layoutForm'].action = "${ctx}/tkdms/exportGdsFileOpcTable?uuid=" + $("#layoutUuid").val() + "&type=DatabaseInfo"; document.forms['layoutForm'].target = "_blank"; document.forms['layoutForm'].method = "post"; document.forms['layoutForm'].submit(); unDisableButton(); } } function fileUpload() { // 2. 创建FormData对象 var formData = new FormData($("#fileForm")[0]); // 添加额外参数(根据之前的示例) formData.append('fileType', 'DatabaseInfo'); formData.append('mastUuidStr', $("#gdsUuid").val()); var url = '${ctx}/tkdms/uploadOriginalFile'; // 4. 发送AJAX请求(修正data属性) $.ajax({ type: "POST", url: url, data: formData, // 将file改为data cache: false, processData: false, // 不处理数据 contentType: false, // 不设置Content-Type,由浏览器自动设置 beforeSend: function () { disableButton(); loadingFLag = loadingLayCommon(); }, complete: function () { // closeLayLoading(loadingFLag); }, success: function(data) { if (xhr.success) { layer.alert("Upload Success!", { icon: 6, time: 500, end: function () { $('#file').val(""); $('#closeFileUpload').click(); location.reload(); } }); unDisableButton(); } else { layer.alert(xhr.logMessage, { icon: 2, area: ['600px', ''] }); unDisableButton(); } // 处理成功 }, error: function() { // 处理错误 // unDisableButton(); } }); } fileUpload@PostMapping("/uploadOriginalFile") @ResponseBody public ResultForm uploadOriginalFile( MultipartFile file, String mastUuidStr,String fileType) { file 为啥我这个为空
最新发布
12-26
<template> <div class="book-management-container"> <!-- 搜索和操作区域 --> <div class="search-operation-bar"> <el-input v-model="title" placeholder="请输入书名" suffix-icon="el-icon-search" style="width: 200px" @keyup.enter.native="loadPost" ></el-input> <el-button type="success" style="margin-left: 5px" @click="loadPost" >查询</el-button > <el-button type="primary" style="float: right" @click="add" >+添加图书</el-button > </div> <!-- 数据表格区域 --> <div class="table-container"> <el-table :data="tableData" :header-cell-style="{ background: '#f2f5fc', color: '#555' }" border height="100%" v-loading="loading" > <el-table-column prop="id" label="ID" width="80"></el-table-column> <el-table-column prop="title" label="书名" width="180"></el-table-column> <el-table-column prop="author" label="作者" width="120"></el-table-column> <el-table-column prop="publishDate" label="发布时间" width="120"></el-table-column> <el-table-column prop="createTime" label="创建时间" width="120"></el-table-column> <el-table-column prop="price" label="价格" width="100"> <template slot-scope="scope"> {{ scope.row.price }} 元 </template> </el-table-column> <el-table-column prop="categoryId" label="分类" width="120"> <template slot-scope="scope"> <el-tag :type="scope.row.categoryId === 1 ? 'primary' : 'success'" disable-transitions >{{ scope.row.categoryId === 1 ? "文学" : "科技" }}</el-tag > </template> </el-table-column> <el-table-column label="操作" width="180" fixed="right"> <template slot-scope="scope"> <el-button size="small" type="primary" @click="mod(scope.row)" >编辑</el-button > <el-popconfirm title="确定删除吗?" @confirm="del(scope.row.id)" style="margin-left: 5px" > <el-button slot="reference" size="small" type="danger" >删除</el-button > </el-popconfirm> </template> </el-table-column> </el-table> </div> <!-- 分页控件 --> <div class="pagination-container"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page" :page-sizes="[5, 10, 20, 50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total" > </el-pagination> </div> <!-- 添加/编辑对话框 --> <el-dialog :title="form.id ? '编辑图书' : '添加图书'" :visible.sync="centerDialogVisible" width="500px" center > <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="书名" prop="title"> <el-input v-model="form.title" placeholder="请输入书名"></el-input> </el-form-item> <el-form-item label="作者" prop="author"> <el-input v-model="form.author" placeholder="请输入作者"></el-input> </el-form-item> <el-form-item label="价格" prop="price"> <el-input v-model="form.price" placeholder="请输入价格" type="number" ></el-input> </el-form-item> <el-form-item label="分类" prop="categoryId"> <el-select v-model="form.categoryId" placeholder="请选择分类"> <el-option label="文学" :value="1"></el-option> <el-option label="科技" :value="2"></el-option> </el-select> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="centerDialogVisible = false">取 消</el-button> <el-button type="primary" @click="save">确 定</el-button> </span> </el-dialog> </div> </template> <script> import axios from "axios"; export default { name: "BookManagement", data() { return { tableData: [], title: "", pageSize: 5, page: 1, total: 0, loading: false, centerDialogVisible: false, form: { id: "", title: "", author: "", price: "", categoryId: "", }, }; }, methods: { resetForm() { this.form = { id: "", title: "", author: "", price: "", categoryId: "", }; }, del() { this.$confirm("确定删除这本书吗?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { // 这里应该是删除API调用 this.$message.success("删除成功"); this.loadPost(); }) .catch(() => { this.$message.info("已取消删除"); }); }, mod(row) { this.form = { ...row }; this.centerDialogVisible = true; }, doSave() { // 模拟新增API调用 setTimeout(() => { this.$message.success("新增成功"); this.centerDialogVisible = false; this.loadPost(); }, 500); }, doMod() { // 模拟修改API调用 setTimeout(() => { this.$message.success("修改成功"); this.centerDialogVisible = false; this.loadPost(); }, 500); }, save() { if (this.form.id) { this.doMod(); } else { this.doSave(); } }, add() { this.centerDialogVisible = true; this.$nextTick(() => { this.resetForm(); }); }, handleSizeChange(val) { this.pageSize = val; this.page = 1; this.loadPost(); }, handleCurrentChange(val) { this.page = val; this.loadPost(); }, loadPost() { axios .get("/book/list", { params: { page: this.page, pageSize: this.pageSize, title: this.title, }, }) .then((res) => { console.log(res); if (res.data.code === 1) { this.tableData = res.data.data.records; this.total = res.data.data.total; } else { this.$message.error("获取数据失败"); } this.loading = false; }) .catch((error) => { console.error(error); this.$message.error("请求失败,请检查网络连接"); this.loading = false; }); }, }, mounted() { this.loadPost(); }, }; </script> <style scoped> .book-management-container { padding: 20px; background-color: #fff; border-radius: 5px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); min-height: 500px; display: flex; flex-direction: column; } .search-operation-bar { margin-bottom: 20px; display: flex; align-items: center; } .table-container { flex: 1; min-height: 300px; margin-bottom: 20px; } .pagination-container { text-align: right; } /* 响应式设计 */ @media (max-width: 768px) { .search-operation-bar { flex-direction: column; align-items: stretch; } .search-operation-bar .el-input { margin-bottom: 10px; } .search-operation-bar .el-button { margin-left: 0; margin-bottom: 10px; } } </style> 这是我的前端代码,然后这是执行了分页查询之后控制台返回的数据:{ "code": 1, "msg": null, "data": { "total": 2, "records": [ { "id": 1, "title": "西游记", "author": "吴承恩", "price": 10, "categoryId": 1, "publishDate": "2025-09-05", "createTime": "2025-09-05" }, { "id": 2, "title": "爱", "author": "哈哈", "price": 10, "categoryId": 2, "publishDate": "2025-09-05", "createTime": "2025-09-05" } ] } } 但是呢,前端页面展示不出分页的数据,这是为什么呢,帮我解决一下吧 给我修改后的完整代码
09-07
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值