You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
11 KiB
299 lines
11 KiB
package console
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"yunyan/comm"
|
|
"yunyan/pb"
|
|
)
|
|
|
|
// 设备管理域数据访问。sys.AdminDB() 恒为 console 主库(supabase)——厂家/产品/设备码/公码/出货单都在这;
|
|
// 只有 dvDelUserDevice / dvDecrProductStatActivated 走 sys.ServiceDB()(选中应用的 MySQL 业务库,重置设备码时清用户绑定)。
|
|
// 只读 + 公码 + 设备/产品写操作(create/disable/revoke/del/update)齐备,覆盖老 console 前端调用。
|
|
|
|
// ---- 厂家 / 产品(下拉只读)----
|
|
|
|
func dvFactorys(sys *appConn) (models []*pb.DBFactory, err error) {
|
|
models = make([]*pb.DBFactory, 0)
|
|
err = sys.AdminDB().Find(comm.TableFactory, &models, "")
|
|
return
|
|
}
|
|
|
|
func dvFactory(sys *appConn, id uint32) (model *pb.DBFactory, err error) {
|
|
model = &pb.DBFactory{}
|
|
// 用 FindOne:厂家不存在时返回 ErrRecordNotFound,存在性校验才有效(Find 对空结果不报错)。
|
|
err = sys.AdminDB().FindOne(comm.TableFactory, model, "id=?", id)
|
|
return
|
|
}
|
|
|
|
func dvAddFactory(sys *appConn, model *pb.DBFactory) (err error) {
|
|
err = sys.AdminDB().Insert(comm.TableFactory, model)
|
|
return
|
|
}
|
|
|
|
// dvAddProduct 新增产品并为其建好 license 分表(license_%x,%x 为回填后的产品 id)。
|
|
func dvAddProduct(sys *appConn, product *pb.DBProduct) (err error) {
|
|
if err = sys.AdminDB().Insert(comm.TableProduct, product); err != nil { // Insert 后回填 product.Id
|
|
return
|
|
}
|
|
err = sys.AdminDB().CreateTable(fmt.Sprintf("%s_%x", comm.TableLicense, product.Id), &pb.DBFactoryDevics{})
|
|
return
|
|
}
|
|
|
|
func dvProducts(sys *appConn) (models []*pb.DBProduct, err error) {
|
|
models = make([]*pb.DBProduct, 0)
|
|
err = sys.AdminDB().Find(comm.TableProduct, &models, "")
|
|
return
|
|
}
|
|
|
|
func dvProduct(sys *appConn, id uint32) (model *pb.DBProduct, err error) {
|
|
model = &pb.DBProduct{}
|
|
err = sys.AdminDB().FindOne(comm.TableProduct, model, "id=?", id)
|
|
return
|
|
}
|
|
|
|
func dvProductVersions(sys *appConn, pid uint32) (models []*pb.DBProductVersion, err error) {
|
|
models = make([]*pb.DBProductVersion, 0)
|
|
err = sys.AdminDB().Find(comm.TableProductVersion, &models, "productid=?", pid)
|
|
return
|
|
}
|
|
|
|
// dvAllProductVersions 取全部产品版本(缓存全量预热用,不按 productid 过滤)。
|
|
func dvAllProductVersions(sys *appConn) (models []*pb.DBProductVersion, err error) {
|
|
models = make([]*pb.DBProductVersion, 0)
|
|
err = sys.AdminDB().Find(comm.TableProductVersion, &models, "")
|
|
return
|
|
}
|
|
|
|
func dvDelFactory(sys *appConn, id uint32) (err error) {
|
|
err = sys.AdminDB().Delete(comm.TableFactory, "id=?", id)
|
|
return
|
|
}
|
|
|
|
func dvSaveFactory(sys *appConn, model *pb.DBFactory) (err error) {
|
|
err = sys.AdminDB().Save(comm.TableFactory, model)
|
|
return
|
|
}
|
|
|
|
// ---- 产品 / 版本(写)----
|
|
|
|
func dvUpdateProduct(sys *appConn, model *pb.DBProduct) (err error) {
|
|
err = sys.AdminDB().Save(comm.TableProduct, model)
|
|
return
|
|
}
|
|
|
|
func dvDelProduct(sys *appConn, id uint32) (err error) {
|
|
err = sys.AdminDB().Delete(comm.TableProduct, "id=?", id)
|
|
return
|
|
}
|
|
|
|
func dvAddProductVersion(sys *appConn, version *pb.DBProductVersion) (err error) {
|
|
err = sys.AdminDB().Insert(comm.TableProductVersion, version)
|
|
return
|
|
}
|
|
|
|
func dvProductVersion(sys *appConn, id uint32) (model *pb.DBProductVersion, err error) {
|
|
model = &pb.DBProductVersion{}
|
|
err = sys.AdminDB().FindOne(comm.TableProductVersion, model, "id=?", id)
|
|
return
|
|
}
|
|
|
|
func dvDelProductVersion(sys *appConn, id uint32) (err error) {
|
|
err = sys.AdminDB().Delete(comm.TableProductVersion, "id=?", id)
|
|
return
|
|
}
|
|
|
|
// ---- 厂家设备(写):授权码批量创建 / 封禁 / 批次撤销 ----
|
|
|
|
// dvAddFactoryDevics 批量写入授权码(按 product 分表 license_%x)。
|
|
// DBFactoryDevics 列多,单条 INSERT 占位符上限 65535,按 1000 行分批。
|
|
func dvAddFactoryDevics(sys *appConn, pid uint32, models []*pb.DBFactoryDevics) (err error) {
|
|
err = sys.AdminDB().Table(fmt.Sprintf("%s_%x", comm.TableLicense, pid)).CreateInBatches(models, 1000).Error
|
|
return
|
|
}
|
|
|
|
// dvSetFactoryDevicsDisabled 批量设封禁状态(disabled: 0 正常, -1 禁用),返回更新条数。
|
|
func dvSetFactoryDevicsDisabled(sys *appConn, pid uint32, codes []string, disabled int32) (affected int64, err error) {
|
|
tx := sys.AdminDB().Table(fmt.Sprintf("%s_%x", comm.TableLicense, pid)).
|
|
Where("code IN ?", codes).Update("disabled", disabled)
|
|
affected = tx.RowsAffected
|
|
err = tx.Error
|
|
return
|
|
}
|
|
|
|
// dvCountUsedFactoryDevicsByBatch 统计批次中已被使用(status>0 或 uid 非空)的设备码数。
|
|
func dvCountUsedFactoryDevicsByBatch(sys *appConn, pid, probatch uint32) (used int64, err error) {
|
|
err = sys.AdminDB().Table(fmt.Sprintf("%s_%x", comm.TableLicense, pid)).
|
|
Where("probatch=? AND (status>0 OR uid<>'')", probatch).Count(&used).Error
|
|
return
|
|
}
|
|
|
|
// dvDelFactoryDevicsByBatch 删除批次全部设备码,返回删除条数。
|
|
func dvDelFactoryDevicsByBatch(sys *appConn, pid, probatch uint32) (affected int64, err error) {
|
|
tx := sys.AdminDB().Table(fmt.Sprintf("%s_%x", comm.TableLicense, pid)).
|
|
Where("probatch=?", probatch).Delete(&pb.DBFactoryDevics{})
|
|
affected = tx.RowsAffected
|
|
err = tx.Error
|
|
return
|
|
}
|
|
|
|
// dvFactoryDevicForUid 取某用户在某产品下持有的全部设备码(按 license 分表)。
|
|
func dvFactoryDevicForUid(sys *appConn, pid uint32, uid string) (models []*pb.DBFactoryDevics, err error) {
|
|
models = make([]*pb.DBFactoryDevics, 0)
|
|
err = sys.AdminDB().Find(fmt.Sprintf("%s_%x", comm.TableLicense, pid), &models, "uid=?", uid)
|
|
return
|
|
}
|
|
|
|
// dvUpdateFactoryDevics 批量保存设备码(按 license 分表)。
|
|
func dvUpdateFactoryDevics(sys *appConn, pid uint32, models []*pb.DBFactoryDevics) (err error) {
|
|
if len(models) == 0 {
|
|
return nil
|
|
}
|
|
err = sys.AdminDB().Save(fmt.Sprintf("%s_%x", comm.TableLicense, pid), &models)
|
|
return
|
|
}
|
|
|
|
// ---- 用户设备 / 产品统计(业务库 ServiceDB)----
|
|
// 注意:userdevice、product_stat 在应用的业务库(ServiceDB),不在设备库(AdminDB)。
|
|
// 重置设备码时要连带删掉用户绑定、扣减激活统计,否则留下孤儿绑定、仪表盘数据偏高。
|
|
|
|
func dvDelUserDevice(sys *appConn, uid string) (err error) {
|
|
err = sys.ServiceDB().Delete(comm.TableUserdevice, "uid=?", uid)
|
|
return
|
|
}
|
|
|
|
// dvDecrProductStatActivated 把 product_stat.activated_count 原地减 1(下限 0)。
|
|
func dvDecrProductStatActivated(sys *appConn, productid uint32) (err error) {
|
|
err = sys.ServiceDB().Exec(
|
|
"UPDATE "+comm.TableProductStat+
|
|
" SET activated_count = GREATEST(0, activated_count - 1)"+
|
|
" WHERE productid = ?",
|
|
productid,
|
|
).Error
|
|
return
|
|
}
|
|
|
|
// ---- 出货单(写 / 单查)----
|
|
|
|
func dvFactoryDeliveryNote(sys *appConn, factoryid, probatch uint32) (model *pb.DBFactoryDeliveryNote, err error) {
|
|
model = &pb.DBFactoryDeliveryNote{}
|
|
err = sys.AdminDB().FindOne(comm.TableFactoryDeliveryNote, model, "factoryid=? and probatch=?", factoryid, probatch)
|
|
return
|
|
}
|
|
|
|
func dvAddFactoryDeliveryNote(sys *appConn, model *pb.DBFactoryDeliveryNote) (err error) {
|
|
err = sys.AdminDB().Insert(comm.TableFactoryDeliveryNote, model)
|
|
return
|
|
}
|
|
|
|
func dvDelFactoryDeliveryNote(sys *appConn, factoryid, productid, probatch uint32) (err error) {
|
|
err = sys.AdminDB().Delete(comm.TableFactoryDeliveryNote,
|
|
"factoryid=? AND productid=? AND probatch=?", factoryid, productid, probatch)
|
|
return
|
|
}
|
|
|
|
// generateCustomMAC 由 [产品id(16位) + 批次(8位) + 序号(24位)] 拼出 6 字节 MAC 字符串。
|
|
// 与 modules/api/core.go 的 GenerateCustomMAC 同源(console 不能引用对方包内未导出函数,复制一份)。
|
|
func generateCustomMAC(productid uint16, batchNumber byte, serial uint32) (code string, err error) {
|
|
if serial > 0xFFFFFF {
|
|
err = fmt.Errorf("serial must be <= 0xFFFFFF (24 bits)")
|
|
return
|
|
}
|
|
mac := []byte{
|
|
byte((productid >> 8) & 0xFF),
|
|
byte(productid & 0xFF),
|
|
byte(batchNumber & 0xFF),
|
|
byte((serial >> 16) & 0xFF),
|
|
byte((serial >> 8) & 0xFF),
|
|
byte(serial & 0xFF),
|
|
}
|
|
code = fmt.Sprintf("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
|
|
return
|
|
}
|
|
|
|
// ---- 厂家设备(授权码,按 product 分表 license_%x)----
|
|
|
|
// dvFactoryDevicsPaged 分页查询授权码(ORDER BY + LIMIT/OFFSET),返回命中总数。
|
|
func dvFactoryDevicsPaged(sys *appConn, pid uint32, query, orderClause string, limit, offset int, args ...interface{}) (models []*pb.DBFactoryDevics, total int64, err error) {
|
|
models = make([]*pb.DBFactoryDevics, 0)
|
|
tName := fmt.Sprintf("%s_%x", comm.TableLicense, pid)
|
|
|
|
tx := sys.AdminDB().Table(tName)
|
|
if query != "" {
|
|
tx = tx.Where(query, args...)
|
|
}
|
|
if err = tx.Count(&total).Error; err != nil {
|
|
return
|
|
}
|
|
tx2 := sys.AdminDB().Table(tName)
|
|
if query != "" {
|
|
tx2 = tx2.Where(query, args...)
|
|
}
|
|
if orderClause != "" {
|
|
tx2 = tx2.Order(orderClause)
|
|
}
|
|
if limit > 0 {
|
|
tx2 = tx2.Limit(limit)
|
|
}
|
|
if offset > 0 {
|
|
tx2 = tx2.Offset(offset)
|
|
}
|
|
err = tx2.Find(&models).Error
|
|
return
|
|
}
|
|
|
|
func dvFactoryDevic(sys *appConn, pid uint32, code string) (model *pb.DBFactoryDevics, err error) {
|
|
model = &pb.DBFactoryDevics{}
|
|
err = sys.AdminDB().FindOne(fmt.Sprintf("%s_%x", comm.TableLicense, pid), &model, "code=?", code)
|
|
return
|
|
}
|
|
|
|
func dvUpdateFactoryDevic(sys *appConn, pid uint32, model *pb.DBFactoryDevics) (err error) {
|
|
err = sys.AdminDB().Save(fmt.Sprintf("%s_%x", comm.TableLicense, pid), &model)
|
|
return
|
|
}
|
|
|
|
// ---- 厂家生产出货单 ----
|
|
|
|
func dvFactoryDeliveryNotes(sys *appConn, query interface{}, args ...interface{}) (models []*pb.DBFactoryDeliveryNote, err error) {
|
|
models = make([]*pb.DBFactoryDeliveryNote, 0)
|
|
err = sys.AdminDB().Find(comm.TableFactoryDeliveryNote, &models, query, args...)
|
|
return
|
|
}
|
|
|
|
// ---- 厂家公码 ----
|
|
|
|
// dvFactoryPublicCodes 按厂家 + 状态过滤(factoryid=0 不过滤厂家,statusFilter<0 不过滤状态)。
|
|
func dvFactoryPublicCodes(sys *appConn, factoryid uint32, statusFilter int32) (models []*pb.DBFactoryPublicCode, err error) {
|
|
models = make([]*pb.DBFactoryPublicCode, 0)
|
|
tx := sys.AdminDB().Table(comm.TableFactoryPublicCode)
|
|
if factoryid != 0 {
|
|
tx = tx.Where("factoryid=?", factoryid)
|
|
}
|
|
if statusFilter >= 0 {
|
|
tx = tx.Where("status=?", statusFilter)
|
|
}
|
|
err = tx.Order("createtime DESC").Find(&models).Error
|
|
return
|
|
}
|
|
|
|
func dvFactoryPublicCode(sys *appConn, code string) (model *pb.DBFactoryPublicCode, err error) {
|
|
model = &pb.DBFactoryPublicCode{}
|
|
err = sys.AdminDB().FindOne(comm.TableFactoryPublicCode, model, "code=?", code)
|
|
return
|
|
}
|
|
|
|
func dvAddFactoryPublicCode(sys *appConn, model *pb.DBFactoryPublicCode) (err error) {
|
|
err = sys.AdminDB().Insert(comm.TableFactoryPublicCode, model)
|
|
return
|
|
}
|
|
|
|
func dvSaveFactoryPublicCode(sys *appConn, model *pb.DBFactoryPublicCode) (err error) {
|
|
err = sys.AdminDB().Save(comm.TableFactoryPublicCode, model)
|
|
return
|
|
}
|
|
|
|
func dvDelFactoryPublicCode(sys *appConn, code string) (err error) {
|
|
err = sys.AdminDB().Delete(comm.TableFactoryPublicCode, "code=?", code)
|
|
return
|
|
}
|
|
|