《电商平台开发标准》 一、*核心协作原则* 1、***你是AI,并且是资深的专业程序工程师,经验远超普通程序员,要以专业的工作态度联系上下文进行深度思考*** 2、不擅自输出代码,没明确要求时绝不主动提供代码,不允许画蛇添足,不做无根据的假设。 3、听从指示沟通,绝不擅自发挥或偏离核心问题,当被问 “是否正确” 等判断类问题:若正确,直接回 “正确”;若不正确,先回 “需要修改”,再简说问题和修正建议,限50字中文说明,禁止过度解释。 4、联系上下文进行分析,所有逻辑都基于开发标准和验证的结果为准。 5、必须在生成代码前回答理解的提示词含义,确保语意一致,如果不一致,禁止写代码。 6、先问后答:凡遇信息不足、存在歧义、技术方案不明确、或任何“拿不准”的情况,必须先向用户提问确认,不得擅自假设、推测或输出结论。 7、三振出局:针对同一用户请求(解决问题、完成任务、回答疑问),若连续输出相同或高度相似的答案达到3次,必须立即暂停并输出: 8、[疑似死循环] 你已连续三次给出相同解答,问题仍未解决。请提供新信息、纠正假设或明确新方向。同时我自我反问:是否遗漏前提?理解有偏差?存在更优路径? -- 在获得用户反馈或自己找到新角度前,不得继续输出原答案。 -- 双向提醒:当我发现用户可能陷入重复提问或逻辑循环时,应主动提醒;用户指出我死循环时,我须立即执行上述暂停规则。 9、你识别到的是什么?在回答前,你必须先确认我的意图。问我要做什么?在我明确前,你不要输出任何实质性答案,禁止任何默认偏好介入 二、全局开发环境 1、服务器操作系统 Ubuntu22.04,已安装宝塔,并使用“进程守护管理器”管理进程,服务器配置:双路CPU/32核/内存128GB/硬盘SSD2TB 2、PHP 8.0.26 全局路径/usr/bin/php,已安装扩展gd、zip 3、nginx 1.28.3 全局路径/usr/bin/nginx 4、MySQL 8.0.45 全局路径/usr/bin/mysql 5、Python 3.10.12 核心软链接/usr/bin/python3 -> python3.10 全局路径/usr/bin/python3 /usr/bin/python3.10 6、ffmpeg 4.4.2 全局路径/usr/bin/ffmpeg,ffprobe 4.4.2全局路径/usr/bin/ffprobe 7、Workerman 4.1.14 全局路径/usr/local/workerman,Workerman自动加载文件路径(require_once '/usr/local/workerman/Autoloader.php');websocket全局默认端口 8282,运行用户为 www,注意:**各站点独立分配端口避免冲突,仅允许使用wss://域名/wss做为连接地址** 8、GD 库适配 PHP8.0 版本,CLI 模式配置路径 /etc/php/8.0/cli/conf.d/20-gd.ini、FPM 模式配置路径 /etc/php/8.0/fpm/conf.d/20-gd.ini,扩展文件路径 /usr/lib/php/20200930/gd.so,GD 状态为已启用,GD headers Version、GD library Version 均为 2.3.3,固定配置 gd.jpeg_ignore_warning = 1,完整支持 JPEG、PNG、WebP、GIF、BMP 图片格式读写。GD 图片压缩核心逻辑统一封装为公共函数gd_image_compress(),增量写入系统公共函数库 /config/functions.php,已集成在全局复用。 9、Mosquitto 2.0.11 全局路径/usr/sbin/mosquitto,各站点设备必须独立配置端口和账号密码,严禁使用默认端口 10、TCPDF(PHP PDF 导出库),项目级依赖,仅允许使用 TCPDF 生成 PDF,禁止使用 DomPDF、mPDF 11、PHP Excel 导出库,项目级依赖,专用于 OFFICE/EXCEL 文件导出,非系统全局安装 三、MYSQL数据表(数据库名fumuqin.net) -- -------------------------------------------------------- CREATE TABLE `organization` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `name` varchar(80) NOT NULL COMMENT '机构名称', `credit_code` varchar(18) NOT NULL COMMENT '统一社会信用代码', `institution_filing_no` varchar(50) NOT NULL COMMENT '机构备案号(必填项)', `org_property` tinyint NOT NULL DEFAULT 1 COMMENT '机构性质(1=公办,2=民办,3=合作,4=公建民营,5=民办公助)', `establish_date` date DEFAULT NULL COMMENT '成立时间', `employee_count` int DEFAULT NULL COMMENT '员工数量', `is_disabled_care` tinyint NOT NULL DEFAULT 0 COMMENT '是否失能照护定点机构(0=否,1=是)', `is_special_support` tinyint NOT NULL DEFAULT 0 COMMENT '是否特困人员集中供养机构(0=否,1=是)', `medical_insurance_type` tinyint NOT NULL DEFAULT 0 COMMENT '医保类型(0=非医保定点,1=医保定点)', `service_scope` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '服务范围', `special_service` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '特色服务项目', `medical_cooperation` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '医疗合作机构', `org_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '机构地址', `org_zip_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '机构邮编', `service_province` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '服务区域(省市区县)', `floor_area` decimal(10,2) DEFAULT NULL COMMENT '占地面积(平方米)', `building_area` decimal(10,2) DEFAULT NULL COMMENT '建筑面积(平方米)', `facility_introduction` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '设施介绍', `legal_person` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '法人姓名', `legal_person_mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '法人手机号', `responsible_person` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '机构负责人', `responsible_person_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '机构负责人电话', `contact_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系电话', `organization_email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '机构邮箱', `supervisor_unit` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '主管单位', `operator_organization_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '运营机构名称', `business_license` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '运营机构统一社会信用代码', `operator_contact` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '运营机构联系人', `operator_contact_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '运营机构联系电话', `operator_introduction` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '运营机构简介', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID(关联users表id)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_operator_id` (`operator_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='服务机构信息表'; -- -------------------------------------------------------- CREATE TABLE `organization_qualification` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `org_id` bigint UNSIGNED NOT NULL COMMENT '关联机构ID(organization表的id)', `qualification_type` tinyint NOT NULL DEFAULT 1 COMMENT '资质类型(1=营业执照,2=养老机构许可证,3=卫生许可证)', `file_type` tinyint NOT NULL COMMENT '文件类型(1=jpg,2=pdf)', `file_path` varchar(512) NOT NULL COMMENT '存储路径(/upload/qualifications/{日期}/{qualification_type}_{3位序号}.jpg)', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID(关联users表id)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_org_id` (`org_id`), KEY `idx_operator_id` (`operator_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='服务机构资质文件'; -- -------------------------------------------------------- CREATE TABLE `users_roles` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `user_id` bigint UNSIGNED NOT NULL COMMENT '用户ID(关联users表id)', `role_id` bigint UNSIGNED NOT NULL COMMENT '角色ID(关联roles表id)', `assign_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '分配时间', `expire_time` timestamp NULL DEFAULT NULL COMMENT '过期时间(NULL表示永久有效)', `status` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1=启用,2=禁用)', `assign_user_id` bigint UNSIGNED DEFAULT NULL COMMENT '分配用户ID(关联users表id)', `assign_user_name` varchar(50) NOT NULL COMMENT '分配用户真实姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_user_role` (`user_id`, `role_id`), KEY `idx_user_id` (`user_id`), KEY `idx_role_id` (`role_id`), KEY `idx_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户角色关联表'; -- -------------------------------------------------------- CREATE TABLE `role_pages` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `role_id` bigint UNSIGNED NOT NULL COMMENT '角色ID(关联roles.id)', `page_id` bigint UNSIGNED NOT NULL COMMENT '页面ID(关联pages.id)', `status` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1=有效,2=无效,3=逻辑删除)', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID(关联users表id)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_role_id` (`role_id`), KEY `idx_page_id` (`page_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色页面关联表'; -- -------------------------------------------------------- CREATE TABLE `role_menu` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `role_id` bigint UNSIGNED NOT NULL COMMENT '角色ID(关联roles.id)', `menu_id` bigint UNSIGNED NOT NULL COMMENT '菜单ID(关联menu.id)', `status` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1=有效,0=无效)', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID(关联users表id)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_role_id` (`role_id`), KEY `idx_menu_id` (`menu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色菜单关联表'; -- -------------------------------------------------------- CREATE TABLE `roles` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `display_name` varchar(50) NOT NULL DEFAULT '' COMMENT '角色显示名称', `role_name` varchar(50) NOT NULL COMMENT '角色标识名', `status` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1=启用,2=禁用)', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID(关联users表id)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统角色表'; -- -------------------------------------------------------- CREATE TABLE `pages` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `page_name` varchar(100) NOT NULL COMMENT '页面中文名称', `page_path` varchar(255) NOT NULL COMMENT '页面绝对路径', `is_menu` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '是否在菜单显示(1=是,0=否)', `parent_page_id` bigint UNSIGNED DEFAULT 0 COMMENT '父页面ID(0=顶级页面)', `status` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1=启用,2=停用,3=逻辑删除)', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID(关联users表id)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_parent_page_id` (`parent_page_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统页面表'; -- -------------------------------------------------------- CREATE TABLE `menu` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `parent_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '父菜单ID(0=一级菜单)', `name` varchar(50) NOT NULL COMMENT '菜单名称', `path` varchar(255) DEFAULT NULL COMMENT '菜单链接路径(空表示目录)', `icon` varchar(50) DEFAULT NULL COMMENT '菜单图标', `sort` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序号(数字越小越靠前)', `status` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1=启用,0=禁用)', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID(关联users表id)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `group_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联分组ID(0=未分组)', PRIMARY KEY (`id`), KEY `idx_parent_id` (`parent_id`), KEY `idx_group_id` (`group_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统菜单表'; -- -------------------------------------------------------- CREATE TABLE `menu_groups` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `name` varchar(50) NOT NULL COMMENT '分组显示名称', `icon` varchar(50) DEFAULT NULL COMMENT '分组图标', `sort` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序号', `status` tinyint UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1=启用,0=禁用)', `operator_id` bigint UNSIGNED NOT NULL COMMENT '最后操作人ID', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='菜单分组表'; -- -------------------------------------------------------- CREATE TABLE `login_failure_records` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `ip_address` varchar(45) NOT NULL COMMENT '登录IP', `fail_count` int UNSIGNED NOT NULL DEFAULT 1 COMMENT '失败次数(默认1次,累计5次后封禁10分钟)', `block_until` datetime DEFAULT NULL COMMENT '封禁截止时间(NULL=未封禁)', PRIMARY KEY (`id`), UNIQUE KEY `uk_ip` (`ip_address`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='登录失败记录表'; -- -------------------------------------------------------- CREATE TABLE `login_records` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `login_name` varchar(50) NOT NULL COMMENT '登录名(关联users.login_name)', `ip_address` varchar(45) NOT NULL COMMENT '登录IP', `login_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '登录时间', PRIMARY KEY (`id`), KEY `idx_login_time` (`login_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='登录记录表'; -- -------------------------------------------------------- CREATE TABLE `users` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `login_name` varchar(50) NOT NULL COMMENT '登录名(必填)', `password` char(60) NOT NULL COMMENT '哈希加密密码(必填)', `real_name` varchar(30) NOT NULL COMMENT '真实姓名(必填)', `id_number` char(18) NOT NULL COMMENT '身份证号(必填,自动转换大写X)', `status` tinyint UNSIGNED NOT NULL DEFAULT '1' COMMENT '账号状态(0=禁用,1=启用)', `role` varchar(255) DEFAULT NULL COMMENT '角色名(关联roles.role_name)', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `operator_id` bigint UNSIGNED DEFAULT NULL COMMENT '最后操作人ID', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_login_name` (`login_name`), UNIQUE KEY `uk_id_number` (`id_number`), KEY `idx_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表'; -- -------------------------------------------------------- CREATE TABLE `users_info` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `user_info_id` bigint UNSIGNED NOT NULL COMMENT '用户信息ID(关联users.id)', `gender` tinyint UNSIGNED NOT NULL DEFAULT 0 COMMENT '性别(0=未填写,1=男性,2=女性)', `phone` char(11) DEFAULT NULL COMMENT '手机号', `email` varchar(100) DEFAULT NULL COMMENT '邮箱', `education` tinyint UNSIGNED NOT NULL DEFAULT 0 COMMENT '学历(0=未填写,1=小学, 2=初中, 3=高中, 4=中专, 5=大专, 6=本科, 7=硕士, 8=博士, 9=其他)', `address` varchar(255) DEFAULT NULL COMMENT '联系地址', `emergency_contact` varchar(30) DEFAULT NULL COMMENT '紧急联系人', `emergency_phone` char(11) DEFAULT NULL COMMENT '紧急联系电话', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `operator_id` bigint UNSIGNED DEFAULT NULL COMMENT '最后操作人ID', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_user_info_id` (`user_info_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户信息表'; -- -------------------------------------------------------- CREATE TABLE `user_certificate` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `cert_user_id` bigint UNSIGNED NOT NULL COMMENT '证书所属用户ID(关联users.id)', `certificate_name` varchar(100) NOT NULL COMMENT '证书名称', `file_path` varchar(255) NOT NULL COMMENT '存储路径(uploads/user_certificate/{user_id}/{3位序号}.jpg)', `sort` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序号', `operator_name` varchar(50) NOT NULL COMMENT '最后操作人姓名', `operator_id` bigint UNSIGNED DEFAULT NULL COMMENT '最后操作人ID', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_cert_user_id` (`cert_user_id`), KEY `idx_certificate_name` (`certificate_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户资质证书表'; -- -------------------------------------------------------- 四、系统目录树 mingshan.fumuqin.net/ # ========== 公共目录 ========== ├── config/ # 系统配置目录 │ ├── conn.php # 数据库连接配置 │ └── init.php # 环境初始化 ├── core/ # 核心公共函数库 │ ├── functions.php # 公共函数 │ └── auth.php # 统一登录验证与权限校验 ├── public/ # 公共入口 │ │ ├── css/ # 样式目录 │ │ └── images/ # 图片目录 │ │ ├── login.png # 登录页图片 │ │ └── logo.png # 系统Logo图片 │ ├── index.php # 系统首页(按端自动跳转) │ ├── permission_denied.php # 权限不足提示页 │ ├── user_register.php # 新用户注册 │ ├── forgot_password.php # 忘记密码(验证取回密码) │ ├── login.php # 统一登录页(PC/移动端自适应) │ └── logout.php # 退出登录 ├── webfonts/ # 系统网页字体目录 ├── vendor/ # 第三方扩展库(PhpSpreadsheet、TCPDF等) │ ├── tcpdf/ # TCPDF完整目录 │ │ └── tcpdf.php # TCPDF引用页 │ └── autoload.php # PhpSpreadsheet引用页 ├── css/ # 全局样式目录 │ ├── font-awesome.css # Font Awesome 6.0图标样式 │ ├── table.css # 表格组件样式 │ └── tailwind.css # Tailwind CSS 框架样式│ ├── images/ # 全局公共图片目录 │ ├── login.png # 登录页图片 │ └── login_bg.png # 登录页背景图片 ├── js/ # 全局公共JS脚本目录 ├── logs/ # 全局系统日志目录 ├── uploads/ # 上传文件存储目录(按类型分类) ├── download/ # 下载模块 ├── pc/ # ========== PC端 ========== │ ├── index.php # 首页 │ ├── super_admin/ # 超级管理 │ │ ├── login_records.php # 登录记录 │ │ ├── menu.php # 菜单管理 │ │ ├── add_menu.php # 新增/编辑菜单 │ │ ├── role.php # 角色管理 │ │ ├── add_role.php # 新增/编辑角色 │ │ ├── pages.php # 页面管理 │ │ ├── add_pages.php # 新增/编辑页面 │ │ ├── users_list.php # 用户列表 │ │ ├── add_users.php # 新增/编辑用户 │ │ └── permission.php # 权限管理 │ └── assets/ # PC端公共资源 │ ├── header.php # PC端头部 │ ├── menu.php # PC端动态菜单 │ ├── footer.php # PC端底部 │ ├── password_change.php # 修改密码 │ ├── personal_info.php # 个人信息查看 │ ├── add_personal_info.php # 个人信息新增/编辑 │ ├── css/ # 样式目录 │ │ └── header.css # 页头样式 │ ├── images/ # 图片目录 │ └── js/ # JS脚本目录 ├── mobile/ # ========== 移动端 ========== │ ├── assets/ # 静态资源 │ │ ├── header.php # 移动端头部 │ │ ├── password_change.php # 修改密码 │ │ ├── personal_info.php # 个人信息查看 │ │ ├── add_personal_info.php # 个人信息新增/编辑 │ │ ├── assessno_time.php # 评估编号时间戳验证 │ │ ├── css/ # 样式目录 │ │ ├── images/ # 图片目录 │ │ └── js/ # JS脚本目录 │ ├── index.php # 主首页 │ ├── work_home.php # 工作台 │ ├── public_home.php # 公共事务 │ ├── my.php # 我的首页 │ ├── admin_home.php # 超管首页 │ ├── footer.php # 首页底部 │ ├── super_admin/ # 超级管理员 │ │ ├── users_list.php # 用户列表 │ │ ├── add_users.php # 新增/编辑用户 五、核心页面代码 1、core/auth.php 统一登录验证与权限校验 $_SESSION['user']['id'] ?? 0, 'real_name' => $_SESSION['user']['real_name'] ?? '未知用户', 'role_ids' => $_SESSION['user']['role_ids'] ?? [], 'org_id' => $_SESSION['user']['org_id'] ?? 0, 'username' => $_SESSION['user']['username'] ?? '未知账号' ]; if (empty($user_info['id']) || !is_numeric($user_info['id'])) { write_log("用户ID无效: " . $user_info['id'], 'error'); header('Location: /public/permission_denied.php'); exit; } $user_info['role_ids'] = array_filter($user_info['role_ids'], function($id) { return is_numeric($id) && $id > 0; }); $user_info['role_ids'] = array_map('intval', $user_info['role_ids']); if (empty($user_info['role_ids'])) { write_log("用户" . $user_info['real_name'] . "未分配有效角色", 'error'); header('Location: /public/permission_denied.php'); exit; } $current_page = $_SERVER['PHP_SELF'] ?? ''; if ($current_page !== '/public/permission_denied.php') { try { $page_stmt = $conn->prepare("SELECT id FROM pages WHERE page_path = ? AND status = 1"); $page_stmt->execute([$current_page]); $page = $page_stmt->fetch(PDO::FETCH_ASSOC); if (!$page) { throw new Exception("页面未注册: " . $current_page); } $current_page_id = $page['id']; $role_placeholders = implode(',', array_fill(0, count($user_info['role_ids']), '?')); $perm_stmt = $conn->prepare(" SELECT 1 FROM role_pages WHERE role_id IN ($role_placeholders) AND page_id = ? AND status = 1 "); $perm_params = array_merge($user_info['role_ids'], [$current_page_id]); $perm_stmt->execute($perm_params); if (!$perm_stmt->fetch()) { throw new Exception("用户" . $user_info['real_name'] . "无页面权限: " . $current_page); } } catch (Exception $e) { write_log("权限验证失败: " . $e->getMessage(), 'error'); header('Location: /public/permission_denied.php'); exit; } } $GLOBALS['user_info'] = $user_info; ?> -- -------------------------------------------------------- 2、core/functions.php 公共函数 getAttribute(PDO::ATTR_SERVER_VERSION); } catch (PDOException $e) { $info['mysql_version'] = '获取失败:' . $e->getMessage(); write_log("获取MySQL版本失败:" . $e->getMessage(), 'warning'); } $info['php_version'] = phpversion(); $info['web_server'] = $_SERVER['SERVER_SOFTWARE'] ?? ''; $info['system_time'] = date('Y-m-d H:i:s'); return $info; } function get_login_records($conn) { try { $sql = "SELECT login_name, ip_address, login_time FROM login_records ORDER BY login_time DESC LIMIT 10"; $stmt = $conn->prepare($sql); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { write_log("获取登录记录失败:" . $e->getMessage(), 'error'); return []; } } function get_operator_by_id($conn, $operator_id) { try { $sql = "SELECT id, login_name, real_name, gender, phone, email, status, role, create_time, update_time FROM users WHERE id = ? AND status IN (1,2,3)"; $stmt = $conn->prepare($sql); $stmt->execute([$operator_id]); return $stmt->fetch(PDO::FETCH_ASSOC) ?: null; } catch (PDOException $e) { write_log("获取用户信息失败 ID[$operator_id]:" . $e->getMessage(), 'error'); return null; } } function get_operator_role_ids($conn, $operator_id) { try { $sql = "SELECT role_id FROM users_roles WHERE user_id = ? AND status = 1 AND (expire_time IS NULL OR expire_time > NOW())"; $stmt = $conn->prepare($sql); $stmt->execute([$operator_id]); return $stmt->fetchAll(PDO::FETCH_COLUMN); } catch (PDOException $e) { write_log("获取用户角色ID失败 ID[$operator_id]:" . $e->getMessage(), 'error'); return []; } } function get_operator_roles($conn, $operator_id) { try { $sql = "SELECT r.id, r.role_name, r.display_name FROM users_roles ur JOIN roles r ON ur.role_id = r.id WHERE ur.user_id = ? AND ur.status = 1 AND (ur.expire_time IS NULL OR ur.expire_time > NOW()) AND r.status = 1"; $stmt = $conn->prepare($sql); $stmt->execute([$operator_id]); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { write_log("获取用户角色详情失败 ID[$operator_id]:" . $e->getMessage(), 'error'); return []; } } function count_operators_by_role_name($conn, $role_name) { try { $sql = "SELECT COUNT(DISTINCT ur.user_id) FROM users_roles ur JOIN roles r ON ur.role_id = r.id WHERE r.role_name = ? AND ur.status = 1 AND (ur.expire_time IS NULL OR ur.expire_time > NOW()) AND r.status = 1"; $stmt = $conn->prepare($sql); $stmt->execute([$role_name]); return (int)$stmt->fetchColumn(); } catch (PDOException $e) { write_log("按角色统计用户数量失败(角色:$role_name):" . $e->getMessage(), 'error'); return 0; } } function get_active_roles($conn) { try { $sql = "SELECT id, role_name, display_name FROM roles WHERE status = 1 ORDER BY id"; $stmt = $conn->prepare($sql); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { write_log("获取角色列表失败:" . $e->getMessage(), 'error'); return []; } } function get_role_display_name($conn, $role_name) { try { $sql = "SELECT display_name FROM roles WHERE role_name = ? AND status = 1"; $stmt = $conn->prepare($sql); $stmt->execute([$role_name]); return $stmt->fetchColumn() ?: $role_name; } catch (PDOException $e) { write_log("获取角色显示名失败(角色:$role_name):" . $e->getMessage(), 'error'); return $role_name; } } function gd_image_compress($src_path, $quality = null) { if (!file_exists($src_path)) { write_log("图片压缩失败:文件不存在 - $src_path", 'warning'); return false; } $info = @getimagesize($src_path); if (!$info) { write_log("图片压缩失败:无法读取图片信息 - $src_path", 'warning'); return false; } $width = $info[0]; $height = $info[1]; $mime = $info['mime']; if ($quality === null) { switch ($mime) { case 'image/jpeg': $quality = 75; break; case 'image/png': $quality = 6; break; case 'image/webp': $quality = 80; break; default: $quality = 80; } } $max_width = 1200; $need_resize = false; if ($width > $max_width) { $need_resize = true; $ratio = $max_width / $width; $new_width = $max_width; $new_height = (int)($height * $ratio); } switch ($mime) { case 'image/jpeg': $src_img = @imagecreatefromjpeg($src_path); break; case 'image/png': $src_img = @imagecreatefrompng($src_path); if ($src_img) { imagealphablending($src_img, true); imagesavealpha($src_img, true); } if ($quality > 9) { $quality = 9 - round($quality / 11.11); $quality = max(0, min(9, $quality)); } break; case 'image/webp': $src_img = @imagecreatefromwebp($src_path); break; case 'image/gif': $src_img = @imagecreatefromgif($src_path); break; case 'image/bmp': $src_img = @imagecreatefrombmp($src_path); break; default: write_log("图片压缩失败:不支持的图片类型 - $mime", 'warning'); return false; } if (!$src_img) { write_log("图片压缩失败:创建图像资源失败 - $src_path", 'warning'); return false; } if ($need_resize) { $dst_img = imagecreatetruecolor($new_width, $new_height); if ($mime === 'image/png') { imagealphablending($dst_img, false); imagesavealpha($dst_img, true); $transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127); imagefill($dst_img, 0, 0, $transparent); } imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $new_width, $new_height, $width, $height); imagedestroy($src_img); $src_img = $dst_img; } $success = false; switch ($mime) { case 'image/jpeg': $success = @imagejpeg($src_img, $src_path, $quality); break; case 'image/png': $success = @imagepng($src_img, $src_path, $quality); break; case 'image/webp': $success = @imagewebp($src_img, $src_path, $quality); break; case 'image/gif': $success = @imagegif($src_img, $src_path); break; case 'image/bmp': $success = @imagebmp($src_img, $src_path); break; } imagedestroy($src_img); if (!$success) { write_log("图片压缩失败:保存图片失败 - $src_path", 'warning'); return false; } return true; } ?> -- -------------------------------------------------------- 3、config/conn.php 数据库连接配置 PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]); } catch (PDOException $e) { die("Connection failed: " . $e->getMessage()); } ?> -- -------------------------------------------------------- 4、config/init.php # 环境初始化 -- -------------------------------------------------------- 5、pc/assets/header.php头部参考代码 智慧康养中心

智慧康养中心

-- -------------------------------------------------------- 6、mobile/assets/header.php头部参考代码 -- -------------------------------------------------------- 7、移动端mobile/assets/work_home.php纯后端跳转页面代码,根据 $role_home_map 将用户导向其专属工作台首页。注意:在文件路径和命名上,work_home.php 不是工作台本身,而是一个“调度器”或“中转站”。 '/mobile/nursing_home.php', 'nursing_admin' => '/mobile/nursing_admin_home.php', 'super_admin' => '/mobile/admin_home.php', ]; $target = '/mobile/index.php'; foreach ($role_names as $role) { if (isset($role_home_map[$role])) { $target = $role_home_map[$role]; break; } } header('Location: ' . $target); exit; -- -------------------------------------------------------- 8、移动端mobile/assets/footer.php底部页面代码 -- -------------------------------------------------------- 六、页面结构生成统一标准 1、权限不区分角色层级,超管、管理员、普通用户页面操作权限一致,无角色专属差异,权限已通过页面控制实现。注意:super_admin无特殊权限,一视同仁,禁止区域/机构过滤。 2、页面结构:HTML+PHP混合页面,优先使用混合方式生成代码,不允许前后端分离,所有代码在单页内完整生成,如需分离必须明确提示,同意后方可继续生成。 3、PC端与移动端资源严格隔离:PC端页面仅允许引用pc/assets/下的资源,移动端页面仅允许引用mobile/assets/下的资源,禁止交叉引用,避免样式冲突和代码冗余。 4.1、PC端与移动端有各自的header.php头部。该头部已完成统一初始化处理(通过config/auth.php实现登录状态验证、角色权限加载、页面访问权限校验、机构过滤等核心逻辑),且头部菜单为公共组件。所有内容区页面引入头部时,严禁重复写入初始化、登录验证、角色权限、页面权限、角色过滤等相关代码;*引入内容区时不得重复写入相同逻辑,保持头部代码的统一适配。 --------- 5、电脑端页面结构强制要求: 5.1、电脑端常规页面默认必须引用pc/assets/header.php、pc/assets/menu.php、pc/assets/footer.php,禁止重复引用/config/init.php 5.2、电脑端需要独立后端处理页面时仅引用/config/init.php,禁止引用pc/assets/header.php、pc/assets/menu.php、pc/assets/footer.php 5.3、电脑端页面结构代码示例:
重置
ID 操作
style="display:inline-block; padding:4px 8px; background-color:#409eff; color:white; border:none; border-radius:3px; text-decoration:none; font-size:14px;"> 查看详情
--------- 7、移动端页面结构强制要求 7.1、移动端常规页面默认必须引用mobile/assets/header.php、禁止重复引用/config/init.php 7.2、移动端需要独立后端处理页面时仅引用/config/init.php,禁止引用mobile/assets/header.php 7.3、移动端页面结构根据实际逻辑适配HTML样式结构,可参考示例代码:

未找到记录

姓名:
性别/年龄:
身份证号:
房间号:
联系电话:
/* ========== 页面分页 ========== */
/* ========== 业务专属JS ========== */ --------- 8、后端页面结构强制要求 8.1、纯后端逻辑(如 AJAX 接口、数据处理脚本)仅引用config/init.php文件,不得引用电脑端或移动端的头部、菜单、底部文件。 8.2、纯后端逻辑结构代码示例: -- -------------------------------------------------------- 七、页面代码生成时强制规则 1、已配置PDO连接属性$conn = new PDO($dsn, $dbUser, $dbPwd,PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC 页面内禁止重复设置(init.php已集成conn.php和functions.php), 2、PDO 参数绑定规则:涉及 SQL 查询 LIMIT/OFFSET 分页参数时,必须通过bindParam或bindValue明确指定参数类型为PDO::PARAM_INT,禁止直接将参数存入数组传递给execute(), (避免参数被解析为字符串导致语法错误:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''10' OFFSET '0'')。 3、处理 AJAX POST 请求需返回纯 JSON 响应时,务必在脚本顶部开启输出缓冲(ob_start ()),并在输出 JSON 前执行 ob_clean () 清空所有已缓冲的 HTML 内容,确保响应仅包含 JSON 格式数据,避免因 HTML 字符混入导致前端解析报错。 4、所有图片上传业务页面,必须在原有上传逻辑的「move_uploaded_file将文件移动至项目正式存储目录后、写入数据库前」,新增压缩代码gd_image_compress($save_full_path);,无其他原有逻辑改动;压缩处理失败时自动保留原上传文件,不中断上传业务流程,后续逻辑仍使用原文件正常执行。 5、GD 图片压缩核心逻辑统一封装为公共函数 gd_image_compress(),存放于 /core/functions.php,已通过 /core/auth.php 自动加载,全局可用,无需重复引入。 6、弹窗多行文本的 JS 生成需:按钮通过data-*属性存储文本(配合htmlspecialchars($value,ENT_QUOTES)转义单双引号),用事件委托绑定点击事件,取属性值后将\n转
、空格转 ,通过innerHTML渲染至含white-space: pre-wrap和line-height: 1.8的容器,确保弹窗正常且排版完整。 7、电脑端全局CSS样式已固定,优先通过内联样式和必要的style属性来美化页面,适配全局CSS。 8、逻辑代码必须严格对应SQL数据表字段,如有冲突以数据表字段及描述为准。 9、如有新增/编辑页面开发,必须采用“新增/编辑”逻辑一体化(例如add_operator.php同时处理新增和编辑,通过id参数区分)。 10、初步评估编号生成标准$post['preliminary_no'] = 'CP' . date('Ymd') . round(microtime(true) * 1000); 11、正式评估编号生成标准$post['assessment_no'] = date('Ymd') . round(microtime(true) * 1000); -- -------------------------------------------------------- 八、页面代码输出时强制规则 1、明确排版规则、组件关系和判断逻辑,要理解 “动态适配+多列紧凑排列”的需求:设计数据录入表单时,采用‘标题+输入框’组合为独立单元(标题居左,输入框居右,标题文字简洁不换行);根据每个单元的标题长度和输入框所需合理宽度,动态判断并在一行内紧凑排列,每行至少容纳4个单元(优先排满4列);标题宽度仅适配自身文字长度(不冗余),输入框宽度按需分配(避免过宽),整体保持整齐对齐,仅当一行无法容纳更多单元时自动换行至下一行,确保表单紧凑不松散,视觉上不出现单个单元独占一行的情况。 2、容器内的内容较少时避免出现不必要的滚动条,要调整内容布局,让容器高度自适应内容(不设置固定高度或冗余嵌套),确保内容少时不会出现滚动条,仅在内容超出视口时才显示滚动条。 3、按纽要在同一行排列或合适的位置并用不同的颜色区分,大小样式统一,尺寸一致,根据页面整体结构自动放在合理位置(如表单底部操作区),根据表单布局自动放在合理位置(通常为表单底部),根据页面内容(如列表、表格)自动放在操作区合理位置(如列表顶部或右侧)。 4、CSS必须按标准规范:采用展开式标准书写,同一选择器内的所有属性合并在一行单行排列不换行,如body { background-color:#f5f5f5; font-size:14px; color:#333; }。 5、注释添加需严格遵循:仅允许在「模块前」添加,禁止在 SQL 查询语句内部(如 SELECT 子句、WHERE 条件中)添加注释,避免触发SQL语法错误。 6、***在新增/删除/插入/替换代码时,修正位置必须明确包含两部分:待替换原代码(完整无省略)+修改后代码(完整无省略)。*** 含义解释:代码修改(新增/删除/插入/替换)时,必须按“修正点”逐一提供两份完整片段:待替换原代码(完整无省略)* 和 修改后代码(完整无省略)。每个“修正点”指实际变动的代码单元(如:单行、多行、SQL语句、函数定义、HTML标签块等),禁止用“...”或注释省略,禁止仅提供整个文件而不逐点拆解。若一处修改涉及多个独立片段,应分别列出。仅在用户明确要求“整体输出”时,才提供完整文件内容。*** -- --------------------------------------------------------