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 SafeDefaultPage = 1 | 2 | 3; // 默认登录页:1工作台 2项目管理 3房源剖视
|
||||||
export type SafeLoginTimeType = 1 | 2 | 3 | 4; // 登录状态保存时间:1:7天, 2:1天, 3:12小时, 4:1小时
|
export type SafeLoginTimeType = 1 | 2 | 3 | 4; // 登录状态保存时间:1:7天, 2:1天, 3:12小时, 4:1小时
|
||||||
export type SafeMoreLogin = 1 | 2; // 多点登录支持:1支持 2不支持
|
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 {
|
export interface SafeParams {
|
||||||
default_url_typee: SafeDefaultPage;
|
default_url_typee: SafeDefaultPage;
|
||||||
|
|
@ -158,6 +162,32 @@ export interface SafeInfo {
|
||||||
createdAt?: string;
|
createdAt?: string;
|
||||||
updatedAt?: 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 DepartmentFormRes = HttpResponse<DepartmentIdData>;
|
||||||
export type DepartmentList = DepartmentItem[];
|
export type DepartmentList = DepartmentItem[];
|
||||||
|
|
@ -173,6 +203,9 @@ export type RoleListRes = HttpResponse<RoleList>;
|
||||||
export type PermissionRes = HttpResponse<UserPermissionItem>;
|
export type PermissionRes = HttpResponse<UserPermissionItem>;
|
||||||
export type RolePermissionRes = HttpResponse<UserPermissionItemList>;
|
export type RolePermissionRes = HttpResponse<UserPermissionItemList>;
|
||||||
export type SafeInfoRes = HttpResponse<{ safeSetting: SafeInfo }>;
|
export type SafeInfoRes = HttpResponse<{ safeSetting: SafeInfo }>;
|
||||||
|
export type SettingProjectRes = HttpResponse<{
|
||||||
|
projectSetting: projectSettingInfo;
|
||||||
|
}>;
|
||||||
|
|
||||||
// ==================== 部门相关 API ====================
|
// ==================== 部门相关 API ====================
|
||||||
export function createDepartment(
|
export function createDepartment(
|
||||||
|
|
@ -291,3 +324,13 @@ export function getSafeSettingInfo(): Promise<SafeInfoRes> {
|
||||||
export function saveSafeSetting(params: SafeParams): Promise<HttpResponse> {
|
export function saveSafeSetting(params: SafeParams): Promise<HttpResponse> {
|
||||||
return axios.post('setting/saveSafeSetting', params);
|
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>
|
<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>
|
</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