联系人信息管理 ER 设计
基于现有联系人管理功能,扩展为全维度个人信息管理系统。 创建时间:2026-08-08
一、整体架构 1 2 3 4 5 6 7 8 9 10 11 erDiagram sys_user ||--o{ user_contact_person : "create_by" user_contact_person ||--|| user_contact_person_ext : "contact_id 一对一" user_contact_person ||--o{ user_contact_work : "contact_id 一对多" user_contact_person ||--o{ user_contact_education : "contact_id 一对多" user_contact_person ||--o{ user_contact_family : "contact_id 一对多" user_contact_person ||--o{ user_contact_health : "contact_id 一对多" user_contact_person ||--o{ user_contact_life : "contact_id 一对多" user_contact_person ||--o{ user_contact_social : "contact_id 一对多" user_contact_person ||--o{ user_contact_finance : "contact_id 一对多" user_contact_person ||--o{ user_contact_certificate : "contact_id 一对多"
二、表关系总览
表名
维度
关系
用途
user_contact_person
基础联系信息
主表
姓名、联系方式、城市
user_contact_person_ext
个人扩展画像
一对一
性别、生日、籍贯、民族、身份证、婚姻、居住地址
user_contact_work
工作经历
一对多
公司、部门、职位、行业、薪资、入职/离职日期
user_contact_education
教育经历
一对多
学校、专业、学历、入学/毕业日期
user_contact_family
家庭成员
一对多
姓名、关系、性别、生日、职业、电话
user_contact_health
健康记录
一对多
血型、身高体重、过敏史、病史、用药、体检记录
user_contact_life
生活记录
一对多
饮食/作息/运动习惯、兴趣爱好、旅行足迹
user_contact_social
社交账号
一对多
微信/QQ/微博/抖音等账号
user_contact_finance
财务信息
一对多
收入/资产/负债、金额、记录日期
user_contact_certificate
证件管理
一对多
身份证/护照/驾照/职业资格证等
三、ER 图详情 3.1 基础表(已实现) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 erDiagram user_contact_person ||--|| user_contact_person_ext : "contact_id 一对一" user_contact_person { bigint contact_id PK "联系人主键" varchar name "姓名" varchar contact_model "联系方式" varchar contact_no "联系号" varchar city "城市" varchar search_keys "搜索暗号(逗号分隔)" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志(0存在 2删除)" } user_contact_person_ext { bigint contact_id PK "扩展主键(关联主表)" varchar avatar "头像URL" char gender "性别(0男 1女)" date birthday "生日" int age "年龄" varchar native_place "籍贯" varchar nation "民族" varchar id_card "身份证号" char marital_status "婚姻状况(0未婚 1已婚 2离异 3丧偶)" varchar home_address "居住地址" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志(0存在 2删除)" }
3.2 工作经历(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 erDiagram user_contact_person ||--o{ user_contact_work : "contact_id" user_contact_work { bigint work_id PK "工作经历ID" bigint contact_id FK "联系人ID" varchar company "公司名称" varchar department "部门" varchar position "职位" varchar industry "行业" varchar work_address "工作地址" varchar work_phone "工作电话" varchar work_email "工作邮箱" date entry_date "入职日期" date leave_date "离职日期" char is_current "是否在职(0是 1否)" decimal salary "薪资" varchar remark "工作备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
3.3 教育经历(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 erDiagram user_contact_person ||--o{ user_contact_education : "contact_id" user_contact_education { bigint edu_id PK "教育经历ID" bigint contact_id FK "联系人ID" varchar school_name "学校名称" varchar major "专业" varchar degree "学历(字典)" date start_date "入学日期" date end_date "毕业日期" char is_graduated "是否毕业(0是 1否)" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
3.4 家庭成员(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 erDiagram user_contact_person ||--o{ user_contact_family : "contact_id" user_contact_family { bigint family_id PK "家庭成员ID" bigint contact_id FK "联系人ID" varchar member_name "成员姓名" char relation "关系(字典:父子/夫妻等)" char gender "性别" date birthday "生日" varchar occupation "职业" varchar phone "电话" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
3.5 健康记录(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 erDiagram user_contact_person ||--o{ user_contact_health : "contact_id" user_contact_health { bigint health_id PK "健康记录ID" bigint contact_id FK "联系人ID" date record_date "记录日期" char blood_type "血型(字典)" decimal height "身高(cm)" decimal weight "体重(kg)" char allergy "过敏史" varchar medical_history "既往病史" varchar current_medication "正在用药" varchar hospital "体检医院" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
3.6 生活记录(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 erDiagram user_contact_person ||--o{ user_contact_life : "contact_id" user_contact_life { bigint life_id PK "生活记录ID" bigint contact_id FK "联系人ID" date record_date "记录日期" char diet_habit "饮食习惯(字典)" char sleep_habit "作息习惯" char exercise_freq "运动频率" varchar hobbies "兴趣爱好" varchar preferences "偏好备注" varchar travel_history "旅行足迹" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
3.7 社交账号(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 erDiagram user_contact_person ||--o{ user_contact_social : "contact_id" user_contact_social { bigint social_id PK "社交账号ID" bigint contact_id FK "联系人ID" char platform "平台类型(字典)" varchar account "账号" varchar nickname "昵称" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
3.8 财务信息(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 erDiagram user_contact_person ||--o{ user_contact_finance : "contact_id" user_contact_finance { bigint finance_id PK "财务记录ID" bigint contact_id FK "联系人ID" char finance_type "类型(收入/资产/负债)" varchar item_name "项目名称" decimal amount "金额" date record_date "记录日期" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
3.9 证件管理(一对多) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 erDiagram user_contact_person ||--o{ user_contact_certificate : "contact_id" user_contact_certificate { bigint cert_id PK "证件ID" bigint contact_id FK "联系人ID" char cert_type "证件类型(字典)" varchar cert_no "证件号码" varchar issue_org "签发机构" date issue_date "签发日期" date expire_date "到期日期" varchar remark "备注" varchar create_by "创建者" datetime create_time "创建时间" varchar update_by "更新者" datetime update_time "更新时间" char del_flag "删除标志" }
四、分阶段实施计划 第一期(已完成)
表名
状态
说明
user_contact_person
已完成
联系人基础信息
user_contact_person_ext
已完成
联系人扩展画像
第二期(推荐下一步)
表名
说明
user_contact_work
工作经历(支持多段)
user_contact_education
教育经历(支持多段)
user_contact_family
家庭成员
第三期
表名
说明
user_contact_health
健康记录
user_contact_life
生活记录
第四期
表名
说明
user_contact_social
社交账号
user_contact_finance
财务信息
user_contact_certificate
证件管理
五、设计原则
主表轻量 :只存核心联系信息,保证查询效率
扩展表一对一 :存固定画像字段(一个联系人只有一份)
明细表一对多 :工作/教育/健康等有时间属性的、可能多条记录的,单独建表
逻辑删除 :所有表都加 del_flag、create_by、create_time、update_by、update_time
字典化 :性别、学历、关系、血型、平台类型等都用字典(sys_dict_type),方便扩展
六、后端功能设计 6.1 目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ruoyi-admin/src/main/java/com/ruoyi/identity/ ├── domain/ # 实体类 │ ├── UserContactPerson.java # 联系人主表 │ ├── UserContactPersonExt.java # 联系人扩展表 │ ├── UserContactWork.java # 工作经历 │ ├── UserContactEducation.java # 教育经历 │ ├── UserContactFamily.java # 家庭成员 │ ├── UserContactHealth.java # 健康记录 │ ├── UserContactLife.java # 生活记录 │ ├── UserContactSocial.java # 社交账号 │ ├── UserContactFinance.java # 财务信息 │ └── UserContactCertificate.java # 证件管理 ├── mapper/ # Mapper 接口 │ ├── UserContactPersonMapper.java │ ├── UserContactPersonExtMapper.java │ └── ... ├── service/ # Service 接口 │ ├── IUserContactPersonService.java │ ├── IUserContactPersonExtService.java │ └── ... │ └── impl/ # Service 实现 │ ├── UserContactPersonServiceImpl.java │ └── ... └── controller/ # Controller ├── UserContactPersonController.java ├── UserContactPersonExtController.java └── ...
1 2 3 4 5 ruoyi-admin/src/main/resources/mapper/identity/ ├── UserContactPersonMapper.xml ├── UserContactPersonExtMapper.xml ├── UserContactWorkMapper.xml └── ...
6.2 Controller 接口规范 每张表统一提供以下接口(以工作经历为例):
接口
方法
路径
权限标识
说明
查询列表
GET
/identity/contact_work/list
identity:contact_work:list
分页查询,支持按 contactId 过滤
查询详情
GET
/identity/contact_work/{workId}
identity:contact_work:query
按主键查询
新增
POST
/identity/contact_work
identity:contact_work:add
新增一条记录
修改
PUT
/identity/contact_work
identity:contact_work:edit
修改一条记录
删除
DELETE
/identity/contact_work/{workIds}
identity:contact_work:remove
逻辑删除(del_flag='2')
导出
POST
/identity/contact_work/export
identity:contact_work:export
导出 Excel
6.3 Domain 设计规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class UserContactWork extends BaseEntity { private static final long serialVersionUID = 1L ; @Excel(name = "工作经历ID") private Long workId; @Excel(name = "联系人ID") private Long contactId; @Excel(name = "公司名称") private String company; @Excel(name = "入职日期", dateFormat = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd") private Date entryDate; @Excel(name = "是否在职", readConverterExp = "0=是,1=否") private String isCurrent; private String delFlag; }
6.4 Mapper XML 查询规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <select id ="selectUserContactWorkList" parameterType ="UserContactWork" resultMap ="UserContactWorkResult" > select <include refid ="selectUserContactWorkVo" /> from user_contact_work <where > del_flag = '0' <if test ="contactId != null" > and contact_id = #{contactId} </if > <if test ="company != null and company != ''" > and company like concat('%', #{company}, '%') </if > <if test ="isCurrent != null and isCurrent != ''" > and is_current = #{isCurrent} </if > </where > order by entry_date desc </select > <update id ="deleteUserContactWorkByWorkIds" > update user_contact_work set del_flag = '2' where work_id in <foreach item ="workId" collection ="array" open ="(" separator ="," close =")" > #{workId} </foreach > </update >
6.5 Service 层规范 1 2 3 4 5 6 7 8 9 10 11 12 public interface IUserContactWorkService { List<UserContactWork> selectUserContactWorkList (UserContactWork userContactWork) ; UserContactWork selectUserContactWorkByWorkId (Long workId) ; int insertUserContactWork (UserContactWork userContactWork) ; int updateUserContactWork (UserContactWork userContactWork) ; int deleteUserContactWorkByWorkIds (Long[] workIds) ; }
6.6 跨表关联查询 扩展信息展示时需要 JOIN 主表带出联系人姓名:
1 2 3 4 5 6 7 8 9 <select id ="selectUserContactWorkList" resultMap ="UserContactWorkResult" > select w.*, p.name as contact_name from user_contact_work w left join user_contact_person p on w.contact_id = p.contact_id <where > w.del_flag = '0' <if test ="contactId != null" > and w.contact_id = #{contactId} </if > </where > </select >
6.7 事务管理 涉及多表操作时加 @Transactional:
1 2 3 4 5 6 7 8 9 10 @Transactional public int insertUserContactPerson (UserContactPerson userContactPerson) { int rows = userContactPersonMapper.insertUserContactPerson(userContactPerson); UserContactPersonExt ext = new UserContactPersonExt (); ext.setContactId(userContactPerson.getContactId()); userContactPersonExtMapper.insertUserContactPersonExt(ext); return rows; }
七、前端功能设计 7.1 目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ruoyi-ui/src/ ├── api/identity/ # API 请求 │ ├── contact_person.js # 联系人主表 API │ ├── contact_person_ext.js # 扩展表 API │ ├── contact_work.js # 工作经历 API │ ├── contact_education.js # 教育经历 API │ ├── contact_family.js # 家庭成员 API │ ├── contact_health.js # 健康记录 API │ ├── contact_life.js # 生活记录 API │ ├── contact_social.js # 社交账号 API │ ├── contact_finance.js # 财务信息 API │ └── contact_certificate.js # 证件管理 API └── views/identity/ ├── contact_person/ # 联系人主页面(列表入口) │ └── index.vue ├── contact_person_ext/ # 扩展信息页面 │ └── index.vue ├── contact_work/ # 工作经历页面 │ └── index.vue ├── contact_education/ # 教育经历页面 │ └── index.vue └── ...
7.2 页面导航设计 采用「主列表 → 子模块 Tab 切换」模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 联系人列表页(contact_person/index.vue) │ ├─ 操作列「详情」按钮 → 联系人详情页 │ └─ 联系人详情页(contact_detail/index.vue) │ ├─ Tab 1: 基础信息(contact_person + ext) ├─ Tab 2: 工作经历(contact_work) ├─ Tab 3: 教育经历(contact_education) ├─ Tab 4: 家庭成员(contact_family) ├─ Tab 5: 健康记录(contact_health) ├─ Tab 6: 生活记录(contact_life) ├─ Tab 7: 社交账号(contact_social) ├─ Tab 8: 财务信息(contact_finance) └─ Tab 9: 证件管理(contact_certificate)
7.3 API 请求规范 每个子模块统一提供 6 个方法(以工作经历为例):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 import request from '@/utils/request' export function listContact_work (query ) { return request ({ url : '/identity/contact_work/list' , method : 'get' , params : query }) } export function getContact_work (workId ) { return request ({ url : '/identity/contact_work/' + workId, method : 'get' }) } export function addContact_work (data ) { return request ({ url : '/identity/contact_work' , method : 'post' , data : data }) } export function updateContact_work (data ) { return request ({ url : '/identity/contact_work' , method : 'put' , data : data }) } export function delContact_work (workId ) { return request ({ url : '/identity/contact_work/' + workId, method : 'delete' }) } export function exportContact_work (query ) { return request ({ url : '/identity/contact_work/export' , method : 'post' , params : query }) }
7.4 页面组件规范
搜索条件:联系人下拉框(filterable)
列表:显示扩展字段 + 联系人姓名(JOIN)
对话框:分区块表单(el-divider 分隔)
新增/修改区分:用 isEdit 标志位,不用 contactId != null
搜索条件:默认按 contactId 过滤(从 URL query 传入)
列表:表格显示该联系人的所有记录
对话框:contactId 只读(从 URL 带入或默认选中当前联系人)
时间线展示:工作经历、教育经历可用 el-timeline 按时间倒序展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <template> <div class="app-container"> <!-- 从联系人详情页带入 contactId --> <el-timeline> <el-timeline-item v-for="work in workList" :key="work.workId" :timestamp="work.entryDate + ' ~ ' + (work.leaveDate || '至今')" placement="top" > <el-card> <h4>{{ work.company }} - {{ work.position }}</h4> <p>{{ work.department }} | {{ work.workAddress }}</p> </el-card> </el-timeline-item> </el-timeline> </div> </template>
7.5 路由配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 { path : '/identity' , component : Layout , children : [ { path : 'contact_person' , name : 'Contact_person' , component : () => import ('@/views/identity/contact_person/index' ), meta : { title : '联系人管理' , icon : 'el-icon-user' } }, { path : 'contact_person_ext' , name : 'Contact_person_ext' , component : () => import ('@/views/identity/contact_person_ext/index' ), meta : { title : '扩展信息' , activeMenu : '/identity/contact_person' } }, { path : 'contact_detail/:contactId' , name : 'Contact_detail' , component : () => import ('@/views/identity/contact_detail/index' ), hidden : true , meta : { title : '联系人详情' , activeMenu : '/identity/contact_person' } } ] }
7.6 字典配置 需要在「系统管理 → 字典管理」中新增以下字典:
字典类型
字典名称
字典项示例
contact_tags
搜索暗号
1=spec, 2=job, 3=life
contact_degree
学历
1=博士, 2=硕士, 3=本科, 4=大专, 5=高中
contact_relation
家庭关系
1=父亲, 2=母亲, 3=配偶, 4=儿子, 5=女儿
contact_blood_type
血型
A=A型, B=B型, O=O型, AB=AB型
contact_platform
社交平台
1=微信, 2=QQ, 3=微博, 4=抖音
contact_finance_type
财务类型
1=收入, 2=资产, 3=负债
contact_cert_type
证件类型
1=身份证, 2=护照, 3=驾照, 4=资格证
7.7 菜单配置 在「系统管理 → 菜单管理」中配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 联系人管理(目录) ├── 联系人列表(菜单,/identity/contact_person) │ ├── 新增(按钮 identity:contact_person:add) │ ├── 修改(按钮 identity:contact_person:edit) │ ├── 删除(按钮 identity:contact_person:remove) │ └── 扩展信息(按钮 identity:contact_person_ext:query) ├── 扩展信息(菜单,/identity/contact_person_ext,隐藏) ├── 工作经历(菜单,/identity/contact_work,隐藏) ├── 教育经历(菜单,/identity/contact_education,隐藏) ├── 家庭成员(菜单,/identity/contact_family,隐藏) ├── 健康记录(菜单,/identity/contact_health,隐藏) ├── 生活记录(菜单,/identity/contact_life,隐藏) ├── 社交账号(菜单,/identity/contact_social,隐藏) ├── 财务信息(菜单,/identity/contact_finance,隐藏) └── 证件管理(菜单,/identity/contact_certificate,隐藏)
子模块菜单设为隐藏,通过联系人列表操作列按钮跳转进入。
八、相关文档
数据库设计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 DROP TABLE IF EXISTS `crm_contact`;CREATE TABLE `crm_contact` ( `contact_id` BIGINT (20 ) NOT NULL AUTO_INCREMENT COMMENT '主键ID' , `name` VARCHAR (100 ) NOT NULL COMMENT '姓名' , `contact_model` VARCHAR (20 ) NOT NULL DEFAULT '手机' COMMENT '联系方式类型(手机/微信/QQ/邮件)' , `contact_value` VARCHAR (100 ) NOT NULL DEFAULT '' COMMENT '联系号(对应具体号码)' , `company` VARCHAR (200 ) DEFAULT '' COMMENT '公司/单位' , `city` VARCHAR (100 ) DEFAULT '' COMMENT '所在城市' , `search_keys` VARCHAR (255 ) DEFAULT '' COMMENT '搜索暗号(标签/别名,逗号分隔)' , `remark` VARCHAR (500 ) DEFAULT '' COMMENT '关键备注(见面话题/历史事件)' , `create_by` VARCHAR (64 ) DEFAULT '' COMMENT '创建者' , `create_time` DATETIME COMMENT '创建时间' , `update_by` VARCHAR (64 ) DEFAULT '' COMMENT '更新者' , `update_time` DATETIME COMMENT '更新时间' , `del_flag` CHAR (1 ) DEFAULT '0' COMMENT '删除标记(0存在 2删除)' , PRIMARY KEY (`contact_id`), KEY `idx_name` (`name`), KEY `idx_contact_value` (`contact_value`), KEY `idx_city` (`city`), KEY `idx_del_flag` (`del_flag`) ) ENGINE= InnoDB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT= '联系人表(个人极简版)' ; DROP TABLE IF EXISTS `user_contact_person_ext`;CREATE TABLE `user_contact_person_ext` ( `contact_id` bigint (20 ) NOT NULL COMMENT '联系人主键ID(关联 user_contact_person.contact_id)' , `avatar` varchar (255 ) DEFAULT NULL COMMENT '头像URL' , `gender` char (1 ) DEFAULT NULL COMMENT '性别(0男 1女)' , `birthday` date DEFAULT NULL COMMENT '生日' , `age` int (3 ) DEFAULT NULL COMMENT '年龄' , `id_card` varchar (20 ) DEFAULT NULL COMMENT '身份证号' , `marital_status` char (1 ) DEFAULT NULL COMMENT '婚姻状况(0未婚 1已婚 2离异 3丧偶)' , `native_place` varchar (100 ) DEFAULT NULL COMMENT '籍贯' , `home_address` varchar (255 ) DEFAULT NULL COMMENT '居住地址' , `company` varchar (100 ) DEFAULT NULL COMMENT '工作单位' , `department` varchar (50 ) DEFAULT NULL COMMENT '部门' , `position` varchar (50 ) DEFAULT NULL COMMENT '职位' , `industry` varchar (50 ) DEFAULT NULL COMMENT '所属行业' , `work_address` varchar (255 ) DEFAULT NULL COMMENT '工作地址' , `email` varchar (100 ) DEFAULT NULL COMMENT '个人邮箱' , `wechat` varchar (50 ) DEFAULT NULL COMMENT '微信号' , `qq` varchar (20 ) DEFAULT NULL COMMENT 'QQ号' , `yuni` varchar (20 ) DEFAULT NULL COMMENT '与你' , `backup_phone` varchar (20 ) DEFAULT NULL COMMENT '备用电话' , `emergency_contact` varchar (50 ) DEFAULT NULL COMMENT '紧急联系人' , `emergency_phone` varchar (20 ) DEFAULT NULL COMMENT '紧急联系电话' , `emergency_relation` varchar (50 ) DEFAULT NULL COMMENT '与紧急联系人关系' , `hobbies` varchar (255 ) DEFAULT NULL COMMENT '兴趣爱好' , `preferences` varchar (255 ) DEFAULT NULL COMMENT '偏好备注(饮食/习惯等)' , `tags` varchar (255 ) DEFAULT NULL COMMENT '业务标签(逗号分隔)' , `remark` varchar (500 ) DEFAULT NULL COMMENT '扩展备注' , `create_by` varchar (64 ) DEFAULT '' COMMENT '创建者' , `create_time` datetime DEFAULT NULL COMMENT '创建时间' , `update_by` varchar (64 ) DEFAULT '' COMMENT '更新者' , `update_time` datetime DEFAULT NULL COMMENT '更新时间' , `del_flag` char (1 ) COLLATE utf8mb4_unicode_ci DEFAULT '0' COMMENT '删除标记(0存在 2删除)' , PRIMARY KEY (`contact_id`), CONSTRAINT `fk_ext_contact` FOREIGN KEY (`contact_id`) REFERENCES `user_contact_person` (`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT= '联系人信息扩展表' ;
用户列表 菜单图标 系统菜单 -》用户管理 -》用户列表,点击修改链接
修改对话框标题 前端页面:src/views/system/info/index.vue 253行删掉列表 263行删掉列表
注册时间 无论新增、修改,都不需要注册时间(自动生成) 1.修改前端代码:130行-137行注释掉 2.修改后端代码:修改sql语句,Mapper 映射文件:ruoyi-admin/src/main/resources/mapper/system/UserInfoMapper.xml
1 insert into user_info (user_name, phone, register_time) values (#{userName}, #{phone}, now())
车辆品牌 参考:https://www.yoojia.com/car/0-0-0-0-0-0-0-0-0-0-0-0-0-0-4-0-0.html
创建车辆品牌表 设置主键自增,防止not null 报错
1 2 3 4 5 6 CREATE TABLE `car_brand` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键' , `name` varchar (255 ) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '品牌名' , `logo` varchar (255 ) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'logo图片' , PRIMARY KEY (`id`) ) ENGINE= InnoDB AUTO_INCREMENT= 4 DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_unicode_ci
代码生成 1、登录若依后台管理系统:系统工具 -> 代码生成 2、点击导入按钮,选择车辆品牌表,点击确定 3、点击车辆品牌表后面的编辑按钮,分别修改基本信息、字段信息、生成信息,点击提交
合并代码 1、把下载的代码解压 2、把 sql 导入 cardb 数据库:拖拽 SQL 文件到数据库即可 3、把 main 文件夹里面的代码复制(打开 main 文件夹,选中 java/resources 进行复制),粘贴到 ruoyiadmin/src/main,选中 main 进行粘贴; 4、把 vue 文件夹里面的代码复制(打开 vue 文件夹,选中 api/views 进行复制),粘贴到ruoyi-ui/src,选中 src 进行粘贴 5、重启后端服务即可,前端服务是热部署的
菜单图标 设置菜单图标,才能打开页面 1、系统管理 -> 系统菜单 -> 用户管理 -> 车辆品牌,点击修改链接 2、刷新页面即可
车辆类型 创建数据表 1 2 3 4 5 6 7 CREATE TABLE `car_type` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键' , `name` varchar (255 ) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '类型名' , `img` varchar (255 ) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '示例图片' , `bid` int DEFAULT NULL COMMENT '所有品牌' , PRIMARY KEY (`id`) ) ENGINE= InnoDB AUTO_INCREMENT= 7 DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_unicode_ci
关联车辆品牌 1、在 CarBrandController 定义查询所有车辆品牌的接口
1 2 3 4 5 6 7 8 9 10 11 @PreAuthorize("@ss.hasPermi('car:brand:list')") @GetMapping("/all") public TableDataInfo all (CarBrand carBrand) { List<CarBrand> list = carBrandService.selectCarBrandList(carBrand); return getDataTable(list); }
2、在 src/api/car/brand.js 中,调用查询所有车辆品牌的接口的方法
1 2 3 4 5 6 7 export function listBrand2 ( ) {return request ({url : '/car/brand/all' ,method : 'get' }) }
3、在车辆类型页面(src/views/car/type/index.vue),定义查询车辆品牌的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import { listBrand2 } from "@/api/car/brand" data ( ) { return { rules : { } ,brandList :[] } }, created ( ) { this .getList () this .getBrandList () } methods : { getBrandList ( ) { this .loading = true listBrand2 ().then (response => { console .log (response); this .brandList = response.rows this .loading = false }) }, handleAdd ( ) { this .getBrandList () this .reset () this .open = true this .title = "添加车辆类型" }, handleUpdate (row ) { this .getBrandList () this .reset () const id = row.id || this .ids getType (id).then (response => { this .form = response.data this .open = true this .title = "修改车辆类型" }) } }
3、在车辆类型页面(src/views/car/type/index.vue),使用下拉框动态渲染车辆品牌数据el-select 组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <el-form-item label ="所属品牌" prop ="bid" > <el-select v-model ="queryParams.bid" placeholder ="请输入所属品牌" clearable @keyup.enter.native ="handleQuery" > <el-option v-for ="item in brandList" :key ="item.id" :label ="item.name" :value ="item.id" > </el-option > </el-select > </el-form-item > <el-form-item label ="所属品牌" prop ="bid" > <el-select v-model ="form.bid" placeholder ="请输入所属品牌" > <el-option v-for ="item in brandList" :key ="item.id" :label ="item.name" :value ="item.id" > </el-option > </el-select > </el-form-item >
数据表格(多表查询) 1、在 ruoyi-admin/src/main/resouces/mapper/car/CarTypeMapper.xml 修改SQL 语句,实现多表查询 在 CarTypeMapper.xml 手动映射 bname
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 < resultMap type= "CarType" id= "CarTypeResult"> < result property= "id" column = "id" / > < result property= "name" column = "name" / > < result property= "img" column = "img" / > < result property= "bid" column = "bid" / > < result property= "bname" column = "bname" / > < / resultMap> < select id= "selectCarTypeList" parameterType= "CarType" resultMap= "CarTypeResult"> < ! SELECT ct.id, ct.`name`, ct.img, ct.bid, cb.`name` AS bname FROM car_type ct LEFT JOIN car_brand cb ON ct.bid = cb.id < where > < if test= "name != null and name != ''"> and ct.name like concat('%' , #{name}, '%' )< / if> < if test= "bid != null "> and ct.bid = #{bid}< / if> < / where > < / select >
2、修改 CarType 实体类,添加 bname 字段;
1 2 3 4 5 6 7 8 9 10 private String bname;public String getBname () { return bname; } public void setBname (String bname) { this .bname = bname; }
3、修改前端页面的数据表格,添加所属品牌列
1 <el-table-column label ="所属品牌" prop ="bname" />
用户车辆 创建数据表 1 2 3 4 5 6 7 8 9 CREATE TABLE `user_car` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键\r\n' , `uid` int DEFAULT NULL COMMENT '所属用户' , `brand` int DEFAULT NULL COMMENT '所属品牌' , `type` int DEFAULT NULL COMMENT '所属类型' , `car_num` varchar (255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '车牌号' , `car_img` varchar (255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '车辆照片' , PRIMARY KEY (`id`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_unicode_ci
关联用户 1、在 UserInfoController 定义查询所有用户的接口
1 2 3 4 5 6 7 8 9 10 11 12 @PreAuthorize("@ss.hasPermi('system:info:list')") @GetMapping("/list") public TableDataInfo list (UserInfo userInfo) { startPage(); List<UserInfo> list = userInfoService.selectUserInfoList(userInfo); return getDataTable(list); }
2、在 src/api/system/info.js 中,调用查询所有用户的接口的方法
1 2 3 4 export function listInfo2 ( ) {return request ({url : '/system/info/all' , method : 'get' })}
3、在 src/views/car/car/index.vue 中,定义查询所有用户的方法
1 2 3 4 5 6 7 8 9 10 11 12 import { listInfo2, getInfo, delInfo, addInfo, updateInfo } from "@/api/system/info" getUserList ( ) {this .loading = true listInfo2 ().then (response => {this .userList = response.rows console .log (response.rows );this .loading = false }) },
4、在新增/修改的事件函数中,调用 getUserList 方法 5、使用下拉框动态渲染用户数据
关联车辆类型 1、把文本框改为下拉框:以下拉框形式,动态显示车辆所属类型 2、根据所属品牌不同,动态显示车辆类型 实现方式: 1、后端代码:定义根据 bid 查询车辆类型的整套代码(Controller、Service、Mapper)
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class CarTypeController extends BaseController { @Autowired private ICarTypeService carTypeService;@PreAuthorize("@ss.hasPermi('car:type:list')") @GetMapping("/listByBid") public TableDataInfo listByBid (Integer bid) { List<CarType> list = carTypeService.selectCarTypeByBId(bid); return getDataTable(list);} }
service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public interface ICarTypeService { public List<CarType> selectCarTypeByBId (Integer bid) ;} @Service public class CarTypeServiceImpl implements ICarTypeService {@Autowired private CarTypeMapper carTypeMapper;@Override public List<CarType> selectCarTypeByBId (Integer bid) {return carTypeMapper.selectCarTypeByBId(bid);} }
mapper
1 2 3 4 5 6 7 8 9 10 11 public interface CarTypeMapper { public List<CarType> selectCarTypeByBId (Integer bid) ;}
1 2 3 4 <select id ="selectCarTypeByBId" parameterType ="Integer" resultMap ="CarTypeResult" >SELECT id, name, img, bid FROM car_type WHERE bid = #{bid}</select >
2、每次所属品牌发生改变,发送请求,获取车辆类型数据即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 export function listType2 (bid ) {return request ({url : '/car/type/listByBid?bid=' + bid, method : 'get' })} <el-select v-model="form.brand" placeholder="请选择品牌" @change="handleBrandChange" clearable> import { listType2, getType, delType, addType, updateType } from "@/api/car/type" brandChange ( ){console .log ('你选择了' + this .form .brand );this .loading = true listType2 (this .form .brand ).then (response => {this .typeList = response.rows console .log (response.rows );this .loading = false }) }, <el-form-item label ="所属类型" prop ="type" > <el-select v-model ="form.type" placeholder ="请选择所属类型" > <el-option v-for ="item in typeList" :key ="item.id" :label ="item.name" :value ="item.id" ></el-option > </el-select > </el-form-item >