瀏覽代碼

新增项目接口

xuwenhao 8 月之前
父節點
當前提交
354f8f6304

+ 24 - 0
server/api/v1/admin/department.go

@@ -1,6 +1,7 @@
 package admin
 
 import (
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"server/dao"
 	"server/global"
@@ -111,3 +112,26 @@ func (da *DepartmentApi) DeleteDep(c *gin.Context) {
 	}
 	response.OkWithMessage("删除成功", c)
 }
+
+// FilesUpload 文件上传
+func (da *DepartmentApi) FilesUpload(c *gin.Context) {
+	form, err := c.MultipartForm()
+	files := form.File["file"]
+	fmt.Println(files)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		//ignore
+		return
+	}
+	cs := c.PostForm("cs")
+
+	fmt.Println(cs)
+	for _, file := range files {
+		dst := file.Filename
+		// gin 简单做了封装,拷贝了文件流
+		if err := c.SaveUploadedFile(file, "./uploads/file/"+dst); err != nil {
+			// ignore
+		}
+	}
+	response.Ok(c)
+}

+ 2 - 0
server/api/v1/admin/enter.go

@@ -4,8 +4,10 @@ import "server/service"
 
 type ApiGroup struct {
 	DepartmentApi
+	ProjectApi
 }
 
 var (
 	departmentService = service.ServiceGroupApp.AdminServiceGroup.DepartmentService
+	projectService    = service.ServiceGroupApp.AdminServiceGroup.ProjectService
 )

+ 150 - 0
server/api/v1/admin/project.go

@@ -0,0 +1,150 @@
+package admin
+
+import (
+	"encoding/json"
+	"github.com/gin-gonic/gin"
+	"server/dao"
+	"server/model/common/request"
+	"server/model/common/response"
+	"strconv"
+)
+
+type ProjectApi struct{}
+
+func (pa *ProjectApi) QueryProjectList(c *gin.Context) {
+	var search request.SearchProject
+	err := c.ShouldBindJSON(&search)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+
+	list, total, err := projectService.QueryProjectList(search)
+
+	response.OkWithDetailed(response.PageResult{
+		List:     list,
+		Total:    total,
+		Page:     search.PageInfo.Page,
+		PageSize: search.PageInfo.PageSize,
+	}, "获取成功", c)
+}
+
+func (pa *ProjectApi) QueryProjectByCode(c *gin.Context) {
+	code := c.Param("code")
+	if code == "" {
+		response.FailWithMessage("编号不能为空", c)
+		return
+	}
+	project, err := projectService.QueryProjectByCode(code)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	response.OkWithData(project, c)
+}
+
+func (pa *ProjectApi) CreateProject(c *gin.Context) {
+	//var project dao.Project
+	//err := c.ShouldBindJSON(&project)
+	//if err != nil {
+	//	response.FailWithMessage(err.Error(), c)
+	//	return
+	//}
+
+	form, err := c.MultipartForm()
+	files := form.File["file"]
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		return
+	}
+	projectJson := c.PostForm("project")
+
+	var project dao.Project
+	err = json.Unmarshal([]byte(projectJson), &project)
+	if err != nil {
+		response.FailWithMessage("JSON失败", c)
+		return
+	}
+	for _, file := range files {
+		dst := file.Filename
+
+		projectFile := dao.ProjectFile{
+			Name: dst,
+			Path: "./uploads/file/" + dst,
+		}
+
+		project.Files = append(project.Files, projectFile)
+
+		// gin 简单做了封装,拷贝了文件流
+		if err := c.SaveUploadedFile(file, "./uploads/file/"+dst); err != nil {
+			response.FailWithMessage("上传失败", c)
+			return
+		}
+	}
+	err = projectService.CreateProject(project)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+
+	response.OkWithMessage("创建成功", c)
+}
+
+func (pa *ProjectApi) CreateProjectFile(c *gin.Context) {
+	var projectFile dao.ProjectFile
+	err := c.ShouldBindJSON(&projectFile)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	err = projectService.CreateProjectFile(projectFile)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	response.OkWithMessage("创建成功", c)
+}
+
+func (pa *ProjectApi) UpdateProject(c *gin.Context) {
+	var project dao.Project
+	err := c.ShouldBindJSON(&project)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	err = projectService.UpdateProject(project)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	response.OkWithMessage("更新成功", c)
+}
+
+func (pa *ProjectApi) DeleteProject(c *gin.Context) {
+	code := c.Param("code")
+	if code == "" {
+		response.FailWithMessage("编号不能为空", c)
+		return
+	}
+	err := projectService.DeleteProject(code)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	response.OkWithMessage("删除成功", c)
+}
+
+func (pa *ProjectApi) DeleteProjectFile(c *gin.Context) {
+	id := c.Param("id")
+	i, err := strconv.Atoi(id)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	err = projectService.DeleteProjectFile(uint(i))
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	response.OkWithMessage("删除成功", c)
+}

+ 2 - 0
server/build.bat

@@ -0,0 +1,2 @@
+%此脚本需要在命令窗口执行,不能直接运行%
+go env -w CGO_ENABLED=0 GOOS=linux GOARCH=amd64 && go build -o build/lc_finance ./

+ 88 - 0
server/dao/project.go

@@ -0,0 +1,88 @@
+package dao
+
+import (
+	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
+	"server/global"
+)
+
+type Project struct {
+	global.GVA_MODEL
+	Code       string          `json:"code" form:"code" gorm:"comment:项目编号"`
+	Name       string          `json:"name" form:"name" gorm:"comment:项目名称"`
+	Principal  uint            `json:"principal" form:"principal" gorm:"comment:负责人"`
+	Price      decimal.Decimal `json:"price" form:"price" gorm:"type:decimal(10,2);not null"`
+	Illustrate string          `json:"illustrate" form:"illustrate" gorm:"comment:说明"`
+	Source     string          `json:"source" form:"source" gorm:"comment:来源"`
+	Progress   int             `json:"progress" form:"progress" gorm:"comment:进度"`
+	State      int             `json:"state" form:"state" gorm:"comment:状态"`
+	Files      []ProjectFile   `json:"files" form:"files" gorm:"-"`
+}
+
+func (Project) TableName() string {
+	return "project"
+}
+
+// TODO:项目查询
+
+// QueryProjectList 查询项目列表
+func QueryProjectList(limit, offset, state int, name, time string) (project []*Project, total int64, err error) {
+	// 创建db
+	db := global.GVA_DB.Model(&Project{})
+	// 如果有条件搜索 下方会自动创建搜索语句
+	if state != 0 {
+		db = db.Where("state = ?", state)
+	}
+	if name != "" {
+		db = db.Where("name LIKE ?", "%"+name+"%")
+	}
+	if time != "" {
+		db = db.Where("WHERE DATE_FORMAT(created_at, '%Y-%m') = ?", time)
+	}
+	err = db.Count(&total).Error
+	if err != nil {
+		return
+	}
+	err = db.Order("id desc").Limit(limit).Offset(offset).Find(&project).Error
+	return project, total, err
+}
+
+// QueryProjectByCode 查询单个项目  按编号
+func QueryProjectByCode(code string) (project Project, err error) {
+	err = global.GVA_DB.Model(&Project{}).Where("code = ?", code).First(&project).Error
+	return
+}
+
+// TODO:项目新增
+
+// CreateProject 新增项目
+func (p Project) CreateProject() error {
+	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
+		txErr := tx.Model(&Project{}).Create(&p).Error
+		if txErr != nil {
+			return txErr
+		}
+
+		for _, file := range p.Files {
+			txErr := tx.Model(&ProjectFile{}).Create(&file).Error
+			if txErr != nil {
+				return txErr
+			}
+		}
+		return txErr
+	})
+}
+
+// TODO:项目修改
+
+// UpdateProject 修改项目
+func (p Project) UpdateProject() error {
+	return global.GVA_DB.Model(&p).Updates(p).Error
+}
+
+// TODO:项目删除
+
+// DeleteProject 删除项目
+func DeleteProject(code string) error {
+	return global.GVA_DB.Unscoped().Where("code = ?", code).Delete(&Project{}).Error
+}

+ 40 - 0
server/dao/projectFile.go

@@ -0,0 +1,40 @@
+package dao
+
+import (
+	"server/global"
+)
+
+type ProjectFile struct {
+	global.GVA_MODEL
+	ProjectCode string `json:"projectCode" from:"projectCode" gorm:"comment:项目编号"`
+	Name        string `json:"name" from:"name" gorm:"comment:文件名称"`
+	Suffix      string `json:"suffix" from:"suffix" gorm:"comment:文件后缀"`
+	Path        string `json:"path" from:"path" gorm:"comment:路径"`
+}
+
+func (ProjectFile) TableName() string {
+	return "project_file"
+}
+
+// TODO:项目文件查询
+
+// QueryFilesByCode 查询项目文件 按项目code
+func QueryFilesByCode(code string) (files []ProjectFile, err error) {
+	err = global.GVA_DB.Model(&ProjectFile{}).Where("project_code = ?", code).Find(&files).Error
+	return files, err
+}
+
+// TODO:项目文件新增
+
+// CreateFile 新增文件
+func (pf ProjectFile) CreateFile() error {
+	return global.GVA_DB.Create(&pf).Error
+}
+
+// TODO:项目文件修改
+// TODO:项目文件删除
+
+// DeleteFile 删除文件
+func DeleteFile(id uint) error {
+	return global.GVA_DB.Unscoped().Where("id = ?", id).Delete(&ProjectFile{}).Error
+}

+ 1 - 0
server/go.mod

@@ -102,6 +102,7 @@ require (
 	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
 	github.com/shoenig/go-m1cpu v0.1.6 // indirect
+	github.com/shopspring/decimal v1.4.0 // indirect
 	github.com/spf13/afero v1.9.5 // indirect
 	github.com/spf13/cast v1.5.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect

+ 2 - 0
server/go.sum

@@ -368,6 +368,8 @@ github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt
 github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
 github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
 github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
 github.com/songzhibin97/gkit v1.2.11 h1:O8+l6eLMrZ2yNbT6Vohc6ggWnH5zt4P8/3ZEkf8jUL4=
 github.com/songzhibin97/gkit v1.2.11/go.mod h1:axjYsiJWnn/kf/uGiUr9JPHRlt2CQrqfq/fPZ3xIY+M=
 github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=

+ 2 - 0
server/initialize/gorm.go

@@ -47,6 +47,8 @@ func RegisterTables() {
 		example.ExaFileChunk{},
 		dao.ExaFileUploadAndDownload{},
 		dao.Department{},
+		dao.Project{},
+		dao.ProjectFile{},
 	)
 	if err != nil {
 		global.GVA_LOG.Error("register table failed", zap.Error(err))

+ 1 - 0
server/initialize/router.go

@@ -88,6 +88,7 @@ func Routers() *gin.Engine {
 		exampleRouter.InitFileUploadAndDownloadRouter(PrivateGroup)
 
 		adminRouter.InitDepartmentRouter(PublicGroup)
+		adminRouter.InitProjectRouter(PublicGroup)
 	}
 
 	global.GVA_LOG.Info("router register success")

+ 7 - 0
server/model/common/request/common.go

@@ -30,4 +30,11 @@ type Ids struct {
 	Id  int   `json:"id" form:"id"`
 }
 
+type SearchProject struct {
+	PageInfo PageInfo `json:"pageInfo" form:"pageInfo"`
+	Name     string   `json:"name" form:"name"`
+	Time     string   `json:"time" form:"time"`
+	State    int      `json:"state" form:"state"`
+}
+
 type Empty struct{}

+ 1 - 0
server/router/admin/department.go

@@ -23,5 +23,6 @@ func (s *DepartmentRouter) InitDepartmentRouter(Router *gin.RouterGroup) {
 	{
 		departmentRouterWithoutRecord.GET("queryAllDep", departmentApi.QueryAllDep)
 		departmentRouterWithoutRecord.GET("queryDepByStart", departmentApi.QueryDepByStart)
+		departmentRouterWithoutRecord.POST("filesUpload", departmentApi.FilesUpload)
 	}
 }

+ 1 - 0
server/router/admin/enter.go

@@ -2,4 +2,5 @@ package admin
 
 type RouterGroup struct {
 	DepartmentRouter
+	ProjectRouter
 }

+ 26 - 0
server/router/admin/project.go

@@ -0,0 +1,26 @@
+package admin
+
+import (
+	"github.com/gin-gonic/gin"
+	v1 "server/api/v1"
+	"server/middleware"
+)
+
+type ProjectRouter struct{}
+
+func (s *ProjectRouter) InitProjectRouter(Router *gin.RouterGroup) {
+	projectRouter := Router.Group("project").Use(middleware.OperationRecord())
+	projectRouterWithoutRecord := Router.Group("project")
+	projectApi := v1.ApiGroupApp.AdminApiGroup.ProjectApi
+	{
+		projectRouter.POST("createProject", projectApi.CreateProject)
+		projectRouter.POST("createProjectFile", projectApi.CreateProjectFile)
+		projectRouter.PUT("updateProject", projectApi.UpdateProject)
+		projectRouter.DELETE("deleteProject/:code", projectApi.DeleteProject)
+		projectRouter.DELETE("deleteProjectFile/:id", projectApi.DeleteProjectFile)
+	}
+	{
+		projectRouterWithoutRecord.POST("queryProjectList", projectApi.QueryProjectList)
+		projectRouterWithoutRecord.GET("queryProjectByCode/:code", projectApi.QueryProjectByCode)
+	}
+}

+ 1 - 0
server/router/system/sys_user.go

@@ -23,6 +23,7 @@ func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, RouterPub *gin.Rout
 		userRouter.POST("setUserAuthorities", baseApi.SetUserAuthorities)         // 设置用户权限组
 		userRouter.POST("resetPassword", baseApi.ResetPassword)                   // 设置用户权限组
 		userPublicRouterWithoutRecord.GET("queryAllUsers", baseApi.QueryAllUsers) //查询所有用户
+
 	}
 	{
 		userRouterWithoutRecord.POST("getUserList", baseApi.GetUserList) // 分页获取用户列表

+ 1 - 0
server/service/admin/enter.go

@@ -2,4 +2,5 @@ package admin
 
 type ServiceGroup struct {
 	DepartmentService
+	ProjectService
 }

+ 49 - 0
server/service/admin/project.go

@@ -0,0 +1,49 @@
+package admin
+
+import (
+	"server/dao"
+	"server/model/common/request"
+)
+
+type ProjectService struct{}
+
+func (ps *ProjectService) QueryProjectList(info request.SearchProject) (list interface{}, total int64, err error) {
+	limit := info.PageInfo.PageSize
+	offset := info.PageInfo.PageSize * (info.PageInfo.Page - 1)
+
+	project, total, err := dao.QueryProjectList(limit, offset, info.State, info.Name, info.Time)
+	return project, total, err
+}
+
+func (ps *ProjectService) QueryProjectByCode(code string) (project dao.Project, err error) {
+	project, err = dao.QueryProjectByCode(code)
+	if err != nil {
+		return
+	}
+	files, err := dao.QueryFilesByCode(code)
+	if err != nil {
+		return
+	}
+	project.Files = files
+	return project, err
+}
+
+func (ps *ProjectService) CreateProject(project dao.Project) error {
+	return project.CreateProject()
+}
+
+func (ps *ProjectService) CreateProjectFile(projectFile dao.ProjectFile) error {
+	return projectFile.CreateFile()
+}
+
+func (ps *ProjectService) UpdateProject(project dao.Project) error {
+	return project.UpdateProject()
+}
+
+func (ps *ProjectService) DeleteProject(code string) error {
+	return dao.DeleteProject(code)
+}
+
+func (ps *ProjectService) DeleteProjectFile(id uint) error {
+	return dao.DeleteFile(id)
+}

二進制
server/uploads/file/c67b3af7ed83579cc083089fc0bbefd0_20240505115511.jpg


+ 5 - 5
web/.env.production

@@ -1,7 +1,7 @@
 ENV = 'production'
 
-#下方为上线需要用到的程序代理前缀,一般用于nginx代理转发
-VITE_BASE_API = /api
-VITE_FILE_API = /api
-#下方修改为你的线上ip(如果需要在线使用表单构建工具时使用,其余情况无需使用以下环境变量)
-VITE_BASE_PATH = https://demo.gin-vue-admin.com
+VITE_CLI_PORT = 8080
+VITE_SERVER_PORT = 443
+VITE_BASE_API = /lc_finance_api
+#下方修改为你的线上ip
+VITE_BASE_PATH = https://cloud.long-chi.com

+ 8 - 0
web/src/api/department.js

@@ -52,3 +52,11 @@ export const deleteDep = (data) => {
     method: 'delete'
   })
 }
+
+export const fileUpload = (data) => {
+  return service({
+    url: '/department/filesUpload',
+    method: 'post',
+    data
+  })
+}

+ 8 - 2
web/src/api/user.js

@@ -164,11 +164,17 @@ export const resetPassword = (data) => {
   })
 }
 
-//返回公钥
-
+// 返回公钥
 export const routerPublicKey = () => {
   return service({
     url: '/base/routerPublicKey',
     method: 'get'
   })
 }
+
+export const getAllUsers = () => {
+  return service({
+    url: '/user/queryAllUsers',
+    method: 'get'
+  })
+}

+ 0 - 1
web/src/core/global.js

@@ -20,7 +20,6 @@ const registerIcons = async(app) => {
   for (const path in iconModules) {
     const iconName = path.split('/').pop().replace(/\.svg$/, '')
     // 如果iconName带空格则不加入到图标库中并且提示名称不合法
-    console.log(iconName)
     if (iconName.indexOf(' ') !== -1) {
       console.error(`icon ${iconName}.svg includes whitespace`)
       continue

+ 60 - 2
web/src/view/department/department.vue

@@ -130,6 +130,27 @@
           </template>
         </el-table-column>
       </el-table>
+      <div>
+        <el-upload
+          ref="uploadRef"
+          class="upload-demo"
+          drag
+          multiple
+          :auto-upload="false"
+          :file-list="files"
+          :on-change="handleChange"
+          :on-remove="handleRemove"
+        >
+          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+          <div class="el-upload__text">
+            在这里放下文件 或 <em>点击上传</em>
+          </div>
+          <template #tip>
+            action="http://localhost:8080/api/department/filesUpload"
+          </template>
+        </el-upload>
+        <el-button @click="submitUpload">上传</el-button>
+      </div>
     </el-main>
     <!--    新增-->
     <el-dialog
@@ -265,7 +286,7 @@
   </el-container>
 </template>
 
-<script setup>
+<script setup lang="ts">
 import { ref, onMounted } from 'vue'
 import {
   createDep,
@@ -274,13 +295,50 @@ import {
   getDepByStart,
   updateDep,
   updateDepStatus,
-  updateUserDep
+  updateUserDep,
+  fileUpload
 } from '@/api/department'
 import CustomPic from '@/components/customPic/index.vue'
 import WarningBar from '@/components/warningBar/warningBar.vue'
 import { getAllUsers } from '@/api/user'
 import { ElMessage, ElMessageBox } from 'element-plus'
 
+const files = ref()
+
+const handleChange = (file, fileList) => {
+  console.log(fileList)
+  files.value = fileList
+}
+// 删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。function(file, fileList)
+const handleRemove = (file, fileList) => {
+  console.log(fileList)
+  files.value = fileList
+}
+
+const submitUpload = async() => {
+  // 判断是否有文件再上传
+  console.log(files.value)
+  if (files.value.length === 0) {
+    return ElMessage.warning('请选取文件后再上传')
+  }
+  // 下面的代码将创建一个空的FormData对象:
+  const formData = new FormData()
+  // 你可以使用FormData.append来添加键/值对到表单里面;
+  files.value.forEach((file) => {
+    formData.append('file', file.raw)
+  })
+  const css = ref({
+    name: 'cs',
+    age: 12
+  })
+  var s = JSON.stringify(css.value)
+  formData.append('cs', s.toString())
+  // 自定义的接口也可以用ajax或者自己封装的接口
+  await fileUpload(formData).then(res => {
+    console.log(res)
+  })
+}
+
 const depTableData = ref([])
 
 const queryData = async() => {