package service import ( "fmt" "strconv" "sync" "time" ) const ( generatedChanKey = "channel_yd_mock" generatedCardType = "1" generatedPackageCode = "CMIOT-SD-500M-24M-D01" generatedSupplierCode = "SUP_CMCC" generatedMonthlyUsage = 18432.0 generatedDailyUsage = 614.4 generatedPoolUsageByte = 18874368.0 ) type inboundExportColumn struct { Header string Key string } var inboundExportColumns = []inboundExportColumn{ {Header: "ICCID*", Key: "ICCID"}, {Header: "MSISDN*", Key: "MSISDN"}, {Header: "IMSI*", Key: "IMSI"}, {Header: "IMEI", Key: "IMEI"}, {Header: "通道编号*", Key: "chanKey"}, {Header: "卡类型", Key: "cardType"}, {Header: "上游套餐编码", Key: "upPkgCode"}, {Header: "供应商编码", Key: "suppliersCode"}, {Header: "上游激活时间", Key: "upstreamActivationTime"}, {Header: "是否贴片转插拔", Key: "insertToPlugEnabled"}, {Header: "是否运营商达量断网", Key: "carrierTrafficCutoffEnabled"}, {Header: "协议到期时间", Key: "agreementExpiryDate"}, {Header: "是否有测试期", Key: "hasTestPeriod"}, {Header: "测试期天数", Key: "testPeriodDays"}, {Header: "测试期最晚过期日期", Key: "testPeriodLatestExpiryDate"}, {Header: "是否有沉默期", Key: "hasSilentPeriod"}, {Header: "沉默期天数", Key: "silentPeriodDays"}, {Header: "沉默期最晚过期日期", Key: "silentPeriodLatestExpiryDate"}, } var inboundExportHeaders = func() []string { headers := make([]string, 0, len(inboundExportColumns)) for _, column := range inboundExportColumns { headers = append(headers, column.Header) } return headers }() // 生成序号分配器。 // // 序号直接来自毫秒时间戳时,同一毫秒内的两次生成会得到完全相同的 seq, // 进而生成重复的 ICCID/IMSI,触发 mock_t_sim_card 的唯一约束冲突 // (表现为「一键生成」连点两次或两个分组连续生成时报 // UNIQUE constraint failed: mock_t_sim_card.imsi)。 // // 这里用进程内单调递增的上界保证 seq 严格递增:时间戳只决定起点, // 真正的唯一性由 nextGeneratedSeq 保证。 var ( generatedSeqMu sync.Mutex generatedSeqLast int64 ) // nextGeneratedSeq 返回严格大于上一次分配值的序号。 func nextGeneratedSeq(candidate int64) int64 { generatedSeqMu.Lock() defer generatedSeqMu.Unlock() if candidate <= generatedSeqLast { candidate = generatedSeqLast + 1 } generatedSeqLast = candidate return candidate } func GenerateSIMCards(batchTime time.Time, count int) []SIMCard { if count <= 0 { return []SIMCard{} } cards := make([]SIMCard, 0, count) base := batchTime.UnixMilli() dbTime := batchTime.Format("2006-01-02 15:04:05") for i := 0; i < count; i++ { seq := nextGeneratedSeq(base + int64(i+1)) card := SIMCard{ MSISDN: fmt.Sprintf("141%08d", seq%100000000), ICCID: fmt.Sprintf("898604%014d", seq%100000000000000), IMSI: fmt.Sprintf("46004%010d", seq%10000000000), IMEI: fmt.Sprintf("86%013d", seq%10000000000000), Remark: sourceRemark("CMCC", generatedPackageCode, generatedPackageCode), CardStatus: "2", LastChangeDate: dbTime, StopReason: "000000000000", FrozenStatus: "0", FrozenOperTime: batchTime.Format("20060102150405"), OpenDate: dbTime, ActiveDate: dbTime, OnOffStatus: "1", SessionStatus: "01", IP: fmt.Sprintf("10.%d.%d.%d", (seq/10000)%255, (seq/100)%255, seq%255), IPv6Prefix: "", IPv6: "", RAT: "6", CardBindStatus: "1", RegionLimitStatus: "0", AreaRestrictType: "1", RestrictedArea: "110000,310000,440000", MonthUsageKB: generatedMonthlyUsage, PoolUsageBytes: generatedPoolUsageByte, DailyBaseKB: generatedDailyUsage, MonthlyBaseKB: generatedMonthlyUsage, GrowthPerMinuteKB: 0, LastUsageUpdateTime: batchTime.Format(time.RFC3339), APNs: []APN{ {Name: "CMIOT", Status: "1", UsageBytes: generatedPoolUsageByte, ModifyTime: batchTime.Format("20060102150405"), ServiceUsageState: "1", PCCs: []PCC{{ServiceCode: "default", Name: "APN 缺省流量", PolicyStatus: "2", ServiceUsageState: "1", ModifyTime: batchTime.Format("20060102150405")}}}, }, } cards = append(cards, card) } return cards } func inboundExportRow(card SIMCard) map[string]string { activation := parseCardTime(card.ActiveDate) return map[string]string{ "ICCID": card.ICCID, "MSISDN": card.MSISDN, "IMSI": card.IMSI, "IMEI": card.IMEI, "chanKey": generatedChanKey, "cardType": generatedCardType, "upPkgCode": generatedPackageCode, "suppliersCode": generatedSupplierCode, "upstreamActivationTime": activation.Format("2006-01-02 15:04:05"), "insertToPlugEnabled": "true", "carrierTrafficCutoffEnabled": "false", "agreementExpiryDate": activation.AddDate(1, 0, 0).Format("2006-01-02"), "hasTestPeriod": "true", "testPeriodDays": "30", "testPeriodLatestExpiryDate": activation.AddDate(0, 0, 30).Format("2006-01-02"), "hasSilentPeriod": "false", "silentPeriodDays": "", "silentPeriodLatestExpiryDate": "", } } func parseCardTime(value string) time.Time { for _, layout := range []string{"2006-01-02 15:04:05", time.RFC3339, time.RFC3339Nano} { if t, err := time.ParseInLocation(layout, value, time.Local); err == nil { return t } } if unixMilli, err := strconv.ParseInt(value, 10, 64); err == nil { return time.UnixMilli(unixMilli) } return time.Now() }