Snapshot friend_back worktree for local merge

Source HEAD: 9d7e220f14
Includes uncommitted project changes and new project files.
Align shared text line endings and executable flags with Friendship-and-chat-api.
Normalize new text to LF; exclude .workbuddy local assistant memory.
Original friend_back checkout is unchanged.
This commit is contained in:
Codex committed 2026-10-29 16:30:16 +08:00
1 parent 9d7e220f14
commit 04bac15e59
30 files changed
+811 -4

No files matched your search

+137
View File
@@ -0,0 +1,137 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""骑遇骑行记录:建表 + 模拟数据(chat_v1 库)。可重复执行(幂等:表已存在跳过,模拟数据按标题去重)。"""
import json
import math
import pymysql
DB = dict(host='139.224.25.207', port=3306, user='chat_v1',
password='BpJ2Ebt4zMPjBcCL', database='chat_v1', charset='utf8mb4',
connect_timeout=15)
DDL = [
"""
CREATE TABLE IF NOT EXISTS `member_ride_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`user_id` bigint(20) NOT NULL COMMENT '骑手编号 member_user.id',
`title` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '战报标题',
`road_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '路线名(如:南昆山)',
`corner_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '弯道名(如:观音潭右弯),空表示非跑山记录',
`distance_km` decimal(8,1) NOT NULL COMMENT '里程(公里)',
`duration_sec` int(11) NOT NULL COMMENT '骑行时长(秒)',
`top_speed_kmh` decimal(5,1) NOT NULL COMMENT '极速(km/h)',
`curve_count` int(11) NOT NULL DEFAULT '0' COMMENT '过弯次数',
`max_lean` decimal(4,1) NOT NULL COMMENT '最大压弯角度(度)',
`track_json` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '轨迹点 JSON [{lat,lng,speed}],仅详情接口返回',
`like_count` int(11) NOT NULL DEFAULT '0' COMMENT '点赞数(冗余计数)',
`report_count` int(11) NOT NULL DEFAULT '0' COMMENT '被举报次数',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0 正常 1 已下架',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '租户编号',
`creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`),
KEY `idx_user` (`user_id`),
KEY `idx_rank` (`road_name`, `corner_name`, `max_lean`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='骑遇骑行记录(战报)'
""",
"""
CREATE TABLE IF NOT EXISTS `member_ride_record_like` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`record_id` bigint(20) NOT NULL COMMENT '战报编号 member_ride_record.id',
`user_id` bigint(20) NOT NULL COMMENT '点赞人编号 member_user.id',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '租户编号',
`creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_record_user` (`record_id`, `user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='骑遇骑行战报点赞'
""",
]
# (user_id, title, road, corner, km, sec, top, curves, max_lean, days_ago, like_user_ids)
MOCK = [
(131, '南昆山 63 连弯,今天左弯终于不虚了', '南昆山', '观音潭右弯', 87, 5760, 138, 63, 52.0, 1, [133, 132, 134]),
(133, '清晨跑山,观音潭右弯刷出个人最佳', '南昆山', '观音潭右弯', 84, 5400, 132, 58, 49.5, 2, [131, 129]),
(129, '压弯一时爽,一直压弯一直爽', '南昆山', '观音潭右弯', 86, 5900, 129, 61, 46.0, 4, [131]),
(132, '第一次跑南昆山,右弯还是不敢深压', '南昆山', '观音潭右弯', 88, 6300, 112, 57, 33.5, 5, [134]),
(131, '连续 S 弯练车,大腿已废', '南昆山', '连续 S 弯', 52, 3900, 118, 41, 44.5, 1, [133, 129]),
(133, 'S 弯 41 连过,人车合一', '南昆山', '连续 S 弯', 52, 3950, 112, 41, 40.0, 3, [131, 134, 132]),
(129, '大夫山夜骑放风,发卡弯有点意思', '大夫山', '发卡弯', 44, 3660, 105, 38, 43.0, 1, [131, 133]),
(131, '大夫山发卡弯,极速压到 43 度', '大夫山', '发卡弯', 43, 3500, 108, 35, 43.2, 3, [133]),
(134, '傍晚放风,夕阳配弯道,舒服', '大夫山', '发卡弯', 44, 3800, 98, 36, 29.0, 4, [132]),
(131, '罗浮山风门坳长弯,全程 6 档', '罗浮山', '风门坳长弯', 121, 7680, 121, 22, 39.0, 2, [133, 129]),
(133, '风门坳长弯磨膝体验,就一次', '罗浮山', '风门坳长弯', 118, 7500, 126, 20, 47.5, 6, [131]),
(129, '周末摩旅,156 公里赶到营地', '', '', 156, 7680, 121, 22, 25.0, 3, [131, 133, 132, 134]),
(133, '市区通勤顺路兜风,绿道休闲骑', '', '', 32, 3000, 85, 12, 18.5, 1, [131]),
(132, '新手第一份战报,求带飞', '', '', 26, 2700, 76, 9, 15.0, 2, [134]),
]
def track_points(seed: int) -> str:
"""生成一个小环形轨迹 JSON(约 60 点),让战报详情有图可画。"""
r = 0.004 + (seed % 7) * 0.0004
pts = []
n = 60
for i in range(n):
t = i / n * math.pi * 4
radius = r + r * 0.35 * math.sin(t * 2.3 + seed)
lat = 23.17 + seed * 0.002 + radius * math.cos(t)
lng = 113.36 + seed * 0.003 + radius * 1.4 * math.sin(t)
speed = round(40 + 60 * (0.5 + 0.5 * math.sin(t * 1.7 + seed)), 1)
pts.append({'lat': round(lat, 6), 'lng': round(lng, 6), 'speed': speed})
return json.dumps(pts, separators=(',', ':'))
def main():
conn = pymysql.connect(**DB)
cur = conn.cursor()
for ddl in DDL:
cur.execute(ddl)
conn.commit()
print('DDL ok')
inserted = 0
for idx, (uid, title, road, corner, km, sec, top, curves, lean, days_ago, likers) in enumerate(MOCK):
cur.execute("SELECT id FROM member_ride_record WHERE title=%s AND deleted=0", (title,))
if cur.fetchone():
print('skip (exists):', title)
continue
cur.execute(
"""INSERT INTO member_ride_record
(user_id, title, road_name, corner_name, distance_km, duration_sec,
top_speed_kmh, curve_count, max_lean, track_json, like_count, report_count,
status, tenant_id, creator, create_time)
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,0,0,1,%s,
DATE_SUB(NOW(), INTERVAL %s DAY) - INTERVAL %s HOUR)""",
(uid, title, road, corner, km, sec, top, curves, lean,
track_points(idx), len(likers), uid, days_ago, (idx * 3) % 20))
record_id = cur.lastrowid
for liker in likers:
cur.execute(
"""INSERT IGNORE INTO member_ride_record_like
(record_id, user_id, tenant_id, creator, create_time)
VALUES (%s,%s,1,%s, DATE_SUB(NOW(), INTERVAL 1 DAY))""",
(record_id, liker, uid))
inserted += 1
print('inserted:', title)
conn.commit()
cur.execute("SELECT COUNT(*) FROM member_ride_record WHERE deleted=0")
print('total records:', cur.fetchone()[0])
cur.execute("SELECT road_name, corner_name, COUNT(*) FROM member_ride_record "
"WHERE deleted=0 AND corner_name<>'' GROUP BY road_name, corner_name")
for r in cur.fetchall():
print('board:', r)
conn.close()
print('done, inserted =', inserted)
if __name__ == '__main__':
main()
@@ -0,0 +1,17 @@
-- 后台菜单与授权:子账号管理 + 会员管理拆分(男号/女号)
-- 执行库:chat_v1
-- 1) 新增菜单(幂等:先删后插)
DELETE FROM system_menu WHERE id IN (5810, 5820, 5821);
INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, updater, deleted)
VALUES
(5810, '子账号管理', 'system:sub-account:manage', 2, 20, 0, '/sub-account', 'ep:user', 'system/subaccount/index', 'SystemSubAccount', 0, b'1', b'1', b'1', '1', '1', b'0'),
(5820, '男号管理', 'member:user:query', 2, 1, 2262, 'male-user', 'ep:male', 'member/user/male', 'MemberUserMale', 0, b'1', b'1', b'1', '1', '1', b'0'),
(5821, '女号管理', 'member:user:query', 2, 2, 2262, 'female-user', 'ep:female', 'member/user/female', 'MemberUserFemale', 0, b'1', b'1', b'1', '1', '1', b'0');
-- 2) 授权给「APP管理员」角色(AppHolder 当前使用的角色)
DELETE FROM system_role_menu WHERE role_id = 158 AND menu_id IN (5810, 5820, 5821);
INSERT INTO system_role_menu (role_id, menu_id, creator, updater, deleted, tenant_id)
VALUES
(158, 5810, '1', '1', b'0', 1),
(158, 5820, '1', '1', b'0', 1),
(158, 5821, '1', '1', b'0', 1);
+17
View File
@@ -0,0 +1,17 @@
-- 子账号管理:holder 与 子账号/专属角色 的绑定关系
-- 执行位置:chat_v1 库
CREATE TABLE IF NOT EXISTS `system_sub_account` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`holder_user_id` bigint NOT NULL COMMENT '管理者用户编号(system_users.id)',
`sub_user_id` bigint NOT NULL COMMENT '子账号用户编号(system_users.id)',
`role_id` bigint NOT NULL COMMENT '子账号专属角色编号(system_role.id)',
`creator` varchar(64) NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`),
KEY `idx_holder_user_id` (`holder_user_id`),
KEY `idx_sub_user_id` (`sub_user_id`)
) ENGINE = InnoDB COMMENT '后台子账号表';