Softhub软件下载站实战开发(十四):软件收藏集设计

文章目录

  • Softhub软件下载站实战开发(十四):软件收藏集设计
    • 引言:为什么我们需要收藏集功能?
    • 收藏集功能的核心价值
      • 1. 资源整合与分类管理
    • 技术架构设计
      • 数据库设计
      • 核心接口设计
    • 后端实现详解
      • 1. 收藏集服务层
      • 2. 列表查询实现
      • 3. 添加软件实现
    • 前端实现详解
      • 1. 收藏集列表页面
      • 2. 软件管理弹窗组件
      • 3. 软件选择与添加逻辑

Softhub软件下载站实战开发(十四):软件收藏集设计

前面几篇我们讲了软件管理相关实现,本篇我们实现后台管理最后一个功能,软件收藏集

引言:为什么我们需要收藏集功能?

在当今数字化时代,软件资源呈现爆炸式增长。用户面对海量软件时,常常会遇到几个核心痛点:

  1. ​资源分散​​:相关软件分散在不同分类中,难以集中管理
  2. ​效率低下​​:每次使用都需要重新搜索和下载
  3. ​知识沉淀​​:优秀的软件组合无法有效保存和分享
  4. ​个性化缺失​​:平台难以根据用户偏好提供精准推荐

收藏集(Resource Set)功能的引入,正是为了解决这些痛点。它就像数字世界的"收藏夹",但比传统收藏功能更强大、更系统化。在Softhub平台中,收藏集不仅是简单的软件列表,更是一个完整的资源组织系统。

收藏集功能的核心价值

1. 资源整合与分类管理

收藏集允许用户将相关软件组织在一起形成主题合集。例如:

  • “前端开发必备工具集”:包含VS Code、Chrome、Git等
  • “设计师创意套装”:包含Photoshop、Illustrator、Figma等
  • “效率提升神器”:包含Notion、Todoist、RescueTime等

这种组织方式实现了多维度的资源聚合。

技术架构设计

数据库设计

核心接口设计

我们设计了完整的RESTful API接口:

端点 方法 描述 参数
/dsResourceSet GET 获取收藏集列表 分页、搜索条件
/dsResourceSet/add POST 创建新收藏集 名称、图标等
/dsResourceSet/edit PUT 修改收藏集 ID、新数据
/dsResourceSet/del DELETE 删除收藏集 ID
/dsResourceSetRel/softwareList GET 获取收藏集软件列表 收藏集ID
/dsResourceSetRel/addSoftware POST 添加软件到收藏集 收藏集ID、软件ID数组
/dsResourceSetRel/removeSoftware DELETE 从收藏集移除软件 收藏集ID、软件ID

后端实现详解

1. 收藏集服务层

type IDsResourceSet interface {
	List(ctx context.Context, req *api.DsResourceSetListReq) (total interface{}, res []*model.DsResourceSetInfo, err error)
	Add(ctx context.Context, req *api.DsResourceSetAddReq) (err error)
	Edit(ctx context.Context, req *api.DsResourceSetEditReq) (err error)
	Delete(ctx context.Context, id uint) (err error)
	BatchDelete(ctx context.Context, ids []uint) (err error)
	GetById(ctx context.Context, id uint) (res *model.DsResourceSetInfo, err error)
	ClientList(ctx context.Context, req *clientApi.DsResourceSetListReq) (total interface{}, res []*model.DsResourceSetInfo, err error)
}

type IDsSoftwareResource interface {
	List(ctx context.Context, req *api.DsSoftwareResourceListReq) (total interface{}, res []*model.DsSoftwareResourceInfo, err error)
	Add(ctx context.Context, req *api.DsSoftwareResourceAddReq) (err error)
	Edit(ctx context.Context, req *api.DsSoftwareResourceEditReq) (err error)
	Delete(ctx context.Context, id interface{}) (err error)
	BatchDelete(ctx context.Context, ids []interface{}) (err error)
	GetById(ctx context.Context, id interface{}) (res *model.DsSoftwareResourceInfo, err error)
	AddCount(ctx context.Context, resourceId interface{}) (count uint, err error)
	SwitchDefault(ctx context.Context, req *api.DsSoftwareResourceSwitchDefaultReq) (err error)
	InitChunkUpload(ctx context.Context, req *api.ChunkInitReq) (res *api.ChunkInitRes, err error)
	UploadChunk(ctx context.Context, req *api.ChunkUploadReq) (res *api.ChunkUploadRes, err error)
	MergeChunks(ctx context.Context, req *api.ChunkMergeReq) (res *api.ChunkMergeRes, err error)
}

2. 列表查询实现

func (s sDsResourceSet) List(ctx context.Context, req *api.DsResourceSetListReq) (total interface{}, dsResourceSetList []*model.DsResourceSetInfo, err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		m := dao.DsResourceSet.Ctx(ctx)
		columns := dao.DsResourceSet.Columns()
		if req.Name != "" {
			m = m.Where(fmt.Sprintf("%s like ?", columns.Name), "%"+req.Name+"%")
		}
		total, err = m.Count()
		liberr.ErrIsNil(ctx, err, "获取资源集管理列表失败")
		orderBy := req.OrderBy
		if orderBy == "" {
			orderBy = "created_at desc"
		}

		// 使用LEFT JOIN统计软件数量
		err = m.Fields(fmt.Sprintf("%s.*, COUNT(DISTINCT rel.software_id) as software_count", dao.DsResourceSet.Table())).
			LeftJoin("ds_resource_set_rel rel", fmt.Sprintf("%s.id = rel.set_id", dao.DsResourceSet.Table())).
			Group(fmt.Sprintf("%s.id", dao.DsResourceSet.Table())).
			Page(req.PageNum, req.PageSize).
			Order(orderBy).
			Scan(&dsResourceSetList)
		liberr.ErrIsNil(ctx, err, "获取资源集管理列表失败")
	})
	return
}

3. 添加软件实现

func (s sDsResourceSet) Add(ctx context.Context, req *api.DsResourceSetAddReq) (err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		//  查询是否已经存在

		// add
		_, err = dao.DsResourceSet.Ctx(ctx).Insert(do.DsResourceSet{
			Name:        req.Name,        // 资源集名称
			Icon:        req.Icon,        // 图标
			Description: req.Description, // 资源描述
			Remark:      req.Remark,      // 备注
			CreatedBy:   SystemS.Context().GetUserId(ctx),
			UpdatedBy:   SystemS.Context().GetUserId(ctx),
		})
		liberr.ErrIsNil(ctx, err, "新增资源集管理失败")
	})
	return
}

前端实现详解

1. 收藏集列表页面


2. 软件管理弹窗组件

关闭
点击添加按钮
取消或完成添加
主弹窗
添加软件弹窗
搜索状态
选择软件
确认添加

代码实现


3. 软件选择与添加逻辑

// 获取所有软件列表(带搜索和分页)
const getAllSoftwareList = () => {
  state.addLoading = true;
  const params = {
    ...state.allSoftwareParam,
    softwareName: state.searchKeyword || undefined
  };
  getDsSoftwareList(params)
    .then(res => {
      state.allSoftwareList = processBigIntIds(res.data.dsSoftwareList || []);
      state.allSoftwareTotal = res.data.total || 0;
    })
    .finally(() => {
      state.addLoading = false;
    });
};

// 添加选中软件到收藏集
const onAddSoftware = () => {
  if (state.selectedSoftwareIds.length === 0) {
    ElMessage.warning('请选择要添加的软件');
    return;
  }

  state.adding = true;
  const softwareIds = state.selectedSoftwareIds.map(id => toBigIntString(id));
  addSoftwareToResourceSet({
    setId: state.currentSetId,
    softwareIds: softwareIds
  })
    .then(() => {
      ElMessage.success('添加软件成功');
      state.isShowAddDialog = false;
      getCurrentSoftwareList();
    })
    .finally(() => {
      state.adding = false;
    });
};

softhub系列往期文章

  1. Softhub软件下载站实战开发(一):项目总览
  2. Softhub软件下载站实战开发(二):项目基础框架搭建
  3. Softhub软件下载站实战开发(三):平台管理模块实战
  4. Softhub软件下载站实战开发(四):代码生成器设计与实现
  5. Softhub软件下载站实战开发(五):分类模块实现
  6. Softhub软件下载站实战开发(六):软件配置面板实现
  7. Softhub软件下载站实战开发(七):集成MinIO实现文件存储功能
  8. Softhub软件下载站实战开发(八):编写软件后台管理
  9. Softhub软件下载站实战开发(九):编写软件配置管理界面
  10. Softhub软件下载站实战开发(十):实现图片视频上传下载接口
  11. Softhub软件下载站实战开发(十一):软件分片上传接口实现
  12. Softhub软件下载站实战开发(十二):软件管理编辑页面实现
  13. Softhub软件下载站实战开发(十三):软件管理前端分片上传实现

你可能感兴趣的:(softHub,前端,golang)