diff --git a/src/api/system/house/index.ts b/src/api/system/house/index.ts index 19001d6..bbc56e1 100644 --- a/src/api/system/house/index.ts +++ b/src/api/system/house/index.ts @@ -95,3 +95,10 @@ export function EditHouseApi(data: addHouseType) { data }); } +/** 根据小区id,获取当前小区的树状结构 */ +export function getVillageTree(id: number) { + return request({ + url: `/house/villageTree/${id}`, + method: 'GET' + }); +} diff --git a/src/api/system/resident/index.ts b/src/api/system/resident/index.ts index 213a00e..efc648d 100644 --- a/src/api/system/resident/index.ts +++ b/src/api/system/resident/index.ts @@ -33,7 +33,7 @@ export const getResident = (id: string | number): AxiosPromise => { */ export const addResident = (data: ResidentForm) => { return request({ - url: '////resident', + url: '/resident', method: 'post', data: data }); @@ -61,3 +61,14 @@ export const delResident = (id: string | number | Array) => { method: 'delete' }); }; + +/** + * 添加住户管理-上传身份证 + * @param id + */ +export const UploadidCardApi = () => { + return request({ + url: '/resident/uploadImage', + method: 'delete' + }); +}; diff --git a/src/api/system/resident/type.ts b/src/api/system/resident/type.ts index 7adb04c..b31b3f9 100644 --- a/src/api/system/resident/type.ts +++ b/src/api/system/resident/type.ts @@ -47,7 +47,7 @@ export interface ResidentVO { /** * 房屋表id */ - houseId: string | number; + houseId: number; /** * 0审核中 1 已认证 @@ -68,6 +68,9 @@ export interface ResidentVO { * 备注 */ remark: string; + + /** 具体住址 */ + houseAddress?: string; } export interface ResidentForm extends BaseEntity { @@ -119,7 +122,7 @@ export interface ResidentForm extends BaseEntity { /** * 房屋表id */ - houseId?: string | number; + houseId?: number; /** * 0审核中 1 已认证 @@ -143,68 +146,24 @@ export interface ResidentForm extends BaseEntity { } export interface ResidentQuery extends PageQuery { - /** - * 住户编号 - */ - code?: number; - - /** - * 姓名 - */ - name?: string; - - /** - * 0业主 1租户 - */ - type?: number; - - /** - * 0 男性 1女性 - */ - gender?: number; - - /** - * 身份证号 - */ - idCard?: string | number; - - /** - * 手机号码 - */ - phone?: number; - - /** - * 小区id - */ - villageId?: string | number; - - /** - * 楼栋id - */ - buildingId?: string | number; - - /** - * 房屋表id - */ - houseId?: string | number; - - /** - * 0审核中 1 已认证 - */ - status?: number; - - /** - * 身份证正面照url - */ - cardImageFront?: string; - - /** - * 身份证背面照url - */ - cardImageBack?: string; - /** * 日期范围参数 */ - params?: any; + date?: any; + + /** + * 住户类型 + * 0业主 1租户 + */ + type: 0 | 1; + /** + * 住户状态 + * 0审核中 1 已认证 + */ + status: 0 | 1; + + houseId: number; + villageId: number; + buildingId: number; + unitNo: number; } diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss index 200a7a4..6fe008d 100644 --- a/src/assets/styles/index.scss +++ b/src/assets/styles/index.scss @@ -106,7 +106,9 @@ li { .inlineBlock { display: block; } - +.flex-column { + flex-direction: column; +} .clearfix { &:after { visibility: hidden; diff --git a/src/types/global.d.ts b/src/types/global.d.ts index cd4a9f4..0db890e 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -80,7 +80,6 @@ declare global { declare interface PageData { form: T; queryParams: D; - rules: ElFormRules; } /** * 分页查询参数 diff --git a/src/views/system/resident/ResidentMain.vue b/src/views/system/resident/ResidentMain.vue new file mode 100644 index 0000000..0416263 --- /dev/null +++ b/src/views/system/resident/ResidentMain.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/system/resident/addResident.vue b/src/views/system/resident/addResident.vue new file mode 100644 index 0000000..b86796b --- /dev/null +++ b/src/views/system/resident/addResident.vue @@ -0,0 +1,372 @@ + + + + + diff --git a/src/views/system/resident/index.ts b/src/views/system/resident/index.ts new file mode 100644 index 0000000..880a2ba --- /dev/null +++ b/src/views/system/resident/index.ts @@ -0,0 +1,136 @@ +interface Tree { + label: string; + value: number; + type: string; + children?: Tree[]; +} + +/** + * 楼栋/单元/房屋 转 Tree 结构(跳过楼层) + * @param buildings 原始楼栋数组 + * @returns Tree[] + */ +export function convertBuildingToTree(buildings: any[]): Tree[] { + if (!buildings || !Array.isArray(buildings)) return []; + + return buildings.map((building) => { + // 1. 楼栋 + const buildingTree: Tree = { + label: building.buildingName || '未知楼栋', + type: 'buildingId', + value: building.buildingId, + children: [] + }; + + // 2. 单元 + const units = building.units || []; + const unitTrees = units.map((unit: any) => { + const unitTree: Tree = { + label: `${unit.unitNo} 单元`, + value: unit.unitNo, + type: 'unitNo', + children: [] + }; + + // ====================== 关键修改 ====================== + // 直接从 floors 里把所有 house 全部抽出来,跳过 floor 层级 + const allHouses: any[] = []; + const floors = unit.floors || []; + + floors.forEach((floor: any) => { + const houses = floor.houses || []; + allHouses.push(...houses); // 把所有房屋合并到一个数组 + }); + + // 房屋直接挂在单元下 + unitTree.children = allHouses.map((house: any) => ({ + label: house.houseNo || '未知房屋', + value: house.houseId, + type: 'houseId' + })); + // ====================================================== + + return unitTree; + }); + + buildingTree.children = unitTrees; + console.log(buildingTree); + return buildingTree; + }); +} + +// 证件类型 +const idCardTypelist = [{}]; + +// 与业主关系 +export const ownerRelationshiplist = [ + { + label: '业主', + value: 0 + }, + { + label: '亲属', + value: 1 + }, + { + label: '租户', + value: 2 + } +]; + +interface Tree { + label: string; + value: number; + type: string; + children?: Tree[]; +} +// 只允许 字符串/数字 类型的 key +type ValidTreeKey = { + [K in keyof Tree]: Tree[K] extends string | number ? K : never; +}[keyof Tree]; + +/** + * 根据 houseId 查找完整路径(楼栋 > 单元 > 楼层 > 房屋) + * @param treeData 转换后的树形数据 + * @param houseId 目标房屋ID + * @returns string[] 路径数组,如 ['1号楼', '1单元', '3层', '301'] + */ +export function getHousePathById(treeData: Tree[], houseId: number, response: ValidTreeKey = 'value'): (string | number)[] { + const path: (string | number)[] = []; + + // 递归查找 + function findNode(nodes: Tree[]): boolean { + for (const node of nodes) { + path.push(node[response]); // 把当前节点加入路径 + + // 找到目标房屋 + if (node.type === 'houseId' && node.value === houseId) { + return true; + } + + // 递归子节点 + if (node.children && node.children.length > 0) { + if (findNode(node.children)) { + return true; + } + } + + path.pop(); // 回溯,移除当前节点 + } + return false; + } + + findNode(treeData); + return path; +} + +/** + * 验证身份证号码(18位,支持尾号x/X) + * @param idCard 身份证号 + * @return {boolean} true 符合 false 不符合 + */ +export function validateIdCard(idCard: string): boolean { + // 18位身份证正则 + const reg = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/; + return reg.test(idCard.trim()); +} diff --git a/src/views/system/resident/index.vue b/src/views/system/resident/index.vue index 117a63d..c041083 100644 --- a/src/views/system/resident/index.vue +++ b/src/views/system/resident/index.vue @@ -1,32 +1,27 @@ @@ -311,8 +349,48 @@ onMounted(() => { display: flex; align-items: center; .treebox { - width: 300px; + width: 250px; margin-right: 10px; + .treeTitlebox { + height: 60px; + line-height: 60px; + padding-left: 20px; + font-size: 18px; + font-weight: 600; + background-color: rgba(233, 242, 255, 0.5); + color: rgba(16, 16, 16, 1); + } + .treeboxbody { + margin-top: 10px; + + &:deep(.el-tree-node__content) { + margin-bottom: 5px; + height: 35px; + line-height: 35px; + .el-tree-node__expand-icon { + font-size: 18px; + } + &:hover { + background: #d1e3ff; + .el-text { + color: #227aff; + } + .el-tree-node__expand-icon { + color: #227aff; + } + } + } + } + } + + .tablebox { + height: calc(100% - 260px); + max-height: calc(100% - 260px); + /* 空数据也不会无限变宽 */ + :deep(.el-table__empty-block) { + width: 100% !important; + max-width: 100% !important; + } } } diff --git a/src/views/system/storeroom/index.vue b/src/views/system/storeroom/index.vue index dd308a0..9bc97c9 100644 --- a/src/views/system/storeroom/index.vue +++ b/src/views/system/storeroom/index.vue @@ -63,8 +63,6 @@ - -