mirror of
http://183.237.82.114:10086/kilo/leaser_front.git
synced 2026-10-23 19:35:25 +00:00
feat: 系统配置项目设置
This commit is contained in:
parent
bcecfc6846
commit
08700f48da
3 changed files with 387 additions and 1 deletions
|
|
@ -143,6 +143,10 @@ export interface UpdateUserRoleParam {
|
|||
export type SafeDefaultPage = 1 | 2 | 3; // 默认登录页:1工作台 2项目管理 3房源剖视
|
||||
export type SafeLoginTimeType = 1 | 2 | 3 | 4; // 登录状态保存时间:1:7天, 2:1天, 3:12小时, 4:1小时
|
||||
export type SafeMoreLogin = 1 | 2; // 多点登录支持:1支持 2不支持
|
||||
export type DefaultPriceType = 1 | 2; // 默认单价:1 元/㎡*月 , 2 元/㎡*天
|
||||
export type AreaAccuracyType = 1 | 2 | 3; // 面积精度:1:两位数,2:1位数,3:整数
|
||||
export type ExpireSoonType = 1 | 2 | 3; // 房源即将到期设置:1:30天,2:60天,3:90天
|
||||
export type CumulativeDayType = 1 | 2 | 3 | 4; // 累计出租率天数类型:1:按本年累计天数计算(从1月1日至今),2:按 本年整年天数 计算(本年:365天),3:按 本月累计天数 计算(从本月1日至今),4:按 本月整月天数 计算(本月:31天)
|
||||
|
||||
export interface SafeParams {
|
||||
default_url_typee: SafeDefaultPage;
|
||||
|
|
@ -158,6 +162,32 @@ export interface SafeInfo {
|
|||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface SettingProjectParam {
|
||||
default_price_type: DefaultPriceType;
|
||||
area_accuracy_type: AreaAccuracyType;
|
||||
expire_soon_type: ExpireSoonType;
|
||||
rent_rate_type: number; // 出租率:1:在租面积 / 总可出租面积 * 100 = 出租率
|
||||
rent_area_type: string; // 在租面积定义:1:合同起始日期,2:合同免租期,3:合同装修期,4:房源保留 (ps:1,2 以逗号隔开)
|
||||
rentable_area_type: string; // 总可出租面积定义:1:房源招商,2:房源保留,3:房源已到期,4:房源下架 (ps:1,2 以逗号隔开)
|
||||
cumulative_rent_rate_type: number; // 累计出租率:1:∑(在租面积 × 在租天数) / ∑(可出租面积 × 可出租天数) = 累计出租率
|
||||
cumulative_day_type: CumulativeDayType;
|
||||
}
|
||||
export interface projectSettingInfo {
|
||||
id: number;
|
||||
systemTenantId: number; // 租户id
|
||||
defaultPriceType: DefaultPriceType;
|
||||
areaAccuracyType: AreaAccuracyType;
|
||||
expireSoonType: ExpireSoonType;
|
||||
rentRateType: number; // 出租率:1:在租面积 / 总可出租面积 * 100 = 出租率
|
||||
rentAreaType: string; // 在租面积定义:1:合同起始日期,2:合同免租期,3:合同装修期,4:房源保留 (ps:1,2 以逗号隔开)
|
||||
rentableAreaType: string; // 总可出租面积定义:1:房源招商,2:房源保留,3:房源已到期,4:房源下架 (ps:1,2 以逗号隔开)
|
||||
cumulativeRentRateType: number; // 累计出租率:1:∑(在租面积 × 在租天数) / ∑(可出租面积 × 可出租天数) = 累计出租率
|
||||
cumulativeDayType: CumulativeDayType;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
// ==================== 响应类型别名 ====================
|
||||
export type DepartmentFormRes = HttpResponse<DepartmentIdData>;
|
||||
export type DepartmentList = DepartmentItem[];
|
||||
|
|
@ -173,6 +203,9 @@ export type RoleListRes = HttpResponse<RoleList>;
|
|||
export type PermissionRes = HttpResponse<UserPermissionItem>;
|
||||
export type RolePermissionRes = HttpResponse<UserPermissionItemList>;
|
||||
export type SafeInfoRes = HttpResponse<{ safeSetting: SafeInfo }>;
|
||||
export type SettingProjectRes = HttpResponse<{
|
||||
projectSetting: projectSettingInfo;
|
||||
}>;
|
||||
|
||||
// ==================== 部门相关 API ====================
|
||||
export function createDepartment(
|
||||
|
|
@ -291,3 +324,13 @@ export function getSafeSettingInfo(): Promise<SafeInfoRes> {
|
|||
export function saveSafeSetting(params: SafeParams): Promise<HttpResponse> {
|
||||
return axios.post('setting/saveSafeSetting', params);
|
||||
}
|
||||
// 项目设置信息
|
||||
export function getProjectSetting(): Promise<SettingProjectRes> {
|
||||
return axios.get('setting/getProjectSetting');
|
||||
}
|
||||
// 项目设置信息保存
|
||||
export function saveProjectSetting(
|
||||
params: SettingProjectParam
|
||||
): Promise<HttpResponse> {
|
||||
return axios.post('setting/saveProjectSetting', params);
|
||||
}
|
||||
|
|
|
|||
59
src/views/setting/system/project-settings/contrant.ts
Normal file
59
src/views/setting/system/project-settings/contrant.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
const projectSetting = [
|
||||
{ id: 1, text: '项目与房源' },
|
||||
{ id: 2, text: '出租率' },
|
||||
{ id: 3, text: '累计出租率' },
|
||||
];
|
||||
const projectHouse = [
|
||||
{
|
||||
title: '默认单价',
|
||||
options: [
|
||||
{ type: 1, label: '元/㎡*月' },
|
||||
{ type: 2, label: '元/㎡*天' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '面积精度',
|
||||
options: [
|
||||
{ type: 1, label: '2位数' },
|
||||
{ type: 2, label: '1位数' },
|
||||
{ type: 3, label: '整数' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '房源即将到期设置',
|
||||
options: [
|
||||
{ type: 1, label: '30' },
|
||||
{ type: 2, label: '60' },
|
||||
{ type: 3, label: '90' },
|
||||
],
|
||||
},
|
||||
];
|
||||
// 在租面积
|
||||
const inRentedAreaOptions = [
|
||||
{ value: '1', label: '合同起始日期' },
|
||||
{ value: '2', label: '合同免租期' },
|
||||
{ value: '3', label: '合同装修期' },
|
||||
{ value: '4', label: '房源保留' },
|
||||
];
|
||||
// 可租面积
|
||||
const availableAreaOptions = [
|
||||
{ value: '1', label: '房源招商' },
|
||||
{ value: '2', label: '房源保留' },
|
||||
{ value: '3', label: '房源保留' },
|
||||
{ value: '4', label: '房源下架' },
|
||||
];
|
||||
// 天数定义
|
||||
const dayeDfinition = [
|
||||
{ value: 1, label: '按本年累计天数计算(从1月1日至今)' },
|
||||
{ value: 2, label: '按本年整年天数 计算(本年:365天)' },
|
||||
{ value: 3, label: '按本月累计天数 计算(从本月1日至今)' },
|
||||
{ value: 4, label: '按本月整月天数 计算(本月:31天)' },
|
||||
];
|
||||
|
||||
export {
|
||||
projectSetting,
|
||||
projectHouse,
|
||||
inRentedAreaOptions,
|
||||
availableAreaOptions,
|
||||
dayeDfinition,
|
||||
};
|
||||
|
|
@ -1,3 +1,287 @@
|
|||
<template>
|
||||
<div> Data Dictionary </div>
|
||||
<div class="system-setting-general">
|
||||
<Breadcrumb
|
||||
:items="['menu.setting', 'menu.setting.system', 'setting.general']"
|
||||
/>
|
||||
<a-card class="full_height" :title="t('setting.project')">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="6">
|
||||
<ul class="project_setting_list">
|
||||
<li
|
||||
v-for="item in projectSetting"
|
||||
:key="item.id"
|
||||
:class="[
|
||||
'project_setting_item',
|
||||
{ isChoose: projectSettingId === item.id },
|
||||
]"
|
||||
@click="chooseProjectSetting(item.id)"
|
||||
>
|
||||
{{ item.text }}
|
||||
</li>
|
||||
</ul>
|
||||
</a-col>
|
||||
<a-col :span="18">
|
||||
<a-card v-if="projectSettingInfoData" :title="cardTitle">
|
||||
<template #extra>
|
||||
<a-button type="primary" @click="handleSaveSafe">保存</a-button>
|
||||
</template>
|
||||
<ul v-if="projectSettingId === 1" class="project_house_list">
|
||||
<li
|
||||
v-for="(item, index) in projectHouse"
|
||||
:key="index"
|
||||
class="project_house_item"
|
||||
>
|
||||
<h4>{{ item.title }}</h4>
|
||||
<ul class="options">
|
||||
<li
|
||||
v-for="(subItem, subIndex) in item.options"
|
||||
:key="subIndex"
|
||||
:class="[
|
||||
'subItem',
|
||||
{ isActive: isActiveOption(index, subItem.type) },
|
||||
]"
|
||||
@click="onOptionClick(index, subItem.type)"
|
||||
>
|
||||
{{ subItem.label }}</li
|
||||
>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-if="projectSettingId === 2" class="in_rented_area">
|
||||
<h3 class="title">出租率(瞬时出租率)</h3>
|
||||
<p class="tips">用于衡量某一时刻资产的出租情况。</p>
|
||||
<p class="desc"
|
||||
>在租面积 / (可租面积 + 在租面积) * 100% = 出租率</p
|
||||
>
|
||||
<h4 class="title_item">在租面积定义</h4>
|
||||
<a-checkbox-group
|
||||
v-model="rentAreaTypeArr"
|
||||
:options="inRentedAreaOptions"
|
||||
/>
|
||||
<h4 class="title_item">可租面积定义</h4>
|
||||
<a-checkbox-group
|
||||
v-model="rentableAreaTypeArr"
|
||||
:options="availableAreaOptions"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="projectSettingId === 3" class="cumulative_leasing_rate">
|
||||
<h3 class="title">累计出租率(时空加权出租率)</h3>
|
||||
<p class="tips"
|
||||
>在选定时间段内,项目中房源所出租天数与总面积总天数的比值。用于衡量项目整体的出租效率。</p
|
||||
>
|
||||
<p class="desc"
|
||||
>∑(在租面积 × 在租天数) / [ (可租面积 + 在租面积) × 天数定义 ] =
|
||||
累计出租率
|
||||
</p>
|
||||
<h4 class="title_item">天数定义</h4>
|
||||
<a-radio-group
|
||||
v-model="projectSettingInfoData.cumulativeDayType"
|
||||
direction="vertical"
|
||||
>
|
||||
<a-radio
|
||||
v-for="(item, index) in dayeDfinition"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
<a-popover v-if="index === 0">
|
||||
{{ item.label }}<icon-question-circle />
|
||||
<template #content>
|
||||
<p
|
||||
>按本年整年天数计算,适用年度指标达成率(预测+实际),反映全年“达标率”基准用于预测。</p
|
||||
>
|
||||
</template>
|
||||
</a-popover>
|
||||
<template v-else>
|
||||
{{ item.label }}
|
||||
</template>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {
|
||||
getProjectSetting,
|
||||
projectSettingInfo,
|
||||
saveProjectSetting,
|
||||
} from '@/api/setting';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import {
|
||||
projectSetting,
|
||||
projectHouse,
|
||||
inRentedAreaOptions,
|
||||
availableAreaOptions,
|
||||
dayeDfinition,
|
||||
} from './contrant';
|
||||
|
||||
const { t } = useI18n();
|
||||
const projectSettingId = ref<number>(1);
|
||||
const projectSettingInfoData = ref<projectSettingInfo | null>(null);
|
||||
const rentAreaTypeArr = ref<string[] | null>(null);
|
||||
const rentableAreaTypeArr = ref<string[] | null>(null);
|
||||
|
||||
const getProjectSettingData = async () => {
|
||||
try {
|
||||
const { code, data } = await getProjectSetting();
|
||||
if (code === 200 && data) {
|
||||
projectSettingInfoData.value = data?.projectSetting;
|
||||
const { rentAreaType, rentableAreaType } = projectSettingInfoData.value;
|
||||
rentAreaTypeArr.value = rentAreaType ? rentAreaType.split(',') : [];
|
||||
rentableAreaTypeArr.value = rentableAreaType
|
||||
? rentableAreaType.split(',')
|
||||
: [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
const chooseProjectSetting = (id: number) => {
|
||||
if (id === projectSettingId.value) return;
|
||||
projectSettingId.value = id;
|
||||
};
|
||||
const isActiveOption = (itemIndex: number, type: number) => {
|
||||
if (!projectSettingInfoData.value) return false;
|
||||
if (itemIndex === 0)
|
||||
return projectSettingInfoData.value.defaultPriceType === type;
|
||||
if (itemIndex === 1)
|
||||
return projectSettingInfoData.value.areaAccuracyType === type;
|
||||
if (itemIndex === 2)
|
||||
return projectSettingInfoData.value.expireSoonType === type;
|
||||
return false;
|
||||
};
|
||||
const onOptionClick = (itemIndex: number, type: any) => {
|
||||
if (!projectSettingInfoData.value) return;
|
||||
if (itemIndex === 0) projectSettingInfoData.value.defaultPriceType = type;
|
||||
if (itemIndex === 1) projectSettingInfoData.value.areaAccuracyType = type;
|
||||
if (itemIndex === 2) projectSettingInfoData.value.expireSoonType = type;
|
||||
};
|
||||
const cardTitle = computed(() => {
|
||||
switch (projectSettingId.value) {
|
||||
case 1:
|
||||
return '项目与房源';
|
||||
case 2:
|
||||
return '出租率';
|
||||
case 3:
|
||||
return '累计出租率';
|
||||
default:
|
||||
return '项目与房源';
|
||||
}
|
||||
});
|
||||
const handleSaveSafe = async () => {
|
||||
try {
|
||||
if (projectSettingInfoData.value) {
|
||||
const params = {
|
||||
default_price_type: projectSettingInfoData.value.defaultPriceType,
|
||||
area_accuracy_type: projectSettingInfoData.value.areaAccuracyType,
|
||||
expire_soon_type: projectSettingInfoData.value.expireSoonType,
|
||||
rent_rate_type: 1,
|
||||
rent_area_type: rentAreaTypeArr.value
|
||||
? rentAreaTypeArr.value.join(',')
|
||||
: '',
|
||||
rentable_area_type: rentableAreaTypeArr.value
|
||||
? rentableAreaTypeArr.value.join(',')
|
||||
: '',
|
||||
cumulative_rent_rate_type: 1,
|
||||
cumulative_day_type: projectSettingInfoData.value.cumulativeDayType,
|
||||
};
|
||||
const { code, data, message } = await saveProjectSetting(params);
|
||||
if (code === 200 && data) {
|
||||
Message.success(message);
|
||||
getProjectSettingData();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
getProjectSettingData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.system-setting-general {
|
||||
.project_setting_list {
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(239, 239, 239, 1);
|
||||
padding: 14px 0;
|
||||
padding-bottom: 200px;
|
||||
|
||||
.project_setting_item {
|
||||
padding: 0 20px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
|
||||
&.isChoose {
|
||||
background-color: #efefef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project_house_list {
|
||||
.project_house_item {
|
||||
margin-top: 20px;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f2f3f5;
|
||||
width: 430px;
|
||||
height: 36px;
|
||||
margin-top: 10px;
|
||||
padding: 0 3px;
|
||||
|
||||
.subItem {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 4px 0;
|
||||
cursor: pointer;
|
||||
|
||||
&.isActive {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.in_rented_area,
|
||||
.cumulative_leasing_rate {
|
||||
.tips {
|
||||
color: rgba(187, 187, 187, 1);
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
background-color: #eaf3fe;
|
||||
border-radius: 2px;
|
||||
background-color: rgba(232, 243, 255, 1);
|
||||
color: rgba(29, 33, 41, 1);
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
border: 0px solid rgba(121, 121, 121, 1);
|
||||
padding: 12px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.title_item {
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue