特惠标签ok
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
./scripts/dev.sh
|
./scripts/dev.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
脚本会自动启动 MySQL、Redis、MinIO,首次初始化数据库结构,刷新开发测试数据,并同时启动后端和前端。
|
脚本会自动启动 MySQL、Redis、MinIO,首次初始化数据库结构,并同时启动后端和前端。
|
||||||
|
|
||||||
前端地址:`http://localhost:5173`
|
前端地址:`http://localhost:5173`
|
||||||
|
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
docker compose -f deploy/docker-compose.dev.yml up -d
|
docker compose -f deploy/docker-compose.dev.yml up -d
|
||||||
|
|
||||||
docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < backend/migrations/000001_init.sql
|
docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < backend/migrations/000001_init.sql
|
||||||
docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < backend/seeds/dev_orders.sql
|
|
||||||
|
|
||||||
cd backend
|
cd backend
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type ListingDTO struct {
|
|||||||
PriceDaily float64 `json:"price_daily"`
|
PriceDaily float64 `json:"price_daily"`
|
||||||
PriceWeekly float64 `json:"price_weekly"`
|
PriceWeekly float64 `json:"price_weekly"`
|
||||||
DepositAmount float64 `json:"deposit_amount"`
|
DepositAmount float64 `json:"deposit_amount"`
|
||||||
|
IsAccelerated bool `json:"is_accelerated_sale"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
ReviewStatus string `json:"review_status"`
|
ReviewStatus string `json:"review_status"`
|
||||||
ReviewReason string `json:"review_reason"`
|
ReviewReason string `json:"review_reason"`
|
||||||
|
|||||||
@@ -521,6 +521,7 @@ func (row listingRow) toDTO() ListingDTO {
|
|||||||
PriceDaily: row.PriceDaily,
|
PriceDaily: row.PriceDaily,
|
||||||
PriceWeekly: row.PriceWeekly,
|
PriceWeekly: row.PriceWeekly,
|
||||||
DepositAmount: row.DepositAmount,
|
DepositAmount: row.DepositAmount,
|
||||||
|
IsAccelerated: isAcceleratedSale(assetSummary),
|
||||||
Status: row.Status,
|
Status: row.Status,
|
||||||
ReviewStatus: row.ReviewStatus,
|
ReviewStatus: row.ReviewStatus,
|
||||||
ReviewReason: row.ReviewReason,
|
ReviewReason: row.ReviewReason,
|
||||||
@@ -551,6 +552,7 @@ func toDTO(account model.GameAccount, listing model.RentalListing) *ListingDTO {
|
|||||||
PriceDaily: listing.PriceDaily,
|
PriceDaily: listing.PriceDaily,
|
||||||
PriceWeekly: listing.PriceWeekly,
|
PriceWeekly: listing.PriceWeekly,
|
||||||
DepositAmount: listing.DepositAmount,
|
DepositAmount: listing.DepositAmount,
|
||||||
|
IsAccelerated: isAcceleratedSale(assetSummary),
|
||||||
Status: listing.Status,
|
Status: listing.Status,
|
||||||
ReviewStatus: listing.ReviewStatus,
|
ReviewStatus: listing.ReviewStatus,
|
||||||
ReviewReason: listing.ReviewReason,
|
ReviewReason: listing.ReviewReason,
|
||||||
@@ -605,6 +607,50 @@ func decodeAssetSummary(raw datatypes.JSON) map[string]any {
|
|||||||
return summary
|
return summary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isAcceleratedSale(summary map[string]any) bool {
|
||||||
|
if summary == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
breakdown, ok := summary["price_breakdown"].(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
referenceRatio := readSummaryNumber(breakdown["seller_reference_ratio"])
|
||||||
|
sellerRatio := readSummaryNumber(breakdown["seller_ratio"])
|
||||||
|
acceleratedRatio := readSummaryNumber(breakdown["accelerated_sale_ratio"])
|
||||||
|
if referenceRatio <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return sellerRatio > referenceRatio || acceleratedRatio > referenceRatio
|
||||||
|
}
|
||||||
|
|
||||||
|
func readSummaryNumber(value any) float64 {
|
||||||
|
switch typed := value.(type) {
|
||||||
|
case float64:
|
||||||
|
return typed
|
||||||
|
case float32:
|
||||||
|
return float64(typed)
|
||||||
|
case int:
|
||||||
|
return float64(typed)
|
||||||
|
case int64:
|
||||||
|
return float64(typed)
|
||||||
|
case json.Number:
|
||||||
|
number, err := typed.Float64()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return number
|
||||||
|
case string:
|
||||||
|
number, err := strconv.ParseFloat(strings.TrimSpace(typed), 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return number
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func cleanScreenshotURLs(urls []string) []string {
|
func cleanScreenshotURLs(urls []string) []string {
|
||||||
cleaned := make([]string, 0, len(urls))
|
cleaned := make([]string, 0, len(urls))
|
||||||
seen := make(map[string]struct{}, len(urls))
|
seen := make(map[string]struct{}, len(urls))
|
||||||
|
|||||||
@@ -1,392 +0,0 @@
|
|||||||
-- 开发环境测试数据:清空旧业务数据并生成带测试图片的已发布账号。
|
|
||||||
-- 用法:
|
|
||||||
-- mysql -uhfb -psecret hfb_sys < backend/seeds/dev_orders.sql
|
|
||||||
-- 或:
|
|
||||||
-- docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < backend/seeds/dev_orders.sql
|
|
||||||
|
|
||||||
SET NAMES utf8mb4;
|
|
||||||
|
|
||||||
SET @old_safe_updates = @@SQL_SAFE_UPDATES;
|
|
||||||
SET SQL_SAFE_UPDATES = 0;
|
|
||||||
|
|
||||||
DELETE FROM disputes;
|
|
||||||
DELETE FROM handoff_records;
|
|
||||||
DELETE FROM wallet_ledger;
|
|
||||||
DELETE FROM notifications WHERE biz_type IN ('order', 'listing', 'listing_review', 'listing_admin') OR biz_type = '';
|
|
||||||
DELETE FROM rental_orders;
|
|
||||||
DELETE FROM rental_listings;
|
|
||||||
DELETE FROM game_accounts;
|
|
||||||
|
|
||||||
DELETE FROM user_realname WHERE user_id IN (SELECT id FROM users WHERE phone IN ('13800000001', '13800000002', '13800000003', '13900000001'));
|
|
||||||
DELETE FROM wallet_accounts WHERE user_id IN (SELECT id FROM users WHERE phone IN ('13800000001', '13800000002', '13800000003', '13900000001'));
|
|
||||||
DELETE FROM users WHERE phone IN ('13800000001', '13800000002', '13800000003', '13900000001');
|
|
||||||
|
|
||||||
ALTER TABLE game_accounts AUTO_INCREMENT = 1;
|
|
||||||
ALTER TABLE rental_listings AUTO_INCREMENT = 1;
|
|
||||||
ALTER TABLE rental_orders AUTO_INCREMENT = 1;
|
|
||||||
ALTER TABLE handoff_records AUTO_INCREMENT = 1;
|
|
||||||
ALTER TABLE disputes AUTO_INCREMENT = 1;
|
|
||||||
ALTER TABLE wallet_ledger AUTO_INCREMENT = 1;
|
|
||||||
ALTER TABLE notifications AUTO_INCREMENT = 1;
|
|
||||||
|
|
||||||
SET SQL_SAFE_UPDATES = @old_safe_updates;
|
|
||||||
|
|
||||||
INSERT INTO users (phone, nickname, realname_status, risk_status, credit_score, status)
|
|
||||||
VALUES
|
|
||||||
('13800000001', '测试号主A', 'verified', 'normal', 100, 'active'),
|
|
||||||
('13800000002', '测试号主B', 'verified', 'normal', 100, 'active'),
|
|
||||||
('13800000003', '测试号主C', 'verified', 'normal', 100, 'active'),
|
|
||||||
('13900000001', '测试租客A', 'verified', 'normal', 100, 'active');
|
|
||||||
|
|
||||||
SELECT id INTO @owner_a FROM users WHERE phone = '13800000001';
|
|
||||||
SELECT id INTO @owner_b FROM users WHERE phone = '13800000002';
|
|
||||||
SELECT id INTO @owner_c FROM users WHERE phone = '13800000003';
|
|
||||||
SELECT id INTO @renter_a FROM users WHERE phone = '13900000001';
|
|
||||||
|
|
||||||
INSERT INTO user_realname (user_id, provider, provider_order_no, status, masked_name, masked_id_no, verified_at)
|
|
||||||
VALUES
|
|
||||||
(@owner_a, 'mock', 'seed-owner-a', 'verified', '测*A', '110***********0001', NOW()),
|
|
||||||
(@owner_b, 'mock', 'seed-owner-b', 'verified', '测*B', '110***********0002', NOW()),
|
|
||||||
(@owner_c, 'mock', 'seed-owner-c', 'verified', '测*C', '110***********0003', NOW()),
|
|
||||||
(@renter_a, 'mock', 'seed-renter-a', 'verified', '测*客', '110***********1001', NOW());
|
|
||||||
|
|
||||||
INSERT INTO wallet_accounts (user_id, available_balance, frozen_balance, status)
|
|
||||||
VALUES
|
|
||||||
(@owner_a, 0.00, 0.00, 'active'),
|
|
||||||
(@owner_b, 0.00, 0.00, 'active'),
|
|
||||||
(@owner_c, 0.00, 0.00, 'active'),
|
|
||||||
(@renter_a, 5000.00, 0.00, 'active');
|
|
||||||
|
|
||||||
INSERT INTO game_accounts
|
|
||||||
(owner_id, game_name, server_region, login_platform, title, description, rank_level, haf_coin_amount, asset_summary, screenshot_urls, status, created_at, updated_at)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
@owner_a, '三角洲行动', 'QQ', '扫码',
|
|
||||||
'纯币300M/6格/6体/6负/4六甲/6六头',
|
|
||||||
'扫码交接,保险 2*3,资源充足,适合高强度体验。',
|
|
||||||
'黑鹰', 300000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '是',
|
|
||||||
'total_asset_wan', 33700,
|
|
||||||
'secret_kd', 2.8,
|
|
||||||
'fire_level', 58,
|
|
||||||
'season_insurance', '2*3',
|
|
||||||
'stamina_level', '6级',
|
|
||||||
'load_level', '6级',
|
|
||||||
'common_regions', JSON_ARRAY('广东', '上海'),
|
|
||||||
'online_time', JSON_OBJECT('start', '10:00', 'end', '23:00'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 80, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 6, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'armor6', 'label', '6甲', 'quantity', 4, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'level6Ammo', 'label', '6级弹', 'quantity', 360, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('龙牙', '信条'),
|
|
||||||
'operatorGold', JSON_ARRAY(),
|
|
||||||
'operatorRed', JSON_ARRAY('凌霄成卫', '蚀金玫瑰'),
|
|
||||||
'weapon', JSON_ARRAY('M4A1棱镜攻势', 'K416命运')
|
|
||||||
),
|
|
||||||
'remark', '部分仓库材料请勿使用,下单后会再次提醒。'
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-001-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-001-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-001-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-001-security/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-001-skin/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 80 MINUTE, NOW() - INTERVAL 80 MINUTE
|
|
||||||
),
|
|
||||||
(
|
|
||||||
@owner_a, '三角洲行动', '微信', '账号密码',
|
|
||||||
'纯币120M/4格/5体/5负/2六头',
|
|
||||||
'账密登录,低押金,保险 2*2,常用登录地江苏。',
|
|
||||||
'钻石', 120000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '否',
|
|
||||||
'total_asset_wan', 13800,
|
|
||||||
'secret_kd', 1.9,
|
|
||||||
'fire_level', 46,
|
|
||||||
'season_insurance', '2*2',
|
|
||||||
'stamina_level', '5级',
|
|
||||||
'load_level', '5级',
|
|
||||||
'common_regions', JSON_ARRAY('江苏', '浙江'),
|
|
||||||
'online_time', JSON_OBJECT('start', '12:00', 'end', '24:00'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 30, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 2, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('怜悯'),
|
|
||||||
'operatorGold', JSON_ARRAY(),
|
|
||||||
'operatorRed', JSON_ARRAY('天际线'),
|
|
||||||
'weapon', JSON_ARRAY('SCAR-H电玩高手')
|
|
||||||
),
|
|
||||||
'remark', ''
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-002-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-002-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-002-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-002-security/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-002-skin/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 70 MINUTE, NOW() - INTERVAL 70 MINUTE
|
|
||||||
),
|
|
||||||
(
|
|
||||||
@owner_b, '三角洲行动', 'Steam', '扫码',
|
|
||||||
'纯币60M/2格/4体/4负/1体验卡',
|
|
||||||
'可包夜,保险 2*1,适合短租。',
|
|
||||||
'铂金', 60000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '是',
|
|
||||||
'total_asset_wan', 7200,
|
|
||||||
'secret_kd', 1.4,
|
|
||||||
'fire_level', 39,
|
|
||||||
'season_insurance', '2*1',
|
|
||||||
'stamina_level', '4级',
|
|
||||||
'load_level', '4级',
|
|
||||||
'common_regions', JSON_ARRAY('四川', '重庆'),
|
|
||||||
'online_time', JSON_OBJECT('start', '18:00', 'end', '02:00'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 12, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'gridCard9', 'label', '9格体验卡', 'quantity', 1, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('暗星'),
|
|
||||||
'operatorGold', JSON_ARRAY(),
|
|
||||||
'operatorRed', JSON_ARRAY(),
|
|
||||||
'weapon', JSON_ARRAY('Vector美杜莎')
|
|
||||||
),
|
|
||||||
'remark', ''
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-003-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-003-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-003-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-003-security/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 60 MINUTE, NOW() - INTERVAL 60 MINUTE
|
|
||||||
),
|
|
||||||
(
|
|
||||||
@owner_b, '三角洲行动', 'QQ', '账号密码',
|
|
||||||
'纯币500M/9格/7体/7负/10六头',
|
|
||||||
'账密交接,高段位,保险 3*3,皮肤资源较多。',
|
|
||||||
'三角洲巅峰', 500000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '是',
|
|
||||||
'total_asset_wan', 58600,
|
|
||||||
'secret_kd', 4.2,
|
|
||||||
'fire_level', 72,
|
|
||||||
'season_insurance', '3*3',
|
|
||||||
'stamina_level', '7级',
|
|
||||||
'load_level', '7级',
|
|
||||||
'common_regions', JSON_ARRAY('北京', '浙江'),
|
|
||||||
'online_time', JSON_OBJECT('start', '09:00', 'end', '23:30'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 120, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 10, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'armor6', 'label', '6甲', 'quantity', 8, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'level6Ammo', 'label', '6级弹', 'quantity', 800, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('坠星者', '处刑者'),
|
|
||||||
'operatorGold', JSON_ARRAY('威龙-铁面判官'),
|
|
||||||
'operatorRed', JSON_ARRAY('蚀金玫瑰'),
|
|
||||||
'weapon', JSON_ARRAY('M7棱镜攻势S2', 'KC17-造物纪元')
|
|
||||||
),
|
|
||||||
'remark', '高价值账号,需按平台流程交接。'
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-004-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-004-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-004-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-004-security/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-004-skin/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 50 MINUTE, NOW() - INTERVAL 50 MINUTE
|
|
||||||
),
|
|
||||||
(
|
|
||||||
@owner_c, '三角洲行动', '微信', '扫码',
|
|
||||||
'纯币180M/6格/6体/5负/80发AWM',
|
|
||||||
'扫码交接,资源适中,适合短期使用。',
|
|
||||||
'黑鹰', 180000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '否',
|
|
||||||
'total_asset_wan', 21600,
|
|
||||||
'secret_kd', 2.1,
|
|
||||||
'fire_level', 53,
|
|
||||||
'season_insurance', '2*3',
|
|
||||||
'stamina_level', '6级',
|
|
||||||
'load_level', '5级',
|
|
||||||
'common_regions', JSON_ARRAY('上海', '安徽'),
|
|
||||||
'online_time', JSON_OBJECT('start', '11:00', 'end', '23:00'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 80, 'mode', '赠送'),
|
|
||||||
JSON_OBJECT('key', 'redPacket45', 'label', '45格大红包', 'quantity', 6, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('影锋'),
|
|
||||||
'operatorGold', JSON_ARRAY(),
|
|
||||||
'operatorRed', JSON_ARRAY('水墨云图'),
|
|
||||||
'weapon', JSON_ARRAY('QBZ95王牌之剑', 'AUG气象感应')
|
|
||||||
),
|
|
||||||
'remark', 'AWM 子弹赠送,其他消耗品按规则扣费。'
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-005-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-005-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-005-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-005-security/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 40 MINUTE, NOW() - INTERVAL 40 MINUTE
|
|
||||||
),
|
|
||||||
(
|
|
||||||
@owner_c, '三角洲行动', 'QQ', '扫码',
|
|
||||||
'纯币90M/4格/5体/4负/3五级套',
|
|
||||||
'短租低价,保险 2*2,适合试号。',
|
|
||||||
'铂金', 90000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '是',
|
|
||||||
'total_asset_wan', 10200,
|
|
||||||
'secret_kd', 1.7,
|
|
||||||
'fire_level', 44,
|
|
||||||
'season_insurance', '2*2',
|
|
||||||
'stamina_level', '5级',
|
|
||||||
'load_level', '4级',
|
|
||||||
'common_regions', JSON_ARRAY('河南', '山东'),
|
|
||||||
'online_time', JSON_OBJECT('start', '14:00', 'end', '01:00'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'coffeeBean', 'label', '高级咖啡豆', 'quantity', 3, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 1, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('北极星'),
|
|
||||||
'operatorGold', JSON_ARRAY('蜂医-送葬人'),
|
|
||||||
'operatorRed', JSON_ARRAY(),
|
|
||||||
'weapon', JSON_ARRAY('MP7电玩高手S2')
|
|
||||||
),
|
|
||||||
'remark', ''
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-006-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-006-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-006-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-006-security/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 30 MINUTE, NOW() - INTERVAL 30 MINUTE
|
|
||||||
),
|
|
||||||
(
|
|
||||||
@owner_a, '三角洲行动', 'Steam', '账号密码',
|
|
||||||
'纯币260M/6格/6体/6负/皮肤多',
|
|
||||||
'Steam 账密,常用地北京/天津,皮肤组合较完整。',
|
|
||||||
'黑鹰', 260000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '否',
|
|
||||||
'total_asset_wan', 30100,
|
|
||||||
'secret_kd', 3.2,
|
|
||||||
'fire_level', 61,
|
|
||||||
'season_insurance', '2*3',
|
|
||||||
'stamina_level', '6级',
|
|
||||||
'load_level', '6级',
|
|
||||||
'common_regions', JSON_ARRAY('北京', '天津'),
|
|
||||||
'online_time', JSON_OBJECT('start', '09:30', 'end', '22:30'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 48, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'armor6', 'label', '6甲', 'quantity', 3, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'helmet6', 'label', '6头', 'quantity', 4, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('赤枭', '黑海'),
|
|
||||||
'operatorGold', JSON_ARRAY('威龙-壮志凌云', '蜂医-危险物质'),
|
|
||||||
'operatorRed', JSON_ARRAY(),
|
|
||||||
'weapon', JSON_ARRAY('AS Val悬赏令', 'K416命运', 'AUG气象感应')
|
|
||||||
),
|
|
||||||
'remark', ''
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-007-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-007-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-007-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-007-security/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-007-skin/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 20 MINUTE, NOW() - INTERVAL 20 MINUTE
|
|
||||||
),
|
|
||||||
(
|
|
||||||
@owner_b, '三角洲行动', '微信', '账号密码',
|
|
||||||
'纯币360M/9格/7体/6负/赠送六级弹',
|
|
||||||
'账密登录,保险 3*3,赠送部分六级弹。',
|
|
||||||
'三角洲巅峰', 360000000,
|
|
||||||
JSON_OBJECT(
|
|
||||||
'face_owner', '是',
|
|
||||||
'total_asset_wan', 42100,
|
|
||||||
'secret_kd', 3.8,
|
|
||||||
'fire_level', 68,
|
|
||||||
'season_insurance', '3*3',
|
|
||||||
'stamina_level', '7级',
|
|
||||||
'load_level', '6级',
|
|
||||||
'common_regions', JSON_ARRAY('福建', '广东'),
|
|
||||||
'online_time', JSON_OBJECT('start', '10:00', 'end', '24:00'),
|
|
||||||
'ban_record', '无封禁记录',
|
|
||||||
'resources', JSON_ARRAY(
|
|
||||||
JSON_OBJECT('key', 'level6Ammo', 'label', '6级弹', 'quantity', 520, 'mode', '赠送'),
|
|
||||||
JSON_OBJECT('key', 'awmAmmo', 'label', 'AWM子弹', 'quantity', 100, 'mode', '收费'),
|
|
||||||
JSON_OBJECT('key', 'gridCard9', 'label', '9格体验卡', 'quantity', 2, 'mode', '收费')
|
|
||||||
),
|
|
||||||
'skin_groups', JSON_OBJECT(
|
|
||||||
'melee', JSON_ARRAY('电锯惊魂', '处刑者'),
|
|
||||||
'operatorGold', JSON_ARRAY('露娜-古墓丽影联动', '红狼-电锯惊魂'),
|
|
||||||
'operatorRed', JSON_ARRAY(),
|
|
||||||
'weapon', JSON_ARRAY('M250电玩高手S2', '腾龙气象感应')
|
|
||||||
),
|
|
||||||
'remark', '六级弹赠送数量以下单截图为准。'
|
|
||||||
),
|
|
||||||
JSON_ARRAY(
|
|
||||||
'https://picsum.photos/seed/hfb-listing-008-coin/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-008-id/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-008-asset/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-008-security/960/540',
|
|
||||||
'https://picsum.photos/seed/hfb-listing-008-skin/960/540'
|
|
||||||
),
|
|
||||||
'published', NOW() - INTERVAL 10 MINUTE, NOW() - INTERVAL 10 MINUTE
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO rental_listings
|
|
||||||
(account_id, owner_id, price_hourly, price_daily, price_weekly, deposit_amount, status, review_status, published_at, created_at, updated_at)
|
|
||||||
SELECT id, owner_id, 29.76, 714.29, 5000.00, 120.00, 'published', 'approved', NOW() - INTERVAL 80 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币300M/6格/6体/6负/4六甲/6六头'
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, owner_id, 33.33, 800.00, 2400.00, 60.00, 'published', 'approved', NOW() - INTERVAL 70 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币120M/4格/5体/5负/2六头'
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, owner_id, 62.50, 1500.00, 1500.00, 80.00, 'published', 'approved', NOW() - INTERVAL 60 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币60M/2格/4体/4负/1体验卡'
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, owner_id, 42.52, 1020.41, 7142.86, 180.00, 'published', 'approved', NOW() - INTERVAL 50 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币500M/9格/7体/7负/10六头'
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, owner_id, 50.00, 1200.00, 3600.00, 100.00, 'published', 'approved', NOW() - INTERVAL 40 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币180M/6格/6体/5负/80发AWM'
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, owner_id, 31.25, 750.00, 750.00, 50.00, 'published', 'approved', NOW() - INTERVAL 30 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币90M/4格/5体/4负/3五级套'
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, owner_id, 25.79, 619.05, 4333.33, 120.00, 'published', 'approved', NOW() - INTERVAL 20 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币260M/6格/6体/6负/皮肤多'
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, owner_id, 35.71, 857.14, 6000.00, 160.00, 'published', 'approved', NOW() - INTERVAL 10 MINUTE, created_at, updated_at
|
|
||||||
FROM game_accounts WHERE title = '纯币360M/9格/7体/6负/赠送六级弹';
|
|
||||||
|
|
||||||
INSERT INTO notifications (user_id, type, title, content, biz_type, biz_id, created_at)
|
|
||||||
SELECT rental_listings.owner_id, 'listing_review', '发布审核通过', CONCAT(game_accounts.title, ' 已上架。'), 'listing', rental_listings.id, rental_listings.updated_at
|
|
||||||
FROM rental_listings
|
|
||||||
JOIN game_accounts ON game_accounts.id = rental_listings.account_id;
|
|
||||||
@@ -20,6 +20,7 @@ export interface Listing {
|
|||||||
price_daily: number
|
price_daily: number
|
||||||
price_weekly: number
|
price_weekly: number
|
||||||
deposit_amount: number
|
deposit_amount: number
|
||||||
|
is_accelerated_sale?: boolean
|
||||||
status: string
|
status: string
|
||||||
review_status: string
|
review_status: string
|
||||||
review_reason: string
|
review_reason: string
|
||||||
|
|||||||
@@ -401,10 +401,17 @@
|
|||||||
object-position: center;
|
object-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-cover em {
|
.card-cover-labels {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 7px;
|
top: 7px;
|
||||||
right: 7px;
|
right: 7px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-cover-labels em {
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ffd21e;
|
background: #ffd21e;
|
||||||
color: #1f2937;
|
color: #1f2937;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import {
|
|||||||
getResourceQuantity,
|
getResourceQuantity,
|
||||||
getServerRegion,
|
getServerRegion,
|
||||||
getSkinGroup,
|
getSkinGroup,
|
||||||
|
hasAcceleratedSaleRatio,
|
||||||
hasGiftResources,
|
hasGiftResources,
|
||||||
readAssetNumber,
|
readAssetNumber,
|
||||||
readAssetString,
|
readAssetString,
|
||||||
@@ -450,7 +451,13 @@ function uniqueOptions(values: string[]) {
|
|||||||
:alt="getListingTitle(item)"
|
:alt="getListingTitle(item)"
|
||||||
/>
|
/>
|
||||||
<span v-else>图</span>
|
<span v-else>图</span>
|
||||||
<em v-if="hasGiftResources(item)">有赠送</em>
|
<div
|
||||||
|
v-if="hasGiftResources(item) || hasAcceleratedSaleRatio(item)"
|
||||||
|
class="card-cover-labels"
|
||||||
|
>
|
||||||
|
<em v-if="hasGiftResources(item)">有赠送</em>
|
||||||
|
<em v-if="hasAcceleratedSaleRatio(item)">特惠</em>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-main">
|
<div class="card-main">
|
||||||
<div class="card-title-row">
|
<div class="card-title-row">
|
||||||
|
|||||||
@@ -122,6 +122,21 @@ export function hasGiftResources(item: Listing) {
|
|||||||
return getListingResources(item).some((resource) => resource.mode === "赠送");
|
return getListingResources(item).some((resource) => resource.mode === "赠送");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasAcceleratedSaleRatio(item: Listing) {
|
||||||
|
if (item.is_accelerated_sale) return true;
|
||||||
|
|
||||||
|
const priceBreakdown = item.asset_summary?.price_breakdown;
|
||||||
|
if (typeof priceBreakdown !== "object" || priceBreakdown === null) return false;
|
||||||
|
|
||||||
|
const row = priceBreakdown as Record<string, unknown>;
|
||||||
|
const referenceRatio = readUnknownNumber(row.seller_reference_ratio);
|
||||||
|
const sellerRatio = readUnknownNumber(row.seller_ratio);
|
||||||
|
const acceleratedRatio = readUnknownNumber(row.accelerated_sale_ratio);
|
||||||
|
|
||||||
|
if (referenceRatio <= 0) return false;
|
||||||
|
return sellerRatio > referenceRatio || acceleratedRatio > referenceRatio;
|
||||||
|
}
|
||||||
|
|
||||||
export function getSkinGroup(item: Listing, groupKey: string) {
|
export function getSkinGroup(item: Listing, groupKey: string) {
|
||||||
const skinGroups = item.asset_summary?.skin_groups;
|
const skinGroups = item.asset_summary?.skin_groups;
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import {
|
|||||||
getListingTitle,
|
getListingTitle,
|
||||||
getLoginMethod,
|
getLoginMethod,
|
||||||
getServerRegion,
|
getServerRegion,
|
||||||
|
hasAcceleratedSaleRatio,
|
||||||
hasGiftResources,
|
hasGiftResources,
|
||||||
} from "@/views/mobile/listingDisplay";
|
} from "@/views/mobile/listingDisplay";
|
||||||
|
|
||||||
@@ -322,7 +323,13 @@ function uniqueOptions(values: string[]) {
|
|||||||
:alt="getListingTitle(item)"
|
:alt="getListingTitle(item)"
|
||||||
/>
|
/>
|
||||||
<span v-else>HFB</span>
|
<span v-else>HFB</span>
|
||||||
<em v-if="hasGiftResources(item)">有赠送</em>
|
<div
|
||||||
|
v-if="hasGiftResources(item) || hasAcceleratedSaleRatio(item)"
|
||||||
|
class="desktop-cover-labels"
|
||||||
|
>
|
||||||
|
<em v-if="hasGiftResources(item)">有赠送</em>
|
||||||
|
<em v-if="hasAcceleratedSaleRatio(item)">特惠</em>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="desktop-info">
|
<div class="desktop-info">
|
||||||
<div class="desktop-title">
|
<div class="desktop-title">
|
||||||
@@ -720,10 +727,17 @@ function uniqueOptions(values: string[]) {
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desktop-cover em {
|
.desktop-cover-labels {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-cover-labels em {
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ff6a00;
|
background: #ff6a00;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ export default defineConfig({
|
|||||||
"/api": "http://127.0.0.1:8080",
|
"/api": "http://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
allowedHosts: [
|
allowedHosts: [
|
||||||
'221329.cc.cd'
|
'221329.cc.cd',
|
||||||
|
"d4aa-77-93-89-84.ngrok-free.app",
|
||||||
|
"frp-bus.com",
|
||||||
|
"www.u499731.nyat.app"
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -70,8 +70,6 @@ init_database() {
|
|||||||
log "数据库结构已存在,跳过迁移"
|
log "数据库结构已存在,跳过迁移"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "刷新开发测试数据..."
|
|
||||||
docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < "${ROOT_DIR}/backend/seeds/dev_orders.sql"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_env_file() {
|
load_env_file() {
|
||||||
|
|||||||
Reference in New Issue
Block a user