mirror of
http://183.237.82.114:10086/kilo/leaser_front.git
synced 2026-10-23 18:35:08 +00:00
feat: 项目管理列表筛选
This commit is contained in:
parent
52102d2e72
commit
194e0faa72
7 changed files with 324 additions and 12 deletions
|
|
@ -53,6 +53,7 @@ module.exports = {
|
|||
'@typescript-eslint/no-unused-vars': 1,
|
||||
'@typescript-eslint/no-empty-function': 1,
|
||||
'@typescript-eslint/no-explicit-any': 0, // 改为警告
|
||||
'no-unused-expressions': 'off',
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 2 : 1, // 生产环境禁用console
|
||||
'import/extensions': [
|
||||
2,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
CreateProjectParam,
|
||||
ProjectDetailRes,
|
||||
} from '@/types/business';
|
||||
import { ProjectPaginationParams } from '@/types/comm';
|
||||
import { ProjectPaginationParams, CommonCityRes } from '@/types/comm';
|
||||
import { HttpResponse } from './interceptor';
|
||||
// import type { RouteRecordNormalized } from 'vue-router';
|
||||
// import { UserState } from '@/store/modules/user/types';
|
||||
|
|
@ -42,3 +42,7 @@ export function updateProject(
|
|||
): Promise<HttpResponse> {
|
||||
return axios.post('project/updateProject', params);
|
||||
}
|
||||
// 全部项目的城市列表
|
||||
export function getProjectCityList(): Promise<CommonCityRes> {
|
||||
return axios.get(`project/getCityList`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,16 @@ export interface AllProjectsItem {
|
|||
name: string; // 项目名称
|
||||
buildings: BuildingItem[];
|
||||
}
|
||||
export interface RoomItem {
|
||||
id?: number;
|
||||
projectId: number;
|
||||
name: string;
|
||||
buildingName: string;
|
||||
rentArea: number;
|
||||
RentAreaStr: string;
|
||||
status: number;
|
||||
statusStr: string;
|
||||
}
|
||||
export interface ProjectItem extends BaseEntity {
|
||||
systemTenantId?: number;
|
||||
name: string; // 项目名称
|
||||
|
|
@ -33,6 +43,7 @@ export interface ProjectItem extends BaseEntity {
|
|||
isDelete: DeleteStatus;
|
||||
status: UserStatus;
|
||||
imageUrls: string[];
|
||||
signedPutURL: string[];
|
||||
typeName: string; // 类型名称
|
||||
district: string;
|
||||
province: string;
|
||||
|
|
@ -44,7 +55,13 @@ export interface ProjectItem extends BaseEntity {
|
|||
rentRate: number;
|
||||
RoomAreaStr: string; // 列表显示的计租面积
|
||||
RentAreaStr: string; // 列表显示的招商面积
|
||||
keepAreaStr?: string; // 列表显示的招商面积
|
||||
RentRateStr: string; // 列表显示的出租率
|
||||
buildings?: BuildingItem[]; // 楼栋数据
|
||||
rooms?: RoomItem[];
|
||||
roomsNum?: number;
|
||||
roomsRentNum?: number;
|
||||
roomsUnRentNum?: number;
|
||||
}
|
||||
|
||||
export type AllProjectListRes = HttpResponse<{
|
||||
|
|
@ -95,5 +112,5 @@ export interface ProjectInfo extends BaseEntity {
|
|||
}
|
||||
|
||||
export type ProjectDetailRes = HttpResponse<{
|
||||
project: ProjectInfo;
|
||||
project: ProjectItem;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export interface CommonProvinceItem {
|
|||
code: string; // 编码
|
||||
}
|
||||
export interface CommonCityItem extends CommonProvinceItem {
|
||||
ProvinceId: number; // 所属省份id
|
||||
ProvinceId?: number; // 所属省份id
|
||||
}
|
||||
export interface CommonDistrictItem extends CommonProvinceItem {
|
||||
CityId: number; // 所属城市id
|
||||
|
|
|
|||
46
src/views/business/project/drawer/project-info-drawer.vue
Normal file
46
src/views/business/project/drawer/project-info-drawer.vue
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
:width="1000"
|
||||
:visible="visible"
|
||||
title="项目详情"
|
||||
:footer="false"
|
||||
unmount-on-close
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
项目详情
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, onMounted } from 'vue';
|
||||
// import { Message } from '@arco-design/web-vue';
|
||||
// import { projectTypeList } from '@/utils/constant';
|
||||
import { ProjectItem } from '@/types/business';
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
projectId: number | null;
|
||||
detailInfo: ProjectItem | null;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void;
|
||||
}>();
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
async (val) => {
|
||||
console.log(val, 'val');
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(label.arco-form-item-label) {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
187
src/views/business/project/drawer/project-list-filter-drawer.vue
Normal file
187
src/views/business/project/drawer/project-list-filter-drawer.vue
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
:width="420"
|
||||
:visible="visible"
|
||||
title="筛选"
|
||||
unmount-on-close
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<p class="label">项目类型</p>
|
||||
<ul class="list">
|
||||
<li
|
||||
v-for="item in projectTypeList"
|
||||
:key="item.value"
|
||||
:class="['item', { isCheck: projectTypeChecked.includes(item.value) }]"
|
||||
@click="handleCheckTypeIds(item.value)"
|
||||
>
|
||||
{{ item.text }}
|
||||
</li>
|
||||
</ul>
|
||||
<p class="label">项目位置</p>
|
||||
<ul class="list">
|
||||
<li
|
||||
v-for="item in projectCityList"
|
||||
:key="item.id"
|
||||
:class="[
|
||||
'item',
|
||||
{
|
||||
isCheck:
|
||||
typeof item.id === 'number'
|
||||
? projectCityChecked.includes(item.id)
|
||||
: false,
|
||||
},
|
||||
]"
|
||||
@click="handleCheckCityIds(item.id)"
|
||||
>
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
<p class="label">出租率</p>
|
||||
<div class="slider">
|
||||
<a-slider
|
||||
v-model="rentRate"
|
||||
:min="0"
|
||||
:max="100"
|
||||
range
|
||||
:marks="marks"
|
||||
></a-slider>
|
||||
</div>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { getProjectCityList } from '@/api/business';
|
||||
import { CommonCityItem } from '@/types/comm';
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void;
|
||||
(
|
||||
e: 'confirm',
|
||||
payload: {
|
||||
typeIds: number[] | null;
|
||||
cityIds: number[] | null;
|
||||
rentRate: number | number[];
|
||||
}
|
||||
): void;
|
||||
}>();
|
||||
const projectTypeChecked = ref<number[]>([0]);
|
||||
const projectCityChecked = ref<number[]>([0]);
|
||||
const rentRate = ref<number | number[]>(0);
|
||||
const projectTypeList = [
|
||||
{ text: '全部', value: 0 },
|
||||
{ text: '写字楼', value: 1 },
|
||||
{ text: '园区', value: 2 },
|
||||
{ text: '商业综合体', value: 3 },
|
||||
];
|
||||
const marks = {
|
||||
0: '0%',
|
||||
100: '100%',
|
||||
};
|
||||
const projectCityList = ref<CommonCityItem[]>([]);
|
||||
const getProjectCityListData = async () => {
|
||||
const { code, data } = await getProjectCityList();
|
||||
if (code === 200 && data) {
|
||||
projectCityList.value = Array.isArray(data.cityList) ? data.cityList : [];
|
||||
projectCityList.value.unshift({ id: 0, code: '0', name: '全部' });
|
||||
}
|
||||
};
|
||||
const handleCheckTypeIds = (id: number) => {
|
||||
if (typeof id !== 'number') return;
|
||||
if (id === 0) {
|
||||
projectTypeChecked.value = [0];
|
||||
} else {
|
||||
if (projectTypeChecked.value.includes(0)) {
|
||||
projectTypeChecked.value = [];
|
||||
}
|
||||
if (projectTypeChecked.value.includes(id)) {
|
||||
projectTypeChecked.value = projectTypeChecked.value.filter(
|
||||
(i) => i !== id
|
||||
);
|
||||
} else {
|
||||
projectTypeChecked.value.push(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
const handleCheckCityIds = (id: any) => {
|
||||
if (typeof id !== 'number') return;
|
||||
if (id === 0) {
|
||||
// 点击 "全部" => 清空并只保留 0
|
||||
projectCityChecked.value = [0];
|
||||
} else {
|
||||
// 如果当前包含 "全部",先去掉
|
||||
if (projectCityChecked.value.includes(0)) {
|
||||
projectCityChecked.value = [];
|
||||
}
|
||||
if (projectCityChecked.value.includes(id)) {
|
||||
projectCityChecked.value = projectCityChecked.value.filter(
|
||||
(i) => i !== id
|
||||
);
|
||||
} else {
|
||||
projectCityChecked.value.push(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
const normalizeIds = (ids: number[]) =>
|
||||
ids.length === 1 && ids[0] === 0 ? null : ids;
|
||||
const handleOk = () => {
|
||||
emit('confirm', {
|
||||
typeIds: normalizeIds(projectTypeChecked.value),
|
||||
cityIds: normalizeIds(projectCityChecked.value),
|
||||
rentRate: rentRate.value,
|
||||
});
|
||||
handleCancel();
|
||||
};
|
||||
watch(
|
||||
() => props.visible,
|
||||
async (val) => {
|
||||
if (val && projectCityList.value.length === 0) {
|
||||
getProjectCityListData();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(label.arco-form-item-label) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-top: 20px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.item {
|
||||
width: 100px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
margin-right: 12px;
|
||||
margin-top: 12px;
|
||||
text-align: center;
|
||||
background-color: #efefef;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&.isCheck {
|
||||
background-color: rgba(232, 243, 255, 1);
|
||||
color: rgba(22, 93, 255, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
:placeholder="t('please.enter', { placeholder: t('content') })"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<a-button>
|
||||
<a-button @click="handleFilter">
|
||||
<template #icon>
|
||||
<icon-filter />
|
||||
</template>
|
||||
|
|
@ -60,14 +60,30 @@
|
|||
</template>
|
||||
<template #operate="{ record }">
|
||||
<a-space>
|
||||
<a-button>查看</a-button>
|
||||
<a-button
|
||||
:loading="isLoadingDetail"
|
||||
@click="handleDetail(record.id)"
|
||||
>查看</a-button
|
||||
>
|
||||
<a-button
|
||||
:loading="isLoadingEdit"
|
||||
type="primary"
|
||||
@click="handleEditProject(record.id)"
|
||||
>编辑</a-button
|
||||
>
|
||||
<a-button>更多</a-button>
|
||||
<a-popover trigger="click" position="bottom">
|
||||
<a-button>{{ $t('more') }}</a-button>
|
||||
<template #content>
|
||||
<a-space direction="vertical">
|
||||
<a-button @click="handleWatchHouse(record.id)">
|
||||
查看房源
|
||||
</a-button>
|
||||
<a-button status="danger" @click="handleDel(record.id)">
|
||||
删除项目
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-popover>
|
||||
</a-space>
|
||||
</template>
|
||||
</DataTable>
|
||||
|
|
@ -76,6 +92,16 @@
|
|||
v-model:visible="showDrawer"
|
||||
:is-edit="isEdit"
|
||||
:record="currentProjectInfo"
|
||||
@submitted="getProjectListData"
|
||||
/>
|
||||
<projectInfoDrawer
|
||||
v-model:visible="showProjectInfoDrawer"
|
||||
:project-id="currentProjectId"
|
||||
:detail-info="currentProjectInfo"
|
||||
/>
|
||||
<projectListFilterDrawer
|
||||
v-model:visible="showListFilterDrawer"
|
||||
@confirm="handleFilterConfirm"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -86,17 +112,23 @@
|
|||
import { useI18n } from 'vue-i18n';
|
||||
import type { TableColumnData } from '@arco-design/web-vue';
|
||||
import useDataTable from '@/composables/useDataTable';
|
||||
import { ProjectItem, ProjectInfo } from '@/types/business';
|
||||
import { ProjectItem } from '@/types/business';
|
||||
import { getProjectList, getProjectDetail } from '@/api/business';
|
||||
import { ProjectPaginationParams, ProjectType } from '@/types/comm';
|
||||
import projectFormDrawer from './drawer/project-form-drawer.vue';
|
||||
import projectInfoDrawer from './drawer/project-info-drawer.vue';
|
||||
import projectListFilterDrawer from './drawer/project-list-filter-drawer.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { loading } = useLoading(false);
|
||||
const showDrawer = ref<boolean>(false);
|
||||
const showProjectInfoDrawer = ref<boolean>(false);
|
||||
const showListFilterDrawer = ref<boolean>(false);
|
||||
const currentProjectId = ref<number | null>(null);
|
||||
const isLoadingEdit = ref<boolean>(false);
|
||||
const isLoadingDetail = ref<boolean>(false);
|
||||
const isEdit = ref<boolean>(false);
|
||||
const currentProjectInfo = ref<ProjectInfo | null>(null);
|
||||
const currentProjectInfo = ref<ProjectItem | null>(null);
|
||||
const projectList = ref<ProjectItem[]>([]);
|
||||
const {
|
||||
data: renderData,
|
||||
|
|
@ -152,15 +184,33 @@
|
|||
}
|
||||
setLoading(false);
|
||||
};
|
||||
const getProjectDetailData = async (id: number) => {
|
||||
isLoadingEdit.value = true;
|
||||
const getProjectDetailData = async (id: number, edit: boolean) => {
|
||||
if (currentProjectInfo.value && currentProjectInfo.value?.id === id) return;
|
||||
edit ? (isLoadingEdit.value = true) : (isLoadingDetail.value = true);
|
||||
const { code, data } = await getProjectDetail(id);
|
||||
if (code === 200 && data) {
|
||||
currentProjectInfo.value = data.project;
|
||||
}
|
||||
isLoadingEdit.value = false;
|
||||
isLoadingDetail.value = false;
|
||||
};
|
||||
const handleWatchHouse = async (id: number) => {
|
||||
try {
|
||||
console.log(id, 'is id');
|
||||
} catch (error) {
|
||||
// 处理错误
|
||||
}
|
||||
};
|
||||
const handleFilterConfirm = ({ typeIds, cityIds, rentRate }) => {
|
||||
queryParams.value.type = typeIds;
|
||||
queryParams.value.province_ids = cityIds;
|
||||
queryParams.value.rent_rate_min = rentRate[0];
|
||||
queryParams.value.rent_rate_max = rentRate[1];
|
||||
getProjectListData();
|
||||
};
|
||||
const handleDel = (id: number) => {
|
||||
console.log(id, 'iiii');
|
||||
};
|
||||
|
||||
// 分页事件处理
|
||||
const onPageChange = (page: number) => {
|
||||
setCurrent(page);
|
||||
|
|
@ -177,12 +227,19 @@
|
|||
};
|
||||
const handleEditProject = async (id: number) => {
|
||||
isEdit.value = true;
|
||||
await getProjectDetailData(id);
|
||||
await getProjectDetailData(id, true);
|
||||
showDrawer.value = true;
|
||||
};
|
||||
const handleDetail = async (id: number) => {
|
||||
await getProjectDetailData(id, false);
|
||||
showProjectInfoDrawer.value = true;
|
||||
};
|
||||
const handleSearch = () => {
|
||||
getProjectListData();
|
||||
};
|
||||
const handleFilter = () => {
|
||||
showListFilterDrawer.value = true;
|
||||
};
|
||||
const getProjectTypeColor = (type: ProjectType) => {
|
||||
const typeMap = { 1: 'green', 2: 'red', 3: 'orange' };
|
||||
return typeMap[type];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue