完成社会服务的增删改查

This commit is contained in:
2025-10-30 14:24:20 +08:00
parent 019c99238b
commit 9f566027dc
22 changed files with 867 additions and 76 deletions

View File

@@ -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",

View File

@@ -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(

View File

@@ -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} // 非空字符串 -> 数据库存储该值
}

View File

@@ -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
}

View File

@@ -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 ""
}

View File

@@ -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%dpageSize%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
}

View File

@@ -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
}

View File

@@ -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字段为11=已删除),保留数据记录
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
}

View File

@@ -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 {