Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fd475d3e63 | |||
| 9b3546b45f | |||
| b8c8c7d7b1 | |||
| 58b8849d8d |
@@ -19,7 +19,7 @@ WORKDIR /app
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
|
||||
COPY --from=builder /build/bin/platform_linux_amd64 /app/platform
|
||||
|
||||
30
pkg/u/u.go
30
pkg/u/u.go
@@ -53,6 +53,18 @@ func X[T comparable](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
// N 零值视为 nil
|
||||
func N[T comparable](v *T) *T {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
var zero T
|
||||
if *v == zero {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// ====================
|
||||
// 数组
|
||||
// ====================
|
||||
@@ -110,3 +122,21 @@ func CombineErrors(errs []error) error {
|
||||
}
|
||||
return combinedErr
|
||||
}
|
||||
|
||||
// ====================
|
||||
// 业务
|
||||
// ====================
|
||||
|
||||
func MaskPhone(phone string) string {
|
||||
if len(phone) < 11 {
|
||||
return phone
|
||||
}
|
||||
return phone[:3] + "****" + phone[7:]
|
||||
}
|
||||
|
||||
func MaskIdNo(idNo string) string {
|
||||
if len(idNo) < 18 {
|
||||
return idNo
|
||||
}
|
||||
return idNo[:3] + "*********" + idNo[14:]
|
||||
}
|
||||
|
||||
@@ -15,9 +15,93 @@ insert into admin (username, password, name, lock) values ('admin', '', '超级
|
||||
-- region 产品
|
||||
-- ====================
|
||||
|
||||
insert into product (code, name, description) values ('short', '短效动态', '短效动态');
|
||||
insert into product (code, name, description) values ('long', '长效动态', '长效动态');
|
||||
insert into product (code, name, description) values ('static', '长效静态', '长效静态');
|
||||
delete from product where true;
|
||||
|
||||
insert into product (code, name, description, sort) values ('short', '短效动态', '短效动态', 1);
|
||||
insert into product (code, name, description, sort) values ('long', '长效动态', '长效动态', 2);
|
||||
insert into product (code, name, description, sort) values ('static', '长效静态', '长效静态', 3);
|
||||
|
||||
-- ====================
|
||||
-- region 套餐
|
||||
-- ====================
|
||||
|
||||
delete from product_sku where true;
|
||||
|
||||
insert into product_sku (product_id, code, name, price, price_min, sort) values
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=quota&live=3&expire=0', '短效动态包量 3 分钟', 10.00, 10.00, 1),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=quota&live=5&expire=0', '短效动态包量 5 分钟', 10.00, 10.00, 2),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=quota&live=10&expire=0', '短效动态包量 10 分钟', 10.00, 10.00, 3),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=quota&live=15&expire=0', '短效动态包量 15 分钟', 10.00, 10.00, 4),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=quota&live=30&expire=0', '短效动态包量 30 分钟', 10.00, 10.00, 5),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=3&expire=7', '短效动态包时 3 分钟 7 天', 10.00, 10.00, 6),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=5&expire=7', '短效动态包时 5 分钟 7 天', 10.00, 10.00, 7),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=10&expire=7', '短效动态包时 10 分钟 7 天', 10.00, 10.00, 8),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=15&expire=7', '短效动态包时 15 分钟 7 天', 10.00, 10.00, 9),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=30&expire=7', '短效动态包时 30 分钟 7 天', 10.00, 10.00, 10),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=3&expire=15', '短效动态包时 3 分钟 15 天', 10.00, 10.00, 11),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=5&expire=15', '短效动态包时 5 分钟 15 天', 10.00, 10.00, 12),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=10&expire=15', '短效动态包时 10 分钟 15 天', 10.00, 10.00, 13),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=15&expire=15', '短效动态包时 15 分钟 15 天', 10.00, 10.00, 14),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=30&expire=15', '短效动态包时 30 分钟 15 天', 10.00, 10.00, 15),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=3&expire=30', '短效动态包时 3 分钟 30 天', 10.00, 10.00, 16),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=5&expire=30', '短效动态包时 5 分钟 30 天', 10.00, 10.00, 17),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=10&expire=30', '短效动态包时 10 分钟 30 天', 10.00, 10.00, 18),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=15&expire=30', '短效动态包时 15 分钟 30 天', 10.00, 10.00, 19),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=30&expire=30', '短效动态包时 30 分钟 30 天', 10.00, 10.00, 20),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=3&expire=90', '短效动态包时 3 分钟 90 天', 10.00, 10.00, 21),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=5&expire=90', '短效动态包时 5 分钟 90 天', 10.00, 10.00, 22),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=10&expire=90', '短效动态包时 10 分钟 90 天', 10.00, 10.00, 23),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=15&expire=90', '短效动态包时 15 分钟 90 天', 10.00, 10.00, 24),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=30&expire=90', '短效动态包时 30 分钟 90 天', 10.00, 10.00, 25),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=3&expire=180', '短效动态包时 3 分钟 180 天', 10.00, 10.00, 26),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=5&expire=180', '短效动态包时 5 分钟 180 天', 10.00, 10.00, 27),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=10&expire=180', '短效动态包时 10 分钟 180 天', 10.00, 10.00, 28),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=15&expire=180', '短效动态包时 15 分钟 180 天', 10.00, 10.00, 29),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=30&expire=180', '短效动态包时 30 分钟 180 天', 10.00, 10.00, 30),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=3&expire=365', '短效动态包时 3 分钟 365 天', 10.00, 10.00, 31),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=5&expire=365', '短效动态包时 5 分钟 365 天', 10.00, 10.00, 32),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=10&expire=365', '短效动态包时 10 分钟 365 天', 10.00, 10.00, 33),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=15&expire=365', '短效动态包时 15 分钟 365 天', 10.00, 10.00, 34),
|
||||
((select id from product where code = 'short' and deleted_at is null), 'mode=time&live=30&expire=365', '短效动态包时 30 分钟 365 天', 10.00, 10.00, 35)
|
||||
;
|
||||
|
||||
insert into product_sku (product_id, code, name, price, price_min, sort) values
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=quota&live=60&expire=0', '长效动态包量 1 小时', 10.00, 10.00, 1),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=quota&live=240&expire=0', '长效动态包量 4 小时', 10.00, 10.00, 2),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=quota&live=480&expire=0', '长效动态包量 8 小时', 10.00, 10.00, 3),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=quota&live=720&expire=0', '长效动态包量 12 小时', 10.00, 10.00, 4),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=quota&live=1440&expire=0', '长效动态包量 24 小时', 10.00, 10.00, 5),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=60&expire=7', '长效动态包时 1 小时 7 天', 10.00, 10.00, 6),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=240&expire=7', '长效动态包时 4 小时 7 天', 10.00, 10.00, 7),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=480&expire=7', '长效动态包时 8 小时 7 天', 10.00, 10.00, 8),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=720&expire=7', '长效动态包时 12 小时 7 天', 10.00, 10.00, 9),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=1440&expire=7', '长效动态包时 24 小时 7 天', 10.00, 10.00, 10),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=60&expire=15', '长效动态包时 1 小时 15 天', 10.00, 10.00, 11),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=240&expire=15', '长效动态包时 4 小时 15 天', 10.00, 10.00, 12),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=480&expire=15', '长效动态包时 8 小时 15 天', 10.00, 10.00, 13),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=720&expire=15', '长效动态包时 12 小时 15 天', 10.00, 10.00, 14),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=1440&expire=15', '长效动态包时 24 小时 15 天', 10.00, 10.00, 15),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=60&expire=30', '长效动态包时 1 小时 30 天', 10.00, 10.00, 16),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=240&expire=30', '长效动态包时 4 小时 30 天', 10.00, 10.00, 17),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=480&expire=30', '长效动态包时 8 小时 30 天', 10.00, 10.00, 18),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=720&expire=30', '长效动态包时 12 小时 30 天', 10.00, 10.00, 19),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=1440&expire=30', '长效动态包时 24 小时 30 天', 10.00, 10.00, 20),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=60&expire=90', '长效动态包时 1 小时 90 天', 10.00, 10.00, 21),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=240&expire=90', '长效动态包时 4 小时 90 天', 10.00, 10.00, 22),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=480&expire=90', '长效动态包时 8 小时 90 天', 10.00, 10.00, 23),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=720&expire=90', '长效动态包时 12 小时 90 天', 10.00, 10.00, 24),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=1440&expire=90', '长效动态包时 24 小时 90 天', 10.00, 10.00, 25),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=60&expire=180', '长效动态包时 1 小时 180 天', 10.00, 10.00, 26),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=240&expire=180', '长效动态包时 4 小时 180 天', 10.00, 10.00, 27),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=480&expire=180', '长效动态包时 8 小时 180 天', 10.00, 10.00, 28),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=720&expire=180', '长效动态包时 12 小时 180 天', 10.00, 10.00, 29),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=1440&expire=180','长效动态包时 24 小时 180 天', 10.00, 10.00, 30),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=60&expire=365', '长效动态包时 1 小时 365 天', 10.00, 10.00, 31),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=240&expire=365', '长效动态包时 4 小时 365 天', 10.00, 10.00, 32),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=480&expire=365', '长效动态包时 8 小时 365 天', 10.00, 10.00, 33),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=720&expire=365', '长效动态包时 12 小时 365 天', 10.00, 10.00, 34),
|
||||
((select id from product where code = 'long' and deleted_at is null), 'mode=time&live=1440&expire=365','长效动态包时 24 小时 365 天', 10.00, 10.00, 35)
|
||||
;
|
||||
|
||||
-- ====================
|
||||
-- region 权限
|
||||
|
||||
@@ -761,6 +761,7 @@ create table product_sku (
|
||||
price decimal not null,
|
||||
price_min decimal not null,
|
||||
status int not null default 1,
|
||||
sort int not null default 0,
|
||||
created_at timestamptz default current_timestamp,
|
||||
updated_at timestamptz default current_timestamp,
|
||||
deleted_at timestamptz
|
||||
@@ -778,6 +779,7 @@ comment on column product_sku.code is 'SKU 代码:格式为 key=value,key=valu
|
||||
comment on column product_sku.name is 'SKU 可读名称';
|
||||
comment on column product_sku.price_min is '最低价格';
|
||||
comment on column product_sku.status is 'SKU状态:0-禁用,1-正常';
|
||||
comment on column product_sku.sort is '排序';
|
||||
comment on column product_sku.created_at is '创建时间';
|
||||
comment on column product_sku.updated_at is '更新时间';
|
||||
comment on column product_sku.deleted_at is '删除时间';
|
||||
|
||||
81
scripts/sql/update.sql
Normal file
81
scripts/sql/update.sql
Normal file
@@ -0,0 +1,81 @@
|
||||
-- ====================
|
||||
-- region 套餐更新
|
||||
-- ====================
|
||||
|
||||
-- --------------------------
|
||||
-- 短效动态
|
||||
-- --------------------------
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包量 3 分钟', price = 10.00, price_min = 10.00, sort = 1 where code = 'mode=quota&live=3&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包量 5 分钟', price = 10.00, price_min = 10.00, sort = 2 where code = 'mode=quota&live=5&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包量 10 分钟', price = 10.00, price_min = 10.00, sort = 3 where code = 'mode=quota&live=10&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包量 15 分钟', price = 10.00, price_min = 10.00, sort = 4 where code = 'mode=quota&live=15&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包量 30 分钟', price = 10.00, price_min = 10.00, sort = 5 where code = 'mode=quota&live=30&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 3 分钟 7 天', price = 10.00, price_min = 10.00, sort = 6 where code = 'mode=time&live=3&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 5 分钟 7 天', price = 10.00, price_min = 10.00, sort = 7 where code = 'mode=time&live=5&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 10 分钟 7 天', price = 10.00, price_min = 10.00, sort = 8 where code = 'mode=time&live=10&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 15 分钟 7 天', price = 10.00, price_min = 10.00, sort = 9 where code = 'mode=time&live=15&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 30 分钟 7 天', price = 10.00, price_min = 10.00, sort = 10 where code = 'mode=time&live=30&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 3 分钟 15 天', price = 10.00, price_min = 10.00, sort = 11 where code = 'mode=time&live=3&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 5 分钟 15 天', price = 10.00, price_min = 10.00, sort = 12 where code = 'mode=time&live=5&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 10 分钟 15 天', price = 10.00, price_min = 10.00, sort = 13 where code = 'mode=time&live=10&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 15 分钟 15 天', price = 10.00, price_min = 10.00, sort = 14 where code = 'mode=time&live=15&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 30 分钟 15 天', price = 10.00, price_min = 10.00, sort = 15 where code = 'mode=time&live=30&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 3 分钟 30 天', price = 10.00, price_min = 10.00, sort = 16 where code = 'mode=time&live=3&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 5 分钟 30 天', price = 10.00, price_min = 10.00, sort = 17 where code = 'mode=time&live=5&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 10 分钟 30 天', price = 10.00, price_min = 10.00, sort = 18 where code = 'mode=time&live=10&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 15 分钟 30 天', price = 10.00, price_min = 10.00, sort = 19 where code = 'mode=time&live=15&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 30 分钟 30 天', price = 10.00, price_min = 10.00, sort = 20 where code = 'mode=time&live=30&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 3 分钟 90 天', price = 10.00, price_min = 10.00, sort = 21 where code = 'mode=time&live=3&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 5 分钟 90 天', price = 10.00, price_min = 10.00, sort = 22 where code = 'mode=time&live=5&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 10 分钟 90 天', price = 10.00, price_min = 10.00, sort = 23 where code = 'mode=time&live=10&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 15 分钟 90 天', price = 10.00, price_min = 10.00, sort = 24 where code = 'mode=time&live=15&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 30 分钟 90 天', price = 10.00, price_min = 10.00, sort = 25 where code = 'mode=time&live=30&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 3 分钟 180 天', price = 10.00, price_min = 10.00, sort = 26 where code = 'mode=time&live=3&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 5 分钟 180 天', price = 10.00, price_min = 10.00, sort = 27 where code = 'mode=time&live=5&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 10 分钟 180 天', price = 10.00, price_min = 10.00, sort = 28 where code = 'mode=time&live=10&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 15 分钟 180 天', price = 10.00, price_min = 10.00, sort = 29 where code = 'mode=time&live=15&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 30 分钟 180 天', price = 10.00, price_min = 10.00, sort = 30 where code = 'mode=time&live=30&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 3 分钟 365 天', price = 10.00, price_min = 10.00, sort = 31 where code = 'mode=time&live=3&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 5 分钟 365 天', price = 10.00, price_min = 10.00, sort = 32 where code = 'mode=time&live=5&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 10 分钟 365 天', price = 10.00, price_min = 10.00, sort = 33 where code = 'mode=time&live=10&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 15 分钟 365 天', price = 10.00, price_min = 10.00, sort = 34 where code = 'mode=time&live=15&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'short' and deleted_at is null), name = '短效动态包时 30 分钟 365 天', price = 10.00, price_min = 10.00, sort = 35 where code = 'mode=time&live=30&expire=365' and deleted_at is null;
|
||||
|
||||
-- --------------------------
|
||||
-- 长效动态
|
||||
-- --------------------------
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包量 1 小时', price = 10.00, price_min = 10.00, sort = 1 where code = 'mode=quota&live=60&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包量 4 小时', price = 10.00, price_min = 10.00, sort = 2 where code = 'mode=quota&live=240&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包量 8 小时', price = 10.00, price_min = 10.00, sort = 3 where code = 'mode=quota&live=480&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包量 12 小时', price = 10.00, price_min = 10.00, sort = 4 where code = 'mode=quota&live=720&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包量 24 小时', price = 10.00, price_min = 10.00, sort = 5 where code = 'mode=quota&live=1440&expire=0' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 1 小时 7 天', price = 10.00, price_min = 10.00, sort = 6 where code = 'mode=time&live=60&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 4 小时 7 天', price = 10.00, price_min = 10.00, sort = 7 where code = 'mode=time&live=240&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 8 小时 7 天', price = 10.00, price_min = 10.00, sort = 8 where code = 'mode=time&live=480&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 12 小时 7 天', price = 10.00, price_min = 10.00, sort = 9 where code = 'mode=time&live=720&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 24 小时 7 天', price = 10.00, price_min = 10.00, sort = 10 where code = 'mode=time&live=1440&expire=7' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 1 小时 15 天', price = 10.00, price_min = 10.00, sort = 11 where code = 'mode=time&live=60&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 4 小时 15 天', price = 10.00, price_min = 10.00, sort = 12 where code = 'mode=time&live=240&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 8 小时 15 天', price = 10.00, price_min = 10.00, sort = 13 where code = 'mode=time&live=480&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 12 小时 15 天', price = 10.00, price_min = 10.00, sort = 14 where code = 'mode=time&live=720&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 24 小时 15 天', price = 10.00, price_min = 10.00, sort = 15 where code = 'mode=time&live=1440&expire=15' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 1 小时 30 天', price = 10.00, price_min = 10.00, sort = 16 where code = 'mode=time&live=60&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 4 小时 30 天', price = 10.00, price_min = 10.00, sort = 17 where code = 'mode=time&live=240&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 8 小时 30 天', price = 10.00, price_min = 10.00, sort = 18 where code = 'mode=time&live=480&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 12 小时 30 天', price = 10.00, price_min = 10.00, sort = 19 where code = 'mode=time&live=720&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 24 小时 30 天', price = 10.00, price_min = 10.00, sort = 20 where code = 'mode=time&live=1440&expire=30' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 1 小时 90 天', price = 10.00, price_min = 10.00, sort = 21 where code = 'mode=time&live=60&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 4 小时 90 天', price = 10.00, price_min = 10.00, sort = 22 where code = 'mode=time&live=240&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 8 小时 90 天', price = 10.00, price_min = 10.00, sort = 23 where code = 'mode=time&live=480&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 12 小时 90 天', price = 10.00, price_min = 10.00, sort = 24 where code = 'mode=time&live=720&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 24 小时 90 天', price = 10.00, price_min = 10.00, sort = 25 where code = 'mode=time&live=1440&expire=90' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 1 小时 180 天', price = 10.00, price_min = 10.00, sort = 26 where code = 'mode=time&live=60&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 4 小时 180 天', price = 10.00, price_min = 10.00, sort = 27 where code = 'mode=time&live=240&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 8 小时 180 天', price = 10.00, price_min = 10.00, sort = 28 where code = 'mode=time&live=480&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 12 小时 180 天', price = 10.00, price_min = 10.00, sort = 29 where code = 'mode=time&live=720&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 24 小时 180 天', price = 10.00, price_min = 10.00, sort = 30 where code = 'mode=time&live=1440&expire=180' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 1 小时 365 天', price = 10.00, price_min = 10.00, sort = 31 where code = 'mode=time&live=60&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 4 小时 365 天', price = 10.00, price_min = 10.00, sort = 32 where code = 'mode=time&live=240&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 8 小时 365 天', price = 10.00, price_min = 10.00, sort = 33 where code = 'mode=time&live=480&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 12 小时 365 天', price = 10.00, price_min = 10.00, sort = 34 where code = 'mode=time&live=720&expire=365' and deleted_at is null;
|
||||
update product_sku set product_id = (select id from product where code = 'long' and deleted_at is null), name = '长效动态包时 24 小时 365 天', price = 10.00, price_min = 10.00, sort = 35 where code = 'mode=time&live=1440&expire=365' and deleted_at is null;
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"platform/pkg/u"
|
||||
"platform/web/core"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
@@ -50,9 +49,8 @@ func authUser(loginType PwdLoginType, username, password string) (user *m.User,
|
||||
}
|
||||
if user == nil {
|
||||
user = &m.User{
|
||||
Phone: username,
|
||||
Username: u.P(username),
|
||||
Status: m.UserStatusEnabled,
|
||||
Phone: username,
|
||||
Status: m.UserStatusEnabled,
|
||||
}
|
||||
}
|
||||
case PwdLoginByEmail:
|
||||
@@ -79,7 +77,7 @@ func authUser(loginType PwdLoginType, username, password string) (user *m.User,
|
||||
|
||||
func authUserBySms(tx *q.Query, username, code string) (*m.User, error) {
|
||||
// 验证验证码
|
||||
err := s.Verifier.VerifySms(context.Background(), username, code)
|
||||
err := s.Verifier.VerifySms(context.Background(), username, code, s.VerifierSmsPurposeLogin)
|
||||
if err != nil {
|
||||
return nil, core.NewBizErr("短信认证失败", err)
|
||||
}
|
||||
|
||||
@@ -537,10 +537,10 @@ func introspectUser(ctx *fiber.Ctx, authCtx *AuthCtx) error {
|
||||
|
||||
// 掩码敏感信息
|
||||
if profile.Phone != "" {
|
||||
profile.Phone = maskPhone(profile.Phone)
|
||||
profile.Phone = u.MaskPhone(profile.Phone)
|
||||
}
|
||||
if profile.IDNo != nil && *profile.IDNo != "" {
|
||||
profile.IDNo = u.P(maskIdNo(*profile.IDNo))
|
||||
profile.IDNo = u.P(u.MaskIdNo(*profile.IDNo))
|
||||
}
|
||||
|
||||
return ctx.JSON(struct {
|
||||
@@ -579,20 +579,6 @@ func introspectAdmin(ctx *fiber.Ctx, authCtx *AuthCtx) error {
|
||||
}{profile, list})
|
||||
}
|
||||
|
||||
func maskPhone(phone string) string {
|
||||
if len(phone) < 11 {
|
||||
return phone
|
||||
}
|
||||
return phone[:3] + "****" + phone[7:]
|
||||
}
|
||||
|
||||
func maskIdNo(idNo string) string {
|
||||
if len(idNo) < 18 {
|
||||
return idNo
|
||||
}
|
||||
return idNo[:3] + "*********" + idNo[14:]
|
||||
}
|
||||
|
||||
type CodeContext struct {
|
||||
UserID int32 `json:"user_id"`
|
||||
ClientID int32 `json:"client_id"`
|
||||
|
||||
@@ -12,9 +12,9 @@ type IModel interface {
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
ID int32 `json:"id" gorm:"column:id;primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
|
||||
ID int32 `json:"id,omitzero" gorm:"column:id;primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at,omitzero" gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitzero" gorm:"column:updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"column:deleted_at"`
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@ func PageBalanceActivityByAdmin(c *fiber.Ctx) error {
|
||||
if req.UserPhone != nil {
|
||||
do = do.Where(q.User.As("User").Phone.Eq(*req.UserPhone))
|
||||
}
|
||||
if req.BillNo != nil {
|
||||
do = do.Where(q.Bill.As("Bill").BillNo.Eq(*req.BillNo))
|
||||
}
|
||||
if req.CreatedAtStart != nil {
|
||||
t := u.DateHead(*req.CreatedAtStart)
|
||||
do = do.Where(q.BalanceActivity.CreatedAt.Gte(t))
|
||||
@@ -68,6 +71,7 @@ func PageBalanceActivityByAdmin(c *fiber.Ctx) error {
|
||||
type PageBalanceActivityByAdminReq struct {
|
||||
core.PageReq
|
||||
UserPhone *string `json:"user_phone,omitempty"`
|
||||
BillNo *string `json:"bill_no,omitempty"`
|
||||
CreatedAtStart *time.Time `json:"created_at_start,omitempty"`
|
||||
CreatedAtEnd *time.Time `json:"created_at_end,omitempty"`
|
||||
}
|
||||
@@ -88,6 +92,9 @@ func PageBalanceActivityOfUserByAdmin(c *fiber.Ctx) error {
|
||||
|
||||
// 构造查询条件
|
||||
do := q.BalanceActivity.Where(q.BalanceActivity.UserID.Eq(req.UserID))
|
||||
if req.BillNo != nil {
|
||||
do = do.Where(q.Bill.As("Bill").BillNo.Eq(*req.BillNo))
|
||||
}
|
||||
if req.CreatedAtStart != nil {
|
||||
t := u.DateHead(*req.CreatedAtStart)
|
||||
do = do.Where(q.BalanceActivity.CreatedAt.Gte(t))
|
||||
@@ -124,6 +131,7 @@ func PageBalanceActivityOfUserByAdmin(c *fiber.Ctx) error {
|
||||
type PageBalanceActivityOfUserByAdminReq struct {
|
||||
core.PageReq
|
||||
UserID int32 `json:"user_id" validate:"required"`
|
||||
BillNo *string `json:"bill_no,omitempty"`
|
||||
CreatedAtStart *time.Time `json:"created_at_start,omitempty"`
|
||||
CreatedAtEnd *time.Time `json:"created_at_end,omitempty"`
|
||||
}
|
||||
|
||||
@@ -34,6 +34,15 @@ func AllProductByAdmin(c *fiber.Ctx) error {
|
||||
type AllProductsByAdminReq struct {
|
||||
}
|
||||
|
||||
func AllProduct(c *fiber.Ctx) error {
|
||||
infos, err := s.Product.AllProductSaleInfos()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(infos)
|
||||
}
|
||||
|
||||
func CreateProduct(c *fiber.Ctx) error {
|
||||
_, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeProductWrite)
|
||||
if err != nil {
|
||||
|
||||
@@ -797,10 +797,7 @@ type CreateResourceReq struct {
|
||||
// ResourcePrice 套餐价格
|
||||
func ResourcePrice(c *fiber.Ctx) error {
|
||||
// 检查权限
|
||||
_, err := auth.GetAuthCtx(c).PermitSecretClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ac := auth.GetAuthCtx(c)
|
||||
|
||||
// 解析请求参数
|
||||
var req = new(CreateResourceReq)
|
||||
@@ -809,7 +806,7 @@ func ResourcePrice(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 获取套餐价格
|
||||
detail, err := req.TradeDetail(nil)
|
||||
detail, err := req.TradeDetail(ac.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -817,11 +814,13 @@ func ResourcePrice(c *fiber.Ctx) error {
|
||||
// 计算折扣
|
||||
return c.JSON(ResourcePriceResp{
|
||||
Price: detail.Amount.StringFixed(2),
|
||||
Discounted: detail.Actual.StringFixed(2),
|
||||
Discounted: detail.Discounted.StringFixed(2),
|
||||
Actual: detail.Actual.StringFixed(2),
|
||||
})
|
||||
}
|
||||
|
||||
type ResourcePriceResp struct {
|
||||
Price string `json:"price"`
|
||||
Discounted string `json:"discounted_price"`
|
||||
Discounted string `json:"discounted"`
|
||||
Actual string `json:"actual"`
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/shopspring/decimal"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gen/field"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -305,14 +306,26 @@ func UpdateUser(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
do := make([]field.AssignExpr, 0)
|
||||
if req.Username != nil && *req.Username != "" {
|
||||
do = append(do, q.User.Username.Value(*req.Username))
|
||||
}
|
||||
if req.Email != nil {
|
||||
if *req.Email == "" {
|
||||
do = append(do, q.User.Email.Null())
|
||||
} else {
|
||||
do = append(do, q.User.Email.Value(*req.Email))
|
||||
}
|
||||
}
|
||||
if req.ContactQQ != nil {
|
||||
do = append(do, q.User.ContactQQ.Value(*req.ContactQQ))
|
||||
}
|
||||
if req.ContactWechat != nil {
|
||||
do = append(do, q.User.ContactWechat.Value(*req.ContactWechat))
|
||||
}
|
||||
_, err = q.User.
|
||||
Where(q.User.ID.Eq(authCtx.User.ID)).
|
||||
Updates(m.User{
|
||||
Username: &req.Username,
|
||||
Email: &req.Email,
|
||||
ContactQQ: &req.ContactQQ,
|
||||
ContactWechat: &req.ContactWechat,
|
||||
})
|
||||
UpdateSimple(do...)
|
||||
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
||||
return core.NewBizErr("用户名或邮箱已被占用")
|
||||
}
|
||||
@@ -325,10 +338,10 @@ func UpdateUser(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
type UpdateUserReq struct {
|
||||
Username string `json:"username" validate:"omitempty,min=3,max=20"`
|
||||
Email string `json:"email" validate:"omitempty,email"`
|
||||
ContactQQ string `json:"contact_qq" validate:"omitempty,qq"`
|
||||
ContactWechat string `json:"contact_wechat" validate:"omitempty,wechat"`
|
||||
Username *string `json:"username" validate:"omitempty,min=3,max=20"`
|
||||
Email *string `json:"email" validate:"omitempty,email"`
|
||||
ContactQQ *string `json:"contact_qq" validate:"omitempty,qq"`
|
||||
ContactWechat *string `json:"contact_wechat" validate:"omitempty,wechat"`
|
||||
}
|
||||
|
||||
// 更新账号信息
|
||||
@@ -379,16 +392,14 @@ func UpdatePassword(c *fiber.Ctx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证手机号
|
||||
if req.Phone != authCtx.User.Phone {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "手机号码不正确")
|
||||
}
|
||||
|
||||
// 验证手机令牌
|
||||
if req.Code == "" {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "手机号码和验证码不能为空")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "验证码不能为空")
|
||||
}
|
||||
err = s.Verifier.VerifySms(c.Context(), authCtx.User.Phone, req.Code, s.VerifierSmsPurposePassword)
|
||||
if errors.Is(err, s.ErrVerifierServiceInvalid) {
|
||||
return core.NewBizErr(s.ErrVerifierServiceInvalid.Error())
|
||||
}
|
||||
err = s.Verifier.VerifySms(c.Context(), req.Phone, req.Code)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -411,7 +422,6 @@ func UpdatePassword(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
type UpdatePasswordReq struct {
|
||||
Phone string `json:"phone"`
|
||||
Code string `json:"code"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"platform/pkg/env"
|
||||
"platform/web/auth"
|
||||
"platform/web/services"
|
||||
s "platform/web/services"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
@@ -13,12 +14,11 @@ import (
|
||||
)
|
||||
|
||||
type VerifierReq struct {
|
||||
Purpose services.VerifierSmsPurpose `json:"purpose"`
|
||||
Phone string `json:"phone"`
|
||||
Purpose s.VerifierSmsPurpose `json:"purpose"`
|
||||
Phone string `json:"phone"`
|
||||
}
|
||||
|
||||
func SmsCode(c *fiber.Ctx) error {
|
||||
|
||||
func SendSmsCode(c *fiber.Ctx) error {
|
||||
_, err := auth.GetAuthCtx(c).PermitOfficialClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -38,9 +38,9 @@ func SmsCode(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 发送身份验证码
|
||||
err = services.Verifier.SendSms(c.Context(), req.Phone, req.Purpose)
|
||||
err = s.Verifier.SendSms(c.Context(), req.Phone, req.Purpose)
|
||||
if err != nil {
|
||||
var sErr services.VerifierServiceSendLimitErr
|
||||
var sErr s.VerifierServiceSendLimitErr
|
||||
if errors.As(err, &sErr) {
|
||||
return fiber.NewError(fiber.StatusTooManyRequests, strconv.Itoa(int(sErr)))
|
||||
}
|
||||
@@ -51,6 +51,23 @@ func SmsCode(c *fiber.Ctx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendSmsCodeForPassword(c *fiber.Ctx) error {
|
||||
ac, err := auth.GetAuthCtx(c).PermitUser()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Verifier.SendSms(c.Context(), ac.User.Phone, s.VerifierSmsPurposePassword); err != nil {
|
||||
var sErr s.VerifierServiceSendLimitErr
|
||||
if errors.As(err, &sErr) {
|
||||
return fiber.NewError(fiber.StatusTooManyRequests, strconv.Itoa(int(sErr)))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DebugGetSmsCode(c *fiber.Ctx) error {
|
||||
if env.RunMode != env.RunModeDev {
|
||||
return fiber.NewError(fiber.StatusForbidden, "not allowed")
|
||||
|
||||
@@ -12,6 +12,8 @@ type Product struct {
|
||||
Description *string `json:"description,omitempty" gorm:"column:description"` // 产品描述
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 排序
|
||||
Status ProductStatus `json:"status" gorm:"column:status"` // 产品状态:0-禁用,1-正常
|
||||
|
||||
Skus []*ProductSku `json:"skus,omitempty" gorm:"foreignKey:ProductID"` // 产品包含的SKU列表
|
||||
}
|
||||
|
||||
// ProductStatus 产品状态枚举
|
||||
|
||||
@@ -16,6 +16,7 @@ type ProductSku struct {
|
||||
Price decimal.Decimal `json:"price" gorm:"column:price"` // 定价
|
||||
PriceMin decimal.Decimal `json:"price_min" gorm:"column:price_min"` // 最低价格
|
||||
Status SkuStatus `json:"status" gorm:"column:status"` // SKU 状态:0-禁用,1-正常
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 排序
|
||||
|
||||
Product *Product `json:"product,omitempty" gorm:"foreignKey:ProductID"`
|
||||
Discount *ProductDiscount `json:"discount,omitempty" gorm:"foreignKey:DiscountId"`
|
||||
|
||||
@@ -145,6 +145,9 @@ func newBalanceActivity(db *gorm.DB, opts ...gen.DOOption) balanceActivity {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -173,6 +176,9 @@ func newBalanceActivity(db *gorm.DB, opts ...gen.DOOption) balanceActivity {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -184,6 +190,9 @@ func newBalanceActivity(db *gorm.DB, opts ...gen.DOOption) balanceActivity {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -192,8 +201,16 @@ func newBalanceActivity(db *gorm.DB, opts ...gen.DOOption) balanceActivity {
|
||||
RelationField: field.NewRelation("Bill.Resource.Short.Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Bill.Resource.Short.Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Bill.Resource.Short.Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -482,6 +499,9 @@ type balanceActivityBelongsToBill struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -143,6 +143,9 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -154,6 +157,9 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -162,8 +168,16 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill {
|
||||
RelationField: field.NewRelation("Resource.Short.Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Resource.Short.Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Resource.Short.Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -540,6 +554,9 @@ type billBelongsToResource struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -138,6 +138,9 @@ func newChannel(db *gorm.DB, opts ...gen.DOOption) channel {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -149,6 +152,9 @@ func newChannel(db *gorm.DB, opts ...gen.DOOption) channel {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -157,8 +163,16 @@ func newChannel(db *gorm.DB, opts ...gen.DOOption) channel {
|
||||
RelationField: field.NewRelation("Resource.Short.Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Resource.Short.Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Resource.Short.Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -490,6 +504,9 @@ type channelBelongsToResource struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -128,6 +128,9 @@ func newLogsUserUsage(db *gorm.DB, opts ...gen.DOOption) logsUserUsage {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -139,6 +142,9 @@ func newLogsUserUsage(db *gorm.DB, opts ...gen.DOOption) logsUserUsage {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -147,8 +153,16 @@ func newLogsUserUsage(db *gorm.DB, opts ...gen.DOOption) logsUserUsage {
|
||||
RelationField: field.NewRelation("Resource.Short.Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Resource.Short.Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Resource.Short.Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -391,6 +405,9 @@ type logsUserUsageBelongsToResource struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -36,6 +36,29 @@ func newProduct(db *gorm.DB, opts ...gen.DOOption) product {
|
||||
_product.Description = field.NewString(tableName, "description")
|
||||
_product.Sort = field.NewInt32(tableName, "sort")
|
||||
_product.Status = field.NewInt(tableName, "status")
|
||||
_product.Skus = productHasManySkus{
|
||||
db: db.Session(&gorm.Session{}),
|
||||
|
||||
RelationField: field.NewRelation("Skus", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Skus.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Skus.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Skus.Discount", "models.ProductDiscount"),
|
||||
},
|
||||
}
|
||||
|
||||
_product.fillFieldMap()
|
||||
|
||||
@@ -55,6 +78,7 @@ type product struct {
|
||||
Description field.String
|
||||
Sort field.Int32
|
||||
Status field.Int
|
||||
Skus productHasManySkus
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
@@ -96,7 +120,7 @@ func (p *product) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
}
|
||||
|
||||
func (p *product) fillFieldMap() {
|
||||
p.fieldMap = make(map[string]field.Expr, 9)
|
||||
p.fieldMap = make(map[string]field.Expr, 10)
|
||||
p.fieldMap["id"] = p.ID
|
||||
p.fieldMap["created_at"] = p.CreatedAt
|
||||
p.fieldMap["updated_at"] = p.UpdatedAt
|
||||
@@ -106,18 +130,113 @@ func (p *product) fillFieldMap() {
|
||||
p.fieldMap["description"] = p.Description
|
||||
p.fieldMap["sort"] = p.Sort
|
||||
p.fieldMap["status"] = p.Status
|
||||
|
||||
}
|
||||
|
||||
func (p product) clone(db *gorm.DB) product {
|
||||
p.productDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
p.Skus.db = db.Session(&gorm.Session{Initialized: true})
|
||||
p.Skus.db.Statement.ConnPool = db.Statement.ConnPool
|
||||
return p
|
||||
}
|
||||
|
||||
func (p product) replaceDB(db *gorm.DB) product {
|
||||
p.productDo.ReplaceDB(db)
|
||||
p.Skus.db = db.Session(&gorm.Session{})
|
||||
return p
|
||||
}
|
||||
|
||||
type productHasManySkus struct {
|
||||
db *gorm.DB
|
||||
|
||||
field.RelationField
|
||||
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
|
||||
func (a productHasManySkus) Where(conds ...field.Expr) *productHasManySkus {
|
||||
if len(conds) == 0 {
|
||||
return &a
|
||||
}
|
||||
|
||||
exprs := make([]clause.Expression, 0, len(conds))
|
||||
for _, cond := range conds {
|
||||
exprs = append(exprs, cond.BeCond().(clause.Expression))
|
||||
}
|
||||
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a productHasManySkus) WithContext(ctx context.Context) *productHasManySkus {
|
||||
a.db = a.db.WithContext(ctx)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a productHasManySkus) Session(session *gorm.Session) *productHasManySkus {
|
||||
a.db = a.db.Session(session)
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a productHasManySkus) Model(m *models.Product) *productHasManySkusTx {
|
||||
return &productHasManySkusTx{a.db.Model(m).Association(a.Name())}
|
||||
}
|
||||
|
||||
func (a productHasManySkus) Unscoped() *productHasManySkus {
|
||||
a.db = a.db.Unscoped()
|
||||
return &a
|
||||
}
|
||||
|
||||
type productHasManySkusTx struct{ tx *gorm.Association }
|
||||
|
||||
func (a productHasManySkusTx) Find() (result []*models.ProductSku, err error) {
|
||||
return result, a.tx.Find(&result)
|
||||
}
|
||||
|
||||
func (a productHasManySkusTx) Append(values ...*models.ProductSku) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Append(targetValues...)
|
||||
}
|
||||
|
||||
func (a productHasManySkusTx) Replace(values ...*models.ProductSku) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Replace(targetValues...)
|
||||
}
|
||||
|
||||
func (a productHasManySkusTx) Delete(values ...*models.ProductSku) (err error) {
|
||||
targetValues := make([]interface{}, len(values))
|
||||
for i, v := range values {
|
||||
targetValues[i] = v
|
||||
}
|
||||
return a.tx.Delete(targetValues...)
|
||||
}
|
||||
|
||||
func (a productHasManySkusTx) Clear() error {
|
||||
return a.tx.Clear()
|
||||
}
|
||||
|
||||
func (a productHasManySkusTx) Count() int64 {
|
||||
return a.tx.Count()
|
||||
}
|
||||
|
||||
func (a productHasManySkusTx) Unscoped() *productHasManySkusTx {
|
||||
a.tx = a.tx.Unscoped()
|
||||
return &a
|
||||
}
|
||||
|
||||
type productDo struct{ gen.DO }
|
||||
|
||||
func (p productDo) Debug() *productDo {
|
||||
|
||||
@@ -38,10 +38,32 @@ func newProductSku(db *gorm.DB, opts ...gen.DOOption) productSku {
|
||||
_productSku.Price = field.NewField(tableName, "price")
|
||||
_productSku.PriceMin = field.NewField(tableName, "price_min")
|
||||
_productSku.Status = field.NewInt32(tableName, "status")
|
||||
_productSku.Sort = field.NewInt32(tableName, "sort")
|
||||
_productSku.Product = productSkuBelongsToProduct{
|
||||
db: db.Session(&gorm.Session{}),
|
||||
|
||||
RelationField: field.NewRelation("Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Product.Skus", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Product.Skus.Product", "models.Product"),
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Product.Skus.Discount", "models.ProductDiscount"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_productSku.Discount = productSkuBelongsToDiscount{
|
||||
@@ -70,6 +92,7 @@ type productSku struct {
|
||||
Price field.Field
|
||||
PriceMin field.Field
|
||||
Status field.Int32
|
||||
Sort field.Int32
|
||||
Product productSkuBelongsToProduct
|
||||
|
||||
Discount productSkuBelongsToDiscount
|
||||
@@ -100,6 +123,7 @@ func (p *productSku) updateTableName(table string) *productSku {
|
||||
p.Price = field.NewField(table, "price")
|
||||
p.PriceMin = field.NewField(table, "price_min")
|
||||
p.Status = field.NewInt32(table, "status")
|
||||
p.Sort = field.NewInt32(table, "sort")
|
||||
|
||||
p.fillFieldMap()
|
||||
|
||||
@@ -116,7 +140,7 @@ func (p *productSku) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
}
|
||||
|
||||
func (p *productSku) fillFieldMap() {
|
||||
p.fieldMap = make(map[string]field.Expr, 13)
|
||||
p.fieldMap = make(map[string]field.Expr, 14)
|
||||
p.fieldMap["id"] = p.ID
|
||||
p.fieldMap["created_at"] = p.CreatedAt
|
||||
p.fieldMap["updated_at"] = p.UpdatedAt
|
||||
@@ -128,6 +152,7 @@ func (p *productSku) fillFieldMap() {
|
||||
p.fieldMap["price"] = p.Price
|
||||
p.fieldMap["price_min"] = p.PriceMin
|
||||
p.fieldMap["status"] = p.Status
|
||||
p.fieldMap["sort"] = p.Sort
|
||||
|
||||
}
|
||||
|
||||
@@ -151,6 +176,16 @@ type productSkuBelongsToProduct struct {
|
||||
db *gorm.DB
|
||||
|
||||
field.RelationField
|
||||
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a productSkuBelongsToProduct) Where(conds ...field.Expr) *productSkuBelongsToProduct {
|
||||
|
||||
@@ -115,8 +115,16 @@ func newProductSkuUser(db *gorm.DB, opts ...gen.DOOption) productSkuUser {
|
||||
RelationField: field.NewRelation("ProductSku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("ProductSku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("ProductSku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -331,6 +339,9 @@ type productSkuUserBelongsToProductSku struct {
|
||||
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -153,6 +153,9 @@ func newProxy(db *gorm.DB, opts ...gen.DOOption) proxy {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -181,6 +184,9 @@ func newProxy(db *gorm.DB, opts ...gen.DOOption) proxy {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -192,6 +198,9 @@ func newProxy(db *gorm.DB, opts ...gen.DOOption) proxy {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -200,8 +209,16 @@ func newProxy(db *gorm.DB, opts ...gen.DOOption) proxy {
|
||||
RelationField: field.NewRelation("Channels.Resource.Short.Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Channels.Resource.Short.Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Channels.Resource.Short.Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -387,6 +404,9 @@ type proxyHasManyChannels struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -44,6 +44,9 @@ func newResource(db *gorm.DB, opts ...gen.DOOption) resource {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
@@ -52,8 +55,16 @@ func newResource(db *gorm.DB, opts ...gen.DOOption) resource {
|
||||
RelationField: field.NewRelation("Short.Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Short.Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Short.Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -266,6 +277,9 @@ type resourceHasOneShort struct {
|
||||
field.RelationField
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -43,8 +43,16 @@ func newResourceLong(db *gorm.DB, opts ...gen.DOOption) resourceLong {
|
||||
RelationField: field.NewRelation("Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -149,6 +157,9 @@ type resourceLongHasOneSku struct {
|
||||
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -43,8 +43,16 @@ func newResourceShort(db *gorm.DB, opts ...gen.DOOption) resourceShort {
|
||||
RelationField: field.NewRelation("Sku", "models.ProductSku"),
|
||||
Product: struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}{
|
||||
RelationField: field.NewRelation("Sku.Product", "models.Product"),
|
||||
Skus: struct {
|
||||
field.RelationField
|
||||
}{
|
||||
RelationField: field.NewRelation("Sku.Product.Skus", "models.ProductSku"),
|
||||
},
|
||||
},
|
||||
Discount: struct {
|
||||
field.RelationField
|
||||
@@ -149,6 +157,9 @@ type resourceShortHasOneSku struct {
|
||||
|
||||
Product struct {
|
||||
field.RelationField
|
||||
Skus struct {
|
||||
field.RelationField
|
||||
}
|
||||
}
|
||||
Discount struct {
|
||||
field.RelationField
|
||||
|
||||
@@ -109,6 +109,14 @@ func userRouter(api fiber.Router) {
|
||||
// 前台
|
||||
inquiry := api.Group("/inquiry")
|
||||
inquiry.Post("/create", handlers.CreateInquiry)
|
||||
|
||||
// 产品
|
||||
product := api.Group("/product")
|
||||
product.Post("/list", handlers.AllProduct)
|
||||
|
||||
// 认证
|
||||
verify := api.Group("/verify")
|
||||
verify.Post("/sms/password", handlers.SendSmsCodeForPassword)
|
||||
}
|
||||
|
||||
// 客户端接口路由
|
||||
@@ -116,7 +124,7 @@ func clientRouter(api fiber.Router) {
|
||||
client := api
|
||||
|
||||
// 验证短信令牌
|
||||
client.Post("/verify/sms", handlers.SmsCode)
|
||||
client.Post("/verify/sms", handlers.SendSmsCode)
|
||||
|
||||
// 套餐定价查询
|
||||
resource := client.Group("/resource")
|
||||
|
||||
@@ -16,7 +16,7 @@ func (s *billService) CreateForBalance(q *q.Query, uid, tradeId int32, detail *T
|
||||
TradeID: &tradeId,
|
||||
Type: m.BillTypeRecharge,
|
||||
Info: &detail.Subject,
|
||||
Amount: detail.Amount,
|
||||
Amount: detail.Discounted,
|
||||
Actual: detail.Actual,
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func (s *billService) CreateForResource(q *q.Query, uid, resourceId int32, trade
|
||||
CouponUserID: detail.CouponUserId,
|
||||
Type: m.BillTypeConsume,
|
||||
Info: &detail.Subject,
|
||||
Amount: detail.Amount,
|
||||
Amount: detail.Discounted,
|
||||
Actual: detail.Actual,
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ func findResource(resourceId int32, now time.Time) (*ResourceView, error) {
|
||||
var sub = resource.Short
|
||||
info.ShortId = &sub.ID
|
||||
info.ExpireAt = sub.ExpireAt
|
||||
info.Live = time.Duration(sub.Live) * time.Second
|
||||
info.Live = time.Duration(sub.Live) * time.Minute
|
||||
info.Mode = sub.Type
|
||||
info.Quota = sub.Quota
|
||||
info.Used = sub.Used
|
||||
|
||||
@@ -20,6 +20,61 @@ func (s *productService) AllProducts() ([]*m.Product, error) {
|
||||
Find()
|
||||
}
|
||||
|
||||
func (s *productService) AllProductSaleInfos() ([]*m.Product, error) {
|
||||
products, err := q.Product.
|
||||
Select(
|
||||
q.Product.ID,
|
||||
q.Product.Code,
|
||||
q.Product.Name,
|
||||
q.Product.Description,
|
||||
q.Product.Sort,
|
||||
).
|
||||
Where(
|
||||
q.Product.Status.Eq(int(m.ProductStatusEnabled)),
|
||||
).
|
||||
Order(q.Product.Sort).
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pids := make([]int32, len(products))
|
||||
for i, p := range products {
|
||||
pids[i] = p.ID
|
||||
}
|
||||
|
||||
skus, err := q.ProductSku.
|
||||
Select(
|
||||
q.ProductSku.ID,
|
||||
q.ProductSku.ProductID,
|
||||
q.ProductSku.Name,
|
||||
q.ProductSku.Code,
|
||||
q.ProductSku.Price,
|
||||
).
|
||||
Where(
|
||||
q.ProductSku.ProductID.In(pids...),
|
||||
q.ProductSku.Status.Eq(int32(m.SkuStatusEnabled)),
|
||||
).
|
||||
Order(q.ProductSku.Sort).
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pmap := make(map[int32]*m.Product, len(products))
|
||||
for _, p := range products {
|
||||
pmap[p.ID] = p
|
||||
p.Skus = make([]*m.ProductSku, 0)
|
||||
}
|
||||
for _, s := range skus {
|
||||
if p, ok := pmap[s.ProductID]; ok {
|
||||
p.Skus = append(p.Skus, s)
|
||||
}
|
||||
}
|
||||
|
||||
return products, nil
|
||||
}
|
||||
|
||||
// 新增产品
|
||||
func (s *productService) CreateProduct(create *CreateProductData) error {
|
||||
return q.Product.Create(&m.Product{
|
||||
|
||||
@@ -20,7 +20,7 @@ func (s *productSkuService) All(product_code string) (result []*m.ProductSku, er
|
||||
Joins(q.ProductSku.Product).
|
||||
Where(q.Product.As("Product").Code.Eq(product_code)).
|
||||
Select(q.ProductSku.ALL).
|
||||
Order(q.ProductSku.CreatedAt.Desc()).
|
||||
Order(q.ProductSku.Sort).
|
||||
Find()
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (s *productSkuService) Page(req *core.PageReq, productId *int32) (result []
|
||||
return q.ProductSku.
|
||||
Joins(q.ProductSku.Discount, q.ProductSku.Product).
|
||||
Where(do...).
|
||||
Order(q.ProductSku.ID).
|
||||
Order(q.ProductSku.Sort).
|
||||
FindByPage(req.GetOffset(), req.GetLimit())
|
||||
}
|
||||
|
||||
|
||||
@@ -144,35 +144,35 @@ type UpdateResourceData struct {
|
||||
Active *bool `json:"active"`
|
||||
}
|
||||
|
||||
func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, cuid *int32) (*m.ProductSku, *m.ProductDiscount, *m.CouponUser, decimal.Decimal, decimal.Decimal, error) {
|
||||
func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, cuid *int32) (*m.ProductSku, *m.ProductDiscount, *m.CouponUser, decimal.Decimal, decimal.Decimal, decimal.Decimal, error) {
|
||||
|
||||
sku, err := q.ProductSku.
|
||||
Joins(q.ProductSku.Discount).
|
||||
Where(q.ProductSku.Code.Eq(skuCode), q.ProductSku.Status.Eq(int32(m.SkuStatusEnabled))).
|
||||
Take()
|
||||
if err != nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, core.NewServErr("产品不可用", err)
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr(fmt.Sprintf("产品不可用 %s", skuCode), err)
|
||||
}
|
||||
|
||||
// 原价
|
||||
price := sku.Price
|
||||
amount := price.Mul(decimal.NewFromInt32(count))
|
||||
amountMin := sku.PriceMin.Mul(decimal.NewFromInt32(count))
|
||||
amount := sku.Price.Mul(decimal.NewFromInt32(count))
|
||||
|
||||
// 折扣价
|
||||
discount := sku.Discount
|
||||
if discount == nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, core.NewServErr("价格查询失败", err)
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr("价格查询失败", err)
|
||||
}
|
||||
|
||||
discountRate := discount.Rate()
|
||||
if user != nil && user.DiscountID != nil { // 用户特殊优惠
|
||||
uDiscount, err := q.ProductDiscount.Where(q.ProductDiscount.ID.Eq(*user.DiscountID)).Take()
|
||||
if err != nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, core.NewServErr("客户特殊价查询失败", err)
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr("客户特殊价查询失败", err)
|
||||
}
|
||||
|
||||
uDiscountRate := uDiscount.Rate()
|
||||
if uDiscountRate.Cmp(discountRate) > 0 {
|
||||
if uDiscountRate.Cmp(discountRate) < 0 {
|
||||
discountRate = uDiscountRate
|
||||
discount = uDiscount
|
||||
}
|
||||
@@ -186,20 +186,20 @@ func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, c
|
||||
var err error
|
||||
coupon, err = Coupon.GetUserCoupon(user.ID, *cuid, discounted)
|
||||
if err != nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, err
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, err
|
||||
}
|
||||
couponApplied = discounted.Sub(coupon.Coupon.Amount)
|
||||
}
|
||||
|
||||
// 约束到最低价格
|
||||
if discounted.Cmp(sku.PriceMin) < 0 {
|
||||
discounted = sku.PriceMin.Copy()
|
||||
if discounted.Cmp(amountMin) < 0 {
|
||||
discounted = amountMin.Copy()
|
||||
}
|
||||
if couponApplied.Cmp(sku.PriceMin) < 0 {
|
||||
couponApplied = sku.PriceMin.Copy()
|
||||
if couponApplied.Cmp(amountMin) < 0 {
|
||||
couponApplied = amountMin.Copy()
|
||||
}
|
||||
|
||||
return sku, discount, coupon, discounted, couponApplied, nil
|
||||
return sku, discount, coupon, amount, discounted, couponApplied, nil
|
||||
}
|
||||
|
||||
type CreateResourceData struct {
|
||||
@@ -260,7 +260,7 @@ func (data *CreateResourceData) Code() string {
|
||||
}
|
||||
|
||||
func (data *CreateResourceData) TradeDetail(user *m.User) (*TradeDetail, error) {
|
||||
sku, discount, coupon, amount, actual, err := Resource.CalcPrice(data.Code(), data.Count(), user, data.CouponId)
|
||||
sku, discount, coupon, amount, discounted, actual, err := Resource.CalcPrice(data.Code(), data.Count(), user, data.CouponId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -277,7 +277,7 @@ func (data *CreateResourceData) TradeDetail(user *m.User) (*TradeDetail, error)
|
||||
data,
|
||||
m.TradeTypePurchase,
|
||||
sku.Name,
|
||||
amount, actual,
|
||||
amount, discounted, actual,
|
||||
discountId, couponUserId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -619,6 +619,7 @@ type TradeDetail struct {
|
||||
Type m.TradeType `json:"type"`
|
||||
Subject string `json:"subject"`
|
||||
Amount decimal.Decimal `json:"amount"`
|
||||
Discounted decimal.Decimal `json:"discounted"`
|
||||
Actual decimal.Decimal `json:"actual"`
|
||||
DiscountId *int32 `json:"discount_id,omitempty"`
|
||||
CouponUserId *int32 `json:"coupon_id,omitempty"`
|
||||
|
||||
@@ -93,7 +93,7 @@ func (data *UpdateBalanceData) TradeDetail(user *m.User) (*TradeDetail, error) {
|
||||
data,
|
||||
m.TradeTypeRecharge,
|
||||
fmt.Sprintf("账户充值 - %s元", amount.StringFixed(2)),
|
||||
amount, amount,
|
||||
amount, amount, amount,
|
||||
nil, nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ func (s *verifierService) SendSms(ctx context.Context, phone string, purpose Ver
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *verifierService) VerifySms(ctx context.Context, phone, code string) error {
|
||||
key := smsKey(phone, VerifierSmsPurposeLogin)
|
||||
func (s *verifierService) VerifySms(ctx context.Context, phone, code string, purpose VerifierSmsPurpose) error {
|
||||
key := smsKey(phone, purpose)
|
||||
keyLock := key + ":lock"
|
||||
|
||||
err := g.Redis.Watch(ctx, func(tx *redis.Tx) error {
|
||||
@@ -146,7 +146,8 @@ func smsKey(phone string, purpose VerifierSmsPurpose) string {
|
||||
type VerifierSmsPurpose int
|
||||
|
||||
const (
|
||||
VerifierSmsPurposeLogin VerifierSmsPurpose = iota // 登录
|
||||
VerifierSmsPurposeLogin VerifierSmsPurpose = iota // 登录
|
||||
VerifierSmsPurposePassword // 修改密码
|
||||
)
|
||||
|
||||
// region 服务异常
|
||||
|
||||
Reference in New Issue
Block a user