浏览代码

Merge remote-tracking branch 'origin/master' into master

# Conflicts:
#	backend/src/dashoo.cn/modi_webapi/router/router.go
zangkai 5 年之前
父节点
当前提交
2431984c3a

+ 139 - 0
backend/src/dashoo.cn/modi_webapi/app/api/class/class.go

@@ -0,0 +1,139 @@
+package class
+
+import (
+	"dashoo.cn/modi_webapi/app/service/class"
+	"dashoo.cn/modi_webapi/library/request"
+	"dashoo.cn/modi_webapi/library/response"
+	"fmt"
+	"github.com/gogf/gf/net/ghttp"
+	"github.com/gogf/gf/os/gtime"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type Controller struct {
+}
+//  获取班级管理列表
+func (c *Controller) GetAllClass(r *ghttp.Request){
+	page := request.GetPageInfo(r)
+	where := ""
+
+	if year := r.GetInt("Year"); year != 0 {
+		if where == ""{
+			where = fmt.Sprintf(" Year = %v", year)
+		} else {
+			where += fmt.Sprintf(" AND Year = %v", year)
+		}
+	}
+
+	if name := r.GetString("Name"); name != ""{
+		if where == ""{
+			where = fmt.Sprintf(" Name LIKE '%%%v%%'", name)
+		} else {
+			where += fmt.Sprintf(" AND Name LIKE '%%%v%%'", name)
+		}
+	}
+
+	var result []class.Entity
+	if err := class.GetAllClass(page, where, &result); err != nil{
+		if err.Error() == "sql: no rows in result set"{
+			response.Json(r, 0, "")
+			return
+		}
+		response.Json(r, -1, err.Error())
+	}else {
+		count, err1 := class.FindClassCount(where)
+		if err1 != nil {
+			response.Json(r, -1, err1.Error())
+		} else {
+			var records response.PagedRecords
+			records.Size = page.Size
+			records.Current = page.Current
+			records.Total = count
+			records.Records = result
+			response.Json(r, 0, "", records)
+		}
+	}
+}
+
+//  添加一条班级信息
+func (c *Controller) AddClass(r *ghttp.Request){
+	Class := new(class.Entity)
+	if err := r.Parse(Class); err != nil {
+		// 数据验证错误
+		if v, ok := err.(*gvalid.Error); ok {
+			response.Json(r, 1, v.FirstString())
+			r.ExitAll()
+		}
+		// 其他错误
+		response.Json(r, 1, err.Error())
+		r.ExitAll()
+	}
+	realName := r.GetParamVar("realname").String()
+	currentTime := gtime.Now()
+	Class.CreatedTime = currentTime
+	Class.CreatedBy = realName
+	Class.UpdatedTime = currentTime
+	Class.UpdatedBy = realName
+
+	if result,err := class.Insert(Class); err != nil {
+		response.Json(r, 1, err.Error())
+	} else {
+		var records response.PagedRecords
+		id, _ := result.LastInsertId()
+		Class.Id = int(id)
+		records.Records = Class
+		response.Json(r, 0, "", records)
+	}
+}
+//  获取一条班级信息
+func (c *Controller) GetOneClass(r *ghttp.Request){
+	id := r.GetInt("id")
+	if result, err := class.FindOne(id); err != nil {
+		response.Json(r, 1, err.Error())
+		r.ExitAll()
+	}else {
+		var records response.PagedRecords
+		records.Records = result
+		response.Json(r, 0, "", records)
+	}
+
+}
+
+// 修改一条班级信息
+func (c *Controller) UpdateClass(r *ghttp.Request){
+	Class := new(class.Entity)
+	if err := r.Parse(Class); err != nil {
+		// 数据验证错误
+		if v, ok := err.(*gvalid.Error); ok {
+			response.Json(r, 1, v.FirstString())
+			r.ExitAll()
+		}
+		// 其他错误
+		response.Json(r, 1, err.Error())
+		r.ExitAll()
+	}
+
+	realName := r.GetParamVar("realname").String()
+	currentTime := gtime.Now()
+
+	Class.UpdatedTime = currentTime
+	Class.UpdatedBy = realName
+
+	if _,err := class.Replace(Class); err != nil {
+		response.Json(r, 1, err.Error())
+	} else {
+		var records response.PagedRecords
+		records.Records = Class
+		response.Json(r, 0, "", records)
+	}
+}
+ //   删除一条班级信息
+func (c *Controller) DeleteClass(r *ghttp.Request){
+	id := r.GetInt("id")
+	if _,err := class.Delete(fmt.Sprintf("Id=%v", id)); err != nil{
+		response.Json(r, 1, err.Error())
+		r.ExitAll()
+	} else {
+		response.Json(r, 0, "该记录已删除!")
+	}
+}

+ 23 - 0
backend/src/dashoo.cn/modi_webapi/app/service/class/class.go

@@ -0,0 +1,23 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package class
+
+import (
+	"dashoo.cn/modi_webapi/library/request"
+	"github.com/gogf/gf/frame/g"
+)
+
+var (
+	recordsTable = g.DB().Table("class").Safe()
+)
+
+func GetAllClass(page request.PageInfo, where string, result *[]Entity)(err error){
+	err = recordsTable.Where(where).Limit((page.Current-1)*page.Size, page.Size).Scan(result)
+	return err
+}
+
+func FindClassCount(where string)(int, error){
+	return recordsTable.Where(where).Count()
+}

+ 62 - 0
backend/src/dashoo.cn/modi_webapi/app/service/class/class_entity.go

@@ -0,0 +1,62 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. You may not really want to edit it.
+// ==========================================================================
+
+package class
+
+import (
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/os/gtime"
+)
+
+// Entity is the golang structure for table instrument.
+type Entity struct {
+	Id                      int           `xorm:"not null pk autoincr INT(10)"`  // id
+	Year                    int           `xorm:"not null pk autoincr INT(11)"`  // 学年
+	Name                    string        `xorm:"VARCHAR(32)"`                   // 班级名称
+	CreatedBy                string        `xorm:"VARCHAR(32)"`                   // 创建人
+	CreatedTime              *gtime.Time   `xorm:"DATETIME created"`              // 创建时间
+	UpdatedBy               string        `xorm:"VARCHAR(32)"`                   // 更新人
+	UpdatedTime             *gtime.Time   `xorm:"DATETIME updated"`              // 更新时间
+	IsDel                   int           `xorm:"INT(11)"`                       // 删除标志
+
+}
+
+// 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/service/class/class_model.go

@@ -0,0 +1,369 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. You may not really want to edit it.
+// ==========================================================================
+
+package class
+
+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 = "class"
+	// 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)
+	})
+
+}

+ 4 - 1
backend/src/dashoo.cn/modi_webapi/router/router.go

@@ -1,6 +1,7 @@
 package router
 
 import (
+	"dashoo.cn/modi_webapi/app/api/class"
 	"dashoo.cn/modi_webapi/app/api/demo"
 	"dashoo.cn/modi_webapi/app/api/information"
 	"dashoo.cn/modi_webapi/app/api/instrument"
@@ -46,7 +47,9 @@ func init() {
 		{"ALL", "/permission", new(permission.Controller)},
 		{"ALL", "/organize", new(organize.Controller)},
 		{"ALL", "/menu", new(menu.Controller)},
-		{"All", "/instrument", new(instrument.Controller)},
+		{"All", "/instrument", new ( instrument.Controller) },
+		// 班级管理
+		{"All", "/class", new ( class.Controller) },
 		// 配置测试路由
 		{"ALL", "/class", new(demo.ClassController)},
 		{"ALL", "/student", new(demo.StudentController)},

+ 47 - 0
frontend_web/src/api/class.js

@@ -0,0 +1,47 @@
+import request from '@/plugin/axios'
+
+export default {
+   // 获取班级列表
+   getAllClass(params) {
+    return request({
+      url: process.env.VUE_APP_API02 + 'class/getallclass',
+      method: 'get', 
+      params: params
+    })
+  },
+
+  // 删除班级信息
+   deleteClass(params) {
+    return request({
+      url: process.env.VUE_APP_API02 + 'class/deleteclass',
+      method: 'delete',
+      params: params
+    })
+  },
+  
+   // 保存班级信息
+  addClass (data) {
+    return request({
+      url: process.env.VUE_APP_API02 + 'class/addclass',
+      method: 'post',
+      data: data
+    })
+  },
+  // 修改保存编辑信息
+  updateClass (data) {
+    return request({
+      url: process.env.VUE_APP_API02 + 'class/updateclass',
+      method: 'post',
+      data: data
+    })
+  },
+  // 获取一条班级信息
+  getOneClass(params) {
+    return request({
+      url: process.env.VUE_APP_API02 + 'class/getoneclass',
+      method: 'get', 
+      params: params
+    })
+  },
+  
+}

+ 10 - 0
frontend_web/src/router/routes.js

@@ -67,6 +67,16 @@ const frameIn = [
       },
       component: _import('instrument')
     },
+    // 班级管理
+    {
+      path: 'class',
+      name: 'class',
+      meta: {
+        title: '班级管理',
+        auth: true
+      },
+      component: _import('class')
+    },
       
       // 系统 前端日志
       {

+ 202 - 0
frontend_web/src/views/class/components/classadd.vue

@@ -0,0 +1,202 @@
+<template>
+  <el-dialog title="添加班级管理"
+             :visible.sync="dialogvisible"
+             width="65%"
+             :before-close="handleCloseAdd">
+    <el-form size="mini"
+             :model="testlistform"
+             :rules="rulestestlistform"
+             label-width="100px"
+             ref="testlistform">
+      <el-row :gutter="20"
+              class="donorsaddformcss">
+        <el-col :span="8">
+          <el-form-item label="年级"
+                        prop="Year"
+                        label-width="120px">
+            <el-select ref="reftube"
+                       v-model="testlistform.Year"
+                       placeholder="请选择年级学年"
+                       style="width:100%">
+              <el-option v-for="item in years"
+                         :key="item.value"
+                         :label="item.label"
+                         :value="item.value">
+              </el-option>
+            </el-select>
+
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="班级名称"
+                        prop="Name"
+                        label-width="120px">
+            <el-input v-model="testlistform.Name"
+                      placeholder="请输入班级名称"
+                      style="width:100%"></el-input>
+          </el-form-item>
+        </el-col>
+
+      </el-row>
+    </el-form>
+    <span slot="footer">
+      <el-button size="mini"
+                 type="primary"
+                 @click="savedata()">保存</el-button>
+      <el-button size="mini"
+                 @click="handleCloseAdd">关闭</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import ClassApi from '@/api/class'
+import axios from 'axios'
+import uploadajax from '@/assets/js/uploadajax.js'
+export default {
+  name: 'classadd',
+  data () {
+    return {
+      years: [],
+      form: {
+        recentYear: ''
+      },
+      fileList: [],
+      FileUrl: {},
+      uploadFile: {},
+      dialogvisible: false,
+      formtype: '1',
+      disabledbarcode: false,
+      testlistform: {
+        Name: '',
+        Year: '',
+        Classification: '',
+        Responsible: '',
+        State: 1,
+        Remarks: '',
+        CalibrationDeadlineType: 3,
+        CalibrationTime: new Date(),
+        CalibrationDeadline: 1,
+        HeartbeatTime: new Date(),
+        TimeNotification: 0,
+        MaintenCycle: 1,
+        CycleType: 3
+
+      },
+      Advancetime: 0,
+      triggerlist: {},
+      TimeNotification: false, // 有效期提醒
+      classificationlist: [],
+      getsupplierlist: [],
+
+      rulestestlistform: {
+
+        Code: [{
+          required: true,
+          message: '请输入设备编码',
+          trigger: 'blur'
+        }],
+        Name: [{
+          required: true,
+          message: '请输入设备名称',
+          trigger: 'blur'
+        }]
+      }
+    }
+  },
+  created () {
+    this.init()
+  },
+  methods: {
+    init () {
+      var myDate = new Date;
+      var year = myDate.getFullYear();//获取当前年
+      this.initSelectYear(year)
+      this.form.recentYear = year;
+    },
+    initSelectYear (year) {
+      this.years = [];
+      for (let i = 0; i < 30; i++) {
+        this.years.push({ value: (year - i), label: (year - i) + "年" });
+      }
+    },
+    yearChange (value) {
+      this.form.recentYear = value
+    },
+
+    //  保存新增班级信息
+    savedata () {
+      ClassApi.addClass(this.testlistform, {})
+        .then(res => {
+          // response
+          this.$emit('closeAddDialog')
+          this.dialogvisible = false
+          this.fileList = []
+          // 刷新
+        })
+        .catch(err => {
+          // handle error
+          console.error(err)
+        })
+    },
+    refreshData () {
+      this.$emit('refreshData')
+    },
+    closedialog () {
+      this.dialogvisible = false
+    },
+    handleCloseAdd () {
+      this.$refs['testlistform'].resetFields()
+      // this.$refs['uploader'].clearFiles()
+      this.testlistform.Code = ''
+      this.testlistform.Name = ''
+      this.testlistform.Brand = ''
+      this.testlistform.SupplierId = ''
+      this.testlistform.FactoryNum = ''
+      this.testlistform.Responsible = ''
+      this.testlistform.CalibrationDeadline = 1
+      this.testlistform.MaintenCycle = 1
+      this.testlistform.Model = ''
+      this.testlistform.Remarks = ''
+      this.testlistform.Classification = ''
+      this.$emit('closeAddDialog')
+    },
+
+    // 计算日期
+    addDate (date, days) {
+      if (days === undefined || days === '') {
+        days = 1
+      }
+      var dates = new Date(date)
+      dates.setDate(dates.getDate() + days)
+      var month = dates.getMonth() + 1
+      var day = dates.getDate()
+      var mm = "'" + month + "'"
+      var dd = "'" + day + "'"
+
+      // 单位数前面加0
+      if (mm.length === 3) {
+        month = '0' + month
+      }
+      if (dd.length === 3) {
+        day = '0' + day
+      }
+
+      var time = dates.getFullYear() + '-' + month + '-' + day
+      return time
+    }
+  }
+}
+
+</script>
+
+<style lang="scss">
+.button {
+  padding: 0;
+  float: right;
+}
+
+.donorsaddformcss .el-col-8 {
+  height: 58px;
+}
+</style>

+ 201 - 0
frontend_web/src/views/class/components/classedit.vue

@@ -0,0 +1,201 @@
+<template>
+  <el-dialog title="编辑班级信息"
+             :visible.sync="dialogvisible"
+             width="75%"
+             :before-close="handleCloseEdit">
+    <el-form size="mini"
+             :model="testlistform"
+             :rules="rulestestlistform"
+             label-width="130px"
+             ref="testlistform">
+      <el-row :gutter="20"
+              class="donorsaddformcss">
+        <el-col :span="8">
+          <el-form-item label="年级"
+                        prop="testlistform.Year"
+                        label-width="120px">
+            <el-select ref="reftube"
+                       v-model="testlistform.Year"
+                       placeholder="请选择年级学年"
+                       style="width:100%">
+              <el-option v-for="item in years"
+                         :key="item.value"
+                         :label="item.label"
+                         :value="item.value">
+              </el-option>
+            </el-select>
+
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="班级名称"
+                        prop="Name"
+                        label-width="120px">
+            <el-input v-model="testlistform.Name"
+                      placeholder="请输入班级名称"
+                      style="width:100%"></el-input>
+          </el-form-item>
+        </el-col>
+
+      </el-row>
+    </el-form>
+    <span slot="footer">
+      <el-button size="mini"
+                 type="primary"
+                 @click="savedata">保存</el-button>
+      <el-button size="mini"
+                 @click="handleCloseEdit">关闭</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import axios from 'axios'
+import uploadajax from '@/assets/js/uploadajax.js'
+import ClassApi from '@/api/class'
+
+export default {
+  name: 'classedit',
+  props: {
+    InstrumentId: {
+      default: 0
+    }
+  },
+  data () {
+    return {
+      years: [],
+      form: {
+        recentYear: ''
+      },
+      fileList: [],
+      FileUrl: {},
+      uploadFile: {},
+      dialogvisible: false,
+      formtype: '1',
+      disabledbarcode: false,
+      testlistform: {
+        Name: '',
+        Year: ''
+      },
+      Advancetime: 0,
+      triggerlist: {},
+      TimeNotification: false, // 有效期提醒
+      classificationlist: [],
+      getsupplierlist: [],
+
+      rulestestlistform: {
+
+      }
+    }
+  },
+  created () {
+    var myDate = new Date;
+    var year = myDate.getFullYear();
+    this.initSelectYear(year)
+  },
+  methods: {
+    init () {
+      var myDate = new Date;
+      var year = myDate.getFullYear();//获取当前年
+      this.initSelectYear(year)
+      this.form.recentYear = year;
+    },
+    initSelectYear (year) {
+      this.years = [];
+      for (let i = 0; i < 30; i++) {
+        this.years.push({ value: (year - i), label: (year - i) + "年" });
+      }
+    },
+    yearChange (value) {
+      this.form.recentYear = value
+    },
+
+    // 修改班级信息
+    savedata () {
+      let _this = this
+      ClassApi.updateClass(this.testlistform, {})
+        .then(res => {
+          this.dialogvisible = false
+          this.fileList = []
+          this.$emit('closeEditDialog')
+        })
+        .catch(err => {
+          // handle error
+          console.error(err)
+        })
+
+    },
+    getEntity (pid) {
+      let _this = this
+      let query = {
+        id: pid
+      }
+      ClassApi.getOneClass(query)
+        .then(response => {
+          _this.testlistform = response.records
+          _this.testlistform.CalibrationTime = new Date(response.CalibrationTime)
+          if (_this.testlistform.FileName !== '') {
+            let file = {
+              name: _this.testlistform.FileName,
+              year: _this.testlistform.Year
+            }
+            _this.fileList.push(file)
+          }
+        }).catch(err => {
+          // handle error
+          console.error(err)
+        })
+    },
+
+
+    // 计算日期
+    addDate (date, days) {
+      if (days === undefined || days === '') {
+        days = 1
+      }
+      var dates = new Date(date)
+      dates.setDate(dates.getDate() + days)
+      var month = dates.getMonth() + 1
+      var day = dates.getDate()
+      var mm = "'" + month + "'"
+      var dd = "'" + day + "'"
+
+      // 单位数前面加0
+      if (mm.length === 3) {
+        month = '0' + month
+      }
+      if (dd.length === 3) {
+        day = '0' + day
+      }
+
+      var time = dates.getFullYear() + '-' + month + '-' + day
+      return time
+    },
+
+    // 返回当前页
+    handleCloseEdit () {
+      // this.$refs['uploader'].clearFiles()
+      this.fileList = []
+      this.$emit('closeEditDialog')
+    },
+    deletedataforDid (val) {
+      deletetriggerlistfordid(val)
+        .then(res => {
+        })
+        .catch(err => {
+          // handle error
+          console.error(err)
+        })
+    }
+
+  }
+}
+
+</script>
+
+<style lang="scss">
+.button {
+  padding: 0;
+  float: right;
+}
+</style>

+ 340 - 0
frontend_web/src/views/class/index.vue

@@ -0,0 +1,340 @@
+<template>
+  <d2-container>
+    <template slot="header"
+              style="padding: 5px;">
+      <el-form size="mini"
+               ref="form"
+               :inline="true"
+               class="sbutton_padding"
+               style="margin-top: -7px;text-align:right;">
+        <el-form-item label="年级"
+                      class="sbutton_margin">
+          <el-input style="width: 140px;"
+                    v-model="search.Year"
+                    placeholder="请输入需要查询的年级"></el-input>
+        </el-form-item>
+        <el-form-item label="班级"
+                      class="sbutton_margin">
+          <el-input style="width: 140px;"
+                    v-model="search.Name"
+                    placeholder="请输入需要查询的班级"></el-input>
+        </el-form-item>
+        <el-button size="mini"
+                   type="primary"
+                   @click="initDatas()"
+                   style="margin-left:10px"
+                   @command="searchCommand"
+                   class="sbutton_margin">查 询</el-button>
+        <el-button size="mini"
+                   type="primary"
+                   @click="clearSearch"
+                   class="sbutton_margin">重 置</el-button>
+        <el-button size="mini"
+                   type="primary"
+                   style="margin-right:6px"
+                   @click="openinstrumentadd()"
+                   class="sbutton_margin">添加</el-button>
+      </el-form>
+    </template>
+    <el-table ref="multipleTable"
+              :data="activities"
+              border
+              fit
+              tooltip-effect="dark"
+              style="width: 100%"
+              @sort-change="orderby"
+              height="100%">
+      <el-table-column label="操作"
+                       width="100px"
+                       align="center"
+                       fixed='right'>
+        <template slot-scope="scope">
+          <el-button size="mini"
+                     title="编辑"
+                     type="primary"
+                     @click="instrumentedit(scope.row.Id)"
+                     icon="el-icon-edit"
+                     circle></el-button>
+          <el-button size="mini"
+                     type="danger"
+                     title="删除"
+                     @click="deleteclass(scope.row)"
+                     style="margin-left:5px;"
+                     icon="el-icon-delete"
+                     circle></el-button>
+        </template>
+      </el-table-column>
+      <el-table-column prop="Year"
+                       fit
+                       min-width="160px"
+                       label="年级"
+                       align="center"
+                       show-overflow-tooltip></el-table-column>
+      <el-table-column prop="Name"
+                       label="班级"
+                       align="center"
+                       min-width="120px"
+                       show-overflow-tooltip></el-table-column>
+    </el-table>
+    <!-- </el-card> -->
+    <addinstrumentlog ref="addinstrument"
+                      @closeAddDialog="handleCloseAdd"
+                      @refreshData="initDatas"
+                      width="75"></addinstrumentlog>
+    <addinstrumenteditlog ref="instrumentedit"
+                          @closeEditDialog="handleCloseEdit"
+                          :InstrumentId="selectedInstrumentId"
+                          @refreshData="initDatas"
+                          width="80%"></addinstrumenteditlog>
+    <!-- </div> -->
+    <template slot="footer">
+      <el-pagination style="margin: -10px;"
+                     @size-change="handleSizeChange"
+                     @current-change="handleCurrentChange"
+                     :current-page="currpage"
+                     :page-sizes="[10, 15, 20]"
+                     :page-size="size"
+                     layout="total, sizes, prev, pager, next, jumper"
+                     :total="totalsize">
+      </el-pagination>
+    </template>
+  </d2-container>
+</template>
+
+<script>
+import ClassApi from '@/api/class'
+import addinstrumentlog from './components/classadd'
+import addinstrumenteditlog from './components/classedit'
+export default {
+  name: 'class',
+  components: {
+    addinstrumentlog,
+    addinstrumenteditlog
+  },
+  data () {
+    return {
+      selectedInstrumentId: 0,
+      dialogvisible: false,
+      name: '',
+      details: false,
+      totalsize: 0,
+      currpage: 1,
+      size: 10,
+      classificationlist: [],
+      activities: [],
+      Code: '',
+      Name: '',
+      Year: '',
+      Brand: '',
+      CalibrationTime: [], // 录入时期
+      Classification: '',
+      State: '正常',
+      Remarks: '',
+      search: {
+        Name: '',
+        Year: '',
+        classification: ''
+      },
+      statelist: [
+        {
+          stateName: '正常',
+          Id: 1
+        },
+        {
+          stateName: '维修',
+          Id: 2
+        },
+        {
+          stateName: '闲置',
+          Id: 3
+        }
+      ],
+      // 列表排序
+      Column: {
+        Order: '',
+        Prop: ''
+      }
+    }
+  },
+  mounted () {
+    this.initDatas()
+  },
+  methods: {
+    download (val) {
+
+    },
+    // 打开 添加弹窗
+    openinstrumentadd () {
+      this.$refs.addinstrument.dialogvisible = true
+    },
+    // 打开 编辑弹窗
+    instrumentedit (instrumentId) {
+      this.$refs.instrumentedit.dialogvisible = true
+      this.$refs.instrumentedit.getEntity(instrumentId)
+      this.selectedInstrumentId = instrumentId
+    },
+    // 添加 返回页面
+    handleCloseAdd () {
+      this.$refs.addinstrument.dialogvisible = false
+      this.currpage = 1
+      this.initDatas()
+    },
+    // 编辑 返回页面
+    handleCloseEdit () {
+      this.$refs.instrumentedit.dialogvisible = false
+      this.initDatas()
+    },
+    // 初始化列表数据,班级管理列表
+    initDatas () {
+      let _this = this
+      let CalibrationTime = []
+      if (!_this.CalibrationTime) {
+        _this.CalibrationTime = []
+      }
+      let params = {
+        _currentPage: this.currpage,
+        _size: this.size,
+        Year: this.search.Year,
+        Classification: this.search.classification,
+        Name: this.search.Name,
+        Order: this.Column.Order,
+        Prop: this.Column.Prop
+      }
+      ClassApi.getAllClass(params)
+        .then(res => {
+          _this.activities = res.records
+        })
+    },
+    handleSizeChange (val) {
+      this.size = val
+      this.currpage = 1
+      this.initDatas()
+    },
+    handleCurrentChange (val) {
+      this.currpage = val
+      this.initDatas()
+    },
+    jstimehandle (val) {
+      if (val === '') {
+        return '----'
+      } else if (val === '0001-01-01T08:00:00+08:00') {
+        return '----'
+      } else if (val === '5000-01-01T23:59:59+08:00') {
+        return '永久'
+      } else {
+        if (val === '0001-01-01T00:00:00Z') {
+          return '----'
+        } else val = val.replace('T', ' ')
+        return val.substring(0, 19)
+      }
+    },
+    count (date2) {
+      var date1 = new Date()
+      var date = (date2.getTime() - date1.getTime()) / (1000 * 60 * 60 * 24)/* 不用考虑闰年否 */
+      return parseInt(date)
+    },
+    //  删除班级管理
+    deleteclass (val) {
+      let _this = this
+      let params = {
+        id: val.Id
+      }
+      _this.$confirm('此操作将永久删除该班级信息, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '关闭',
+        type: 'warning'
+      }).then(() => {
+        ClassApi.deleteClass(params)
+          .then(data => {
+            _this.initDatas()
+          })
+          .catch(function (error) {
+            console.log(error)
+          })
+      })
+        .catch(() => { })
+    },
+    // 列表排序功能
+    orderby (column) {
+      if (column.order === 'ascending') {
+        this.Column.Order = 'asc'
+      } else if (column.order === 'descending') {
+        this.Column.Order = 'desc'
+      }
+      this.Column.Prop = column.prop
+      this.initDatas()
+    },
+
+    formatDateTime (date) {
+      var y = date.getFullYear()
+      var m = date.getMonth() + 1
+      m = m < 10 ? '0' + m : m
+      var d = date.getDate()
+      d = d < 10 ? '0' + d : d
+      // var h = date.getHours();
+      // var minute = date.getMinutes();
+      // minute = minute < 10 ? ('0' + minute) : minute;
+      return y + '-' + m + '-' + d
+    },
+    searchCommand (command) {
+      if (command === 'search') {
+        this.dialogvisible = true
+      } else if (command === 'clear') {
+        this.clearSearch()
+      }
+    },
+    clearSearch () {
+      this.currpage = 1
+      this.search.Year = ''
+      this.search.Name = ''
+      this.search.classification = ''
+      this.CalibrationTime = []
+      this.initDatas()
+    },
+    deletedataforDid (val) {
+      deletetriggerlistfordid(val)
+        .then(res => {
+        })
+        .catch(err => {
+          // handle error
+          console.error(err)
+        })
+    },
+    addDate (date, days) {
+      if (days === undefined || days === '') {
+        days = 1
+      }
+      var dates = new Date(date)
+      dates.setDate(dates.getDate() + days)
+      var month = dates.getMonth() + 1
+      var day = dates.getDate()
+      var mm = "'" + month + "'"
+      var dd = "'" + day + "'"
+
+      // 单位数前面加0
+      if (mm.length === 3) {
+        month = '0' + month
+      }
+      if (dd.length === 3) {
+        day = '0' + day
+      }
+
+      var time = dates.getFullYear() + '-' + month + '-' + day
+      return time
+    }
+
+  }
+}
+</script>
+
+<style lang="scss">
+.el-pagination {
+  margin: 1rem 0 2rem;
+  text-align: right;
+}
+
+.plab {
+  font-size: 13px;
+  color: #999;
+}
+</style>