瀏覽代碼

新增 施工人员 工时

xuwenhao 8 月之前
父節點
當前提交
55155e030c

+ 94 - 0
server/api/v1/admin/constructor.go

@@ -0,0 +1,94 @@
+package admin
+
+import (
+	"github.com/gin-gonic/gin"
+	"server/dao"
+	"server/global"
+	"server/model/common/request"
+	"server/model/common/response"
+)
+
+type ConstructorApi struct{}
+
+func (ca *ConstructorApi) QueryConstructorList(c *gin.Context) {
+	var info request.SearchProject
+	err := c.ShouldBindJSON(&info)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("QueryConstructorList ====== " + err.Error())
+		return
+	}
+	list, total, err := constructorService.QueryConstructorList(info)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("QueryConstructorList ====== " + err.Error())
+		return
+	}
+	response.OkWithDetailed(response.PageResult{
+		List:     list,
+		Total:    total,
+		Page:     info.PageInfo.Page,
+		PageSize: info.PageInfo.PageSize,
+	}, "获取成功", c)
+}
+
+func (ca *ConstructorApi) QueryConstructor(c *gin.Context) {
+	constructors, err := constructorService.QueryConstructor()
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("UpdateConstructor ====== " + err.Error())
+		return
+	}
+	response.OkWithData(constructors, c)
+}
+
+func (ca *ConstructorApi) CreateConstructor(c *gin.Context) {
+	var constructor dao.Constructor
+	err := c.ShouldBindJSON(&constructor)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("CreateConstructor ====== " + err.Error())
+		return
+	}
+	err = constructorService.CreateConstructor(constructor)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("CreateConstructor ====== " + err.Error())
+		return
+	}
+	response.OkWithMessage("新增成功", c)
+}
+
+func (ca *ConstructorApi) UpdateConstructor(c *gin.Context) {
+	var constructor dao.Constructor
+	err := c.ShouldBindJSON(&constructor)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("UpdateConstructor ====== " + err.Error())
+		return
+	}
+	err = constructorService.UpdateConstructor(constructor)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("UpdateConstructor ====== " + err.Error())
+		return
+	}
+	response.OkWithMessage("新增成功", c)
+}
+
+func (ca *ConstructorApi) DeleteConstructor(c *gin.Context) {
+	var constructor dao.Constructor
+	err := c.ShouldBindJSON(&constructor)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("DeleteConstructor ====== " + err.Error())
+		return
+	}
+	err = constructorService.DeleteConstructor(constructor)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("DeleteConstructor ====== " + err.Error())
+		return
+	}
+	response.OkWithMessage("新增成功", c)
+}

+ 6 - 4
server/api/v1/admin/enter.go

@@ -7,11 +7,13 @@ type ApiGroup struct {
 	ProjectApi
 	FileApi
 	FinanceApi
+	ConstructorApi
 }
 
 var (
-	departmentService = service.ServiceGroupApp.AdminServiceGroup.DepartmentService
-	projectService    = service.ServiceGroupApp.AdminServiceGroup.ProjectService
-	fileService       = service.ServiceGroupApp.AdminServiceGroup.FileService
-	financeService    = service.ServiceGroupApp.AdminServiceGroup.FinanceService
+	departmentService  = service.ServiceGroupApp.AdminServiceGroup.DepartmentService
+	projectService     = service.ServiceGroupApp.AdminServiceGroup.ProjectService
+	fileService        = service.ServiceGroupApp.AdminServiceGroup.FileService
+	financeService     = service.ServiceGroupApp.AdminServiceGroup.FinanceService
+	constructorService = service.ServiceGroupApp.AdminServiceGroup.ConstructorService
 )

+ 23 - 1
server/api/v1/admin/project.go

@@ -125,7 +125,7 @@ func (pa *ProjectApi) QueryWorkingHours(c *gin.Context) {
 }
 
 func (pa *ProjectApi) QueryWorkingHoursList(c *gin.Context) {
-	var info request.SearchProjectList
+	var info request.SearchWorkingHours
 	err := c.ShouldBindJSON(&info)
 	if err != nil {
 		response.FailWithMessage("失败", c)
@@ -146,6 +146,28 @@ func (pa *ProjectApi) QueryWorkingHoursList(c *gin.Context) {
 	}, "获取成功", c)
 }
 
+func (pa *ProjectApi) QueryWorkingHoursSum(c *gin.Context) {
+	var info request.SearchWorkingHours
+	err := c.ShouldBindJSON(&info)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("QueryWorkingHoursSum ====== " + err.Error())
+		return
+	}
+	list, total, err := projectService.QueryWorkingHoursSum(info)
+	if err != nil {
+		response.FailWithMessage("失败", c)
+		global.GVA_LOG.Error("QueryWorkingHoursSum ====== " + err.Error())
+		return
+	}
+	response.OkWithDetailed(response.PageResult{
+		List:     list,
+		Total:    total,
+		Page:     info.PageInfo.Page,
+		PageSize: info.PageInfo.PageSize,
+	}, "获取成功", c)
+}
+
 func (pa *ProjectApi) QueryCollections(c *gin.Context) {
 	code := c.Query("code")
 	collections, err := projectService.QueryCollections(code)

+ 2 - 2
server/config.yaml

@@ -125,8 +125,8 @@ mysql:
     config: charset=utf8mb4&parseTime=True&loc=Local
     db-name: lc_finance
     username: root
-    password: root
-    path: 127.0.0.1
+    password: lczm*2019
+    path: 106.52.134.22
     engine: ""
     log-mode: error
     max-idle-conns: 10

+ 52 - 0
server/dao/constructor.go

@@ -0,0 +1,52 @@
+package dao
+
+import (
+	"github.com/shopspring/decimal"
+	"server/global"
+)
+
+type Constructor struct {
+	global.GVA_MODEL
+	Name  string          `json:"name" form:"name" gorm:"comment:施工人员姓名"`
+	Price decimal.Decimal `json:"price" form:"price" gorm:"type:decimal(10,2);not null;comment:人天单价"`
+}
+
+func (Constructor) TableName() string {
+	return "constructor"
+}
+
+// QueryConstructorList 查询施工人员列表
+func QueryConstructorList(limit, offset int, name string) (constructors []Constructor, total int64, err error) {
+	// 创建db
+	db := global.GVA_DB.Model(&Constructor{})
+	// 如果有条件搜索 下方会自动创建搜索语句
+	if name != "" {
+		db = db.Where("people LIKE ?", "%"+name+"%")
+	}
+	err = db.Count(&total).Error
+	if err != nil {
+		return
+	}
+	err = db.Order("id desc").Limit(limit).Offset(offset).Find(&constructors).Error
+	return constructors, total, err
+}
+
+func QueryConstructor() (constructors []Constructor, err error) {
+	err = global.GVA_DB.Model(&Constructor{}).Find(&constructors).Error
+	return
+}
+
+// CreateConstructor 新增施工人员
+func (c Constructor) CreateConstructor() error {
+	return global.GVA_DB.Create(&c).Error
+}
+
+// UpdateConstructor 修改施工人员
+func (c Constructor) UpdateConstructor() error {
+	return global.GVA_DB.Model(&c).Updates(&c).Error
+}
+
+// DeleteConstructor 删除施工人员
+func (c Constructor) DeleteConstructor() error {
+	return global.GVA_DB.Unscoped().Delete(&c).Error
+}

+ 45 - 13
server/dao/projectWorkingHours.go

@@ -1,16 +1,16 @@
 package dao
 
 import (
-	"github.com/shopspring/decimal"
 	"server/global"
 )
 
 type ProjectWorkingHours struct {
 	global.GVA_MODEL
-	ProjectCode string          `json:"projectCode" form:"projectCode" gorm:"comment:项目编号"`
-	People      string          `json:"people" form:"people" gorm:"comment:报工人"`
-	Days        float64         `json:"days" form:"days" gorm:"type:double(5,1);not null;comment:天数"`
-	Price       decimal.Decimal `json:"price" form:"price" gorm:"type:decimal(10,2);not null;comment:人天单价"`
+	ProjectCode string      `json:"projectCode" form:"projectCode" gorm:"comment:项目编号"`
+	People      int         `json:"people" form:"people" gorm:"comment:报工人"`
+	Constructor Constructor `json:"constructor" form:"constructor" gorm:"foreignKey:People;references:id;"`
+	Days        float64     `json:"days" form:"days" gorm:"type:double(5,1);not null;comment:天数"`
+	PeopleTime  string      `json:"peopleTime" form:"peopleTime" gorm:"comment:报工时间"`
 }
 
 func (ProjectWorkingHours) TableName() string {
@@ -19,31 +19,63 @@ func (ProjectWorkingHours) TableName() string {
 
 // TODO:工时查询
 
-// QueryWorkingHoursList 查询工时列表
-func QueryWorkingHoursList(limit, offset int, code, name string) (projectWorkingHours []ProjectWorkingHours, total int64, err error) {
+// QueryWorkingHoursList 查询工时详情列表
+func QueryWorkingHoursList(limit, offset, people int, code, time string) (projectWorkingHours []ProjectWorkingHours, total int64, err error) {
 	// 创建db
-	db := global.GVA_DB.Model(&ProjectWorkingHours{}).Where("project_code = ?", code)
+	db := global.GVA_DB.Model(&ProjectWorkingHours{})
 	// 如果有条件搜索 下方会自动创建搜索语句
-	if name != "" {
-		db = db.Where("people LIKE ?", "%"+name+"%")
+	if code != "" {
+		db = db.Where("project_code = ?", "%"+code+"%")
+	}
+	if people != 0 {
+		db = db.Where("people = ?", people)
+	}
+	if time != "" {
+		db = db.Where("DATE_FORMAT(people_time, '%Y-%m') = ?", time)
 	}
 	err = db.Count(&total).Error
 	if err != nil {
 		return
 	}
-	err = db.Order("id desc").Limit(limit).Offset(offset).Find(&projectWorkingHours).Error
+	err = db.Order("id desc").Limit(limit).Offset(offset).Preload("Constructor").Find(&projectWorkingHours).Error
 	return projectWorkingHours, total, err
 }
 
+func QueryWorkingHoursSum(limit, offset, people int, code, time string) (list interface{}, total int64, err error) {
+	type Result struct {
+		People   uint
+		Name     string
+		SumDay   float64
+		PriceSum float64
+	}
+
+	var results []Result
+	db := global.GVA_DB.Model(&ProjectWorkingHours{}).Select("people,constructor.`name`,SUM(days) as sum_day,(SUM(days) * price) as price_sum").
+		Joins("JOIN constructor ON project_working_hours.people = constructor.id")
+
+	// 如果有条件搜索 下方会自动创建搜索语句
+	if code != "" {
+		db = db.Where("project_code = ?", "%"+code+"%")
+	}
+	if people != 0 {
+		db = db.Where("people = ?", people)
+	}
+	if time != "" {
+		db = db.Where("DATE_FORMAT(people_time, '%Y-%m') = ?", time)
+	}
+	err = db.Group("people").Order("project_working_hours.id desc").Limit(limit).Offset(offset).Preload("Constructor").Count(&total).Scan(&results).Error
+	return results, total, err
+}
+
 // QueryWorkingHours 查询工时
 func QueryWorkingHours(code string) (workingHours []ProjectWorkingHours, err error) {
-	err = global.GVA_DB.Model(&ProjectWorkingHours{}).Where("project_code = ?", code).Find(&workingHours).Error
+	err = global.GVA_DB.Model(&ProjectWorkingHours{}).Where("project_code = ?", code).Preload("Constructor").Find(&workingHours).Error
 	return workingHours, err
 }
 
 // QueryWorkingHoursByCode 查询单个工时 按id
 func QueryWorkingHoursByCode(code string, people string) (workingHours ProjectWorkingHours, err error) {
-	err = global.GVA_DB.Model(&ProjectWorkingHours{}).Where("code = ? and people = ?", code, people).First(&workingHours).Error
+	err = global.GVA_DB.Model(&ProjectWorkingHours{}).Where("code = ? and people = ?", code, people).Preload("Constructor").First(&workingHours).Error
 	return workingHours, err
 }
 

+ 1 - 0
server/initialize/gorm.go

@@ -60,6 +60,7 @@ func RegisterTables() {
 		dao.DailyFile{},
 		dao.Reimbursement{},
 		dao.FeeDetails{},
+		dao.Constructor{},
 	)
 	if err != nil {
 		global.GVA_LOG.Error("register table failed", zap.Error(err))

+ 1 - 0
server/initialize/router.go

@@ -91,6 +91,7 @@ func Routers() *gin.Engine {
 		adminRouter.InitProjectRouter(PrivateGroup)
 		adminRouter.InitFileRouter(PrivateGroup)
 		adminRouter.InitFinanceRouter(PrivateGroup)
+		adminRouter.InitConstructorRouter(PrivateGroup)
 	}
 
 	global.GVA_LOG.Info("router register success")

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

@@ -37,6 +37,13 @@ type SearchProject struct {
 	State    int      `json:"state" form:"state"`
 }
 
+type SearchWorkingHours struct {
+	PageInfo PageInfo `json:"pageInfo" form:"pageInfo"`
+	Code     string   `json:"name" form:"name"`
+	Time     string   `json:"time" form:"time"`
+	People   int      `json:"people" form:"people"`
+}
+
 type SearchProjectList struct {
 	PageInfo PageInfo `json:"pageInfo" form:"pageInfo"`
 	Code     string   `json:"code" form:"code"`

+ 25 - 0
server/router/admin/constructor.go

@@ -0,0 +1,25 @@
+package admin
+
+import (
+	"github.com/gin-gonic/gin"
+	v1 "server/api/v1"
+	"server/middleware"
+)
+
+type ConstructorRouter struct{}
+
+func (s *DepartmentRouter) InitConstructorRouter(Router *gin.RouterGroup) {
+	constructorRouter := Router.Group("constructor").Use(middleware.OperationRecord())
+	constructorRouterWithoutRecord := Router.Group("constructor")
+
+	constructorApi := v1.ApiGroupApp.AdminApiGroup.ConstructorApi
+	{
+		constructorRouter.POST("createConstructor", constructorApi.CreateConstructor)
+		constructorRouter.PUT("updateConstructor", constructorApi.UpdateConstructor)
+		constructorRouter.DELETE("deleteConstructor", constructorApi.DeleteConstructor)
+	}
+	{
+		constructorRouterWithoutRecord.GET("queryConstructor", constructorApi.QueryConstructor)
+		constructorRouterWithoutRecord.POST("queryConstructorList", constructorApi.QueryConstructorList)
+	}
+}

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

@@ -3,4 +3,7 @@ package admin
 type RouterGroup struct {
 	DepartmentRouter
 	ProjectRouter
+	ConstructorRouter
+	FileRouter
+	FinanceRouter
 }

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

@@ -43,6 +43,7 @@ func (s *ProjectRouter) InitProjectRouter(Router *gin.RouterGroup) {
 		projectRouterWithoutRecord.GET("queryWorkingHours", projectApi.QueryWorkingHours)
 		projectRouterWithoutRecord.GET("queryCollection", projectApi.QueryCollections)
 		projectRouterWithoutRecord.POST("queryWorkingHoursList", projectApi.QueryWorkingHoursList)
+		projectRouterWithoutRecord.POST("queryWorkingHoursSum", projectApi.QueryWorkingHoursSum)
 		projectRouterWithoutRecord.POST("queryCollectionList", projectApi.QueryCollectionList)
 		projectRouterWithoutRecord.POST("queryReimbursementList", projectApi.QueryReimbursementList)
 		projectRouterWithoutRecord.GET("queryReimbursement", projectApi.QueryReimbursement)

+ 31 - 0
server/service/admin/constructor.go

@@ -0,0 +1,31 @@
+package admin
+
+import (
+	"server/dao"
+	"server/model/common/request"
+)
+
+type ConstructorService struct{}
+
+func (cs *ConstructorService) QueryConstructorList(info request.SearchProject) (list interface{}, total int64, err error) {
+	limit := info.PageInfo.PageSize
+	offset := info.PageInfo.PageSize * (info.PageInfo.Page - 1)
+	constructors, total, err := dao.QueryConstructorList(limit, offset, info.Name)
+	return constructors, total, err
+}
+
+func (cs *ConstructorService) QueryConstructor() ([]dao.Constructor, error) {
+	return dao.QueryConstructor()
+}
+
+func (cs *ConstructorService) CreateConstructor(constructor dao.Constructor) error {
+	return constructor.CreateConstructor()
+}
+
+func (cs *ConstructorService) UpdateConstructor(constructor dao.Constructor) error {
+	return constructor.UpdateConstructor()
+}
+
+func (cs *ConstructorService) DeleteConstructor(constructor dao.Constructor) error {
+	return constructor.DeleteConstructor()
+}

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

@@ -5,4 +5,5 @@ type ServiceGroup struct {
 	ProjectService
 	FileService
 	FinanceService
+	ConstructorService
 }

+ 3 - 7
server/service/admin/finance.go

@@ -54,15 +54,12 @@ func (fs *FinanceService) QueryProjectFinance(code string) (dao.Project, error)
 	if err != nil {
 		return dao.Project{}, err
 	}
-	collection, err := dao.QueryCollection(code)
+	collection, _, err := dao.QueryCollectionList(1, 5, code, "")
 	if err != nil {
 		return dao.Project{}, err
 	}
-	workingHours, err := dao.QueryWorkingHours(code)
-	if err != nil {
-		return dao.Project{}, err
-	}
-	reimbursements, err := dao.QueryReimbursement(code)
+
+	reimbursements, _, err := dao.QueryReimbursementList(1, 5, code, "", "")
 	if err != nil {
 		return dao.Project{}, err
 	}
@@ -74,7 +71,6 @@ func (fs *FinanceService) QueryProjectFinance(code string) (dao.Project, error)
 		reimbursements[i].FeeDetails = details
 	}
 	project.Collection = collection
-	project.WorkingHours = workingHours
 	project.Reimbursement = reimbursements
 
 	return project, err

+ 9 - 19
server/service/admin/project.go

@@ -80,10 +80,16 @@ func (ps *ProjectService) QueryWorkingHours(code string) ([]dao.ProjectWorkingHo
 	return dao.QueryWorkingHours(code)
 }
 
-func (ps *ProjectService) QueryWorkingHoursList(info request.SearchProjectList) (list interface{}, total int64, err error) {
+func (ps *ProjectService) QueryWorkingHoursList(info request.SearchWorkingHours) (list interface{}, total int64, err error) {
 	limit := info.PageInfo.PageSize
 	offset := info.PageInfo.PageSize * (info.PageInfo.Page - 1)
-	return dao.QueryWorkingHoursList(limit, offset, info.Code, info.Name)
+	return dao.QueryWorkingHoursList(limit, offset, info.People, info.Code, info.Time)
+}
+
+func (ps *ProjectService) QueryWorkingHoursSum(info request.SearchWorkingHours) (list interface{}, total int64, err error) {
+	limit := info.PageInfo.PageSize
+	offset := info.PageInfo.PageSize * (info.PageInfo.Page - 1)
+	return dao.QueryWorkingHoursSum(limit, offset, info.People, info.Code, info.Time)
 }
 
 func (ps *ProjectService) QueryCollections(code string) ([]dao.Collection, error) {
@@ -129,23 +135,7 @@ func (ps *ProjectService) CreateProjectState(projectState dao.ProjectState) erro
 }
 
 func (ps *ProjectService) CreateOrUpdateWorkingHours(workingHours dao.ProjectWorkingHours) error {
-	// 查询是否已有工时
-	hours, err := dao.QueryWorkingHoursByCode(workingHours.ProjectCode, workingHours.People)
-	if err != nil { // 创建时没有id 判断是创建还是修改
-		// 新增工时+已有工时
-		zongHours := hours.Days + workingHours.Days
-		workingHours.Days = zongHours
-		workingHours.Price = hours.Price
-
-		err = workingHours.UpdateWorkingHours()
-		return err
-	} else {
-		err := workingHours.CreateWorkingHours()
-		if err != nil {
-			return err
-		}
-		return err
-	}
+	return workingHours.CreateWorkingHours()
 }
 
 func (ps *ProjectService) CreateCollection(collection dao.Collection) error {

+ 55 - 0
web/src/api/finance.js

@@ -0,0 +1,55 @@
+import service from '@/utils/request'
+
+export const queryConstructor = () => {
+  return service({
+    url: '/constructor/queryConstructor',
+    method: 'get',
+  })
+}
+
+export const queryConstructorList = (data) => {
+  return service({
+    url: '/constructor/queryConstructorList',
+    method: 'post',
+    data
+  })
+}
+
+export const queryWorkingHoursList = (data) => {
+  return service({
+    url: '/project/queryWorkingHoursList',
+    method: 'post',
+    data
+  })
+}
+
+export const queryWorkingHoursSum = (data) => {
+  return service({
+    url: '/project/queryWorkingHoursSum',
+    method: 'post',
+    data
+  })
+}
+
+export const createConstructor = (data) => {
+  return service({
+    url: '/constructor/createConstructor',
+    method: 'post',
+    data
+  })
+}
+
+export const updateConstructor = (data) => {
+  return service({
+    url: '/constructor/updateConstructor',
+    method: 'put',
+    data
+  })
+}
+export const deleteConstructor = (data) => {
+  return service({
+    url: '/constructor/deleteConstructor',
+    method: 'delete',
+    data
+  })
+}

+ 96 - 0
web/src/view/finance/borrowing/borrowing.vue

@@ -0,0 +1,96 @@
+<template>
+  <div>
+    <el-table
+      v-loading="loading"
+      :data="tableData"
+      row-key="id"
+    >
+      <el-table-column
+        property="id"
+        label="序号"
+      />
+      <el-table-column
+        property="name"
+        label="姓名"
+      >
+        <template #default="scope">
+          <el-input
+            v-if="!scope.row.id"
+            v-model="scope.row.name"
+          />
+          <span v-else> {{ scope.row.name }} </span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        property="number"
+        label="年龄"
+      >
+        <template #default="scope">
+          <el-input
+            v-if="!scope.row.id"
+            v-model="scope.row.number"
+          />
+          <span v-else> {{ scope.row.number }} </span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="操作"
+        fixed="right"
+        align="center"
+        width="200"
+      >
+        <template #default="scope">
+          <el-button
+            v-if="!scope.row.id"
+            type="primary"
+            size="small"
+            @click.stop="handleSave(scope.row)"
+          >保存</el-button>
+          <el-button
+            v-if="!scope.row.id"
+            type="primary"
+            size="small"
+            @click.stop="handleDelete(scope.row)"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div>
+      <el-button
+        type="success"
+        @click="addLineData"
+      >添加一行</el-button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { ElMessageBox } from 'element-plus'
+const tableData = ref([])
+const addLineData = () => {
+  const newData = {
+    name: '',
+    number: '',
+  }
+  tableData.value.push(newData)
+}
+
+const handleDelete = (val) => {
+  ElMessageBox.confirm('确认删除该条数据?', '警告', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning',
+  }).then(() => {
+    console.log(val)
+  })
+}
+
+const handleSave = (val) => {
+  console.log(tableData.value)
+}
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 335 - 0
web/src/view/finance/workingHours/workingHours.vue

@@ -0,0 +1,335 @@
+<template>
+  <el-container class="gva-table-box">
+    <el-header>
+      <el-dropdown>
+        <el-button type="primary">
+          菜单<el-icon class="el-icon--right"><arrow-down /></el-icon>
+        </el-button>
+        <template #dropdown>
+          <el-dropdown-menu>
+            <el-dropdown-item @click="openConstructor = true">
+              施工人员
+            </el-dropdown-item>
+            <el-dropdown-item @click="listSwitching(1)">
+              详情列表
+            </el-dropdown-item>
+            <el-dropdown-item @click="listSwitching(2)">
+              总列表
+            </el-dropdown-item>
+          </el-dropdown-menu>
+        </template>
+      </el-dropdown>
+    </el-header>
+    <el-main>
+      <div v-if="isOpen === 1">
+        <el-table :data="workingHoursList">
+          <el-table-column
+            prop="projectCode"
+            label="项目编号"
+          />
+          <el-table-column
+            prop="constructor.name"
+            label="姓名"
+          />
+          <el-table-column
+            prop="days"
+            label="天数"
+          />
+          <el-table-column
+            prop="peopleTime"
+            label="时间"
+          />
+        </el-table>
+      </div>
+      <div v-if="isOpen === 2">
+        <el-table :data="workingHoursSum">
+          <el-table-column
+            prop="Name"
+            label="姓名"
+          />
+          <el-table-column
+            prop="SumDay"
+            label="总天数"
+          />
+          <el-table-column
+            prop="PriceSum"
+            label="总金额"
+          />
+        </el-table>
+      </div>
+      <div class="gva-pagination">
+        <el-pagination
+          :current-page="searchWorkingHours.pageInfo.page"
+          :page-size="searchWorkingHours.pageInfo.pageSize"
+          :page-sizes="[10, 30, 50, 100]"
+          :total="workingTotal"
+          layout="total, sizes, prev, pager, next, jumper"
+          @current-change="handleCurrentChange"
+          @size-change="handleSizeChange"
+        />
+      </div>
+      <el-dialog
+        v-model="openConstructor"
+        title="施工人员"
+        width="800"
+        align-center
+      >
+        <el-collapse v-model="activeNames">
+          <el-collapse-item
+            title="操作"
+            name="1"
+          >
+            <el-form>
+              <el-form-item label="施工人员">
+                <el-input
+                  v-model="constructorData.name"
+                  style="width: 400px"
+                >
+                  <template #prepend>
+                    <el-select
+                      v-model="constructorData.id"
+                      placeholder="查询"
+                      style="width: 115px"
+                      clearable
+                      filterable
+                      @change="changeConstructor"
+                    >
+                      <el-option
+                        v-for="item in constructorOptions"
+                        :key="item.ID"
+                        :label="item.name"
+                        :value="item.ID"
+                      />
+                    </el-select>
+                  </template>
+                  <template #append>
+                    <el-button @click="erasureConstructor">删除</el-button>
+                  </template>
+                </el-input>
+              </el-form-item>
+              <el-form-item label="人天单价">
+                <el-input
+                  v-model="constructorData.price"
+                  style="width: 400px"
+                />
+              </el-form-item>
+              <el-form-item>
+                <el-button @click="saveConstructor">保存</el-button>
+              </el-form-item>
+            </el-form>
+          </el-collapse-item>
+          <el-collapse-item
+            title="列表"
+            name="2"
+          >
+            <div>
+              <el-table :data="constructorTableData">
+                <el-table-column
+                  prop="name"
+                  label="姓名"
+                />
+                <el-table-column
+                  prop="price"
+                  label="人天单价"
+                />
+              </el-table>
+              <div class="gva-pagination">
+                <el-pagination
+                  :current-page="searchData.pageInfo.page"
+                  :page-size="searchData.pageInfo.pageSize"
+                  :page-sizes="[10, 30, 50, 100]"
+                  :total="total"
+                  layout="total, sizes, prev, pager, next, jumper"
+                  @current-change="handleCurrentChange"
+                  @size-change="handleSizeChange"
+                />
+              </div>
+            </div>
+          </el-collapse-item>
+        </el-collapse>
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button @click="openConstructor = false">取消</el-button>
+            <el-button
+              type="primary"
+              @click="openConstructor = false"
+            >
+              确定
+            </el-button>
+          </div>
+        </template>
+      </el-dialog>
+    </el-main>
+  </el-container>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import {
+  createConstructor,
+  deleteConstructor,
+  queryConstructor,
+  queryConstructorList, queryWorkingHoursList, queryWorkingHoursSum,
+  updateConstructor
+} from '@/api/finance'
+import { ElMessage, ElMessageBox } from 'element-plus'
+
+// 施工人员----------------------------------------------------------------
+
+const activeNames = ref(['1'])
+const openConstructor = ref(false)
+
+const constructorOptions = ref()
+const constructorData = ref({
+  id: null,
+  name: '',
+  price: null,
+})
+
+const searchData = ref({
+  pageInfo: {
+    page: 1,
+    pageSize: 10
+  },
+  name: ''
+})
+
+const total = ref(0)
+
+// 分页
+const handleSizeChange = (val) => {
+  searchData.value.pageInfo.pageSize = val
+  queryData()
+}
+
+const handleCurrentChange = (val) => {
+  searchData.value.pageInfo.page = val
+  queryData()
+}
+
+const constructorTableData = ref()
+
+// 工时----------------------------------------------------------------------------------------------------------------
+const searchWorkingHours = ref({
+  pageInfo: {
+    page: 1,
+    pageSize: 10
+  },
+  code: '',
+  time: '',
+  people: null,
+})
+
+const workingTotal = ref(0)
+
+const workingHoursList = ref()
+const workingHoursSum = ref()
+
+const queryData = async() => {
+  await queryConstructor().then(res => {
+    constructorOptions.value = res.data
+  })
+  await queryConstructorList(searchData.value).then(res => {
+    constructorTableData.value = res.data.list
+    searchData.value.pageInfo.page = res.data.page
+    searchData.value.pageInfo.pageSize = res.data.pageSize
+    total.value = res.data.total
+  })
+  await queryWorkingHoursList(searchWorkingHours.value).then(res => {
+    console.log(res)
+    workingHoursList.value = res.data.list
+    searchWorkingHours.value.pageInfo.page = res.data.page
+    searchWorkingHours.value.pageInfo.pageSize = res.data.pageSize
+    workingTotal.value = res.data.total
+  })
+}
+
+const isOpen = ref(1)
+
+// 列表切换
+const listSwitching = async(val) => {
+  if (val === 1) {
+    await queryData()
+  } else if (val === 2) {
+    await queryWorkingHoursSum(searchWorkingHours.value).then(res => {
+      console.log(res)
+      workingHoursSum.value = res.data.list
+      searchWorkingHours.value.pageInfo.page = res.data.page
+      searchWorkingHours.value.pageInfo.pageSize = res.data.pageSize
+      workingTotal.value = res.data.total
+    })
+  }
+  isOpen.value = val
+}
+
+const changeConstructor = (val) => {
+  for (const key in constructorOptions.value) {
+    if (constructorOptions.value[key].ID === val) {
+      constructorData.value.name = constructorOptions.value[key].name
+      constructorData.value.price = constructorOptions.value[key].price
+    }
+  }
+}
+
+// 保存
+const saveConstructor = async() => {
+  if (constructorData.value.name === '' || constructorData.value.price === null) {
+    ElMessage.error('数据不能为空')
+    return false
+  }
+  if (constructorData.value.id === null) {
+    await createConstructor(constructorData.value).then(res => {
+      if (res.code === 0) {
+        ElMessage.success('新增成功')
+      }
+      queryData()
+    })
+  } else {
+    await updateConstructor(constructorData.value).then(res => {
+      if (res.code === 0) {
+        ElMessage.success('修改成功')
+      }
+      queryData()
+    })
+  }
+}
+
+// 删除
+const erasureConstructor = async() => {
+  if (constructorData.value.id === null) {
+    ElMessage.error('请选择人员')
+    return false
+  }
+  ElMessageBox.confirm(
+    '确定进行删除操作吗?',
+    '删除',
+    {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }
+  )
+    .then(async() => {
+      await deleteConstructor(constructorData.value).then(res => {
+        if (res.code === 0) {
+          ElMessage.success('删除成功')
+        }
+        queryData()
+      })
+    })
+    .catch(() => {
+      ElMessage({
+        type: 'info',
+        message: '取消删除',
+      })
+    })
+}
+
+onMounted(() => {
+  queryData()
+})
+</script>
+
+<style scoped lang="scss">
+
+</style>