7/10 缴费分析,人员分析 数据对接
This commit is contained in:
@@ -1,65 +1,62 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = 智慧物业后台管理系统
|
VITE_APP_TITLE=智慧物业后台管理系统
|
||||||
|
|
||||||
VITE_APP_LOGO_TITLE = 智慧物业后台管理系统
|
VITE_APP_LOGO_TITLE=智慧物业后台管理系统
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
VITE_APP_ENV = 'development'
|
VITE_APP_ENV='development'
|
||||||
|
|
||||||
# 开发环境
|
# 开发环境
|
||||||
VITE_APP_BASE_API = '/dev-api'
|
VITE_APP_BASE_API='/dev-api'
|
||||||
# # 开发环境 接口代理地址
|
# # 开发环境 接口代理地址
|
||||||
VITE_APP_PROXY_API = 'http://192.168.1.222:8080'
|
VITE_APP_PROXY_API='http://192.168.1.222:8080'
|
||||||
# 开发环境 接口代理地址
|
# 开发环境 接口代理地址
|
||||||
# VITE_APP_PROXY_API = 'http://192.168.0.239:8080'
|
#VITE_APP_PROXY_API='http://192.168.1.6:8080'
|
||||||
# 图片基础地址
|
# 图片基础地址
|
||||||
VITE_IMG_URL = 'http://192.168.1.222:8080'
|
VITE_IMG_URL='http://192.168.1.222:8080'
|
||||||
|
|
||||||
# 应用访问路径 例如使用前缀 /admin/
|
# 应用访问路径 例如使用前缀 /admin/
|
||||||
VITE_APP_CONTEXT_PATH = '/'
|
VITE_APP_CONTEXT_PATH='/'
|
||||||
|
|
||||||
# 监控地址
|
# 监控地址
|
||||||
VITE_APP_MONITOR_ADMIN = 'http://192.168.1.215/admin/applications'
|
VITE_APP_MONITOR_ADMIN='http://192.168.1.215/admin/applications'
|
||||||
|
|
||||||
|
|
||||||
# SnailJob 控制台地址
|
# SnailJob 控制台地址
|
||||||
VITE_APP_SNAILJOB_ADMIN = 'http://192.168.1.215/snail-job'
|
VITE_APP_SNAILJOB_ADMIN='http://192.168.1.215/snail-job'
|
||||||
|
|
||||||
VITE_APP_PORT = 5173
|
VITE_APP_PORT=5173
|
||||||
|
|
||||||
# 登录成功跳转地址
|
# 登录成功跳转地址
|
||||||
# VITE_LOGIN_BACK_URL = '/equipment/WaterDevice'
|
# VITE_LOGIN_BACK_URL = '/equipment/WaterDevice'
|
||||||
VITE_LOGIN_BACK_URL = '/index'
|
VITE_LOGIN_BACK_URL='/index'
|
||||||
# 工作台正式内容:false 假内容:true
|
# 工作台正式内容:false 假内容:true
|
||||||
VITE_LOGIN_BACK_URL_WORKBENCH_TRUE= false
|
VITE_LOGIN_BACK_URL_WORKBENCH_TRUE=false
|
||||||
# 是否展示工作台
|
# 是否展示工作台
|
||||||
VITE_APP_SHOW_WORK_PLATFORM = true
|
VITE_APP_SHOW_WORK_PLATFORM=true
|
||||||
|
|
||||||
|
|
||||||
# 地图类型 天地图 WGS84 高德地图 GCJ02, 高德地图 需要在高德地图官网申请key
|
# 地图类型 天地图 WGS84 高德地图 GCJ02, 高德地图 需要在高德地图官网申请key
|
||||||
VITE_APP_MAP_TYPE = 'GCJ02'
|
VITE_APP_MAP_TYPE='GCJ02'
|
||||||
|
|
||||||
# 高德地图key 建议放入环境变量中,避免泄露
|
# 高德地图key 建议放入环境变量中,避免泄露
|
||||||
VITE_GCJ02_KEY_GD = '8e302fe1be5f4db62bc734db23dca149'
|
VITE_GCJ02_KEY_GD='8e302fe1be5f4db62bc734db23dca149'
|
||||||
VITE_GCJ02_JS_CODE_GD = '09534b3534d8da53968529a9ce164118'
|
VITE_GCJ02_JS_CODE_GD='09534b3534d8da53968529a9ce164118'
|
||||||
|
|
||||||
# 天地图key 建议放入环境变量中,避免泄露
|
# 天地图key 建议放入环境变量中,避免泄露
|
||||||
VITE_TIANDITU_KEY = 'f71689f9e22158947ebf64ad95e0a595'
|
VITE_TIANDITU_KEY='f71689f9e22158947ebf64ad95e0a595'
|
||||||
|
|
||||||
|
|
||||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||||
VITE_APP_ENCRYPT = true
|
VITE_APP_ENCRYPT=true
|
||||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
VITE_APP_RSA_PRIVATE_KEY='MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
||||||
|
|
||||||
# 客户端id
|
# 客户端id
|
||||||
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
VITE_APP_CLIENT_ID='e5cd7e4891bf95d1d19206ce24a7b32e'
|
||||||
|
|
||||||
# websocket 开关 默认使用sse推送
|
# websocket 开关 默认使用sse推送
|
||||||
VITE_APP_WEBSOCKET = false
|
VITE_APP_WEBSOCKET=false
|
||||||
|
|
||||||
# sse 开关
|
# sse 开关
|
||||||
VITE_APP_SSE = true
|
VITE_APP_SSE=true
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +1,58 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = 智慧物业后台管理系统
|
VITE_APP_TITLE=智慧物业后台管理系统
|
||||||
|
|
||||||
VITE_APP_LOGO_TITLE = 智慧物业后台管理系统
|
VITE_APP_LOGO_TITLE=智慧物业后台管理系统
|
||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
VITE_APP_ENV = 'production'
|
VITE_APP_ENV='production'
|
||||||
|
|
||||||
# 应用访问路径 例如使用前缀 /admin/
|
# 应用访问路径 例如使用前缀 /admin/
|
||||||
VITE_APP_CONTEXT_PATH = '/'
|
VITE_APP_CONTEXT_PATH='/'
|
||||||
|
|
||||||
# 监控地址
|
# 监控地址
|
||||||
VITE_APP_MONITOR_ADMIN = '/admin/applications'
|
VITE_APP_MONITOR_ADMIN='/admin/applications'
|
||||||
|
|
||||||
# SnailJob 控制台地址
|
# SnailJob 控制台地址
|
||||||
VITE_APP_SNAILJOB_ADMIN = '/snail-job'
|
VITE_APP_SNAILJOB_ADMIN='/snail-job'
|
||||||
|
|
||||||
# 生产环境
|
# 生产环境
|
||||||
# VITE_APP_BASE_API = 'https://wuyeapi.bugtc.com'
|
# VITE_APP_BASE_API = 'https://wuyeapi.bugtc.com'
|
||||||
VITE_APP_BASE_API = 'https://wuyeapi.ckdzkj.com'
|
VITE_APP_BASE_API='https://wuyeapi.ckdzkj.com'
|
||||||
|
|
||||||
# 登录成功跳转地址
|
# 登录成功跳转地址
|
||||||
# VITE_LOGIN_BACK_URL = '/equipment/WaterDevice'
|
# VITE_LOGIN_BACK_URL = '/equipment/WaterDevice'
|
||||||
VITE_LOGIN_BACK_URL = '/index'
|
VITE_LOGIN_BACK_URL='/index'
|
||||||
# 工作台正式内容:false 假内容:true
|
# 工作台正式内容:false 假内容:true
|
||||||
VITE_LOGIN_BACK_URL_WORKBENCH_TRUE= false
|
VITE_LOGIN_BACK_URL_WORKBENCH_TRUE=false
|
||||||
# 是否展示工作台
|
# 是否展示工作台
|
||||||
VITE_APP_SHOW_WORK_PLATFORM = true
|
VITE_APP_SHOW_WORK_PLATFORM=true
|
||||||
|
|
||||||
|
|
||||||
# 地图类型 天地图 WGS84 高德地图 GCJ02, 高德地图 需要在高德地图官网申请key
|
# 地图类型 天地图 WGS84 高德地图 GCJ02, 高德地图 需要在高德地图官网申请key
|
||||||
VITE_APP_MAP_TYPE = 'GCJ02'
|
VITE_APP_MAP_TYPE='GCJ02'
|
||||||
|
|
||||||
# 高德地图key 建议放入环境变量中,避免泄露
|
# 高德地图key 建议放入环境变量中,避免泄露
|
||||||
VITE_GCJ02_KEY_GD = '8e302fe1be5f4db62bc734db23dca149'
|
VITE_GCJ02_KEY_GD='8e302fe1be5f4db62bc734db23dca149'
|
||||||
VITE_GCJ02_JS_CODE_GD = '09534b3534d8da53968529a9ce164118'
|
VITE_GCJ02_JS_CODE_GD='09534b3534d8da53968529a9ce164118'
|
||||||
|
|
||||||
# 天地图key 建议放入环境变量中,避免泄露
|
# 天地图key 建议放入环境变量中,避免泄露
|
||||||
VITE_TIANDITU_KEY = 'f71689f9e22158947ebf64ad95e0a595'
|
VITE_TIANDITU_KEY='f71689f9e22158947ebf64ad95e0a595'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||||
# VITE_BUILD_COMPRESS = gzip
|
# VITE_BUILD_COMPRESS = gzip
|
||||||
|
|
||||||
VITE_APP_PORT = 80
|
VITE_APP_PORT=80
|
||||||
|
|
||||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||||
VITE_APP_ENCRYPT = true
|
VITE_APP_ENCRYPT=true
|
||||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
VITE_APP_RSA_PRIVATE_KEY='MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
||||||
|
|
||||||
# 客户端id
|
# 客户端id
|
||||||
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
VITE_APP_CLIENT_ID='e5cd7e4891bf95d1d19206ce24a7b32e'
|
||||||
|
|
||||||
# websocket 开关 默认使用sse推送
|
# websocket 开关 默认使用sse推送
|
||||||
VITE_APP_WEBSOCKET = false
|
VITE_APP_WEBSOCKET=false
|
||||||
|
|
||||||
# sse 开关
|
# sse 开关
|
||||||
VITE_APP_SSE = true
|
VITE_APP_SSE=true
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ export interface DecorationVO {
|
|||||||
* 所属房屋id
|
* 所属房屋id
|
||||||
*/
|
*/
|
||||||
houseId: string | number;
|
houseId: string | number;
|
||||||
|
buildingId: string;
|
||||||
|
unitNoId: string;
|
||||||
/**
|
/**
|
||||||
* 申请人姓名
|
* 申请人姓名
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -40,3 +40,110 @@ export const income_statsApi = (datetime?: string): AxiosPromise<IncomeStatsResp
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface sourceType {
|
||||||
|
'totalPayable': string;
|
||||||
|
'totalReceived': string;
|
||||||
|
'totalPending': string;
|
||||||
|
'parkingFee': string;
|
||||||
|
'parkingFeePercent': string;
|
||||||
|
'propertyFee': string;
|
||||||
|
'propertyFeePercent': string;
|
||||||
|
'utilityFee': string;
|
||||||
|
'utilityFeePercent': string;
|
||||||
|
'shopRent': string;
|
||||||
|
'shopRentPercent': string;
|
||||||
|
'repairFee': string;
|
||||||
|
'repairFeePercent': string;
|
||||||
|
'garbageFee': string;
|
||||||
|
'garbageFeePercent': string;
|
||||||
|
}
|
||||||
|
// 收入来源 --₧╬.╬
|
||||||
|
export const income_scourcApi = (datetime?: string): AxiosPromise<sourceType> => {
|
||||||
|
return request({
|
||||||
|
url: '/api/analysis/income/source',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
date: datetime
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export interface PayMentMethod {
|
||||||
|
'wechatAmount': string;
|
||||||
|
'wechatPercent': string;
|
||||||
|
'alipayAmount': string;
|
||||||
|
'alipayPercent': string;
|
||||||
|
'offlineAmount': string;
|
||||||
|
'offlinePercent': string;
|
||||||
|
}
|
||||||
|
// 缴费方式
|
||||||
|
export const payment_methodApi = (datetime?: string): AxiosPromise<PayMentMethod> => {
|
||||||
|
return request({
|
||||||
|
url: '/api/analysis/income/payment_method',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
date: datetime
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export interface Arrears_distrubution {
|
||||||
|
month: number;
|
||||||
|
amount: string;
|
||||||
|
}
|
||||||
|
// 欠费分布
|
||||||
|
export const arrears_distributionApi = (
|
||||||
|
datetime?: string
|
||||||
|
): AxiosPromise<{
|
||||||
|
items: Arrears_distrubution[];
|
||||||
|
}> => {
|
||||||
|
return request({
|
||||||
|
url: '/api/analysis/income/arrears_distribution',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
date: datetime
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export interface payment_sourceType {
|
||||||
|
'miniProgramAmount': string;
|
||||||
|
'miniProgramPercent': string;
|
||||||
|
'mobileAppAmount': string;
|
||||||
|
'mobileAppPercent': string;
|
||||||
|
'offlineAmount': string;
|
||||||
|
'offlinePercent': string;
|
||||||
|
}
|
||||||
|
// 缴费来源分析
|
||||||
|
export const payment_sourceApi = (datetime?: string): AxiosPromise<payment_sourceType> => {
|
||||||
|
return request({
|
||||||
|
url: '/api/analysis/income/payment_source',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
date: datetime
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface payment_trendType {
|
||||||
|
'date': string;
|
||||||
|
'paidAmount': string;
|
||||||
|
'unpaidAmount': string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 缴费走势分析
|
||||||
|
export const payment_trendApi = (startDate?: string, endDate?: string): AxiosPromise<{
|
||||||
|
items:payment_trendType[]
|
||||||
|
}> => {
|
||||||
|
return request({
|
||||||
|
url: '/api/analysis/income/payment_trend',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { AxiosPromise } from 'axios';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const user_movein_list = (query?: {
|
export const user_movein_list = (query?: {
|
||||||
datetime: string;
|
dateTime: string;
|
||||||
}): AxiosPromise<{
|
}): AxiosPromise<{
|
||||||
'villageId': string;
|
'villageId': string;
|
||||||
'villageName': string;
|
'villageName': string;
|
||||||
@@ -31,7 +31,7 @@ export const user_movein_list = (query?: {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const get_movein_user_type = (query?: {
|
export const get_movein_user_type = (query?: {
|
||||||
datetime: string;
|
dateTime: string;
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
'owner': string;
|
'owner': string;
|
||||||
'ownerRate': string;
|
'ownerRate': string;
|
||||||
@@ -56,7 +56,7 @@ export const get_movein_user_type = (query?: {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const get_movein_user_sex = (query?: {
|
export const get_movein_user_sex = (query?: {
|
||||||
datetime: string;
|
dateTime: string;
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
'man': number;
|
'man': number;
|
||||||
'woman': number;
|
'woman': number;
|
||||||
@@ -92,3 +92,22 @@ export const get_movein_moveout_list = (query?: {
|
|||||||
params: query
|
params: query
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const get_person_age = (query?: {
|
||||||
|
dateTime: string;
|
||||||
|
}): AxiosPromise<
|
||||||
|
{
|
||||||
|
'date': string;
|
||||||
|
'moveInCount': number;
|
||||||
|
'moveOutCount': number;
|
||||||
|
'totalCount': number;
|
||||||
|
}[]
|
||||||
|
> => {
|
||||||
|
return request({
|
||||||
|
url: '/gender/personAge',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export function listOss(query: OssQuery): AxiosPromise<OssVO[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询OSS对象基于id串
|
// 查询OSS对象基于id串
|
||||||
export function listByIds(ossId: string | number): AxiosPromise<OssVO[]> {
|
export function listByIds(ossId: string): AxiosPromise<OssVO[]> {
|
||||||
return request({
|
return request({
|
||||||
url: '/resource/oss/listByIds/' + ossId,
|
url: '/resource/oss/listByIds/' + ossId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export interface ResidentVO {
|
|||||||
*/
|
*/
|
||||||
userId: string;
|
userId: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
unitNoId: string;
|
||||||
/**
|
/**
|
||||||
* 住户编号
|
* 住户编号
|
||||||
*/
|
*/
|
||||||
@@ -79,6 +80,7 @@ export interface ResidentForm extends BaseEntity {
|
|||||||
* 主键 住户管理id
|
* 主键 住户管理id
|
||||||
*/
|
*/
|
||||||
userId?: string;
|
userId?: string;
|
||||||
|
unitNoId: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 住户编号
|
* 住户编号
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const fileAccept = computed(() => props.fileType.map((type) => `.${type}`).join(
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
async (val) => {
|
async (val:string) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
let temp = 1;
|
let temp = 1;
|
||||||
// 首先将值转为数组
|
// 首先将值转为数组
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
<el-table-column label="手机号码" align="center" prop="phone" />
|
<el-table-column label="手机号码" align="center" prop="phone" />
|
||||||
<el-table-column label="房间" show-overflow-tooltip align="center">
|
<el-table-column label="房间" show-overflow-tooltip align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
{{ row.housePath }}
|
{{ row.houseName }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -78,7 +78,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { listResident } from '@/api/system/resident';
|
import { listResident } from '@/api/system/resident';
|
||||||
import { ResidentVO } from '@/api/system/resident/type';
|
import { ResidentVO } from '@/api/system/resident/type';
|
||||||
import { getHousePathById } from '@/utils/house';
|
|
||||||
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
import { useHouseStore } from '@/store/modules/house';
|
||||||
|
|
||||||
@@ -235,12 +234,6 @@ function getlist() {
|
|||||||
listResident(queryParams.value)
|
listResident(queryParams.value)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
tableData.value = res.rows;
|
tableData.value = res.rows;
|
||||||
tableData.value.forEach((item) => {
|
|
||||||
if (item.houseId !== null) {
|
|
||||||
const houselist = getHousePathById(treedata.value, item.houseId, 'label');
|
|
||||||
item.housePath = houselist?.join('-') || '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
handleUserSelection();
|
handleUserSelection();
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ function isMapAvailable() {
|
|||||||
function fitMapView(overlays: any[]) {
|
function fitMapView(overlays: any[]) {
|
||||||
if (!isMapAvailable() || overlays.length === 0) return;
|
if (!isMapAvailable() || overlays.length === 0) return;
|
||||||
// 第二个参数true关闭动画,留白80px,最大缩放18级
|
// 第二个参数true关闭动画,留白80px,最大缩放18级
|
||||||
console.log(props.smallScroll);
|
|
||||||
map.value.setFitView(overlays, props.smallScroll);
|
map.value.setFitView(overlays, props.smallScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import { getNormalPath } from '@/utils/ruoyi';
|
|||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
import { usePermissionStore } from '@/store/modules/permission';
|
import { usePermissionStore } from '@/store/modules/permission';
|
||||||
import { useTagsViewStore } from '@/store/modules/tagsView';
|
import { useTagsViewStore } from '@/store/modules/tagsView';
|
||||||
import { RouteRecordRaw, RouteLocationNormalized } from 'vue-router';
|
import { RouteRecordRaw, RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
|
||||||
import { Back, CircleClose, Close, RefreshRight, Right } from '@element-plus/icons-vue';
|
import { Back, CircleClose, Close, RefreshRight, Right } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
@@ -181,7 +181,7 @@ const closeLeftTags = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
const closeOthersTags = () => {
|
const closeOthersTags = () => {
|
||||||
router.push(selectedTag.value).catch(() => {});
|
router.push(selectedTag.value as RouteLocationRaw).catch(() => {});
|
||||||
proxy?.$tab.closeOtherPage(selectedTag.value).then(() => {
|
proxy?.$tab.closeOtherPage(selectedTag.value).then(() => {
|
||||||
moveToCurrentTag();
|
moveToCurrentTag();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import SideBar from './components/Sidebar/index.vue';
|
|||||||
import { AppMain, Navbar, Settings } from './components';
|
import { AppMain, Navbar, Settings } from './components';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
// import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
||||||
import { initWebSocket } from '@/utils/websocket';
|
import { initWebSocket } from '@/utils/websocket';
|
||||||
import { initSSE } from '@/utils/sse';
|
import { initSSE } from '@/utils/sse';
|
||||||
|
|
||||||
@@ -75,13 +75,13 @@ const theme = computed(() => settingsStore.theme);
|
|||||||
const sidebar = computed(() => useAppStore().sidebar);
|
const sidebar = computed(() => useAppStore().sidebar);
|
||||||
const device = computed(() => useAppStore().device);
|
const device = computed(() => useAppStore().device);
|
||||||
const needTagsView = computed(() => settingsStore.tagsView);
|
const needTagsView = computed(() => settingsStore.tagsView);
|
||||||
const fixedHeader = computed(() => settingsStore.fixedHeader);
|
// const fixedHeader = computed(() => settingsStore.fixedHeader);
|
||||||
const layout = computed(() => settingsStore.navType);
|
// const layout = computed(() => settingsStore.navType);
|
||||||
|
|
||||||
const showSidebar = computed(() => {
|
// const showSidebar = computed(() => {
|
||||||
if (sidebar.value.hide) return false;
|
// if (sidebar.value.hide) return false;
|
||||||
return layout.value === NavTypeEnum.LEFT || layout.value === NavTypeEnum.MIX;
|
// return layout.value === NavTypeEnum.LEFT || layout.value === NavTypeEnum.MIX;
|
||||||
});
|
// });
|
||||||
|
|
||||||
const classObj = computed(() => ({
|
const classObj = computed(() => ({
|
||||||
hideSidebar: !sidebar.value.opened,
|
hideSidebar: !sidebar.value.opened,
|
||||||
@@ -108,9 +108,9 @@ watchEffect(() => {
|
|||||||
const navbarRef = ref<InstanceType<typeof Navbar>>();
|
const navbarRef = ref<InstanceType<typeof Navbar>>();
|
||||||
const settingRef = ref<InstanceType<typeof Settings>>();
|
const settingRef = ref<InstanceType<typeof Settings>>();
|
||||||
|
|
||||||
const handleClickOutside = () => {
|
// const handleClickOutside = () => {
|
||||||
useAppStore().closeSideBar({ withoutAnimation: false });
|
// useAppStore().closeSideBar({ withoutAnimation: false });
|
||||||
};
|
// };
|
||||||
|
|
||||||
const setLayout = () => {
|
const setLayout = () => {
|
||||||
settingRef.value?.openSetting();
|
settingRef.value?.openSetting();
|
||||||
@@ -120,7 +120,7 @@ const setLayout = () => {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@use '@/assets/styles/mixin.scss';
|
@use '@/assets/styles/mixin.scss';
|
||||||
@use '@/assets/styles/variables.module.scss' as *;
|
@use '@/assets/styles/variables.module.scss' as *;
|
||||||
|
//8^▐╬╬2╬╬>╘
|
||||||
.app-wrapper {
|
.app-wrapper {
|
||||||
@include mixin.clearfix;
|
@include mixin.clearfix;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { getVillageByIdAPI } from '@/api/system/community';
|
|||||||
import { communitylist_rows_type } from '@/api/system/community/type';
|
import { communitylist_rows_type } from '@/api/system/community/type';
|
||||||
import { getBuildinglistAPI, getHouselistAPI, getVillageTree } from '@/api/system/house';
|
import { getBuildinglistAPI, getHouselistAPI, getVillageTree } from '@/api/system/house';
|
||||||
import type { BuildingUnit, BuildingVo } from '@/api/system/house/type';
|
import type { BuildingUnit, BuildingVo } from '@/api/system/house/type';
|
||||||
import { convertBuildingToTree } from '@/utils/house';
|
import { buildHousePathCache, convertBuildingToTree } from '@/utils/house';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
// 数字排序
|
// 数字排序
|
||||||
function sortNumberStr(a: string, b: string) {
|
function sortNumberStr(a: string, b: string) {
|
||||||
@@ -235,6 +235,8 @@ export const useHouseStore = defineStore(
|
|||||||
treedata.value = [];
|
treedata.value = [];
|
||||||
const res = await getVillageTree(villageid);
|
const res = await getVillageTree(villageid);
|
||||||
treedata.value = convertBuildingToTree(res.data.buildings || []);
|
treedata.value = convertBuildingToTree(res.data.buildings || []);
|
||||||
|
|
||||||
|
buildHousePathCache(treedata.value);
|
||||||
return treedata.value;
|
return treedata.value;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('获取楼栋树失败:', err);
|
console.error('获取楼栋树失败:', err);
|
||||||
|
|||||||
2
src/types/env.d.ts
vendored
2
src/types/env.d.ts
vendored
@@ -30,7 +30,7 @@ interface ImportMetaEnv {
|
|||||||
|
|
||||||
VITE_LOGIN_BACK_URL: string;
|
VITE_LOGIN_BACK_URL: string;
|
||||||
VITE_LOGIN_BACK_URL_WORKBENCH_TRU: boolean;
|
VITE_LOGIN_BACK_URL_WORKBENCH_TRU: boolean;
|
||||||
VITE_APP_SHOW_WORK_PLATFORM: boolean;
|
VITE_APP_SHOW_WORK_PLATFORM: string;
|
||||||
}
|
}
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
readonly env: ImportMetaEnv;
|
readonly env: ImportMetaEnv;
|
||||||
|
|||||||
@@ -68,43 +68,94 @@ interface Tree {
|
|||||||
type ValidTreeKey = {
|
type ValidTreeKey = {
|
||||||
[K in keyof Tree]: Tree[K] extends string | number ? K : never;
|
[K in keyof Tree]: Tree[K] extends string | number ? K : never;
|
||||||
}[keyof Tree];
|
}[keyof Tree];
|
||||||
|
// 全局缓存:houseId -> 对应字段路径数组
|
||||||
|
const pathCache = new Map<ValidTreeKey, Map<string, (string | number)[]>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 houseId 查找完整路径(楼栋 > 单元 > 楼层 > 房屋)
|
* 初始化缓存,树形数据加载完成执行一次
|
||||||
* @param treeData 转换后的树形数据
|
* @param treeData 完整树形数据
|
||||||
* @param houseId 目标房屋ID
|
|
||||||
* @param response
|
|
||||||
* @returns string[] 路径数组,如 ['1号楼', '1单元', '3层', '301']
|
|
||||||
*/
|
*/
|
||||||
export function getHousePathById(treeData: Tree[], houseId: string | number, response: ValidTreeKey = 'value'): (string | number)[] {
|
export function buildHousePathCache(treeData: Tree[]) {
|
||||||
const path: (string | number)[] = [];
|
// 清空旧缓存
|
||||||
|
pathCache.set('label', new Map());
|
||||||
|
pathCache.set('value', new Map());
|
||||||
|
|
||||||
// 递归查找
|
const stack: [Tree, (string | number)[], (string | number)[]][] = treeData.map(node => [
|
||||||
function findNode(nodes: Tree[]): boolean {
|
node,
|
||||||
for (const node of nodes) {
|
[node.label],
|
||||||
path.push(node[response]); // 把当前节点加入路径
|
[node.value]
|
||||||
|
]);
|
||||||
|
|
||||||
// 找到目标房屋
|
while (stack.length) {
|
||||||
if (node.type === 'houseId' && node.value === houseId) {
|
const [node, labelPath, valPath] = stack.pop()!;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 递归子节点
|
// 房屋节点存入两套索引
|
||||||
if (node.children && node.children.length > 0) {
|
if (node.type === 'houseId') {
|
||||||
if (findNode(node.children)) {
|
const id = String(node.value);
|
||||||
return true;
|
pathCache.get('label')!.set(id, labelPath);
|
||||||
}
|
pathCache.get('value')!.set(id, valPath);
|
||||||
}
|
|
||||||
|
|
||||||
path.pop(); // 回溯,移除当前节点
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
findNode(treeData);
|
if (node.children?.length) {
|
||||||
return path;
|
const reverseChildren = [...node.children].reverse();
|
||||||
|
for (const child of reverseChildren) {
|
||||||
|
stack.push([
|
||||||
|
child,
|
||||||
|
[...labelPath, child.label],
|
||||||
|
[...valPath, child.value]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存版极速查询房屋路径,O(1)
|
||||||
|
* @param houseId 房屋ID
|
||||||
|
* @param fieldKey 返回字段 label / value
|
||||||
|
*/
|
||||||
|
export function getHousePathById(houseId: string | number, fieldKey: ValidTreeKey = 'value'): (string | number)[] {
|
||||||
|
const id = String(houseId);
|
||||||
|
console.log(pathCache);
|
||||||
|
const cacheMap = pathCache.get(fieldKey);
|
||||||
|
if (!cacheMap) return [];
|
||||||
|
return cacheMap.get(id) ?? [];
|
||||||
|
}
|
||||||
|
// /**
|
||||||
|
// * 根据 houseId 查找完整路径(楼栋 > 单元 > 楼层 > 房屋)
|
||||||
|
// * @param treeData 转换后的树形数据
|
||||||
|
// * @param houseId 目标房屋ID
|
||||||
|
// * @param response
|
||||||
|
// * @returns string[] 路径数组,如 ['1号楼', '1单元', '3层', '301']
|
||||||
|
// */
|
||||||
|
// export function getHousePathById(treeData: Tree[], houseId: string | 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;
|
||||||
|
// }
|
||||||
|
|
||||||
// 对字符串 图片地址,处理
|
// 对字符串 图片地址,处理
|
||||||
export function splitStringUrl(str: string, splitLabel: string = ',') {
|
export function splitStringUrl(str: string, splitLabel: string = ',') {
|
||||||
const list = str.split(splitLabel);
|
const list = str.split(splitLabel);
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ const whiteVillageId = [
|
|||||||
'/payRecordList/payRecordList/list',
|
'/payRecordList/payRecordList/list',
|
||||||
'/warehouse',
|
'/warehouse',
|
||||||
'/notification/read', // 已读
|
'/notification/read', // 已读
|
||||||
'/cash/billList',
|
'/cash/billList'
|
||||||
'/building/list'
|
// '/building/list'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -55,11 +55,13 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import defaultVilageinfoImage from '@/assets/images/villageimage.png';
|
import defaultVilageinfoImage from '@/assets/images/villageimage.png';
|
||||||
import Navbar from '@/layout/components/Navbar.vue';
|
import Navbar from '@/layout/components/Navbar.vue';
|
||||||
import { deleteVillageByIdAPI, switchVillageAPI, getCommunitylistAPI } from '@/api/system/community/index';
|
import { deleteVillageByIdAPI, getCommunitylistAPI, switchVillageAPI } from '@/api/system/community/index';
|
||||||
import type { communitylist_rows_type } from '@/api/system/community/type';
|
import type { communitylist_rows_type } from '@/api/system/community/type';
|
||||||
import { AddLocation, Picture } from '@element-plus/icons-vue';
|
import { AddLocation, Picture } from '@element-plus/icons-vue';
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
import { useHouseStore } from '@/store/modules/house';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
const houseStore = useHouseStore();
|
const houseStore = useHouseStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const list = ref<communitylist_rows_type[]>([]);
|
const list = ref<communitylist_rows_type[]>([]);
|
||||||
@@ -85,9 +87,10 @@ function handleAdd() {
|
|||||||
|
|
||||||
/** 删除小区 */
|
/** 删除小区 */
|
||||||
function handleDelete(item: communitylist_rows_type) {
|
function handleDelete(item: communitylist_rows_type) {
|
||||||
deleteVillageByIdAPI(item.villageId).then(() => {
|
proxy?.$modal.confirm('该信息删除后无法恢复,确定要删除吗?').then(() => {
|
||||||
const newlist = list.value.filter((listitem) => listitem.villageId !== item.villageId);
|
deleteVillageByIdAPI(item.villageId).then(() => {
|
||||||
list.value = newlist;
|
list.value = list.value.filter((listitem) => listitem.villageId !== item.villageId);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,13 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="装修押金(元)" prop="decorationDeposit">
|
<el-form-item label="装修押金(元)" prop="decorationDeposit">
|
||||||
<el-input v-model.trim="form.decorationDeposit" placeholder="请输入装修押金" />
|
<el-input
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="0.01"
|
||||||
|
placeholder="请输入装修押金,最多保留2位小数"
|
||||||
|
v-model.trim.number="form.decorationDeposit"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -57,7 +63,7 @@ import { ref } from 'vue';
|
|||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { addDecoration, getDecoration, updateDecoration } from '@/api/system/Decoration';
|
import { addDecoration, getDecoration, updateDecoration } from '@/api/system/Decoration';
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
import { useHouseStore } from '@/store/modules/house';
|
||||||
import { getHousePathById } from '@/utils/house';
|
import { validator } from '@/utils/Reg';
|
||||||
|
|
||||||
const houseStore = useHouseStore();
|
const houseStore = useHouseStore();
|
||||||
const treedata = ref([]);
|
const treedata = ref([]);
|
||||||
@@ -68,15 +74,56 @@ const formRef = ref();
|
|||||||
const form = ref({
|
const form = ref({
|
||||||
'id': null,
|
'id': null,
|
||||||
'houseId': null,
|
'houseId': null,
|
||||||
|
'buildingId': null,
|
||||||
|
'unitNoId': null,
|
||||||
'applyName': '',
|
'applyName': '',
|
||||||
'decorationCompany': '',
|
'decorationCompany': '',
|
||||||
'decorationContent': '',
|
'decorationContent': '',
|
||||||
'decorationDeposit': null
|
'decorationDeposit': null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用金额校验器
|
||||||
|
* @param value 输入值
|
||||||
|
* @param type money金额 / num整数
|
||||||
|
* @returns 校验提示信息,空则校验通过
|
||||||
|
*/
|
||||||
|
const validator = (value: number | null, type: 'money' | 'num') => {
|
||||||
|
// 空值由 required 规则拦截,这里只处理有值的情况
|
||||||
|
if (value === null || value === undefined) return '';
|
||||||
|
|
||||||
|
// 转字符串处理小数位数
|
||||||
|
const strVal = String(value);
|
||||||
|
// 禁止负数
|
||||||
|
if (value < 0) return '金额不能为负数';
|
||||||
|
|
||||||
|
if (type === 'money') {
|
||||||
|
// 匹配最多两位小数
|
||||||
|
const reg = /^\d+(\.\d{1,2})?$/;
|
||||||
|
if (!reg.test(strVal)) return '金额仅支持最多两位小数';
|
||||||
|
// 限制金额上限(可按需修改)
|
||||||
|
if (value > 9999999.99) return '押金金额不能超过9999999.99元';
|
||||||
|
} else if (type === 'num') {
|
||||||
|
const reg = /^\d+$/;
|
||||||
|
if (!reg.test(strVal)) return '只能输入正整数';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
};
|
||||||
const rules = {
|
const rules = {
|
||||||
houseId: [{ required: true, message: '请选择具体房屋', trigger: 'blur' }],
|
houseId: [{ required: true, message: '请选择具体房屋', trigger: 'blur' }],
|
||||||
applyName: [{ required: true, message: '请输入申请人', trigger: 'blur' }],
|
applyName: [{ required: true, message: '请输入申请人', trigger: 'blur' }],
|
||||||
decorationDeposit: [{ required: true, message: '请输入装修押金', trigger: 'blur' }],
|
decorationDeposit: [
|
||||||
|
{ required: true, message: '请输入装修押金', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
validator: (rule, val, callback) => {
|
||||||
|
const msg = validator(val, 'money');
|
||||||
|
if (msg) callback(new Error(msg));
|
||||||
|
else callback();
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}
|
||||||
|
],
|
||||||
decorationContent: [{ required: true, message: '请输入装修内容', trigger: 'blur' }]
|
decorationContent: [{ required: true, message: '请输入装修内容', trigger: 'blur' }]
|
||||||
};
|
};
|
||||||
const userid = ref();
|
const userid = ref();
|
||||||
@@ -85,7 +132,7 @@ const userid = ref();
|
|||||||
const userHousepath = ref([]);
|
const userHousepath = ref([]);
|
||||||
function handleChange(val: (string | number)[]) {
|
function handleChange(val: (string | number)[]) {
|
||||||
if (val.length >= 3) {
|
if (val.length >= 3) {
|
||||||
form.value.houseId = val.pop() as number;
|
form.value.houseId = val.at(2) as number;
|
||||||
} else {
|
} else {
|
||||||
form.value.houseId = null;
|
form.value.houseId = null;
|
||||||
}
|
}
|
||||||
@@ -102,14 +149,14 @@ function getTree() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
getTree();
|
getTree();
|
||||||
|
// TODO
|
||||||
function init() {
|
function init() {
|
||||||
getDecoration(userid.value).then((res) => {
|
getDecoration(userid.value).then((res) => {
|
||||||
form.value = {
|
form.value = {
|
||||||
...form.value,
|
...form.value,
|
||||||
...res.data
|
...res.data
|
||||||
};
|
};
|
||||||
const arr = getHousePathById(treedata.value, form.value.houseId);
|
userHousepath.value = [form.value.buildingId, form.value.unitNoId, form.value.houseId];
|
||||||
userHousepath.value = arr;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ const rules = ref({
|
|||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
trigger: 'blur' // ✅ 只在失焦时验证
|
trigger: 'blur' // ✅ 只在失焦时验证╬N
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
startTime: [{ required: true, message: '请选择有效日期', trigger: 'blur' }],
|
startTime: [{ required: true, message: '请选择有效日期', trigger: 'blur' }],
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<el-form-item label="项目名称" prop="itemName">
|
<el-form-item label="项目名称" prop="itemName">
|
||||||
<el-input v-model.trim="form.itemName" placeholder="请输入项目名称" />
|
<el-input v-model.trim="form.itemName" placeholder="请输入项目名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="收费项目" prop="typeId">
|
<el-form-item label="收费类型" prop="typeId">
|
||||||
<el-select v-model="form.typeId">
|
<el-select v-model="form.typeId">
|
||||||
<el-option v-for="(item, index) in chargeitemlist" :key="index" :value="item.id" :label="item.name"></el-option>
|
<el-option v-for="(item, index) in chargeitemlist" :key="index" :value="item.id" :label="item.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ const { com_charge_item_carry_method } = toRefs<any>(proxy?.useDict('com_charge_
|
|||||||
const { com_charge_item_formula } = toRefs<any>(proxy?.useDict('com_charge_item_formula'));
|
const { com_charge_item_formula } = toRefs<any>(proxy?.useDict('com_charge_item_formula'));
|
||||||
|
|
||||||
const chargeItemList = ref<ChargeItemVO[]>([]);
|
const chargeItemList = ref<ChargeItemVO[]>([]);
|
||||||
const buttonLoading = ref(false);
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
const ids = ref<Array<string | number>>([]);
|
const ids = ref<Array<string | number>>([]);
|
||||||
@@ -117,12 +116,6 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const chargeItemFormRef = ref<ElFormInstance>();
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
|
||||||
visible: false,
|
|
||||||
title: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const initFormData: ChargeItemForm = {
|
const initFormData: ChargeItemForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@@ -138,7 +131,7 @@ const data = reactive<PageData<ChargeItemForm, ChargeItemQuery>>({
|
|||||||
rules: {}
|
rules: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams } = toRefs(data);
|
||||||
|
|
||||||
/** 查询收费项目管理列表 */
|
/** 查询收费项目管理列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
@@ -153,18 +146,6 @@ const getList = async () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 取消按钮 */
|
|
||||||
const cancel = () => {
|
|
||||||
reset();
|
|
||||||
dialog.visible = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 表单重置 */
|
|
||||||
const reset = () => {
|
|
||||||
form.value = { ...initFormData };
|
|
||||||
chargeItemFormRef.value?.resetFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
@@ -221,17 +202,6 @@ const handleDelete = async (row?: ChargeItemVO) => {
|
|||||||
await getList();
|
await getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 导出按钮操作 */
|
|
||||||
const handleExport = () => {
|
|
||||||
proxy?.download(
|
|
||||||
'chargeItem/chargeItem/export',
|
|
||||||
{
|
|
||||||
...queryParams.value
|
|
||||||
},
|
|
||||||
`chargeItem_${new Date().getTime()}.xlsx`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,16 +6,11 @@
|
|||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
||||||
<el-form-item label="选择仪表" prop="deviceType">
|
<el-form-item label="选择仪表" prop="deviceType">
|
||||||
<el-radio-group v-model="form.deviceType" @change="handlechange">
|
<el-radio-group v-model="form.deviceType" @change="handleChange">
|
||||||
<el-radio label="电表" value="1"></el-radio>
|
<el-radio label="电表" value="1"></el-radio>
|
||||||
<el-radio label="水表" value="2"></el-radio>
|
<el-radio label="水表" value="2"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="抄表项目" prop="payType">
|
|
||||||
<el-radio-group v-model="form.payType" @change="handlechange2">
|
|
||||||
<el-radio v-for="(item, index) in chargeitemlist" :key="index" :label="item.itemName" :value="item.id"></el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item> -->
|
|
||||||
<el-form-item label="抄表月份" prop="recordMonth">
|
<el-form-item label="抄表月份" prop="recordMonth">
|
||||||
<el-date-picker @update:model-value="handleMonth" v-model="form.recordMonth" value-format="YYYY-MM" format="YYYY-MM" type="month" />
|
<el-date-picker @update:model-value="handleMonth" v-model="form.recordMonth" value-format="YYYY-MM" format="YYYY-MM" type="month" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -47,14 +42,12 @@ import { ref } from 'vue';
|
|||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { addPayRecord, getPayRecord, updatePayRecord } from '@/api/system/SdbPayRecord';
|
import { addPayRecord, getPayRecord, updatePayRecord } from '@/api/system/SdbPayRecord';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const form = ref({
|
const form = ref({
|
||||||
'deviceType': '1', // 设备类型 1电表 2水表
|
'deviceType': '1', // 设备类型: 1 电表 2 水表
|
||||||
'payType': '1', // 设备类型 1电表 2水表
|
'payType': '1', // 设备类型: 1 电表 2 水表
|
||||||
'recordMonth': '', // 抄表月份
|
'recordMonth': '', // 抄表月份
|
||||||
'startTime': '', // 开始时间
|
'startTime': '', // 开始时间
|
||||||
'endTime': '' // 结束时间
|
'endTime': '' // 结束时间
|
||||||
@@ -112,11 +105,7 @@ const disabledDate = (time: Date) => {
|
|||||||
// 不在 [当月1号 ~ 当月最后1号] 之间 → 禁用
|
// 不在 [当月1号 ~ 当月最后1号] 之间 → 禁用
|
||||||
return time < chooseStart.value || time > chooseEnd.value;
|
return time < chooseStart.value || time > chooseEnd.value;
|
||||||
};
|
};
|
||||||
// const chargeitemlist = ref([]);
|
|
||||||
function init() {
|
function init() {
|
||||||
// listChargeItem().then((res) => {
|
|
||||||
// chargeitemlist.value = res.rows;
|
|
||||||
// });
|
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
userid.value = route.query.id;
|
userid.value = route.query.id;
|
||||||
getPayRecord(userid.value).then((res) => {
|
getPayRecord(userid.value).then((res) => {
|
||||||
@@ -130,7 +119,7 @@ function init() {
|
|||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
function handlechange(val: string) {
|
function handleChange(val: string) {
|
||||||
form.value.deviceType = val;
|
form.value.deviceType = val;
|
||||||
form.value.payType = val;
|
form.value.payType = val;
|
||||||
}
|
}
|
||||||
@@ -141,12 +130,12 @@ const submitForm = () => {
|
|||||||
formRef.value?.validate(async (valid: boolean) => {
|
formRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (userid.value) {
|
if (userid.value) {
|
||||||
updatePayRecord(form.value).then((res) => {
|
updatePayRecord(form.value).then(() => {
|
||||||
ElMessage.success('编辑成功');
|
ElMessage.success('编辑成功');
|
||||||
cancelForm();
|
cancelForm();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
addPayRecord(form.value).then((res) => {
|
addPayRecord(form.value).then(() => {
|
||||||
ElMessage.success('添加成功');
|
ElMessage.success('添加成功');
|
||||||
cancelForm();
|
cancelForm();
|
||||||
});
|
});
|
||||||
@@ -192,52 +181,6 @@ const cancelForm = () => {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 10px 5px;
|
padding: 10px 5px;
|
||||||
}
|
}
|
||||||
.checkoutSideUsesbox {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: 5px;
|
|
||||||
li {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
min-width: 120px;
|
|
||||||
height: 35px;
|
|
||||||
padding: 0 10px;
|
|
||||||
line-height: 35px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
background-color: #f3f9ff;
|
|
||||||
border: 1px solid #8fc0f1;
|
|
||||||
|
|
||||||
@media (max-width: 2000px) {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
@media (max-width: 1650px) {
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
@media (max-width: 1650px) {
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
.el-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.add {
|
|
||||||
cursor: pointer;
|
|
||||||
justify-content: center;
|
|
||||||
color: #409eff;
|
|
||||||
border: 1px dashed #409eff;
|
|
||||||
background-color: transparent;
|
|
||||||
&:hover {
|
|
||||||
background-color: #40a0ff10;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:deep(.el-form-item__content, .el-select, .el-input) {
|
&:deep(.el-form-item__content, .el-select, .el-input) {
|
||||||
width: 350px !important;
|
width: 350px !important;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|||||||
@@ -142,7 +142,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="PayRecordList" lang="ts">
|
<script setup name="PayRecordList" lang="ts">
|
||||||
import { listPayRecordList, getPayRecordList, addPayRecordList, updatePayRecordList } from '@/api/system/SdbPayRecordMain/index';
|
import { listPayRecordList, getPayRecordList, addPayRecordList, updatePayRecordList } from '@/api/system/SdbPayRecordMain';
|
||||||
import { PayRecordListVO, PayRecordListQuery, PayRecordListForm } from '@/api/system/SdbPayRecordMain/type';
|
import { PayRecordListVO, PayRecordListQuery, PayRecordListForm } from '@/api/system/SdbPayRecordMain/type';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@@ -155,8 +155,6 @@ const buttonLoading = ref(false);
|
|||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
const ids = ref<Array<string | number>>([]);
|
const ids = ref<Array<string | number>>([]);
|
||||||
const single = ref(true);
|
|
||||||
const multiple = ref(true);
|
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -219,9 +217,9 @@ const deviceCodeList = [
|
|||||||
];
|
];
|
||||||
const { queryParams, form } = toRefs(data);
|
const { queryParams, form } = toRefs(data);
|
||||||
|
|
||||||
const queryid = ref('');
|
const queryId = ref('');
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
queryid.value = route.query.id as string;
|
queryId.value = route.query.id as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询抄表周期明细列表 */
|
/** 查询抄表周期明细列表 */
|
||||||
@@ -229,7 +227,7 @@ const getList = async () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await listPayRecordList({
|
const res = await listPayRecordList({
|
||||||
...queryParams.value,
|
...queryParams.value,
|
||||||
recordId: queryid.value ?? undefined
|
recordId: queryId.value ?? undefined
|
||||||
});
|
});
|
||||||
payRecordListList.value = res.rows;
|
payRecordListList.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)">
|
<el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)">
|
||||||
<el-option
|
<el-option
|
||||||
:disabled="item.status === '1'"
|
:disabled="item.status === '1'"
|
||||||
v-for="(item, index) in chargeitemlist"
|
v-for="(item, index) in chargeItemList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
:label="item.itemName"
|
:label="item.itemName"
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 水费,电费, 收费范围为 房屋 -->
|
<!-- 水费,电费, 收费范围为 房屋 -->
|
||||||
<el-form-item label="收费范围" prop="chargeScope" v-if="typeNamelist.includes(typeName)">
|
<el-form-item label="收费范围" prop="chargeScope" v-if="typeNameList.includes(typeName)">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex flex-row flex-items-end">
|
<div class="flex flex-row flex-items-end">
|
||||||
<el-radio-group v-model="form.chargeScope">
|
<el-radio-group v-model="form.chargeScope">
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<div style="height: 32px">
|
<div style="height: 32px">
|
||||||
<el-button @click="OpenUseTablesfun('house')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
|
<el-button @click="OpenUseTablesFun('house')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -57,21 +57,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<div style="height: 32px">
|
<div style="height: 32px">
|
||||||
<el-button @click="OpenUseTablesfun('user')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
|
<el-button @click="OpenUseTablesFun('user')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 房屋选择 -->
|
<!-- 房屋选择 -->
|
||||||
<el-form-item v-if="form.chargeScope === '1' && typeNamelist.includes(typeName)">
|
<el-form-item v-if="form.chargeScope === '1' && typeNameList.includes(typeName)">
|
||||||
<div class="residentBox">
|
<div class="residentBox">
|
||||||
<House returnvalue="houseId" ref="HolderRef" :isMultiple="true" @change="handleSelect"> </House>
|
<House returnvalue="houseId" ref="HolderRef" :isMultiple="true" @change="handleSelect"> </House>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 业主选择 -->
|
<!-- 业主选择 -->
|
||||||
<el-form-item v-if="form.chargeScope === '1' && !typeNamelist.includes(typeName)">
|
<el-form-item v-if="form.chargeScope === '1' && !typeNameList.includes(typeName)">
|
||||||
<!-- 业主选择 车位费用 -->
|
<!-- 业主选择 车位费用 -->
|
||||||
<div class="residentBox" v-if="typeName === HandleTypeId.Resident.Parking">
|
<div class="residentBox" v-if="typeName === HandleTypeId.Resident.Parking">
|
||||||
<CarUser returnvalue="parkingId" ref="ParkinguserRef" :isMultiple="true" @change="handleCheckPaking"></CarUser>
|
<CarUser returnvalue="parkingId" ref="ParkingUserRef" :isMultiple="true" @change="handleCheckParking"></CarUser>
|
||||||
</div>
|
</div>
|
||||||
<div class="residentBox" v-else>
|
<div class="residentBox" v-else>
|
||||||
<UserHolder returnvalue="residentId" ref="userRef" :isMultiple="true" @change="handleCheckUser"></UserHolder>
|
<UserHolder returnvalue="residentId" ref="userRef" :isMultiple="true" @change="handleCheckUser"></UserHolder>
|
||||||
@@ -192,7 +192,7 @@ function handleClear() {
|
|||||||
form.value.endDate = '';
|
form.value.endDate = '';
|
||||||
}
|
}
|
||||||
// 收费类型
|
// 收费类型
|
||||||
const chargeitemlist = ref([]);
|
const chargeItemList = ref([]);
|
||||||
|
|
||||||
// // 房屋列表
|
// // 房屋列表
|
||||||
// const houselist = ref([]);
|
// const houselist = ref([]);
|
||||||
@@ -200,7 +200,7 @@ const chargeitemlist = ref([]);
|
|||||||
// const userlist = ref([]);
|
// const userlist = ref([]);
|
||||||
async function init() {
|
async function init() {
|
||||||
listChargeItem({}).then((res) => {
|
listChargeItem({}).then((res) => {
|
||||||
chargeitemlist.value = res.rows;
|
chargeItemList.value = res.rows;
|
||||||
|
|
||||||
// const res = await listBillHouse({ pageNum: 1, pageSize: 999999 });
|
// const res = await listBillHouse({ pageNum: 1, pageSize: 999999 });
|
||||||
// houselist.value = res.rows;
|
// houselist.value = res.rows;
|
||||||
@@ -252,11 +252,11 @@ const HandleTypeId = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 符合类型: 显示房屋,选择房屋
|
// 符合类型: 显示房屋,选择房屋
|
||||||
const typeNamelist = ref([HandleTypeId.House.Water, HandleTypeId.House.Electricity]);
|
const typeNameList = ref([HandleTypeId.House.Water, HandleTypeId.House.Electricity]);
|
||||||
const typeName = ref('');
|
const typeName = ref('');
|
||||||
// 获取收费类型id
|
// 获取收费类型id
|
||||||
function handleChange(val: string, callback: boolean = false) {
|
function handleChange(val: string, callback: boolean = false) {
|
||||||
const find = chargeitemlist.value.find((item) => item.id === val);
|
const find = chargeItemList.value.find((item) => item.id === val);
|
||||||
if (find) {
|
if (find) {
|
||||||
form.value.chargeTypeId = find.typeId;
|
form.value.chargeTypeId = find.typeId;
|
||||||
typeName.value = find.typeId;
|
typeName.value = find.typeId;
|
||||||
@@ -282,7 +282,7 @@ function handleCheckUser(val: string[]) {
|
|||||||
}
|
}
|
||||||
const checkoutParking = ref([]);
|
const checkoutParking = ref([]);
|
||||||
/** 添加 车位业主 */
|
/** 添加 车位业主 */
|
||||||
function handleCheckPaking(val: string[]) {
|
function handleCheckParking(val: string[]) {
|
||||||
checkoutParking.value = val;
|
checkoutParking.value = val;
|
||||||
console.log(val);
|
console.log(val);
|
||||||
form.value.parkingIds = val;
|
form.value.parkingIds = val;
|
||||||
@@ -299,13 +299,13 @@ function handleClearCheckout() {
|
|||||||
// 打开
|
// 打开
|
||||||
const HolderRef = ref<InstanceType<typeof House>>();
|
const HolderRef = ref<InstanceType<typeof House>>();
|
||||||
const userRef = ref<InstanceType<typeof UserHolder>>();
|
const userRef = ref<InstanceType<typeof UserHolder>>();
|
||||||
const ParkinguserRef = ref<InstanceType<typeof CarUser>>();
|
const ParkingUserRef = ref<InstanceType<typeof CarUser>>();
|
||||||
function OpenUseTablesfun(val: string) {
|
function OpenUseTablesFun(val: string) {
|
||||||
if (val === 'house') {
|
if (val === 'house') {
|
||||||
HolderRef.value.open(checkoutHouses.value);
|
HolderRef.value.open(checkoutHouses.value);
|
||||||
} else if (val === 'user') {
|
} else if (val === 'user') {
|
||||||
if (typeName.value === HandleTypeId.Resident.Parking) {
|
if (typeName.value === HandleTypeId.Resident.Parking) {
|
||||||
ParkinguserRef.value.open(checkoutParking.value);
|
ParkingUserRef.value.open(checkoutParking.value);
|
||||||
} else {
|
} else {
|
||||||
userRef.value.open(checkoutUser.value);
|
userRef.value.open(checkoutUser.value);
|
||||||
}
|
}
|
||||||
@@ -370,63 +370,6 @@ const cancelForm = () => {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 10px 5px;
|
padding: 10px 5px;
|
||||||
}
|
}
|
||||||
.checkoutSideUsesbox {
|
|
||||||
// display: grid;
|
|
||||||
// grid-template-columns: repeat(3, 1fr);
|
|
||||||
// gap: 5px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 10px 5px;
|
|
||||||
li {
|
|
||||||
margin-right: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
min-width: 240px;
|
|
||||||
height: 35px;
|
|
||||||
padding: 0 10px;
|
|
||||||
line-height: 35px;
|
|
||||||
|
|
||||||
background-color: #f3f9ff;
|
|
||||||
border: 1px solid #8fc0f1;
|
|
||||||
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
@media (max-width: 2000px) {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
@media (max-width: 1650px) {
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
@media (max-width: 1650px) {
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
.el-icon {
|
|
||||||
margin-left: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.add {
|
|
||||||
cursor: pointer;
|
|
||||||
justify-content: center;
|
|
||||||
color: #409eff;
|
|
||||||
border: 1px dashed #409eff;
|
|
||||||
background-color: transparent;
|
|
||||||
&:hover {
|
|
||||||
background-color: #40a0ff10;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:deep(.el-form-item__content, .el-select, .el-input) {
|
&:deep(.el-form-item__content, .el-select, .el-input) {
|
||||||
width: 350px !important;
|
width: 350px !important;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|||||||
@@ -11,11 +11,11 @@
|
|||||||
|
|
||||||
<el-form-item label="收费项目" prop="chargeItemId">
|
<el-form-item label="收费项目" prop="chargeItemId">
|
||||||
<el-select disabled v-model="form.chargeItemId" @change="handleChange">
|
<el-select disabled v-model="form.chargeItemId" @change="handleChange">
|
||||||
<el-option v-for="(item, index) in chargeitemlist" :key="index" :value="item.id" :label="item.itemName"></el-option>
|
<el-option v-for="(item, index) in chargeItemList" :key="index" :value="item.id" :label="item.itemName"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="收费范围" prop="chargeScope" v-if="itemTypeincludes">
|
<el-form-item label="收费范围" prop="chargeScope" v-if="itemTypeIncludes">
|
||||||
<el-radio-group disabled v-model="form.chargeScope">
|
<el-radio-group disabled v-model="form.chargeScope">
|
||||||
<el-radio v-for="(item, index) in com_questionnaire_scope" :key="index" :value="item.value" :label="item.label"></el-radio>
|
<el-radio v-for="(item, index) in com_questionnaire_scope" :key="index" :value="item.value" :label="item.label"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@@ -110,23 +110,23 @@ function handleDate(val: string[]) {
|
|||||||
form.value.startDate = formatDate2(val[0]);
|
form.value.startDate = formatDate2(val[0]);
|
||||||
form.value.endDate = formatDate2(val[1]);
|
form.value.endDate = formatDate2(val[1]);
|
||||||
}
|
}
|
||||||
const chargeitemlist = ref([]);
|
const chargeItemList = ref([]);
|
||||||
// 电费 水费
|
// 电费 水费
|
||||||
const typeNamelist = ref(['2049026484272791553', '2049026503017136129']);
|
const typeNameList = ref(['2049026484272791553', '2049026503017136129']);
|
||||||
|
|
||||||
const itemTypeincludes = computed(() => {
|
const itemTypeIncludes = computed(() => {
|
||||||
return typeNamelist.value.includes(form.value.chargeItemId);
|
return typeNameList.value.includes(form.value.chargeItemId);
|
||||||
});
|
});
|
||||||
|
|
||||||
const houselist = ref([]);
|
const houseList = ref([]);
|
||||||
|
|
||||||
const checkoutUses = ref([]);
|
const checkoutUses = ref([]);
|
||||||
async function init() {
|
async function init() {
|
||||||
const res1 = await listBillHouse({ pageNum: 1, pageSize: 999999 });
|
const res1 = await listBillHouse({ pageNum: 1, pageSize: 999999 });
|
||||||
houselist.value = res1.rows;
|
houseList.value = res1.rows;
|
||||||
|
|
||||||
listChargeItem().then(async (res) => {
|
listChargeItem().then(async (res) => {
|
||||||
chargeitemlist.value = res.rows;
|
chargeItemList.value = res.rows;
|
||||||
|
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
userid.value = route.query.id;
|
userid.value = route.query.id;
|
||||||
@@ -140,7 +140,7 @@ async function init() {
|
|||||||
checkoutUses.value = form.value.houseIds
|
checkoutUses.value = form.value.houseIds
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
if (item) {
|
if (item) {
|
||||||
const find = houselist.value.find((it) => it.houseId === item);
|
const find = houseList.value.find((it) => it.houseId === item);
|
||||||
if (find) {
|
if (find) {
|
||||||
return find;
|
return find;
|
||||||
} else {
|
} else {
|
||||||
@@ -158,14 +158,11 @@ init();
|
|||||||
|
|
||||||
// 获取收费类型id
|
// 获取收费类型id
|
||||||
function handleChange(val) {
|
function handleChange(val) {
|
||||||
const find = chargeitemlist.value.find((item) => item.id === val);
|
const find = chargeItemList.value.find((item) => item.id === val);
|
||||||
if (find) {
|
if (find) {
|
||||||
form.value.charegeTypeId = find.typeId;
|
form.value.charegeTypeId = find.typeId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// !== 提交 =============================================================================
|
|
||||||
|
|
||||||
// 推出
|
// 推出
|
||||||
const cancelForm = () => {
|
const cancelForm = () => {
|
||||||
router.back();
|
router.back();
|
||||||
@@ -228,8 +225,6 @@ const cancelForm = () => {
|
|||||||
background-color: #f3f9ff;
|
background-color: #f3f9ff;
|
||||||
border: 1px solid #8fc0f1;
|
border: 1px solid #8fc0f1;
|
||||||
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
@media (max-width: 2000px) {
|
@media (max-width: 2000px) {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ import { billlistType, billPrint, BillPrintType, billQuery } from '@/api/system/
|
|||||||
import { printTicketDiv } from '@/utils/print';
|
import { printTicketDiv } from '@/utils/print';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_pay_method, com_pay_status } = toRefs<any>(proxy?.useDict('com_pay_method', 'com_pay_status'));
|
const { com_pay_status } = toRefs<any>(proxy?.useDict('com_pay_status'));
|
||||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
||||||
const { com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_unit'));
|
const { com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_unit'));
|
||||||
|
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ function changeTabs(value: number) {
|
|||||||
function handleChangeVillage(val: string) {
|
function handleChangeVillage(val: string) {
|
||||||
queryParams.value.unitNoId = undefined;
|
queryParams.value.unitNoId = undefined;
|
||||||
queryParams.value.buildingId = undefined;
|
queryParams.value.buildingId = undefined;
|
||||||
|
queryParams.value.chargeItemId = undefined;
|
||||||
buildingList.value = [];
|
buildingList.value = [];
|
||||||
unitList.value = [];
|
unitList.value = [];
|
||||||
if (val) {
|
if (val) {
|
||||||
@@ -398,14 +399,25 @@ const buttonLoading = ref(false);
|
|||||||
const inComeFrom = ref({
|
const inComeFrom = ref({
|
||||||
allCost: null, // 金额
|
allCost: null, // 金额
|
||||||
billResidentId: [], // 账单id
|
billResidentId: [], // 账单id
|
||||||
payStatus: '0', // 0:未缴 1:已缴
|
payStatus: '1', // 0:未缴 1:已缴
|
||||||
payType: '0', // 0:微信 1:支付宝 2 线下
|
payType: '0', // 0:微信 1:支付宝 2 线下
|
||||||
remark: '',
|
remark: '',
|
||||||
residentName: '' // 缴费人
|
residentName: '' // 缴费人
|
||||||
});
|
});
|
||||||
|
function initInComeFrom() {
|
||||||
|
inComeFrom.value = {
|
||||||
|
allCost: null, // 金额
|
||||||
|
billResidentId: [], // 账单id
|
||||||
|
payStatus: '1', // 0:未缴 1:已缴
|
||||||
|
payType: '2', // 0:微信 1:支付宝 2 线下
|
||||||
|
remark: '',
|
||||||
|
residentName: '' // 缴费人
|
||||||
|
};
|
||||||
|
}
|
||||||
// 收费 --------------------------------------------------------------
|
// 收费 --------------------------------------------------------------
|
||||||
/** 收费 */
|
/** 收费 */
|
||||||
function handleIncome(row: billlistType | false) {
|
function handleIncome(row: billlistType | false) {
|
||||||
|
initInComeFrom();
|
||||||
console.log(ids.value);
|
console.log(ids.value);
|
||||||
inComeFrom.value.allCost = 0;
|
inComeFrom.value.allCost = 0;
|
||||||
inComeFrom.value.billResidentId = [];
|
inComeFrom.value.billResidentId = [];
|
||||||
@@ -436,6 +448,7 @@ function handleIncome(row: billlistType | false) {
|
|||||||
const closer = () => {
|
const closer = () => {
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
dialog.title = '';
|
dialog.title = '';
|
||||||
|
initInComeFrom();
|
||||||
};
|
};
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
@@ -526,6 +539,142 @@ onMounted(() => {
|
|||||||
villageList.value = res.rows;
|
villageList.value = res.rows;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
/*
|
||||||
|
* 显。 更何况李恩成把自己的要求提得很清楚,一来是【血
|
||||||
|
* 暾果】,二来是通过【宣元坊】来联系他,不要再去府辰峰。
|
||||||
|
* “此人在宗内独善其身多年,果然有些心思……” 李
|
||||||
|
* 曦治思忖一阵,先把笔墨搁置,朝着杨宵儿道: “恐怕还
|
||||||
|
* 要宵儿去一趟帝云峰,查一查李恩成入宗前后之事,是不是得罪了什
|
||||||
|
* 么人,在自己峰中都不敢说话。” 李恩成虽然是丹修大师
|
||||||
|
* ,却处处受制于云丹峰,大部分人情都是求到云丹峰,他苦苦炼成丹
|
||||||
|
* 药,最后人情与好处大都被云丹峰得去。 只是他一向表现
|
||||||
|
* 得古怪,众人都当他不在乎,李曦治现下想来也觉得蹊跷了,不敢让
|
||||||
|
* 自己父亲贸然行事,打算打听个清楚。 ‘杨天衙亲自为我
|
||||||
|
* 家遮掩,想必与我家有联系或是与萧家有图谋,去帝云峰才能查出真
|
||||||
|
* 消息,也不至于露出马脚。’ 他放了笔墨,取出《六色寻
|
||||||
|
* 元遁》,创出这遁法的前辈明显是個好面子的,玉简上五彩缤纷,雕
|
||||||
|
* 刻着各色华纹。 ‘若是论真元华丽,《朝霞采露诀》还真
|
||||||
|
* 是一等一…’ 李曦治看了一夜,便见着杨宵儿驾风回来,
|
||||||
|
* 皱着眉进来,回答道: “李恩成…还真得罪过一人!”
|
||||||
|
* “谁?” 李曦治连忙抬头,却见杨宵儿面色古怪
|
||||||
|
* ,低声道: “迟尉!” “迟尉?!”
|
||||||
|
* 李曦治呆了一瞬,有些难以置信地道: “怎么可能?”
|
||||||
|
* 杨宵儿仔细检查门窗,用秘法传音: “迟尉当
|
||||||
|
* 年还是筑基,与李恩成外出,两人在一片废墟中寻到了一道丹道传承
|
||||||
|
* ,李恩成见利起欲,打伤迟尉,将他锁在秘境之中,夺取此道…”
|
||||||
|
* “不曾想迟尉后来反而在其中得了大好处,归宗而来,李恩
|
||||||
|
* 成被拿下审问,只依靠了当年的府辰峰主一力保下,迟尉也大度不再
|
||||||
|
* 追究。” “两人化干戈为玉帛,后头李恩成再未出宗,一
|
||||||
|
* 日日在峰上炼丹,以赎罪过……” 李曦治听得摇头:
|
||||||
|
* “原来还有这种渊源…难怪…” 杨宵儿复又道:
|
||||||
|
* “如今迟尉身死,李恩成成了摇钱树,宗内已经抹去这一段
|
||||||
|
* 不提,乃是老祖派人告诉我的。” “难怪李恩成很少外出
|
||||||
|
* …” 李曦治点头,若有所思: “未必是他不愿
|
||||||
|
* 出宗,兴许是不敢。” 李曦治从架上取出一枚玉简,仔细
|
||||||
|
* 一查,若有所悟,低声道: “果然有这小段记录,所得【
|
||||||
|
* 密樊宗】一丹道传承…原来其中还有这样一段故事。” 杨
|
||||||
|
* 宵儿努努嘴,提醒道: “这事情实在太过久远,除了几个
|
||||||
|
* 紫府,如今宗内的峰主与弟子皆不晓得,应该没有什么问题。”
|
||||||
|
* “我家老祖当年也不过是个小弟子,这事情几分真几分假,宗
|
||||||
|
* 内说的和秘境中发生的都不知真假,姑且一听。” 李曦治
|
||||||
|
* 微微点头,心中暗暗计较,拿起笔来又在信上添了几句,默默折好,
|
||||||
|
* 用自家秘法封了,准备寄出去。 李渊蛟送来的三枚宝药并
|
||||||
|
* 没有用上,虽然父亲李渊蛟信中说的是若是结交无望,留以自用,李
|
||||||
|
* 曦治却不舍得全都塞进自己腰包里。 李曦治仔细看了看,
|
||||||
|
* 取出其中一枚【云藤灵椒】,准备交给云丹峰炼制一炉丹药,其余两
|
||||||
|
* 枚还是原封不动地收好,装入小袋之中,随信送回家去。
|
||||||
|
* …… 青杜峰。 李曦明端坐在炉火旁,金黄色的
|
||||||
|
* 火焰照的他面上忽明忽暗,手中轻轻一钩,【玄阳离火】跳动而出,
|
||||||
|
* 在他指上回荡勾勒。 【玄阳离火】爆裂难缠,却在他手中
|
||||||
|
* 乖巧犹如精灵,跳跃流动。 这原本是对敌的上好灵火,只
|
||||||
|
* 可惜家中只有这一份,只能转成【长行元火】,李曦明在手中把玩着
|
||||||
|
* ,感受着其中爆裂灼热的强大威力,有些惋惜。 李曦明受
|
||||||
|
* 了符种,修为到达练气五层,距离练气六层本只有一步之遥,闭关四
|
||||||
|
* 月,轻轻松松地突破练气六层,气息平缓,游刃有余。 ‘
|
||||||
|
* 箓气如此神妙,可惜只能受一道,若是能服用几道就好了…’
|
||||||
|
* 李曦明闭关两月,才出了关,心中痒痒,把院外的下人叫进来,
|
||||||
|
* 吩咐道: “把那窦…几个都叫上来…” 这人帮
|
||||||
|
* 着传唤多次,闻弦歌而知雅意,自然晓得,正拜退下去,李曦明又连
|
||||||
|
* 忙道: “等等!等等…有人来了。” 便见着院
|
||||||
|
* 门嘎吱一声开了,外头进来个白袍少年,剑眉星目,一身真元如寒雪
|
||||||
|
* ,笑道: “曦明出关了,倒是来得巧!” 李曦
|
||||||
|
* 峻的修为也达到了练气五层,两人受的都是筑基级别,一连突破,都
|
||||||
|
* 比宗内的李曦治高出一筹了,都成了练气中期,唯独山下的李曦峸还
|
||||||
|
* 是练气二层。 兄弟两坐下,李曦明还有些尴尬,李曦峻不
|
||||||
|
* 去点破,将他闭关前后的事情一一说了,把两条矿脉一指,李曦明也
|
||||||
|
* 颇为欣喜,答道: “是好事!” 李曦峻开口道
|
||||||
|
* : “仲父如今已经闭关养伤,我这两月外出采气,修炼【
|
||||||
|
* 屠钧葵光】,顺道走了两个坊市,已经把施【闰阳法】的灵萃灵物为
|
||||||
|
* 你买齐了。” 说着从储物袋中摆出诸物,凤尾花纹的灵石
|
||||||
|
* 、入手温热的玉瓶、赤红的灵萃…一系列灵物: “这是【
|
||||||
|
* 凤尾石】、这是【灰乌烟】、【元阳灵萃】……” 李曦明
|
||||||
|
* 一一接过,见着李曦峻风尘仆仆的模样,连忙谢了一句,把东西先放
|
||||||
|
* 在案上,就不好意思多说什么,只能说着多谢。 李曦峻摆
|
||||||
|
* 手,不曾放在心上。 他如今修为有所精进,又开始修炼《
|
||||||
|
* 清目灵瞳》,眼中精光流转,仿佛能把人看个通透,低声道:
|
||||||
|
* “大叔公近来很是憔悴,应该是心魔缠身,只是他从不肯说,你
|
||||||
|
* 多炼些清心一类的丹药…我找机会再叫几人跑一趟南边大郡,寻一寻
|
||||||
|
* 这一类的丹药。” “恰好我有一味灵水也需要外出寻找,
|
||||||
|
* 把这两件事合在一块做,也方便些。” 李曦明听了他的话
|
||||||
|
* ,点头应是,李玄宣是他大父,本来是他最该上心的,只是闭关修炼
|
||||||
|
* ,耽误了时间,愧道: “我这就去炼丹,我这就去炼丹…
|
||||||
|
* 大父的事情我今后仔细看着,不必你们操心。” 李曦峻笑
|
||||||
|
* 着点头,李曦明当下问道: “【屠钧葵光】竟然这样难修
|
||||||
|
* 炼?家中已经有一味寒水,一道寒气,袁家那处得了一道,《寒雪集
|
||||||
|
* 》中有三道寒气,一道寒水寻法…还要外出?” “就差那
|
||||||
|
* 一道寒水了。” 李曦峻笑着点头,答道: “我
|
||||||
|
* 这【明霜松岭】善于使用法术,【屠钧葵光】在我手中很是厉害。”
|
||||||
|
* 他伸出两指,将拇指抵在为食指根处,口中念诀,顿时放
|
||||||
|
* 出一阵刺目的寒光来,寒气凛凛,指尖飘散出一缕缕洁白无瑕的华光
|
||||||
|
* ,在空中四散飞舞。 李曦明只觉得面上生寒,身后汗毛根
|
||||||
|
* 根竖起,脚底下的地面浮现出一层白莹莹的霜,体力的真元流转都有
|
||||||
|
* 些不畅起来。 桌案上放着灵材,李曦峻不敢放开,只略微
|
||||||
|
* 展示,挥手散去法术,解释道: “屠钧葵光远不止在寒、
|
||||||
|
* 还在于阴,等我得了灵水,还能更上一层,到时候在打斗中运起这法
|
||||||
|
* 术,就算是修为高出我许多,猝不及防也要吃个闷亏。”
|
||||||
|
* 李曦明羡慕地看了看: “只可惜我功法乃是金阳一系,不
|
||||||
|
* 能修炼,《金殿煌元诀》虽好,却没有配套的法术与遁术。”
|
||||||
|
* 两人交谈一阵,青杜山大阵外传来一声娇喝: “玄岳
|
||||||
|
* 门孔氏,应约而来,还请开一开山门!” 两人微愣,驾风
|
||||||
|
* 而起,阵外正站着个素衣女子,腰间佩着金珠,挂着两把弯刀,姿容
|
||||||
|
* 绰约,后头则是个平平无奇的中年人,一言不发。 ‘好美
|
||||||
|
* 的女子。’ 李曦明性格平和,虽然有些留恋于女色,却还
|
||||||
|
* 不至于色令智昏,知道是筑基前辈,低垂着头不敢看。 李
|
||||||
|
* 曦峻则抱拳道: “来人可是孔婷云前辈?” “
|
||||||
|
* 不错,你是…?” 孔婷云看了他一眼,心中暗赞,客气几
|
||||||
|
* 分,轻声道: “蛟兄曾经与我约定为贵族修筑火脉,如今
|
||||||
|
* 我已应约而来。” “哗啦…” 言谈之间,望月
|
||||||
|
* 湖深青色的湖面轰然破开,一个黑袍青年驾风上来,阴沉沉地看了一
|
||||||
|
* 眼孔婷云,目光停留在她腰间配着两把弯刀上,脸色一下难看起来,
|
||||||
|
* 一言不发地立着。 孔婷云瞥了他一眼,只觉得很是眼熟,
|
||||||
|
* 震惊了一瞬,失声道: “钩蛇?!” 李乌梢深
|
||||||
|
* 深地出了两口气,低声下气地道: “钩蛇已死,在下是青
|
||||||
|
* 杜李乌梢,乌梢见过上仙。” 孔婷云很是不自然地应了,
|
||||||
|
* 埋藏多时的疑惑总算是解决: ‘我说李渊蛟怎地莫名其妙
|
||||||
|
* 、不嫌苦累一路把这钩蛇带回李家…原来是有控制妖物的法子…毕竟
|
||||||
|
* 靠近北方,也不足为奇。’ 只是她腰上还挂着钩蛇曾经的
|
||||||
|
* 尾钩炼制成的一对筑基法器,实在有些尴尬,钩蛇如今是李家的人,
|
||||||
|
* 该给的面子要给,默默把法器收到储物袋中,孔婷云道:
|
||||||
|
* “玄岳孔婷云,见过道友。” 李乌梢面色好看许多,默默
|
||||||
|
* 退到李曦峻身后。 李渊蛟与李清虹闭关,这担子自然落到
|
||||||
|
* 李曦峻身上,他客客气气地道: “还请前辈稍待些时日,
|
||||||
|
* 长辈正闭关,一时间不能出来迎接…” 孔婷云摆摆手,显
|
||||||
|
* 现出无所谓的模样,径直道: “用不着李渊蛟,伱指一座
|
||||||
|
* 山让我开了火脉,便把那阵盘还我,我便要离去了,没有多少闲功夫
|
||||||
|
* 。” 言罢,孔婷云还有些提心吊胆地疑问道:
|
||||||
|
* “那阵法不会给李渊蛟弄坏了,至今不敢见我?这可是贵重物件,要
|
||||||
|
* 是弄坏了,你家可赔得多了!” “前辈放心,自然无事。
|
||||||
|
* ” 李曦峻点头,火脉的选址本是李家计划好的,选在了乌
|
||||||
|
* 涂山。 火脉变动大多会影响周边的灵田,其余几峰都矗立
|
||||||
|
* 在大片灵田之中,唯独乌涂山孤零零地悬在山林中,只能选了这山。
|
||||||
|
* 孔婷云一示意,那练气巅峰的中年男子已经驾风落向乌涂
|
||||||
|
* 山,李曦峻带人驾风过去,一齐在空中看着。 亲,点击进去,给个
|
||||||
|
* 好评呗,分数越高更新越快,据说给香书小说打满分的最后都找到了
|
||||||
|
* 漂亮的老婆哦! 手机站全新改版升级地址:http://wap
|
||||||
|
* .xbiqugu.la,数据和书签与电脑站同步,无广告清新阅
|
||||||
|
* 读!
|
||||||
|
*/
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -35,27 +35,17 @@
|
|||||||
<el-card class="flex-1" shadow="never">
|
<el-card class="flex-1" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<!-- <el-col :span="1.5">
|
|
||||||
<el-button type="primary" plain icon="Plus" @click="handleMarkqrcode" v-has-permi="['equipment:addqrcode:electricitydevice']"
|
|
||||||
>批量生成条形码</el-button
|
|
||||||
>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button type="success" plain icon="Upload">批量更新固件</el-button>
|
|
||||||
</el-col> -->
|
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<div style="font-size: 0.8rem">电表列表</div>
|
<div style="font-size: 0.8rem">电表列表</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :show-add="false" :show-edit="false" :show-delete="false">
|
<right-toolbar :show-add="false" :show-edit="false" :show-delete="false">
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<!-- <el-dropdown-menu> -->
|
|
||||||
<el-dropdown-item @click="handleMarkqrcode" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
<el-dropdown-item @click="handleMarkqrcode" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
||||||
<span>批量生成条形码</span>
|
<span>批量生成条形码</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item @click="handleMarkQrcodeZip" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
<el-dropdown-item @click="handleMarkQrcodeZip" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
||||||
<span>批量下载条形码</span>
|
<span>批量下载条形码</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<!-- </el-dropdown-menu> -->
|
|
||||||
<!-- <el-dropdown-item v-has-permi="['equipment:addqrcode:electricitydevice']">
|
<!-- <el-dropdown-item v-has-permi="['equipment:addqrcode:electricitydevice']">
|
||||||
<div @click="handleMarkqrcode">批量更新固件</div>
|
<div @click="handleMarkqrcode">批量更新固件</div>
|
||||||
</el-dropdown-item> -->
|
</el-dropdown-item> -->
|
||||||
@@ -261,7 +251,7 @@ import {
|
|||||||
getElectricityDeviceTimeRangeUsedWater,
|
getElectricityDeviceTimeRangeUsedWater,
|
||||||
listElectricityDevice,
|
listElectricityDevice,
|
||||||
updateElectricityDevice
|
updateElectricityDevice
|
||||||
} from '@/api/system/SdbElectricityDevice/index';
|
} from '@/api/system/SdbElectricityDevice';
|
||||||
import { ElectricityDeviceVO } from '@/api/system/SdbElectricityDevice/type';
|
import { ElectricityDeviceVO } from '@/api/system/SdbElectricityDevice/type';
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
import { useHouseStore } from '@/store/modules/house';
|
||||||
import { useUserStore } from '@/store/modules/user';
|
import { useUserStore } from '@/store/modules/user';
|
||||||
@@ -510,7 +500,7 @@ function getTree() {
|
|||||||
|
|
||||||
/** 电表 启停*/
|
/** 电表 启停*/
|
||||||
// TODO 修改电表 启停
|
// TODO 修改电表 启停
|
||||||
const handleChangeWater = (val: string, row: ElectricityDeviceVO) => {};
|
// const handleChangeWater = (val: string, row: ElectricityDeviceVO) => {};
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
if (dialogType.value === 'usedWater') {
|
if (dialogType.value === 'usedWater') {
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ import {
|
|||||||
updateWaterDevice,
|
updateWaterDevice,
|
||||||
WaterDeviceUpdateBin,
|
WaterDeviceUpdateBin,
|
||||||
latestRecord
|
latestRecord
|
||||||
} from '@/api/system/SdbWaterDevice/index';
|
} from '@/api/system/SdbWaterDevice';
|
||||||
import { WaterDeviceVO } from '@/api/system/SdbWaterDevice/type';
|
import { WaterDeviceVO } from '@/api/system/SdbWaterDevice/type';
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
import { useHouseStore } from '@/store/modules/house';
|
||||||
import { useUserStore } from '@/store/modules/user';
|
import { useUserStore } from '@/store/modules/user';
|
||||||
@@ -614,7 +614,7 @@ function getTree() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 水表 启停*/
|
/** 水表 ╬«2222╬2╬22╬╬╬╬2╬22222╬ 启停*/
|
||||||
const handleChangeWater = (val: string, row: WaterDeviceVO) => {};
|
const handleChangeWater = (val: string, row: WaterDeviceVO) => {};
|
||||||
|
|
||||||
function handleUpdate(id: string) {
|
function handleUpdate(id: string) {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="WaterRecord" lang="ts">
|
<script setup name="WaterRecord" lang="ts">
|
||||||
import { listWaterRecord, getWaterRecord, delWaterRecord, addWaterRecord, updateWaterRecord } from '@/api/system/SdbWaterMeterReading/index';
|
import { listWaterRecord, getWaterRecord, delWaterRecord, addWaterRecord, updateWaterRecord } from '@/api/system/SdbWaterMeterReading';
|
||||||
import { WaterRecordVO, WaterRecordQuery, WaterRecordForm } from '@/api/system/SdbWaterMeterReading/type';
|
import { WaterRecordVO, WaterRecordQuery, WaterRecordForm } from '@/api/system/SdbWaterMeterReading/type';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SearchTime = val;
|
SearchTime = val;
|
||||||
const days = val;
|
const [star, end] = val.map((item) => item.split(' ')[0]);
|
||||||
const [star, end] = days.map((item) => item.split(' ')[0]);
|
|
||||||
queryParams.startDate = star + ' 00:00:00';
|
queryParams.startDate = star + ' 00:00:00';
|
||||||
queryParams.endDate = end + ' 23:59:59';
|
queryParams.endDate = end + ' 23:59:59';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ function init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
|
|
||||||
function back() {
|
function back() {
|
||||||
router.back();
|
router.back();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,12 +267,12 @@ function choiceResidentFun() {
|
|||||||
function handleChange(pop) {
|
function handleChange(pop) {
|
||||||
holderInfo.value = null;
|
holderInfo.value = null;
|
||||||
holderInfo.value = pop;
|
holderInfo.value = pop;
|
||||||
form.value.residentId = '';
|
form.value.userId = '';
|
||||||
form.value.residentName = '';
|
form.value.userName = '';
|
||||||
console.log(pop);
|
console.log(pop);
|
||||||
if (pop !== null) {
|
if (pop !== null) {
|
||||||
form.value.residentId = pop.user_id;
|
form.value.userId = pop.user_id;
|
||||||
form.value.residentName = pop.user_name;
|
form.value.userName = pop.user_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="info_item">
|
<div class="info_item">
|
||||||
<div class="label">设备状态:</div>
|
<div class="label">设备状态:</div>
|
||||||
<span class="value">电梯</span>
|
<dict-tag :options="com_equipment_archive_status" :value="form.status"></dict-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="info_item">
|
<div class="info_item">
|
||||||
<div class="label">维护人员:</div>
|
<div class="label">维护人员:</div>
|
||||||
@@ -88,6 +88,7 @@ import { delDeviceRepair, listDeviceRepair } from '@/api/system/equipment/Repair
|
|||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_equipment_repair_status } = toRefs<any>(proxy?.useDict('com_equipment_repair_status'));
|
const { com_equipment_repair_status } = toRefs<any>(proxy?.useDict('com_equipment_repair_status'));
|
||||||
|
const { com_equipment_archive_status } = toRefs<any>(proxy?.useDict('com_equipment_archive_status'));
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|||||||
@@ -220,6 +220,8 @@ const form = ref({
|
|||||||
vx: '', //微信
|
vx: '', //微信
|
||||||
houseUse: '0', //房屋用途
|
houseUse: '0', //房屋用途
|
||||||
rentalStatus: 0, //租赁状态
|
rentalStatus: 0, //租赁状态
|
||||||
|
buildingId: null, //楼栋id
|
||||||
|
unitNoId: null, //单元id
|
||||||
email: '' //邮箱
|
email: '' //邮箱
|
||||||
});
|
});
|
||||||
const userHousepath = ref<CascaderValue>([]);
|
const userHousepath = ref<CascaderValue>([]);
|
||||||
@@ -257,11 +259,9 @@ async function gettreedata() {
|
|||||||
...form.value,
|
...form.value,
|
||||||
...res.data
|
...res.data
|
||||||
};
|
};
|
||||||
housedeviceslist.value = form.value.facilities.split(',').filter((item) => item);
|
if (form.value.facilities) housedeviceslist.value = form.value.facilities.split(',').filter((item) => item);
|
||||||
const imgurllist = splitStringUrl(form.value.houseImageUrl);
|
if (form.value.houseImageUrl) fileList.value = splitStringUrl(form.value.houseImageUrl);
|
||||||
fileList.value = imgurllist;
|
handleChange([form.value.buildingId, form.value.unitNoId, form.value.houseId]);
|
||||||
const arr = getHousePathById(treedata.value, form.value.houseId);
|
|
||||||
userHousepath.value = arr;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsbox">
|
||||||
<div class="label">房屋:</div>
|
<div class="label">房屋:</div>
|
||||||
<div class="value">{{ HouseInfo.house }}</div>
|
<div class="value">{{ HouseInfo.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsbox">
|
||||||
<div class="label">业主姓名:</div>
|
<div class="label">业主姓名:</div>
|
||||||
@@ -104,10 +104,8 @@ import { getHousePathById } from '@/utils/house';
|
|||||||
import { listHouseFacilities } from '@/api/system/HouseFacilities';
|
import { listHouseFacilities } from '@/api/system/HouseFacilities';
|
||||||
|
|
||||||
const houseStore = useHouseStore();
|
const houseStore = useHouseStore();
|
||||||
const { treedata } = storeToRefs(houseStore);
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_rental_method } = toRefs<any>(proxy?.useDict('com_rental_method'));
|
const { com_rental_method } = toRefs<any>(proxy?.useDict('com_rental_method'));
|
||||||
const { com_house_rental_facilities } = toRefs<any>(proxy?.useDict('com_house_rental_facilities'));
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -145,15 +143,14 @@ async function init() {
|
|||||||
}
|
}
|
||||||
const reslist = await listHouseFacilities();
|
const reslist = await listHouseFacilities();
|
||||||
housefacilities.value = reslist.rows;
|
housefacilities.value = reslist.rows;
|
||||||
|
await houseStore.getCurrentVilageTreeHouse();
|
||||||
getHouseRental(houseRentalid.value).then((res) => {
|
getHouseRental(houseRentalid.value).then((res) => {
|
||||||
HouseInfo.value = res.data;
|
HouseInfo.value = res.data;
|
||||||
HouseInfo.value.facilitieslist = res.data.facilities.split(',').filter((item) => item);
|
HouseInfo.value.facilitieslist = res.data.facilities.split(',').filter((item) => item);
|
||||||
HouseInfo.value.houseImageUrls = HouseInfo.value.houseImageUrl.split(',').filter((item) => item);
|
HouseInfo.value.houseImageUrls = HouseInfo.value.houseImageUrl.split(',').filter((item) => item);
|
||||||
const arr = getHousePathById(treedata.value, HouseInfo.value.houseId, 'label');
|
|
||||||
HouseInfo.value.house = arr.join(' - ');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
//.╬
|
||||||
init();
|
init();
|
||||||
|
|
||||||
function handlefacilities(id: string) {
|
function handlefacilities(id: string) {
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ const route = useRoute();
|
|||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const form = ref<ResidentForm>({
|
const form = ref<ResidentForm>({
|
||||||
houseId: null,
|
houseId: null,
|
||||||
|
unitNoId: null,
|
||||||
name: '',
|
name: '',
|
||||||
gender: '0',
|
gender: '0',
|
||||||
idCard: '',
|
idCard: '',
|
||||||
@@ -178,8 +179,7 @@ function gettreedata() {
|
|||||||
form.value = {
|
form.value = {
|
||||||
...res.data
|
...res.data
|
||||||
};
|
};
|
||||||
const arr = getHousePathById(treedata.value, form.value.houseId);
|
userHousepath.value = [form.value.buildingId, form.value.unitNoId, form.value.houseId];
|
||||||
userHousepath.value = arr;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="证件号" min-width="120" align="center" prop="idCard" />
|
<el-table-column label="证件号" min-width="120" align="center" prop="idCard" />
|
||||||
<el-table-column label="手机号码" min-width="120" align="center" prop="phone" />
|
<el-table-column label="手机号码" min-width="120" align="center" prop="phone" />
|
||||||
<el-table-column label="房间" min-width="120" align="center" prop="houseAddress" />
|
<el-table-column label="房间" min-width="120" align="center" prop="houseName" />
|
||||||
<el-table-column label="操作" align="center" min-width="120" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" min-width="120" fixed="right" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button v-if="scope.row.status !== '1'" link type="primary" @click="handleMain(scope.row)" v-has-permi="['resident:resident:edit']"
|
<el-button v-if="scope.row.status !== '1'" link type="primary" @click="handleMain(scope.row)" v-has-permi="['resident:resident:edit']"
|
||||||
@@ -98,7 +98,6 @@ import DictTag from '@/components/DictTag/index.vue';
|
|||||||
|
|
||||||
import { listResident, delResident } from '@/api/system/resident';
|
import { listResident, delResident } from '@/api/system/resident';
|
||||||
import { ResidentVO, ResidentQuery, ResidentForm } from '@/api/system/resident/type';
|
import { ResidentVO, ResidentQuery, ResidentForm } from '@/api/system/resident/type';
|
||||||
import { getHousePathById } from '@/utils/house';
|
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
import { useHouseStore } from '@/store/modules/house';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|
||||||
@@ -229,10 +228,6 @@ const getList = async () => {
|
|||||||
listResident(queryParams.value)
|
listResident(queryParams.value)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
residentList.value = res.rows;
|
residentList.value = res.rows;
|
||||||
residentList.value.forEach((item) => {
|
|
||||||
const arr = getHousePathById(treated.value, item.houseId, 'label');
|
|
||||||
item.houseAddress = arr.join(' ');
|
|
||||||
});
|
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -324,6 +319,9 @@ onMounted(() => {
|
|||||||
width: 250px;
|
width: 250px;
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
.treeTitlebox {
|
.treeTitlebox {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
line-height: 60px;
|
line-height: 60px;
|
||||||
@@ -333,7 +331,11 @@ onMounted(() => {
|
|||||||
background-color: rgba(233, 242, 255, 0.5);
|
background-color: rgba(233, 242, 255, 0.5);
|
||||||
color: rgba(16, 16, 16, 1);
|
color: rgba(16, 16, 16, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.treeboxbody {
|
.treeboxbody {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
|
||||||
&:deep(.el-tree-node__content) {
|
&:deep(.el-tree-node__content) {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ import { allocatedUserList, authUserCancel, authUserCancelAll } from '@/api/syst
|
|||||||
import { UserQuery } from '@/api/system/user/types';
|
import { UserQuery } from '@/api/system/user/types';
|
||||||
import { UserVO } from '@/api/system/user/types';
|
import { UserVO } from '@/api/system/user/types';
|
||||||
import SelectUser from './selectUser.vue';
|
import SelectUser from './selectUser.vue';
|
||||||
import { RouteLocationNormalized } from 'vue-router';
|
import { RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@@ -115,7 +115,7 @@ const handleClose = () => {
|
|||||||
query: undefined,
|
query: undefined,
|
||||||
redirectedFrom: undefined
|
redirectedFrom: undefined
|
||||||
};
|
};
|
||||||
proxy?.$tab.closeOpenPage(obj);
|
proxy?.$tab.closeOpenPage(obj as RouteLocationRaw);
|
||||||
};
|
};
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<script name="RingProgress" setup lang="ts">
|
||||||
|
import { EChartsOption } from 'echarts';
|
||||||
|
import Echarts from '@/components/Echarts/index.vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
color: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
console.log(props.name, props.value);
|
||||||
|
|
||||||
|
const options = ref<EChartsOption>({
|
||||||
|
tooltip: {
|
||||||
|
show: false,
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{b}: {c}%'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '80%'], // 环形大小
|
||||||
|
center: ['50%', '50%'], // 每个图表各自居中
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: 100 - Number(props.value),
|
||||||
|
itemStyle: {
|
||||||
|
color: '#ebeef5' // 背景色
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
color: '#ebeef5'
|
||||||
|
},
|
||||||
|
scale: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: Number(props.value),
|
||||||
|
name: props.name,
|
||||||
|
itemStyle: { color: props.color, borderRadius: 8, borderColor: props.color, borderWidth: 0 },
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'center', // 显示在圆环中心
|
||||||
|
formatter: '{c}%', // 显示百分比数值
|
||||||
|
// fontSize: '50%',
|
||||||
|
// fontWeight: 'bold',
|
||||||
|
color: '#4ce19c',
|
||||||
|
rich: {
|
||||||
|
num: {
|
||||||
|
fontSize: '28%', // 富文本内支持百分比,相对圆环直径
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#4ce19c'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
scale: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="chart-item flex flex-col items-center" style="flex: 1; height: 100%">
|
||||||
|
<Echarts :options="options as EChartsOption" style="width: 100%; height: 165px"></Echarts>
|
||||||
|
<div class="chart-item-name">{{ props.name }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.chart-item {
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-item-name {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -13,47 +13,42 @@
|
|||||||
<el-button type="primary" @click="querySearch">查询</el-button>
|
<el-button type="primary" @click="querySearch">查询</el-button>
|
||||||
<el-button @click="reset">重置</el-button>
|
<el-button @click="reset">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-bottom: 15px; position: relative; z-index: 2">
|
<div style="position: relative; z-index: 2">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :lg="14" :xl="14">
|
<el-col :lg="14" :xl="14" style="margin-bottom: 15px">
|
||||||
<div class="cardbox">
|
<div class="cardbox">
|
||||||
<div>收入来源</div>
|
<div>收入来源</div>
|
||||||
<div class="card_infoall">
|
<div class="card_InfoAll">
|
||||||
<div>应缴费用:{{ formatMoneyWithUnit(form.totalDue) }}</div>
|
<div>应缴费用:{{ formatMoneyWithUnit(sourceFrom.totalPayable) }}</div>
|
||||||
<div>已收:{{ formatMoneyWithUnit(form.totalPaid) }}</div>
|
<div>已收:{{ formatMoneyWithUnit(sourceFrom.totalReceived) }}</div>
|
||||||
<div>待收:{{ formatMoneyWithUnit(form.totalUnpaid) }}</div>
|
<div>待收:{{ formatMoneyWithUnit(sourceFrom.totalPending) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cardbody" style="height: 165px">
|
<div class="cardBody" style="display: flex; flex-wrap: wrap" v-if="sourceFromIsComputed">
|
||||||
<div
|
<RingProgress name="停车费" color="#1a75ff" :value="sourceFrom.parkingFeePercent"></RingProgress>
|
||||||
v-for="(opt, index) in incomeChartOptions"
|
<RingProgress name="物业费" color="#ffbf05" :value="sourceFrom.propertyFeePercent"></RingProgress>
|
||||||
:key="index"
|
<RingProgress name="水电费" color="#6c76f4" :value="sourceFrom.utilityFeePercent"></RingProgress>
|
||||||
class="chart-item flex flex-col items-center"
|
<RingProgress name="商铺租金" color="#fa746b" :value="sourceFrom.shopRentPercent"></RingProgress>
|
||||||
style="width: 165px; height: 100%"
|
<RingProgress name="维修费" color="#3fdf95" :value="sourceFrom.repairFeePercent"></RingProgress>
|
||||||
>
|
<RingProgress name="垃圾处理费" color="#1e1b39" :value="sourceFrom.garbageFeePercent"></RingProgress>
|
||||||
<Echarts :options="opt.options ?? []" style="width: 100%; height: 165px"></Echarts>
|
|
||||||
<!-- 如果需要额外显示名称,可以在这里加 div,但图表中心已显示 -->
|
|
||||||
<div class="chart-item-name">{{ opt.name }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :lg="10" :xl="10" style="margin-bottom: 15px">
|
||||||
<el-col :lg="10" :xl="10">
|
|
||||||
<div class="cardbox">
|
<div class="cardbox">
|
||||||
<div>欠费分布</div>
|
<div>缴费方式</div>
|
||||||
<div class="cardbody w-full" style="height: 150px">
|
<div class="cardBody w-full" style="height: 100%">
|
||||||
<Echarts :options="options2"></Echarts>
|
<Echarts :options="options2"></Echarts>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-bottom: 15px; position: relative; z-index: 2">
|
<div style="position: relative; z-index: 2">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :lg="12" :xl="14">
|
<el-col :lg="12" :xl="14" style="margin-bottom: 15px">
|
||||||
<div class="cardbox w-full">
|
<div class="cardbox w-full">
|
||||||
<div>欠费分布</div>
|
<div>欠费分布</div>
|
||||||
<div class="cardbody w-full" style="height: 330px">
|
<div class="cardBody w-full" style="height: 330px">
|
||||||
<Echarts :options="options3"></Echarts>
|
<Echarts :options="options3"></Echarts>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,7 +67,7 @@
|
|||||||
<span class="ml-2">{{ item.label }}</span>
|
<span class="ml-2">{{ item.label }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="circlebox">
|
<ul class="circleBox">
|
||||||
<li :data-level="index" :style="{ backgroundColor: item.color }" v-for="(item, index) in sortPayList" :key="index">
|
<li :data-level="index" :style="{ backgroundColor: item.color }" v-for="(item, index) in sortPayList" :key="index">
|
||||||
{{ item.number }}%
|
{{ item.number }}%
|
||||||
</li>
|
</li>
|
||||||
@@ -90,7 +85,7 @@
|
|||||||
</div> -->
|
</div> -->
|
||||||
<div class="cardbox w-full">
|
<div class="cardbox w-full">
|
||||||
<div>缴费走势分析</div>
|
<div>缴费走势分析</div>
|
||||||
<div class="cardbody w-full" style="height: 400px">
|
<div class="cardBody w-full" style="height: 400px">
|
||||||
<Echarts :options="flowLineOption"></Echarts>
|
<Echarts :options="flowLineOption"></Echarts>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -110,59 +105,48 @@ import Echarts from '@/components/Echarts/index.vue';
|
|||||||
import { formatMoneyWithUnit } from '@/utils/money';
|
import { formatMoneyWithUnit } from '@/utils/money';
|
||||||
import { EChartsOption } from 'echarts';
|
import { EChartsOption } from 'echarts';
|
||||||
import { getLast7Days, getPastDayDate } from '@/utils/time';
|
import { getLast7Days, getPastDayDate } from '@/utils/time';
|
||||||
import { income_statsApi } from '@/api/system/Payment';
|
import {
|
||||||
|
arrears_distributionApi,
|
||||||
const open = ref(false);
|
Arrears_distrubution,
|
||||||
const dataTime = ref('2025-01-01');
|
income_scourcApi,
|
||||||
const form = ref({
|
payment_methodApi,
|
||||||
'totalDue': '',
|
payment_sourceApi,
|
||||||
'totalPaid': '',
|
payment_trendApi,
|
||||||
'totalUnpaid': '',
|
payment_trendType,
|
||||||
'paidPercentage': '',
|
PayMentMethod
|
||||||
'payWx': null,
|
} from '@/api/system/Payment';
|
||||||
'payZfb': null,
|
import RingProgress from './compontents/RingProgress.vue';
|
||||||
'payOffline': null,
|
|
||||||
'totalPay': null,
|
|
||||||
'feeTypeStats': [],
|
|
||||||
'dailyStats': []
|
|
||||||
});
|
|
||||||
|
|
||||||
const defaultDay = 30; // 默认查询近30天数据
|
const defaultDay = 30; // 默认查询近30天数据
|
||||||
|
const open = ref(false);
|
||||||
|
const last10Day = getPastDayDate(defaultDay);
|
||||||
|
const dataTime = ref(last10Day);
|
||||||
|
|
||||||
|
const sourceFromIsComputed = ref(true);
|
||||||
/** 收入来源 */
|
/** 收入来源 */
|
||||||
/** 收入来源图表配置 */
|
const sourceFrom = ref({
|
||||||
const incomeChartOptions = ref<
|
'totalPayable': '0',
|
||||||
{
|
'totalReceived': '0',
|
||||||
name: string;
|
'totalPending': '0',
|
||||||
options?: EChartsOption;
|
|
||||||
}[]
|
'parkingFee': '0',
|
||||||
>(
|
'parkingFeePercent': '0',
|
||||||
[
|
|
||||||
{
|
'propertyFee': '0',
|
||||||
'name': '停车费'
|
'propertyFeePercent': '0',
|
||||||
},
|
|
||||||
{
|
'utilityFee': '0',
|
||||||
'name': '物业费'
|
'utilityFeePercent': '0',
|
||||||
},
|
|
||||||
{
|
'shopRent': '0',
|
||||||
'name': '水电费'
|
'shopRentPercent': '0',
|
||||||
},
|
|
||||||
{
|
'repairFee': '0',
|
||||||
'name': '商铺租金'
|
'repairFeePercent': '0',
|
||||||
},
|
|
||||||
{
|
'garbageFee': '0',
|
||||||
'name': '维修费'
|
'garbageFeePercent': '0'
|
||||||
}
|
});
|
||||||
].map((i) => {
|
|
||||||
return {
|
|
||||||
name: i.name,
|
|
||||||
options: {
|
|
||||||
tooltip: {},
|
|
||||||
series: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
/** 缴费方式 */
|
/** 缴费方式 */
|
||||||
const options2 = shallowRef<EChartsOption>({
|
const options2 = shallowRef<EChartsOption>({
|
||||||
@@ -199,23 +183,54 @@ const options2 = shallowRef<EChartsOption>({
|
|||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
data: [
|
data: [
|
||||||
{ value: 50, name: '支付宝', itemStyle: { color: '#0a74fe' } },
|
{ value: 0, name: '支付宝', itemStyle: { color: '#0a74fe' } },
|
||||||
{ value: 30, name: '微信', itemStyle: { color: '#f74043' } },
|
{ value: 0, name: '微信', itemStyle: { color: '#f74043' } },
|
||||||
{ value: 20, name: '线下', itemStyle: { color: '#fcd152' } }
|
{ value: 0, name: '线下', itemStyle: { color: '#fcd152' } }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
function updatePayMethod(dataFrom: PayMentMethod): EChartsOption {
|
||||||
|
return {
|
||||||
|
legend: {
|
||||||
|
top: 'center',
|
||||||
|
left: '0',
|
||||||
|
orient: 'vertical',
|
||||||
|
itemGap: 50,
|
||||||
|
itemWidth: 12, // 图例色块宽度
|
||||||
|
itemHeight: 12 // 图例色块高度
|
||||||
|
},
|
||||||
|
clockwise: true,
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '缴费方式',
|
||||||
|
type: 'pie',
|
||||||
|
startAngle: 280,
|
||||||
|
radius: ['50%', '100%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
left: '50%',
|
||||||
|
emphasis: {
|
||||||
|
scale: true,
|
||||||
|
scaleSize: 6
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: Number(dataFrom.alipayAmount) ?? 0, name: '支付宝', itemStyle: { color: '#0a74fe' } },
|
||||||
|
{ value: Number(dataFrom.wechatAmount) ?? 0, name: '微信', itemStyle: { color: '#f74043' } },
|
||||||
|
{ value: Number(dataFrom.offlineAmount) ?? 0, name: '线下', itemStyle: { color: '#fcd152' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 【新增】定义12个月份
|
// 【新增】定义12个月份
|
||||||
const monthX = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
|
const monthX = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
|
||||||
/** 欠费分布 散点图 */
|
/** 欠费分布 散点图 */
|
||||||
/** 欠费分布 散点图 (带特效版) */
|
|
||||||
const options3 = shallowRef<EChartsOption>({
|
const options3 = shallowRef<EChartsOption>({
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
formatter: (params: any) => {
|
formatter: (params: any) => {
|
||||||
return `${monthX[params.value[0]]}<br/>欠费金额: <b>${params.value[1]}</b> 万元`;
|
return `${params.name}<br/>欠费金额: <b>${formatMoneyWithUnit(params.value[1])}</b>`;
|
||||||
},
|
},
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||||
borderColor: '#eee',
|
borderColor: '#eee',
|
||||||
@@ -304,7 +319,92 @@ const options3 = shallowRef<EChartsOption>({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
function UpdateOptions3(data: Arrears_distrubution[]): EChartsOption {
|
||||||
|
const xData = data.map((item, index) => {
|
||||||
|
return [index, item.amount];
|
||||||
|
});
|
||||||
|
const xMonth = data.map((item) => `${item.month}月`);
|
||||||
|
return {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: (params: any) => {
|
||||||
|
return `${params.name}<br/>欠费金额: <b>${formatMoneyWithUnit(params.value[1])}</b>`;
|
||||||
|
},
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||||
|
borderColor: '#eee',
|
||||||
|
textStyle: { color: '#333' }
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '1%',
|
||||||
|
right: '2%',
|
||||||
|
top: '12%',
|
||||||
|
bottom: '12%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: xMonth,
|
||||||
|
boundaryGap: false,
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
length: 5, // 刻度线长度
|
||||||
|
lineStyle: { color: '#ccc' }
|
||||||
|
},
|
||||||
|
axisLine: { lineStyle: { color: '#eee' }, onZero: false },
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666',
|
||||||
|
interval: 0, // 强制显示所有月份
|
||||||
|
margin: 12 // 标签与轴线的距离
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#f0f0f0',
|
||||||
|
type: 'dashed',
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: '金额(万元)',
|
||||||
|
nameTextStyle: { color: '#999', padding: [0, 0, 0, 10] },
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#f0f0f0',
|
||||||
|
type: 'dashed' // 虚线网格更轻盈
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: { color: '#999', margin: 20 }
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '欠费金额',
|
||||||
|
type: 'scatter',
|
||||||
|
symbolSize: (data: any) => {
|
||||||
|
const value = data[1];
|
||||||
|
return Math.min(Math.max(value * 1.5, 10), 40);
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: (params: any) => {
|
||||||
|
const index = params.dataIndex;
|
||||||
|
if (index % 2 === 0) {
|
||||||
|
return '#739ff0';
|
||||||
|
} else {
|
||||||
|
return '#86c9d0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 【特效 2】高亮状态(鼠标悬停)
|
||||||
|
emphasis: {
|
||||||
|
scale: 1.2 // 悬停时额外放大
|
||||||
|
},
|
||||||
|
data: xData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
// ! 进十日缴费数量情况 -------------------------------------------------------------------------------------
|
// ! 进十日缴费数量情况 -------------------------------------------------------------------------------------
|
||||||
// 近10天日期
|
// 近10天日期
|
||||||
const dayX = getLast7Days(10);
|
const dayX = getLast7Days(10);
|
||||||
@@ -393,50 +493,65 @@ const flowLineOption = shallowRef<EChartsOption>({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
// ! 进十日缴费数量情况 -------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const paytypelist = ref([
|
const payTypeList = ref([
|
||||||
{ label: '微信', value: 'payWx', number: 0, color: '#4a3afe' },
|
{ label: '小程序', number: 0, color: '#4a3afe' },
|
||||||
{ label: '支付宝', value: 'payZfb', number: 0, color: '#1e1b39' },
|
{ label: '线下缴费', number: 0, color: '#1e1b39' },
|
||||||
{ label: '线下', value: 'payOffline', number: 0, color: '#c893fd' }
|
{ label: '手机APP', number: 0, color: '#c893fd' }
|
||||||
]);
|
]);
|
||||||
// 排序后
|
// 排序后
|
||||||
const sortPayList = ref([]);
|
const sortPayList = ref(payTypeList.value);
|
||||||
|
|
||||||
|
const payMethodFrom = ref({
|
||||||
|
'wechatAmount': '0',
|
||||||
|
'wechatPercent': '0',
|
||||||
|
'alipayAmount': '0',
|
||||||
|
'alipayPercent': '0',
|
||||||
|
'offlineAmount': '0',
|
||||||
|
'offlinePercent': '0'
|
||||||
|
});
|
||||||
|
|
||||||
function getList() {
|
function getList() {
|
||||||
const startData = getPastDayDate(defaultDay);
|
sourceFromIsComputed.value = false;
|
||||||
income_statsApi(dataTime.value === '' ? startData : dataTime.value).then((res) => {
|
// 收入来源
|
||||||
form.value = res.data;
|
income_scourcApi(dataTime.value)
|
||||||
const { payOffline, payWx, payZfb, feeTypeStats, dailyStats } = res.data;
|
.then((res) => {
|
||||||
const total = (payOffline ?? 0) + (payWx ?? 0) + (payZfb ?? 0);
|
sourceFrom.value = res.data;
|
||||||
if (total > 0) {
|
})
|
||||||
form.value.payOffline = Number.isNaN((payOffline / total) * 100) ? 0 : ((payOffline / total) * 100).toFixed(2);
|
.finally(() => {
|
||||||
form.value.payWx = Number.isNaN((payWx / total) * 100) ? 0 : ((payWx / total) * 100).toFixed(2);
|
setTimeout(() => {
|
||||||
form.value.payZfb = Number.isNaN((payZfb / total) * 100) ? 0 : ((payZfb / total) * 100).toFixed(2);
|
sourceFromIsComputed.value = true;
|
||||||
const payTypeList = JSON.parse(JSON.stringify(paytypelist.value));
|
});
|
||||||
payTypeList[0].number = form.value.payWx;
|
});
|
||||||
payTypeList[1].number = form.value.payZfb;
|
// 缴费方式
|
||||||
payTypeList[2].number = form.value.payOffline;
|
payment_methodApi(dataTime.value).then((res) => {
|
||||||
sortPayList.value = payTypeList.toSorted((a, b) => Number(b.number) - Number(a.number));
|
payMethodFrom.value = res.data;
|
||||||
}
|
options2.value = updatePayMethod(res.data);
|
||||||
|
});
|
||||||
// 收入来源
|
// 欠费分布
|
||||||
// 2. 处理收入来源 (新逻辑)
|
arrears_distributionApi(dataTime.value).then((res) => {
|
||||||
if (feeTypeStats && Array.isArray(feeTypeStats)) {
|
options3.value = UpdateOptions3(res.data.items);
|
||||||
updateIncomeChart(feeTypeStats);
|
});
|
||||||
}
|
//缴费来源
|
||||||
|
payment_sourceApi(dataTime.value).then((res) => {
|
||||||
// 3. 【新增】处理缴费走势 (近十日缴费情况)
|
const payTypeListCopy = JSON.parse(JSON.stringify(payTypeList.value));
|
||||||
if (dailyStats && Array.isArray(dailyStats)) {
|
payTypeListCopy[0].number = res.data.miniProgramPercent;
|
||||||
updateFlowLineChart(dailyStats);
|
payTypeListCopy[1].number = res.data.offlinePercent;
|
||||||
}
|
payTypeListCopy[2].number = res.data.mobileAppPercent;
|
||||||
|
sortPayList.value = payTypeListCopy.toSorted(
|
||||||
|
(a: { number: string | number }, b: { number: string | number }) => Number(b.number) - Number(a.number)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
// 缴费走势
|
||||||
|
payment_trendApi(dataTime.value, getPastDayDate(0)).then((res) => {
|
||||||
|
updateFlowLineChart(res.data.items);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 更新缴费走势图表
|
* 更新缴费走势图表
|
||||||
* @param stats 后端返回的 dailyStats 数组
|
* @param stats 后端返回的 dailyStats 数组&
|
||||||
*/
|
*/
|
||||||
function updateFlowLineChart(stats: any[]) {
|
function updateFlowLineChart(stats: payment_trendType[]) {
|
||||||
if (!stats.length) {
|
if (!stats.length) {
|
||||||
flowLineOption.value.series = [];
|
flowLineOption.value.series = [];
|
||||||
flowLineOption.value.xAxis.data = [];
|
flowLineOption.value.xAxis.data = [];
|
||||||
@@ -444,13 +559,13 @@ function updateFlowLineChart(stats: any[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 提取数据
|
// 提取数据
|
||||||
const dates = stats.map((item) => item.statDate);
|
const dates = stats.map((item) => item.date);
|
||||||
const paidData = stats.map((item) => Number(item.totalPaid) || 0);
|
const paidData = stats.map((item) => Number(item.paidAmount) || 0);
|
||||||
const unpaidData = stats.map((item) => Number(item.totalUnpaid) || 0);
|
const unpaidData = stats.map((item) => Number(item.unpaidAmount) || 0);
|
||||||
|
|
||||||
// 更新图表配置
|
// 更新图表配置
|
||||||
// 使用 shallowRef 时,建议替换整个对象或确保深层属性被正确追踪
|
// 使用 shallowRef 时,建议替换整个对象或确保深层属性被正确追踪
|
||||||
// 这里我们直接修改 series 和 xAxis 的数据
|
// 这里我们直接修改 series 和 xAxis 的数据 ╬╬
|
||||||
flowLineOption.value = {
|
flowLineOption.value = {
|
||||||
...flowLineOption.value,
|
...flowLineOption.value,
|
||||||
xAxis: {
|
xAxis: {
|
||||||
@@ -507,96 +622,12 @@ function updateFlowLineChart(stats: any[]) {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 更新收入来源图表数组
|
|
||||||
* @param stats 后端返回的 feeTypeStats 数组
|
|
||||||
*/
|
|
||||||
function updateIncomeChart(stats: any[]) {
|
|
||||||
incomeChartOptions.value = [];
|
|
||||||
let statslist = stats;
|
|
||||||
if (statslist.length === 0) {
|
|
||||||
statslist = [
|
|
||||||
{
|
|
||||||
'feeName': '停车费'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'feeName': '物业费'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'feeName': '水电费'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'feeName': '商铺租金'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'feeName': '维修费'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
incomeChartOptions.value = statslist.map((item) => {
|
|
||||||
const percentage = Number(item.paidPercentage) || 0;
|
|
||||||
const color = '#409eff';
|
|
||||||
return {
|
|
||||||
name: item.feeName, // 图表名称
|
|
||||||
options: {
|
|
||||||
tooltip: {
|
|
||||||
show: false,
|
|
||||||
trigger: 'item',
|
|
||||||
formatter: '{b}: {c}%'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
radius: ['50%', '70%'], // 环形大小
|
|
||||||
center: ['50%', '50%'], // 每个图表各自居中
|
|
||||||
select: {
|
|
||||||
scale: false
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: 100 - percentage,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#ebeef5' // 背景色
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
color: '#ebeef5'
|
|
||||||
},
|
|
||||||
scale: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: percentage,
|
|
||||||
name: item.feeName,
|
|
||||||
itemStyle: { color: color },
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'center', // 显示在圆环中心
|
|
||||||
formatter: '{c}%', // 显示百分比数值
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: '#4ce19c'
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
scale: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
console.log(incomeChartOptions.value);
|
|
||||||
}
|
|
||||||
function querySearch() {
|
function querySearch() {
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
function reset() {
|
function reset() {
|
||||||
dataTime.value = '';
|
dataTime.value = getPastDayDate(defaultDay);
|
||||||
querySearch();
|
querySearch();
|
||||||
}
|
}
|
||||||
getList();
|
getList();
|
||||||
@@ -632,6 +663,7 @@ onUnmounted(() => {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
min-height: 275px;
|
min-height: 275px;
|
||||||
|
height: 100%;
|
||||||
@media (max-width: 1600px) {
|
@media (max-width: 1600px) {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
@@ -641,7 +673,7 @@ onUnmounted(() => {
|
|||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.card_infoall {
|
.card_InfoAll {
|
||||||
padding-left: 40px;
|
padding-left: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -653,7 +685,7 @@ onUnmounted(() => {
|
|||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardbody {
|
.cardBody {
|
||||||
padding: 0 30px;
|
padding: 0 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -663,10 +695,10 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
.card_leftbox {
|
.card_leftbox {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
.labelbox {
|
.labelBox {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
.valuebox {
|
.valueBox {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
color: #222222;
|
color: #222222;
|
||||||
@@ -683,7 +715,6 @@ onUnmounted(() => {
|
|||||||
li {
|
li {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100px;
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -700,7 +731,7 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.circlebox {
|
.circleBox {
|
||||||
margin-left: 60px;
|
margin-left: 60px;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
|||||||
@@ -17,13 +17,13 @@
|
|||||||
<el-col :lg="8" :xl="8">
|
<el-col :lg="8" :xl="8">
|
||||||
<div class="cardbox">
|
<div class="cardbox">
|
||||||
<div>入住情况</div>
|
<div>入住情况</div>
|
||||||
<div class="cardbody" style="height: 200px">
|
<div class="cardBody" style="height: 200px">
|
||||||
<div class="card_leftbox">
|
<div class="card_LeftBox">
|
||||||
<div class="valuebox">{{ movein.totalResident }}</div>
|
<div class="valueBox">{{ MoveIn.totalResident }}</div>
|
||||||
<div class="labelbox">入住人数</div>
|
<div class="labelBox">入住人数</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="echartsbox h-full">
|
<div class="echartsBox h-full">
|
||||||
<Echarts :options="options"></Echarts>
|
<Echarts :options="options as EChartsOption"></Echarts>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,16 +31,16 @@
|
|||||||
<el-col :lg="10" :xl="8">
|
<el-col :lg="10" :xl="8">
|
||||||
<div class="cardbox">
|
<div class="cardbox">
|
||||||
<div>住户类型情况</div>
|
<div>住户类型情况</div>
|
||||||
<div class="cardbody w-full" style="height: 150px">
|
<div class="cardBody w-full" style="height: 180px">
|
||||||
<Echarts :options="options1"></Echarts>
|
<Echarts :options="options1 as EChartsOption"></Echarts>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :lg="6" :xl="8">
|
<el-col :lg="6" :xl="8">
|
||||||
<div class="cardbox">
|
<div class="cardbox">
|
||||||
<div>男女比例</div>
|
<div>男女比例</div>
|
||||||
<div class="cardbody w-full" style="height: 150px">
|
<div class="cardBody w-full" style="height: 180px">
|
||||||
<Echarts :options="options2"></Echarts>
|
<Echarts :options="options2 as EChartsOption"></Echarts>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<el-row style="margin-top: 20px; position: relative; z-index: 2">
|
<el-row style="margin-top: 20px; position: relative; z-index: 2">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<div class="cardbox w-full" style="height: 450px">
|
<div class="cardbox w-full" style="height: 450px">
|
||||||
<Echarts :options="flowLineOption"></Echarts>
|
<Echarts :options="flowLineOption as EChartsOption"></Echarts>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -68,12 +68,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// TODO 人员分析
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import Echarts from '@/components/Echarts/index.vue';
|
import Echarts from '@/components/Echarts/index.vue';
|
||||||
import { EChartsOption } from 'echarts';
|
import { EChartsOption } from 'echarts';
|
||||||
import { getLastNDays } from '@/utils/time';
|
import { getLastNDays } from '@/utils/time';
|
||||||
import { get_movein_moveout_list, get_movein_user_sex, get_movein_user_type, user_movein_list } from '@/api/system/Personnel';
|
import { get_movein_moveout_list, get_movein_user_sex, get_movein_user_type, get_person_age, user_movein_list } from '@/api/system/Personnel';
|
||||||
|
|
||||||
const date = ref('');
|
const date = ref('');
|
||||||
const open = ref(true);
|
const open = ref(true);
|
||||||
@@ -86,25 +85,29 @@ onUnmounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
date.value = '';
|
date.value = getLastNDays(10)[0];
|
||||||
|
querySelect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 入住情况 */
|
/** 入住情况 */
|
||||||
const options = ref<EChartsOption>({
|
const options = ref<EChartsOption>({
|
||||||
tooltip: { show: false },
|
tooltip: { show: true, trigger: 'item' },
|
||||||
series: [
|
series: [
|
||||||
// 1. 底层细圆环(灰色底色)
|
// 1. 底层细圆环(灰色底色)
|
||||||
{
|
{
|
||||||
|
name: '总房屋',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['68%', '90%'], // 细一点
|
radius: ['68%', '90%'], // 细一点
|
||||||
clockwise: true,
|
clockwise: true,
|
||||||
data: [100],
|
data: [100],
|
||||||
itemStyle: { color: '#ebeef5' },
|
itemStyle: { color: '#ebeef5' },
|
||||||
emphasis: { disabled: true },
|
emphasis: { disabled: true },
|
||||||
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
label: { show: false }
|
label: { show: false }
|
||||||
},
|
},
|
||||||
// 2. 上层粗圆环(进度条)
|
// 2. 上层粗圆环(进度条)
|
||||||
{
|
{
|
||||||
|
name: '入住房屋',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['65%', '98%'], // 粗一点
|
radius: ['65%', '98%'], // 粗一点
|
||||||
clockwise: true,
|
clockwise: true,
|
||||||
@@ -132,33 +135,39 @@ const options = ref<EChartsOption>({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: [{ value: 85 }, { value: 15, itemStyle: { color: 'transparent' } }]
|
data: [
|
||||||
|
{ value: 85 },
|
||||||
|
{
|
||||||
|
value: 15,
|
||||||
|
itemStyle: { color: 'transparent' }
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 入住类型 */
|
/** 住户类型 */
|
||||||
const options1 = ref<EChartsOption>({
|
const options1 = ref<EChartsOption>({
|
||||||
legend: {
|
legend: {
|
||||||
top: 'center',
|
top: 'center',
|
||||||
left: '0',
|
left: '0',
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
itemGap: 50
|
itemGap: 80
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Access From',
|
name: '住户类型',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['50%', '100%'],
|
radius: ['45%', '95%'],
|
||||||
avoidLabelOverlap: false,
|
avoidLabelOverlap: false,
|
||||||
left: '50%',
|
left: '50%',
|
||||||
label: {
|
label: {
|
||||||
show: false,
|
show: false,
|
||||||
position: 'center'
|
position: 'center'
|
||||||
},
|
},
|
||||||
tooltip: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
emphasis: {
|
emphasis: {
|
||||||
label: {
|
label: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -185,12 +194,15 @@ const options2 = ref<EChartsOption>({
|
|||||||
top: 'center',
|
top: 'center',
|
||||||
left: '0',
|
left: '0',
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
itemGap: 50
|
itemGap: 80
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
},
|
},
|
||||||
clockwise: true,
|
clockwise: true,
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Access From',
|
name: '男女比例',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
startAngle: 280,
|
startAngle: 280,
|
||||||
radius: ['50%', '100%'],
|
radius: ['50%', '100%'],
|
||||||
@@ -200,9 +212,6 @@ const options2 = ref<EChartsOption>({
|
|||||||
show: false,
|
show: false,
|
||||||
position: 'center'
|
position: 'center'
|
||||||
},
|
},
|
||||||
tooltip: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
emphasis: {
|
emphasis: {
|
||||||
label: {
|
label: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -221,15 +230,23 @@ const options2 = ref<EChartsOption>({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
// ! 年龄分布 -------------------------------------------------------------------------------------
|
// ! 年龄分布 -----------------------------------------
|
||||||
const agesX = ['6岁以下', '6-11岁', '11-14岁', '15-24岁', '25-30岁', '31-40岁', '41-50岁', '51-61岁', '61-65岁', '65-70岁', '70岁以上'];
|
const agesX = ['6岁以下', '6-11岁', '11-14岁', '15-24岁', '25-30岁', '31-40岁', '41-50岁', '51-61岁', '61-65岁', '65-70岁', '70岁以上'];
|
||||||
const agesData = [520, 680, 460, 750, 1350, 1860, 1420, 960, 630, 380, 210];
|
const agesData = ref(new Array(11).fill(0));
|
||||||
// 🔥 关键:灰色背景数据 = 最大值 - 真实数据(互补100%)
|
const maxValue = ref(10); // 设定总高度
|
||||||
const maxValue = 2000; // 设定总高度(可自行调整)
|
const middleHeight = 0.05; // 中间白条高度
|
||||||
const middleHeight = 20;
|
const barWidth = '10%'; // 柱状图粗度
|
||||||
const barwidth = '10%';
|
const bgData = computed(() => {
|
||||||
const bgData = agesData.map((item) => maxValue - item - middleHeight);
|
return agesData.value.map((item) => {
|
||||||
const bgData2 = agesData.map((item) => middleHeight);
|
const num = maxValue.value - item - middleHeight;
|
||||||
|
if (num > 0) {
|
||||||
|
return num;
|
||||||
|
} else {
|
||||||
|
return maxValue.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const bgData2 = agesX.map(() => middleHeight);
|
||||||
/** 年龄分布 */
|
/** 年龄分布 */
|
||||||
const options3 = shallowRef<EChartsOption>({
|
const options3 = shallowRef<EChartsOption>({
|
||||||
title: {
|
title: {
|
||||||
@@ -250,19 +267,16 @@ const options3 = shallowRef<EChartsOption>({
|
|||||||
confine: true,
|
confine: true,
|
||||||
axisPointer: { type: 'shadow' }
|
axisPointer: { type: 'shadow' }
|
||||||
},
|
},
|
||||||
// 鼠标悬浮高亮当前,其他隐藏
|
|
||||||
|
|
||||||
xAxis: { type: 'category', data: agesX, axisLabel: { interval: 0 } },
|
xAxis: { type: 'category', data: agesX, axisLabel: { interval: 0 } },
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
splitLine: { show: true, lineStyle: { color: '#eee' } }
|
splitLine: { show: true, lineStyle: { color: '#eee' } }
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
// 蓝色真实数据
|
|
||||||
{
|
{
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: barwidth,
|
barWidth: barWidth,
|
||||||
data: agesData,
|
data: agesData.value,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#409eff',
|
color: '#409eff',
|
||||||
borderRadius: [4, 4, 0, 0]
|
borderRadius: [4, 4, 0, 0]
|
||||||
@@ -271,7 +285,7 @@ const options3 = shallowRef<EChartsOption>({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: barwidth,
|
barWidth: barWidth,
|
||||||
data: bgData2,
|
data: bgData2,
|
||||||
tooltip: { show: false }, // 关键:不显示提示
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
@@ -281,8 +295,8 @@ const options3 = shallowRef<EChartsOption>({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: barwidth,
|
barWidth: barWidth,
|
||||||
data: bgData,
|
data: bgData.value,
|
||||||
tooltip: { show: false }, // 关键:不显示提示
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: 'rgba(180, 180, 180, 0.2)'
|
color: 'rgba(180, 180, 180, 0.2)'
|
||||||
@@ -291,6 +305,65 @@ const options3 = shallowRef<EChartsOption>({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
function updateOptions3(data: number[]): EChartsOption {
|
||||||
|
return {
|
||||||
|
title: {
|
||||||
|
text: '住户年龄分布',
|
||||||
|
left: '0',
|
||||||
|
top: '0',
|
||||||
|
textStyle: { fontSize: 16, fontWeight: 'bold' }
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
top: '12%',
|
||||||
|
bottom: '8%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
confine: true,
|
||||||
|
axisPointer: { type: 'shadow' }
|
||||||
|
},
|
||||||
|
xAxis: { type: 'category', data: agesX, axisLabel: { interval: 0 } },
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: { show: true, lineStyle: { color: '#eee' } }
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barWidth,
|
||||||
|
data: data,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409eff',
|
||||||
|
borderRadius: [4, 4, 0, 0]
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barWidth,
|
||||||
|
data: bgData2,
|
||||||
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
|
itemStyle: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: barWidth,
|
||||||
|
data: bgData.value,
|
||||||
|
tooltip: { show: false }, // 关键:不显示提示
|
||||||
|
itemStyle: {
|
||||||
|
color: 'rgba(180, 180, 180, 0.2)'
|
||||||
|
},
|
||||||
|
stack: 'total'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
// ! 年龄分布 -------------------------------------------------------------------------------------
|
// ! 年龄分布 -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||||
@@ -388,7 +461,7 @@ const flowLineOption = ref<EChartsOption>({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
function flowLineOptionFun(days: string[], indata: number[], outdata: number[]): EChartsOption {
|
function flowLineOptionFun(days: string[], InData: number[], OutData: number[]): EChartsOption {
|
||||||
return {
|
return {
|
||||||
title: {
|
title: {
|
||||||
text: '近十日人员流动趋势',
|
text: '近十日人员流动趋势',
|
||||||
@@ -430,7 +503,7 @@ function flowLineOptionFun(days: string[], indata: number[], outdata: number[]):
|
|||||||
name: '人员流入',
|
name: '人员流入',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true, // 平滑折线 核心
|
smooth: true, // 平滑折线 核心
|
||||||
data: indata,
|
data: InData,
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
symbolSize: 6,
|
symbolSize: 6,
|
||||||
itemStyle: { color: '#f94144' },
|
itemStyle: { color: '#f94144' },
|
||||||
@@ -453,7 +526,7 @@ function flowLineOptionFun(days: string[], indata: number[], outdata: number[]):
|
|||||||
name: '人员流出',
|
name: '人员流出',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true, // 平滑折线 核心
|
smooth: true, // 平滑折线 核心
|
||||||
data: outdata,
|
data: OutData,
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
symbolSize: 6,
|
symbolSize: 6,
|
||||||
itemStyle: { color: '#f9c74f' },
|
itemStyle: { color: '#f9c74f' },
|
||||||
@@ -477,34 +550,43 @@ function flowLineOptionFun(days: string[], indata: number[], outdata: number[]):
|
|||||||
}
|
}
|
||||||
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
const movein = ref({
|
const MoveIn = ref({
|
||||||
totalResident: 0,
|
totalResident: 0,
|
||||||
totalHouse: 0
|
totalHouse: 0
|
||||||
});
|
});
|
||||||
function init() {
|
function init() {
|
||||||
// 获取入住情况
|
// 入住情况
|
||||||
moveinFun();
|
MoveInFun();
|
||||||
// 入住类型
|
// 入住类型
|
||||||
moveinUserType();
|
MoveInUserType();
|
||||||
|
// 男女类型
|
||||||
moveinUserSex();
|
MoveInUserSex();
|
||||||
moveinUserMoveinOut();
|
// 迁入迁出
|
||||||
|
MoveInUserMoveInOut();
|
||||||
|
// 住户年龄分布
|
||||||
|
MoveInPersonAge();
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
function querySelect() {
|
function querySelect() {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
// 入住情况
|
||||||
function moveinFun() {
|
function MoveInFun() {
|
||||||
user_movein_list({
|
user_movein_list({
|
||||||
datetime: date.value
|
dateTime: date.value
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// 获取入住情况
|
// 获取入住情况
|
||||||
movein.value.totalResident = res.data.occupancyCount;
|
MoveIn.value.totalResident = res.data.occupancyCount;
|
||||||
movein.value.totalHouse = res.data.totalHouse;
|
MoveIn.value.totalHouse = res.data.totalHouse;
|
||||||
options.value.series[1].data = [
|
options.value.series[1].data = [
|
||||||
{ value: res.data.occupiedHouse },
|
{ value: res.data.occupiedHouse },
|
||||||
{ value: res.data.totalHouse - res.data.occupiedHouse, itemStyle: { color: 'transparent' } }
|
{
|
||||||
|
value: res.data.totalHouse - res.data.occupiedHouse,
|
||||||
|
itemStyle: { color: 'transparent' },
|
||||||
|
tooltip: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
options.value.series[1].label.formatter = () => {
|
options.value.series[1].label.formatter = () => {
|
||||||
const total = res.data.totalHouse;
|
const total = res.data.totalHouse;
|
||||||
@@ -518,17 +600,22 @@ function moveinFun() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 获取住户类型
|
// 获取住户类型
|
||||||
function moveinUserType() {
|
function MoveInUserType() {
|
||||||
get_movein_user_type({
|
get_movein_user_type({
|
||||||
datetime: date.value
|
dateTime: date.value
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
console.log(res);
|
options1.value.series[0].data = [
|
||||||
|
{ value: res.owner, name: '业主', itemStyle: { color: '#0a74fe' } },
|
||||||
|
{ value: res.tenant, name: '租户', itemStyle: { color: '#fe3d4e' } },
|
||||||
|
{ value: res.relatives, name: '亲属', itemStyle: { color: '#00cf7f' } },
|
||||||
|
{ value: res.other, name: '其他', itemStyle: { color: '#f48e3b' } }
|
||||||
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 住户性别
|
// 住户性别
|
||||||
function moveinUserSex() {
|
function MoveInUserSex() {
|
||||||
get_movein_user_sex({
|
get_movein_user_sex({
|
||||||
datetime: date.value
|
dateTime: date.value
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
options2.value.series[0].data = [
|
options2.value.series[0].data = [
|
||||||
{ value: res.man, name: '男', itemStyle: { color: '#0a74fe' } },
|
{ value: res.man, name: '男', itemStyle: { color: '#0a74fe' } },
|
||||||
@@ -537,11 +624,7 @@ function moveinUserSex() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 迁入迁出
|
// 迁入迁出
|
||||||
function moveinUserMoveinOut() {
|
function MoveInUserMoveInOut() {
|
||||||
// 判断 date.value 是否为今天
|
|
||||||
if (date.value === '') {
|
|
||||||
date.value = getLastNDays(7)[0];
|
|
||||||
}
|
|
||||||
get_movein_moveout_list({
|
get_movein_moveout_list({
|
||||||
date: date.value
|
date: date.value
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
@@ -551,6 +634,17 @@ function moveinUserMoveinOut() {
|
|||||||
flowLineOption.value = flowLineOptionFun(dayX.value, inData.value, outData.value);
|
flowLineOption.value = flowLineOptionFun(dayX.value, inData.value, outData.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 住户年龄分布
|
||||||
|
function MoveInPersonAge() {
|
||||||
|
get_person_age({
|
||||||
|
dateTime: date.value
|
||||||
|
}).then((res) => {
|
||||||
|
const values = Object.values(res).slice(0, -1);
|
||||||
|
maxValue.value = res.total;
|
||||||
|
agesData.value = values;
|
||||||
|
options3.value = updateOptions3(values);
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -571,6 +665,7 @@ function moveinUserMoveinOut() {
|
|||||||
}
|
}
|
||||||
// 入住清空
|
// 入住清空
|
||||||
.cardbox {
|
.cardbox {
|
||||||
|
box-sizing: border-box;
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
|
||||||
border-radius: 16px 16px 16px 16px;
|
border-radius: 16px 16px 16px 16px;
|
||||||
border: 2px solid #ffffff;
|
border: 2px solid #ffffff;
|
||||||
@@ -580,25 +675,25 @@ function moveinUserMoveinOut() {
|
|||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.cardbody {
|
.cardBody {
|
||||||
padding: 0 30px;
|
padding: 0 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
.card_leftbox {
|
.card_LeftBox {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
.labelbox {
|
.labelBox {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
.valuebox {
|
.valueBox {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
color: #222222;
|
color: #222222;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.echartsbox {
|
.echartsBox {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const storeroomList = ref<StoreroomVO[]>([]);
|
const storeroomList = ref<StoreroomVO[]>([]);
|
||||||
const buttonLoading = ref(false);
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
const ids = ref<Array<string | number>>([]);
|
const ids = ref<Array<string | number>>([]);
|
||||||
@@ -77,12 +76,6 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const storeroomFormRef = ref<ElFormInstance>();
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
|
||||||
visible: false,
|
|
||||||
title: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const initFormData: StoreroomForm = {
|
const initFormData: StoreroomForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@@ -116,7 +109,7 @@ const data = reactive<PageData<StoreroomForm, StoreroomQuery>>({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams } = toRefs(data);
|
||||||
|
|
||||||
/** 查询储藏室管理列表 */
|
/** 查询储藏室管理列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
@@ -127,18 +120,6 @@ const getList = async () => {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 取消按钮 */
|
|
||||||
const cancel = () => {
|
|
||||||
reset();
|
|
||||||
dialog.visible = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 表单重置 */
|
|
||||||
const reset = () => {
|
|
||||||
form.value = { ...initFormData };
|
|
||||||
storeroomFormRef.value?.resetFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
@@ -166,7 +147,7 @@ const handleAdd = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = async (row?: StoreroomVO) => {
|
const handleUpdate = (row?: StoreroomVO) => {
|
||||||
const id = row?.id || ids.value[0];
|
const id = row?.id || ids.value[0];
|
||||||
router.push({
|
router.push({
|
||||||
path: '/house/EditStoreRoom',
|
path: '/house/EditStoreRoom',
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ import pagination from '@/components/Pagination/index.vue';
|
|||||||
import { RoleVO } from '@/api/system/role/types';
|
import { RoleVO } from '@/api/system/role/types';
|
||||||
import { getAuthRole, updateAuthRole } from '@/api/system/user';
|
import { getAuthRole, updateAuthRole } from '@/api/system/user';
|
||||||
import { UserForm } from '@/api/system/user/types';
|
import { UserForm } from '@/api/system/user/types';
|
||||||
import { RouteLocationNormalized } from 'vue-router';
|
import { RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@@ -112,7 +112,7 @@ const close = () => {
|
|||||||
redirectedFrom: undefined,
|
redirectedFrom: undefined,
|
||||||
path: '/system/user'
|
path: '/system/user'
|
||||||
};
|
};
|
||||||
proxy?.$tab.closeOpenPage(obj);
|
proxy?.$tab.closeOpenPage(obj as RouteLocationRaw);
|
||||||
};
|
};
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
|
|||||||
@@ -482,7 +482,7 @@ const cancel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = async () => {
|
const handleAdd = () => {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/system/addUser'
|
path: '/system/addUser'
|
||||||
});
|
});
|
||||||
@@ -490,7 +490,7 @@ const handleAdd = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = async (row?: UserForm) => {
|
const handleUpdate = (row?: UserForm) => {
|
||||||
const userId = row?.userId || ids.value[0];
|
const userId = row?.userId || ids.value[0];
|
||||||
router.push({
|
router.push({
|
||||||
path: '/system/editUser',
|
path: '/system/editUser',
|
||||||
@@ -548,10 +548,6 @@ onMounted(() => {
|
|||||||
initPassword.value = response.data;
|
initPassword.value = response.data;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function handleDeptChange(value: number | string) {
|
|
||||||
console.log(value);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ import { optionselect as getDictOptionselect } from '@/api/system/dict/type';
|
|||||||
import { DictTypeVO } from '@/api/system/dict/type/types';
|
import { DictTypeVO } from '@/api/system/dict/type/types';
|
||||||
import BasicInfoForm from './basicInfoForm.vue';
|
import BasicInfoForm from './basicInfoForm.vue';
|
||||||
import GenInfoForm from './genInfoForm.vue';
|
import GenInfoForm from './genInfoForm.vue';
|
||||||
import { RouteLocationNormalized } from 'vue-router';
|
import { RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@@ -179,7 +179,7 @@ const close = () => {
|
|||||||
redirectedFrom: undefined,
|
redirectedFrom: undefined,
|
||||||
query: { t: Date.now().toString(), pageNum: route.query.pageNum }
|
query: { t: Date.now().toString(), pageNum: route.query.pageNum }
|
||||||
};
|
};
|
||||||
proxy?.$tab.closeOpenPage(obj);
|
proxy?.$tab.closeOpenPage(obj as RouteLocationRaw);
|
||||||
};
|
};
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user