Com o avanço socioeconômico e a melhoria do padrão de vida, a frequência de renovação de vestuário tem aumentado significativamente. Grande quantidade de roupas usadas é subutilizada ou descartada, resultando em desperdício de recursos e impactos ambientais negativos. A reciclagem e doação de roupas usadas emergem como soluções eficazes, porém os métodos tradicionais enfrentam desafios como falta de transparência e baixa eficiência. Consequentemente, o desenvolvimento de um sistema de gestão eficiente e transparente para a doação de roupas usadas em comunidades é de suma importância. Este sistema visa integrar recursos comunitários, facilitar as doações pelos moradores e, simultaneamente, fornecer um canal acessível para que necessitados possam adquirir as peças.
O sistema emprega o SpringBoot como framework backend, combinado com a tecnologia frontend Vue.js, para entregar uma interface de usuário amigável e um processamento lógico de negócios eficiente. O banco de dados escolhido é o MySQL, garantindo segurança e estabilidade no armazenamento de dados. As funcionalidades do sistema incluem gestão de usuários, solicitação de doação de vestuário, gerenciamento de distribuição de roupas e estatísticas/aálise de dados. Através desta plataforma, usuários podem submeter pedidos de doação facilmente, administradores podem gerenciar estoques e registros de distribuição de forma ágil, e o sistema oferece recursos de visualização de dados para auxiliar os administradores a entenderem melhor o fluxo do vestuário.
Estrutura das Tabelas de Dados
Tabela de Informações de Usuários
Esta tabela armazena as informações básicas dos usuários do sistema, como ID do usuário, nome e informações de contato. Os tipos de usuário são categorizados como usuário comum e administrador, diferenciados por um campo de permissão. O horário de registro é gerado automaticamente pelo sistema para garantir a precisão dos dados. A estrutura da tabela é apresentada na Tabela 3-1.
| Nome do Campo | Tipo de Dado | Descrição |
|---|---|---|
| user_id | BIGINT | ID do usuário, chave primária |
| username | VARCHAR(50) | Nome de usuário |
| password | VARCHAR(100) | Senha (armazenada de forma criptografada) |
| phone | VARCHAR(20) | Número de telefone para contato |
| VARCHAR(50) | Endereço de e-mail | |
| user_type | TINYINT | Tipo de usuário (0: comum, 1: administrador) |
| register_time | DATETIME | Horário de registro |
Tabela de Doações de Roupas
Esta tabela registra as informações de doação de roupas submetidas pelos usuários, incluindo tipo de peça, quantidade e status da doação. O horário da doação é gerado automaticamente pelo sistema, e o campo de status é utilizado para rastrear o progresso do processamento das peças. A estrutura da tabela é apresentada na Tabela 3-2.
| Nome do Campo | Tipo de Dado | Descrição |
|---|---|---|
| donation_id | BIGINT | ID da doação, chave primária |
| user_id | BIGINT | ID do usuário doador |
| cloth_type | VARCHAR(50) | Tipo de peça de vestuário |
| quantity | INT | Quantidade de peças |
| donation_status | TINYINT | Status da doação (0: pendente de revisão, 1: recebido) |
| donate_time | DATETIME | Horário da doação |
Tabela de Distribuição de Roupas
Esta tabela registra o destino da distribuição das roupas, incluindo informações do recebedor e horário da distribuição. Os registros de distribuição estão associados aos registros de doação através de chaves estrangeiras para garantir a consistência dos dadoss. A estrutura da tabela é apresentada na Tabela 3-3.
| Nome do Campo | Tipo de Dado | Descrição |
|---|---|---|
| allocation_id | BIGINT | ID da distribuição, chave primária |
| donation_id | BIGINT | ID da doação associada |
| receiver_name | VARCHAR(50) | Nome do recebedor |
| receiver_phone | VARCHAR(20) | Telefone de contato do recebedor |
| allocate_time | DATETIME | Horário da distribuição |
| remarks | VARCHAR(200) | Observações |
Arquitetura Técnica
Backend: Spring Boot
O Spring Boot, como framework central para desenvolvimento Java corporativo moderno, redefine o modelo de desenvolvimento de aplicações com sua filosofia de "convenção sobre configuração".
- Inicialização com Configuração Zero: Integra mecanismos de configuração automática, reduzindo drasticamente a necessidade de arquivos de configuração XML.
- Servidor Embutido: Inclui servidores Tomcat/Jetty/Undertow, suportando implantação como um JAR executável independente.
- Pronto para Produção: Integra componentes de monitoramento como o Actuator, oferecendo recursos corporativos como verificação de saúde e coleta de métricas.
- Amigável a Microsserviços: Suporta nativamente arquiteturas distribuídas e integra-se perfeitamente com o ecossistema Spring Cloud.
Vantagens no Desenvolvimento: Através do sistema de dependências Starter e do auto-assembly inteligente, os desenvolvedores podem focar totalmente na implementação da lógica de negócios, em vez da construção da infraestrutura subjacente. O modelo de implantação com um único JAR executável simplifica enormemente os processos de operação e manutenção.
Frontend: Vue.js
O Vue.js, com seu design de framework progressivo e excelente experiência de desenvolvimento, tornou-se uma solução preferencial para o desenvolvimento front end moderno.
- Fluxo de Dados Reativo: Baseado em um sistema reativo de rastreamento de dependências, que permite atualizações eficientes da interface.
- Arquitetura Baseada em Componentes: O design de Componentes de Arquivo Único (SFC) permite o encapsulamento perfeito de estilos, lógica e templates.
- Design Progressivo e Flexível: Pode ser escalado de uma simples biblioteca de camada de visualização para uma solução completa de SPA (Single Page Application).
- Ecossistema Rico: Ferramentas oficiais como Vue Router, Vuex/Pinia e Vue CLI estão completas.
Eficiência no Desenvolvimento: A sintaxe intuitiva de template, combinada com um poderoso sistema de diretivas, torna as interações complexas do usuário simples e claras. O excelente suporte a TypeScript e as ferramentas de desenvolvedor fornecem garantia confiável para projetos de grande escala.
Código Essencial
Classe Principal do Backend (SpringBootApplication)
package com;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
// Escaneia os pacotes de Mapeamento do MyBatis
@MapperScan(basePackages = {"com.dao"})
@SpringBootApplication
public class CommunityDonationApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(CommunityDonationApp.class, args);
}
// Configuração para implantação como WAR
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
return applicationBuilder.sources(CommunityDonationApp.class);
}
}
Controlador de Usuários (UserController)
package com.controller;
import java.util.Date;
import java.util.Map;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.utils.ValidatorUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.annotation.IgnoreAuth;
import com.entity.UserEntity; // Renomeado de YonghuEntity
import com.entity.view.UserView; // Renomeado de YonghuView
import com.service.UserService; // Renomeado de YonghuService
import com.service.TokenService;
import com.utils.PageUtils;
import com.utils.R;
import com.utils.MPUtil;
import com.utils.MapUtils;
/**
* Gestão de Usuários
* API Backend
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService; // Injetado o serviço de usuário
@Autowired
private TokenService tokenService;
/**
* Autenticação de usuário
*/
@IgnoreAuth
@PostMapping(value = "/login")
public R login(String username, String password, HttpServletRequest request) {
UserEntity user = userService.selectOne(new EntityWrapper<userentity>().eq("username", username)); // Usando nome de campo renomeado
if(user == null || !user.getPassword().equals(password)) { // Usando nome de campo renomeado
return R.error("Nome de usuário ou senha incorretos");
}
// Gera um token para a sessão do usuário
String token = tokenService.generateToken(user.getUserId(), username, "user", "Usuário"); // Usando ID renomeado
return R.ok().put("token", token);
}
/**
* Registro de novo usuário
*/
@IgnoreAuth
@PostMapping("/register")
public R register(@RequestBody UserEntity user){
// Validação de entidade, se necessário
// ValidatorUtils.validateEntity(user);
UserEntity existingUser = userService.selectOne(new EntityWrapper<userentity>().eq("username", user.getUsername())); // Usando nome de campo renomeado
if(existingUser != null) {
return R.error("Este nome de usuário já está em uso.");
}
// Gera um ID único para o novo usuário
long newUserId = System.currentTimeMillis();
user.setUserId(newUserId); // Usando ID renomeado
userService.insert(user);
return R.ok("Registro bem-sucedido!");
}
/**
* Logout do usuário
*/
@RequestMapping("/logout")
public R logout(HttpServletRequest request) {
// Invalida a sessão atual
request.getSession().invalidate();
return R.ok("Logout realizado com sucesso.");
}
/**
* Recuperação de senha
*/
@IgnoreAuth
@PostMapping(value = "/resetPass")
public R resetPass(String username, HttpServletRequest request){
UserEntity user = userService.selectOne(new EntityWrapper<userentity>().eq("username", username));
if(user == null) {
return R.error("Usuário não encontrado.");
}
// Define uma senha padrão (exemplo: '123456')
user.setPassword("123456"); // Usando nome de campo renomeado
userService.updateById(user);
return R.ok("Senha redefinida para: 123456");
}
/**
* Listagem de usuários (para administração)
*/
@GetMapping("/page")
public R adminPage(@RequestParam Map<string object=""> params, UserEntity user){
// Cria um wrapper para consultas dinâmicas
EntityWrapper<userentity> ew = new EntityWrapper<>();
// Aplica filtros e ordenação conforme parâmetros
PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, user), params), params));
return R.ok().put("data", page);
}
/**
* Listagem de usuários (pública/frontend)
*/
@IgnoreAuth
@GetMapping("/list")
public R publicList(@RequestParam Map<string object=""> params, UserEntity user){
EntityWrapper<userentity> ew = new EntityWrapper<>();
PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, user), params), params));
return R.ok().put("data", page);
}
/**
* Consulta detalhada de usuários
*/
@GetMapping("/query")
public R query(UserEntity user){
EntityWrapper<userentity> ew = new EntityWrapper<>();
// Aplica filtros baseados nos campos do objeto UserEntity
ew.allEq(MPUtil.allEQMapPre(user, "user"));
UserView userView = userService.selectView(ew); // Usa UserView para informações detalhadas
return R.ok("Consulta de usuário realizada com sucesso.").put("data", userView);
}
/**
* Detalhes do usuário (para administração)
*/
@GetMapping("/info/{id}")
public R adminInfo(@PathVariable("id") Long id){
UserEntity user = userService.selectById(id);
return R.ok().put("data", user);
}
/**
* Detalhes do usuário (público/frontend)
*/
@IgnoreAuth
@GetMapping("/detail/{id}")
public R publicDetail(@PathVariable("id") Long id){
UserEntity user = userService.selectById(id);
return R.ok().put("data", user);
}
/**
* Criação de usuário (para administração)
*/
@PostMapping("/save")
public R adminSave(@RequestBody UserEntity user){
// Verifica se o nome de usuário já existe
if(userService.selectCount(new EntityWrapper<userentity>().eq("username", user.getUsername())) > 0) {
return R.error("Nome de usuário já em uso.");
}
// Gera um ID único
long newUserId = System.currentTimeMillis();
user.setUserId(newUserId);
userService.insert(user);
return R.ok("Usuário criado com sucesso.");
}
/**
* Criação de usuário (público/frontend)
*/
@PostMapping("/add")
public R publicAdd(@RequestBody UserEntity user){
if(userService.selectCount(new EntityWrapper<userentity>().eq("username", user.getUsername())) > 0) {
return R.error("Nome de usuário já em uso.");
}
long newUserId = System.currentTimeMillis();
user.setUserId(newUserId);
userService.insert(user);
return R.ok("Usuário adicionado com sucesso.");
}
/**
* Atualização de usuário
*/
@PutMapping("/update")
@Transactional
public R update(@RequestBody UserEntity user){
// Validação opcional
// ValidatorUtils.validateEntity(user);
// Verifica se o nome de usuário já existe para outro usuário
if(userService.selectCount(new EntityWrapper<userentity>().ne("user_id", user.getUserId()).eq("username", user.getUsername())) > 0) {
return R.error("Nome de usuário já em uso por outro registro.");
}
// Atualiza o registro completo do usuário
userService.updateById(user);
return R.ok("Informações do usuário atualizadas.");
}
/**
* Exclusão de usuários
*/
@DeleteMapping("/delete")
public R delete(@RequestBody Long[] ids){
userService.deleteBatchIds(java.util.Arrays.asList(ids));
return R.ok("Usuários excluídos com sucesso.");
}
}
</userentity></userentity></userentity></userentity></userentity></string></userentity></string></userentity></userentity></userentity>