智能图像处理平台:图片管理

接着我们讲图片管理,先实现图片基础的增删改查,再去考虑图像处理。

主要是,我们需要完成查询时,查询的图片的上传者的角色等级小于等于我们当前登陆账号。

后端controller:

package com.llpp.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.llpp.entity.Image;
import com.llpp.entity.User;
import com.llpp.service.impl.ImageServiceImpl;
import com.llpp.service.impl.RedisService;
import com.llpp.tool.PrimaryKey;
import com.llpp.tool.Result;
import com.llpp.vo.ImageVO;
import lombok.RequiredArgsConstructor;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Optional;

/**
 * @Author 21326
 * @Date 2025 2025/2/25 22:23
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/image")
public class ImageController {
    private final RedisService redisService;
    private final ImageServiceImpl imageService;

    @GetMapping("/getPage")
    public Result getPage(Page<ImageVO> page, ImageVO image, HttpServletRequest request) {
        String token = request.getHeader("authorization");
        token = token.substring(token.indexOf(" ") + 1);
        String user = redisService.getValueOrDefault(token, "").toString();
        image.setRoleId(JSONUtil.toBean(user, User.class).getRoleId());
        return Result.data(imageService.getPage(page, image));
    }

    @PostMapping("/rowSave")
    public Result rowSave(@RequestBody Image image, HttpServletRequest request) {
        return Optional.ofNullable(image)
                .filter(i -> !StringUtils.isEmpty(i.getUrl()))
                .filter(i -> !StringUtils.isEmpty(i.getName()))
                .map(i -> {
                    String token = request.getHeader("authorization");
                    token = token.substring(token.indexOf(" ") + 1);
                    String user = redisService.getValueOrDefault(token, "").toString();
                    User info = JSONUtil.toBean(user, User.class);
                    i.setStatus(0);
                    i.setUserId(info.getId());
                    i.setId(new PrimaryKey().nextId());
                    i.setCreateTime(LocalDateTime.now());
                    return Result.status(imageService.save(i));
                })
                .orElse(Result.fail("参数异常"));
    }

    @PostMapping("/rowEdit")
    public Result rowEdit(@RequestBody Image image) {
        return Optional.ofNullable(image)
                .filter(i -> Objects.nonNull(i.getId()))
                .map(i -> Result.status(imageService.updateById(i)))
                .orElse(Result.fail("参数异常"));
    }

    @PostMapping("/rowDel")
    public Result rowDel(@RequestBody Image image) {
        return Optional.ofNullable(image)
                .filter(i -> Objects.nonNull(i.getId()))
                .map(i -> Result.status(imageService.removeById(i.getId())))
                .orElse(Result.fail("参数异常"));
    }
}

service:

@Service
public class ImageServiceImpl extends ServiceImpl<ImageMapper, Image> implements IImageService {

    @Override
    public IPage<ImageVO> getPage(IPage<ImageVO> page, ImageVO image) {
        return baseMapper.getPage(page, image);
    }
}

mapper:

package com.llpp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.llpp.entity.Image;
import com.llpp.vo.ImageVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

/**
 * @Author 21326
 * @Date 2025 2025/1/31 20:44
 */
@Mapper
public interface ImageMapper extends BaseMapper<Image> {
    IPage<ImageVO> getPage(IPage<ImageVO> page, @Param("image") ImageVO imageVO);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.llpp.mapper.ImageMapper">
    <select id="getPage" resultType="com.llpp.vo.ImageVO">
        SELECT i.id,i.deleted,i.status,i.remark,i.name,i.url,i.result,i.create_time,u.username,r.name AS role_name
        FROM image i
        LEFT JOIN user u ON i.user_id = u.id
        LEFT JOIN role r ON u.role_id = r.id
        WHERE i.deleted=0
        AND u.deleted=0
        AND r.deleted=0
        AND u.role_id &gt;= #{image.roleId}
        AND r.id &gt;= #{image.roleId}
        <if test="image.id != null">
            AND i.id = #{image.id}
        </if>
        <if test="image.status != null">
            AND i.status = #{image.status}
        </if>
        <if test="image.startTime != null">
            AND i.create_time &gt;= #{image.startTime}
        </if>
        <if test="image.endTime != null">
            AND i.create_time &lt;= #{image.endTime}
        </if>
        <if test="image.name != null and image.name !=''">
            AND i.name LIKE CONCAT('%',#{image.name},'%')
        </if>
        <if test="image.remark != null and image.remark !=''">
            AND i.remark LIKE CONCAT('%',#{image.remark},'%')
        </if>
        <if test="image.username != null and image.username !=''">
            AND u.username LIKE CONCAT('%',#{image.username},'%')
        </if>
        <if test="image.roleName != null and image.roleName !=''">
            AND r.name LIKE CONCAT('%',#{image.roleName},'%')
        </if>
    </select>
</mapper>

image.js:

import request from '@/router/axios';
import {baseUrl} from '@/config/env';

export const getPage = (current, size, params) => {
    return request({
        url: baseUrl + '/image/getPage',
        method: 'get',
        params: {
            current,
            size,
            ...params
        }
    })
}

export const rowSave = (form) => {
    return request({
        url: baseUrl + '/image/rowSave',
        method: 'post',
        data: form
    })
}

export const rowEdit = (row) => {
    return request({
        url: baseUrl + '/image/rowEdit',
        method: 'post',
        data: row
    })
}

export const rowDel = (row) => {
    return request({
        url: baseUrl + '/image/rowDel',
        method: 'post',
        data: row
    })
}

image.vue:

<template>
  <basic-container>
    <avue-crud :option="option"
               :search="search"
               :page="page"
               v-model="form"
               :table-loading="loading"
               :data="tableData"
               ref="crud"
               @row-update="rowUpdate"
               @row-save="rowSave"
               @row-del="rowDel"
               @search-change="searchChange"
               @search-reset="searchReset"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
    </avue-crud>
  </basic-container>
</template>

<script>
import {getPage, rowDel, rowEdit, rowSave} from "@/api/image/image";

export default {
  name: "image",
  data() {
    return {
      option: {
        height: 'auto',
        stripe: true,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        border: true,
        index: false,
        viewBtn: true,
        addBtn: true,
        delBtn: true,
        editBtn: true,
        column: [
          {
            label: '图片编号',
            prop: 'id',
            search: true,
            width: 120,
            span: 24,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true,
          },
          {
            label: '图片名称',
            prop: 'name',
            search: true,
            span: 24,
            rules: [{required: true, message: '请输入图片名称', trigger: 'blur'}]
          },
          {
            label: '上传用户',
            prop: 'username',
            search: true,
            span: 24,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true,
          },
          {
            label: '上传时间',
            prop: 'createTime',
            type: 'datetime',
            format: 'yyyy-MM-dd HH:mm:ss',
            valueFormat: 'yyyy-MM-dd HH:mm:ss',
            search: true,
            searchRange: true,
            span: 24,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true,
            startPlaceholder: '时间日期开始范围自定义',
            endPlaceholder: '时间日期结束范围自定义',
          },
          {
            label: '用户角色',
            prop: 'roleName',
            search: true,
            width: 70,
            span: 24,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true,
          }, {
            label: '状态',
            prop: 'status',
            type: 'select',
            search: true,
            width: 70,
            span: 24,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true,
            props: {
              label: 'label',
              value: 'value'
            },
            dicData: [
              {label: '已处理', value: 1},
              {label: '未处理', value: 0}
            ],
          },
          {
            label: '备注',
            prop: 'remark',
            search: true,
            span: 24,
          },
          {
            label: '图片详情',
            prop: 'url',
            type: 'upload',
            width: 100,
            span: 24,
            listType: 'picture-img',
            fileSize: 3584,
            dataType: 'string',
            action: '/api/file/upload',
            propsHttp: {
              res: 'data',
              url: 'url',
            },
          },
          {
            label: '处理结果',
            prop: 'result',
            type: 'upload',
            width: 100,
            span: 24,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true,
            listType: 'picture-img',
            fileSize: 3584,
            dataType: 'string',
            action: '/api/file/upload',
            propsHttp: {
              res: 'data',
              url: 'url',
            },
          },
        ]
      },
      form: {},
      search: {},
      page: {
        total: 0,
        currentPage: 1,
        pageSize: 10,
        pageSizes: [5, 10, 15, 20, 50, 100, 150, 200]
      },
      query: {},
      loading: false,
      tableData: []
    }
  },
  created() {
    this.onLoad();
  },
  methods: {
    onLoad(page, params = {}) {
      this.loading = true;
      if (this.query.createTime != undefined && this.query.createTime != null && this.query.createTime.length > 0) {
        this.query.startTime = this.query.createTime[0];
        this.query.endTime = this.query.createTime[1]
        this.query.createTime = null;
      }
      getPage(this.page.currentPage, this.page.pageSize, Object.assign(params, this.query)).then(res => {
        const data = res.data.data;
        this.page.total = data.total;
        this.tableData = data.records;
        this.loading = false;
      })
    },
    rowSave(form, done, loading) {
      rowSave(form).then(res => {
        if (res.data.code == 200) {
          this.$message.success(res.data.msg);
          done();
        } else {
          this.$message.error(res.data.msg);
          loading();
        }
      }).then(() => {
        this.onLoad();
      }).catch(err => {
        loading();
      })
    },
    rowUpdate(row, index, done, loading) {
      rowEdit(row).then(res => {
        if (res.data.code == 200) {
          this.$message.success(res.data.msg);
          done();
        } else {
          this.$message.error(res.data.msg);
          loading();
        }
      }).then(() => {
        this.onLoad();
      }).catch(err => {
        loading();
      })
    },
    rowDel(row, done, loading) {
      rowDel(row).then(res => {
        if (res.data.code == 200) {
          this.$message.success(res.data.msg);
          done();
        } else {
          this.$message.error(res.data.msg);
          loading();
        }
      }).then(() => {
        this.onLoad();
      }).catch(err => {
        loading();
      })
    },
    searchReset() {
      this.query = {}
      this.onLoad(this.page)
    },
    searchChange(params, done) {
      this.query = params
      this.onLoad(this.page, params)
      done()
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize
    },
    refreshChange(refresh) {
      if (refresh) {
        this.onLoad(this.page, this.query)
      }
    },
  }
}
</script>

<style scoped>

</style>

效果展示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/980338.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计Hadoop+Spark+DeepSeek-R1大模型音乐推荐系统 音乐数据分析 音乐可视化 音乐爬虫 知识图谱 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

《Python实战进阶》No 11:微服务架构设计与 Python 实现

第11集&#xff1a;微服务架构设计与 Python 实现 2025年3月3日更新了代码和微服务运行后的系统返回信息截图&#xff0c;所有代码在 python3.11.5虚拟环境下运行通过。 微服务架构通过将复杂应用拆分为独立部署的小型服务&#xff0c;显著提升了系统的可扩展性和维护性。本集…

NC2227_约瑟夫环

题解: import java.util.Scanner;​public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int k sc.nextInt();int m sc.nextInt();int set 0;for(int i 2;i < n;i ){set (set m) % i;}System.out.p…

openEuler操作系统

一、OpenEuler简介 OpenEuler 是一款由华为发起、社区驱动的开源 Linux 操作系统&#xff0c;专注于企业级应用场景(如服务器、云计算、边缘计算等)。其前身是华为的 EulerOS&#xff0c;2019 年正式开源并捐赠给开放原子开源基金会&#xff0c;旨在构建一个中立、开放的生态系…

vite+react+ts如何集成redux状态管理工具,实现持久化缓存

1.安装插件 这里的redux-persist--进行数据的持久化缓存&#xff0c;确保页面刷新数据不会丢失 yarn add react-redux^9.2.0 redux-persist^6.0.0 reduxjs/toolkit^2.5.1 2.创建仓库文件夹 在项目的src文件夹下创建名为store的文件夹&#xff0c;里面的具体文件如下 featur…

大模型function calling:让AI函数调用更智能、更高效

大模型function calling&#xff1a;让AI函数调用更智能、更高效 随着大语言模型&#xff08;LLM&#xff09;的快速发展&#xff0c;其在实际应用中的能力越来越受到关注。Function Calling 是一种新兴的技术&#xff0c;允许大模型与外部工具或API进行交互&#xff0c;从而扩…

图像分类项目1:基于卷积神经网络的动物图像分类

一、选题背景及动机 在现代社会中&#xff0c;图像分类是计算机视觉领域的一个重要任务。动物图像分类具有广泛的应用&#xff0c;例如生态学研究、动物保护、农业监测等。通过对动物图像进行自动分类&#xff0c;可以帮助人们更好地了解动物种类、数量和分布情况&#xff0c;…

在 Ansys Maxwell 中分析磁场

在 Ansys Maxwell 中分析磁场 分析磁场的能力对于理解电磁系统至关重要。Ansys Maxwell 为工程师提供了强大的工具&#xff0c;帮助他们探索磁场数据并从中提取有价值的见解。在本指南中&#xff0c;我将深入研究 Ansys Maxwell 中的几种基本技术和方法&#xff0c;以有效地分…

[Lc滑动窗口_1] 长度最小的数组 | 无重复字符的最长子串 | 最大连续1的个数 III | 将 x 减到 0 的最小操作数

目录 1. 长度最小的字数组 题解 代码 ⭕2.无重复字符的最长子串 题解 代码 3.最大连续1的个数 III 题解 代码 4.将 x 减到 0 的最小操作数 题解 代码 1. 长度最小的字数组 题目链接&#xff1a;209.长度最小的字数组 题目分析: 给定一个含有 n 个 正整数 的数组…

数据库Redis数据库

目录 一、数据库类型 1、关系型数据库 2、非关系型数据库 3、关系型非关系型区别 二、Redis数据库 1、什么是Redis 3、Redis特点 4、Redis为什么读写快 5、部署Redis数据库 6、redis管理 7、Redis数据库五大类型 8、Redis数据库基础使用 9、redis五大类型增删查?…

蓝桥备赛(四)- 数组(下)

一 、 字符数组 1.1 介绍 数组的元素如果是字符类型 &#xff0c; 这种数组就是字符数组 &#xff0c; 字符数组可以是一维数组 &#xff0c; 可以是二维数组 (多维数组)。 接下来主要讨论一维的字符数组 : char arr1[5] //一维数组 char arr2[3][5] // 二维数组 C语言 中…

数据图表ScottPlot.WPF用法示例

目录 一、添加 NuGet 程序包&#xff08;5.0.47&#xff09; 二、MainWindow.xaml中添加引用 三、MainWindow.xaml.cs 具体使用代码 图表示例&#xff1a; 一、添加 NuGet 程序包&#xff08;5.0.47&#xff09; 二、MainWindow.xaml中添加引用 <Window x:Class"…

AtCoder Beginner Contest 001(A - 積雪深差、B - 視程の通報、C - 風力観測、D - 感雨時刻の整理)题目翻译

由于我发现网上很少有人会发很久之前AtCoder Beginner Contes的题&#xff0c;所以我打算从AtCoder Beginner Contest 001开始写。大约两周一更&#xff0c;需要的可以订阅专栏&#xff0c;感谢支持Thanks♪(&#xff65;ω&#xff65;)&#xff89; →题目讲解 A - 積雪深差 …

Windows 11【1001问】查看Windows是否激活的11种方法

在使用Windows 11的过程中&#xff0c;确保系统已正确激活是非常重要的一步。未激活的系统可能会限制某些功能的使用&#xff0c;并且无法获得最新的安全更新和支持。本文将详细介绍多种判断Windows 11是否已激活的11种方法&#xff0c;帮助用户快速了解自己的系统状态&#xf…

秒杀系统的常用架构是什么?怎么设计?

架构 秒杀系统需要单独部署&#xff0c;如果说放在订单服务里面&#xff0c;秒杀的系统压力太大了就会影响正常的用户下单。 常用架构&#xff1a; Redis 数据倾斜问题 第一步扣减库存时 假设现在有 10 个商品需要秒杀&#xff0c;正常情况下&#xff0c;这 10 个商品应该均…

USRP7440-通用软件无线电平台

1、产品描述 USRP7440基于第三代XILINX Zynq UltraScale RFSoC架构&#xff0c;它将射频ADC、DAC、ARM、FPGA等集成一体&#xff0c;瞬时带宽可以达到2.5GHz&#xff0c;尤其适合于射频直采应用&#xff0c;比如通信与雷达。 第一代RFSOC高达4GHz • 8x 或 16x 6.554GSPS DAC…

【Python机器学习】1.1. 机器学习(Machine Learning)介绍

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 1.1.1. 什么是机器学习&#xff1f; 举个例子&#xff1a; 小明1月工资1000&#xff0c;每月增长10%&#xff0c;第10月是多少&#xff…

协议-Airkiss

是什么&#xff1f; 设备 A 与外界没有建立任何实质性连接&#xff0c;可以称之为信息孤岛。设备 B 通过路由 或者直接 将 Wifi 的 ssid 与密码 UDP广播 传递给 A 为什么&#xff1f; 解决将无线网络的 ssid 与密码传输到设备难题 怎么做&#xff1f; 芯片自带AT指令开启Air…

python第十一课:并发编程 | 多任务交响乐团

&#x1f3af; 本节目标 理解多线程/多进程/协程的应用场景掌握threading与multiprocessing核心用法学会使用asyncio进行异步编程开发实战项目&#xff1a;高并发爬虫引擎破解GIL锁的性能迷思 1️⃣ 并发编程三剑客 &#x1f3bb; 生活化比喻&#xff1a; 多线程 → 餐厅多个…

linux中断调用流程(arm)

文章目录 ARM架构下Linux中断处理全流程解析&#xff1a;从硬件触发到驱动调用 ⚡**一、中断触发与硬件层响应** &#x1f50c;**1. 设备触发中断** &#x1f4e1; **二、CPU阶段&#xff1a;异常入口与上下文处理** &#x1f5a5;️**1. 异常模式切换** &#x1f504;**2. 跳转…