完成社会服务的增删改查
This commit is contained in:
@@ -6,6 +6,8 @@ package socialService
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service/internal/logic/socialService"
|
||||
@@ -18,10 +20,19 @@ import (
|
||||
func DeleteSocialServiceHandler(cfg *config.Config) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.DeleteSocialServiceReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
pathParts := strings.Split(r.URL.Path, "/")
|
||||
if len(pathParts) < 3 { // 确保路径格式正确
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format"))
|
||||
return
|
||||
}
|
||||
idStr := pathParts[3]
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID"))
|
||||
return
|
||||
}
|
||||
fmt.Println("idStr:", idStr)
|
||||
req.Id = id
|
||||
|
||||
mysqlCfg := cfg.MySQL
|
||||
dsn := fmt.Sprintf(
|
||||
|
||||
@@ -6,6 +6,8 @@ package socialService
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service/internal/logic/socialService"
|
||||
@@ -18,10 +20,19 @@ import (
|
||||
func GetSocialServiceHandler(cfg *config.Config) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetSocialServiceReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
pathParts := strings.Split(r.URL.Path, "/")
|
||||
if len(pathParts) < 3 { // 确保路径格式正确
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format"))
|
||||
return
|
||||
}
|
||||
idStr := pathParts[3]
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID"))
|
||||
return
|
||||
}
|
||||
fmt.Println("idStr:", idStr)
|
||||
req.Id = id
|
||||
|
||||
mysqlCfg := cfg.MySQL
|
||||
dsn := fmt.Sprintf(
|
||||
|
||||
@@ -56,8 +56,8 @@ type ListSocialServiceData struct {
|
||||
}
|
||||
|
||||
type ListSocialServiceReq struct {
|
||||
Page int `json:"page" form:"page" validate:"min=1"` // 页码(默认1)
|
||||
PageSize int `json:"page_size" form:"page_size" validate:"min=1,max=100"` // 每页条数(默认10,最大100)
|
||||
Page int `json:"page" validate:"min=1"` // 页码(默认1)
|
||||
PageSize int `json:"page_size" validate:"min=1,max=100"` // 每页条数(默认10,最大100)
|
||||
}
|
||||
|
||||
type ListSocialServiceResp struct {
|
||||
@@ -83,17 +83,17 @@ type SocialService struct {
|
||||
}
|
||||
|
||||
type UpdateSocialServiceReq struct {
|
||||
Id int64 `json:"-" path:"id" validate:"min=1"` // 社会服务ID(路径参数,必填)
|
||||
Title string `json:"title,omitempty"` // 标题
|
||||
Subtitle string `json:"subtitle,omitempty"` // 副标题
|
||||
CoverUrl string `json:"cover_url,omitempty"` // 封面图片URL
|
||||
Intro string `json:"intro,omitempty"` // 简介(纯文字)
|
||||
Content string `json:"content,omitempty"` // 内容(Markdown格式)
|
||||
ImageEditors string `json:"image_editors,omitempty"` // 图片编辑者名单(逗号分隔)
|
||||
TextEditors string `json:"text_editors,omitempty"` // 文字编辑者名单(逗号分隔)
|
||||
ChiefEditor string `json:"chief_editor,omitempty"` // 总编辑
|
||||
Proofreaders string `json:"proofreaders,omitempty"` // 校对者名单(逗号分隔)
|
||||
Reviewers string `json:"reviewers,omitempty"` // 审核者名单(逗号分隔)
|
||||
Id int64 `json:"id" validate:"min=1"` // 社会服务ID(路径参数,必填)
|
||||
Title string `json:"title,omitempty"` // 标题
|
||||
Subtitle string `json:"subtitle,omitempty"` // 副标题
|
||||
CoverUrl string `json:"cover_url,omitempty"` // 封面图片URL
|
||||
Intro string `json:"intro,omitempty"` // 简介(纯文字)
|
||||
Content string `json:"content,omitempty"` // 内容(Markdown格式)
|
||||
ImageEditors string `json:"image_editors,omitempty"` // 图片编辑者名单(逗号分隔)
|
||||
TextEditors string `json:"text_editors,omitempty"` // 文字编辑者名单(逗号分隔)
|
||||
ChiefEditor string `json:"chief_editor,omitempty"` // 总编辑
|
||||
Proofreaders string `json:"proofreaders,omitempty"` // 校对者名单(逗号分隔)
|
||||
Reviewers string `json:"reviewers,omitempty"` // 审核者名单(逗号分隔)
|
||||
}
|
||||
|
||||
type UpdateSocialServiceResp struct {
|
||||
|
||||
@@ -6,6 +6,8 @@ package socialServiceGovernmentProgram
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/logic/socialServiceGovernmentProgram"
|
||||
@@ -18,10 +20,19 @@ import (
|
||||
func DeleteSocialServiceGovernmentProgramHandler(cfg *config.Config) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.DeleteSocialServiceGovernmentProgramReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
pathParts := strings.Split(r.URL.Path, "/")
|
||||
if len(pathParts) < 4 { // 确保路径格式正确
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format"))
|
||||
return
|
||||
}
|
||||
idStr := pathParts[4]
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID"))
|
||||
return
|
||||
}
|
||||
fmt.Println("idStr:", idStr)
|
||||
req.Id = id
|
||||
mysqlCfg := cfg.MySQL
|
||||
dsn := fmt.Sprintf(
|
||||
"%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=Local",
|
||||
|
||||
@@ -6,6 +6,8 @@ package socialServiceGovernmentProgram
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/logic/socialServiceGovernmentProgram"
|
||||
@@ -18,10 +20,19 @@ import (
|
||||
func GetSocialServiceGovernmentProgramHandler(cfg *config.Config) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetSocialServiceGovernmentProgramReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
pathParts := strings.Split(r.URL.Path, "/")
|
||||
if len(pathParts) < 4 { // 确保路径格式正确
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format"))
|
||||
return
|
||||
}
|
||||
idStr := pathParts[4]
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID"))
|
||||
return
|
||||
}
|
||||
fmt.Println("idStr:", idStr)
|
||||
req.Id = id
|
||||
|
||||
mysqlCfg := cfg.MySQL
|
||||
dsn := fmt.Sprintf(
|
||||
|
||||
@@ -5,10 +5,12 @@ package socialServiceGovernmentProgram
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/model"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/svc"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
@@ -31,7 +33,66 @@ func NewCreateSocialServiceGovernmentProgramLogic(ctx context.Context, cfg *conf
|
||||
}
|
||||
|
||||
func (l *CreateSocialServiceGovernmentProgramLogic) CreateSocialServiceGovernmentProgram(req *types.CreateSocialServiceGovernmentProgramReq) (resp *types.CreateSocialServiceGovernmentProgramResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 兜底验证必填参数(避免validate失效场景)
|
||||
if req.Title == "" {
|
||||
return &types.CreateSocialServiceGovernmentProgramResp{
|
||||
Code: 400, // 参数错误码
|
||||
Msg: "标题不能为空",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 构造数据库实体(严格对应表字段)
|
||||
dbData := &model.SocialServiceGovernmentprogram{
|
||||
Title: req.Title,
|
||||
Subtitle: req.Subtitle,
|
||||
CoverUrl: req.CoverUrl,
|
||||
Intro: req.Intro,
|
||||
Content: stringToNullString(req.Content),
|
||||
ImageEditors: req.ImageEditors,
|
||||
TextEditors: req.TextEditors,
|
||||
ChiefEditor: req.ChiefEditor,
|
||||
Proofreaders: req.Proofreaders,
|
||||
Reviewers: req.Reviewers,
|
||||
// 按要求格式设置当前时间(yyyy-MM-dd HH:mm:ss)
|
||||
PublishTime: time.Now(),
|
||||
IsDelete: 0, // 默认未删除(0=未删除,1=已删除,适配软删除)
|
||||
}
|
||||
|
||||
// 3. 调用model插入数据
|
||||
result, err := l.model.Insert(context.Background(), dbData)
|
||||
if err != nil {
|
||||
fmt.Printf("插入社会服务政府项目失败:%v\n", err)
|
||||
return &types.CreateSocialServiceGovernmentProgramResp{
|
||||
Code: 500, // 服务器/数据库错误码
|
||||
Msg: "项目创建失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 4. 获取新增记录的主键ID
|
||||
newId, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
fmt.Printf("获取新增项目ID失败:%v\n", err)
|
||||
return &types.CreateSocialServiceGovernmentProgramResp{
|
||||
Code: 500,
|
||||
Msg: "项目创建成功,但获取ID失败",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 5. 构造成功响应
|
||||
resp = &types.CreateSocialServiceGovernmentProgramResp{
|
||||
Code: 0, // 0表示成功
|
||||
Msg: "项目创建成功",
|
||||
Data: types.CreateSocialServiceGovernmentProgramData{
|
||||
Id: newId, // 返回新增记录ID,供前端后续使用
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func stringToNullString(s string) sql.NullString {
|
||||
if s == "" {
|
||||
return sql.NullString{String: "", Valid: false} // 空字符串 -> 数据库 NULL
|
||||
}
|
||||
return sql.NullString{String: s, Valid: true} // 非空字符串 -> 数据库存储该值
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package socialServiceGovernmentProgram
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/model"
|
||||
@@ -30,7 +31,30 @@ func NewDeleteSocialServiceGovernmentProgramLogic(ctx context.Context, cfg *conf
|
||||
}
|
||||
|
||||
func (l *DeleteSocialServiceGovernmentProgramLogic) DeleteSocialServiceGovernmentProgram(req *types.DeleteSocialServiceGovernmentProgramReq) (resp *types.DeleteSocialServiceGovernmentProgramResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 兜底验证必填参数(避免validate失效,确保ID合法)
|
||||
if req.Id <= 0 {
|
||||
return &types.DeleteSocialServiceGovernmentProgramResp{
|
||||
Code: 400, // 参数错误码
|
||||
Msg: "项目ID不合法,必须大于0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 调用model执行删除操作(软删除/物理删除按model实现逻辑)
|
||||
err = l.model.Delete(context.Background(), req.Id)
|
||||
if err != nil {
|
||||
// 打印错误日志便于排查
|
||||
fmt.Printf("删除社会服务政府项目失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.DeleteSocialServiceGovernmentProgramResp{
|
||||
Code: 500, // 服务器/数据库错误码
|
||||
Msg: "项目删除失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. 构造成功响应
|
||||
resp = &types.DeleteSocialServiceGovernmentProgramResp{
|
||||
Code: 0, // 0表示成功
|
||||
Msg: "项目删除成功",
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ package socialServiceGovernmentProgram
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/model"
|
||||
@@ -31,7 +33,68 @@ func NewGetSocialServiceGovernmentProgramLogic(ctx context.Context, cfg *config.
|
||||
}
|
||||
|
||||
func (l *GetSocialServiceGovernmentProgramLogic) GetSocialServiceGovernmentProgram(req *types.GetSocialServiceGovernmentProgramReq) (resp *types.GetSocialServiceGovernmentProgramResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 兜底验证参数合法性
|
||||
if req.Id <= 0 {
|
||||
return &types.GetSocialServiceGovernmentProgramResp{
|
||||
Code: 400,
|
||||
Msg: "项目ID不合法,必须大于0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 调用model查询详情(已添加软删除过滤)
|
||||
program, err := l.model.FindOne(context.Background(), req.Id)
|
||||
if err != nil {
|
||||
if err == model.ErrNotFound {
|
||||
return &types.GetSocialServiceGovernmentProgramResp{
|
||||
Code: 404,
|
||||
Msg: "未找到该社会服务政府项目",
|
||||
}, nil
|
||||
}
|
||||
fmt.Printf("查询社会服务政府项目详情失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.GetSocialServiceGovernmentProgramResp{
|
||||
Code: 500,
|
||||
Msg: "查询项目详情失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. 软删除二次校验(双重保障)
|
||||
if program.IsDelete == 1 {
|
||||
return &types.GetSocialServiceGovernmentProgramResp{
|
||||
Code: 404,
|
||||
Msg: "未找到该社会服务政府项目(已删除)",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 核心修复:手动映射model层结构体到types层(解决类型不匹配)
|
||||
data := types.SocialServiceGovernmentProgram{
|
||||
Id: program.Id,
|
||||
Title: program.Title,
|
||||
Subtitle: program.Subtitle,
|
||||
CoverUrl: program.CoverUrl,
|
||||
Intro: program.Intro,
|
||||
Content: getNullStringValue(program.Content),
|
||||
ImageEditors: program.ImageEditors,
|
||||
TextEditors: program.TextEditors,
|
||||
ChiefEditor: program.ChiefEditor,
|
||||
Proofreaders: program.Proofreaders,
|
||||
Reviewers: program.Reviewers,
|
||||
PublishTime: program.PublishTime.Format("2006-01-02 15:04:05"),
|
||||
UpdateTime: program.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
// 4. 构造成功响应
|
||||
resp = &types.GetSocialServiceGovernmentProgramResp{
|
||||
Code: 0,
|
||||
Msg: "查询成功",
|
||||
Data: data, // 传入映射后的types层结构体
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func getNullStringValue(nullStr sql.NullString) string {
|
||||
if nullStr.Valid {
|
||||
return nullStr.String
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package socialServiceGovernmentProgram
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/model"
|
||||
@@ -30,7 +31,73 @@ func NewListSocialServiceGovernmentProgramLogic(ctx context.Context, cfg *config
|
||||
}
|
||||
|
||||
func (l *ListSocialServiceGovernmentProgramLogic) ListSocialServiceGovernmentProgram(req *types.ListSocialServiceGovernmentProgramReq) (resp *types.ListSocialServiceGovernmentProgramResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 分页参数校验(与请求参数validate规则保持一致)
|
||||
if req.Page < 1 {
|
||||
req.Page = 1 // 默认第一页
|
||||
}
|
||||
if req.PageSize < 1 || req.PageSize > 100 {
|
||||
req.PageSize = 10 // 默认10条/页,最大100条
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 计算分页偏移量(offset = (page-1) * pageSize)
|
||||
offset := (req.Page - 1) * req.PageSize
|
||||
|
||||
// 3. 调用model层查询:先查总数,再查列表数据
|
||||
// 3.1 查询符合条件的总条数(过滤已删除记录)
|
||||
total, err := l.model.Count(context.Background())
|
||||
if err != nil {
|
||||
fmt.Printf("查询社会服务政府项目总数失败:%v\n", err)
|
||||
return &types.ListSocialServiceGovernmentProgramResp{
|
||||
Code: 500,
|
||||
Msg: "获取列表总数失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3.2 查询当前页数据(带分页+软删除过滤)
|
||||
list, err := l.model.ListByPage(
|
||||
context.Background(),
|
||||
offset,
|
||||
req.PageSize,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("查询社会服务政府项目列表失败,offset:%d,pageSize:%d,错误:%v\n", offset, req.PageSize, err)
|
||||
return &types.ListSocialServiceGovernmentProgramResp{
|
||||
Code: 500,
|
||||
Msg: "获取项目列表失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 4. 批量转换model层数据到types层(处理类型差异)
|
||||
typesList := make([]types.SocialServiceGovernmentProgram, 0, len(list))
|
||||
for _, item := range list {
|
||||
// 单个项目数据转换(复用之前的字段映射逻辑)
|
||||
typesItem := types.SocialServiceGovernmentProgram{
|
||||
Id: item.Id,
|
||||
Title: item.Title,
|
||||
Subtitle: item.Subtitle,
|
||||
CoverUrl: item.CoverUrl,
|
||||
Intro: item.Intro,
|
||||
Content: getNullStringValue(item.Content), // 处理sql.NullString→string
|
||||
ImageEditors: item.ImageEditors,
|
||||
TextEditors: item.TextEditors,
|
||||
ChiefEditor: item.ChiefEditor,
|
||||
Proofreaders: item.Proofreaders,
|
||||
Reviewers: item.Reviewers,
|
||||
PublishTime: item.PublishTime.Format("2006-01-02 15:04:05"), // time.Time→string
|
||||
UpdateTime: item.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
typesList = append(typesList, typesItem)
|
||||
}
|
||||
|
||||
// 5. 构造分页响应
|
||||
resp = &types.ListSocialServiceGovernmentProgramResp{
|
||||
Code: 0,
|
||||
Msg: "查询成功",
|
||||
Data: types.ListSocialServiceGovernmentProgramData{
|
||||
Total: total, // 总条数
|
||||
List: typesList, // 转换后的当前页数据
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ package socialServiceGovernmentProgram
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_governmentprogram/internal/model"
|
||||
@@ -30,7 +33,84 @@ func NewUpdateSocialServiceGovernmentProgramLogic(ctx context.Context, cfg *conf
|
||||
}
|
||||
|
||||
func (l *UpdateSocialServiceGovernmentProgramLogic) UpdateSocialServiceGovernmentProgram(req *types.UpdateSocialServiceGovernmentProgramReq) (resp *types.UpdateSocialServiceGovernmentProgramResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 验证ID合法性(路径参数)
|
||||
if req.Id <= 0 {
|
||||
return &types.UpdateSocialServiceGovernmentProgramResp{
|
||||
Code: 400,
|
||||
Msg: "项目ID不合法,必须大于0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 查询原记录(检查是否存在且未被删除)
|
||||
oldProgram, err := l.model.FindOne(context.Background(), req.Id)
|
||||
if err != nil {
|
||||
if err == model.ErrNotFound {
|
||||
return &types.UpdateSocialServiceGovernmentProgramResp{
|
||||
Code: 404,
|
||||
Msg: "未找到该社会服务政府项目(或已被删除)",
|
||||
}, nil
|
||||
}
|
||||
fmt.Printf("查询待更新项目失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.UpdateSocialServiceGovernmentProgramResp{
|
||||
Code: 500,
|
||||
Msg: "查询项目信息失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. 构造更新数据(复用原记录字段,仅覆盖req中提供的非空值)
|
||||
updateData := &model.SocialServiceGovernmentprogram{
|
||||
Id: req.Id, // 必须携带ID用于WHERE条件
|
||||
// 基础字段:优先使用req中的值,未提供则保留原记录值
|
||||
Title: getUpdateValue(req.Title, oldProgram.Title),
|
||||
Subtitle: getUpdateValue(req.Subtitle, oldProgram.Subtitle),
|
||||
CoverUrl: getUpdateValue(req.CoverUrl, oldProgram.CoverUrl),
|
||||
Intro: getUpdateValue(req.Intro, oldProgram.Intro),
|
||||
// 特殊类型:string → sql.NullString(处理Content字段)
|
||||
Content: getNullStringFromUpdate(req.Content, oldProgram.Content),
|
||||
ImageEditors: getUpdateValue(req.ImageEditors, oldProgram.ImageEditors),
|
||||
TextEditors: getUpdateValue(req.TextEditors, oldProgram.TextEditors),
|
||||
ChiefEditor: getUpdateValue(req.ChiefEditor, oldProgram.ChiefEditor),
|
||||
Proofreaders: getUpdateValue(req.Proofreaders, oldProgram.Proofreaders),
|
||||
Reviewers: getUpdateValue(req.Reviewers, oldProgram.Reviewers),
|
||||
// 时间字段:保留原发布时间,更新最后修改时间为当前时间
|
||||
PublishTime: oldProgram.PublishTime, // 发布时间不随更新改变(除非有特殊需求)
|
||||
UpdateTime: time.Now(), // 强制更新为当前时间
|
||||
IsDelete: oldProgram.IsDelete, // 保留原删除状态(不允许通过更新接口修改删除状态)
|
||||
}
|
||||
|
||||
// 4. 调用model执行更新
|
||||
err = l.model.Update(context.Background(), updateData)
|
||||
if err != nil {
|
||||
fmt.Printf("更新社会服务政府项目失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.UpdateSocialServiceGovernmentProgramResp{
|
||||
Code: 500,
|
||||
Msg: "项目更新失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 5. 构造成功响应
|
||||
resp = &types.UpdateSocialServiceGovernmentProgramResp{
|
||||
Code: 0,
|
||||
Msg: "项目更新成功",
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
func getUpdateValue(newVal, oldVal string) string {
|
||||
if newVal != "" {
|
||||
return newVal
|
||||
}
|
||||
return oldVal
|
||||
}
|
||||
|
||||
// getNullStringFromUpdate:处理Content字段的更新(string → sql.NullString)
|
||||
// 若请求中提供了新内容,则包装为有效NullString;否则保留原记录的NullString
|
||||
func getNullStringFromUpdate(newContent string, oldNull sql.NullString) sql.NullString {
|
||||
if newContent != "" {
|
||||
return sql.NullString{
|
||||
String: newContent,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
return oldNull
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ type (
|
||||
FindOne(ctx context.Context, id int64) (*SocialServiceGovernmentprogram, error)
|
||||
Update(ctx context.Context, data *SocialServiceGovernmentprogram) error
|
||||
Delete(ctx context.Context, id int64) error
|
||||
Count(ctx context.Context) (int64, error)
|
||||
ListByPage(ctx context.Context, offset, limit int) ([]*SocialServiceGovernmentprogram, error)
|
||||
}
|
||||
|
||||
defaultSocialServiceGovernmentprogramModel struct {
|
||||
@@ -62,13 +64,14 @@ func newSocialServiceGovernmentprogramModel(conn sqlx.SqlConn) *defaultSocialSer
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceGovernmentprogramModel) Delete(ctx context.Context, id int64) error {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
// 软删除:更新is_delete字段为1(1=已删除),保留数据记录
|
||||
query := fmt.Sprintf("UPDATE %s SET `is_delete` = 1, `update_time` = NOW() WHERE `id` = ? AND `is_delete` = 0", m.table)
|
||||
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceGovernmentprogramModel) FindOne(ctx context.Context, id int64) (*SocialServiceGovernmentprogram, error) {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", socialServiceGovernmentprogramRows, m.table)
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and `is_delete` = 0 limit 1", socialServiceGovernmentprogramRows, m.table)
|
||||
var resp SocialServiceGovernmentprogram
|
||||
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||
switch err {
|
||||
@@ -93,6 +96,28 @@ func (m *defaultSocialServiceGovernmentprogramModel) Update(ctx context.Context,
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceGovernmentprogramModel) Count(ctx context.Context) (int64, error) {
|
||||
query := fmt.Sprintf("select count(*) from %s where `is_delete` = 0", m.table)
|
||||
var total int64
|
||||
err := m.conn.QueryRowCtx(ctx, &total, query)
|
||||
return total, err
|
||||
}
|
||||
|
||||
// 2. 分页查询列表数据(带偏移量+限制条数+软删除过滤)
|
||||
func (m *defaultSocialServiceGovernmentprogramModel) ListByPage(ctx context.Context, offset, limit int) ([]*SocialServiceGovernmentprogram, error) {
|
||||
query := fmt.Sprintf(
|
||||
"select %s from %s where `is_delete` = 0 order by `id` desc limit ?, ?",
|
||||
socialServiceGovernmentprogramRows, // 包内全局变量直接引用,无前缀
|
||||
m.table,
|
||||
)
|
||||
var list []*SocialServiceGovernmentprogram // 包内结构体直接引用,无model.前缀
|
||||
err := m.conn.QueryRowsCtx(ctx, &list, query, offset, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceGovernmentprogramModel) tableName() string {
|
||||
return m.table
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ type ListSocialServiceGovernmentProgramData struct {
|
||||
}
|
||||
|
||||
type ListSocialServiceGovernmentProgramReq struct {
|
||||
Page int `json:"page" form:"page" validate:"min=1"` // 页码(默认1)
|
||||
PageSize int `json:"page_size" form:"page_size" validate:"min=1,max=100"` // 每页条数(默认10,最大100)
|
||||
Page int `json:"page" validate:"min=1"` // 页码(默认1)
|
||||
PageSize int `json:"page_size" validate:"min=1,max=100"` // 每页条数(默认10,最大100)
|
||||
}
|
||||
|
||||
type ListSocialServiceGovernmentProgramResp struct {
|
||||
@@ -83,17 +83,17 @@ type SocialServiceGovernmentProgram struct {
|
||||
}
|
||||
|
||||
type UpdateSocialServiceGovernmentProgramReq struct {
|
||||
Id int64 `json:"-" path:"id" validate:"min=1"` // 社会服务政府项目ID(路径参数,必填)
|
||||
Title string `json:"title,omitempty"` // 标题
|
||||
Subtitle string `json:"subtitle,omitempty"` // 副标题
|
||||
CoverUrl string `json:"cover_url,omitempty"` // 封面图片URL
|
||||
Intro string `json:"intro,omitempty"` // 简介(纯文字)
|
||||
Content string `json:"content,omitempty"` // 内容(Markdown格式)
|
||||
ImageEditors string `json:"image_editors,omitempty"` // 图片编辑者名单(逗号分隔)
|
||||
TextEditors string `json:"text_editors,omitempty"` // 文字编辑者名单(逗号分隔)
|
||||
ChiefEditor string `json:"chief_editor,omitempty"` // 总编辑
|
||||
Proofreaders string `json:"proofreaders,omitempty"` // 校对者名单(逗号分隔)
|
||||
Reviewers string `json:"reviewers,omitempty"` // 审核者名单(逗号分隔)
|
||||
Id int64 `json:"id" validate:"min=1"` // 社会服务政府项目ID(路径参数,必填)
|
||||
Title string `json:"title,omitempty"` // 标题
|
||||
Subtitle string `json:"subtitle,omitempty"` // 副标题
|
||||
CoverUrl string `json:"cover_url,omitempty"` // 封面图片URL
|
||||
Intro string `json:"intro,omitempty"` // 简介(纯文字)
|
||||
Content string `json:"content,omitempty"` // 内容(Markdown格式)
|
||||
ImageEditors string `json:"image_editors,omitempty"` // 图片编辑者名单(逗号分隔)
|
||||
TextEditors string `json:"text_editors,omitempty"` // 文字编辑者名单(逗号分隔)
|
||||
ChiefEditor string `json:"chief_editor,omitempty"` // 总编辑
|
||||
Proofreaders string `json:"proofreaders,omitempty"` // 校对者名单(逗号分隔)
|
||||
Reviewers string `json:"reviewers,omitempty"` // 审核者名单(逗号分隔)
|
||||
}
|
||||
|
||||
type UpdateSocialServiceGovernmentProgramResp struct {
|
||||
|
||||
@@ -6,6 +6,8 @@ package socialServiceInternship
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_internship/internal/logic/socialServiceInternship"
|
||||
@@ -18,10 +20,19 @@ import (
|
||||
func DeleteSocialServiceInternshipHandler(cfg *config.Config) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.DeleteSocialServiceInternshipReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
pathParts := strings.Split(r.URL.Path, "/")
|
||||
if len(pathParts) < 4 { // 确保路径格式正确
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format"))
|
||||
return
|
||||
}
|
||||
idStr := pathParts[4]
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID"))
|
||||
return
|
||||
}
|
||||
fmt.Println("idStr:", idStr)
|
||||
req.Id = id
|
||||
|
||||
mysqlCfg := cfg.MySQL
|
||||
dsn := fmt.Sprintf(
|
||||
|
||||
@@ -6,6 +6,8 @@ package socialServiceInternship
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_internship/internal/logic/socialServiceInternship"
|
||||
@@ -18,10 +20,19 @@ import (
|
||||
func GetSocialServiceInternshipHandler(cfg *config.Config) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetSocialServiceInternshipReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
pathParts := strings.Split(r.URL.Path, "/")
|
||||
if len(pathParts) < 4 { // 确保路径格式正确
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid path format"))
|
||||
return
|
||||
}
|
||||
idStr := pathParts[4]
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, fmt.Errorf("invalid meeting ID"))
|
||||
return
|
||||
}
|
||||
fmt.Println("idStr:", idStr)
|
||||
req.Id = id
|
||||
|
||||
mysqlCfg := cfg.MySQL
|
||||
dsn := fmt.Sprintf(
|
||||
|
||||
@@ -5,6 +5,9 @@ package socialServiceInternship
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_internship/internal/model"
|
||||
@@ -30,7 +33,68 @@ func NewCreateSocialServiceInternshipLogic(ctx context.Context, cfg *config.Conf
|
||||
}
|
||||
|
||||
func (l *CreateSocialServiceInternshipLogic) CreateSocialServiceInternship(req *types.CreateSocialServiceInternshipReq) (resp *types.CreateSocialServiceInternshipResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 兜底验证必填参数(补充validate标签的校验漏洞)
|
||||
if req.Title == "" {
|
||||
return &types.CreateSocialServiceInternshipResp{
|
||||
Code: 400, // 参数错误码
|
||||
Msg: "标题不能为空",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 构造数据库实体(严格对应表字段与Insert参数顺序)
|
||||
dbData := &model.SocialServiceInternship{
|
||||
Title: req.Title,
|
||||
Subtitle: req.Subtitle,
|
||||
CoverUrl: req.CoverUrl,
|
||||
Intro: req.Intro,
|
||||
// 关键:string → sql.NullString(适配model层字段类型)
|
||||
Content: getNullString(req.Content),
|
||||
ImageEditors: req.ImageEditors,
|
||||
TextEditors: req.TextEditors,
|
||||
ChiefEditor: req.ChiefEditor,
|
||||
Proofreaders: req.Proofreaders,
|
||||
Reviewers: req.Reviewers,
|
||||
// 按要求格式设置发布时间(yyyy-MM-dd HH:mm:ss)
|
||||
PublishTime: time.Now(),
|
||||
IsDelete: 0, // 默认未删除(适配软删除逻辑)
|
||||
}
|
||||
|
||||
// 3. 调用model插入数据
|
||||
result, err := l.model.Insert(context.Background(), dbData)
|
||||
if err != nil {
|
||||
fmt.Printf("插入社会服务实习项目失败:%v\n", err)
|
||||
return &types.CreateSocialServiceInternshipResp{
|
||||
Code: 500, // 服务器/数据库错误码
|
||||
Msg: "实习项目创建失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 4. 获取新增记录的主键ID
|
||||
newId, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
fmt.Printf("获取新增实习项目ID失败:%v\n", err)
|
||||
return &types.CreateSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "实习项目创建成功,但获取ID失败",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 5. 构造成功响应
|
||||
resp = &types.CreateSocialServiceInternshipResp{
|
||||
Code: 0, // 0表示成功
|
||||
Msg: "实习项目创建成功",
|
||||
Data: types.CreateSocialServiceInternshipData{
|
||||
Id: newId, // 返回新增ID供前端后续使用
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// 辅助函数:string → sql.NullString(适配model层Content字段类型)
|
||||
func getNullString(val string) sql.NullString {
|
||||
return sql.NullString{
|
||||
String: val,
|
||||
Valid: val != "", // 非空字符串标记为有效,空字符串标记为无效(数据库存NULL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package socialServiceInternship
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_internship/internal/model"
|
||||
@@ -30,7 +31,45 @@ func NewDeleteSocialServiceInternshipLogic(ctx context.Context, cfg *config.Conf
|
||||
}
|
||||
|
||||
func (l *DeleteSocialServiceInternshipLogic) DeleteSocialServiceInternship(req *types.DeleteSocialServiceInternshipReq) (resp *types.DeleteSocialServiceInternshipResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 兜底验证ID合法性(补充validate标签校验漏洞)
|
||||
if req.Id <= 0 {
|
||||
return &types.DeleteSocialServiceInternshipResp{
|
||||
Code: 400,
|
||||
Msg: "实习项目ID不合法,必须大于0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 先查询记录是否存在且未被删除(避免删除不存在/已删除的记录)
|
||||
_, err = l.model.FindOne(context.Background(), req.Id)
|
||||
if err != nil {
|
||||
if err == model.ErrNotFound {
|
||||
return &types.DeleteSocialServiceInternshipResp{
|
||||
Code: 404,
|
||||
Msg: "未找到该社会服务实习项目(或已被删除)",
|
||||
}, nil
|
||||
}
|
||||
fmt.Printf("查询待删除实习项目失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.DeleteSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "查询项目信息失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. 调用Model层执行软删除(已修改为更新is_delete=1)
|
||||
err = l.model.Delete(context.Background(), req.Id)
|
||||
if err != nil {
|
||||
fmt.Printf("软删除社会服务实习项目失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.DeleteSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "项目删除失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 4. 构造成功响应
|
||||
resp = &types.DeleteSocialServiceInternshipResp{
|
||||
Code: 0,
|
||||
Msg: "实习项目删除成功",
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ package socialServiceInternship
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_internship/internal/model"
|
||||
@@ -30,7 +32,71 @@ func NewGetSocialServiceInternshipLogic(ctx context.Context, cfg *config.Config,
|
||||
}
|
||||
|
||||
func (l *GetSocialServiceInternshipLogic) GetSocialServiceInternship(req *types.GetSocialServiceInternshipReq) (resp *types.GetSocialServiceInternshipResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 兜底验证参数合法性
|
||||
if req.Id <= 0 {
|
||||
return &types.GetSocialServiceInternshipResp{
|
||||
Code: 400,
|
||||
Msg: "实习项目ID不合法,必须大于0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 调用Model查询详情(已添加软删除过滤)
|
||||
internship, err := l.model.FindOne(context.Background(), req.Id)
|
||||
if err != nil {
|
||||
// 区分"未找到"和"数据库错误"
|
||||
if err == model.ErrNotFound {
|
||||
return &types.GetSocialServiceInternshipResp{
|
||||
Code: 404,
|
||||
Msg: "未找到该社会服务实习项目",
|
||||
}, nil
|
||||
}
|
||||
fmt.Printf("查询社会服务实习项目详情失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.GetSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "查询项目详情失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. 软删除二次校验(双重保障,避免漏过滤)
|
||||
if internship.IsDelete == 1 {
|
||||
return &types.GetSocialServiceInternshipResp{
|
||||
Code: 404,
|
||||
Msg: "未找到该社会服务实习项目(已删除)",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 4. 手动映射Model→Types(处理类型转换)
|
||||
data := types.SocialServiceInternship{
|
||||
Id: internship.Id,
|
||||
Title: internship.Title,
|
||||
Subtitle: internship.Subtitle,
|
||||
CoverUrl: internship.CoverUrl,
|
||||
Intro: internship.Intro,
|
||||
// 关键:sql.NullString → string(处理Content字段)
|
||||
Content: getNullStringValue(internship.Content),
|
||||
ImageEditors: internship.ImageEditors,
|
||||
TextEditors: internship.TextEditors,
|
||||
ChiefEditor: internship.ChiefEditor,
|
||||
Proofreaders: internship.Proofreaders,
|
||||
Reviewers: internship.Reviewers,
|
||||
// 关键:time.Time → string(按要求格式)
|
||||
PublishTime: internship.PublishTime.Format("2006-01-02 15:04:05"),
|
||||
UpdateTime: internship.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
// 5. 构造成功响应
|
||||
resp = &types.GetSocialServiceInternshipResp{
|
||||
Code: 0,
|
||||
Msg: "查询成功",
|
||||
Data: data,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func getNullStringValue(nullStr sql.NullString) string {
|
||||
if nullStr.Valid {
|
||||
return nullStr.String
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package socialServiceInternship
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_internship/internal/model"
|
||||
@@ -30,7 +31,78 @@ func NewListSocialServiceInternshipLogic(ctx context.Context, cfg *config.Config
|
||||
}
|
||||
|
||||
func (l *ListSocialServiceInternshipLogic) ListSocialServiceInternship(req *types.ListSocialServiceInternshipReq) (resp *types.ListSocialServiceInternshipResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 分页参数校验与兜底(兼容前端未传/传参非法场景)
|
||||
if req.Page < 1 {
|
||||
req.Page = 1 // 默认第一页
|
||||
}
|
||||
if req.PageSize < 1 || req.PageSize > 100 {
|
||||
req.PageSize = 10 // 默认10条/页,最大限制100条
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 计算分页偏移量(offset = (page-1) * pageSize)
|
||||
offset := (req.Page - 1) * req.PageSize
|
||||
|
||||
// 3. 调用Model层查询:先查总数,再查分页数据
|
||||
// 3.1 查询未删除的总条数
|
||||
total, err := l.model.Count(context.Background())
|
||||
if err != nil {
|
||||
fmt.Printf("查询社会服务实习项目总数失败:%v\n", err)
|
||||
return &types.ListSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "获取列表总数失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3.2 查询当前页数据(带软删除过滤+分页+排序)
|
||||
list, err := l.model.ListByPage(
|
||||
context.Background(),
|
||||
offset,
|
||||
req.PageSize,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("查询实习项目列表失败,offset:%d,pageSize:%d,错误:%v\n", offset, req.PageSize, err)
|
||||
return &types.ListSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "获取项目列表失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 4. 批量转换Model→Types(处理类型差异,批量映射)
|
||||
typesList := make([]types.SocialServiceInternship, 0, len(list)) // 预分配容量提升性能
|
||||
for _, item := range list {
|
||||
typesItem := types.SocialServiceInternship{
|
||||
Id: item.Id,
|
||||
Title: item.Title,
|
||||
Subtitle: item.Subtitle,
|
||||
CoverUrl: item.CoverUrl,
|
||||
Intro: item.Intro,
|
||||
// sql.NullString → string(复用辅助函数)
|
||||
Content: getNullStringValue(item.Content),
|
||||
ImageEditors: item.ImageEditors,
|
||||
TextEditors: item.TextEditors,
|
||||
ChiefEditor: item.ChiefEditor,
|
||||
Proofreaders: item.Proofreaders,
|
||||
Reviewers: item.Reviewers,
|
||||
// time.Time → string(按要求格式:yyyy-MM-dd HH:mm:ss)
|
||||
PublishTime: item.PublishTime.Format("2006-01-02 15:04:05"),
|
||||
UpdateTime: item.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
typesList = append(typesList, typesItem)
|
||||
}
|
||||
|
||||
// 5. 构造分页响应
|
||||
resp = &types.ListSocialServiceInternshipResp{
|
||||
Code: 0,
|
||||
Msg: "查询成功",
|
||||
Data: types.ListSocialServiceInternshipData{
|
||||
Total: total, // 总条数(用于前端计算总页数)
|
||||
List: typesList, // 当前页转换后的数据列表
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 依赖的辅助函数(复用自Get接口,无需重复定义)
|
||||
// ------------------------------
|
||||
|
||||
@@ -5,6 +5,9 @@ package socialServiceInternship
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/JACKYMYPERSON/hldrCenter/config"
|
||||
"github.com/JACKYMYPERSON/hldrCenter/internal/social_service_internship/internal/model"
|
||||
@@ -30,7 +33,91 @@ func NewUpdateSocialServiceInternshipLogic(ctx context.Context, cfg *config.Conf
|
||||
}
|
||||
|
||||
func (l *UpdateSocialServiceInternshipLogic) UpdateSocialServiceInternship(req *types.UpdateSocialServiceInternshipReq) (resp *types.UpdateSocialServiceInternshipResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 1. 验证ID合法性(路径参数必填且有效)
|
||||
if req.Id <= 0 {
|
||||
return &types.UpdateSocialServiceInternshipResp{
|
||||
Code: 400,
|
||||
Msg: "实习项目ID不合法,必须大于0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return
|
||||
// 2. 查询原记录(确认存在且未被软删除)
|
||||
oldInternship, err := l.model.FindOne(context.Background(), req.Id)
|
||||
if err != nil {
|
||||
if err == model.ErrNotFound {
|
||||
return &types.UpdateSocialServiceInternshipResp{
|
||||
Code: 404,
|
||||
Msg: "未找到该社会服务实习项目(或已被删除)",
|
||||
}, nil
|
||||
}
|
||||
fmt.Printf("查询待更新实习项目失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.UpdateSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "查询项目信息失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. 构造更新数据(增量更新:仅覆盖请求中提供的非空值,其余保留原记录)
|
||||
updateData := &model.SocialServiceInternship{
|
||||
Id: req.Id, // 主键ID,用于SQL WHERE条件
|
||||
// 基础字段:有新值则更新,无则保留原值
|
||||
Title: getUpdateValue(req.Title, oldInternship.Title),
|
||||
Subtitle: getUpdateValue(req.Subtitle, oldInternship.Subtitle),
|
||||
CoverUrl: getUpdateValue(req.CoverUrl, oldInternship.CoverUrl),
|
||||
Intro: getUpdateValue(req.Intro, oldInternship.Intro),
|
||||
// 特殊字段:string → sql.NullString(适配Content字段类型)
|
||||
Content: getNullStringFromUpdate(req.Content, oldInternship.Content),
|
||||
ImageEditors: getUpdateValue(req.ImageEditors, oldInternship.ImageEditors),
|
||||
TextEditors: getUpdateValue(req.TextEditors, oldInternship.TextEditors),
|
||||
ChiefEditor: getUpdateValue(req.ChiefEditor, oldInternship.ChiefEditor),
|
||||
Proofreaders: getUpdateValue(req.Proofreaders, oldInternship.Proofreaders),
|
||||
Reviewers: getUpdateValue(req.Reviewers, oldInternship.Reviewers),
|
||||
// 时间字段:发布时间保留原值,更新时间强制设为当前时间
|
||||
PublishTime: oldInternship.PublishTime, // 发布时间不随更新改变
|
||||
UpdateTime: time.Now(), // 最后修改时间自动更新
|
||||
IsDelete: oldInternship.IsDelete, // 保留删除状态(不允许通过更新接口修改)
|
||||
}
|
||||
|
||||
// 4. 调用Model层执行更新
|
||||
err = l.model.Update(context.Background(), updateData)
|
||||
if err != nil {
|
||||
fmt.Printf("更新社会服务实习项目失败,ID:%d,错误:%v\n", req.Id, err)
|
||||
return &types.UpdateSocialServiceInternshipResp{
|
||||
Code: 500,
|
||||
Msg: "项目更新失败,请稍后重试",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 5. 构造成功响应
|
||||
resp = &types.UpdateSocialServiceInternshipResp{
|
||||
Code: 0,
|
||||
Msg: "实习项目更新成功",
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// 辅助函数(复用自政府项目模块,无需重复开发)
|
||||
// ------------------------------
|
||||
|
||||
// getUpdateValue:处理普通字符串字段的增量更新
|
||||
func getUpdateValue(newVal, oldVal string) string {
|
||||
if newVal != "" {
|
||||
return newVal // 有新值则使用新值
|
||||
}
|
||||
return oldVal // 无新值则保留原值
|
||||
}
|
||||
|
||||
// getNullStringFromUpdate:处理Content字段的增量更新(string → sql.NullString)
|
||||
func getNullStringFromUpdate(newContent string, oldNull sql.NullString) sql.NullString {
|
||||
if newContent != "" {
|
||||
// 新值非空:包装为有效sql.NullString
|
||||
return sql.NullString{
|
||||
String: newContent,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
// 新值为空:保留原记录的sql.NullString状态(可能是NULL或有效字符串)
|
||||
return oldNull
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ type (
|
||||
FindOne(ctx context.Context, id int64) (*SocialServiceInternship, error)
|
||||
Update(ctx context.Context, data *SocialServiceInternship) error
|
||||
Delete(ctx context.Context, id int64) error
|
||||
Count(ctx context.Context) (int64, error)
|
||||
ListByPage(ctx context.Context, offset, limit int) ([]*SocialServiceInternship, error)
|
||||
}
|
||||
|
||||
defaultSocialServiceInternshipModel struct {
|
||||
@@ -62,13 +64,17 @@ func newSocialServiceInternshipModel(conn sqlx.SqlConn) *defaultSocialServiceInt
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceInternshipModel) Delete(ctx context.Context, id int64) error {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
// 软删除逻辑:更新is_delete=1,保留数据;同时更新最后修改时间
|
||||
query := fmt.Sprintf(
|
||||
"UPDATE %s SET `is_delete` = 1, `update_time` = NOW() WHERE `id` = ? AND `is_delete` = 0",
|
||||
m.table,
|
||||
)
|
||||
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceInternshipModel) FindOne(ctx context.Context, id int64) (*SocialServiceInternship, error) {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", socialServiceInternshipRows, m.table)
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and `is_delete` = 0 limit 1", socialServiceInternshipRows, m.table)
|
||||
var resp SocialServiceInternship
|
||||
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||
switch err {
|
||||
@@ -93,6 +99,29 @@ func (m *defaultSocialServiceInternshipModel) Update(ctx context.Context, data *
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceInternshipModel) Count(ctx context.Context) (int64, error) {
|
||||
query := fmt.Sprintf("select count(*) from %s where `is_delete` = 0", m.table)
|
||||
var total int64
|
||||
err := m.conn.QueryRowCtx(ctx, &total, query)
|
||||
return total, err
|
||||
}
|
||||
|
||||
// ListByPage:分页查询未删除的记录(按ID倒序,最新在前)
|
||||
func (m *defaultSocialServiceInternshipModel) ListByPage(ctx context.Context, offset, limit int) ([]*SocialServiceInternship, error) {
|
||||
query := fmt.Sprintf(
|
||||
"select %s from %s where `is_delete` = 0 order by `id` desc limit ?, ?",
|
||||
socialServiceInternshipRows, // 包内全局变量,直接引用(无前缀)
|
||||
m.table,
|
||||
)
|
||||
// 修复点:切片类型去掉 model. 前缀(当前在model包内,直接使用结构体)
|
||||
var list []*SocialServiceInternship
|
||||
err := m.conn.QueryRowsCtx(ctx, &list, query, offset, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (m *defaultSocialServiceInternshipModel) tableName() string {
|
||||
return m.table
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ type ListSocialServiceInternshipData struct {
|
||||
}
|
||||
|
||||
type ListSocialServiceInternshipReq struct {
|
||||
Page int `json:"page" form:"page" validate:"min=1"` // 页码(默认1)
|
||||
PageSize int `json:"page_size" form:"page_size" validate:"min=1,max=100"` // 每页条数(默认10,最大100)
|
||||
Page int `json:"page" validate:"min=1"` // 页码(默认1)
|
||||
PageSize int `json:"page_size" validate:"min=1,max=100"` // 每页条数(默认10,最大100)
|
||||
}
|
||||
|
||||
type ListSocialServiceInternshipResp struct {
|
||||
@@ -83,17 +83,17 @@ type SocialServiceInternship struct {
|
||||
}
|
||||
|
||||
type UpdateSocialServiceInternshipReq struct {
|
||||
Id int64 `json:"-" path:"id" validate:"min=1"` // 社会服务实习ID(路径参数,必填)
|
||||
Title string `json:"title,omitempty"` // 标题
|
||||
Subtitle string `json:"subtitle,omitempty"` // 副标题
|
||||
CoverUrl string `json:"cover_url,omitempty"` // 封面图片URL
|
||||
Intro string `json:"intro,omitempty"` // 简介(纯文字)
|
||||
Content string `json:"content,omitempty"` // 内容(Markdown格式)
|
||||
ImageEditors string `json:"image_editors,omitempty"` // 图片编辑者名单(逗号分隔)
|
||||
TextEditors string `json:"text_editors,omitempty"` // 文字编辑者名单(逗号分隔)
|
||||
ChiefEditor string `json:"chief_editor,omitempty"` // 总编辑
|
||||
Proofreaders string `json:"proofreaders,omitempty"` // 校对者名单(逗号分隔)
|
||||
Reviewers string `json:"reviewers,omitempty"` // 审核者名单(逗号分隔)
|
||||
Id int64 `json:"id" validate:"min=1"` // 社会服务实习ID(路径参数,必填)
|
||||
Title string `json:"title,omitempty"` // 标题
|
||||
Subtitle string `json:"subtitle,omitempty"` // 副标题
|
||||
CoverUrl string `json:"cover_url,omitempty"` // 封面图片URL
|
||||
Intro string `json:"intro,omitempty"` // 简介(纯文字)
|
||||
Content string `json:"content,omitempty"` // 内容(Markdown格式)
|
||||
ImageEditors string `json:"image_editors,omitempty"` // 图片编辑者名单(逗号分隔)
|
||||
TextEditors string `json:"text_editors,omitempty"` // 文字编辑者名单(逗号分隔)
|
||||
ChiefEditor string `json:"chief_editor,omitempty"` // 总编辑
|
||||
Proofreaders string `json:"proofreaders,omitempty"` // 校对者名单(逗号分隔)
|
||||
Reviewers string `json:"reviewers,omitempty"` // 审核者名单(逗号分隔)
|
||||
}
|
||||
|
||||
type UpdateSocialServiceInternshipResp struct {
|
||||
|
||||
Reference in New Issue
Block a user