Explorar el Código

课程表详情的列表和新增

liuyang hace 5 años
padre
commit
31088d50fb

+ 90 - 0
backend/src/dashoo.cn/modi_webapi/app/api/course/detail/detail.go

@@ -0,0 +1,90 @@
+package detail
+
+import (
+	"dashoo.cn/modi_webapi/app/model/course/detail"
+	detailService "dashoo.cn/modi_webapi/app/service/course/detail"
+	"dashoo.cn/modi_webapi/library/request"
+	"dashoo.cn/modi_webapi/library/response"
+	"github.com/gogf/gf/net/ghttp"
+	"github.com/gogf/gf/os/glog"
+)
+
+// 课程详情管理API
+type CourseDetailController struct {
+
+}
+
+
+// 分页查询课程详情
+func (c CourseDetailController)GetPageList(r *ghttp.Request)  {
+	// tenant 租户模式
+	tenant := r.Header.Get("Tenant")
+	page := request.GetPageInfo(r)
+	// 初始化service
+	service, err := detailService.NewCourseDetailService(tenant)
+	if err != nil {
+		response.Json(r, 1, err.Error())
+	}
+	glog.Info(page)
+	pageInfo := detail.PageInfo{
+		Current:  page.Current,
+		PagesSize: page.Size,
+	}
+
+	selectPageReq := detail.SelectPageReq{
+		Tenant: tenant,
+		CourseName:   "",
+		Page:   &pageInfo,
+		// 排序
+		Order: r.GetString("order"),
+	}
+
+	if CourseId := r.GetInt32("CourseId"); CourseId != 0 {
+		selectPageReq.CourseId = int(CourseId)
+	}
+	if name := r.GetString("CourseName"); name != "" {
+		selectPageReq.CourseName = name
+	}
+	if detailList, total, err := service.GetPageList(&selectPageReq); err != nil {
+		response.Json(r, -1, err.Error())
+	} else {
+		var records response.PagedRecords
+		records.Current = page.Current
+		records.Size = page.Size
+		records.Total = total
+		records.Records = detailList
+		response.Json(r, 0, "ok", records)
+	}
+
+}
+
+
+// 添加
+func (c CourseDetailController)Save(r *ghttp.Request)  {
+	// tenant 租户模式
+	tenant := r.Header.Get("Tenant")
+	var entity  *detail.Entity
+	// 赋值并校验参数
+	if err := r.Parse(&entity); err != nil {
+		response.Json(r,-1, err.Error())
+	}
+
+	// 初始化课程详情service
+	service, err := detailService.NewCourseDetailService(tenant)
+	if err != nil {
+		response.Json(r, -1, err.Error())
+	}
+	// 判断是新增还是删除,获取的id为空新增,不为空则更新
+
+
+	if newId, err := service.Add(entity); err != nil {
+		response.Json(r, 1, err.Error())
+	} else {
+		response.Json(r, 0,"success", newId)
+	}
+
+}
+
+func (c CourseDetailController) DeleteDetailById()  {
+
+}

+ 42 - 0
backend/src/dashoo.cn/modi_webapi/app/model/course/detail/detail.go

@@ -0,0 +1,42 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package detail
+
+import (
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/os/gtime"
+)
+
+var (
+	recordsTable = g.DB().Table(Table).Safe()
+)
+
+// 分页请求
+type PageInfo struct {
+	Current   int `protobuf:"varint,1,opt,name=current,proto3" json:"current,omitempty"`
+	PagesSize int `protobuf:"varint,2,opt,name=pages_size,json=pagesSize,proto3" json:"pages_size,omitempty"`
+}
+
+type SelectPageReq struct {
+	Tenant 			string		`protobuf:"bytes,1,opt,name=tenant,proto3" json:"tenant,omitempty"`
+	CourseName  	string    	`protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Page   			*PageInfo 	`protobuf:"bytes,3,opt,name=page" json:"page,omitempty"`
+	CourseId 		int 		`protobuf:"varint,4,opt,name=CourseId,json=CourseId,proto3" json:"CourseId,omitempty"`
+	Prop   			string    	`json:prop`
+	Order  			string    	`json:order`
+}
+
+// 查询信息
+type SearchEntity struct {
+	Id          int 		`xorm:"not null pk autoincr INT(10)"`
+	CourseId    int			`xorm:"INT(10)"`   		// 课程ID
+	CourseName  string		`xorm:"VARCHAR(32)"`	// 课程名
+	Teacher		int			`xorm:"INT(10)"`  		// 授课老师
+	TeacherName string		`xorm:"VARCHAR(32)"`    // 授课教师
+	Local 		int 		`xorm:"INT(10)"`  		// 实验地点
+	Num 		int 		`xorm:"INT(10)"`		// 人数
+	CreatedTime	*gtime.Time	`xorm:"DATETIME"`		// 创建时间
+}
+

+ 69 - 0
backend/src/dashoo.cn/modi_webapi/app/model/course/detail/detail_entity.go

@@ -0,0 +1,69 @@
+package detail
+
+import (
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/os/gtime"
+)
+
+// Entity is the golang structure for table detail.
+type Entity struct {
+	Id          int 		`xorm:"not null pk autoincr INT(10)"`
+	CourseId    int			`xorm:"INT(10)"`   		// 课程ID
+	Year		int			`xorm:"INT(10)"`  		// 学年
+	Term 		int 		`xorm:"INT(10)"`		// 学期
+	CourseName  string		`xorm:"VARCHAR(32)"`	// 课程名
+	Teacher		int			`xorm:"INT(10)"`  		// 授课老师
+	Local 		int 		`xorm:"INT(10)"`  		// 实验地点
+	Class		int 		`xorm:"INT(10)"`  		// 授课班级
+	Mark		string		`xorm:"DECIMAL"`		// 学分
+	Num 		int 		`xorm:"INT(10)"`		// 人数
+	WeekTitle	string		`xorm:"VARCHAR(32)"`	// 教学周
+	DayOfWeek   int 		`xorm:"INT(10)"`  		// 周次 1-7
+	Time		string 		`xorm:"VARCHAR(32)"`	// 节次
+	Status		int 		`xorm:"TINYINT"` 		// 状态 发布状态
+	CreatedBy	string		`xorm:"VARCHAR(32)"`	// 创建人
+	CreatedTime	*gtime.Time	`xorm:"DATETIME"`		// 创建时间
+	UpdatedBy	string		`xorm:"VARCHAR(32)"`	// 更新人
+	UpdatedTime	*gtime.Time	`xorm:"DATETIME"`		// 更新时间
+	IsDel		int			`xorm:"TINYINT"`		// 是否删除:1删除0未删除
+}
+
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (r *Entity) OmitEmpty() *arModel {
+	return Model.Data(r).OmitEmpty()
+}
+
+// Inserts does "INSERT...INTO..." statement for inserting current object into table.
+func (r *Entity) Insert() (result sql.Result, err error) {
+	return Model.Data(r).Insert()
+}
+
+
+// Replace does "REPLACE...INTO..." statement for inserting current object into table.
+// If there's already another same record in the table (it checks using primary key or unique index),
+// it deletes it and insert this one.
+func (r *Entity) Replace() (result sql.Result, err error) {
+	return Model.Data(r).Replace()
+}
+
+// Save does "INSERT...INTO..." statement for inserting/updating current object into table.
+// It updates the record if there's already another same record in the table
+// (it checks using primary key or unique index).
+func (r *Entity) Save() (result sql.Result, err error) {
+	return Model.Data(r).Save()
+}
+
+// Update does "UPDATE...WHERE..." statement for updating current object from table.
+// It updates the record if there's already another same record in the table
+// (it checks using primary key or unique index).
+func (r *Entity) Update() (result sql.Result, err error) {
+	return Model.Data(r).Where(gdb.GetWhereConditionOfStruct(r)).Update()
+}
+
+// Delete does "DELETE FROM...WHERE..." statement for deleting current object from table.
+func (r *Entity) Delete() (result sql.Result, err error) {
+	return Model.Where(gdb.GetWhereConditionOfStruct(r)).Delete()
+}

+ 369 - 0
backend/src/dashoo.cn/modi_webapi/app/model/course/detail/detail_model.go

@@ -0,0 +1,369 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. You may not really want to edit it.
+// ==========================================================================
+
+package detail
+
+import (
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"time"
+)
+
+// arModel is a active record design model for table instrument operations.
+type arModel struct {
+	M *gdb.Model
+}
+
+var (
+	// Table is the table name of instrument.
+	Table = "course_detail"
+	// Model is the model object of instrument.
+	Model = &arModel{g.DB("default").Table(Table).Safe()}
+	// Columns defines and stores column names for table instrument.
+)
+
+// FindOne is a convenience method for Model.FindOne.
+// See Model.FindOne.
+func FindOne(where ...interface{}) (*Entity, error) {
+	return Model.FindOne(where...)
+}
+
+// FindAll is a convenience method for Model.FindAll.
+// See Model.FindAll.
+func FindAll(where ...interface{}) ([]*Entity, error) {
+	return Model.FindAll(where...)
+}
+
+// FindValue is a convenience method for Model.FindValue.
+// See Model.FindValue.
+func FindValue(fieldsAndWhere ...interface{}) (gdb.Value, error) {
+	return Model.FindValue(fieldsAndWhere...)
+}
+
+// FindCount is a convenience method for Model.FindCount.
+// See Model.FindCount.
+func FindCount(where ...interface{}) (int, error) {
+	return Model.FindCount(where...)
+}
+
+// Insert is a convenience method for Model.Insert.
+func Insert(data ...interface{}) (result sql.Result, err error) {
+	return Model.Insert(data...)
+}
+
+// Replace is a convenience method for Model.Replace.
+func Replace(data ...interface{}) (result sql.Result, err error) {
+	return Model.Replace(data...)
+}
+
+// Save is a convenience method for Model.Save.
+func Save(data ...interface{}) (result sql.Result, err error) {
+	return Model.Save(data...)
+}
+
+// Update is a convenience method for Model.Update.
+func Update(dataAndWhere ...interface{}) (result sql.Result, err error) {
+	return Model.Update(dataAndWhere...)
+}
+
+// Delete is a convenience method for Model.Delete.
+func Delete(where ...interface{}) (result sql.Result, err error) {
+	return Model.Delete(where...)
+}
+
+// As sets an alias name for current table.
+func (m *arModel) As(as string) *arModel {
+	return &arModel{m.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (m *arModel) TX(tx *gdb.TX) *arModel {
+	return &arModel{m.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (m *arModel) Master() *arModel {
+	return &arModel{m.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (m *arModel) Slave() *arModel {
+	return &arModel{m.M.Slave()}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+func (m *arModel) LeftJoin(joinTable string, on string) *arModel {
+	return &arModel{m.M.LeftJoin(joinTable, on)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+func (m *arModel) RightJoin(joinTable string, on string) *arModel {
+	return &arModel{m.M.RightJoin(joinTable, on)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+func (m *arModel) InnerJoin(joinTable string, on string) *arModel {
+	return &arModel{m.M.InnerJoin(joinTable, on)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+func (m *arModel) Fields(fields string) *arModel {
+	return &arModel{m.M.Fields(fields)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+func (m *arModel) FieldsEx(fields string) *arModel {
+	return &arModel{m.M.FieldsEx(fields)}
+}
+
+// Option sets the extra operation option for the model.
+func (m *arModel) Option(option int) *arModel {
+	return &arModel{m.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (m *arModel) OmitEmpty() *arModel {
+	return &arModel{m.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (m *arModel) Filter() *arModel {
+	return &arModel{m.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (m *arModel) Where(where interface{}, args ...interface{}) *arModel {
+	return &arModel{m.M.Where(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (m *arModel) And(where interface{}, args ...interface{}) *arModel {
+	return &arModel{m.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (m *arModel) Or(where interface{}, args ...interface{}) *arModel {
+	return &arModel{m.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (m *arModel) Group(groupBy string) *arModel {
+	return &arModel{m.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (m *arModel) Order(orderBy string) *arModel {
+	return &arModel{m.M.Order(orderBy)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (m *arModel) Limit(limit ...int) *arModel {
+	return &arModel{m.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (m *arModel) Offset(offset int) *arModel {
+	return &arModel{m.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (m *arModel) Page(page, limit int) *arModel {
+	return &arModel{m.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (m *arModel) Batch(batch int) *arModel {
+	return &arModel{m.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (m *arModel) Cache(expire time.Duration, name ...string) *arModel {
+	return &arModel{m.M.Cache(expire, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (m *arModel) Data(data ...interface{}) *arModel {
+	return &arModel{m.M.Data(data...)}
+}
+
+// Insert does "INSERT INTO ..." statement for the model.
+// The optional parameter <data> is the same as the parameter of Model.Data function,
+// see Model.Data.
+func (m *arModel) Insert(data ...interface{}) (result sql.Result, err error) {
+	return m.M.Insert(data...)
+}
+
+// Replace does "REPLACE INTO ..." statement for the model.
+// The optional parameter <data> is the same as the parameter of Model.Data function,
+// see Model.Data.
+func (m *arModel) Replace(data ...interface{}) (result sql.Result, err error) {
+	return m.M.Replace(data...)
+}
+
+// Save does "INSERT INTO ... ON DUPLICATE KEY UPDATE..." statement for the model.
+// It updates the record if there's primary or unique index in the saving data,
+// or else it inserts a new record into the table.
+//
+// The optional parameter <data> is the same as the parameter of Model.Data function,
+// see Model.Data.
+func (m *arModel) Save(data ...interface{}) (result sql.Result, err error) {
+	return m.M.Save(data...)
+}
+
+// Update does "UPDATE ... " statement for the model.
+//
+// If the optional parameter <dataAndWhere> is given, the dataAndWhere[0] is the updated
+// data field, and dataAndWhere[1:] is treated as where condition fields.
+// Also see Model.Data and Model.Where functions.
+func (m *arModel) Update(dataAndWhere ...interface{}) (result sql.Result, err error) {
+	return m.M.Update(dataAndWhere...)
+}
+
+// Delete does "DELETE FROM ... " statement for the model.
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+func (m *arModel) Delete(where ...interface{}) (result sql.Result, err error) {
+	return m.M.Delete(where...)
+}
+
+// Count does "SELECT COUNT(x) FROM ..." statement for the model.
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+func (m *arModel) Count(where ...interface{}) (int, error) {
+	return m.M.Count(where...)
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*Entity.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+func (m *arModel) All(where ...interface{}) ([]*Entity, error) {
+	all, err := m.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*Entity
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *Entity.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+func (m *arModel) One(where ...interface{}) (*Entity, error) {
+	one, err := m.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *Entity
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// Value retrieves a specified record value from table and returns the result as interface type.
+// It returns nil if there's no record found with the given conditions from table.
+//
+// If the optional parameter <fieldsAndWhere> is given, the fieldsAndWhere[0] is the selected fields
+// and fieldsAndWhere[1:] is treated as where condition fields.
+// Also see Model.Fields and Model.Where functions.
+func (m *arModel) Value(fieldsAndWhere ...interface{}) (gdb.Value, error) {
+	return m.M.Value(fieldsAndWhere...)
+}
+
+// FindOne retrieves and returns a single Record by Model.WherePri and Model.One.
+// Also see Model.WherePri and Model.One.
+func (m *arModel) FindOne(where ...interface{}) (*Entity, error) {
+	one, err := m.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *Entity
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by Model.WherePri and Model.All.
+// Also see Model.WherePri and Model.All.
+func (m *arModel) FindAll(where ...interface{}) ([]*Entity, error) {
+	all, err := m.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*Entity
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// FindValue retrieves and returns single field value by Model.WherePri and Model.Value.
+// Also see Model.WherePri and Model.Value.
+func (m *arModel) FindValue(fieldsAndWhere ...interface{}) (gdb.Value, error) {
+	return m.M.FindValue(fieldsAndWhere...)
+}
+
+// FindCount retrieves and returns the record number by Model.WherePri and Model.Count.
+// Also see Model.WherePri and Model.Count.
+func (m *arModel) FindCount(where ...interface{}) (int, error) {
+	return m.M.FindCount(where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (m *arModel) Chunk(limit int, callback func(entities []*Entity, err error) bool) {
+	m.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*Entity
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+
+}

+ 76 - 0
backend/src/dashoo.cn/modi_webapi/app/service/course/detail/detail.go

@@ -0,0 +1,76 @@
+package detail
+
+import (
+	"dashoo.cn/micro_libary/db"
+	"dashoo.cn/modi_webapi/app/common"
+	"dashoo.cn/modi_webapi/app/model/course/detail"
+	"database/sql"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/os/gtime"
+)
+
+// 课程详情定义
+type CourseDetailService struct {
+	db.ServiceBase
+}
+
+
+// NewCourseService 初始化CourseService
+func NewCourseDetailService(tenant string) (CourseDetailService, error) {
+	var service CourseDetailService
+	err := service.Init(tenant, detail.Table)
+	return service, err
+}
+
+
+// Add 新增课程信息
+func (s CourseDetailService) Add(param *detail.Entity) (id int64, err error) {
+	param.CreatedTime = gtime.Now()
+	if result, err := s.SafeModel.Insert(param); err != nil {
+		return 0, err
+	} else {
+		id, _ = result.LastInsertId()
+	}
+	return id, nil
+}
+
+// 分页查询课程表详情
+func (s CourseDetailService) GetPageList(param *detail.SelectPageReq) (list []*detail.SearchEntity, total int, err error) {
+	s.DB.Table("student s").InnerJoin("class c", "s.class_id = c.id")
+	model := s.DB.Table(detail.Table).As("d").InnerJoin("base_itemdetails b", "d.Teacher = b.ItemValue").Where("b.ItemCode","Teacher")
+	if param != nil {
+		if param.CourseName != "" {
+			model = model.Where("CourseName like ?", "%"+param.CourseName+"%")
+		}
+		if param.CourseId !=0 {
+			model = model.Where("CourseId",param.CourseId)
+		}
+		// todo more
+	}
+
+	// 查询总数
+	total, err = model.Where("isDel", 0).Count()
+	if err != nil {
+		return nil, -1, gerror.New("读取行数失败")
+	}
+	// 排序
+	prop := param.Prop
+	order := param.Order
+	orderby := "d.Id asc" // 默认排序
+	if prop != "" {
+		if prop == "TeacherName" {
+			orderby = "b.ItemName " + order
+		} else {
+			orderby = "s." + common.UnMarshal(prop) + " " + order
+		}
+	}
+	// 查询列表
+	model = model.Fields("d.*, b.ItemName as TeacherName").Page(int(param.Page.Current), int(param.Page.PagesSize)).Where("isDel", 0).Order(orderby)
+	var result []*detail.SearchEntity
+	err = model.Structs(&result)
+	// 如果未查到列表返回空
+	if err == sql.ErrNoRows {
+		return nil, 0, nil
+	}
+	return result, total, err
+}

+ 2 - 0
backend/src/dashoo.cn/modi_webapi/router/router.go

@@ -3,6 +3,7 @@ package router
 import (
 	"dashoo.cn/modi_webapi/app/api/class"
 	"dashoo.cn/modi_webapi/app/api/course"
+	"dashoo.cn/modi_webapi/app/api/course/detail"
 	"dashoo.cn/modi_webapi/app/api/duty"
 	"dashoo.cn/modi_webapi/app/api/information"
 	"dashoo.cn/modi_webapi/app/api/instrument"
@@ -57,6 +58,7 @@ func init() {
 		{"All", "/duty", new(duty.Controller)},
 		// 课程管理
 		{"All", "/course", new(course.Controller)},
+		{"All", "/course/detail", new(detail.CourseDetailController)},
 		// 配置测试路由
 		//{"ALL", "/class", new(demo.ClassController)},
 		//{"ALL", "/student", new(demo.StudentController)},

+ 11 - 11
frontend_web/src/api/course.js

@@ -1,25 +1,25 @@
 import request from '@/plugin/axios'
 
 export default {
-   // 获取课程列表
-   getPageList(params) {
+  // 获取课程列表
+  getPageList: function (params) {
     return request({
       url: process.env.VUE_APP_API + 'course/getallcourse',
-      method: 'get', 
+      method: 'get',
       params: params
     })
   },
 
-   // 新增课程管理信息
-   addCourse(data) {
+  // 新增课程管理信息
+  addCourse (data) {
     return request({
       url: process.env.VUE_APP_API + 'course/addcourse',
       method: 'post',
       data: data
     })
   },
-   // 删除主表课程信息
-   deleteCourse(params) {
+  // 删除主表课程信息
+  deleteCourse (params) {
     return request({
       url: process.env.VUE_APP_API + 'course/deletecourse',
       method: 'delete',
@@ -27,12 +27,12 @@ export default {
     })
   },
   // 根据id查询当前课程信息
-  getById(params) {
+  getById (params) {
     return request({
       url: process.env.VUE_APP_API + 'course/getdetailbyid',
-      method: 'get', 
+      method: 'get',
       params: params
     })
   }
-  
-}
+
+}

+ 36 - 0
frontend_web/src/api/course/detail.js

@@ -0,0 +1,36 @@
+import request from '@/plugin/axios'
+// 课程详情管理
+export default {
+    // 获取课程详情列表
+    getList (params) {
+        return request({
+            url: process.env.VUE_APP_API + 'course/detail/getpagelist',
+            method: 'get',
+            params: params
+        })
+    },
+    // 添加或保存
+    save (formData) {
+        return request({
+            url: process.env.VUE_APP_API + 'course/detail/save',
+            method: 'post',
+            data: formData
+        })
+    },
+    // // 获取学生详情
+    // getEntityById (params) {
+    //     return request({
+    //         url: process.env.VUE_APP_API + 'detail/getdetailbyid',
+    //         method: 'get',
+    //         params: params
+    //     })
+    // },
+    // // 删除学生
+    // delete (params) {
+    //     return request({
+    //         url: process.env.VUE_APP_API + 'detail/deletestudentbyid',
+    //         method: 'get',
+    //         params: params
+    //     })
+    // }
+}

+ 357 - 346
frontend_web/src/router/routes.js

@@ -1,346 +1,357 @@
-import layoutHeaderAside from '@/layout/header-aside'
-
-// 由于懒加载页面太多的话会造成webpack热更新太慢,所以开发环境不使用懒加载,只有生产环境使用懒加载
-const _import = require('@/libs/util.import.' + process.env.NODE_ENV)
-
-/**
- * 在主框架内显示
- */
-const frameIn = [
-  {
-    path: '/',
-    redirect: { name: 'index' },
-    component: layoutHeaderAside,
-    children: [
-      // 首页
-      {
-        path: 'index_1',
-        name: 'index_1',
-        meta: {
-          auth: true
-        },
-        component: _import('system/index')
-      },
-      {
-        path: 'index',
-        name: 'index',
-        meta: {
-          auth: true
-        },
-        component: _import('system/index')
-      },
-      // 演示页面
-      {
-        path: 'page1',
-        name: 'page1',
-        meta: {
-          title: '页面 1',
-          auth: true
-        },
-        component: _import('demo/page1')
-      },
-      {
-        path: 'page2',
-        name: 'page2',
-        meta: {
-          title: '页面 2',
-          auth: true
-        },
-        component: _import('demo/page2')
-      },
-      {
-        path: 'page3',
-        name: 'page3',
-        meta: {
-          title: '页面 3',
-          auth: true
-        },
-        component: _import('demo/page3')
-      },
-      // 设备管理
-      {
-        path: 'instrument',
-        name: 'instrument',
-        meta: {
-          title: '设备管理',
-          auth: true
-        },
-        component: _import('instrument')
-      },
-      // 人员管理
-      {
-        path: 'personnel',
-        name: 'personnel',
-        meta: {
-          title: '人员管理',
-          auth: true
-        },
-        component: _import('personnel')
-      },
-      // 班级管理
-      {
-        path: 'class',
-        name: 'class',
-        meta: {
-          title: '班级管理',
-          auth: true
-        },
-        component: _import('class')
-      },
-      // 值班管理
-      {
-        path: 'duty',
-        name: 'duty',
-        meta: {
-          title: '值班管理',
-          auth: true
-        },
-        component: _import('duty')
-      },
-      // 信息发布
-      {
-        path: 'information',
-        name: 'information',
-        meta: {
-          title: '信息发布',
-          auth: true
-        },
-        component: _import('information')
-      },
-        // 课程管理
-        {
-            path: 'course',
-            name: 'course',
-            meta: {
-                title: '课程管理',
-                auth: true
-            },
-            component: _import('course')
-        },
-      // 系统 前端日志
-      {
-        path: 'log',
-        name: 'log',
-        meta: {
-          title: '前端日志',
-          auth: true
-        },
-        component: _import('system/log')
-      },
-      // 刷新页面 必须保留
-      {
-        path: 'refresh',
-        name: 'refresh',
-        hidden: true,
-        component: _import('system/function/refresh')
-      },
-      // 页面重定向 必须保留
-      {
-        path: 'redirect/:route*',
-        name: 'redirect',
-        hidden: true,
-        component: _import('system/function/redirect')
-      },
-      // mypage
-      {
-        path: '/mypage',
-        name: 'mypage',
-        meta: {
-          title: 'mypage-示例页面',
-          auth: true
-        },
-        component: _import('mypage')
-      },
-      {
-        path: 'sysadmin/organize',
-        name: 'organizes',
-        meta: {
-          title: '部门管理',
-          auth: true,
-          cache: true
-        },
-        component: _import('sysadmin/organize/index')
-      },
-      {
-        path: 'sysadmin/user',
-        name: 'user',
-        meta: {
-          title: '用户管理',
-          auth: true,
-          cache: true
-        },
-        component: _import('sysadmin/user/index')
-      },
-      {
-        path: 'sysadmin/role',
-        name: 'role',
-        meta: {
-          title: '角色管理',
-          auth: true,
-          cache: true
-        },
-        component: _import('sysadmin/role/index')
-      },
-      {
-        path: 'sysadmin/menu',
-        name: 'menu',
-        meta: {
-          title: '菜单管理',
-          auth: true,
-          cache: true
-        },
-        component: _import('sysadmin/menu/index')
-      },
-      {
-        path: 'module01',
-        name: 'module01',
-        meta: {
-          title: 'frame测试',
-          auth: true,
-          cache: true
-        },
-        component: _import('system/module/module01')
-      },
-      {
-        path: '/setuser/userset',
-        name: 'setuser',
-        meta: {
-          title: '设置用户信息',
-          auth: true
-        },
-        component: _import('setuser/userset')
-      },
-      {
-        path: '/setuser/passwordset',
-        name: 'setuserpassword',
-        meta: {
-          title: '密码修改',
-          auth: true
-        },
-        component: _import('setuser/passwordset')
-      }, // 工作流
-      {
-        path: '/workflow/edit',
-        name: 'editWorkflow',
-        meta: {
-          title: '部门管理',
-          auth: true,
-          cache: true
-        },
-        component: _import('workflow/edit/index')
-      }, // 测试相关--学生
-      {
-        path: '/demo/student',
-        name: 'student',
-        meta: {
-          title: '学生管理',
-          auth: true,
-          cache: true
-        },
-        component: _import('demo/student/index')
-      }, // 测试相关调用微服务接口--学生
-      {
-        path: '/micro/student',
-        name: 'student2',
-        meta: {
-          title: '学生管理2',
-          auth: true,
-          cache: true
-        },
-        component: _import('micro/student/index')
-      },
-      // ================== add 字典分类 08-12 s ====================
-      {
-        path: '/sysadmin/item',
-        name: 'itemEdit',
-        meta: {
-          title: '字典分类',
-          auth: true,
-          cache: true
-        },
-        component: _import('sysadmin/item/index')
-      },
-      // 字典项
-      {
-        path: '/sysadmin/itemdetail',
-        name: 'itemDetailEdit',
-        meta: {
-          title: '字典项',
-          auth: true,
-          cache: true
-        },
-        component: _import('sysadmin/item_detail/index')
-      },
-      // 房间管理
-      {
-        path: 'managingrooms',
-        name: 'managingrooms',
-        meta: {
-          title: '实验室管理',
-          auth: true
-        },
-        component: _import('managingrooms')
-      },
-      // 运行记录
-      {
-        path: 'instrument/instrumenrunrecord',
-        name: 'instrument/instrumenrunrecord',
-        meta: {
-          title: '运行记录',
-          auth: true
-        },
-        component: _import('instrument/instrumenrunrecord')
-      },
-      // 维护保养
-      {
-        path: 'instrument/maintainlog',
-        name: 'instrument/maintainlog',
-        meta: {
-          title: '维护保养',
-          auth: true
-        },
-        component: _import('instrument/maintainlog')
-      },
-      // 确认及报废
-      {
-        path: 'instrument/confirmandscrap',
-        name: 'instrument/confirmandscrap',
-        meta: {
-          title: '确认及报废',
-          auth: true
-        },
-        component: _import('instrument/confirmandscrap')
-      }
- 
-    ]
-  }
-]
-
-/**
- * 在主框架之外显示
- */
-const frameOut = [
-  // 登录
-  {
-    path: '/login',
-    name: 'login',
-    component: _import('system/login')
-  }
-]
-
-/**
- * 错误页面
- */
-const errorPage = [
-  {
-    path: '*',
-    name: '404',
-    component: _import('system/error/404')
-  }
-]
-
-// 导出需要显示菜单的
-export const frameInRoutes = frameIn
-
-// 重新组织后导出
-export default [...frameIn, ...frameOut, ...errorPage]
+import layoutHeaderAside from '@/layout/header-aside'
+
+// 由于懒加载页面太多的话会造成webpack热更新太慢,所以开发环境不使用懒加载,只有生产环境使用懒加载
+const _import = require('@/libs/util.import.' + process.env.NODE_ENV)
+
+/**
+ * 在主框架内显示
+ */
+const frameIn = [
+  {
+    path: '/',
+    redirect: { name: 'index' },
+    component: layoutHeaderAside,
+    children: [
+      // 首页
+      {
+        path: 'index_1',
+        name: 'index_1',
+        meta: {
+          auth: true
+        },
+        component: _import('system/index')
+      },
+      {
+        path: 'index',
+        name: 'index',
+        meta: {
+          auth: true
+        },
+        component: _import('system/index')
+      },
+      // 演示页面
+      {
+        path: 'page1',
+        name: 'page1',
+        meta: {
+          title: '页面 1',
+          auth: true
+        },
+        component: _import('demo/page1')
+      },
+      {
+        path: 'page2',
+        name: 'page2',
+        meta: {
+          title: '页面 2',
+          auth: true
+        },
+        component: _import('demo/page2')
+      },
+      {
+        path: 'page3',
+        name: 'page3',
+        meta: {
+          title: '页面 3',
+          auth: true
+        },
+        component: _import('demo/page3')
+      },
+      // 设备管理
+      {
+        path: 'instrument',
+        name: 'instrument',
+        meta: {
+          title: '设备管理',
+          auth: true
+        },
+        component: _import('instrument')
+      },
+      // 人员管理
+      {
+        path: 'personnel',
+        name: 'personnel',
+        meta: {
+          title: '人员管理',
+          auth: true
+        },
+        component: _import('personnel')
+      },
+      // 班级管理
+      {
+        path: 'class',
+        name: 'class',
+        meta: {
+          title: '班级管理',
+          auth: true
+        },
+        component: _import('class')
+      },
+      // 值班管理
+      {
+        path: 'duty',
+        name: 'duty',
+        meta: {
+          title: '值班管理',
+          auth: true
+        },
+        component: _import('duty')
+      },
+      // 信息发布
+      {
+        path: 'information',
+        name: 'information',
+        meta: {
+          title: '信息发布',
+          auth: true
+        },
+        component: _import('information')
+      },
+      // 课程管理
+      {
+        path: 'course',
+        name: 'course',
+        meta: {
+          title: '课程管理',
+          auth: true
+        },
+        component: _import('course')
+      },
+      // 课程详情
+      {
+        path: '/course/detail',
+        name: 'courseDetailEdit',
+        meta: {
+          title: '课程详情',
+          auth: true,
+          cache: true
+        },
+        component: _import('course/detail/index')
+      },
+      // 系统 前端日志
+      {
+        path: 'log',
+        name: 'log',
+        meta: {
+          title: '前端日志',
+          auth: true
+        },
+        component: _import('system/log')
+      },
+      // 刷新页面 必须保留
+      {
+        path: 'refresh',
+        name: 'refresh',
+        hidden: true,
+        component: _import('system/function/refresh')
+      },
+      // 页面重定向 必须保留
+      {
+        path: 'redirect/:route*',
+        name: 'redirect',
+        hidden: true,
+        component: _import('system/function/redirect')
+      },
+      // mypage
+      {
+        path: '/mypage',
+        name: 'mypage',
+        meta: {
+          title: 'mypage-示例页面',
+          auth: true
+        },
+        component: _import('mypage')
+      },
+      {
+        path: 'sysadmin/organize',
+        name: 'organizes',
+        meta: {
+          title: '部门管理',
+          auth: true,
+          cache: true
+        },
+        component: _import('sysadmin/organize/index')
+      },
+      {
+        path: 'sysadmin/user',
+        name: 'user',
+        meta: {
+          title: '用户管理',
+          auth: true,
+          cache: true
+        },
+        component: _import('sysadmin/user/index')
+      },
+      {
+        path: 'sysadmin/role',
+        name: 'role',
+        meta: {
+          title: '角色管理',
+          auth: true,
+          cache: true
+        },
+        component: _import('sysadmin/role/index')
+      },
+      {
+        path: 'sysadmin/menu',
+        name: 'menu',
+        meta: {
+          title: '菜单管理',
+          auth: true,
+          cache: true
+        },
+        component: _import('sysadmin/menu/index')
+      },
+      {
+        path: 'module01',
+        name: 'module01',
+        meta: {
+          title: 'frame测试',
+          auth: true,
+          cache: true
+        },
+        component: _import('system/module/module01')
+      },
+      {
+        path: '/setuser/userset',
+        name: 'setuser',
+        meta: {
+          title: '设置用户信息',
+          auth: true
+        },
+        component: _import('setuser/userset')
+      },
+      {
+        path: '/setuser/passwordset',
+        name: 'setuserpassword',
+        meta: {
+          title: '密码修改',
+          auth: true
+        },
+        component: _import('setuser/passwordset')
+      }, // 工作流
+      {
+        path: '/workflow/edit',
+        name: 'editWorkflow',
+        meta: {
+          title: '部门管理',
+          auth: true,
+          cache: true
+        },
+        component: _import('workflow/edit/index')
+      }, // 测试相关--学生
+      {
+        path: '/demo/student',
+        name: 'student',
+        meta: {
+          title: '学生管理',
+          auth: true,
+          cache: true
+        },
+        component: _import('demo/student/index')
+      }, // 测试相关调用微服务接口--学生
+      {
+        path: '/micro/student',
+        name: 'student2',
+        meta: {
+          title: '学生管理2',
+          auth: true,
+          cache: true
+        },
+        component: _import('micro/student/index')
+      },
+      // ================== add 字典分类 08-12 s ====================
+      {
+        path: '/sysadmin/item',
+        name: 'itemEdit',
+        meta: {
+          title: '字典分类',
+          auth: true,
+          cache: true
+        },
+        component: _import('sysadmin/item/index')
+      },
+      // 字典项
+      {
+        path: '/sysadmin/itemdetail',
+        name: 'itemDetailEdit',
+        meta: {
+          title: '字典项',
+          auth: true,
+          cache: true
+        },
+        component: _import('sysadmin/item_detail/index')
+      },
+      // 房间管理
+      {
+        path: 'managingrooms',
+        name: 'managingrooms',
+        meta: {
+          title: '实验室管理',
+          auth: true
+        },
+        component: _import('managingrooms')
+      },
+      // 运行记录
+      {
+        path: 'instrument/instrumenrunrecord',
+        name: 'instrument/instrumenrunrecord',
+        meta: {
+          title: '运行记录',
+          auth: true
+        },
+        component: _import('instrument/instrumenrunrecord')
+      },
+      // 维护保养
+      {
+        path: 'instrument/maintainlog',
+        name: 'instrument/maintainlog',
+        meta: {
+          title: '维护保养',
+          auth: true
+        },
+        component: _import('instrument/maintainlog')
+      },
+      // 确认及报废
+      {
+        path: 'instrument/confirmandscrap',
+        name: 'instrument/confirmandscrap',
+        meta: {
+          title: '确认及报废',
+          auth: true
+        },
+        component: _import('instrument/confirmandscrap')
+      }
+
+    ]
+  }
+]
+
+/**
+ * 在主框架之外显示
+ */
+const frameOut = [
+  // 登录
+  {
+    path: '/login',
+    name: 'login',
+    component: _import('system/login')
+  }
+]
+
+/**
+ * 错误页面
+ */
+const errorPage = [
+  {
+    path: '*',
+    name: '404',
+    component: _import('system/error/404')
+  }
+]
+
+// 导出需要显示菜单的
+export const frameInRoutes = frameIn
+
+// 重新组织后导出
+export default [...frameIn, ...frameOut, ...errorPage]

+ 5 - 7
frontend_web/src/views/course/components/courseInfoDialog.vue

@@ -78,13 +78,13 @@ import CourseApi from '@/api/course'
 export default {
   name: 'courseInfoDialog',
   props: {
+    courseId: Number
   },
   data () {
     return {
       checkAll: false,
       dialogvisible: false,
       fileList: [],
-      courseId: Number,
       course: {}
     }
   },
@@ -94,13 +94,11 @@ export default {
   methods: {
     dialogOpen () {
       this.course = {}
-      console.log("courseId:" + this.courseId)
       this.$refs.courseForm.resetFields()
       this.getData()
     },
     dialogClose () {
       this.course = {}
-      console.log("courseId:" + this.courseId)
       this.$refs.courseForm.resetFields()
       this.$emit('handleClose')
       this.dialogVisible = false
@@ -118,14 +116,14 @@ export default {
               console.error(err)
             })
         } else {
-          console.log("error submit!!");
-          return false;
+          console.log('error submit!!')
+          return false
         }
-      });
-
+      })
     },
     // 编辑修改
     getData () {
+      console.log('获取courseId:' + this.courseId)
       if (this.courseId > 0) {
         var id = {
           id: this.courseId

+ 13 - 0
frontend_web/src/views/course/detail/components/command.vue

@@ -0,0 +1,13 @@
+<template>
+    
+</template>
+
+<script>
+    export default {
+        name: "command"
+    }
+</script>
+
+<style scoped>
+
+</style>

+ 246 - 0
frontend_web/src/views/course/detail/editForm.vue

@@ -0,0 +1,246 @@
+<template>
+    <el-dialog title="课程详情"
+               :visible.sync="dialogVisible"
+               @opened="dialogOpen"
+               @closed="dialogClose"
+               width="40%"
+    >
+        <el-form ref="form"
+                 :model="formdata"
+                 label-width="110px"
+                 :rules="rules"
+                 size="small">
+            <el-form-item prop="CourseName"
+                          label="课程名">
+                <el-input v-model="formdata.CourseName"></el-input>
+            </el-form-item>
+            <el-form-item label="授课教师">
+                <el-select v-model="formdata.Teacher"
+                           style="width: 100%">
+                    <el-option v-for="item in Teachers"
+                               :key="item.Teacher"
+                               :label="item.ItemName"
+                               :value="parseInt(item.ItemValue)">
+                    </el-option>
+                </el-select>
+            </el-form-item>
+
+            <el-form-item label="实验地点">
+                <el-select v-model="formdata.Teacher"
+                           style="width: 100%">
+                    <el-option v-for="item in Teachers"
+                               :key="item.Teacher"
+                               :label="item.ItemName"
+                               :value="parseInt(item.ItemValue)">
+                    </el-option>
+                </el-select>
+            </el-form-item>
+
+            <el-form-item prop="Mark"
+                          label="学分">
+                <el-input v-model="formdata.Mark"></el-input>
+            </el-form-item>
+
+            <el-form-item prop="Num"
+                          label="人数">
+                <el-input v-model="formdata.Num"></el-input>
+            </el-form-item>
+
+
+            <el-form-item prop="WeekTitle"
+                          label="教学周">
+                <el-input v-model="formdata.WeekTitle"></el-input>
+            </el-form-item>
+
+            <el-form-item prop="DayOfWeek"
+                          label="周次">
+                <el-input v-model="formdata.DayOfWeek"></el-input>
+            </el-form-item>
+
+            <el-form-item prop="Time"
+                          label="节次">
+                <el-input v-model="formdata.Time"></el-input>
+            </el-form-item>
+
+
+            <el-form-item label="发布状态" prop="Graduate">
+                <el-switch style="width:100%;text-align:left" v-model="formdata.Status"></el-switch>
+            </el-form-item>
+
+
+        </el-form>
+        <div slot="footer"
+             class="dialog-footer">
+            <el-button type="primary"
+                       size="mini"
+                       :loading="loading"
+                       @click="saveEntity">保存</el-button>
+            <el-button size="mini"
+                       @click="close">关闭</el-button>
+        </div>
+    </el-dialog>
+</template>
+<script>
+    import studentApi from '@/api/course/detail'
+    import itemDetailApi from '@/api/sysadmin/itemdetail'
+    export default {
+        name: 'detailEditForm',
+        props: {
+            id: Number,
+            value: Boolean,
+            CourseId: Number,
+            Year: Number,
+            Term: Number,
+            ClassId: Number,
+        },
+        data () {
+            return {
+                loading: false,
+                dialogVisible: false,
+                classList: [],
+                subjectList: [],
+                selectSubject: [],
+                Teachers :[],
+                formdata: {
+                    Id: 0,
+                    CourseId : '',
+                    Year : '',
+                    Term : '',
+                    CourseName : '',
+                    Teacher : 1,
+                    Local : '',
+                    Class :'',
+                    Mark : '',
+                    Num :'',
+                    WeekTitle : '',
+                    DayOfWeek : '',
+                    Time : '',
+                    Status : '',
+                },
+                imageUrl: '',
+                rules: {
+                    CourseName: [{
+                        required: true,
+                        message: '课程名不能为空',
+                        trigger: 'blur'
+                    }],
+                    Mark: [{
+                        required: true,
+                        message: '学分不能为空',
+                        trigger: 'blur'
+                    }],
+                    Num: [{
+                        required: true,
+                        message: '人数不能为空',
+                        trigger: 'blur'
+                    }],
+                    WeekTitle: [{
+                        required: true,
+                        message: '教学周不能为空',
+                        trigger: 'blur'
+                    }],
+                    DayOfWeek: [{
+                        required: true,
+                        message: '周次不能为空',
+                        trigger: 'blur'
+                    }],
+                    Time: [{
+                        required: true,
+                        message: '节次不能为空',
+                        trigger: 'blur'
+                    }],
+                }
+            }
+        },
+        watch: {
+            value (val) {
+                this.dialogVisible = val
+            },
+            dialogVisible (val) {
+                this.$emit('input', val)
+            }
+        },
+        mounted () {
+            itemDetailApi.getItemDetailByItemCode({ ItemCode: 'Teacher' })
+                .then(res => {
+                    this.Teachers = res
+                    this.initData()
+                })
+                .catch(err => {
+                    console.error(err)
+                })
+        },
+        methods: {
+            dialogOpen () {
+                this.$refs.form.resetFields()
+                this.initData()
+            },
+            initData () {
+                let _this = this
+                if (this.id > 0) {
+                    _this.formdata = {}
+                    const params = {
+                        id: this.id
+                    }
+                    studentApi.getEntityById(params)
+                        .then(res => {
+                            _this.formdata = res
+                            // 编辑时初始化表单数据,给字段赋值
+
+                        })
+                        .catch(err => {
+                            console.error(err)
+                        })
+                } else {
+                    console.log(_this)
+                    _this.formdata.Id = 0
+                    _this.formdata.CourseId = _this.CourseId
+                    _this.formdata.Year = _this.Year
+                    _this.formdata.Term = _this.Term
+                    _this.formdata.CourseName = ''
+                    _this.formdata.Teacher = ''
+                    _this.formdata.Local = ''
+                    _this.formdata.Class = _this.Class
+                    _this.formdata.Mark = ''
+                    _this.formdata.Num = ''
+                    _this.formdata.WeekTitle = ''
+                    _this.formdata.DayOfWeek = ''
+                    _this.formdata.Time = ''
+                    _this.formdata.Status = ''
+                }
+            },
+            saveEntity () {
+                let _this = this
+                _this.formdata.Id = this.Id
+                _this.$refs['form'].validate(valid => {
+                    if (valid) {
+                        _this.loading = true
+                        studentApi.save(_this.formdata)
+                            .then(data => {
+                                _this.loading = false
+                                _this.dialogVisible = false
+                                _this.$emit('submit')
+                            }).catch(err => {
+                            _this.loading = false
+                            console.error(err)
+                        })
+                    } else {
+                        return false
+                    }
+                })
+            },
+            dialogClose () {
+                this.$refs['form'].resetFields()
+                this.getSubjectList()
+                this.dialogVisible = false
+            },
+            close () {
+                this.dialogClose()
+            },
+        }
+    }
+</script>
+
+<style>
+
+</style>

+ 331 - 0
frontend_web/src/views/course/detail/index.vue

@@ -0,0 +1,331 @@
+<template>
+    <d2-container>
+        <template slot="header">
+            <el-form :inline="true"
+                     :model="searchForm"
+                     ref="searchForm"
+                     size="mini"
+                     style="height: 25px; margin-top: -7px;text-align:right;">
+                <el-form-item label="课程名称"
+                              prop="name">
+                    <el-input v-model="searchForm.name"
+                              placeholder="课程名称"
+                              style="width: 140px;"
+                              clearable/>
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary"
+                               size="mini"
+                               style="margin-left:10px"
+                               @click="handleSearch">
+                        <d2-icon name="search" /> 查询
+                    </el-button>
+                    <el-button @click="handleSearchFormReset"
+                               type="primary"
+                               size="mini">
+                        <d2-icon name="refresh" /> 重置
+                    </el-button>
+                    <el-button type="primary"
+                               size="mini"
+                               icon="el-icon-circle-plus"
+                               @click="add"> 新增
+                    </el-button>
+                    <el-button type="primary"
+                               size="mini"
+                               icon="el-icon-circle-plus"
+                               :disabled="deleteBtnVisible"
+                               @click="delSelectedIds"> 删除
+                    </el-button>
+                    <el-button type="primary"
+                               size="mini"
+                               icon="el-icon-back"
+                               @click="back"> 返回
+                    </el-button>
+                </el-form-item>
+            </el-form>
+        </template>
+        <ag-grid-vue class="table ag-theme-balham ag-title-center"
+                     style="width: 100%; height: 100%;"
+                     id="myGrid"
+                     :gridOptions="gridOptions"
+                     @gridReady="onGridReady"
+                     :rowData="rowData"
+                     :columnDefs="columnDefs"
+                     rowSelection="multiple"
+        >
+        </ag-grid-vue>
+        <template slot="footer">
+            <el-pagination style="margin: -10px;"
+                           @size-change="handleSizeChange"
+                           @current-change="handleCurrentChange"
+                           :current-page="page.current"
+                           :page-size="page.size"
+                           :total="page.total"
+                           :page-sizes="[10, 20]"
+                           layout="total, sizes, prev, pager, next, jumper">
+            </el-pagination>
+        </template>
+        <edit-form :id="id"
+                   v-model="editFormVisible"
+                   :CourseId="parseInt(CourseId)"
+                   :Year="parseInt(Year)"
+                   :Term="parseInt(Term)"
+                   :ClassId="parseInt(Class)"
+                   @submit="doRefresh" />
+    </d2-container>
+</template>
+
+<script>
+    import command from './components/command'
+    import detailApi from '@/api/course/detail'
+    import editForm from './editForm'
+    import { AgGridVue } from 'ag-grid-vue'
+    import 'ag-grid-community/dist/styles/ag-grid.css'
+    import 'ag-grid-community/dist/styles/ag-theme-balham.css'
+    export default {
+        name: 'courseDetail',
+        components: { AgGridVue, editForm },
+        data () {
+            return {
+                // ag-grid相关变量
+                gridOptions: null,
+                gridApi: null,
+                columnApi: null,
+                rowData: null,
+                columnDefs: null,
+
+                page: {
+                    current: 1,
+                    size: 10,
+                    total: 1
+                },
+                sort: {
+                    prop: '',
+                    order: ''
+                },
+
+                id: -1,
+                CourseId:null,
+                Term:null,
+                Class:null,
+                Year:null,
+                rowdata: {},
+                searchForm: {
+                    name: ''
+                },
+                loading: false,
+                multipleSelection: [],
+                editFormVisible: false,
+                deleteBtnVisible: true,
+                deleteIds: []
+            }
+        },
+        beforeMount () {
+            this.gridOptions = {
+                rowHeight: 32, // 设置行高为32px
+                // 缺省列属性
+                defaultColDef: {
+                    width: 200,
+                    resizable: true
+                },
+                onRowSelected: this.handleSelectionChange, // 行选中
+                onSortChanged: this.handleSortChange // 排序传递后台
+            }
+            this.columnDefs = [
+                { headerName: '', checkboxSelection: true, headerCheckboxSelection: true, width: 50, 'pinned': 'left' },
+                {
+                    headerName: '序号',
+                    width: 50,
+                    field: 'OrdNo',
+                    cellRenderer: (params) => {
+                        return params ? params.node.rowIndex + 1 + '' : ''
+                    }
+                }, {
+                    headerName: '课程名称',
+                    field: 'CourseName',
+                    sortable: true
+                }, {
+                    headerName: '授课老师',
+                    field: 'TeacherName',
+                    sortable: true
+                 },
+                { headerName: '实验地点', field: 'Local', sortable: true },
+                { headerName: '人数', field: 'Num', sortable: true },
+                { headerName: '创建时间', field: 'CreatedTime', sortable: true },
+                { headerName: '操作', field: 'operation', width: 120, 'pinned': 'right', cellRendererFramework: command }
+            ]
+        },
+        created () {
+        },
+        mounted () {
+            let _this = this
+            _this.gridOptions.context = { page: _this }
+            _this.gridApi = _this.gridOptions.api
+            _this.CourseId = _this.$route.query.CourseId
+            _this.Year = _this.$route.query.Year
+            _this.Term = _this.$route.query.Term
+            _this.Class = _this.$route.query.Class
+            this.doRefresh()
+        },
+        methods: {
+            formatTeachers (row, column) {
+                for (var i = 0; i < this.Teachers.length; i++) {
+                    if (parseInt(this.Teachers[i].ItemValue) === row.Teacher) {
+                        return this.Teachers[i].ItemName
+                    }
+                }
+            },
+            // 表格就绪后后执行
+            onGridReady (params) {
+                // 调整表格列宽大小自适应
+                this.gridApi.sizeColumnsToFit()
+            },
+            // 执行刷新(获取数据)
+            doRefresh () {
+                let _this = this
+                let query = {
+                    // 分页信息
+                    size: this.page.size,
+                    current: this.page.current,
+                    // 排序信息
+                    prop: this.sort.prop,
+                    order: this.sort.order,
+                    // 搜索名称
+                    CourseName: this.searchForm.name,
+                    CourseId:this.CourseId // 课程ID
+                }
+                detailApi.getList(query)
+                    .then(res => {
+                        _this.rowData = res.records
+                        // console.log(_this.rowData, '============')
+                        // _this.page.current = res.current
+                        // _this.page.size = res.size
+                        _this.page.total = res.total
+                    })
+                    .catch(err => {
+                        console.error(err)
+                    })
+            },
+
+            // 分页-改变分页大小
+            handleSizeChange (value) {
+                this.page.size = value
+                this.page.current = 1
+                this.doRefresh()
+            },
+            // 分页-改变当前页
+            handleCurrentChange (value) {
+                this.page.current = value
+                this.doRefresh()
+            },
+            // 处理编辑
+            handleEdit (id) {
+                this.id = id
+                this.editFormVisible = true
+            },
+            // 处理删除
+            handleDelete (id) {
+                const params = {
+                    ids: this.deleteIds
+                }
+                detailApi.delete(params).then((res) => {
+                    this.$message({
+                        type: 'success',
+                        message: '删除成功!'
+                    })
+                    this.doRefresh()
+                })
+            },
+            // 查询
+            handleSearch () {
+                this.currentPage = 1
+                this.doRefresh()
+            },
+            // 重置
+            handleSearchFormReset () {
+                this.searchForm.name = ''
+                this.doRefresh()
+            },
+            // 新建窗口
+            add () {
+                this.rowdata = {}
+                this.id = -1
+                this.editFormVisible = true
+            },
+            // 批量删除
+            delSelectedIds () {
+                this.$confirm('此操作将永久删除所选课程, 是否继续?', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(() => {
+                    const params = {
+                        ids: this.deleteIds
+                    }
+                    detailApi.delete(params).then((res) => {
+                        this.$message({
+                            type: 'success',
+                            message: '删除成功!'
+                        })
+                        this.doRefresh()
+                    })
+                }).catch(() => {
+                    this.$message({
+                        type: 'info',
+                        message: '已取消删除'
+                    })
+                })
+            },
+            // 处理列表选择
+            handleSelectionChange () {
+                let _this = this
+                _this.multipleSelection = _this.gridOptions.api.getSelectedRows()
+                _this.deleteBtnVisible = !_this.multipleSelection || _this.multipleSelection.length === 0
+                if (!_this.deleteBtnVisible) {
+                    _this.deleteIds = []
+                    // 赋值删除id列表
+                    _this.multipleSelection.forEach((item, k) => {
+                        _this.deleteIds.push(item.Id)
+                    })
+                } else {
+                    _this.deleteIds = []
+                }
+            },
+            handleSortChange (val) {
+                var sortState = this.gridApi.getSortModel()
+                // 获取排序的字段
+                if (sortState && sortState.length > 0) {
+                    var item = sortState[0]
+                    this.sort.prop = item.colId
+                    this.sort.order = item.sort
+                }
+                this.doRefresh()
+            },
+            back () { // 返回上一页
+                this.$router.go(-1)
+            }
+        }
+    }
+</script>
+
+<style lang="scss">
+
+    .el-pagination {
+        margin: 1rem 0 2rem;
+        text-align: right;
+    }
+
+    .plab {
+        font-size: 13px;
+        color: #999;
+    }
+
+    .rowequippower .el-checkbox {
+        margin-left: 1px;
+        padding: 5px 10px 0 0;
+    }
+    .ag-header-cell-text{
+        text-align: center ;
+        width: 100%;
+    }
+</style>

+ 11 - 8
frontend_web/src/views/course/index.vue

@@ -58,13 +58,13 @@
           <el-button size="mini"
                      title="编辑"
                      type="primary"
-                     @click="courseEdit(scope.row.id)"
+                     @click="courseEdit(scope.row.Id)"
                      icon="el-icon-edit"
                      circle></el-button>
           <el-button size="mini"
                      type="primary"
-                     title="发布"
-                     @click="publish(scope.row)"
+                     title="详情"
+                     @click="handleDetail(scope.row)"
                      style="margin-left:5px;"
                      icon="el-icon-circle-plus"
                      circle></el-button>
@@ -190,8 +190,8 @@ export default {
   methods: {
     formatStatus (row, column) {
       for (var i = 0; i < this.status.length; i++) {
-        if (this.status[i].value == row.status) {
-          return this.status[i].key;
+        if (this.status[i].value === row.status) {
+          return this.status[i].key
         }
       }
     },
@@ -199,10 +199,10 @@ export default {
       this.search = {
         Title: '',
         Status: -1,
-        Content: '',
+        Content: ''
       }
     },
-    //初始化分页分页对象
+    // 初始化分页分页对象
     initPageInfo () {
       this.search.page = {
         total: 0,
@@ -247,7 +247,10 @@ export default {
       this.search.page.current = val
       this.initDatas()
     },
-
+    // 详情
+    handleDetail (course) {
+      this.$router.push({ path: '/course/detail', query : { CourseId:course.Id, Year:course.Year, Term: course.Term, Class:course.ClassId}})
+    },
     //  删除课程
     deleteCourse (val) {
       let _this = this