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:
1 parent
9d7e220f14
commit
04bac15e59
30 files changed
+811
-4
No files matched your search
@@ -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);
|
||||
@@ -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 '后台子账号表';
|
||||
Reference in new issue
Block a user