8/4 更新 输入限制,修复收银台
This commit is contained in:
@@ -9,9 +9,9 @@ VITE_APP_ENV='development'
|
||||
# 开发环境
|
||||
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.1.6:8080'
|
||||
VITE_APP_PROXY_API='http://192.168.1.6:8080'
|
||||
# 图片基础地址
|
||||
VITE_IMG_URL='http://192.168.1.222:8080'
|
||||
|
||||
@@ -24,7 +24,7 @@ VITE_APP_MONITOR_ADMIN='http://192.168.1.215/admin/applications'
|
||||
# SnailJob 控制台地址
|
||||
VITE_APP_SNAILJOB_ADMIN='http://192.168.1.215/snail-job'
|
||||
|
||||
VITE_APP_PORT=5173
|
||||
VITE_APP_PORT=5174
|
||||
|
||||
# 登录成功跳转地址
|
||||
# VITE_LOGIN_BACK_URL = '/equipment/WaterDevice'
|
||||
|
||||
@@ -39,7 +39,7 @@ export const get_movein_user_type = (query?: {
|
||||
'tenantRate': string;
|
||||
'relatives': string;
|
||||
'relativeRate': string;
|
||||
'other': string;
|
||||
'otherType': string;
|
||||
'otherRate': string;
|
||||
'totalResident': string;
|
||||
}> => {
|
||||
|
||||
@@ -42,6 +42,7 @@ export type billlistType = {
|
||||
'endDate': string;
|
||||
'money': string;
|
||||
'payStatus': string;
|
||||
'remark': string;
|
||||
amount: string;
|
||||
residentName: string;
|
||||
};
|
||||
|
||||
@@ -87,3 +87,27 @@ export const getHouseOwnUser = (houseId: string): AxiosPromise<uploadHouseImaget
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 房屋租赁管理 改变状态 0:下架 1:上架
|
||||
* @param houseId
|
||||
* */
|
||||
export const changeHouseRedientStatus = (houseId: string): AxiosPromise<uploadHouseImagetype> => {
|
||||
return request({
|
||||
url: `/houseRental/changeStatus/${houseId}`,
|
||||
method: 'PUT',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 房屋租赁管理 签约
|
||||
* @param data
|
||||
*/
|
||||
export const HouseRedientSign = (data: HouseRentalForm): AxiosPromise<uploadHouseImagetype> => {
|
||||
return request({
|
||||
url: `/houseRental/sign`,
|
||||
method: 'POST',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ export interface HouseRentalVO {
|
||||
/**
|
||||
* id 房屋租赁表id
|
||||
*/
|
||||
id: string | number;
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* 租户姓名
|
||||
@@ -72,7 +72,7 @@ export interface HouseRentalVO {
|
||||
/**
|
||||
* 房屋id
|
||||
*/
|
||||
houseId: number;
|
||||
houseId: string;
|
||||
/**
|
||||
* 房屋用途
|
||||
*/
|
||||
@@ -88,83 +88,74 @@ export interface HouseRentalVO {
|
||||
pubTime: string;
|
||||
houseImageUrls: string[];
|
||||
facilitieslist: string[];
|
||||
signingList?: HouseRentalSigningVO[];
|
||||
}
|
||||
|
||||
export interface HouseRentalForm extends BaseEntity {
|
||||
/**
|
||||
* id 房屋租赁表id
|
||||
* 收费模式
|
||||
*/
|
||||
id?: string | number;
|
||||
|
||||
chargeMode: string;
|
||||
/**
|
||||
* 租户姓名
|
||||
* 收费标准
|
||||
*/
|
||||
rentalName?: string;
|
||||
|
||||
chargeStandard: string;
|
||||
/**
|
||||
* 租金 单位元
|
||||
* 合同编号
|
||||
*/
|
||||
rent?: number;
|
||||
|
||||
contractNo: string;
|
||||
/**
|
||||
* 0 整租 1 合租
|
||||
* 合同状态
|
||||
*/
|
||||
rentalType?: string;
|
||||
|
||||
/**
|
||||
* 房屋朝向
|
||||
*/
|
||||
houseFace?: string;
|
||||
|
||||
/**
|
||||
* 房屋面积
|
||||
*/
|
||||
houseArea?: number;
|
||||
|
||||
/**
|
||||
* 楼层号
|
||||
*/
|
||||
floorNo?: number;
|
||||
|
||||
/**
|
||||
* 入住时间
|
||||
*/
|
||||
inTime?: string;
|
||||
|
||||
/**
|
||||
* 房屋设施(“,”隔开)
|
||||
*/
|
||||
facilities?: string;
|
||||
|
||||
/**
|
||||
* 房屋照片url( "," 隔开)
|
||||
*/
|
||||
houseImageUrl?: string;
|
||||
|
||||
/**
|
||||
* 补充租房信息
|
||||
*/
|
||||
supInfo?: string;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
phone?: number;
|
||||
|
||||
/**
|
||||
* 微信
|
||||
*/
|
||||
vx?: string;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
email?: string;
|
||||
|
||||
contractStatus: string;
|
||||
/**
|
||||
* 房屋id
|
||||
*/
|
||||
houseId?: string | number;
|
||||
houseId?: string;
|
||||
/**
|
||||
* 租赁结束时间
|
||||
*/
|
||||
leaseEndDate: string;
|
||||
/**
|
||||
* 租赁起始时间
|
||||
*/
|
||||
leaseStartDate: string;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
/**
|
||||
* 房屋租赁ID
|
||||
*/
|
||||
rentalId: string;
|
||||
/**
|
||||
* 承租方姓名
|
||||
*/
|
||||
tenantName: string;
|
||||
/**
|
||||
* 承租方联系电话
|
||||
*/
|
||||
tenantPhone: string;
|
||||
/**
|
||||
* 小区id
|
||||
*/
|
||||
villageId?: string;
|
||||
}
|
||||
export interface HouseRentalSigningVO {
|
||||
'id': string;
|
||||
'rentalId': string;
|
||||
'contractNo': string;
|
||||
'tenantName': string;
|
||||
'tenantPhone': string;
|
||||
'chargeMode': string;
|
||||
'chargeStandard': string;
|
||||
'contractStatus': string;
|
||||
'leaseStartDate': string;
|
||||
'leaseEndDate': string;
|
||||
'houseId': string;
|
||||
'villageId': string;
|
||||
'remark': string;
|
||||
'createTime': string;
|
||||
}
|
||||
|
||||
export interface HouseRentalQuery extends PageQuery {
|
||||
|
||||
@@ -77,6 +77,10 @@ export interface ResidentVO {
|
||||
}
|
||||
|
||||
export interface ResidentForm extends BaseEntity {
|
||||
/**
|
||||
* 年龄
|
||||
*/
|
||||
age?: number;
|
||||
/**
|
||||
* 主键 住户管理id
|
||||
*/
|
||||
@@ -163,17 +167,24 @@ export interface ResidentQuery extends PageQuery {
|
||||
* 日期范围参数
|
||||
*/
|
||||
date?: any;
|
||||
|
||||
/**
|
||||
* 0业主
|
||||
* 1亲属
|
||||
* 2租户
|
||||
* 3朋友
|
||||
* 房屋名称
|
||||
*/
|
||||
houseName?: string;
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* 0 业主
|
||||
* 1 亲属
|
||||
* 2 租户
|
||||
* 3 朋友
|
||||
*/
|
||||
ownerRelationship?: string;
|
||||
/**
|
||||
* 住户状态
|
||||
* 0审核中 1 已认证
|
||||
* 0 审核中 1 已认证
|
||||
*/
|
||||
status?: string;
|
||||
|
||||
|
||||
198
src/utils/Reg.ts
198
src/utils/Reg.ts
@@ -1,40 +1,3 @@
|
||||
/**
|
||||
* 验证身份证号码(18位,支持尾号x/X)
|
||||
* @param idCard 身份证号
|
||||
* @return {boolean} true 符合 false 不符合
|
||||
*/
|
||||
export function validateIdCard(idCard: string): boolean {
|
||||
// 18位身份证正则
|
||||
const reg = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
|
||||
return reg.test(idCard.trim());
|
||||
}
|
||||
/**
|
||||
* 验证车牌号
|
||||
* @param val 兼容新能源 + 普通车牌
|
||||
* @return {boolean} true 符合 false 不符合
|
||||
*/
|
||||
export function isPlateNumber(val: string): boolean {
|
||||
const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/;
|
||||
return reg.test(val);
|
||||
}
|
||||
/**
|
||||
* 验证金钱
|
||||
* @return {boolean} true 符合 false 不符合
|
||||
* @param value
|
||||
*/
|
||||
export function isMoney(value: number): boolean {
|
||||
const reg = /^(0|[1-9]\d*)(\.\d{1,2})?$/;
|
||||
return reg.test(String(value).trim());
|
||||
}
|
||||
/**
|
||||
* 验证姓名
|
||||
* @param {string} val
|
||||
* @return {boolean} true 符合 false 不符合
|
||||
*/
|
||||
export function isChineseName(val: string): boolean {
|
||||
return /^[\u4e00-\u9fa5·]{2,16}$/.test(String(val).trim());
|
||||
}
|
||||
|
||||
const reg = {
|
||||
/** 金钱 */
|
||||
money: /^(0|[1-9]\d*)(\.\d{1,2})?$/,
|
||||
@@ -43,7 +6,11 @@ const reg = {
|
||||
/** 车牌 */
|
||||
PlateNumber: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/,
|
||||
/** 姓名 */
|
||||
ChineseName: /^[\u4e00-\u9fa5·]{2,16}$/,
|
||||
ChineseName: /^[\u4e00-\u9fa5]{1,16}$/,
|
||||
/** 字符 除了颜文字,emoji表情 */
|
||||
Character: /^[a-zA-Z0-9_\u4e00-\u9fa5-]+$/,
|
||||
/** 联系方式 */
|
||||
contact: /^[a-zA-Z0-9_\u4e00-\u9fa5-@.]+$/,
|
||||
/** 手机号 */
|
||||
phone: /^1[3-9]\d{9}$/,
|
||||
/** 邮箱 */
|
||||
@@ -55,7 +22,14 @@ const reg = {
|
||||
/** 护照 */
|
||||
passport: /^[EG]\d{8}$/,
|
||||
/** 港澳通行证 */
|
||||
hongkongPassport: /^[CHMW]\d{8}$/
|
||||
hongkongPassport: /^[CHMW]\d{8}$/,
|
||||
/** 年龄 */
|
||||
age: /^[0-9]\d{0,2}$/,
|
||||
/** 数字 */
|
||||
number: /^[0-9]+$/,
|
||||
// 完整版:所有emoji+肤色修饰+组合连接符+全部颜文字符号
|
||||
fullFilterReg:
|
||||
/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{1F900}-\u{1F9FF}\u{1F3FB}-\u{1F3FF}\u{200D}。「」、・~ー『』「」・ヽヾゝゞ〆゛゜○●△▲□■◇◆◎▽▼┐┌└┘╮╭╰╯┬┴┼│─╱╲╳︵︶︹︺︿﹀︽︾﹁﹂﹃﹄ァ-ヺヽヾ]/gu
|
||||
};
|
||||
// 自动推导 TS 类型(最标准)
|
||||
export type RegType = keyof typeof reg;
|
||||
@@ -68,149 +42,3 @@ export type RegType = keyof typeof reg;
|
||||
export function validator(value: string | number, regType: RegType): boolean {
|
||||
return reg[regType].test(String(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 车牌验证工具类
|
||||
* 支持传统燃油、新能源、军警、武警、使馆、临时、港澳、挂车等全量车牌
|
||||
*/
|
||||
export class LicensePlateValidator {
|
||||
/**
|
||||
* 省份简称正则片段
|
||||
*/
|
||||
private static readonly PROVINCE = '[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]';
|
||||
|
||||
/**
|
||||
* 验证传统燃油车牌 (蓝牌/黄牌)
|
||||
* 格式: 省份 + 字母 + 5位字符 (数字或字母,排除I,O)
|
||||
* 示例: 京A·12345, 粤B·88888
|
||||
* 总长7位
|
||||
*/
|
||||
static isTraditionalPlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][A-HJ-NP-Z0-9]{5}$`);
|
||||
if (!reg.test(plate.toUpperCase())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证新能源车牌 (绿牌)
|
||||
* 规则:除了标识位 D/F 外,其余序号位必须为数字 (0-9)
|
||||
* 小型: 省份 + 字母 + D/F + 5位数字 或 省份 + 字母 + 5位数字 + D/F
|
||||
* 大型: 省份 + 字母 + 5位数字 + D/F
|
||||
* 总长8位
|
||||
*/
|
||||
static isNewEnergyPlate(plate: string): boolean {
|
||||
// 修正:非D/F位仅限数字
|
||||
// 1. [省份][A-HJ-NP-Z][D-F][0-9]{5} (D/F在序号第1位,后跟5位数字)
|
||||
// 2. [省份][A-HJ-NP-Z][0-9]{5}[D-F] (D/F在序号最后1位,前跟5位数字)
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z](?:[D-F][0-9]{5}|[0-9]{5}[D-F])$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证警车车牌
|
||||
* 格式: 省份 + 字母 + 4位数字 + 警
|
||||
* 总长7位
|
||||
*/
|
||||
static isPolicePlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9]{4}警$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证教练车牌
|
||||
* 格式: 省份 + 字母 + 4位数字 + 学
|
||||
* 总长7位
|
||||
*/
|
||||
static isCoachPlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9]{4}学$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证挂车车牌
|
||||
* 格式: 省份 + 字母 + 4位数字 + 挂
|
||||
* 总长7位
|
||||
*/
|
||||
static isTrailerPlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9]{4}挂$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证武警车牌 (2013式)
|
||||
* 格式: WJ + 省份/部门简称 + 5位字符
|
||||
* 总长8位 (WJ+1+5)
|
||||
*/
|
||||
static isArmedPolicePlate(plate: string): boolean {
|
||||
const reg = /^WJ(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]|[A-HJ-NP-Z])[0-9A-HJ-NP-Z]{5}$/;
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证军队车牌 (2012式)
|
||||
* 格式: 军种字母 + 字母/数字 + 5位字符
|
||||
* 总长7位
|
||||
*/
|
||||
static isMilitaryPlate(plate: string): boolean {
|
||||
const reg = /^[VKBHSLJNGCMPEOA][A-HJ-NP-Z0-9][0-9A-HJ-NP-Z]{4}$/;
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证使馆/领馆车牌
|
||||
* 格式: 使/领 + 6位数字
|
||||
* 总长7位
|
||||
*/
|
||||
static isEmbassyPlate(plate: string): boolean {
|
||||
const reg = /^[使领][0-9]{6}$/;
|
||||
return reg.test(plate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证港澳入出境车 (粤Z牌)
|
||||
* 格式: 粤Z + 4位字符 + 港/澳
|
||||
* 总长7位
|
||||
*/
|
||||
static isHKMacauPlate(plate: string): boolean {
|
||||
const reg = /^粤Z[A-HJ-NP-Z0-9]{4}[港澳]$/;
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证临时车牌
|
||||
* 格式: 省份 + 字母 + 5位字符 + 临 / 超
|
||||
* 总长8位
|
||||
*/
|
||||
static isTemporaryPlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9A-HJ-NP-Z]{5}[临超]$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证所有合法车牌(全量)
|
||||
* @param plate 车牌号码
|
||||
*/
|
||||
static isValidPlate(plate: string): boolean {
|
||||
if (!plate || typeof plate !== 'string') return false;
|
||||
|
||||
const upperPlate = plate.toUpperCase().replace(/[·\s-]/g, ''); // 去除分隔符和空格
|
||||
|
||||
// 长度预检查:车牌只能是 7 位或 8 位
|
||||
if (upperPlate.length !== 7 && upperPlate.length !== 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
this.isTraditionalPlate(upperPlate) ||
|
||||
this.isNewEnergyPlate(upperPlate) ||
|
||||
this.isPolicePlate(upperPlate) ||
|
||||
this.isCoachPlate(upperPlate) ||
|
||||
this.isTrailerPlate(upperPlate) ||
|
||||
this.isArmedPolicePlate(upperPlate) ||
|
||||
this.isMilitaryPlate(upperPlate) ||
|
||||
this.isEmbassyPlate(upperPlate) ||
|
||||
this.isHKMacauPlate(upperPlate) ||
|
||||
this.isTemporaryPlate(upperPlate)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ const whiteVillageId = [
|
||||
'/payRecordList/payRecordList/list',
|
||||
'/warehouse',
|
||||
'/notification/read', // 已读
|
||||
'/cash/billList'
|
||||
'/cash/billList',
|
||||
'/houseRental/changeStatus'
|
||||
// '/building/list'
|
||||
];
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@
|
||||
<el-col :span="11">
|
||||
<el-form-item label="报名截止日期" prop="deadline">
|
||||
<el-date-picker
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
v-model="deadline"
|
||||
@update:model-value="
|
||||
(data) => {
|
||||
@@ -68,7 +68,7 @@
|
||||
}
|
||||
}
|
||||
"
|
||||
type="date"
|
||||
type="datetime"
|
||||
placeholder="请选择报名截止日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -115,6 +115,7 @@
|
||||
:on-exceed="handleExceed"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-error="handleError"
|
||||
accept=".png,.jpg,.jpeg,.bmp"
|
||||
:limit="1"
|
||||
>
|
||||
<img alt="活动封面" v-if="form.coverImage" :src="form.coverImage" class="avatar" />
|
||||
@@ -225,6 +226,7 @@ import { addActivity, getActivity, updateActivity } from '@/api/system/Activity'
|
||||
import { genFileId, UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { validator } from '@/utils/Reg';
|
||||
|
||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/activity/uploadImage';
|
||||
|
||||
@@ -278,13 +280,34 @@ const form = ref({
|
||||
});
|
||||
const rules = {
|
||||
title: [{ required: true, message: '请输入活动标题', trigger: 'blur' }],
|
||||
author: [{ required: true, message: '请输入作者', trigger: 'blur' }],
|
||||
author: [
|
||||
{ required: true, message: '请输入作者', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number) => validator(value, 'Character'),
|
||||
message: '请输入中文,字母,数字,-,_等字符',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
applyDeadline: [{ required: true, message: '请输入报名截止日期', trigger: 'blur' }],
|
||||
startTime: [{ required: true, message: '请选择开始日期', trigger: 'blur' }],
|
||||
endTime: [{ required: true, message: '请选择结束日期', trigger: 'blur' }],
|
||||
address: [{ required: true, message: '请输入活动地点', trigger: 'blur' }],
|
||||
organizer: [{ required: true, message: '请输入主办方', trigger: 'blur' }],
|
||||
contactName: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
|
||||
organizer: [
|
||||
{ required: true, message: '请输入主办方', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number) => validator(value, 'Character'),
|
||||
message: '请输入中文,字母,数字,-,_等字符',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
contactName: [
|
||||
{ required: true, message: '请输入联系人', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number) => validator(value, 'Character'),
|
||||
message: '请输入中文,字母,数字,-,_等字符',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
contactPhone: [{ required: true, message: '请输入联系方式', trigger: 'blur' }],
|
||||
coverImage: [{ required: true, message: '请上传活动封面', trigger: 'blur' }],
|
||||
content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
|
||||
@@ -301,10 +324,11 @@ const activityTime = ref([]);
|
||||
const upload = ref<UploadInstance>();
|
||||
// 上传成功
|
||||
const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
|
||||
console.log(response);
|
||||
if (response.data && response.data.url) {
|
||||
form.value.coverImage = response.data.url;
|
||||
} else {
|
||||
ElMessage.warning('上传频繁,请稍后再试');
|
||||
ElMessage.warning(response.msg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -320,7 +344,7 @@ const handleExceed: UploadProps['onExceed'] = (files) => {
|
||||
const handleError: UploadProps['onError'] = (error: Error) => {
|
||||
console.log(error);
|
||||
};
|
||||
const allowImgSuffix = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic'];
|
||||
const allowImgSuffix = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
|
||||
/** 检测文件大小和格式 */
|
||||
const handleBeforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
if (!allowImgSuffix.includes(rawFile.name.split('.')[1])) {
|
||||
@@ -342,7 +366,7 @@ let geocoder: any = null;
|
||||
const mapReady = ref(false);
|
||||
let mouseTool = null;
|
||||
|
||||
// 0 开始 1编辑 2结束
|
||||
// 0 开始 1 编辑 2结束
|
||||
const isDraw = ref(0);
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -80,6 +80,17 @@ const form = ref({
|
||||
const rules = {
|
||||
houseId: [{ required: true, message: '请选择具体房屋', trigger: 'blur' }],
|
||||
applyName: [{ required: true, message: '请输入申请人', trigger: 'blur' }],
|
||||
decorationCompany: [
|
||||
{ required: true, message: '请输入装修公司名称', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number, callback: any) => {
|
||||
if (value === '' || value === '') {
|
||||
return callback();
|
||||
}
|
||||
return !validator(value, 'fullFilterReg') ? callback() : callback(new Error('请输入正确的装修公司名称'));
|
||||
}
|
||||
}
|
||||
],
|
||||
decorationDeposit: [
|
||||
{ required: true, message: '请输入装修押金', trigger: 'blur' },
|
||||
{
|
||||
@@ -103,7 +114,17 @@ const rules = {
|
||||
trigger: ['blur', 'change']
|
||||
}
|
||||
],
|
||||
decorationContent: [{ required: true, message: '请输入装修内容', trigger: 'blur' }]
|
||||
decorationContent: [
|
||||
{ required: true, message: '请输入装修内容', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number, callback: any) => {
|
||||
if (value === '' || value === '') {
|
||||
return callback();
|
||||
}
|
||||
return !validator(value, 'fullFilterReg') ? callback() : callback(new Error('请输入正确的装修内容'));
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
const userid = ref();
|
||||
|
||||
|
||||
@@ -112,7 +112,8 @@ import { addHandleLog, getHandleLog, updateHandleLog, uploadAttachments } from '
|
||||
import { UploadFiles, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Upload } from '@element-plus/icons-vue'; // 确保引入图标组件╬╬╬
|
||||
import { Upload } from '@element-plus/icons-vue';
|
||||
import { validator } from '@/utils/Reg'; // 确保引入图标组件
|
||||
|
||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/handleLog/uploadAttachments';
|
||||
const route = useRoute();
|
||||
@@ -129,7 +130,25 @@ const form = ref({
|
||||
});
|
||||
const rules = {
|
||||
content: [{ required: true, message: '请输入办事内容', trigger: 'blur' }],
|
||||
seekName: [{ required: true, message: '请选择求助人', trigger: 'blur' }]
|
||||
seekName: [
|
||||
{ required: true, message: '请选择求助人', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number) => validator(value, 'Character'),
|
||||
message: '请输入中文,字母,数字,-,_等字符',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{ required: false, message: '请输入联系方式', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number, callback: any) => {
|
||||
if (value === '' || value === '') {
|
||||
return callback();
|
||||
}
|
||||
return !validator(value, 'fullFilterReg') ? callback() : callback(new Error('请输入正确的联系方式'));
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
const userid = ref();
|
||||
|
||||
|
||||
@@ -99,7 +99,6 @@ import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addMonthCard, getMonthCard, updateMonthCard } from '@/api/system/MonthCard';
|
||||
import { validator } from '@/utils/Reg';
|
||||
import { LicensePlateValidator2 } from '@/utils/Reg2';
|
||||
import { callback } from '@/api/login';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method'));
|
||||
|
||||
@@ -126,7 +125,14 @@ function handleDate() {
|
||||
form.value.endTime = checkDate.value[1];
|
||||
}
|
||||
const rules = ref({
|
||||
cardCode: [{ required: true, message: '请输入月卡编号', trigger: 'blur' }],
|
||||
cardCode: [
|
||||
{ required: true, message: '请输入月卡编号', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number) => validator(value, 'Character'),
|
||||
message: '请输入中文,字母,数字,-,_等字符',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
cardName: [
|
||||
{ required: true, message: '请输入姓名', trigger: 'blur' },
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="起止日期" prop="price">
|
||||
<el-date-picker
|
||||
:disabled="!Boolean(form.recordMonth)"
|
||||
v-model="StartEndDate"
|
||||
@update:model-value="handleDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item @change="handleChangeHouseNo" label="房号" prop="houseId">
|
||||
<el-select v-model="queryParams.houseId" placeholder="请选择收费项目">
|
||||
<el-select v-model="queryParams.houseId" placeholder="请选择房号">
|
||||
<el-option-group v-for="group in houseList" :key="group.floorNo" :label="String(group.floorNo) + ' 楼'">
|
||||
<el-option v-for="item in group.houses" :key="item.houseId" :label="item.houseNo" :value="item.houseId" />
|
||||
</el-option-group>
|
||||
@@ -30,7 +30,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<el-form-item label="收费项目" prop="itemId">
|
||||
<el-select v-model="queryParams.chargeItemId" placeholder="请选择收费项目">
|
||||
<el-select multiple v-model="queryParams.chargeItemId" placeholder="请选择收费项目">
|
||||
<el-option
|
||||
:disabled="item.status === '1'"
|
||||
v-for="(item, index) in chargeItems"
|
||||
@@ -147,7 +147,10 @@
|
||||
<el-table-column label="应收金额" width="100" align="center" prop="amount" />
|
||||
<el-table-column label="缴费状态" width="100" align="center" prop="payStatus">
|
||||
<template #default="scope">
|
||||
<DictTag :options="com_pay_status" :value="scope.row.payStatus"></DictTag>
|
||||
<span v-if="scope.row.payStatus === '0'">未缴纳</span>
|
||||
<span v-else-if="scope.row.payStatus === '1'">已缴纳</span>
|
||||
<span v-else-if="scope.row.payStatus === '2'">缴纳失败</span>
|
||||
<span v-else>部分缴纳</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="应缴金额" width="100" align="center" prop="amount" />
|
||||
@@ -159,7 +162,7 @@
|
||||
<el-table-column label="操作" width="110" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" v-if="scope.row.payStatus !== '1'" @click="handleIncome(scope.row)" v-has-permi="['bill:bill:edit']"
|
||||
>收费</el-button
|
||||
>收款</el-button
|
||||
>
|
||||
<el-button link type="success" v-if="scope.row.payStatus === '1'" @click="printPIaoJuByOnly(scope.row)" v-has-permi="['bill:bill:query']"
|
||||
>打印票据</el-button
|
||||
@@ -180,7 +183,10 @@
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="650px" append-to-body>
|
||||
<div class="payInfo">
|
||||
<div>
|
||||
<div>缴费人: {{ inComeFrom.residentName }}</div>
|
||||
<div class="flex flex-items-center justify-between">
|
||||
<span>缴费人: {{ inComeFrom.residentName }}</span>
|
||||
<span style="color: #ff9947">待缴纳</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span>收费名称: </span>
|
||||
@@ -204,11 +210,11 @@
|
||||
<span>{{ item.amount }}¥</span>
|
||||
</div>
|
||||
<div style="text-align: right" class="flex justify-between">
|
||||
<span>上次优惠金额</span>
|
||||
<span>累计优惠金额</span>
|
||||
<span>− {{ item.singleDiscountAmount }}¥</span>
|
||||
</div>
|
||||
<div style="text-align: right" class="flex justify-between">
|
||||
<span>上次已交金额</span>
|
||||
<span>累计已交金额</span>
|
||||
<span>− {{ item.paidAmount }}¥</span>
|
||||
</div>
|
||||
<div
|
||||
@@ -264,40 +270,11 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="缴纳状态" prop="payStatus">
|
||||
<el-radio-group v-model="inComeFrom.payStatus">
|
||||
<el-radio v-for="dict in com_pay_status" :key="dict.value" :label="dict.label" :value="dict.value"></el-radio>
|
||||
<el-radio value="1" label="已缴纳"></el-radio>
|
||||
<el-radio value="2" label="部分缴纳"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付方式" prop="payType" v-if="inComeFrom.payStatus !== '0'">
|
||||
<div class="flex-1">
|
||||
<div class="flex flex-items-center" v-for="(item, index) in payList" :key="index">
|
||||
<div class="flex-1 flex">
|
||||
<el-select @change="handleChangePayTypeId($event, index)" v-model="item.payType" placeholder="请选择">
|
||||
<el-option
|
||||
:disabled="isOptionDisabled(dict.value, item.payType)"
|
||||
v-for="dict in com_pay_method"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-input @change="(val: string) => handleChangePay(val, index)" v-model.number.trim="item.payAmount" style="margin: 0 10px">
|
||||
<template #append>¥</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div style="width: 80px; text-align: left">
|
||||
<el-icon
|
||||
color="blue"
|
||||
size="24"
|
||||
v-if="index === payList.length - 1 && payList.length < com_pay_method.length"
|
||||
@click="addPayList"
|
||||
style="margin-right: 10px; cursor: pointer"
|
||||
><CirclePlus
|
||||
/></el-icon>
|
||||
<el-icon color="red" style="cursor: pointer" size="24" v-if="payList.length > 1" @click="removePayList(index)"><Delete /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="优惠方式" prop="discountMethod" v-if="inComeFrom.payStatus !== '0'">
|
||||
<el-select style="width: 400px" @change="handleChangeDisCountMethod" v-model="inComeFrom.discountMethod" placeholder="请选择">
|
||||
<el-option label="不优惠" :value="0"></el-option>
|
||||
@@ -335,6 +312,37 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label="支付方式" prop="payType" v-if="inComeFrom.payStatus !== '0'">
|
||||
<div class="flex-1">
|
||||
<div class="flex flex-items-center" v-for="(item, index) in payList" :key="index">
|
||||
<div class="flex-1 flex">
|
||||
<el-select @change="handleChangePayTypeId($event, index)" v-model="item.payType" placeholder="请选择">
|
||||
<el-option
|
||||
:disabled="isOptionDisabled(dict.value, item.payType)"
|
||||
v-for="dict in com_pay_method"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-input @change="(val: string) => handleChangePay(val, index)" v-model.number.trim="item.payAmount" style="margin: 0 10px">
|
||||
<template #append>¥</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div style="width: 80px; text-align: left">
|
||||
<el-icon
|
||||
color="blue"
|
||||
size="24"
|
||||
v-if="index === payList.length - 1 && payList.length < com_pay_method.length"
|
||||
@click="addPayList"
|
||||
style="margin-right: 10px; cursor: pointer"
|
||||
><CirclePlus
|
||||
/></el-icon>
|
||||
<el-icon color="red" style="cursor: pointer" size="24" v-if="payList.length > 1" @click="removePayList(index)"><Delete /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input style="width: 400px" type="textarea" show-word-limit maxlength="100" :rows="5" v-model="inComeFrom.remark"></el-input>
|
||||
</el-form-item>
|
||||
@@ -433,9 +441,7 @@ import { CirclePlus, Delete, QuestionFilled } from '@element-plus/icons-vue';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_pay_status, com_pay_method, com_charge_item_unit } = toRefs<any>(
|
||||
proxy?.useDict('com_pay_status', 'com_pay_method', 'com_charge_item_unit')
|
||||
);
|
||||
const { com_pay_method, com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_pay_method', 'com_charge_item_unit'));
|
||||
|
||||
const userStore = useUserStore();
|
||||
const loading = ref(false);
|
||||
@@ -668,7 +674,7 @@ function initInComeFrom() {
|
||||
inComeFrom.value = {
|
||||
allCost: 0, // 总金额
|
||||
billResidentId: [], // 账单id
|
||||
payStatus: '1', // 0:未缴 1:已缴
|
||||
payStatus: '1', // 0:未缴 1:已缴 2: 缴纳失败 3: 部分缴纳
|
||||
payType: '2', // 0:微信 1:支付宝 2 线下
|
||||
remark: '',
|
||||
discountMethod: 0, // 优惠方式 0 不优惠 1 比例 2 金额
|
||||
@@ -694,7 +700,6 @@ function initInComeFrom() {
|
||||
}
|
||||
// 改变优惠方式
|
||||
function handleChangeDisCountMethod(val: number) {
|
||||
console.log(val);
|
||||
inComeFrom.value.discountRate = '0'; // 优惠比例
|
||||
inComeFrom.value.discount = '0.00'; // 优惠金额
|
||||
totalReadDiscount.value = '0.00'; // 实际优惠金额
|
||||
@@ -718,7 +723,6 @@ function handleChangeDiscountMoney(val: string) {
|
||||
}
|
||||
let discount = toBig(cleanVal).toNumber();
|
||||
if (Number.isNaN(discount)) discount = 0;
|
||||
console.log('折扣金额:', discount);
|
||||
const allCost = inComeFrom.value.allCost ?? 0;
|
||||
if (discount < 0) {
|
||||
ElMessage.warning('优惠金额不能为负数');
|
||||
@@ -830,6 +834,7 @@ function handleIncome(row: billlistType | false) {
|
||||
if (row) {
|
||||
inComeFrom.value.allCost = row.needPayAmount;
|
||||
inComeFrom.value.billResidentId = [row];
|
||||
inComeFrom.value.remark = row.remark;
|
||||
inComeFrom.value.residentName = row.residentName;
|
||||
totalPayAmount.value = row.needPayAmount;
|
||||
} else {
|
||||
@@ -845,6 +850,7 @@ function handleIncome(row: billlistType | false) {
|
||||
ElMessage.warning('缴费人不一致,重新选择');
|
||||
return;
|
||||
} else if (set.size === 1) {
|
||||
inComeFrom.value.remark = '';
|
||||
inComeFrom.value.residentName = ids.value[0].residentName;
|
||||
ids.value.forEach((item) => {
|
||||
inComeFrom.value.billResidentId.push(item);
|
||||
@@ -866,12 +872,17 @@ const closer = () => {
|
||||
};
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
if (!handlePayListIsEmpt()) {
|
||||
ElMessage.warning('请填写完整支付方式和支付金额');
|
||||
return;
|
||||
}
|
||||
buttonLoading.value = true;
|
||||
// 部分缴纳时 不管
|
||||
// 已缴纳时 判断 支付金额 和 预计支付金额 是否相等
|
||||
// 混合缴纳时 不管
|
||||
if (inComeFrom.value.payStatus === '1') {
|
||||
if (!eqMoney(totalPayAmount.value, payListAllAmount.value)) {
|
||||
return ElMessage.error('实际支付金额 和 预计支付金额 不相等');
|
||||
buttonLoading.value = false;
|
||||
return ElMessage.warning('支付金额不足,可选择 部分缴纳 方式');
|
||||
}
|
||||
}
|
||||
const obj = {
|
||||
@@ -998,11 +1009,15 @@ const printOption = {
|
||||
}
|
||||
`,
|
||||
afterCloseCallback: () => {
|
||||
console.log('打印结束');
|
||||
isPrint.value = false;
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
// 打印状态恢复函数
|
||||
function resetPrintState() {
|
||||
isPrint.value = false;
|
||||
isLoading.value = false;
|
||||
}
|
||||
function conFimPrint() {
|
||||
isLoading.value = true;
|
||||
isPrint.value = true;
|
||||
@@ -1017,7 +1032,8 @@ function conFimPrint() {
|
||||
// isPrint.value = false;
|
||||
// isLoading.value = false;
|
||||
// });
|
||||
}, 1000);
|
||||
resetPrintState();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -1072,7 +1088,6 @@ const payListAllAmount = computed(() => {
|
||||
});
|
||||
// 添加支付方式
|
||||
function addPayList() {
|
||||
console.log(com_pay_method.value);
|
||||
payList.value.push({
|
||||
payType: '',
|
||||
payAmount: null
|
||||
@@ -1104,6 +1119,27 @@ function handleChangePay(val: string, index: number = -1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handlePayListIsEmpt() {
|
||||
if (payList.value.length === 0) {
|
||||
ElMessage.warning('请添加支付方式');
|
||||
return false;
|
||||
}
|
||||
const invalidIndex = payList.value.findIndex(
|
||||
(item) =>
|
||||
item.payType === null ||
|
||||
item.payType === undefined ||
|
||||
item.payType === '' ||
|
||||
item.payAmount === null ||
|
||||
item.payAmount === undefined ||
|
||||
item.payAmount === ''
|
||||
);
|
||||
if (invalidIndex !== -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 校验数字
|
||||
function checkMoney(value: string) {
|
||||
if (!value) return false;
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addArea, getArea, updateArea } from '@/api/system/carArea';
|
||||
import { validator } from '@/utils/Reg';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
@@ -68,8 +69,46 @@ const form = ref({
|
||||
remark: null
|
||||
});
|
||||
const rules = ref({
|
||||
areaName: [{ required: true, message: '请输入区域名称', trigger: 'blur' }],
|
||||
areaCode: [{ required: true, message: '请输入区域编号', trigger: 'blur' }],
|
||||
areaName: [
|
||||
{ required: true, message: '请输入区域名称', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入名称'));
|
||||
}
|
||||
return validator(val, 'Character') ? callback() : callback(new Error('请输入中文,字母,数字,-,_等字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
parkingCount: [
|
||||
{ required: false, message: '请输入车位数量', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback();
|
||||
}
|
||||
const value = Number(val);
|
||||
if (Number.isNaN(value)) {
|
||||
return callback(new Error('请输入数字'));
|
||||
}
|
||||
if (value < 0) {
|
||||
return callback(new Error('请输入大于0的数字'));
|
||||
}
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
],
|
||||
areaCode: [
|
||||
{ required: true, message: '请输入区域编号', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入区域编号'));
|
||||
}
|
||||
return validator(val, 'Character') ? callback() : callback(new Error('请输入中文,字母,数字,-,_等字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
area: [
|
||||
{ required: true, message: '请输入区域面积', trigger: 'blur' },
|
||||
{
|
||||
|
||||
@@ -116,7 +116,6 @@ const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/car/uploadImage';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const formRef = ref();
|
||||
const carNumInputRef = ref();
|
||||
const form = ref({
|
||||
id: null,
|
||||
areaId: null, // 区域id
|
||||
@@ -158,9 +157,6 @@ const rules = ref({
|
||||
],
|
||||
carBrand: [{ required: false, message: '请输入车辆品牌', trigger: 'blur' }]
|
||||
});
|
||||
function handleValidate() {
|
||||
formRef.value.validateField('carNum');
|
||||
}
|
||||
function headerToken() {
|
||||
const useStore = useUserStore();
|
||||
return {
|
||||
@@ -168,7 +164,7 @@ function headerToken() {
|
||||
};
|
||||
}
|
||||
const userid = ref('');
|
||||
const allowImgSuffix = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic'];
|
||||
const allowImgSuffix = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
|
||||
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
const type = rawFile.type.split('/').pop();
|
||||
if (allowImgSuffix.includes(type)) {
|
||||
@@ -224,12 +220,6 @@ function changeAreaList(val: string) {
|
||||
// !== 提交 =============================================================================
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
const plateResult = carNumInputRef.value.validate();
|
||||
if (!plateResult.valid) {
|
||||
// 自动聚焦到错误字段
|
||||
carNumInputRef.value.focus();
|
||||
return;
|
||||
}
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
if (userid.value.trim() !== '') {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<el-option v-for="item in houseFormat" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="楼高(m)" prop="buildTail">
|
||||
<el-form-item label="楼高(m)" prop="buildTall">
|
||||
<el-input maxlength="4" v-model.trim="form.buildTall" placeholder="请输入楼高(m)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="楼栋结构" prop="buildStructure">
|
||||
@@ -46,6 +46,7 @@ import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addBuildingApi, editBuildingApi } from '@/api/system/house';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useHouseStore } from '@/store/modules/house';
|
||||
import { validator } from '@/utils/Reg';
|
||||
|
||||
const houseStore = useHouseStore();
|
||||
const houseFormat = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
|
||||
@@ -56,14 +57,37 @@ const form = ref({
|
||||
buildingName: '',
|
||||
buildToward: '',
|
||||
buildTall: '',
|
||||
// buildingUse: '0',
|
||||
buildStructure: '',
|
||||
// unitCount: null,
|
||||
floorCount: 1
|
||||
});
|
||||
const rules = ref({
|
||||
buildingName: [{ required: true, message: '请输入楼栋名称', trigger: 'blur' }],
|
||||
// buildingUse: [{ required: true, message: '请选择楼栋类型', trigger: 'blur' }],
|
||||
buildingName: [
|
||||
{ required: true, message: '请输入楼栋名称', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入名称'));
|
||||
}
|
||||
return validator(val, 'Character') ? callback() : callback(new Error('请输入中文,字母,数字,-,_等字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
buildTall: [
|
||||
{ required: false, message: '请输入楼高', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
console.log('val', val);
|
||||
if (val === '') {
|
||||
return callback();
|
||||
}
|
||||
const num = Number(val);
|
||||
if (Number.isNaN(num)) {
|
||||
return callback(new Error('请输入数字'));
|
||||
}
|
||||
return validator(num, 'number') ? callback() : callback(new Error('请输入数字'));
|
||||
}
|
||||
}
|
||||
],
|
||||
unitCount: [{ required: true, message: '请输入单元数', trigger: 'blur' }],
|
||||
floorCount: [{ required: true, message: '请输入楼层数', trigger: 'blur' }]
|
||||
});
|
||||
@@ -78,6 +102,7 @@ if (buildingId) {
|
||||
function getBuildingById() {
|
||||
houseStore.currentBuildingInfoList.forEach((item) => {
|
||||
if (item.id == buildingId) {
|
||||
console.log(item);
|
||||
form.value.buildingName = item.buildingName;
|
||||
form.value.buildToward = item.buildToward;
|
||||
// form.value.buildingUse = item.buildingUse;
|
||||
|
||||
@@ -86,6 +86,7 @@ import { GetVillageListParking } from '@/api/system/parking';
|
||||
import { GetVillagelistStoreroom } from '@/api/system/storeroom';
|
||||
import { listHouseUseType_add_house } from '@/api/system/houseUse';
|
||||
import { getByBUildingidtoUnitNo } from '@/api/system/houseUnit';
|
||||
import { validator } from '@/utils/Reg';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
@@ -93,7 +94,7 @@ const houseStore = useHouseStore();
|
||||
const formRef = ref();
|
||||
const form = ref<addHouseType>({
|
||||
buildingId: '',
|
||||
houseUseTypeId: '', // 房屋用途
|
||||
houseUseTypeId: '', // 房屋用途╬
|
||||
unitNoId: '',
|
||||
floorNo: '',
|
||||
houseNo: '', // 房 间 号
|
||||
@@ -110,7 +111,17 @@ const rules = ref({
|
||||
floorNo: [{ required: true, message: '请选择楼层', trigger: 'blur' }],
|
||||
houseUseTypeId: [{ required: true, message: '请选择房屋用途', trigger: 'blur' }],
|
||||
buildingName: [{ required: true, message: '请输入房间号', trigger: 'blur' }],
|
||||
houseNo: [{ required: true, message: '请输入房间号', trigger: 'blur' }],
|
||||
houseNo: [
|
||||
{ required: true, message: '请输入房间号', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入名称'));
|
||||
}
|
||||
return validator(val, 'Character') ? callback() : callback(new Error('请输入中文,字母,数字,-,_等字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
buildingArea: [{ required: true, message: '请输入建筑面积', trigger: 'blur' }],
|
||||
internalFloorArea: [{ required: true, message: '请输入套内面积', trigger: 'blur' }],
|
||||
CommonArea: [{ required: true, message: '请输入公摊面积', trigger: 'blur' }],
|
||||
@@ -129,7 +140,7 @@ const rules = ref({
|
||||
if (Number.isNaN(val)) {
|
||||
return callback(new Error('请输入数字'));
|
||||
}
|
||||
if (val < 0 || val > 99999.99) {
|
||||
if (val < 0 || val > 99999999) {
|
||||
ElMessage.error('房屋面积超出合法范围');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -229,7 +229,17 @@ const form = ref({
|
||||
const userHousePath = ref<CascaderValue>([]);
|
||||
const rules = ref({
|
||||
houseId: [{ required: true, message: '请选择房屋', trigger: 'blur' }],
|
||||
rentalName: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
||||
rentalName: [
|
||||
{ required: true, message: '请输入名称', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入名称'));
|
||||
}
|
||||
return validator(val, 'ChineseName') ? callback() : callback(new Error('请输入中文字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||
{
|
||||
@@ -316,7 +326,7 @@ async function getTreeData() {
|
||||
};
|
||||
if (form.value.facilities) houseDevicesList.value = form.value.facilities.split(',').filter((item) => item);
|
||||
if (form.value.houseImageUrl) fileList.value = splitStringUrl(form.value.houseImageUrl);
|
||||
handleChange([form.value.buildingId, form.value.unitNoId, form.value.houseId]);
|
||||
userHousePath.value = [form.value.buildingId, form.value.unitNoId, form.value.houseId];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card>
|
||||
<div class="h-full flex flex-align-center">
|
||||
<el-form label-width="120px" ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form label-width="80px" ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="房屋类型" prop="houseUse">
|
||||
<el-select v-model="queryParams.houseUse" placeholder="选择房屋类型" style="width: 240px">
|
||||
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
@@ -53,7 +53,6 @@
|
||||
<el-table-column label="发布时间" align="center" prop="pubTime" />
|
||||
<el-table-column label="房屋类型" align="center" prop="houseUse">
|
||||
<template #default="{ row }">
|
||||
<!-- <DictTag :options="com_house_use" :value="row.houseUse"></DictTag>-->
|
||||
<span>{{ handleHouseUse(row.houseUse) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -62,8 +61,25 @@
|
||||
<DictTag :options="com_rental_method" :value="row.rentalType"></DictTag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.status === '0' ? '下架' : '上架' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" v-if="scope.row.status === '0'" @click="sign(scope.row)" v-has-permi="['houseRental:houseRental:edit']"
|
||||
>签约</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
v-if="scope.row.status === '0'"
|
||||
@click="putOnSale(scope.row)"
|
||||
v-has-permi="['houseRental:houseRental:edit']"
|
||||
>上架</el-button
|
||||
>
|
||||
<el-button link type="primary" v-else @click="putOnSale(scope.row)" v-has-permi="['houseRental:houseRental:edit']">下架</el-button>
|
||||
<el-button link type="primary" @click="handleMain(scope.row)" v-has-permi="['houseRental:houseRental:edit']">详情</el-button>
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['houseRental:houseRental:query']">编辑</el-button>
|
||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['houseRental:houseRental:remove']">删除</el-button>
|
||||
@@ -73,18 +89,76 @@
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="houseRentalFormRef" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form-item label="合同编号" prop="contractNo">
|
||||
<el-input maxlength="20" show-word-limit v-model.trim="form.contractNo" placeholder="请输入合同编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域" prop="villageId">
|
||||
<el-input disabled maxlength="20" v-model.trim="form.villageName" placeholder="请输入区域" />
|
||||
</el-form-item>
|
||||
<el-form-item label="承租方" prop="tenantName">
|
||||
<el-input maxlength="20" show-word-limit v-model.trim="form.tenantName" placeholder="请输入承租方" />
|
||||
</el-form-item>
|
||||
<el-form-item label="电话" prop="tenantPhone">
|
||||
<el-input maxlength="11" v-model.trim="form.tenantPhone" placeholder="请输入电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="房号" prop="houseId">
|
||||
<el-input disabled maxlength="20" show-word-limit v-model.trim="form.houseName" placeholder="请输入房号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="面积" prop="houseArea">
|
||||
<el-input disabled maxlength="20" show-word-limit v-model.trim="form.houseArea" placeholder="请输入面积" />
|
||||
</el-form-item>
|
||||
<el-form-item label="收费模式" prop="chargeMode">
|
||||
<el-input v-model.trim="form.chargeMode" placeholder="请输入收费模式" />
|
||||
</el-form-item>
|
||||
<el-form-item label="收费标准" prop="chargeStandard">
|
||||
<el-input v-model.trim="form.chargeStandard" placeholder="请输入收费标准" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同状态" prop="contractStatus">
|
||||
<el-input v-model.trim="form.contractStatus" placeholder="请输入合同状态" />
|
||||
</el-form-item>
|
||||
<el-form-item label="租赁起始日" prop="leaseStartDate">
|
||||
<el-date-picker
|
||||
style="width: 100%"
|
||||
v-model.trim="form.leaseStartDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD"
|
||||
type="date"
|
||||
placeholder="请选择租赁起始日"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="租赁终止日" prop="leaseEndDate">
|
||||
<el-date-picker
|
||||
style="width: 100%"
|
||||
v-model.trim="form.leaseEndDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD"
|
||||
type="date"
|
||||
placeholder="请选择租赁终止日"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="HouseRental" lang="ts">
|
||||
import Pageheader from '@/components/Pageheader/index.vue';
|
||||
import { listHouseRental, delHouseRental } from '@/api/system/houseRental/index';
|
||||
import { listHouseRental, delHouseRental, changeHouseRedientStatus, HouseRedientSign } from '@/api/system/houseRental/index';
|
||||
import { HouseRentalVO, HouseRentalQuery, HouseRentalForm } from '@/api/system/houseRental/type';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
import { listHouseUseType_add_house } from '@/api/system/houseUse';
|
||||
import { validator } from '@/utils/Reg';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_house_use } = toRefs<any>(proxy?.useDict('com_house_use'));
|
||||
const { com_rental_status } = toRefs<any>(proxy?.useDict('com_rental_status'));
|
||||
const { com_rental_method } = toRefs<any>(proxy?.useDict('com_rental_method'));
|
||||
|
||||
@@ -101,29 +175,34 @@ const total = ref(0);
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const houseRentalFormRef = ref<ElFormInstance>();
|
||||
|
||||
const villageInfo = localStorage.getItem('villageInfo');
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const initFormData: HouseRentalForm = {
|
||||
id: undefined,
|
||||
rentalName: undefined,
|
||||
rent: undefined,
|
||||
rentalType: undefined,
|
||||
houseFace: undefined,
|
||||
houseArea: undefined,
|
||||
floorNo: undefined,
|
||||
inTime: undefined,
|
||||
facilities: undefined,
|
||||
houseImageUrl: undefined,
|
||||
supInfo: undefined,
|
||||
phone: undefined,
|
||||
vx: undefined,
|
||||
email: undefined,
|
||||
houseId: undefined
|
||||
type HouseRentalFormType = HouseRentalForm & {
|
||||
villageName?: string;
|
||||
houseName?: string;
|
||||
houseArea?: number;
|
||||
};
|
||||
const data = reactive<PageData<HouseRentalForm, HouseRentalQuery>>({
|
||||
|
||||
const initFormData: HouseRentalFormType = {
|
||||
'rentalId': undefined,
|
||||
'contractNo': undefined,
|
||||
'tenantName': undefined,
|
||||
'tenantPhone': undefined,
|
||||
'chargeMode': undefined,
|
||||
'chargeStandard': undefined,
|
||||
'contractStatus': undefined,
|
||||
'leaseStartDate': undefined,
|
||||
'leaseEndDate': undefined,
|
||||
'houseId': undefined,
|
||||
'villageId': undefined,
|
||||
'remark': undefined
|
||||
};
|
||||
|
||||
const data = reactive<PageData<HouseRentalFormType, HouseRentalQuery>>({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
@@ -142,12 +221,44 @@ const data = reactive<PageData<HouseRentalForm, HouseRentalQuery>>({
|
||||
phone: undefined,
|
||||
vx: undefined,
|
||||
email: undefined,
|
||||
houseId: undefined,
|
||||
params: {}
|
||||
houseId: undefined
|
||||
},
|
||||
rules: {
|
||||
contractNo: [
|
||||
{ required: true, message: '请输入合同编号', trigger: 'blur' },
|
||||
{ min: 1, max: 20, message: '合同编号长度必须在 1 到 20 个字符之间', trigger: 'blur' },
|
||||
{ pattern: /^[a-zA-Z0-9_\-]+$/, message: '合同编号只能包含字母、数字,下划线和短横线', trigger: 'blur' }
|
||||
],
|
||||
tenantName: [
|
||||
{ required: true, message: '请输入承租方姓名', trigger: 'blur' },
|
||||
{ min: 1, max: 20, message: '承租方姓名长度必须在 1 到 20 个字符之间', trigger: 'blur' }
|
||||
],
|
||||
tenantPhone: [
|
||||
{ required: true, message: '请输入承租方联系电话', trigger: 'blur' },
|
||||
{ min: 11, max: 11, message: '承租方联系电话长度必须为 11 个字符', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (!validator(value, 'phone')) {
|
||||
callback(new Error('承租方联系电话格式错误'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: ['blur', 'change']
|
||||
}
|
||||
],
|
||||
chargeMode: [{ required: true, message: '请选择收费模式', trigger: 'change' }],
|
||||
chargeStandard: [{ required: true, message: '请输入收费标准', trigger: 'blur' }],
|
||||
contractStatus: [{ required: true, message: '请选择合同状态', trigger: 'change' }],
|
||||
leaseStartDate: [{ required: true, message: '请选择租赁起始日', trigger: 'change' }],
|
||||
leaseEndDate: [{ required: true, message: '请选择租赁终止日', trigger: 'change' }],
|
||||
houseId: [{ required: true, message: '请选择房屋', trigger: 'change' }],
|
||||
villageId: [{ required: true, message: '请选择小区', trigger: 'change' }],
|
||||
houseArea: [{ required: true, message: '请输入房屋面积', trigger: 'blur' }]
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form } = toRefs(data);
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
/** 查询房屋租赁管理列表 */
|
||||
const getList = async () => {
|
||||
@@ -203,7 +314,7 @@ const handleAdd = () => {
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: HouseRentalVO) => {
|
||||
const handleUpdate = (row?: HouseRentalVO) => {
|
||||
const id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/house/edithouseRental',
|
||||
@@ -213,7 +324,7 @@ const handleUpdate = async (row?: HouseRentalVO) => {
|
||||
});
|
||||
};
|
||||
/** 详情按钮操作 */
|
||||
const handleMain = async (row?: HouseRentalVO) => {
|
||||
const handleMain = (row?: HouseRentalVO) => {
|
||||
router.push({
|
||||
path: '/house/houseMain',
|
||||
query: {
|
||||
@@ -241,6 +352,40 @@ function handleHouseUse(houseUser: string) {
|
||||
const item = houseUseTypeList.value.find((item) => item.id === houseUser);
|
||||
return item?.name || '';
|
||||
}
|
||||
|
||||
// 签约
|
||||
function sign(row: HouseRentalVO) {
|
||||
form.value = {
|
||||
...row.signingList?.[0]
|
||||
};
|
||||
const info = JSON.parse(villageInfo || '{}');
|
||||
form.value.villageName = info.villageName;
|
||||
form.value.houseName = row.name;
|
||||
form.value.houseArea = row.houseArea;
|
||||
form.value.houseId = row.houseId;
|
||||
form.value.villageId = info.villageId;
|
||||
form.value.rentalId = row.id;
|
||||
dialog.visible = true;
|
||||
dialog.title = '签约';
|
||||
}
|
||||
// 上架
|
||||
function putOnSale(row: HouseRentalVO) {
|
||||
changeHouseRedientStatus(row.id).then(() => {
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
getList();
|
||||
});
|
||||
}
|
||||
function submitForm() {
|
||||
houseRentalFormRef.value.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
HouseRedientSign(form.value).then(() => {
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
getList();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
getHouseUseType();
|
||||
|
||||
@@ -145,8 +145,36 @@ const form = ref({
|
||||
const rules = ref({
|
||||
areaId: [{ required: true, message: '请选择车位区域', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '请选择车位类型', trigger: 'blur' }],
|
||||
parkingCode: [{ required: true, message: '请输入车位编号', trigger: 'blur' }],
|
||||
parkingCode: [
|
||||
{ required: true, message: '请输入车位编号', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入车位编号'));
|
||||
}
|
||||
return validator(val, 'Character') ? callback() : callback(new Error('请输入中文,字母,数字,-,_等字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
residentId: [{ required: false, message: '请选择持有人', trigger: 'blur' }],
|
||||
parkingFloor: [
|
||||
{ required: false, message: '请输入车位楼层', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (value === '' || value === null) {
|
||||
return callback();
|
||||
}
|
||||
const val = Number(value);
|
||||
if (Number.isNaN(val)) {
|
||||
return callback(new Error('请输入数字'));
|
||||
}
|
||||
if (val <= 0) {
|
||||
return callback(new Error('请输入大于0的数字'));
|
||||
}
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
],
|
||||
contactPhone: [
|
||||
{ required: true, message: '请输入联系人电话', trigger: 'blur' },
|
||||
{
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="住户姓名" prop="name">
|
||||
<el-input maxlength="15" show-word-limit v-model.trim="form.name" placeholder="请输入住户姓名" />
|
||||
<el-input maxlength="10" show-word-limit v-model.trim="form.name" placeholder="请输入住户姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="住户性别" prop="gender">
|
||||
@@ -51,7 +50,13 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="年龄" prop="age" v-if="form.idCardType !== '0'">
|
||||
<el-input maxlength="3" v-model.number.trim="form.age" placeholder="年龄" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="与业主的关系" prop="ownerRelationship">
|
||||
@@ -152,12 +157,32 @@ const form = ref<ResidentForm>({
|
||||
cardImageFront: '',
|
||||
idCardType: '0', // 证件类型
|
||||
cardImageBack: '',
|
||||
remark: '' //备注╬╬╬.╬╬╬╬╬
|
||||
age: 0, //年龄
|
||||
remark: '' //备注╬╬▓╬▐╬╬
|
||||
});
|
||||
const userHousePath = ref<CascaderValue>([]);
|
||||
const rules = ref({
|
||||
houseId: [{ required: true, message: '请选择房屋', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
||||
name: [
|
||||
{ required: true, message: '请输入名称', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入名称'));
|
||||
}
|
||||
return validator(val, 'ChineseName') ? callback() : callback(new Error('请输入中文名称,1-10位字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
age: [
|
||||
{ required: true, message: '请输入年龄', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
|
||||
return validator(value, 'age') ? callback() : callback(new Error('请输入正确的年龄'));
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
gender: [{ required: true, message: '请选择性别', trigger: 'blur' }],
|
||||
cardImageFront: [{ required: true, message: '请上传身份证照片', trigger: 'blur' }],
|
||||
cardImageBack: [{ required: true, message: '请上传身份证照片', trigger: 'blur' }],
|
||||
@@ -266,7 +291,7 @@ const handleBeforeUpload = (uploadFile: UploadRawFile) => {
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// !== 提交 =============================================================================
|
||||
// !==╬╬&╬╬╬ ╬ 提交 =============================================================================
|
||||
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" label-width="120" label-position="left" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
||||
<el-form ref="queryFormRef" label-width="100" label-position="left" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
||||
<el-form-item label="与主业主关系" prop="ownerRelationship">
|
||||
<el-select v-model="queryParams.ownerRelationship" placeholder="请选择与主业主关系" style="width: 240px">
|
||||
<el-option v-for="item in com_resident_relationship" :key="item.value" :label="item.label" :value="item.value" />
|
||||
@@ -15,6 +15,12 @@
|
||||
<el-option v-for="item in com_review" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="住户姓名" prop="name">
|
||||
<el-input v-model.trim="queryParams.name" maxlength="10" placeholder="请输入住户姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="房间号" prop="houseName">
|
||||
<el-input v-model.trim="queryParams.houseName" maxlength="10" placeholder="请输入房间号" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
@@ -170,10 +176,11 @@ const data = reactive<PageData<ResidentForm, ResidentQuery>>({
|
||||
date: '',
|
||||
ownerRelationship: null,
|
||||
status: null,
|
||||
|
||||
houseId: null,
|
||||
buildingId: null,
|
||||
unitNoId: null
|
||||
unitNoId: null,
|
||||
houseName: null,
|
||||
name: null
|
||||
}
|
||||
});
|
||||
|
||||
@@ -199,7 +206,9 @@ const handleNodeClick = (data: Tree, node) => {
|
||||
...{
|
||||
houseId: null,
|
||||
buildingId: null,
|
||||
unitNoId: null
|
||||
unitNoId: null,
|
||||
houseName: null,
|
||||
name: null
|
||||
},
|
||||
...obj2
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ onUnmounted(() => {
|
||||
});
|
||||
|
||||
function reset() {
|
||||
date.value = getLastNDays(10)[0];
|
||||
date.value = getLastNDays(7)[0];
|
||||
querySelect();
|
||||
}
|
||||
|
||||
@@ -372,10 +372,10 @@ const dayX = ref([]);
|
||||
const inData = ref([]);
|
||||
const outData = ref([]);
|
||||
|
||||
/** 近十天人员流入流出 - 平滑折线图 */
|
||||
/** 近十天人员流入流出 - 平滑折线图╥╬ */
|
||||
const flowLineOption = ref<EChartsOption>({
|
||||
title: {
|
||||
text: '近十日人员流动趋势',
|
||||
text: '近七日人员流动趋势',
|
||||
left: 0,
|
||||
top: 0,
|
||||
textStyle: { fontSize: 14, fontWeight: 'normal' }
|
||||
@@ -461,7 +461,7 @@ const flowLineOption = ref<EChartsOption>({
|
||||
function flowLineOptionFun(days: string[], InData: number[], OutData: number[]): EChartsOption {
|
||||
return {
|
||||
title: {
|
||||
text: '近十日人员流动趋势',
|
||||
text: '近七日人员流动趋势',
|
||||
left: 0,
|
||||
top: 0,
|
||||
textStyle: { fontSize: 14, fontWeight: 'normal' }
|
||||
@@ -605,7 +605,7 @@ function MoveInUserType() {
|
||||
{ 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' } }
|
||||
{ value: res.otherType, name: '其他', itemStyle: { color: '#f48e3b' } }
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="建筑面积" prop="houseArea">
|
||||
<el-input maxlength="8" v-model="form.houseArea" placeholder="请输入建筑面积">
|
||||
<el-input maxlength="8" v-model.trim="form.houseArea" placeholder="请输入建筑面积">
|
||||
<template #append>
|
||||
<span>㎡</span>
|
||||
</template>
|
||||
@@ -42,7 +42,7 @@
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="公摊面积" prop="shareArea">
|
||||
<el-input maxlength="8" v-model="form.shareArea" placeholder="请输入公摊面积">
|
||||
<el-input maxlength="8" v-model.trim="form.shareArea" placeholder="请输入公摊面积">
|
||||
<template #append>
|
||||
<span>㎡</span>
|
||||
</template>
|
||||
@@ -52,7 +52,7 @@
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="实用面积" prop="internalArea">
|
||||
<el-input maxlength="8" v-model="form.internalArea" placeholder="请输入实用面积">
|
||||
<el-input maxlength="8" v-model.trim="form.internalArea" placeholder="请输入实用面积">
|
||||
<template #append>
|
||||
<span>㎡</span>
|
||||
</template>
|
||||
@@ -61,7 +61,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model="form.remark" placeholder="请输入备注" />
|
||||
<el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model.trim="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-top: 30px">
|
||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||
@@ -80,6 +80,7 @@ import { getBuildinglists } from '@/api/system/house';
|
||||
import { addStoreroom, getStoreroom, updateStoreroom } from '@/api/system/storeroom';
|
||||
import { StoreroomVO } from '@/api/system/storeroom/types';
|
||||
import { getByBUildingidtoUnitNo } from '@/api/system/houseUnit';
|
||||
import { validator } from '@/utils/Reg';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -100,7 +101,17 @@ const form = ref<StoreroomVO>({
|
||||
const rules = ref({
|
||||
buildingId: [{ required: true, message: '请选择楼栋', trigger: 'blur' }],
|
||||
unitNoId: [{ required: true, message: '请选择单元', trigger: 'blur' }],
|
||||
storeroomNo: [{ required: true, message: '请输入储藏室号', trigger: 'blur' }],
|
||||
storeroomNo: [
|
||||
{ required: true, message: '请输入储藏室号', trigger: 'blur' },
|
||||
{
|
||||
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error('请输入储藏室号'));
|
||||
}
|
||||
return validator(val, 'Character') ? callback() : callback(new Error('请输入中文,字母,数字,-,_等字符'));
|
||||
}
|
||||
}
|
||||
],
|
||||
houseArea: [
|
||||
{ required: true, message: '请输入建筑面积', trigger: 'blur' },
|
||||
{
|
||||
@@ -112,7 +123,7 @@ const rules = ref({
|
||||
if (Number.isNaN(val)) {
|
||||
return callback(new Error('请输入数字'));
|
||||
}
|
||||
if (val <= 0) {
|
||||
if (val < 0) {
|
||||
return callback(new Error('请输入大于0的数字'));
|
||||
}
|
||||
return callback();
|
||||
@@ -130,7 +141,7 @@ const rules = ref({
|
||||
if (Number.isNaN(val)) {
|
||||
return callback(new Error('请输入数字'));
|
||||
}
|
||||
if (val <= 0) {
|
||||
if (val < 0) {
|
||||
return callback(new Error('请输入大于0的数字'));
|
||||
}
|
||||
return callback();
|
||||
@@ -148,7 +159,7 @@ const rules = ref({
|
||||
if (Number.isNaN(val)) {
|
||||
return callback(new Error('请输入数字'));
|
||||
}
|
||||
if (val <= 0) {
|
||||
if (val < 0) {
|
||||
return callback(new Error('请输入大于0的数字'));
|
||||
}
|
||||
return callback();
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
<div
|
||||
class="topbox"
|
||||
:class="{
|
||||
quickbg: Sideactive === 1,
|
||||
todobg: Sideactive === 2
|
||||
quickbg: sideActive === 1,
|
||||
todobg: sideActive === 2
|
||||
}"
|
||||
>
|
||||
<div
|
||||
:class="{
|
||||
active: Sideactive === 1
|
||||
active: sideActive === 1
|
||||
}"
|
||||
@click="handleSelect(1)"
|
||||
>
|
||||
@@ -34,7 +34,7 @@
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
active: Sideactive === 2
|
||||
active: sideActive === 2
|
||||
}"
|
||||
@click="handleSelect(2)"
|
||||
>
|
||||
@@ -43,8 +43,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="body flex-1">
|
||||
<quick v-if="Sideactive === SideList.quick"></quick>
|
||||
<todo v-else-if="Sideactive === SideList.todo"></todo>
|
||||
<quick v-if="sideActive === SideList.quick"></quick>
|
||||
<todo v-else-if="sideActive === SideList.todo"></todo>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,7 +68,7 @@ import icon1 from './assets/user.png';
|
||||
import icon2 from './assets/user.png';
|
||||
import icon3 from './assets/car.png';
|
||||
import icon4 from './assets/device.png';
|
||||
import icon5 from './assets/wuliao.png';
|
||||
// import icon5 from './assets/wuliao.png';
|
||||
import icon6 from './assets/tousu.png';
|
||||
|
||||
import { getVillageByIdAPI } from '@/api/system/community';
|
||||
@@ -81,7 +81,7 @@ import quick from './components/quick.vue';
|
||||
import todo from './components/todo.vue';
|
||||
import feeOverview from './components/feeOverview.vue';
|
||||
|
||||
import inandoutEcharts from './components/inandout.vue';
|
||||
// import inandoutEcharts from './components/inandout.vue';
|
||||
import repairechartsAll from './components/repairechartsAll.vue';
|
||||
const houseStore = useHouseStore();
|
||||
const villageinfo = ref({
|
||||
@@ -97,15 +97,15 @@ const list = ref([
|
||||
// { name: '物料总数量', value: 458, icon: icon5 }
|
||||
]);
|
||||
|
||||
function getVillageinfo() {
|
||||
function getVillageInfo() {
|
||||
const id = localStorage.getItem('villageid');
|
||||
workSpaceTotalListApi(id).then((res) => {
|
||||
list.value[0].value = res.totalResident;
|
||||
list.value[1].value = res.totalHouse;
|
||||
list.value[2].value = res.totalParking;
|
||||
list.value[3].value = res.totalDevice;
|
||||
list.value[4].value = res.totalMaterial;
|
||||
list.value[5].value = res.totalComplaint;
|
||||
list.value[4].value = res.totalComplaint;
|
||||
list.value[5].value = res.totalMaterial;
|
||||
});
|
||||
getVillageByIdAPI(id).then((res) => {
|
||||
villageinfo.value = {
|
||||
@@ -127,12 +127,12 @@ function getVillageinfo() {
|
||||
houseStore.updateVilageinfo(res.data);
|
||||
});
|
||||
}
|
||||
getVillageinfo();
|
||||
getVillageInfo();
|
||||
|
||||
// ! 侧边栏
|
||||
const Sideactive = ref(1);
|
||||
const sideActive = ref(1);
|
||||
function handleSelect(val: number) {
|
||||
Sideactive.value = val;
|
||||
sideActive.value = val;
|
||||
}
|
||||
// ! 侧边栏
|
||||
/** 侧边栏功能枚举 */
|
||||
|
||||
Reference in New Issue
Block a user