ruoyi vue v-hasPermi

时间: 2025-04-16 07:14:23 AIGC 浏览: 109
### RuoYi Vue `v-hasPermi` 指令详解 #### 使用说明 `v-hasPermi` 是用于权限控制的自定义指令,在前端实现基于角色或权限码的功能显示逻辑。通过该指令可以动态判断当前用户是否有特定权限来决定是否渲染某些组件或DOM元素。 此指令通常应用于按钮、菜单项以及其他需要根据用户权限进行隐藏或展示的内容上[^1]。 #### 示例代码 下面是一个简单的例子,展示了如何在Vue模板中使用 `v-hasPermi` 来控制按钮可见性: ```html <template> <!-- 只有当用户的权限列表包含 'system:user:add' 才会渲染这个按钮 --> <el-button type="primary" v-hasPermi="'system:user:add'" @click="handleAddUser"> 添加用户 </el-button> <!-- 同样适用于其他类型的HTML标签 --> <div v-hasPermi="'system:user:view'">仅管理员可查看</div> </template> ``` 为了使上述功能生效,还需要确保已经在项目的入口文件(如 main.js 或者 permission.js 中)注册了这条指令: ```javascript import { createApp } from "vue"; import App from "./App.vue"; // 注册全局指令 const app = createApp(App); app.directive('hasPermi', { mounted(el, binding) { const permissions = store.getters.permissions; // 假设从Vuex获取权限数据 if (!permissions.includes(binding.value)) { el.parentNode && el.parentNode.removeChild(el); // 如果没有对应权限,则移除节点 } }, }); ``` 这段JavaScript代码实现了对指定权限字符串(`binding.value`)与用户实际拥有的权限集合之间的对比验证过程,并据此调整视图结构。 #### 主要作用 - **增强安全性**: 防止未经授权访问敏感操作; - **提升用户体验**: 减少不必要的UI干扰,只向用户提供其有权使用的选项; - **简化业务逻辑处理**: 将权限校验工作交给框架本身完成,减少开发者手动编写条件语句的工作量; #### 解决方案 如果遇到无法正常工作的 `v-hasPermi` 指令问题时,建议按照以下思路排查原因并解决问题: - 确认 Vuex Store 已经正确加载了用户的权限信息; - 检查应用启动过程中是否成功初始化了 `v-hasPermi` 自定义指令; - 审核 HTML 结构中的语法错误以及拼写失误; - 对比服务器返回的实际权限编码格式同前端预期的一致性;
阅读全文

相关推荐

<template> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form-item label="姓名" prop="name"> <el-input v-model="queryParams.name" placeholder="请输入姓名" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model="queryParams.age" placeholder="请输入年龄" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="用车开始时间" prop="carUseStartTime"> <el-date-picker clearable v-model="queryParams.carUseStartTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车开始时间"> </el-date-picker> </el-form-item> <el-form-item label="用车结束时间" prop="carUseEndTime"> <el-date-picker clearable v-model="queryParams.carUseEndTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车结束时间"> </el-date-picker> </el-form-item> <el-form-item label="创建时间" prop="createdAt"> <el-date-picker clearable v-model="queryParams.createdAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择创建时间"> </el-date-picker> </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:car: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:car: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:car: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:car:export']" >导出</el-button> </el-col> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> </el-row> <el-table v-loading="loading" :data="carList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column label="${comment}" align="center" prop="id" /> <el-table-column label="姓名" align="center" prop="name" /> <el-table-column label="年龄" align="center" prop="age" /> <el-table-column label="用车开始时间" align="center" prop="carUseStartTime" width="180"> <template slot-scope="scope"> {{ parseTime(scope.row.carUseStartTime, '{y}-{m}-{d}') }} </template> </el-table-column> <el-table-column label="用车结束时间" align="center" prop="carUseEndTime" width="180"> <template slot-scope="scope"> {{ parseTime(scope.row.carUseEndTime, '{y}-{m}-{d}') }} </template> </el-table-column> <el-table-column label="创建时间" align="center" prop="createdAt" width="180"> <template slot-scope="scope"> {{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }} </template> </el-table-column> <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:car:edit']" >修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:car:remove']" >删除</el-button> </template> </el-table-column> </el-table> 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form-item label="姓名" prop="name"> <el-input v-model="form.name" placeholder="请输入姓名" /> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model="form.age" placeholder="请输入年龄" /> </el-form-item> <el-form-item label="用车开始时间" prop="carUseStartTime"> <el-date-picker clearable v-model="form.carUseStartTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车开始时间"> </el-date-picker> </el-form-item> <el-form-item label="用车结束时间" prop="carUseEndTime"> <el-date-picker clearable v-model="form.carUseEndTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车结束时间"> </el-date-picker> </el-form-item> <el-form-item label="创建时间" prop="createdAt"> <el-date-picker clearable v-model="form.createdAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择创建时间"> </el-date-picker> </el-form-item> </el-form> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </el-dialog> </template> <script> import { listCar, getCar, delCar, addCar, updateCar } from "@/api/system/car" export default { name: "Car", data() { return { // 遮罩层 loading: true, // 选中数组 ids: [], // 非单个禁用 single: true, // 非多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 用户用车信息表格数据 carList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 查询参数 queryParams: { pageNum: 1, pageSize: 10, name: null, age: null, carUseStartTime: null, carUseEndTime: null, createdAt: null }, // 表单参数 form: {}, // 表单校验 rules: { name: [ { required: true, message: "姓名不能为空", trigger: "blur" } ], age: [ { required: true, message: "年龄不能为空", trigger: "blur" } ], carUseStartTime: [ { required: true, message: "用车开始时间不能为空", trigger: "blur" } ], carUseEndTime: [ { required: true, message: "用车结束时间不能为空", trigger: "blur" } ], } } }, created() { this.getList() }, methods: { /** 查询用户用车信息列表 */ getList() { this.loading = true listCar(this.queryParams).then(response => { this.carList = response.rows this.total = response.total this.loading = false }) }, // 取消按钮 cancel() { this.open = false this.reset() }, // 表单重置 reset() { this.form = { id: null, name: null, age: null, carUseStartTime: null, carUseEndTime: null, createdAt: 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 getCar(id).then(response => { this.form = response.data this.open = true this.title = "修改用户用车信息" }) }, /** 提交按钮 */ submitForm() { this.$refs["form"].validate(valid => { if (valid) { if (this.form.id != null) { updateCar(this.form).then(response => { this.$modal.msgSuccess("修改成功") this.open = false this.getList() }) } else { addCar(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 delCar(ids) }).then(() => { this.getList() this.$modal.msgSuccess("删除成功") }).catch(() => {}) }, /** 导出按钮操作 */ handleExport() { this.download('system/car/export', { ...this.queryParams }, car_${new Date().getTime()}.xlsx) } } } </script> 生成增删改查的文件

package com.zzyl.nursing.controller; import java.util.List; import javax.servlet.http.HttpServletResponse; import com.zzyl.common.core.domain.R; import com.zzyl.nursing.vo.NursingProjectVo; import org.springframework.security.access.prepost.PreAuthorize; 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.PutMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.zzyl.common.annotation.Log; import com.zzyl.common.core.controller.BaseController; import com.zzyl.common.core.domain.AjaxResult; import com.zzyl.common.enums.BusinessType; import com.zzyl.nursing.domain.NursingProject; import com.zzyl.nursing.service.INursingProjectService; import com.zzyl.common.utils.poi.ExcelUtil; import com.zzyl.common.core.page.TableDataInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiImplicitParam; /** * 护理项目Controller * * @author ruoyi * @date 2025-08-07 */ @RestController @RequestMapping("/nursing/project") @Api(tags = "护理项目管理", description = "护理项目相关的操作接口") public class NursingProjectController extends BaseController { @Autowired private INursingProjectService nursingProjectService; /** * 获取所有护理计划 * @return */ @GetMapping("/all") @ApiOperation("获取所有护理计划") public AjaxResult all() { List<NursingProjectVo> list = nursingProjectService.listAll(); return success(list); } /** * 查询护理项目列表 */ @PreAuthorize("@ss.hasPermi('nursing:project:list')") @GetMapping("/list") @ApiOperation(value = "查询护理项目列表", notes = "根据条件查询护理项目列表信息") public TableDataInfo> list( @ApiParam(name = "nursingProject", value = "护理项目查询条件", required = false) NursingProject nursingProject) { startPage(); List<NursingProject> list = nursingProjectService.selectNursingProjectList(nursingProject); return getDataTable(list); } /** * 导出护理项目列表 */ @PreAuthorize("@ss.hasPermi('nursing:project:export')") @Log(title = "护理项目", businessType = BusinessType.EXPORT) @PostMapping("/export") @ApiOperation(value = "导出护理项目列表", notes = "将护理项目数据导出为Excel文件") public void export( @ApiParam(name = "response", value = "HttpServletResponse对象", required = true) HttpServletResponse response, @ApiParam(name = "nursingProject", value = "护理项目查询条件", required = false) NursingProject nursingProject) { List<NursingProject> list = nursingProjectService.selectNursingProjectList(nursingProject); ExcelUtil<NursingProject> util = new ExcelUtil<NursingProject>(NursingProject.class); util.exportExcel(response, list, "护理项目数据"); } /** * 获取护理项目详细信息 */ @PreAuthorize("@ss.hasPermi('nursing:project:query')") @GetMapping(value = "/{id}") @ApiOperation(value = "获取护理项目详情", notes = "根据ID获取护理项目的详细信息") @ApiImplicitParam(name = "id", value = "护理项目ID", required = true, dataType = "Long", paramType = "path") public R<NursingProject> getInfo( @ApiParam(name = "id", value = "护理项目ID", required = true) @PathVariable("id") Long id) { return R.ok(nursingProjectService.selectNursingProjectById(id)); } /** * 新增护理项目 */ @PreAuthorize("@ss.hasPermi('nursing:project:add')") @Log(title = "护理项目", businessType = BusinessType.INSERT) @PostMapping @ApiOperation(value = "新增护理项目", notes = "添加一个新的护理项目信息") public AjaxResult add( @ApiParam(name = "nursingProject", value = "护理项目信息", required = true) @RequestBody NursingProject nursingProject) { return toAjax(nursingProjectService.insertNursingProject(nursingProject)); } /** * 修改护理项目 */ @PreAuthorize("@ss.hasPermi('nursing:project:edit')") @Log(title = "护理项目", businessType = BusinessType.UPDATE) @PutMapping @ApiOperation(value = "修改护理项目", notes = "更新已有的护理项目信息") public AjaxResult edit( @ApiParam(name = "nursingProject", value = "护理项目信息", required = true) @RequestBody NursingProject nursingProject) { return toAjax(nursingProjectService.updateNursingProject(nursingProject)); } /** * 删除护理项目 */ @PreAuthorize("@ss.hasPermi('nursing:project:remove')") @Log(title = "护理项目", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") @ApiOperation(value = "删除护理项目", notes = "根据ID批量删除护理项目信息") @ApiImplicitParam(name = "ids", value = "护理项目ID数组", required = true, dataType = "Long[]", paramType = "path") public AjaxResult remove( @ApiParam(name = "ids", value = "护理项目ID数组", required = true) @PathVariable Long[] ids) { return toAjax(nursingProjectService.deleteNursingProjectByIds(ids)); } } package com.zzyl.nursing.domain; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.zzyl.common.annotation.Excel; import com.zzyl.common.core.domain.BaseEntity; /** * 护理项目对象 nursing_project * * @author ruoyi * @date 2025-08-07 */ @ApiModel(description = "护理项目实体") public class NursingProject extends BaseEntity { private static final long serialVersionUID = 1L; /** 编号 */ @ApiModelProperty(value = "编号") private Long id; /** 名称 */ @Excel(name = "名称") @ApiModelProperty(value = "名称") private String name; /** 排序号 */ @Excel(name = "排序号") @ApiModelProperty(value = "排序号") private Integer orderNo; /** 单位 */ @Excel(name = "单位") @ApiModelProperty(value = "单位") private String unit; /** 价格 */ @Excel(name = "价格") @ApiModelProperty(value = "价格") private Double price; /** 图片 */ @Excel(name = "图片") @ApiModelProperty(value = "图片URL") private String image; /** 护理要求 */ @Excel(name = "护理要求") @ApiModelProperty(value = "护理要求") private String nursingRequirement; /** 状态(0:禁用,1:启用) */ @Excel(name = "状态", readConverterExp = "0=:禁用,1:启用") @ApiModelProperty(value = "状态(0:禁用,1:启用)") private Integer status; public void setId(Long id) { this.id = id; } public Long getId() { return id; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setOrderNo(Integer orderNo) { this.orderNo = orderNo; } public Integer getOrderNo() { return orderNo; } public void setUnit(String unit) { this.unit = unit; } public String getUnit() { return unit; } public void setPrice(Double price) { this.price = price; } public Double getPrice() { return price; } public void setImage(String image) { this.image = image; } public String getImage() { return image; } public void setNursingRequirement(String nursingRequirement) { this.nursingRequirement = nursingRequirement; } public String getNursingRequirement() { return nursingRequirement; } public void setStatus(Integer status) { this.status = status; } public Integer getStatus() { return status; } @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("id", getId()) .append("name", getName()) .append("orderNo", getOrderNo()) .append("unit", getUnit()) .append("price", getPrice()) .append("image", getImage()) .append("nursingRequirement", getNursingRequirement()) .append("status", getStatus()) .append("createBy", getCreateBy()) .append("updateBy", getUpdateBy()) .append("remark", getRemark()) .append("createTime", getCreateTime()) .append("updateTime", getUpdateTime()) .toString(); } } package com.zzyl.plan.controller; import java.util.List; import javax.servlet.http.HttpServletResponse; import com.zzyl.nursing.dto.NursingPlanDto; import org.springframework.security.access.prepost.PreAuthorize; 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.PutMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.zzyl.common.annotation.Log; import com.zzyl.common.core.controller.BaseController; import com.zzyl.common.core.domain.AjaxResult; import com.zzyl.common.enums.BusinessType; import com.zzyl.plan.domain.NursingPlan; import com.zzyl.plan.service.INursingPlanService; import com.zzyl.common.utils.poi.ExcelUtil; import com.zzyl.common.core.page.TableDataInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; /** * 护理计划Controller * * @author ruoyi * @date 2025-08-07 */ @Api(tags = "护理计划管理") @RestController @RequestMapping("/nursing/plan") public class NursingPlanController extends BaseController { @Autowired private INursingPlanService nursingPlanService; /** * 查询护理计划列表 */ @ApiOperation("查询护理计划列表") @PreAuthorize("@ss.hasPermi('nursing:plan:list')") @GetMapping("/list") public TableDataInfo list( @ApiParam("护理计划查询参数") NursingPlan nursingPlan) { startPage(); List<NursingPlan> list = nursingPlanService.selectNursingPlanList(nursingPlan); return getDataTable(list); } /** * 导出护理计划列表 */ @ApiOperation("导出护理计划列表") @PreAuthorize("@ss.hasPermi('nursing:plan:export')") @Log(title = "护理计划", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export( @ApiParam("HTTP响应对象") HttpServletResponse response, @ApiParam("护理计划查询参数") NursingPlan nursingPlan) { List<NursingPlan> list = nursingPlanService.selectNursingPlanList(nursingPlan); ExcelUtil<NursingPlan> util = new ExcelUtil<NursingPlan>(NursingPlan.class); util.exportExcel(response, list, "护理计划数据"); } /** * 获取护理计划详细信息 */ @ApiOperation("获取护理计划详细信息") @PreAuthorize("@ss.hasPermi('nursing:plan:query')") @GetMapping(value = "/{id}") public AjaxResult getInfo( @ApiParam("护理计划ID") @PathVariable("id") Long id) { return success(nursingPlanService.selectNursingPlanById(id)); } /** * 新增护理计划 */ @ApiOperation("新增护理计划") @PreAuthorize("@ss.hasPermi('nursing:plan:add')") @Log(title = "护理计划", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add( @ApiParam("护理计划对象") @RequestBody NursingPlanDto dto) { return toAjax(nursingPlanService.insertNursingPlan(dto)); } /** * 修改护理计划 */ @ApiOperation("修改护理计划") @PreAuthorize("@ss.hasPermi('nursing:plan:edit')") @Log(title = "护理计划", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit( @ApiParam("护理计划对象") @RequestBody NursingPlan nursingPlan) { return toAjax(nursingPlanService.updateNursingPlan(nursingPlan)); } /** * 删除护理计划 */ @ApiOperation("删除护理计划") @PreAuthorize("@ss.hasPermi('nursing:plan:remove')") @Log(title = "护理计划", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public AjaxResult remove( @ApiParam("护理计划ID数组") @PathVariable Long[] ids) { return toAjax(nursingPlanService.deleteNursingPlanByIds(ids)); } } <template> <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px"> <el-form-item label="护理项目名称" prop="name"> <el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="状态" prop="status"> <el-select v-model="queryParams.status" placeholder="请选择" clearable> <el-option v-for="item in nursing_project_status" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button icon="Refresh" @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="Plus" @click="handleAdd" v-hasPermi="['nursing:project:add']" >新增</el-button> </el-col> <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> </el-row> <el-table v-loading="loading" :data="projectList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column label="序号" align="center" type="index" width="70" /> <el-table-column label="护理图片" align="center" prop="image" width="100"> <template #default="scope"> <image-preview :src="scope.row.image" :width="50" :height="50"/> </template> </el-table-column> <el-table-column label="护理项目名称" align="center" prop="name" /> <el-table-column label="价格(元)" align="center" prop="price" /> <el-table-column label="单位" align="center" prop="unit" /> <el-table-column label="排序" align="center" prop="orderNo" /> <el-table-column label="创建人" align="center" prop="createBy" /> <el-table-column label="创建时间" align="center" prop="createTime" width="180" /> <el-table-column label="状态" align="center" prop="status"> <template #default="scope"> <el-tag :type="scope.row.status === 1 ? 'success' : 'info'">{{ scope.row.status === 1 ? '启用' : '禁用' }}</el-tag> </template> </el-table-column> <el-table-column label="操作" width="200" fixed="right" align="center" class-name="small-padding fixed-width"> <template #default="scope"> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['nursing:project:edit']">修改</el-button> <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['nursing:project:remove']">删除</el-button> <el-button link type="primary" :icon="scope.row.status == 0 ? 'Lock' : 'Unlock'" @click="handleEnable(scope.row)" >{{ scope.row.status === 1 ? '禁用' : '启用' }}</el-button> </template> </el-table-column> </el-table> 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> <el-dialog :title="title" v-model="open" width="500px" append-to-body> <el-form ref="projectRef" :model="form" :rules="rules" label-width="120px"> <el-form-item label="护理项目名称" prop="name"> <el-input v-model="form.name" placeholder="请输入名称" :maxlength="10" show-word-limit /> </el-form-item> <el-form-item label="价格" prop="price"> <el-input v-model="form.price" placeholder="请输入价格" @input="validatePrice" /> </el-form-item> <el-form-item label="单位" prop="unit"> <el-input v-model="form.unit" placeholder="请输入单位" :maxlength="5" show-word-limit /> </el-form-item> <el-form-item label="排序号" prop="orderNo"> <el-input-number v-model="form.orderNo" placeholder="请输入" :min="1" :max="999999" controls-position="right" /> </el-form-item> <el-form-item label="状态" prop="status"> <el-radio-group v-model="form.status"> <el-radio v-for="dict in nursing_project_status" :key="dict.value" :label="dict.value" > {{ dict.label }} </el-radio> </el-radio-group> </el-form-item> <el-form-item label="图片" prop="image"> <image-upload v-model="form.image"/> </el-form-item> <el-form-item label="护理要求" prop="nursingRequirement"> <el-input v-model="form.nursingRequirement" placeholder="请输入护理要求" type="textarea" :maxlength="50" show-word-limit :autosize="{ minRows: 2, maxRows: 4 }" /> </el-form-item> </el-form> <template #footer> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </template> </el-dialog> </template> <script setup name="Project"> import { listProject, getProject, delProject, addProject, updateProject } from "@/api/nursing/project"; import { ref } from "vue"; const { proxy } = getCurrentInstance(); const projectList = ref([]); const open = ref(false); const loading = ref(true); const showSearch = ref(true); const ids = ref([]); const single = ref(true); const multiple = ref(true); const total = ref(0); const title = ref(""); //引用数据字典 const dictResult = proxy.useDict("nursing_project_status"); const nursing_project_status = dictResult?.nursing_project_status || []; /* const options = ref([ { value: 1, label: "启用" }, { value: 0, label: "禁用" } ]); */ //禁用或启用 const handleEnable = (row) => { // 获取状态 const status = row.status === 1 ? 0 : 1; //弹窗提示,并发送请求 proxy.$modal.confirm('确认要' + (status === 1 ? "启用" : "禁用") + row.name + '护理项目吗?').then(function () { return updateProject({ id: row.id, status: status }); }).then(() => { proxy.$modal.msgSuccess(status === 1 ? "启用成功" : "禁用成功"); getList(); }).catch(function () { row.status = row.status === 1 ? 0 : 1; }) } /** * 价格输入验证 * @description 限制价格输入格式,只允许数字和小数点,最多两位小数 */ function validatePrice(value) { // 保留两位小数 let price = value.toString(); if (price.includes('.')) { const parts = price.split('.'); if (parts[1].length > 2) { form.value.price = parts[0] + '.' + parts[1].substring(0, 2); } } } const data = reactive({ form: {}, queryParams: { pageNum: 1, pageSize: 10, name: null, status: null, }, rules: { name: [ { required: true, message: "护理项目名称不能为空", trigger: "blur" }, { min: 1, max: 10, message: "护理项目名称长度不能超过10个字符", trigger: "blur" } ], price: [ { required: true, message: "价格不能为空", trigger: "blur" }, { pattern: /^([0-9]\d*|0)(\.\d{1,2})?$/, message: "请输入正确的金额格式,最多两位小数", trigger: "blur" } ], unit: [ { required: true, message: "单位不能为空", trigger: "blur" }, { min: 1, max: 5, message: "单位长度不能超过5个字符", trigger: "blur" } ], orderNo: [ { required: true, message: "排序号不能为空", trigger: "blur" }, { type: "number", message: "排序号必须为数字值", trigger: "blur" } ], status: [ { required: true, message: "状态不能为空", trigger: "change" } ], image: [ { required: true, message: "图片不能为空", trigger: "change" } ], nursingRequirement: [ { required: true, message: "护理要求不能为空", trigger: "blur" }, { min: 1, max: 50, message: "护理要求长度不能超过50个字符", trigger: "blur" } ] } }); const { queryParams, form, rules } = toRefs(data); /** * 查询护理项目列表 * @description 获取护理项目数据并更新到页面中 */ function getList() { loading.value = true; listProject(queryParams.value).then(response => { projectList.value = response.rows; total.value = response.total; loading.value = false; }); } /** * 取消按钮操作 * @description 关闭弹窗并重置表单 */ function cancel() { open.value = false; reset(); } /** * 表单重置 * @description 将表单数据恢复为初始状态,并清空校验结果 */ function reset() { form.value = { id: null, name: null, orderNo: 1, unit: null, price: null, image: null, nursingRequirement: null, status: 1, // 默认启用状态 createBy: null, updateBy: null, remark: null, createTime: null, updateTime: null }; proxy.resetForm("projectRef"); } /** * 搜索按钮操作 * @description 触发查询操作,将页码重置为第一页 */ function handleQuery() { queryParams.value.pageNum = 1; getList(); } /** * 重置按钮操作 * @description 重置搜索条件并重新加载数据 */ function resetQuery() { proxy.resetForm("queryRef"); handleQuery(); } /** * 多选框选中数据处理 * @param {Array} selection - 当前选中的行数据数组 * @description 更新选中项ID列表,并控制修改/删除按钮的可用性 */ function handleSelectionChange(selection) { ids.value = selection.map(item => item.id); single.value = selection.length != 1; multiple.value = !selection.length; } /** * 新增按钮操作 * @description 打开新增护理项目的弹窗 */ function handleAdd() { reset(); open.value = true; title.value = "添加护理项目"; } /** * 修改按钮操作 * @param {Object} row - 要修改的数据行对象(可选) * @description 根据传入的行数据或选中ID获取详细信息并打开编辑弹窗 */ function handleUpdate(row) { reset(); const _id = row.id || ids.value getProject(_id).then(response => { form.value = response.data; open.value = true; title.value = "修改护理项目"; }); } /** * 提交按钮操作 * @description 验证表单并根据是否有ID决定是新增还是修改操作 */ function submitForm() { proxy.$refs["projectRef"].validate(valid => { if (valid) { if (form.value.id != null) { updateProject(form.value).then(response => { proxy.$modal.msgSuccess("修改成功"); open.value = false; getList(); }); } else { addProject(form.value).then(response => { proxy.$modal.msgSuccess("新增成功"); open.value = false; getList(); }); } } }); } /** * 删除按钮操作 * @param {Object} row - 要删除的数据行对象(可选) * @description 删除指定ID的数据项,并提示用户确认操作 */ function handleDelete(row) { const _ids = row.id || ids.value; proxy.$modal.confirm('是否确认删除护理项目编号为"' + _ids + '"的数据项?').then(function() { return delProject(_ids); }).then(() => { getList(); proxy.$modal.msgSuccess("删除成功"); }).catch(() => {}); } /** * 导出按钮操作 * @description 导出当前查询条件下的护理项目数据为Excel文件 */ function handleExport() { proxy.download('nursing/project/export', { ...queryParams.value }, project_${new Date().getTime()}.xlsx) } // 初始化加载数据 getList(); </script> 如果该护理项目,已经被护理计划所引用,则不能进行删除、编辑、禁用

<template> <BaseTable ref="baseTable" :table-url='tableUrl' :auto-search-flag="true" :search-options='searchOptions' :columns='columns' :slot-columns="slotColumns" :call-style='callStyle' :table-event-btn='eventBtnList'> <template #file='{ row }'> <el-button v-if='row.file' type="primary" link @click='reportViewHandler(row)'>查看</el-button> <el-button v-else link>未上传</el-button> </template> <template #think='{ row }'> <el-button v-if='row.think' type="primary" link @click='thinkViewHandler(row)'>查看</el-button> <el-button v-else link>未上传</el-button> </template> <template #eventType="{row}"> {{formatListByKey(eventType,row.eventType)}} </template> <template #maintenanceStatus="{row}"> {{formatListByKey(maintenanceStatus,row.maintenanceStatus)}} </template> <template #isoVersion="{row}"> {{ row.event.isoFileVersion?row.event.isoFileVersion:'--' }} </template> <template #executeTime="{row}"> {{ row.executeTime }} ~ {{ row.executeEndTime }} </template> <template #approvedStatus="{row}"> <el-tag effect="dark" v-if='row.approvedStatus === "0"'>未审核</el-tag> <el-tag effect="dark" v-if='row.approvedStatus === "1"' type="success">审核通过</el-tag> <el-tag effect="dark" v-if='row.approvedStatus === "2"' type="danger">审核驳回</el-tag> </template> <template #action="{row}"> <el-button style='margin: 1px;' type="primary" link size="small" @click="handleDetailMethod(row)">查看</el-button> <el-button style='margin: 1px;' type="primary" link size="small" @click="handleApprovedMethod(row)" v-if='row.approvedStatus === "0"' v-hasPermi='["qa:history:approved"]'>审核</el-button> <el-button style='margin: 1px;' type="primary" link size="small" @click="handleUpdateMethod(row)" v-hasPermi='["device:history:edit"]' class="mr10">编辑</el-button> <el-popconfirm title="Are you sure to delete this?" @confirm="handleDeleteMethod(row)"> <template #reference> <el-button style='margin: 1px;' link type="danger" size="small" v-hasPermi='["device:history:del:admin"]' class="mr10">删除</el-button> </template> </el-popconfirm> <el-upload :show-file-list="false" style='display: inline-block' :action="actionUrl" :http-request="httpRequest"> <el-button link style='margin: 1px;' v-if="row.maintenanceStatus === '2'" type="success" size="small" @click="beforeUpload(row)" v-hasPermi='["device:history:edit"]'>重新导入</el-button> </el-upload> <el-button style='margin: 1px;' link type="primary" size="small" @click="handleReportMethod(row)">提交报告</el-button> <el-button style='margin: 1px;' link type="primary" size="small" @click="handleThinkMethod(row)">提交改进与思考</el-button> <el-popconfirm title="确定要发送催办邮件吗?" @confirm="remind(row)"> <template #reference> <el-button v-if='row.approvedStatus === "2"' style='margin: 1px;' link type="primary" size="small" v-hasPermi='["qa:history:remind"]'>催办</el-button> </template> </el-popconfirm> </template> </BaseTable> <el-dialog v-model="reportFormDialog.dialogVisible" :title="reportFormDialog.title" width="40%" class='form-dialog' @close="handleCloseReportFormDialog" style='border-radius: 5px;'> <BaseForm ref='baseReportForm' v-if='reportFormDialog.dialogVisible' :form-options='reportFormDialog.formOptions' :form-modal='reportFormDialog.formModal' :form-rules='reportFormDialog.formRules' @resolve-params='getReportFormDialogParams' > </BaseForm> <template #footer> <el-button @click="handleCloseReportFormDialog">取消</el-button> <el-button type="primary" @click="handleSubmitReportFormDialog">保存</el-button> </template> </el-dialog> <el-dialog v-model="thinkFormDialog.dialogVisible" :title="thinkFormDialog.title" width="60%" class='form-dialog' @close="handleCloseThinkFormDialog" style='border-radius: 5px;'> <BaseForm ref='baseThinkForm' v-if='thinkFormDialog.dialogVisible' :form-options='thinkFormDialog.formOptions' :form-modal='thinkFormDialog.formModal' :form-rules='thinkFormDialog.formRules' @resolve-params='getThinkFormDialogParams' > </BaseForm> <template #footer> <el-button @click="handleCloseThinkFormDialog">取消</el-button> <el-button type="primary" @click="handleSubmitThinkFormDialog">保存</el-button> </template> </el-dialog> <el-dialog v-model="unGeneraldetailDialog.dialogVisible" :title="unGeneraldetailDialog.title" width="60%" class='form-dialog' style='border-radius: 5px;' @close="unGeneraldetailDialog.dialogVisible = false"> <detail-view v-if="unGeneraldetailDialog.dialogVisible" ref="detailViewUnGeneral" :detail-dialog="unGeneraldetailDialog"></detail-view> </el-dialog> <el-dialog v-model="detailDialog.dialogVisible" :title="detailDialog.title" width="60%" class='form-dialog' @close="handleCancelDetail" style='border-radius: 5px;'> <detail-view v-if="detailDialog.dialogVisible" ref="detailView" :detail-dialog="detailDialog"></detail-view> </el-dialog> <el-dialog v-model="formDialog.dialogVisible" :title="formDialog.title" width="40%" @close="handleCloseFormDialog" class='form-dialog' style='border-radius: 5px;'> <BaseForm ref='baseForm' v-if='formDialog.dialogVisible' :form-options='formDialog.formOptions' :form-modal='formDialog.formModal' :form-rules='formDialog.formRules' @resolve-params='getFormDialogParams' > </BaseForm> <template #footer v-if='formDialog.type != "info"'> <el-button @click="handleCloseFormDialog">取消</el-button> <el-button type="primary" @click="handleSubmitFormDialog">保存</el-button> </template> </el-dialog> <el-dialog v-model="approvedDialog.dialogFormVisible" title="PM历史审核" width='500px' style='border-radius: 5px;'> <el-form :model="approvedDialog.form" status-icon ref="ruleFormRef" :rules="approvedDialog.rules"> <el-form-item label="审核状态:" prop='status'> <el-select v-model="approvedDialog.form.status" style='width: 100%' placeholder="Please select a status"> <el-option label="审核通过" value="1" /> <el-option label="审核驳回" value="2" /> </el-select> </el-form-item> <el-form-item label="审核意见:" prop='advise'> <el-input type='textarea' :autosize="{ minRows: 2, maxRows: 4 }" v-model="approvedDialog.form.advise" autocomplete="off" /> </el-form-item> </el-form> <template #footer> <el-button @click="approvedDialog.dialogFormVisible = false">取消</el-button> <el-button type="primary" @click="approvedConfirm"> 确定 </el-button> </template> </el-dialog> <el-dialog v-model="thinkView.thinkViewFlag" title="思考&改进" width="40%" style='border-radius: 5px;'> <el-link :href="${baseUrl}${item}" :underline="true" target="_blank"> {{ getFileName(item) }} </el-link> </el-dialog> <el-dialog v-model="reportView.reportViewFlag" title="报告" width="80%"> <el-link :href="${baseUrl}${item}" :underline="true" target="_blank"> {{ getFileName(item) }} </el-link> <el-link :href="${baseUrl}${item}" :underline="true" target="_blank"> {{ getFileName(item) }} </el-link> <el-table :data="tableData" style="width: 100%"> <el-table-column v-for="col in columns" :key="col.key" :prop="col.key" :label="col.label"></el-table-column> </el-table> {{ reportView.formModel.createBy }}:{{ reportView.formModel.uploadTime }} </el-dialog> </template> <script setup lang="ts" name="ExecuteHistory"> import Divider from '@/views/pms/tool-modules/divider.vue'; const baseUrl = import.meta.env.VITE_APP_BASE_API; import {cloneDeep as _cloneDeep} from "lodash"; import { searchOptionsInterface } from '@/components/BaseTable/modules/interface'; import { downloadBlobFile, formatListByKey, getObjectKeys } from '@/utils/ruoyi'; import { eventType, getEventTypeList, getMaintenanceStatus, getPeriodsUnitList, intervalType, maintenanceStatus } from "@/views/pms/common/variable"; import {getEqpId} from "@/api/pms/check-list"; import { importMaintenanceById, updateMaintenanceInHis, approved, delById, exportHis, remindHis } from '@/api/pms/execute'; import {ElMessage} from "element-plus"; import {ComponentInternalInstance, getCurrentInstance} from "vue"; import DetailView from "@/views/pms/common/modules/detail-view.vue"; import {getEqpIdByEqpArea} from "@/api/pms/eqp"; const { proxy } = getCurrentInstance() as ComponentInternalInstance; import { saveReport,saveThink } from '@/api/pms/file' const columns = ref([ // { type: 'checkbox',width:60,field:'eventType'}, { field: 'eventType', title: '类型',slots:{default:'eventType'},width: 100,fixed:'left'}, { field: 'eqpId', title: '机台ID',width: 100,fixed:'left'}, { field: 'eqpType', title: '机台型号',width: 100,fixed:'left'}, { field: 'maintenanceStatus', title: '状态',slots:{default:'maintenanceStatus'},width: 80,fixed:'left'}, { field: 'lastExeDate', title: '上次实际执行时间',width: 150,fixed:'left'}, { field: 'maintenanceTime', title: '计划执行时间',width: 150}, { field: 'executeTime', title: '实际执行时间',width: 280,slots:{default:'executeTime'}}, // { field: 'executeEndTime', title: '实际完成时间',width: 150}, { field: 'realityPeopleNum', title: '实际人力',width: 100}, { field: 'nextMaintenanceTime', title: '预计下次执行时间',width: 150}, { field: 'approvedStatus', title: '审核状态',slots: {default: 'approvedStatus'},width: 100}, { field: 'approvedAdvice', title: '审核意见',width: 100}, { field: 'approvedUser', title: '审核人',width: 100}, { field: 'event.isoFileVersion', title: 'ISO版本',slots: {default: 'isoVersion'},width: 100}, { field: 'file', title: 'CheckItem报告&PM验证报告',slots: {default: 'file'},width: 200}, { field: 'think', title: '思考&改进',slots: {default: 'think'},width: 120}, { field: 'maintenanceRemark', title: '备注',width: 100}, { field: 'action', title: '操作栏',slots:{default: 'action'},width:240,fixed:'right'}, ]) const searchOptions = ref([ {field:'eqpArea',title:'机台区域',type:'select',options:[],optionType:1,handle:changeEqpArea}, {field:'eqpId',title:'机台Id',type:'select',options:[],optionType:1,handle:changeEqpId }, {field:'startTime',title:'开始时间',type:'date' }, {field:'endTime',title:'结束时间',type:'date' }, {field:'approvedStatus',title:'审核状态',type:'select', options:[{label:'审核通过',value:'1'},{label:'驳回',value:'2'},{label:'未审核',value:'0'}], optionFormatter:{ label:'label' , value:'value' },labelType:1 }, {field:'eventType',title:'类型',type:'select',options:eventType,optionType:2,labelType:1,optionFormatter:{ label:'label' , value:'value' }}, {field:'maintenanceStatus',title:'状态',type:'select',options:maintenanceStatus,optionType:2,labelType:1,optionFormatter:{ label:'label' , value:'value' }}, {field:'id',title:'ID',type:'input' }, ]) const tableUrl = ref('/maintenance/eqpId/his') const slotColumns = ref(['action','eventType','maintenanceStatus','approvedStatus','isoVersion','file','think','executeTime']) let formDialog = reactive({ dialogVisible: false, title: '', type:'', formOptions: [ { name: '实际执行时间', field: 'executeTime', type: 'dateTime',col: 24 }, { name: '实际完成时间', field: 'executeEndTime', type: 'dateTime',col: 24 }, { name: '实际人力', field: 'realityPeopleNum', type: 'input',col: 24 }, { name: '备注', field: 'maintenanceRemark', type: 'textarea',col: 24 }, ], formModal:{ id:'', executeTime:'', executeEndTime:'', realityPeopleNum:'', maintenanceRemark:'', }, formRules: {}, }) function exportHandler(){ let params = proxy.$refs.baseTable.getSearchParams() exportHis(params).then(res =>{ if(res){ let fileName = moment().format('YYYY-MM-DD') + '_保养历史.xlsx' downloadBlobFile(res,fileName) } }) } const eventBtnList = ref([ { name: '导出', handle:exportHandler , type: 'primary' }, ]); /** 报告 report */ let reportFormDialog = reactive({ dialogVisible: false, title: '', formOptions: [ { name: 'PMCheckList报告', field: 'checkListFilePath', type: 'file',col: 24 }, { name: 'PM验证报告', field: 'pmReportFilePath', type: 'file',col: 24, }, { name: '备注', field: 'remark', type: 'textarea',col: 24 }, ], formModal:{ maintenanceId:'', checkListFilePath:'', pmReportFilePath:'', remark:'', }, formRules: {}, }) let thinkFormDialog = reactive({ dialogVisible: false, title: '', formOptions: [ { name: '思考&改进', field: 'content', type: 'edit',col: 24 }, { name: '附件', field: 'filePath', type: 'file',col: 24, }, { name: '备注', field: 'remark', type: 'textarea',col: 24 }, ], formModal:{ maintenanceId:'', content:'', filePath:'', remark:'', }, formRules: {}, }) let unGeneraldetailDialog = reactive({ dialogVisible: false, title: '', type:'', formOptions: [ { name: '保养时间', field: 'schedulingStartTime', type: 'dateTime',col: 24 }, { name: '负责人', field: 'schedulingUser', type: 'input',col: 24 }, { name: 'email', field: 'email', type: 'textarea',col: 24 }, { name: '标准作业时间', field: 'jobTime', type: 'input',col: 24 }, { name: '标准人力', field: 'jobPeopleNum', type: 'input',col: 24 }, /* { name: '保养周期', field: 'schedulingPeriods', type: 'input',col: 24 }, { name: '保养周期类型', field: 'schedulingPeriodsUnit', type: 'select',col: 24,options:intervalType },*/ { name: 'PM原因', field: 'schedulingDes', type: 'input',col: 24 }, { name: '提前通知时间/H', field: 'schedulingNoticeBeforeTime', type: 'input',col: 24 }, { name: '延后通知时间/H', field: 'schedulingNoticeAfterTime', type: 'input',col: 24 } ], formModal:{ id:'', schedulingStartTime:'', schedulingUser:'', email:'', jobTime:'', jobPeopleNum:'', schedulingDes:'', /* schedulingPeriods:'', schedulingPeriodsUnit:'',*/ schedulingNoticeBeforeTime:'', schedulingNoticeAfterTime:'', }, formRules: {}, activeName:'first', currentRow:null }) let detailDialog = reactive({ dialogVisible: false, title: '', type:'', formOptions: [ { name: '第一次保养时间', field: 'schedulingStartTime', type: 'dateTime',col: 24 }, { name: '负责人', field: 'schedulingUser', type: 'input',col: 24 }, { name: 'email', field: 'email', type: 'textarea',col: 24 }, { name: '标准作业时间', field: 'jobTime', type: 'input',col: 24 }, { name: '标准人力', field: 'jobPeopleNum', type: 'input',col: 24 }, { name: '保养周期', field: 'schedulingPeriods', type: 'input',col: 24 }, { name: '保养周期类型', field: 'schedulingPeriodsUnit', type: 'select',col: 24,options:intervalType }, { name: '提前通知时间/H', field: 'schedulingNoticeBeforeTime', type: 'input',col: 24 }, { name: '延后通知时间/H', field: 'schedulingNoticeAfterTime', type: 'input',col: 24 } ], formModal:{ id:'', schedulingStartTime:'', schedulingUser:'', email:'', jobTime:'', jobPeopleNum:'', schedulingPeriods:'', schedulingPeriodsUnit:'', schedulingNoticeBeforeTime:'', schedulingNoticeAfterTime:'', }, formRules: {}, activeName:'first', currentRow:null }) const resetDetailDialog = _cloneDeep(detailDialog) const resetFormDialog = _cloneDeep(formDialog) const actionUrl = ref('') const currentRow = ref('') const eqpAreaMap = ref(null) let approvedDialog = reactive({ form:{ status:"", advise:"", maintenanceId:"" }, rules:{ status: [ { required: true, message: '选择审核状态', trigger: 'blur' }, ], advise: [ { required: true, message: '输入审核意见', trigger: 'blur' }, ], }, dialogFormVisible:false }) import { useRouter } from 'vue-router'; import moment from 'moment'; const route = useRouter() watch(() => route.currentRoute.value,(newValue) => { if (newValue.query){ searchOptions.value[7].value = newValue.query.id nextTick(() =>{ proxy.$refs.baseTable.getTableList() }) } },{immediate:true,deep:true} ) watch(()=> approvedDialog.form.status,(newValue,oldValue) => { if (newValue === '1'){ approvedDialog.form.advise = '审核通过' } if (newValue === '2'){ approvedDialog.form.advise = '' } },{immediate:true,deep:true}) getEqpIdList() getEventTypeList() getMaintenanceStatus() getPeriodsUnitList() getEqpAreaAndEqp() function getEqpAreaAndEqp(){ getEqpIdByEqpArea().then(response => { if(response.code === 200){ eqpAreaMap.value = response.data setOptions(searchOptions.value,'eqpArea',Object.keys(response.data)) }else{ ElMessage.error(response.msg) } }) } function callStyle({ row,column}){ if (row.approvedStatus === '2'){ return { background: 'rgba(238, 180, 180,.3)'} } if (row.approvedStatus === '1'){ return { background: 'rgba(155, 205, 155,.3)'} } } function changeEqpArea(value){ setOptions(searchOptions.value,'eqpId',eqpAreaMap.value[value]) } function handleCancelDetail(){ type formType = keyof typeof resetDetailDialog; getObjectKeys(resetDetailDialog).forEach(<K extends formType>(item: K)=>{ detailDialog[item] = _cloneDeep(resetDetailDialog[item]) }) } function handleApprovedMethod(row){ approvedDialog.form.maintenanceId = row.id approvedDialog.form.status = '' approvedDialog.form.advise = '' approvedDialog.dialogFormVisible = true } function approvedConfirm() { proxy.$refs.ruleFormRef.validate(vali =>{ if (vali){ approved(approvedDialog.form).then(res => { if (res.code === 200){ approvedDialog.dialogFormVisible = false proxy.$refs.baseTable.getTableList() ElMessage.success(res.msg) }else{ ElMessage.error(res.msg) } }) } }) } function handleDetailMethod(row){ let type = formatListByKey(eventType.value,row.eventType) if (type === 'unGeneral'){ unGeneraldetailDialog.dialogVisible = true unGeneraldetailDialog.title = '详情' getObjectKeys(unGeneraldetailDialog.formModal).forEach(item=>{ unGeneraldetailDialog.formModal[item] = row.scheduling[item] }) unGeneraldetailDialog.currentRow = row }else { detailDialog.dialogVisible = true detailDialog.title = '详情' getObjectKeys(detailDialog.formModal).forEach(item=>{ detailDialog.formModal[item] = row.scheduling[item] }) detailDialog.currentRow = row } } function beforeUpload(row){ currentRow.value = row } function httpRequest({file}){ let formData = new FormData() formData.append('file',file) formData.append('id',currentRow.value.id) importMaintenanceById(formData).then(response=>{ if(response.code === 200){ proxy.$refs.baseTable.getTableList() }else{ ElMessage.error(response.msg) } }) } function changeEqpId(){ proxy.$refs.baseTable.getTableList() } // 向初始条件的options里添加值 function setOptions(list: Array<searchOptionsInterface>,name:string,options:Array<any>){ let result = list.find((item)=>item.field === name) if(result){ result.options = options } } function getFormDialogParams(){ updateMaintenanceInHis(formDialog.formModal).then(res =>{ if(res.code === 200){ ElMessage.success(res.msg) handleCloseFormDialog() proxy.$refs.baseTable.getTableList() }else{ ElMessage.error(res.msg) } }) } function handleSubmitFormDialog(){ proxy.$refs.baseForm.getFormParams() } function handleCloseFormDialog(){ type formType = keyof typeof resetFormDialog; getObjectKeys(resetFormDialog).forEach(<K extends formType>(item: K)=>{ formDialog[item] = _cloneDeep(resetFormDialog[item]) }) } function handleUpdateMethod(row){ setOptions(formDialog.formOptions,'maintenanceStatus',maintenanceStatus.value) formDialog.dialogVisible = true formDialog.title = '修改信息' getObjectKeys(formDialog.formModal).forEach(item=>{ formDialog.formModal[item] = row[item] }) } function handleDeleteMethod(row) { delById(row.id).then(res =>{ if (res.data){ ElMessage.success('操作成功') proxy.$refs.baseTable.getTableList() } }) } function getEqpIdList(){ getEqpId({pageSize:9999,pageNum:1}).then(res =>{ if(res.code === 200){ setOptions(searchOptions.value,'eqpId',res.rows.map((item:{eqpId:string})=>item.eqpId)) } }) } function handleReportMethod(row) { let { file } = row reportFormDialog.formModal = { ... file} reportFormDialog.formModal.maintenanceId = row.id reportFormDialog.dialogVisible = true reportFormDialog.title = '新增/修改报告' } function handleThinkMethod(row) { let { think } = row thinkFormDialog.formModal = {... think } thinkFormDialog.formModal.maintenanceId = row.id thinkFormDialog.dialogVisible = true } function getReportFormDialogParams() { saveReport(reportFormDialog.formModal).then(res =>{ ElMessage.success(res.msg) handleCloseReportFormDialog() proxy.$refs.baseTable.getTableList() }) } function getThinkFormDialogParams(){ saveThink(thinkFormDialog.formModal).then(res =>{ ElMessage.success(res.msg) handleCloseThinkFormDialog() proxy.$refs.baseTable.getTableList() }) } function handleCloseReportFormDialog() { reportFormDialog.dialogVisible = false } function handleCloseThinkFormDialog(){ thinkFormDialog.dialogVisible = false } function handleSubmitReportFormDialog() { proxy.$refs.baseReportForm.getFormParams() } function handleSubmitThinkFormDialog() { proxy.$refs.baseThinkForm.getFormParams() } function getFileName(name: any) { if (name.lastIndexOf('/') > -1) { return name.slice(name.lastIndexOf('/') + 1); } else { return ''; } } function remind(row) { console.log(row) remindHis(row).then(res => { if (res.code === 200) { ElMessage.success(res.msg) } else { ElMessage.error(res.msg) } }); } const reportView = reactive({ reportViewFlag:false, formModel:{ checkListFilePath:'', pmReportFilePath:'', createBy:'', uploadTime:'' } }) const thinkView = reactive({ thinkViewFlag:false, formModel:{ content:'', filePath:'', createBy:'', uploadTime:'' } }) function thinkViewHandler({ think }){ thinkView.thinkViewFlag = true Object.assign(thinkView.formModel,think) } function reportViewHandler({ file }) { reportView.reportViewFlag = true Object.assign(reportView.formModel,file) } </script> <style scoped lang="scss"> </style>这是完整代码改为点击PM CheckList 报告和PM 验证报告那个文件才展示xlsx的文件内容

package com.zzyl.plan.controller; import java.util.List; import javax.servlet.http.HttpServletResponse; import com.zzyl.nursing.dto.NursingPlanDto; import org.springframework.security.access.prepost.PreAuthorize; 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.PutMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.zzyl.common.annotation.Log; import com.zzyl.common.core.controller.BaseController; import com.zzyl.common.core.domain.AjaxResult; import com.zzyl.common.enums.BusinessType; import com.zzyl.plan.domain.NursingPlan; import com.zzyl.plan.service.INursingPlanService; import com.zzyl.common.utils.poi.ExcelUtil; import com.zzyl.common.core.page.TableDataInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; /** * 护理计划Controller * * @author ruoyi * @date 2025-08-07 */ @Api(tags = "护理计划管理") @RestController @RequestMapping("/nursing/plan") public class NursingPlanController extends BaseController { @Autowired private INursingPlanService nursingPlanService; /** * 查询护理计划列表 */ @ApiOperation("查询护理计划列表") @PreAuthorize("@ss.hasPermi('nursing:plan:list')") @GetMapping("/list") public TableDataInfo list( @ApiParam("护理计划查询参数") NursingPlan nursingPlan) { startPage(); List<NursingPlan> list = nursingPlanService.selectNursingPlanList(nursingPlan); return getDataTable(list); } /** * 导出护理计划列表 */ @ApiOperation("导出护理计划列表") @PreAuthorize("@ss.hasPermi('nursing:plan:export')") @Log(title = "护理计划", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export( @ApiParam("HTTP响应对象") HttpServletResponse response, @ApiParam("护理计划查询参数") NursingPlan nursingPlan) { List<NursingPlan> list = nursingPlanService.selectNursingPlanList(nursingPlan); ExcelUtil<NursingPlan> util = new ExcelUtil<NursingPlan>(NursingPlan.class); util.exportExcel(response, list, "护理计划数据"); } /** * 获取护理计划详细信息 */ @ApiOperation("获取护理计划详细信息") @PreAuthorize("@ss.hasPermi('nursing:plan:query')") @GetMapping(value = "/{id}") public AjaxResult getInfo( @ApiParam("护理计划ID") @PathVariable("id") Long id) { return success(nursingPlanService.selectNursingPlanById(id)); } /** * 新增护理计划 */ @ApiOperation("新增护理计划") @PreAuthorize("@ss.hasPermi('nursing:plan:add')") @Log(title = "护理计划", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add( @ApiParam("护理计划对象") @RequestBody NursingPlanDto dto) { return toAjax(nursingPlanService.insertNursingPlan(dto)); } /** * 修改护理计划 */ @ApiOperation("修改护理计划") @PreAuthorize("@ss.hasPermi('nursing:plan:edit')") @Log(title = "护理计划", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit( @ApiParam("护理计划对象") @RequestBody NursingPlan nursingPlan) { return toAjax(nursingPlanService.updateNursingPlan(nursingPlan)); } /** * 删除护理计划 */ @ApiOperation("删除护理计划") @PreAuthorize("@ss.hasPermi('nursing:plan:remove')") @Log(title = "护理计划", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public AjaxResult remove( @ApiParam("护理计划ID数组") @PathVariable Long[] ids) { return toAjax(nursingPlanService.deleteNursingPlanByIds(ids)); } } @Data @ApiModel(description = "护理计划") public class NursingPlanVo { /** * 护理计划id */ private Long id; /** * 排序号 */ @ApiModelProperty(value = "护理计划排序号") private Integer sortNo; @ApiModelProperty(value = "护理计划名称") private String planName; @ApiModelProperty(value = "状态(0:禁用,1:启用)") private Integer status; @ApiModelProperty(value = "护理计划项目计划列表") List<NursingProjectPlanVo> projectPlans; } 这是我相应给前端的实体,如何修改

package com.zzyl.nursing.domain; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.zzyl.common.annotation.Excel; import com.zzyl.common.core.domain.BaseEntity; /** * 护理计划和项目关联对象 nursing_project_plan * * @author ruoyi * @date 2025-08-09 */ public class NursingProjectPlan extends BaseEntity { private static final long serialVersionUID = 1L; /** $column.columnComment */ private Long id; /** 计划id */ @Excel(name = "计划id") private Long planId; /** 项目id */ @Excel(name = "项目id") private Long projectId; /** 计划执行时间 */ @Excel(name = "计划执行时间") private String executeTime; /** 执行周期 0 天 1 周 2月 */ @Excel(name = "执行周期 0 天 1 周 2月") private Long executeCycle; /** 执行频次 */ @Excel(name = "执行频次") private Long executeFrequency; public void setId(Long id) { this.id = id; } public Long getId() { return id; } public void setPlanId(Long planId) { this.planId = planId; } public Long getPlanId() { return planId; } public void setProjectId(Long projectId) { this.projectId = projectId; } public Long getProjectId() { return projectId; } public void setExecuteTime(String executeTime) { this.executeTime = executeTime; } public String getExecuteTime() { return executeTime; } public void setExecuteCycle(Long executeCycle) { this.executeCycle = executeCycle; } public Long getExecuteCycle() { return executeCycle; } public void setExecuteFrequency(Long executeFrequency) { this.executeFrequency = executeFrequency; } public Long getExecuteFrequency() { return executeFrequency; } @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("id", getId()) .append("planId", getPlanId()) .append("projectId", getProjectId()) .append("executeTime", getExecuteTime()) .append("executeCycle", getExecuteCycle()) .append("executeFrequency", getExecuteFrequency()) .append("createTime", getCreateTime()) .append("updateTime", getUpdateTime()) .append("createBy", getCreateBy()) .append("updateBy", getUpdateBy()) .append("remark", getRemark()) .toString(); } } 有一张中间表

最新推荐

recommend-type

appstream-0.15.2-beta-javadoc.jar

appstream-0.15.2-beta-javadoc.jar
recommend-type

b2bi-jvm-1.4.114.jar

b2bi-jvm-1.4.114.jar
recommend-type

Node.js构建的运动咖啡馆RESTful API介绍

标题《sportscafeold:体育咖啡馆》指出了项目名称为“体育咖啡馆”,这个名字暗示了该项目可能是一个结合了运动和休闲主题的咖啡馆相关的网络服务平台。该项目运用了多种技术栈,核心的开发语言为JavaScript,这从标签中可以得到明确的信息。 从描述中可以提取以下知识点: 1. **Node.js**:体育咖啡馆项目使用了Node.js作为服务器端运行环境。Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它能够使得JavaScript应用于服务器端开发。Node.js的事件驱动、非阻塞I/O模型使其适合处理大量并发连接,这对于RESTFUL API的构建尤为重要。 2. **Express Framework**:项目中使用了Express框架来创建RESTFUL API。Express是基于Node.js平台,快速、灵活且极简的Web应用开发框架。它提供了构建Web和移动应用的强大功能,是目前最流行的Node.js Web应用框架之一。RESTFUL API是一组遵循REST原则的应用架构,其设计宗旨是让Web服务通过HTTP协议进行通信,并且可以使用各种语言和技术实现。 3. **Mongoose ORM**:这个项目利用了Mongoose作为操作MongoDB数据库的接口。Mongoose是一个对象文档映射器(ODM),它为Node.js提供了MongoDB数据库的驱动。通过Mongoose可以定义数据模型,进行数据库操作和查询,从而简化了对MongoDB数据库的操作。 4. **Passport.js**:项目中采用了Passport.js库来实现身份验证系统。Passport是一个灵活的Node.js身份验证中间件,它支持多种验证策略,例如用户名和密码、OAuth等。它提供了标准化的方法来为用户登录提供认证,是用户认证功能的常用解决方案。 5. **版权信息**:项目的版权声明表明了Sportscafe 2015是版权所有者,这表明项目或其相关内容最早发布于2015年或之前。这可能表明该API背后有商业实体的支持或授权使用。 从【压缩包子文件的文件名称列表】中我们可以了解到,该文件的版本控制仓库使用的是“master”分支。在Git版本控制系统中,“master”分支通常用于存放当前可部署的稳定版本代码。在“master”分支上进行的更改通常都是经过测试且准备发布到生产环境的。 综上所述,我们可以知道体育咖啡馆项目是一个利用现代JavaScript技术栈搭建的后端服务。它包含了处理HTTP请求的Express框架、连接MongoDB数据库的Mongoose库和实现用户身份验证的Passport.js中间件。该项目可用于构建提供体育信息、咖啡馆菜单信息、预约服务等的Web应用或API服务,这为体育咖啡馆的营销、用户体验和数据管理提供了可能。 考虑到文档资料的提及,该项目的安装和API文档应该包含在项目资料中,可能在项目的README文件或其他说明文档中。对于项目的使用者或者开发者而言,这部分文档非常重要,因为它们可以提供详细的信息和指导,帮助用户快速部署和使用该API。 总结来说,这是一套针对体育咖啡馆相关业务的后端解决方案,它使用了流行的开源技术栈,可以灵活地应用于体育咖啡馆的网络服务中,如信息发布、在线预约、会员管理等。
recommend-type

【LNR优化与用户体验】:一文看透互操作优化如何提升用户感知

# 摘要 LNR(邻区关系优化)是提升移动通信网络性能与用户体验的关键技术。本文系统阐述了LNR优化的基本概念、理论基础与技术实现路径,构建了包括信道质量评估、干扰建模及关键性能指标分析在内的数学模型,并探讨了参数配置、邻区管理及AI与大数据在LNR优化中的应用。通过量化用户感知指标,分析了LNR优化对视频流畅度、页面加载速度及切换性能的实际改善效果,并结合典型场景验证了其优化成效。本文进一步展望了LNR技术在5G及未来网络中的发展趋势与技术挑战。
recommend-type

Java1.8 的编程语言、使用场景、版本号、厂商、是否开源、发行日期、终止日期、可替代产品、推荐产品是什么

以下是关于 **Java 1.8** 的全面信息汇总,涵盖其编程语言特性、使用场景、版本号、厂商、是否开源、发行日期、终止支持日期、可替代产品和推荐产品。 --- ## ✅ Java 1.8 综合信息表 | 项目 | 内容 | |------|------| | **编程语言** | Java | | **版本号** | Java 1.8(也称为 Java 8) | | **厂商** | Oracle、Adoptium、Amazon(Corretto)、Azul(Zulu)、Red Hat、IBM 等 | | **是否开源** | ✅ 是(OpenJDK 1.8 是开源的,Oracle
recommend-type

Java开发的教区牧民支持系统介绍

根据给定文件信息,下面将详细阐述相关知识点: ### 标题知识点 #### catecumenus-java: 教区牧民支持系统 - **Java技术栈应用**:标题提到的“catecumenus-java”表明这是一个使用Java语言开发的系统。Java是目前最流行的编程语言之一,广泛应用于企业级应用、Web开发、移动应用等,尤其是在需要跨平台运行的应用中。Java被设计为具有尽可能少的实现依赖,所以它可以在多种处理器上运行。 - **教区牧民支持系统**:从标题来看,这个系统可能面向的是教会管理或教区管理,用来支持牧民(教会领导者或牧师)的日常管理工作。具体功能可能包括教友信息管理、教区活动安排、宗教教育资料库、财务管理、教堂资源调配等。 ### 描述知识点 #### 儿茶类 - **儿茶素(Catechin)**:描述中提到的“儿茶类”可能与“catecumenus”(新信徒、教徒)有关联,暗示这个系统可能与教会或宗教教育相关。儿茶素是一类天然的多酚类化合物,常见于茶、巧克力等植物中,具有抗氧化、抗炎等多种生物活性,但在系统标题中可能并无直接关联。 - **系统版本号**:“0.0.1”表示这是一个非常初期的版本,意味着该系统可能刚刚开始开发,功能尚不完善。 ### 标签知识点 #### Java - **Java语言特点**:标签中明确提到了“Java”,这暗示了整个系统都是用Java编程语言开发的。Java的特点包括面向对象、跨平台(即一次编写,到处运行)、安全性、多线程处理能力等。系统使用Java进行开发,可能看重了这些特点,尤其是在构建可扩展、稳定的后台服务。 - **Java应用领域**:Java广泛应用于企业级应用开发中,包括Web应用程序、大型系统后台、桌面应用以及移动应用(Android)。所以,此系统可能也会涉及这些技术层面。 ### 压缩包子文件的文件名称列表知识点 #### catecumenus-java-master - **Git项目结构**:文件名称中的“master”表明了这是Git版本控制系统中的一个主分支。在Git中,“master”分支通常被用作项目的主干,是默认的开发分支,所有开发工作都是基于此分支进行的。 - **项目目录结构**:在Git项目中,“catecumenus-java”文件夹应该包含了系统的源代码、资源文件、构建脚本、文档等。文件夹可能包含各种子文件夹和文件,比如src目录存放Java源代码,lib目录存放相关依赖库,以及可能的build.xml文件用于构建过程(如Ant或Maven构建脚本)。 ### 结合以上信息的知识点整合 综合以上信息,我们可以推断“catecumenus-java: 教区牧民支持系统”是一个使用Java语言开发的系统,可能正处于初级开发阶段。这个系统可能是为了支持教会内部管理,提供信息管理、资源调度等功能。其使用Java语言的目的可能是希望利用Java的多线程处理能力、跨平台特性和强大的企业级应用支持能力,以实现一个稳定和可扩展的系统。项目结构遵循了Git版本控制的规范,并且可能采用了模块化的开发方式,各个功能模块的代码和资源文件都有序地组织在不同的子文件夹内。 该系统可能采取敏捷开发模式,随着版本号的增加,系统功能将逐步完善和丰富。由于是面向教会的内部支持系统,对系统的用户界面友好性、安全性和数据保护可能会有较高的要求。此外,考虑到宗教性质的敏感性,系统的开发和使用可能还需要遵守特定的隐私和法律法规。
recommend-type

LNR切换成功率提升秘籍:参数配置到网络策略的全面指南

# 摘要 LNR(LTE to NR)切换技术是5G网络部署中的关键环节,直接影
recommend-type

How to install watt toolkit in linux ?

安装 Watt Toolkit(原名 Steam++)在 Linux 系统上通常可以通过编译源码或者使用预编译的二进制文件来完成。Watt Toolkit 是一个开源工具,主要用于加速 Steam 平台的下载速度,支持跨平台运行,因此在 Linux 上也能够很好地工作。 ### 安装步骤 #### 方法一:使用预编译的二进制文件 1. 访问 [Watt Toolkit 的 GitHub 仓库](https://github.com/BeyondDimension/SteamTools) 并下载适用于 Linux 的最新版本。 2. 解压下载的压缩包。 3. 给予可执行权限: ```
recommend-type

PHP实现用户墙上帖子与评论的分享功能

根据给定文件信息,我们可以推导出与“userwallposts”相关的知识点。这里涉及的关键概念包括用户墙面墙(User Wall)、帖子(Posts)和评论(Comments),以及它们在编程语言PHP中的实现方式。用户墙是一种允许用户发布信息,并让他们的朋友或跟随者查看并参与讨论的功能,常见于社交网站。 ### 用户墙概念 用户墙类似于现实生活中的一面墙,用户可以在上面贴上“帖子”来分享自己的想法、照片、视频等信息。其他用户可以在这些帖子下面进行“评论”,类似于在墙上留言。这种互动方式构建了一个社区式的交流环境,增加了用户之间的互动性和参与感。 ### 用户墙的实现 在PHP中实现用户墙功能需要处理前端用户界面和后端服务器逻辑。前端负责展示用户墙、帖子和评论的界面,而后端则负责存储、检索和管理这些数据。 1. **前端实现**:前端可以使用HTML、CSS和JavaScript来构建用户墙的界面。使用AJAX技术可以让用户无需刷新页面即可提交和获取新的帖子和评论。此外,可能还会用到模板引擎(如Twig或Smarty)来动态生成页面内容。 2. **后端实现**:后端PHP代码将负责处理前端发送的请求,如帖子和评论的添加、删除和检索。数据库(如MySQL)将用于存储用户信息、帖子内容、评论以及它们之间的关联关系。 3. **数据库设计**: - 用户表(users):存储用户信息,例如用户名、密码(加密存储)、用户状态等。 - 帖子表(posts):存储帖子信息,例如帖子ID、帖子内容、发帖时间、所属用户ID等。 - 评论表(comments):存储评论信息,包括评论ID、评论内容、评论时间、所属帖子ID和用户ID等。 4. **PHP与数据库交互**:使用PDO(PHP Data Objects)或mysqli扩展来执行SQL语句与数据库进行交互。PDO提供了数据库访问的抽象层,可以连接多种数据库系统,而mysqli则针对MySQL进行了优化。 5. **安全性**: - 输入验证:为了防止SQL注入等安全问题,需要对用户输入进行验证和清理。 - 输出编码:在将数据输出到浏览器之前,应将特殊字符转换为HTML实体。 - 用户认证:用户登录系统时,应采取安全措施如使用会话管理(session management)和防止跨站请求伪造(CSRF)。 6. **功能实现细节**: - 发布帖子:用户输入帖子内容并提交,后端接收并存储到帖子表中。 - 显示帖子:从帖子表中检索所有帖子并展示在用户墙上,包括帖子标题、内容、发布时间和发帖人等信息。 - 发布评论:用户对特定帖子发表评论,后端接收评论信息并将其存储到评论表中。 - 显示评论:为每个帖子显示其下的所有评论,包括评论内容、时间、评论者等。 ### 开源项目实践 “userwallposts-master”暗示了可能存在一个与用户墙帖子和评论相关的开源项目或代码库。这个项目可能包含预设的代码和文件结构,允许开发者下载、安装和配置来创建他们自己的用户墙功能。开发人员可以使用这个项目作为起点,根据自己的需求进一步定制和扩展功能。 在实际开发过程中,还需要考虑系统的可扩展性和维护性。例如,可以设计RESTful API让前端和后端分离,或者使用现代的PHP框架(如Laravel、Symfony等)来简化开发流程和提高代码的组织性。 在总结上述内容后,我们可以了解到用户墙是社交平台中常见的一种功能,其核心功能包括发布帖子和评论。在PHP环境下实现这样的功能需要对前端界面和后端逻辑有深入的理解,以及对数据库设计和交互的安全性有一定的认识。开源项目如“userwallposts-master”可能提供了一个基础框架,帮助开发者快速构建和部署一个用户墙系统。
recommend-type

【LNR信令深度解析】:MR-DC双连接建立全过程技术揭秘

# 摘要 本文系统探讨了LNR信令与MR-DC双连接技术的基本原理、架构组成及其关键信令流程。深入分析了MR-DC的网络架构分类、核心网元功能、无线承载管理机制以及双连接建立过程中的关键信令交互路径。同时,文章解析了LNR信令消息的结构特征与关键字段,探讨了MR-DC场景下的性能评估指标与优化策略,包括信令压缩、负载均衡及节能调度机制。最后,文章展望了MR-DC技术在5G