7/30 限制前端输入字数

This commit is contained in:
Zy
2026-07-30 17:59:32 +08:00
parent 903c92fef0
commit 2907f9202c
115 changed files with 2561 additions and 1213 deletions

View File

@@ -17,7 +17,7 @@ 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_APP_BASE_API='http://192.168.1.198'
# 登录成功跳转地址 # 登录成功跳转地址
# VITE_LOGIN_BACK_URL = '/equipment/WaterDevice' # VITE_LOGIN_BACK_URL = '/equipment/WaterDevice'
VITE_LOGIN_BACK_URL='/index' VITE_LOGIN_BACK_URL='/index'

View File

@@ -61,3 +61,61 @@ export const delParkingCost = (id: string | number | Array<string | number>) =>
method: 'delete' method: 'delete'
}); });
}; };
export type Request = {
/**
* 区域id
*/
areaId?: string;
/**
* 0 审核中 1 审核通过 2 审核不通过
*/
checkStatus?: string;
/**
* 添加者姓名sys_user nickname
*/
createName?: string;
/**
* id车位管理表
*/
id?: string;
/**
* 车位面积(单位㎡)
*/
parkingArea?: number;
/**
* 车位编号
*/
parkingCode?: string;
/**
* 车位楼层
*/
parkingFloor?: string;
/**
* 车位状态 0 闲置 1自用 2出租
*/
parkingStatus?: string;
/**
* 备注
*/
remark?: string;
/**
* 住户id
*/
residentId?: string;
/**
* 所属小区id
*/
villageId?: string;
};
/**
* 查询停车缴费 车位列表
* @param {Request} queryParams
*/
export const getParkingCostCarAreaApi = (queryParams: Request) => {
return request({
url: '/parkingCost/parkingList',
method: 'get',
params: queryParams
});
};

View File

@@ -22,8 +22,9 @@ export const cashQuery = (data: { residentName?: string; queryType: number }): A
}; };
export type billlistType = { export type billlistType = {
actualAccount: string; needPayAmount: string; // 需要支付金额
singleDiscountAmount: string; actualAccount: string; // 实际支付金额
singleDiscountAmount: string; // 单笔优惠金额
'villageId': string; 'villageId': string;
'residentId': string; 'residentId': string;
'houseId': string; 'houseId': string;
@@ -61,7 +62,10 @@ export const billEdit = (data: { 'detailsId': string[]; 'payType': string; 'payS
return request({ return request({
url: '/cash/billEdit', url: '/cash/billEdit',
method: 'post', method: 'post',
data: data data: data,
headers: {
'isEncrypt': 'true'
}
}); });
}; };

View File

@@ -4,9 +4,9 @@ export interface communitylist_rows_type {
villageCode: string; villageCode: string;
address: string; address: string;
houseUse: number | null; houseUse: number | null;
villageArea: number; villageArea: string;
remark: string; remark: string;
parkingSpaceCount: number; parkingSpaceCount: string;
villageImageUrl: string; villageImageUrl: string;
city: string; city: string;
status: '0' | '1'; status: '0' | '1';

View File

@@ -5,6 +5,7 @@ export interface ResidentVO {
userId: string; userId: string;
id: string; id: string;
unitNoId: string; unitNoId: string;
idCardType: string;
/** /**
* 住户编号 * 住户编号
*/ */
@@ -81,7 +82,13 @@ export interface ResidentForm extends BaseEntity {
*/ */
userId?: string; userId?: string;
unitNoId?: string; unitNoId?: string;
/**
* 证件类型
* 0 身份证
* 1 护照
* 2 港澳通行证
*/
idCardType?: string;
/** /**
* 住户编号 * 住户编号
*/ */

View File

@@ -212,10 +212,11 @@ export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => {
/** /**
* 查询用户 根据不同的角色key * 查询用户 根据不同的角色key
*/ */
export const getUserByRoleKey = (roleKey: string = 'repair') => { export const getUserByRoleKey = (data: { roleKey: string; pageSize?: number; pageNum?: number; phonenumber?: string; nickName?: string }) => {
return request({ return request({
url: '/system/user/list/byRoleKey?roleKey=' + roleKey, url: '/system/user/list/byRoleKey',
method: 'get' method: 'get',
params: data
}); });
}; };

View File

@@ -1 +1,5 @@
<svg width="130" height="130" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg> <?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="72" height="72">
<path d="M0 0 C2.20570851 -0.00968797 4.41047736 -0.04072695 6.6159668 -0.07226562 C8.03327902 -0.07879854 9.45059785 -0.08404788 10.86791992 -0.08789062 C12.14642822 -0.09723633 13.42493652 -0.10658203 14.7421875 -0.11621094 C19.47309186 0.34343639 23.47367381 1.57231844 27.15307617 4.74023438 C30.37034726 9.00034505 31.56636885 11.94712449 31.66088867 17.24023438 C31.68666992 18.10648438 31.71245117 18.97273438 31.73901367 19.86523438 C31.33471302 22.79160097 30.73125242 23.46286318 28.41088867 25.24023438 C26.09619141 25.6211853 26.09619141 25.6211853 23.34448242 25.62841797 C21.79772827 25.64260269 21.79772827 25.64260269 20.21972656 25.65707397 C19.10718506 25.65100128 17.99464355 25.64492859 16.84838867 25.63867188 C15.7055542 25.64154205 14.56271973 25.64441223 13.38525391 25.64736938 C10.96768702 25.64941195 8.55010368 25.64386876 6.13256836 25.63134766 C2.42548783 25.61529758 -1.28050233 25.63119078 -4.98754883 25.65039062 C-7.33390541 25.64840823 -9.68026131 25.64456463 -12.02661133 25.63867188 C-13.69542358 25.64778091 -13.69542358 25.64778091 -15.39794922 25.65707397 C-16.42911865 25.64761749 -17.46028809 25.63816101 -18.52270508 25.62841797 C-19.88480103 25.6248378 -19.88480103 25.6248378 -21.27441406 25.6211853 C-24.04037872 25.16596517 -24.92923084 24.46245011 -26.58911133 22.24023438 C-27.60354862 16.46192001 -26.97476687 11.09300732 -23.58911133 6.24023438 C-16.66108134 -0.90126433 -9.35102094 0.02485596 0 0 Z M-18.58911133 11.24023438 C-18.91911133 13.55023438 -19.24911133 15.86023438 -19.58911133 18.24023438 C-5.06911133 18.24023438 9.45088867 18.24023438 24.41088867 18.24023438 C24.11197307 11.59954901 24.11197307 11.59954901 21.30541992 8.8359375 C17.68528986 6.84022478 15.2236764 6.72349544 11.09838867 6.70898438 C10.40704834 6.70515747 9.71570801 6.70133057 9.00341797 6.6973877 C7.54775529 6.69467651 6.09204324 6.70198226 4.63647461 6.71875 C2.41693822 6.74017598 0.20063771 6.71892665 -2.01879883 6.69335938 C-3.43807676 6.6960028 -4.85735268 6.70112809 -6.27661133 6.70898438 C-7.55922852 6.71349609 -8.8418457 6.71800781 -10.16333008 6.72265625 C-14.24225476 7.3389134 -15.87427125 8.1400784 -18.58911133 11.24023438 Z " transform="translate(33.589111328125,39.759765625)"/>
<path d="M0 0 C4.3525815 2.2134923 7.02675779 4.79167963 9.078125 9.3046875 C9.84088671 14.58111131 9.73444722 18.86077861 7.515625 23.7421875 C3.60118069 27.85737255 -0.12616384 30.46772755 -5.921875 30.8046875 C-11.71758616 30.46772755 -15.44493069 27.85737255 -19.359375 23.7421875 C-21.57819722 18.86077861 -21.68463671 14.58111131 -20.921875 9.3046875 C-18.87050779 4.79167963 -16.1963315 2.2134923 -11.84375 0 C-7.76639941 -1.47513904 -4.07735059 -1.47513904 0 0 Z M-13.921875 10.3046875 C-15.07584314 13.30500466 -15.04771333 14.82421387 -14.234375 17.9296875 C-12.72322882 20.66414249 -11.68578936 21.84595492 -8.921875 23.3046875 C-5.10725414 23.87282252 -3.43491208 23.61250975 -0.109375 21.6171875 C2.35349982 19.01357698 2.99140319 17.86028174 3.078125 14.3046875 C2.30174948 11.34034461 1.45595939 9.69601598 -0.671875 7.4921875 C-6.02599766 4.66640054 -9.91623177 6.07015037 -13.921875 10.3046875 Z " transform="translate(41.921875,7.6953125)"/>
</svg>

Before

Width:  |  Height:  |  Size: 440 B

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="72" height="72">
<path d="M0 0 C2.20570851 -0.00968797 4.41047736 -0.04072695 6.6159668 -0.07226562 C8.03327902 -0.07879854 9.45059785 -0.08404788 10.86791992 -0.08789062 C12.14642822 -0.09723633 13.42493652 -0.10658203 14.7421875 -0.11621094 C19.47309186 0.34343639 23.47367381 1.57231844 27.15307617 4.74023438 C30.37034726 9.00034505 31.56636885 11.94712449 31.66088867 17.24023438 C31.68666992 18.10648438 31.71245117 18.97273438 31.73901367 19.86523438 C31.33471302 22.79160097 30.73125242 23.46286318 28.41088867 25.24023438 C26.09619141 25.6211853 26.09619141 25.6211853 23.34448242 25.62841797 C21.79772827 25.64260269 21.79772827 25.64260269 20.21972656 25.65707397 C19.10718506 25.65100128 17.99464355 25.64492859 16.84838867 25.63867188 C15.7055542 25.64154205 14.56271973 25.64441223 13.38525391 25.64736938 C10.96768702 25.64941195 8.55010368 25.64386876 6.13256836 25.63134766 C2.42548783 25.61529758 -1.28050233 25.63119078 -4.98754883 25.65039062 C-7.33390541 25.64840823 -9.68026131 25.64456463 -12.02661133 25.63867188 C-13.69542358 25.64778091 -13.69542358 25.64778091 -15.39794922 25.65707397 C-16.42911865 25.64761749 -17.46028809 25.63816101 -18.52270508 25.62841797 C-19.88480103 25.6248378 -19.88480103 25.6248378 -21.27441406 25.6211853 C-24.04037872 25.16596517 -24.92923084 24.46245011 -26.58911133 22.24023438 C-27.60354862 16.46192001 -26.97476687 11.09300732 -23.58911133 6.24023438 C-16.66108134 -0.90126433 -9.35102094 0.02485596 0 0 Z M-18.58911133 11.24023438 C-18.91911133 13.55023438 -19.24911133 15.86023438 -19.58911133 18.24023438 C-5.06911133 18.24023438 9.45088867 18.24023438 24.41088867 18.24023438 C24.11197307 11.59954901 24.11197307 11.59954901 21.30541992 8.8359375 C17.68528986 6.84022478 15.2236764 6.72349544 11.09838867 6.70898438 C10.40704834 6.70515747 9.71570801 6.70133057 9.00341797 6.6973877 C7.54775529 6.69467651 6.09204324 6.70198226 4.63647461 6.71875 C2.41693822 6.74017598 0.20063771 6.71892665 -2.01879883 6.69335938 C-3.43807676 6.6960028 -4.85735268 6.70112809 -6.27661133 6.70898438 C-7.55922852 6.71349609 -8.8418457 6.71800781 -10.16333008 6.72265625 C-14.24225476 7.3389134 -15.87427125 8.1400784 -18.58911133 11.24023438 Z " fill="#1974FF" transform="translate(33.589111328125,39.759765625)"/>
<path d="M0 0 C4.3525815 2.2134923 7.02675779 4.79167963 9.078125 9.3046875 C9.84088671 14.58111131 9.73444722 18.86077861 7.515625 23.7421875 C3.60118069 27.85737255 -0.12616384 30.46772755 -5.921875 30.8046875 C-11.71758616 30.46772755 -15.44493069 27.85737255 -19.359375 23.7421875 C-21.57819722 18.86077861 -21.68463671 14.58111131 -20.921875 9.3046875 C-18.87050779 4.79167963 -16.1963315 2.2134923 -11.84375 0 C-7.76639941 -1.47513904 -4.07735059 -1.47513904 0 0 Z M-13.921875 10.3046875 C-15.07584314 13.30500466 -15.04771333 14.82421387 -14.234375 17.9296875 C-12.72322882 20.66414249 -11.68578936 21.84595492 -8.921875 23.3046875 C-5.10725414 23.87282252 -3.43491208 23.61250975 -0.109375 21.6171875 C2.35349982 19.01357698 2.99140319 17.86028174 3.078125 14.3046875 C2.30174948 11.34034461 1.45595939 9.69601598 -0.671875 7.4921875 C-6.02599766 4.66640054 -9.91623177 6.07015037 -13.921875 10.3046875 Z " fill="#1974FF" transform="translate(41.921875,7.6953125)"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -382,6 +382,9 @@ onUnmounted(() => {
} }
</style> </style>
<style scoped> <style scoped>
.editor {
max-width: 800px;
}
.editor, .editor,
.ql-toolbar { .ql-toolbar {
white-space: pre-wrap !important; white-space: pre-wrap !important;

View File

@@ -1,6 +1,26 @@
<template> <template>
<slot name="default" /> <slot name="default" />
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050"> <el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
<nav class="flex flex-items-center mb-8 justify-between">
<div class="flex flex-items-center">
<div class="flex flex-items-center mr-20px">
<div style="width: 80px; text-align: right; padding-right: 10px">业主账号</div>
<div class="flex-1">
<el-input clearable @clear="handleClear" style="width: 200px" v-model="queryParams.userName" placeholder="请输入业主账号"></el-input>
</div>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 60px; text-align: right; padding-right: 10px">手机号</div>
<div class="flex-1">
<el-input clearable @clear="handleClear" style="width: 200px" v-model="queryParams.userPhone" placeholder="请输入手机号"></el-input>
</div>
</div>
</div>
<div>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</div>
</nav>
<el-table v-loading="loading" ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange"> <el-table v-loading="loading" ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="业主" align="center"> <el-table-column label="业主" align="center">
@@ -64,7 +84,9 @@ const dialog = ref({
const queryParams = ref({ const queryParams = ref({
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10,
userPhone: '',
userName: ''
}); });
const multipleTableRef = ref(); const multipleTableRef = ref();
@@ -101,7 +123,10 @@ const handleUserSelection = () => {
}; };
// ====================== 方法 ====================== // ====================== 方法 ======================
function handleClear() {
queryParams.value.userName = '';
getList();
}
// 获取列表 // 获取列表
function getList() { function getList() {
isFetching.value = true; // 加锁 isFetching.value = true; // 加锁
@@ -164,7 +189,9 @@ function handleSelectionChange(selection: AppUserList[]) {
function resetQuery() { function resetQuery() {
queryParams.value = { queryParams.value = {
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10,
userPhone: '',
userName: ''
}; };
getList(); getList();
} }

View File

@@ -101,10 +101,6 @@ import { BillHouse, listBillHouse } from '@/api/system/SdbBill';
import { ref, nextTick, toRefs } from 'vue'; import { ref, nextTick, toRefs } from 'vue';
import pagination from '@/components/Pagination/index.vue'; import pagination from '@/components/Pagination/index.vue';
// const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
// const { com_build_use } = toRefs<any>(proxy?.useDict('com_build_use'));
const props = defineProps({ const props = defineProps({
returnvalue: { returnvalue: {
type: String, type: String,

View File

@@ -11,7 +11,7 @@
</div> </div>
</div> </div>
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050"> <el-dialog @close="conback" append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
<nav class="flex flex-items-center mb-8"> <nav class="flex flex-items-center mb-8">
<div class="flex flex-items-center mr-5 flex-1"> <div class="flex flex-items-center mr-5 flex-1">
<div style="width: 120px">住户类型</div> <div style="width: 120px">住户类型</div>
@@ -20,7 +20,7 @@
</el-select> </el-select>
</div> </div>
<div class="mr-5 flex-1"> <div class="mr-5 flex-1">
<el-input clearable v-model="queryParams.name" placeholder="请输入住户姓名" /> <el-input maxlength="30" clearable v-model="queryParams.name" placeholder="请输入住户姓名" />
</div> </div>
<div> <div>
<el-button type="primary" @click="getlist">查询</el-button> <el-button type="primary" @click="getlist">查询</el-button>

View File

@@ -40,14 +40,20 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="角色" align="center" prop="roleName" /> <el-table-column label="角色" align="center" prop="roleName" />
<el-table-column label="当前任务数量" align="center" prop="taskCount" v-if="props.userType == 'repair'" />
<el-table-column label="手机号码" align="center" prop="phonenumber" /> <el-table-column label="手机号码" align="center" prop="phonenumber" />
<el-table-column label="状态" align="center" prop="status">
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">{{ row.status === '0' ? '正常' : '停用' }}</el-tag>
</template>
</el-table-column>
</el-table> </el-table>
<template #footer> <template #footer>
<div class="dialog-footer flex flex-items-center flex-justify-between"> <div class="dialog-footer flex flex-items-center flex-justify-between">
<pagination <pagination
style="margin-top: 0" style="margin-top: 0"
layout="total, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
v-show="total > 0" v-show="total > 0"
:total="total" :total="total"
v-model:page="queryParams.pageNum" v-model:page="queryParams.pageNum"
@@ -180,7 +186,10 @@ function choiceResidentFun() {
// 获取列表 // 获取列表
function getList() { function getList() {
loading.value = true; loading.value = true;
getUserByRoleKey(userType.value) getUserByRoleKey({
...queryParams.value,
roleKey: userType.value
})
.then((res) => { .then((res) => {
tableData.value = res.rows; tableData.value = res.rows;
total.value = res.total; total.value = res.total;

View File

@@ -1,9 +1,59 @@
<template> <template>
<slot name="default" /> <slot name="default" />
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050"> <el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
<nav class="flex flex-items-center mb-8 justify-between">
<div class="flex flex-items-center">
<div class="flex flex-items-center">
<div style="width: 50px; text-align: right; padding-right: 10px">楼栋</div>
<div class="flex-1"></div>
<el-select @change="handleChangeBuilding" clearable style="width: 120px" v-model="queryParams.buildingId">
<el-option v-for="(item, index) in buildingList" :key="index" :label="item.buildingName" :value="item.id"></el-option>
</el-select>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 50px; text-align: right; padding-right: 10px">单元</div>
<div class="flex-1">
<el-select @change="handleChangeUnit" clearable style="width: 120px" v-model="queryParams.unitNoId">
<el-option v-for="(item, index) in unitList" :key="index" :label="item.unitNoName" :value="item.unitNoId"></el-option>
</el-select>
</div>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 60px; text-align: right; padding-right: 10px">房屋号</div>
<div class="flex-1">
<el-input clearable @clear="handleClear" style="width: 120px" v-model="queryParams.houseNo" placeholder="请输入房屋号"></el-input>
</div>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 80px; text-align: right; padding-right: 10px">业主名称</div>
<div class="flex-1">
<el-input clearable @clear="handleClear" style="width: 120px" v-model="queryParams.residentName" placeholder="请输入业主名称"></el-input>
</div>
</div>
</div>
<div>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</div>
</nav>
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange"> <el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" width="55" type="index" /> <el-table-column label="序号" align="center" width="55" type="index" />
<el-table-column label="楼栋号" align="center">
<template #default="scope">
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[0] : '---' }}</span>
</template>
</el-table-column>
<el-table-column label="单元" align="center">
<template #default="scope">
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[1] : '---' }}</span>
</template>
</el-table-column>
<el-table-column label="房间" align="center">
<template #default="scope">
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[2] : '---' }}</span>
</template>
</el-table-column>
<el-table-column label="业主" align="center"> <el-table-column label="业主" align="center">
<template #default="scope"> <template #default="scope">
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span> <span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
@@ -15,9 +65,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="手机号" align="center" prop="phone" /> <el-table-column label="手机号" align="center" prop="phone" />
<el-table-column label="房屋" align="center" prop="house_name" />
</el-table> </el-table>
<template #footer> <template #footer>
<div class="dialog-footer flex flex-items-center flex-justify-between"> <div class="dialog-footer flex flex-items-center flex-justify-between">
<pagination <pagination
@@ -27,7 +75,7 @@
:total="total" :total="total"
v-model:page="queryParams.pageNum" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" v-model:limit="queryParams.pageSize"
@pagination="getlist" @pagination="getList"
/> />
<div> <div>
<el-button @click="conback">退出</el-button> <el-button @click="conback">退出</el-button>
@@ -77,7 +125,12 @@ const dialog = ref({
const queryParams = ref({ const queryParams = ref({
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10,
buildingId: null,
residentName: null,
houseNo: null,
unitNoId: null
}); });
const multipleTableRef = ref(); const multipleTableRef = ref();
@@ -116,7 +169,7 @@ const handleUserSelection = () => {
// ====================== 方法 ====================== // ====================== 方法 ======================
// 获取列表 // 获取列表
function getlist() { function getList() {
isFetching.value = true; // 加锁 isFetching.value = true; // 加锁
loading.value = true; loading.value = true;
queryResidentList_holder(queryParams.value) queryResidentList_holder(queryParams.value)
@@ -135,23 +188,33 @@ function getlist() {
} }
/** 楼栋列表 */ /** 楼栋列表 */
const buildinglist = ref([]); const buildingList = ref([]);
/** 房屋列表 */ /** 单元列表 */
const unitlist = ref([]); const unitList = ref([]);
/** 获取楼栋 列表 */
/** 筛选房屋类型 */ function handleChangeHouse() {
function handleChangeHouse(val: string) {
getBuildinglistAPI().then((res) => { getBuildinglistAPI().then((res) => {
buildinglist.value = res.data; buildingList.value = res.data;
}); });
} }
function handleClear() {
getList();
}
/** 单元列表 */ /** 单元列表 */
function handleChangebuilding(val: string) { function handleChangeBuilding(val: string) {
getHouselistAPI(val).then((res) => { queryParams.value.unitNoId = null;
unitlist.value = res.data.units; unitList.value = [];
}); if (queryParams.value.buildingId) {
getHouselistAPI(val).then((res) => {
unitList.value = res.data.units;
getList();
});
}
getList();
}
function handleChangeUnit() {
getList();
} }
// ============================================== // ==============================================
// ✅ 新增:处理 selection-change多选专用 // ✅ 新增:处理 selection-change多选专用
// ============================================== // ==============================================
@@ -183,39 +246,17 @@ function handleSelectionChange(selection: BillUserlist[]) {
} }
} }
} }
// ==============================================
// 最佳单选方案:点击行选中,无报错、无循环、最稳定
// ==============================================
// 优化 handleRowClick避免重复
function handleRowClick(row: BillUserlist) {
if (!multipleTableRef.value) return;
if (isMultiple.value) {
const index = multipleSelection.value.findIndex((item) => item.residentId === row.residentId);
if (index > -1) {
// 取消选中
multipleSelection.value.splice(index, 1);
multipleTableRef.value?.toggleRowSelection(row, false);
} else {
// 选中
multipleSelection.value.push(row);
multipleTableRef.value?.toggleRowSelection(row, true);
}
} else {
// 【单选模式】先清空,再选中当前行
multipleSelection.value = [];
multipleTableRef.value.clearSelection();
multipleSelection.value = [row];
multipleTableRef.value.toggleRowSelection(row, true);
}
}
// 重置查询 // 重置查询
function resetQuery() { function resetQuery() {
queryParams.value = { queryParams.value = {
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10,
buildingId: null,
unitNoId: null,
residentName: null,
houseNo: null
}; };
getlist(); getList();
} }
// 退出 // 退出
@@ -270,7 +311,8 @@ defineExpose({
multipleSelection.value = []; multipleSelection.value = [];
} }
getlist(); getList();
handleChangeHouse();
dialog.value.dialogVisible = true; dialog.value.dialogVisible = true;
} }
}); });

View File

@@ -1,359 +0,0 @@
<template>
<div class="license-plate-input">
<div class="plate_line">
<div
v-for="(item, index) in chars"
:key="index"
class="plate-item"
:class="{
active: activeIndex === index,
disabled: disabled,
error: hasError
}"
>
<input
ref="inputRefs"
v-model="chars[index]"
type="text"
maxlength="1"
:disabled="disabled"
@input="onInput(index)"
@keydown="onKeydown($event, index)"
@paste="onPaste"
@focus="activeIndex = index"
@blur="onBlur"
@compositionend="onCompositionEnd(index)"
/>
</div>
</div>
<!-- 错误提示 -->
<transition name="el-fade-in-linear">
<div v-if="hasError && errorMessage" class="plate-error">
{{ errorMessage }}
</div>
</transition>
</div>
</template>
<script setup lang="ts">
import { ref, watch, nextTick } from 'vue';
import { LicensePlateValidator } from '@/utils/Reg';
// 省份简称
const PROVINCES = [
'京',
'津',
'沪',
'渝',
'冀',
'豫',
'云',
'辽',
'黑',
'湘',
'皖',
'鲁',
'新',
'苏',
'浙',
'赣',
'鄂',
'桂',
'甘',
'晋',
'蒙',
'陕',
'吉',
'闽',
'贵',
'粤',
'青',
'藏',
'川',
'宁',
'琼'
];
// 合法基础字符:字母 (排除I,O) 和 数字
const VALID_CHAR_REGEX = /^[A-HJ-NP-Z0-9]$/i;
// 车牌特殊结尾字符
const SPECIAL_CHARS = ['警', '学', '挂', '临', '超', '港', '澳'];
const props = defineProps<{
modelValue: string;
disabled?: boolean;
required?: boolean;
}>();
const emit = defineEmits<{
'update:modelValue': [value: string];
'change': [value: string];
}>();
const inputRefs = ref<HTMLInputElement[]>([]);
const activeIndex = ref(-1);
const chars = ref<string[]>(Array(8).fill(''));
const hasError = ref(false);
const errorMessage = ref('');
// 外部值同步到内部
watch(
() => props.modelValue,
(val) => {
const cleanVal = (val || '').toUpperCase().trim();
const currentJoined = chars.value.join('').trim();
if (cleanVal !== currentJoined) {
const newChars = Array(8).fill('');
if (cleanVal) {
const arr = cleanVal.split('');
for (let i = 0; i < Math.min(arr.length, 8); i++) {
newChars[i] = arr[i];
}
}
chars.value = newChars;
if (cleanVal) clearError();
}
},
{ immediate: true }
);
// 内部值同步到外部
watch(
chars,
(newChars) => {
const value = newChars.join('').trim();
emit('update:modelValue', value);
emit('change', value);
if (hasError.value) {
clearError();
}
},
{ deep: true }
);
function onInput(index: number) {
let char = chars.value[index];
if (!char) return;
// 统一转大写 (汉字不受影响)
char = char.toUpperCase();
let isValid = false;
// 1. 第一位:必须是省份
if (index === 0) {
if (PROVINCES.includes(char)) {
isValid = true;
}
}
// 2. 特殊字符处理 (警/学/挂/临/超/港/澳)
else if (SPECIAL_CHARS.includes(char)) {
// 特殊字符通常出现在最后一位,或者倒数第二位(如临时车牌的"临"可能在最后,也可能在倒数第二?不,通常是最后)
// 为了用户体验,允许在任何非第一位的位置输入,但最终校验会判断位置是否正确
isValid = true;
}
// 3. 常规字符:字母或数字
else {
if (VALID_CHAR_REGEX.test(char)) {
isValid = true;
}
}
if (!isValid) {
chars.value[index] = '';
return;
} else {
chars.value[index] = char;
// 如果输入的是特殊字符,通常意味着车牌结束,不再自动跳转
// 如果输入的是常规字符,且不是最后一格,则跳转
if (!SPECIAL_CHARS.includes(char) && char && index < 7) {
nextTick(() => {
inputRefs.value[index + 1]?.focus();
});
}
}
}
function onCompositionEnd(index: number) {
onInput(index);
}
function onKeydown(e: KeyboardEvent, index: number) {
if (e.key === 'Backspace') {
if (!chars.value[index] && index > 0) {
e.preventDefault();
nextTick(() => {
inputRefs.value[index - 1]?.focus();
});
}
return;
}
if (e.key === 'ArrowLeft' && index > 0) {
e.preventDefault();
inputRefs.value[index - 1]?.focus();
}
if (e.key === 'ArrowRight' && index < 7) {
e.preventDefault();
inputRefs.value[index + 1]?.focus();
}
}
function onPaste(e: ClipboardEvent) {
e.preventDefault();
const text = e.clipboardData?.getData('text')?.toUpperCase().trim() || '';
if (!text) return;
const filledChars = [...chars.value];
let insertPos = activeIndex.value >= 0 ? activeIndex.value : 0;
for (let i = 0; i < text.length; i++) {
if (insertPos >= 8) break;
const char = text[i];
let canInsert = false;
if (insertPos === 0) {
if (PROVINCES.includes(char)) canInsert = true;
} else if (SPECIAL_CHARS.includes(char)) {
canInsert = true;
} else {
if (VALID_CHAR_REGEX.test(char)) canInsert = true;
}
if (canInsert) {
filledChars[insertPos] = char;
insertPos++;
}
}
chars.value = filledChars;
nextTick(() => {
const focusIdx = Math.min(insertPos, 7);
inputRefs.value[focusIdx]?.focus();
});
}
function onBlur() {
setTimeout(() => {
const hasFocus = inputRefs.value.some((input) => document.activeElement === input);
if (!hasFocus) {
activeIndex.value = -1;
validate();
}
}, 200);
}
function validate(): { valid: boolean; message?: string } {
const value = chars.value.join('').trim();
if (props.required && !value) {
setError('请输入车牌号');
return { valid: false, message: '请输入车牌号' };
}
if (!value) {
clearError();
return { valid: true };
}
if (!LicensePlateValidator.isValidPlate(value)) {
setError('车牌号格式不正确');
return { valid: false, message: '车牌号格式不正确' };
}
clearError();
return { valid: true };
}
function setError(msg: string) {
hasError.value = true;
errorMessage.value = msg;
}
function clearError() {
hasError.value = false;
errorMessage.value = '';
}
defineExpose({
focus: () => nextTick(() => inputRefs.value[0]?.focus()),
clear: () => {
chars.value = Array(8).fill('');
clearError();
emit('update:modelValue', '');
emit('change', '');
},
validate,
clearError
});
</script>
<style scoped>
.license-plate-input {
display: flex;
flex-direction: column;
gap: 4px;
width: fit-content;
}
.plate_line {
display: flex;
align-items: center;
gap: 6px;
}
.plate-item {
width: 32px;
height: 32px;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
background-color: #fff;
}
.plate-item.active {
border-color: #409eff;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
.plate-item.error {
border-color: #f56c6c;
}
.plate-item.disabled {
background-color: #f5f7fa;
cursor: not-allowed;
color: #a8abb2;
}
.plate-item input {
width: 100%;
height: 100%;
border: none;
text-align: center;
font-size: 16px;
font-weight: 500;
background: transparent;
outline: none;
padding: 0;
margin: 0;
color: inherit;
}
.plate-error {
color: #f56c6c;
font-size: 12px;
line-height: 1.5;
margin-top: 2px;
min-height: 18px;
}
</style>

View File

@@ -52,7 +52,7 @@ import { CSSProperties } from 'vue';
const props = defineProps({ const props = defineProps({
columns: propTypes.fieldOption, columns: propTypes.fieldOption,
gutter: propTypes.number.def(10), gutter: propTypes.number.def(10),
moreTitle: propTypes.string.def('批量操作'), moreTitle: propTypes.string.def('更多操作'),
showAdd: propTypes.bool.def(true), showAdd: propTypes.bool.def(true),
showDelete: propTypes.bool.def(true), showDelete: propTypes.bool.def(true),

View File

@@ -79,7 +79,7 @@ defineProps<{
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 12px; font-size: 11px;
font-weight: 800; font-weight: 800;
flex-shrink: 0; flex-shrink: 0;
z-index: 1; z-index: 1;

View File

@@ -183,11 +183,32 @@ export const useHouseStore = defineStore(
// 清空 楼层信息 // 清空 楼层信息
floorslist.value.clear(); floorslist.value.clear();
// 重新获取楼层信息 // 重新获取楼层信息
currentHouseInfoList.value.units.forEach((item) => { const units = currentHouseInfoList.value.units.toSorted((a, b) => {
const aVal = a.unitNoName;
const bVal = b.unitNoName;
// 判断是否为纯数字
const aIsNumber = /^-?\d+$/.test(aVal);
const bIsNumber = /^-?\d+$/.test(bVal);
if (aIsNumber && bIsNumber) {
// 都是数字,按数值排序
return Number(aVal) - Number(bVal);
} else if (aIsNumber) {
// a是数字优先排前面
return -1;
} else if (bIsNumber) {
// b是数字优先排前面
return 1;
} else {
// 都是文字,按中文字典序排序
return aVal.localeCompare(bVal, 'zh-CN');
}
});
units.forEach((item) => {
item.floors.forEach((floor) => { item.floors.forEach((floor) => {
floorslist.value.add(floor.floorNo); floorslist.value.add(floor.floorNo);
}); });
}); });
console.log(units);
return; return;
}); });
}; };

View File

@@ -51,7 +51,11 @@ const reg = {
/** QQ */ /** QQ */
qq: /^[1-9]\d{4,11}$/, qq: /^[1-9]\d{4,11}$/,
/** 微信 */ /** 微信 */
wechat: /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/ wechat: /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/,
/** 护照 */
passport: /^[EG]\d{8}$/,
/** 港澳通行证 */
hongkongPassport: /^[CHMW]\d{8}$/
}; };
// 自动推导 TS 类型(最标准) // 自动推导 TS 类型(最标准)
export type RegType = keyof typeof reg; export type RegType = keyof typeof reg;

699
src/utils/Reg2.ts Normal file
View File

@@ -0,0 +1,699 @@
/**
* 中国车牌号校验工具
*
* 支持的车牌类型:
* 1. 普通蓝牌/黄牌7位— 小型汽车 / 大型汽车 / 摩托车
* 2. 新能源小车8位— 纯电动(D) / 非纯电动(F)
* 3. 新能源大车8位— 纯电动(D) / 非纯电动(F)
* 4. 警车牌7位
* 5. 教练车牌7位
* 6. 挂车牌7位
* 7. 港澳入出境车牌7位
* 8. 临时行驶车牌8位
* 9. 使馆车牌
* 10. 领事馆车牌7位
* 11. 武警车牌
* 12. 试车牌7位
*
* 合理性校验规则:
* - 字母数字混合段至少包含 1 位数字拒绝纯字母组合如京AAAAAA
* - 字母排除 I、O避免与数字 1、0 混淆)
*/
// ===================== 常量 =====================
/** 省份简称31个 */
export const PROVINCES = [
'京',
'津',
'沪',
'渝',
'冀',
'豫',
'云',
'辽',
'黑',
'湘',
'皖',
'鲁',
'新',
'苏',
'浙',
'赣',
'鄂',
'桂',
'甘',
'晋',
'蒙',
'陕',
'吉',
'闽',
'贵',
'粤',
'青',
'藏',
'川',
'宁',
'琼'
] as const;
/** 省份正则字符集 */
const PROVINCE_CHARS = `[${PROVINCES.join('')}]`;
/** 合法字母数字(排除 I、O */
const ALPHANUM = `[A-HJ-NP-Z0-9]`;
/** 纯数字 */
const DIGIT = `[0-9]`;
/** 字母(排除 I、O */
const LETTER = `[A-HJ-NP-Z]`;
/** 车牌类型枚举 */
export enum PlateType {
/** 普通蓝牌/黄牌7位 */
STANDARD = 'standard',
/** 新能源小车8位 */
NEW_ENERGY_SMALL = 'newEnergySmall',
/** 新能源大车8位 */
NEW_ENERGY_LARGE = 'newEnergyLarge',
/** 警车7位 */
POLICE = 'police',
/** 教练车7位 */
COACH = 'coach',
/** 挂车7位 */
TRAILER = 'trailer',
/** 港澳入出境车7位 */
HK_MACAU = 'hkMacau',
/** 临时车牌8位 */
TEMPORARY = 'temporary',
/** 使馆车 */
EMBASSY = 'embassy',
/** 领事馆车7位 */
CONSULATE = 'consulate',
/** 武警车 */
ARMED_POLICE = 'armedPolice',
/** 试车牌7位 */
TEST = 'test'
}
/** 车牌类型中文标签 */
export const PLATE_TYPE_LABELS: Record<string, string> = {
[PlateType.STANDARD]: '普通车牌',
[PlateType.NEW_ENERGY_SMALL]: '新能源小型车',
[PlateType.NEW_ENERGY_LARGE]: '新能源大型车',
[PlateType.POLICE]: '警车',
[PlateType.COACH]: '教练车',
[PlateType.TRAILER]: '挂车',
[PlateType.HK_MACAU]: '港澳入出境车',
[PlateType.TEMPORARY]: '临时车牌',
[PlateType.EMBASSY]: '使馆车',
[PlateType.CONSULATE]: '领事馆车',
[PlateType.ARMED_POLICE]: '武警车',
[PlateType.TEST]: '试车牌'
};
/** 车牌类型颜色(用于 UI 标识) */
export const PLATE_TYPE_COLORS: Record<string, string> = {
[PlateType.STANDARD]: '#409eff', // 蓝色
[PlateType.NEW_ENERGY_SMALL]: '#67c23a', // 绿色
[PlateType.NEW_ENERGY_LARGE]: '#67c23a', // 绿色
[PlateType.POLICE]: '#f56c6c', // 红色
[PlateType.COACH]: '#e6a23c', // 黄色
[PlateType.TRAILER]: '#e6a23c', // 黄色
[PlateType.HK_MACAU]: '#909399', // 灰色
[PlateType.TEMPORARY]: '#9b59b6', // 紫色
[PlateType.EMBASSY]: '#909399', // 灰色
[PlateType.CONSULATE]: '#909399', // 灰色
[PlateType.ARMED_POLICE]: '#f56c6c', // 红色
[PlateType.TEST]: '#909399' // 灰色
};
/** 特殊结尾字符 */
export const SPECIAL_CHARS = ['警', '学', '挂', '临', '港', '澳', '领', '试'] as const;
/** 首位可输入字符集说明 */
export const POSITION_RULES: { position: number; description: string }[] = [
{ position: 0, description: '省份简称京、津、沪、渝等31个' },
{ position: 1, description: '发牌机关代号字母A-Z排除I、O' },
{ position: 2, description: '字母或数字新能源小车此位为D纯电/F非纯电' },
{ position: 3, description: '字母或数字' },
{ position: 4, description: '字母或数字' },
{ position: 5, description: '字母或数字' },
{ position: 6, description: '字母或数字,或特殊字符(警/学/挂/港/澳/领/试)' },
{ position: 7, description: '字母或数字,或特殊字符(临)/新能源标识D/F' }
];
// ===================== 正则表达式 =====================
/**
* 各类车牌正则表达式
*
* 基础格式说明:
* - 省份: 1位31个省份简称
* - 字母: 发牌机关代号排除I、O避免与数字1、0混淆
* - 中间位: 字母或数字组合
* - 特殊结尾: 警/学/挂/港/澳/领/临/试
* - 新能源标识: D纯电/ F非纯电/插混/燃料电池)
*/
const PATTERNS: Record<PlateType, RegExp> = {
/**
* 普通蓝牌/黄牌7位
* 格式: 省 + 字母 + 5位字母数字
* 示例: 京A12345, 京A123AB, 京AB1234
* 适用: 小型汽车(蓝牌)、大型汽车(黄牌)、普通摩托车(黄牌)、轻便摩托车(蓝牌)
*/
[PlateType.STANDARD]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${ALPHANUM}{5}$`),
/**
* 新能源小型车8位
* 格式: 省 + 字母 + D/F + 5位字母数字
* 示例: 京AD12345, 沪AF12345
* 说明: D=纯电动, F=非纯电动(插电混动/增程式/燃料电池)
*/
[PlateType.NEW_ENERGY_SMALL]: new RegExp(`^${PROVINCE_CHARS}${LETTER}[DF]${ALPHANUM}{5}$`),
/**
* 新能源大型车8位
* 格式: 省 + 字母 + 5位字母数字 + D/F
* 示例: 京A12345D, 沪A12345F
*/
[PlateType.NEW_ENERGY_LARGE]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${ALPHANUM}{5}[DF]$`),
/**
* 警车牌7位
* 格式: 省 + 字母 + 4位数字 + 警
* 示例: 京A1234警, 粤B5678警
*/
[PlateType.POLICE]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${DIGIT}{4}警$`),
/**
* 教练车牌7位
* 格式: 省 + 字母 + 4位字母数字 + 学
* 示例: 京A1234学, 粤B123A学
*/
[PlateType.COACH]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${ALPHANUM}{4}学$`),
/**
* 挂车牌7位
* 格式: 省 + 字母 + 4位字母数字 + 挂
* 示例: 京A1234挂, 鲁B5678挂
*/
[PlateType.TRAILER]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${ALPHANUM}{4}挂$`),
/**
* 港澳入出境车牌7位
* 格式: 省 + Z + 4位数字 + 港/澳
* 示例: 粤Z1234港, 粤Z5678澳
* 说明: 第二位固定为Z黑底白字
*/
[PlateType.HK_MACAU]: new RegExp(`^${PROVINCE_CHARS}Z${DIGIT}{4}[港澳]$`),
/**
* 临时行驶车牌8位
* 格式: 省 + 字母 + 5位字母数字 + 临
* 示例: 京A12345临, 沪B67890临
*/
[PlateType.TEMPORARY]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${ALPHANUM}{5}临$`),
/**
* 使馆车牌
* 格式: 使 + 3~5位数字
* 示例: 使123, 使12345
* 说明: 黑底白字,不以省份开头
*/
[PlateType.EMBASSY]: /^使[0-9]{3,5}$/,
/**
* 领事馆车牌7位
* 格式: 省 + 字母 + 4位数字 + 领
* 示例: 京A1234领, 沪B5678领
*/
[PlateType.CONSULATE]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${DIGIT}{4}领$`),
/**
* 武警车牌
* 格式1: WJ + 省 + 4位数字 + 字母 (例: WJ京1234X)
* 格式2: WJ + 5位数字 + 字母 (例: WJ12345X)
* 格式3: WJ + 省 + 5位数字 (例: WJ京12345)
* 说明: 白底红字"WJ"
*/
[PlateType.ARMED_POLICE]: /^WJ(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼])?[0-9]{4,5}[A-Z]?$/,
/**
* 试车牌7位
* 格式: 省 + 字母 + 试 + 4位字母数字
* 示例: 京A试1234, 沪B试5678
*/
[PlateType.TEST]: new RegExp(`^${PROVINCE_CHARS}${LETTER}${ALPHANUM}{4}$`)
};
// ===================== 合理性校验 =====================
/**
* 字母数字混合段至少包含 N 位数字的规则。
*
* 车牌序号(字母数字混合)不能全为字母——
* 现实中不存在 京AAAAAA / 京ADAAAAA / 京A试AAAA 这类车牌。
*/
interface DigitRequirement {
/** 需要统计数字的起始索引(含) */
start: number;
/** 需要统计数字的结束索引(含) */
end: number;
/** 区间内最少数字个数 */
minDigits: number;
}
/** 各类型字母数字段的数字最低要求 */
const DIGIT_REQUIREMENT: Partial<Record<PlateType, DigitRequirement>> = {
[PlateType.STANDARD]: { start: 2, end: 6, minDigits: 1 },
[PlateType.NEW_ENERGY_SMALL]: { start: 3, end: 7, minDigits: 1 },
[PlateType.NEW_ENERGY_LARGE]: { start: 2, end: 6, minDigits: 1 },
[PlateType.COACH]: { start: 2, end: 5, minDigits: 1 },
[PlateType.TRAILER]: { start: 2, end: 5, minDigits: 1 },
[PlateType.TEMPORARY]: { start: 2, end: 6, minDigits: 1 },
[PlateType.TEST]: { start: 3, end: 6, minDigits: 1 }
};
// ===================== 校验类 =====================
export interface ValidationResult {
valid: boolean;
type?: PlateType;
label?: string;
color?: string;
message?: string;
}
export class LicensePlateValidator2 {
/** 省份列表 */
static readonly PROVINCES = PROVINCES;
/** 特殊字符列表 */
static readonly SPECIAL_CHARS = SPECIAL_CHARS;
/** 所有正则 */
static readonly PATTERNS = PATTERNS;
// ---- 公开方法 ----
/**
* 校验车牌号是否合法(格式 + 合理性)
* @param value 车牌号字符串
* @returns 是否合法
*/
static isValidPlate(value: string): boolean {
const val = (value || '').toUpperCase().trim();
if (!val) return false;
// 统一走 getPlateType确保格式校验和合理性校验一致
return this.getPlateType(val) !== null;
}
/**
* 获取车牌类型(含格式校验 + 合理性校验)
* @param value 车牌号字符串
* @returns 车牌类型枚举,未匹配返回 null
*/
static getPlateType(value: string): PlateType | null {
const val = (value || '').toUpperCase().trim();
if (!val) return null;
// 使馆车(不以省份开头,先匹配再校验数字段不需要额外检查)
if (val.startsWith('使') && PATTERNS[PlateType.EMBASSY].test(val)) {
return PlateType.EMBASSY;
}
// 武警车以WJ开头
if (val.startsWith('WJ') && PATTERNS[PlateType.ARMED_POLICE].test(val)) {
return PlateType.ARMED_POLICE;
}
// 以省份开头的车牌
if (PROVINCES.includes(val[0] as any)) {
// 按优先级逐条匹配(特殊结尾 > 新能源 > 普通)
if (val.endsWith('警') && PATTERNS[PlateType.POLICE].test(val)) {
return PlateType.POLICE;
}
if (val.endsWith('学')) {
if (PATTERNS[PlateType.COACH].test(val) && this._checkDigits(val, PlateType.COACH)) {
return PlateType.COACH;
}
return null;
}
if (val.endsWith('挂')) {
if (PATTERNS[PlateType.TRAILER].test(val) && this._checkDigits(val, PlateType.TRAILER)) {
return PlateType.TRAILER;
}
return null;
}
if (val.endsWith('港') || val.endsWith('澳')) {
if (PATTERNS[PlateType.HK_MACAU].test(val)) {
return PlateType.HK_MACAU;
}
return null;
}
if (val.endsWith('领') && PATTERNS[PlateType.CONSULATE].test(val)) {
return PlateType.CONSULATE;
}
if (val.endsWith('临')) {
if (PATTERNS[PlateType.TEMPORARY].test(val) && this._checkDigits(val, PlateType.TEMPORARY)) {
return PlateType.TEMPORARY;
}
return null;
}
if (val.includes('试')) {
if (PATTERNS[PlateType.TEST].test(val) && this._checkDigits(val, PlateType.TEST)) {
return PlateType.TEST;
}
return null;
}
// 8位新能源
if (val.length === 8) {
// 新能源小车: 第3位是D或F
if (/^[DF]$/.test(val[2]) && PATTERNS[PlateType.NEW_ENERGY_SMALL].test(val) && this._checkDigits(val, PlateType.NEW_ENERGY_SMALL)) {
return PlateType.NEW_ENERGY_SMALL;
}
// 新能源大车: 最后一位是D或F
if (/^[DF]$/.test(val[7]) && PATTERNS[PlateType.NEW_ENERGY_LARGE].test(val) && this._checkDigits(val, PlateType.NEW_ENERGY_LARGE)) {
return PlateType.NEW_ENERGY_LARGE;
}
}
// 普通蓝牌/黄牌7位
if (val.length === 7 && PATTERNS[PlateType.STANDARD].test(val) && this._checkDigits(val, PlateType.STANDARD)) {
return PlateType.STANDARD;
}
}
return null;
}
/**
* 完整校验(返回类型和描述)
* @param value 车牌号字符串
* @returns 校验结果对象
*/
static validate(value: string): ValidationResult {
const val = (value || '').toUpperCase().trim();
if (!val) {
return { valid: false, message: '请输入车牌号' };
}
// 格式预检(提供更精准的错误信息)
const formatError = this._formatCheck(val);
if (formatError) {
return formatError;
}
// 合法性校验
const type = this.getPlateType(val);
if (!type) {
return { valid: false, message: '请输入正确的车牌号' };
}
return {
valid: true,
type,
label: PLATE_TYPE_LABELS[type],
color: PLATE_TYPE_COLORS[type]
};
}
/**
* 获取车牌类型描述信息
* @param value 车牌号字符串
* @returns 描述字符串
*/
static getPlateInfo(value: string): string {
const result = this.validate(value);
if (result.valid && result.label) {
return result.label;
}
return result.message || '未知格式';
}
/**
* 获取所有支持的车牌类型及其格式说明
*/
static getAllPlateTypes(): { type: PlateType; label: string; format: string; example: string; color: string; length: number }[] {
return [
{
type: PlateType.STANDARD,
label: '普通蓝牌/黄牌',
format: '省+字母+5位字母数字',
example: '京A12345',
color: PLATE_TYPE_COLORS[PlateType.STANDARD],
length: 7
},
{
type: PlateType.NEW_ENERGY_SMALL,
label: '新能源小型车纯电D/非纯电F',
format: '省+字母+D/F+5位字母数字',
example: '京AD12345',
color: PLATE_TYPE_COLORS[PlateType.NEW_ENERGY_SMALL],
length: 8
},
{
type: PlateType.NEW_ENERGY_LARGE,
label: '新能源大型车纯电D/非纯电F',
format: '省+字母+5位字母数字+D/F',
example: '京A12345D',
color: PLATE_TYPE_COLORS[PlateType.NEW_ENERGY_LARGE],
length: 8
},
{
type: PlateType.POLICE,
label: '警车',
format: '省+字母+4位数字+警',
example: '京A1234警',
color: PLATE_TYPE_COLORS[PlateType.POLICE],
length: 7
},
{
type: PlateType.COACH,
label: '教练车',
format: '省+字母+4位字母数字+学',
example: '京A1234学',
color: PLATE_TYPE_COLORS[PlateType.COACH],
length: 7
},
{
type: PlateType.TRAILER,
label: '挂车',
format: '省+字母+4位字母数字+挂',
example: '京A1234挂',
color: PLATE_TYPE_COLORS[PlateType.TRAILER],
length: 7
},
{
type: PlateType.HK_MACAU,
label: '港澳入出境车',
format: '省+Z+4位数字+港/澳',
example: '粤Z1234港',
color: PLATE_TYPE_COLORS[PlateType.HK_MACAU],
length: 7
},
{
type: PlateType.TEMPORARY,
label: '临时车牌',
format: '省+字母+5位字母数字+临',
example: '京A12345临',
color: PLATE_TYPE_COLORS[PlateType.TEMPORARY],
length: 8
},
{
type: PlateType.CONSULATE,
label: '领事馆车',
format: '省+字母+4位数字+领',
example: '京A1234领',
color: PLATE_TYPE_COLORS[PlateType.CONSULATE],
length: 7
},
{
type: PlateType.TEST,
label: '试车牌',
format: '省+字母+试+4位字母数字',
example: '京A试1234',
color: PLATE_TYPE_COLORS[PlateType.TEST],
length: 7
},
{
type: PlateType.EMBASSY,
label: '使馆车',
format: '使+3~5位数字',
example: '使12345',
color: PLATE_TYPE_COLORS[PlateType.EMBASSY],
length: 0
},
{
type: PlateType.ARMED_POLICE,
label: '武警车',
format: 'WJ+省(可选)+4~5位数字+字母(可选)',
example: 'WJ京1234X',
color: PLATE_TYPE_COLORS[PlateType.ARMED_POLICE],
length: 0
}
];
}
/**
* 校验指定位置的字符是否合法(逐字输入场景,如多格拆分输入框)
* @param char 待校验字符
* @param index 位置索引0-7
* @param currentChars 当前所有字符(用于上下文判断)
* @returns 是否合法
*/
static isValidCharAtPosition(char: string, index: number, currentChars: string[] = []): boolean {
if (!char) return true;
const c = char.toUpperCase();
const joined = currentChars.join('').toUpperCase().trim();
// 使馆车(以"使"开头):后续只能输入数字
if (index === 0 && c === '使') return true;
if (joined.startsWith('使')) {
return /[0-9]/.test(c);
}
// 武警车WJ 前缀):前两位必须依次是 W、J
if (index === 0 && c === 'W') return true;
if (index === 1 && joined[0] === 'W' && c === 'J') return true;
if (joined.startsWith('WJ')) {
// WJ 后可以是 [省份] 或 [数字]
if (index === 2 && PROVINCES.includes(c as any)) return true;
// 数字段
if (index >= 2 && /[0-9]/.test(c)) return true;
// 末尾可选字母
if (index >= 6 && index <= 7 && /[A-Z]/.test(c)) return true;
return false;
}
// 位置 0必须是省份W 已被 WJ 分支处理,不会到此处)
if (index === 0) {
return PROVINCES.includes(c as any);
}
// 位置 1必须是字母排除 I、O
if (index === 1) {
return /^[A-HJ-NP-Z]$/i.test(c);
}
// 位置 2-5字母或数字
if (index >= 2 && index <= 5) {
return /^[A-HJ-NP-Z0-9]$/i.test(c);
}
// 位置 6字母数字 或 特殊结尾(警/学/挂/港/澳/领/试),排除"临"
if (index === 6) {
if (SPECIAL_CHARS.includes(c as any)) {
if (c === '临') return false;
return true;
}
return /^[A-HJ-NP-Z0-9]$/i.test(c);
}
// 位置 7字母数字 或 D/F新能源大车或 临(临时车牌)
if (index === 7) {
if (c === '临') return true;
return /^[A-HJ-NP-Z0-9]$/i.test(c);
}
return false;
}
/**
* 根据当前已输入内容推测车牌长度7或8位
* @param currentChars 当前已输入字符数组
* @returns 推测的车牌长度
*/
static guessPlateLength(currentChars: string[]): 7 | 8 {
const joined = currentChars.join('').toUpperCase().trim();
// 已有确定长度的特殊结尾
if (['警', '学', '挂', '领', '港', '澳'].some((s) => joined.endsWith(s))) return 7;
if (joined.endsWith('临')) return 8;
if (joined.includes('试')) return 7;
// 第3位是D或F → 新能源小车8位
if (joined.length >= 3 && /^[DF]$/.test(joined[2])) return 8;
// 默认7位
if (joined.length <= 7) return 7;
// 已满8位检查最后一位是否为D/F
if (joined.length === 8 && /^[DF]$/.test(joined[7])) return 8;
return 8;
}
// ---- 内部方法 ----
/**
* 合理性校验:字母数字混合段至少包含 minDigits 位数字
* 用于拒绝京AAAAAA / 京ADAAAAA / 京A试AAAA 等纯字母组合
*/
private static _checkDigits(val: string, type: PlateType): boolean {
const req = DIGIT_REQUIREMENT[type];
if (!req) return true; // 无数字要求则通过
let count = 0;
const end = Math.min(req.end, val.length - 1);
for (let i = req.start; i <= end; i++) {
if (/[0-9]/.test(val[i])) count++;
}
return count >= req.minDigits;
}
/**
* 格式预检:在 getPlateType 之前做轻量格式判断,给出更友好的错误提示
*/
private static _formatCheck(val: string): ValidationResult | null {
// 首位检查(使馆和武警由 getPlateType 处理)
if (!PROVINCES.includes(val[0] as any) && !val.startsWith('使') && !val.startsWith('WJ')) {
return { valid: false, message: '请输入正确的车牌号' };
}
// 长度检查
if (val.startsWith('使')) {
if (val.length < 4) {
return { valid: false, message: '请输入正确的车牌号' };
}
if (val.length > 6) {
return { valid: false, message: '请输入正确的车牌号' };
}
return null;
}
if (val.startsWith('WJ')) {
if (val.length < 6) {
return { valid: false, message: '请输入正确的车牌号' };
}
if (val.length > 9) {
return { valid: false, message: '请输入正确的车牌号' };
}
return null;
}
// 省份开头的车牌
if (val.length < 7) {
return { valid: false, message: '请输入正确的车牌号' };
}
if (val.length > 8) {
return { valid: false, message: '请输入正确的车牌号' };
}
// 第二位检查(排除 I、O
if (val.length >= 2 && /[IO]/.test(val[1])) {
return { valid: false, message: '请输入正确的车牌号' };
}
return null;
}
}
export default LicensePlateValidator2;

View File

@@ -134,8 +134,8 @@ export function add(a: string | number, b: string | number): number {
/** /**
* 乘法 a * b * 乘法 a * b
*/ */
export function mul(a: string | number, b: string | number): number { export function mul(a: string | number, b: string | number, decimal = 2): number {
return Number(toBig(a).times(toBig(b))); return Number(toBig(a).times(toBig(b)).round(decimal));
} }
/** /**
@@ -147,6 +147,50 @@ export function div(a: string | number, b: string | number): number {
if (bigB.eq(0)) throw new Error('除数不能为0'); if (bigB.eq(0)) throw new Error('除数不能为0');
return Number(toBig(a).div(bigB)); return Number(toBig(a).div(bigB));
} }
/**
* a > b
*/
export function gtMoney(a: string | number, b: string | number): boolean {
return toBig(a).gt(toBig(b));
}
/**
* a >= b
*/
export function gteMoney(a: string | number, b: string | number): boolean {
return toBig(a).gte(toBig(b));
}
/**
* a < b
*/
export function ltMoney(a: string | number, b: string | number): boolean {
return toBig(a).lt(toBig(b));
}
/**
* a <= b
*/
export function lteMoney(a: string | number, b: string | number): boolean {
return toBig(a).lte(toBig(b));
}
/**
* a === b 金额相等
*/
export function eqMoney(a: string | number, b: string | number): boolean {
return toBig(a).eq(toBig(b));
}
/**
* a !== b 金额不相等
*/
export function neqMoney(a: string | number, b: string | number): boolean {
return !toBig(a).eq(toBig(b));
}
// 保留2位小数金额专用 // 保留2位小数金额专用
export function toFixed2(val) { export function toFixed2(val) {
return Number(val).toFixed(2); return Number(val).toFixed(2);

View File

@@ -78,7 +78,7 @@ service.interceptors.request.use(
const villageid = localStorage.getItem('villageid'); const villageid = localStorage.getItem('villageid');
config.headers['Content-Language'] = getLanguage(); config.headers['Content-Language'] = getLanguage();
config.headers['villageId'] = villageid; config.headers['villageId'] = villageid;
const disableAutoVillage = config.headers?.autoVillage === false; // const disableAutoVillage = config.headers?.autoVillage === false;
const isToken = config.headers?.isToken === false; const isToken = config.headers?.isToken === false;
// 是否需要防止数据重复提交 // 是否需要防止数据重复提交

View File

@@ -10,16 +10,16 @@
<div class="title">基本信息</div> <div class="title">基本信息</div>
<div class="addBuildingFormBody"> <div class="addBuildingFormBody">
<el-form-item label="小区名称" prop="villageName"> <el-form-item label="小区名称" prop="villageName">
<el-input v-model.trim="form.villageName" placeholder="请输入小区名称" /> <el-input maxlength="25" v-model.trim="form.villageName" placeholder="请输入小区名称" />
</el-form-item> </el-form-item>
<el-form-item label="小区编号" prop="villageCode"> <el-form-item label="小区编号" prop="villageCode">
<el-input v-model.trim="form.villageCode" placeholder="请输入小区编号" /> <el-input maxlength="20" v-model.trim="form.villageCode" placeholder="请输入小区编号" />
</el-form-item> </el-form-item>
<el-form-item label="所在城市" prop="city"> <el-form-item label="所在城市" prop="city">
<el-cascader :options="pcaTextArrlist" v-model="city" @change="cityChange"> </el-cascader> <el-cascader :options="pcaTextArrList" v-model="city" @change="cityChange"> </el-cascader>
</el-form-item> </el-form-item>
<el-form-item label="完整详细地址" prop="buildingArea"> <el-form-item label="完整详细地址" prop="buildingArea">
<el-input v-model.trim="form.address" placeholder="请输入完整详细地址" /> <el-input type="textarea" :row="3" maxlength="100" show-word-limit v-model.trim="form.address" placeholder="请输入完整详细地址" />
</el-form-item> </el-form-item>
<el-form-item label="建成时间" prop="buildingArea"> <el-form-item label="建成时间" prop="buildingArea">
<el-date-picker v-model="builtTime" type="date" placeholder="选择建成时间" value-format="YYYY-MM-DD" @change="changeBuiltTime" /> <el-date-picker v-model="builtTime" type="date" placeholder="选择建成时间" value-format="YYYY-MM-DD" @change="changeBuiltTime" />
@@ -30,19 +30,10 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="小区面积" prop="villageArea"> <el-form-item label="小区面积" prop="villageArea">
<el-input v-model.trim.number="form.villageArea" placeholder="请输入小区面积"><template #append></template> </el-input> <el-input maxlength="8" v-model.trim="form.villageArea" placeholder="请输入小区面积"><template #append></template> </el-input>
</el-form-item> </el-form-item>
<!-- <el-form-item label="小区楼栋" prop="buildingArea">
<el-input v-model="form.buildingArea" placeholder="请输入小区楼栋"><template #append></template> </el-input>
</el-form-item>
<el-form-item label="小区房屋" prop="buildingArea">
<el-input v-model="form.buildingArea" placeholder="请输入小区房屋"><template #append></template> </el-input>
</el-form-item>
<el-form-item label="小区面积" prop="buildingArea">
<el-input v-model="form.buildingArea" placeholder="请输入小区面积"><template #append></template> </el-input>
</el-form-item> -->
<el-form-item label="车位数量" prop="parkingSpaceCount"> <el-form-item label="车位数量" prop="parkingSpaceCount">
<el-input v-model.trim.number="form.parkingSpaceCount" placeholder="请输入车位数量"> <el-input maxlength="8" v-model.trim="form.parkingSpaceCount" placeholder="请输入车位数量">
<template #append></template> <template #append></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -50,11 +41,13 @@
<el-upload <el-upload
accept=".jpg, .png" accept=".jpg, .png"
ref="uploadRef" ref="uploadRef"
:action="uploadfileurl" :action="uploadFileUrl"
:headers="headerToken()" :headers="headerToken()"
list-type="picture-card" list-type="picture-card"
:file-list="villageImg" :file-list="villageImg"
:auto-upload="false" :auto-upload="false"
:limit="9"
:on-exceed="handleExceed"
@change="handleUploadChange" @change="handleUploadChange"
@before-upload="handleBeforeUpload" @before-upload="handleBeforeUpload"
> >
@@ -70,12 +63,12 @@
</div> </div>
</template> </template>
<template #tip> <template #tip>
<div class="el-upload__tip">支持jpg, png等格式文件上传文件大小不超过10MB可上传多张</div> <div class="el-upload__tip">支持jpg, png等格式文件上传文件大小不超过10MB</div>
</template> </template>
</el-upload> </el-upload>
</el-form-item> </el-form-item>
<el-form-item style="width: 100%" label="小区简介"> <el-form-item style="width: 100%" label="小区简介">
<el-input v-model.trim="form.remark" :rows="5" type="textarea" placeholder="小区简介" /> <el-input maxlength="200" show-word-limit v-model.trim="form.remark" :rows="5" type="textarea" placeholder="小区简介" />
</el-form-item> </el-form-item>
</div> </div>
</div> </div>
@@ -83,19 +76,19 @@
<div class="title">负责人信息</div> <div class="title">负责人信息</div>
<div class="addBuildingFormBody addBuildingForm_User_Body"> <div class="addBuildingFormBody addBuildingForm_User_Body">
<el-form-item label="姓名"> <el-form-item label="姓名">
<el-input v-model.trim="form.manageName" placeholder="请输入姓名" /> <el-input maxlength="20" v-model.trim="form.manageName" placeholder="请输入姓名" />
</el-form-item> </el-form-item>
<el-form-item label="电话"> <el-form-item label="电话" prop="managePhone">
<el-input v-model.trim="form.managePhone" placeholder="请输入电话" /> <el-input v-model.trim="form.managePhone" placeholder="请输入电话" />
</el-form-item> </el-form-item>
<el-form-item label="微信"> <el-form-item label="微信" prop="manageVx">
<el-input v-model.trim="form.manageVx" placeholder="请输入微信"> </el-input> <el-input maxlength="20" v-model.trim="form.manageVx" placeholder="请输入微信"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="QQ"> <el-form-item label="QQ" prop="manageQq">
<el-input v-model.trim="form.manageQq" placeholder="请输入QQ"> </el-input> <el-input maxlength="20" v-model.trim="form.manageQq" placeholder="请输入QQ"> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="邮箱"> <el-form-item label="邮箱" prop="manageEmail">
<el-input v-model.trim="form.manageEmail" placeholder="请输入邮箱"> </el-input> <el-input maxlength="30" v-model.trim="form.manageEmail" placeholder="请输入邮箱"> </el-input>
</el-form-item> </el-form-item>
<div class="pl-100px"> <div class="pl-100px">
<el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button>
@@ -122,12 +115,11 @@ import { Delete, Plus } from '@element-plus/icons-vue';
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const editId = ref(route.query.id as string); const editId = ref(route.query.id as string);
const isedit = computed(() => Boolean(editId.value)); const isEdit = computed(() => Boolean(editId.value));
const apiPrefix = import.meta.env.VITE_APP_BASE_API;
const apipriex = import.meta.env.VITE_APP_BASE_API; const uploadFileUrl = `${apiPrefix}/village/uploadImages`;
const uploadfileurl = `${apipriex}/village/uploadImages`; // 获取省 市 区╬╬╬╬╬╬╬
// 获取省 市 区 const pcaTextArrList = ref<DataItem[]>(pcaTextArr);
const pcaTextArrlist = ref<DataItem[]>(pcaTextArr);
// 获取小区用途 // 获取小区用途
const houseUserList = ref([ const houseUserList = ref([
{ {
@@ -156,9 +148,9 @@ const form = ref<communitylist_rows_type>({
villageCode: '', villageCode: '',
address: '', address: '',
houseUse: null, houseUse: null,
villageArea: 0, villageArea: '',
remark: '', remark: '',
parkingSpaceCount: 0, parkingSpaceCount: '',
villageImageUrl: '', villageImageUrl: '',
city: '', city: '',
status: '0', status: '0',
@@ -177,12 +169,131 @@ const villageImg = ref([]);
// 表单验证 // 表单验证
const rules = ref({ const rules = ref({
villageName: [{ required: true, message: '请输入小区名称', trigger: 'blur' }], villageName: [{ required: true, message: '请输入小区名称', trigger: 'blur' }],
villageCode: [{ required: true, message: '请输入小区编号', trigger: 'blur' }], villageArea: [
city: [{ required: true, message: '请选择城市', trigger: 'blur' }] { required: false, message: '请输入小区面积', trigger: 'blur' },
{
validator: (rule, value, callback) => {
const num = Number(value);
if (value === '' || value === null) {
return callback();
}
if (Number.isNaN(num)) {
return callback(new Error('请输入正确的小区面积'));
}
if (num < 0) {
return callback(new Error('小区面积不能小于0'));
}
callback();
}
}
],
parkingSpaceCount: [
{ required: false, message: '请输入车位数量', trigger: 'blur' },
{
validator: (rule, value, callback) => {
const num = Number(value);
if (value === '' || value === null) {
return callback();
}
if (Number.isNaN(num)) {
return callback(new Error('请输入正确的车位数量'));
}
if (num < 0) {
return callback(new Error('车位数量不能小于0'));
}
if (num % 1 !== 0) {
return callback(new Error('请输入正确的整数车位数量'));
}
callback();
}
}
],
villageCode: [
{ required: true, message: '请输入小区编号', trigger: 'blur' },
{
validator: (_, value, callback) => {
if (value === '' || value === null) {
return callback(new Error('请输入小区编号'));
}
if (!/^[a-zA-Z0-9_-]{1,20}$/.test(value)) {
callback(new Error('请输入正确的小区编号,只能包含字母、数字、_和-'));
} else {
callback();
}
}
}
],
city: [{ required: true, message: '请选择城市', trigger: 'blur' }],
managePhone: [
{ required: false, message: '请输入电话', trigger: 'blur' },
{
validator: (_, value, callback) => {
// 值为空直接放行(非必填)
if (value === '' || value === null) {
return callback();
}
if (!/^1[3456789]\d{9}$/.test(value)) {
callback(new Error('请输入正确的手机号'));
} else {
callback();
}
}
}
],
manageEmail: [
{ required: false, message: '请输入邮箱', trigger: 'blur' },
{
validator: (_, value, callback) => {
if (value === '' || value === null) {
return callback();
}
// 邮箱总长度不超过254个字符用户名不超过64个字符
if (value.length > 254 || value.split('@')[0].length > 64) {
callback(new Error('邮箱地址过长'));
} else if (!/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.test(value)) {
callback(new Error('请输入正确的邮箱'));
} else {
callback();
}
}
}
],
manageVx: [
{ required: false, message: '请输入微信', trigger: 'blur' },
{
validator: (_, value, callback) => {
// 值为空直接放行(非必填)
if (value === '' || value === null) {
return callback();
}
if (!/^[a-zA-Z0-9_]{4,20}$/.test(value)) {
callback(new Error('请输入正确的微信'));
} else {
callback();
}
}
}
],
manageQq: [
{ required: false, message: '请输入QQ', trigger: 'blur' },
{
validator: (_, value, callback) => {
// 值为空直接放行(非必填)
if (value === '' || value === null) {
return callback();
}
if (!/^[1-9]\d{4,10}$/.test(value)) {
callback(new Error('请输入正确的QQ'));
} else {
callback();
}
}
}
]
}); });
/** 获取编辑小区的信息 */ /** 获取编辑小区的信息 */
function getCommunityinfo() { function getCommunityInfo() {
const id = editId.value; const id = editId.value;
getVillageByIdAPI(id).then((res) => { getVillageByIdAPI(id).then((res) => {
city.value = res.data.city ? res.data.city.split('/') : []; city.value = res.data.city ? res.data.city.split('/') : [];
@@ -206,9 +317,11 @@ function getCommunityinfo() {
}; };
}); });
} }
if (isedit.value) {
getCommunityinfo(); if (isEdit.value) {
getCommunityInfo();
} }
// 请求头 // 请求头
function headerToken() { function headerToken() {
const useStore = useUserStore(); const useStore = useUserStore();
@@ -216,9 +329,11 @@ function headerToken() {
Authorization: 'Bearer ' + useStore.token Authorization: 'Bearer ' + useStore.token
}; };
} }
const allowImgSuffix = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic']; const allowImgSuffix = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic'];
/** 检测文件大小和格式 */ /** 检测文件大小和格式 */
function handleBeforeUpload(file: UploadFile): Promise<boolean | { file: UploadFile; type: string }> { function handleBeforeUpload(file: UploadFile): Promise<boolean | { file: UploadFile; type: string }> {
const type = file.raw.type.split('/').pop();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const isLt10M = file.size / 1024 / 1024 < 10; const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) { if (!isLt10M) {
@@ -226,11 +341,13 @@ function handleBeforeUpload(file: UploadFile): Promise<boolean | { file: UploadF
type: '文件大小错误', type: '文件大小错误',
file: file file: file
}); });
} else if (!allowImgSuffix.includes(file.raw.type)) { ElMessage.warning('图片大小超过10M,请重新上传');
} else if (!allowImgSuffix.includes(type)) {
reject({ reject({
type: '文件类型错误', type: '文件类型错误',
file: file file: file
}); });
ElMessage.warning('图片格式不是 png/jpg/jpeg 格式, 请重新上传');
} else { } else {
resolve(true); resolve(true);
} }
@@ -238,15 +355,18 @@ function handleBeforeUpload(file: UploadFile): Promise<boolean | { file: UploadF
} }
/** 上传狗子 */ /** 上传狗子 */
async function handleUploadChange(file: UploadFile) { async function handleUploadChange(file: UploadFile) {
const isupload = await handleBeforeUpload(file); const isUpload = await handleBeforeUpload(file);
if (typeof isupload === 'object') { if (typeof isUpload === 'object') {
ElMessage.error(isupload.type); ElMessage.error(isUpload.type);
return; return;
} else if (typeof isupload === 'boolean' && isupload === true) { } else if (typeof isUpload === 'boolean' && isUpload === true) {
villageImg.value.push(file.raw); villageImg.value.push(file.raw);
} }
} }
function handleExceed() {
ElMessage.error('最多上传9张图片');
}
/** 移除钩子 */ /** 移除钩子 */
const handleRemove = (file: UploadFile) => { const handleRemove = (file: UploadFile) => {
villageImg.value = villageImg.value.filter((item) => item.uid !== file.uid); villageImg.value = villageImg.value.filter((item) => item.uid !== file.uid);
@@ -256,6 +376,7 @@ const handleRemove = (file: UploadFile) => {
const changeBuiltTime = (value: string) => { const changeBuiltTime = (value: string) => {
form.value.completDate = value; form.value.completDate = value;
}; };
const cityChange = (value: CascaderValue[]) => { const cityChange = (value: CascaderValue[]) => {
form.value.city = value.join('/'); form.value.city = value.join('/');
}; };
@@ -299,7 +420,7 @@ const submitForm = () => {
// 3) 有新文件先上传新文件再与已有URL合并 // 3) 有新文件先上传新文件再与已有URL合并
const formdata = new FormData(); const formdata = new FormData();
newFiles.forEach((file) => formdata.append('files', file)); newFiles.forEach((file) => formdata.append('files', file));
console.log('newFiles', newFiles);
uploadVillageImageAPI(formdata).then((res) => { uploadVillageImageAPI(formdata).then((res) => {
const uploadedUrls = res.data.success.map((x) => x.url).filter(Boolean); const uploadedUrls = res.data.success.map((x) => x.url).filter(Boolean);
// 4) 最终图片 = 已有图片 + 新上传图片(避免覆盖) // 4) 最终图片 = 已有图片 + 新上传图片(避免覆盖)
@@ -336,18 +457,19 @@ function submitFormInfo() {
} }
} }
if (isedit.value) { if (isEdit.value) {
editVillageAPI<communitylist_rows_type>(form.value).then((res) => { editVillageAPI<communitylist_rows_type>(form.value).then(() => {
ElMessage.success('编辑成功'); ElMessage.success('编辑成功');
cancelForm(); cancelForm();
}); });
} else { } else {
addVillageAPI<communitylist_rows_type>(form.value).then((res) => { addVillageAPI<communitylist_rows_type>(form.value).then(() => {
ElMessage.success('添加成功'); ElMessage.success('添加成功');
cancelForm(); cancelForm();
}); });
} }
} }
// 返回
const cancelForm = () => { const cancelForm = () => {
router.back(); router.back();
}; };
@@ -368,7 +490,6 @@ const cancelForm = () => {
& > span { & > span {
padding-left: 20px; padding-left: 20px;
font-size: 20px; font-size: 20px;
color: white;
color: #000; color: #000;
} }
} }

View File

@@ -10,7 +10,7 @@
</div> </div>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input v-model.trim="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('login.username')"> <el-input v-model.trim="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('login.username')">
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template> <template #prefix><svg-icon icon-class="user_login" class="el-input__icon input-icon" /></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
@@ -255,7 +255,7 @@ onMounted(() => {
height: 393px; height: 393px;
padding: 30px; padding: 30px;
border-radius: 10px; border-radius: 10px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.3) 100%); background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.85) 60%, rgba(0, 0, 0, 0.55) 100%);
.input-icon { .input-icon {
height: 40px; height: 40px;
width: 23px; width: 23px;

View File

@@ -12,12 +12,12 @@
<el-row> <el-row>
<el-col :span="13"> <el-col :span="13">
<el-form-item label="活动标题" prop="title"> <el-form-item label="活动标题" prop="title">
<el-input v-model.trim="form.title" placeholder="请输入活动标题" /> <el-input maxlength="30" v-model.trim="form.title" placeholder="请输入活动标题" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="活动作者" prop="author"> <el-form-item label="活动作者" prop="author">
<el-input v-model.trim="form.author" placeholder="请输入活动作者" /> <el-input maxlength="20" v-model.trim="form.author" placeholder="请输入活动作者" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -48,7 +48,7 @@
</el-col> </el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="活动地点" prop="address"> <el-form-item label="活动地点" prop="address">
<el-input v-model.trim="form.address" placeholder="请输入活动地点" /> <el-input maxlength="50" type="textarea" show-word-limit v-model.trim="form.address" placeholder="请输入活动地点" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -77,19 +77,19 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="主办方" prop="organizer"> <el-form-item label="主办方" prop="organizer">
<el-input v-model.trim="form.organizer" placeholder="请输入主办方" /> <el-input maxlength="20" v-model.trim="form.organizer" placeholder="请输入主办方" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="联系人" prop="contactName"> <el-form-item label="联系人" prop="contactName">
<el-input v-model.trim="form.contactName" placeholder="请输入联系人" /> <el-input maxlength="20" v-model.trim="form.contactName" placeholder="请输入联系人" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="联系方式" prop="contactName"> <el-form-item label="联系方式" prop="contactPhone">
<el-input v-model.trim="form.contactPhone" placeholder="请输入联系方式" /> <el-input maxlength="20" v-model.trim="form.contactPhone" placeholder="请输入联系方式" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -97,8 +97,8 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="活动名额" prop="quota"> <el-form-item label="活动名额" prop="quota">
<div class="flex items-center"> <div class="flex items-center">
<el-input-number v-model.trim.number="form.quota" :min="0" placeholder="0代表无限" /> <el-input-number v-model.trim.number="form.quota" :min="0" :max="99999999" placeholder="0代表无限" />
<span class="ml-2 text-gray-500 text-sm" style="font-size: 12px">(填 <b>0</b> 代表<u>不限制名额</u></span> <span class="ml-2 text-gray-500 text-sm" style="font-size: 12px">(填 <strong>0</strong> 代表 <u>不限制名额</u> </span>
</div> </div>
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -124,14 +124,21 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="招募要求"> <el-form-item label="招募要求">
<el-input :row="8" type="textarea" v-model.trim="form.requirements" placeholder="请输入招募要求" /> <el-input
maxlength="200"
show-word-limit
:row="8"
type="textarea"
v-model.trim="form.requirements"
placeholder="请输入招募要求"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col> <el-col>
<el-form-item label="活动详情" prop="content"> <el-form-item label="活动详情" prop="content">
<editor v-model="form.content" :height="500" :min-height="300" :read-only="false" :file-size="5" :type="'url'" /> <editor v-model="form.content" :height="500" :min-height="300" :read-only="false" :file-size="5" :type="'url'" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -296,6 +303,8 @@ const upload = ref<UploadInstance>();
const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => { const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
if (response.data && response.data.url) { if (response.data && response.data.url) {
form.value.coverImage = response.data.url; form.value.coverImage = response.data.url;
} else {
ElMessage.warning('上传频繁,请稍后再试');
} }
}; };

View File

@@ -44,6 +44,7 @@
v-if="scope.row.coverImage" v-if="scope.row.coverImage"
:src="scope.row.coverImage" :src="scope.row.coverImage"
fit="cover" fit="cover"
style="width: 100px; height: 100px"
></el-image> ></el-image>
<span v-else style="color: grey">暂无</span> <span v-else style="color: grey">暂无</span>
</template> </template>
@@ -71,7 +72,7 @@
<span v-else>{{ scope.row.quota }}</span> <span v-else>{{ scope.row.quota }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="300px" fixed="right"> <el-table-column label="操作" align="center" width="200px" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button v-if="scope.row.status === '0'" link type="primary" @click="handleSend(scope.row)">发布</el-button> <el-button v-if="scope.row.status === '0'" link type="primary" @click="handleSend(scope.row)">发布</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['activity:activity:edit']">编辑</el-button> <el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['activity:activity:edit']">编辑</el-button>
@@ -84,7 +85,7 @@
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="activityFormRef" :model="form" :rules="rules" label-width="120px"> <el-form ref="activityFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="发布人姓名" prop="createName"> <el-form-item label="发布人姓名" prop="createName">
<el-input v-model="form.createName" placeholder="请输入发布人姓名" /> <el-input maxlength="20" v-model.trim="form.createName" placeholder="请输入发布人姓名" />
</el-form-item> </el-form-item>
<el-form-item label="发布后状态" prop="status"> <el-form-item label="发布后状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">
@@ -225,7 +226,7 @@ const handleUpdate = (row?: ActivityVO) => {
}); });
}; };
/** 提交按钮 */ /** 提交按钮 ╬╬╬╬╬╬2╬22╬2╬«2╬2▐2╬╬╬╬╬ */
const submitForm = () => { const submitForm = () => {
activityFormRef.value?.validate(async (valid: boolean) => { activityFormRef.value?.validate(async (valid: boolean) => {
if (valid) { if (valid) {

View File

@@ -6,7 +6,7 @@
<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="Banner名称" prop="name"> <el-form-item label="Banner名称" prop="name">
<el-input v-model.trim="form.name" placeholder="请输入" /> <el-input maxlength="20" show-word-limit v-model.trim="form.name" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item label="Banner图" prop="url"> <el-form-item label="Banner图" prop="url">
<el-upload <el-upload
@@ -15,6 +15,7 @@
accept=".png, .jpg" accept=".png, .jpg"
:action="uploadUrl" :action="uploadUrl"
name="file" name="file"
:limit="1"
:headers="headerToken()" :headers="headerToken()"
:show-file-list="false" :show-file-list="false"
:on-success="handleAvatarSuccess" :on-success="handleAvatarSuccess"
@@ -85,7 +86,7 @@ const handleAvatarSuccess: UploadProps['onSuccess'] = (response: any) => {
} }
}; };
const handleAvatarError: UploadProps['onError'] = (respones) => {}; const handleAvatarError: UploadProps['onError'] = () => {};
const formRef = ref(); const formRef = ref();
const form = ref({ const form = ref({

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="名称" prop="name"> <el-form-item label="名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -54,6 +54,7 @@
:key="index" :key="index"
:src="item" :src="item"
:preview-teleported="true" :preview-teleported="true"
:initial-index="index"
:preview-src-list="problemImageUrlList" :preview-src-list="problemImageUrlList"
style="width: 120px; height: 120px; margin-right: 10px" style="width: 120px; height: 120px; margin-right: 10px"
></el-image> ></el-image>
@@ -80,6 +81,7 @@
</el-form-item> </el-form-item>
<el-form-item label="处理人员" prop="handleId"> <el-form-item label="处理人员" prop="handleId">
<repairUser <repairUser
title-name="选择处理人员"
:is-multiple="false" :is-multiple="false"
:username="formInfo.handleName" :username="formInfo.handleName"
:userid="formInfo.handleId" :userid="formInfo.handleId"
@@ -88,7 +90,7 @@
></repairUser> ></repairUser>
</el-form-item> </el-form-item>
<el-form-item label="处理描述" prop="handleContent"> <el-form-item label="处理描述" prop="handleContent">
<el-input type="textarea" :rows="5" v-model="form.handleContent"></el-input> <el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.handleContent"></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" v-if="form.status !== '0'" @click="submitForm">提交</el-button> <el-button type="primary" v-if="form.status !== '0'" @click="submitForm">提交</el-button>
@@ -123,7 +125,7 @@ const formInfo = ref({
'complaintName': '', 'complaintName': '',
'phone': '', 'phone': '',
'problemImageUrl': '', 'problemImageUrl': '',
'status': '2', // 投诉状态 0待处理 1处理中 2已处理 'status': '1', // 投诉状态 0 待处理 1 已处理
'handleId': '', 'handleId': '',
'handleName': '', 'handleName': '',
'handleContent': '', 'handleContent': '',
@@ -152,8 +154,13 @@ async function init() {
...formInfo.value, ...formInfo.value,
...res.data ...res.data
}; };
console.log(formInfo.value); form.value = {
...form.value,
...res.data
};
// 处理照片
problemImageUrlList.value = res.data.problemImageUrl ? res.data.problemImageUrl.split(',') : []; problemImageUrlList.value = res.data.problemImageUrl ? res.data.problemImageUrl.split(',') : [];
// 处理 投诉类型
const find = res2.rows.find((item) => item.id === formInfo.value.typeId); const find = res2.rows.find((item) => item.id === formInfo.value.typeId);
if (find) { if (find) {
formInfo.value.type = find.name; formInfo.value.type = find.name;
@@ -172,7 +179,6 @@ function handleChange(pop: ResidentVO) {
} }
// 提交 // 提交
const formRef = ref(); const formRef = ref();
const submitForm = () => { const submitForm = () => {
formRef.value?.validate(async (valid: boolean) => { formRef.value?.validate(async (valid: boolean) => {

View File

@@ -4,7 +4,7 @@
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]"> <div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" label-width="120px" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" label-width="90px" label-position="left" :model="queryParams" :inline="true">
<el-form-item label="投诉类型" prop="typeId"> <el-form-item label="投诉类型" prop="typeId">
<el-select v-model="queryParams.typeId" placeholder="请选择投诉类型" style="width: 240px"> <el-select v-model="queryParams.typeId" placeholder="请选择投诉类型" style="width: 240px">
<el-option :disabled="item.status === '1'" v-for="item in complainTypeList" :key="item.id" :label="item.name" :value="item.id" /> <el-option :disabled="item.status === '1'" v-for="item in complainTypeList" :key="item.id" :label="item.name" :value="item.id" />

View File

@@ -10,7 +10,7 @@
<div class="formbox"> <div class="formbox">
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="投诉类型名称" prop="name"> <el-form-item label="投诉类型名称" prop="name">
<el-input v-model.trim="form.name" placeholder="请输入投诉类型名称" /> <el-input maxlength="20" show-word-limit v-model.trim="form.name" placeholder="请输入投诉类型名称" />
</el-form-item> </el-form-item>
<el-form-item label="投诉类型状态" prop="status"> <el-form-item label="投诉类型状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" label-width="100px" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" label-width="100px" :model="queryParams" :inline="true">
<el-form-item label="投诉类型名称" prop="name"> <el-form-item label="投诉类型名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入投诉类型名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model.trim="queryParams.name" placeholder="请输入投诉类型名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -17,7 +17,7 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="申请人" prop="applyName"> <el-form-item label="申请人" prop="applyName">
<el-input v-model.trim="form.applyName" placeholder="请输入申请人" /> <el-input maxlength="20" v-model.trim="form.applyName" placeholder="请输入申请人" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -25,12 +25,12 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="装修公司" prop="decorationCompany"> <el-form-item label="装修公司" prop="decorationCompany">
<el-input v-model.trim="form.decorationCompany" placeholder="请输入装修公司" /> <el-input maxlength="20" v-model.trim="form.decorationCompany" placeholder="请输入装修公司" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="装修内容" prop="decorationContent"> <el-form-item label="装修内容" prop="decorationContent">
<el-input v-model.trim="form.decorationContent" placeholder="请输入装修内容" /> <el-input maxlength="200" show-word-limit type="textarea" v-model.trim="form.decorationContent" placeholder="请输入装修内容" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -41,6 +41,7 @@
type="number" type="number"
min="0" min="0"
step="0.01" step="0.01"
maxlength="8"
placeholder="请输入装修押金最多保留2位小数" placeholder="请输入装修押金最多保留2位小数"
v-model.trim.number="form.decorationDeposit" v-model.trim.number="form.decorationDeposit"
/> />
@@ -116,6 +117,9 @@ const rules = {
{ required: true, message: '请输入装修押金', trigger: 'blur' }, { required: true, message: '请输入装修押金', trigger: 'blur' },
{ {
validator: (rule, val, callback) => { validator: (rule, val, callback) => {
if (val === '' || val === null) {
return callback(new Error('请输入装修押金'));
}
const msg = validator(val, 'money'); const msg = validator(val, 'money');
if (msg) callback(new Error(msg)); if (msg) callback(new Error(msg));
else callback(); else callback();

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form label-width="120px" ref="queryFormRef" :model="queryParams" :inline="true"> <el-form label-width="120px" ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="申请人姓名" prop="applyName"> <el-form-item label="申请人姓名" prop="applyName">
<el-input v-model="queryParams.applyName" placeholder="请输入申请人姓名" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.applyName" placeholder="请输入申请人姓名" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="装修验收结果" prop="inspectionResult"> <el-form-item label="装修验收结果" prop="inspectionResult">
<el-select v-model="queryParams.inspectionResult" placeholder="请选择装修验收结果" style="width: 240px"> <el-select v-model="queryParams.inspectionResult" placeholder="请选择装修验收结果" style="width: 240px">

View File

@@ -26,12 +26,12 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="求助人姓名" prop="seekName"> <el-form-item label="求助人姓名" prop="seekName">
<el-input v-model.trim="form.seekName" placeholder="请输入求助人姓名" /> <el-input maxlength="20" v-model.trim="form.seekName" placeholder="请输入求助人姓名" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="联系方式" prop="phone"> <el-form-item label="联系方式" prop="phone">
<el-input v-model.trim="form.phone" placeholder="请输入联系方式" /> <el-input maxlength="50" show-word-limit v-model.trim="form.phone" placeholder="请输入联系方式" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -49,7 +49,14 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="办事地点" prop="handlePosition"> <el-form-item label="办事地点" prop="handlePosition">
<el-input v-model.trim="form.handlePosition" placeholder="请输入办事地点" /> <el-input
maxlength="200"
type="textarea"
:rows="3"
show-word-limit
v-model.trim="form.handlePosition"
placeholder="请输入办事地点"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -62,6 +69,7 @@
:action="uploadUrl" :action="uploadUrl"
:multiple="true" :multiple="true"
:auto-upload="false" :auto-upload="false"
:limit="9"
ref="uploadRef" ref="uploadRef"
:show-file-list="true" :show-file-list="true"
name="files" name="files"

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="求助人" prop="seekName"> <el-form-item label="求助人" prop="seekName">
<el-input v-model="queryParams.seekName" placeholder="请输入求助人" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.seekName" placeholder="请输入求助人" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -6,7 +6,7 @@
<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="name"> <el-form-item label="房屋设施名称" prop="name">
<el-input v-model.trim="form.name" placeholder="请输入房屋设施名称" /> <el-input maxlength="20" show-word-limit v-model.trim="form.name" placeholder="请输入房屋设施名称" />
</el-form-item> </el-form-item>
<el-form-item label="房屋设置状态" prop="status"> <el-form-item label="房屋设置状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="设施名称" prop="name"> <el-form-item label="设施名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入设施名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model.trim="queryParams.name" placeholder="请输入设施名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -8,13 +8,13 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="月卡编号" prop="cardCode"> <el-form-item label="月卡编号" prop="cardCode">
<el-input v-model.trim="form.cardCode" placeholder="请输入月卡编号" /> <el-input maxlength="15" v-model.trim="form.cardCode" placeholder="请输入月卡编号" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="持卡人姓名" prop="cardName"> <el-form-item label="持卡人姓名" prop="cardName">
<el-input v-model.trim="form.cardName" placeholder="请输入持卡人姓名" /> <el-input maxlength="15" v-model.trim="form.cardName" placeholder="请输入持卡人姓名" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -22,20 +22,25 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="手机号码" prop="phone"> <el-form-item label="手机号码" prop="phone">
<el-input v-model.number="form.phone" placeholder="请输入手机号码" /> <el-input maxlength="11" v-model.number="form.phone" placeholder="请输入手机号码" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="绑定车牌号" prop="carNum"> <el-form-item label="绑定车牌号" prop="carNum">
<LicensePlateInput ref="carNumInputRef" required v-model="form.carNum" @change="() => handleValidate()" /> <el-input
maxlength="10"
v-model.trim="form.carNum"
placeholder="请输入车牌号"
style="text-transform: uppercase; letter-spacing: 2px"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="办理人" prop="handleName"> <el-form-item label="办理人" prop="handleName">
<el-input v-model="form.handleName" placeholder="请输入办理人姓名" /> <el-input maxlength="15" v-model="form.handleName" placeholder="请输入办理人姓名" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
@@ -57,7 +62,7 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="费用" prop="cost"> <el-form-item label="费用" prop="cost">
<el-input v-model.number="form.cost" placeholder="请输入费用"> <el-input maxlength="8" v-model.number.trim="form.cost" placeholder="请输入费用">
<template #suffix></template> <template #suffix></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -74,7 +79,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" /> <el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -90,10 +95,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import LicensePlateInput from '@/components/LicensePlateInput/index.vue';
import PageHeader from '@/components/Pageheader/index.vue'; import PageHeader from '@/components/Pageheader/index.vue';
import { addMonthCard, getMonthCard, updateMonthCard } from '@/api/system/MonthCard'; import { addMonthCard, getMonthCard, updateMonthCard } from '@/api/system/MonthCard';
import { LicensePlateValidator, validator } from '@/utils/Reg'; import { validator } from '@/utils/Reg';
import { LicensePlateValidator2 } from '@/utils/Reg2';
import { callback } from '@/api/login';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method')); const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method'));
@@ -150,32 +156,35 @@ const rules = ref({
{ {
validator: (_: any, value: string, callback: any) => { validator: (_: any, value: string, callback: any) => {
if (!value) { if (!value) {
callback(); callback(new Error('请输入车牌号'));
return; return;
} }
if (!LicensePlateValidator.isValidPlate(value)) { if (!LicensePlateValidator2.isValidPlate(value)) {
callback(); callback(new Error('请输入正确的车牌号'));
return; return;
} }
callback(); callback();
}, },
trigger: 'blur' // ✅ 只在失焦时验证 trigger: 'blur'
} }
], ],
startTime: [{ required: true, message: '请选择有效日期', trigger: 'blur' }], startTime: [{ required: true, message: '请选择有效日期', trigger: 'blur' }],
payMethod: [{ required: true, message: '请选择支付方式', trigger: 'blur' }], payMethod: [{ required: true, message: '请选择支付方式', trigger: 'blur' }],
cost: [ cost: [
{ required: true, message: '请输入费用', trigger: 'blur' },
{ {
validator: (_: any, value: string | number) => validator(value, 'money'), validator: (_: any, value: string | number, callback) => {
message: '请输入正确的金额,最多两位小数', if (value === null || value === undefined || value === 0) {
trigger: 'blur', return callback(new Error('请输入费用'));
required: true }
if (!validator(value, 'money')) {
return callback(new Error('请输入正确的金额,最多两位小数'));
}
return callback();
}
} }
] ]
}); });
function handleValidate() {
formRef.value.validateField('carNum');
}
const userid = ref(null); const userid = ref(null);

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="月卡编号" prop="cardCode"> <el-form-item label="月卡编号" prop="cardCode">
<el-input v-model="queryParams.cardCode" placeholder="请输入月卡编号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="12" v-model="queryParams.cardCode" placeholder="请输入月卡编号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -12,7 +12,7 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="公告标题" prop="noticeTitle"> <el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model.trim="form.noticeTitle" placeholder="请输入公告标题" /> <el-input maxlength="30" v-model.trim="form.noticeTitle" placeholder="请输入公告标题" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12">--> <!-- <el-col :span="12">-->

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="公告标题" prop="noticeTitle"> <el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" /> <el-input maxlength="30" v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -34,15 +34,20 @@
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="缴费人" prop="payerName"> <el-form-item label="缴费人" prop="payerName">
<el-input v-model.trim="form.payerName" placeholder="请输入缴费人姓名" /> <el-input maxlength="15" v-model.trim="form.payerName" placeholder="请输入缴费人姓名" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车牌号" prop="carNum"> <el-form-item label="车牌号" prop="carNum">
<!-- <el-input v-model.number.trim="form.carNum" placeholder="请输入车牌号" /> --> <el-input
<LicensePlateInput ref="carNumInputRef" required v-model="form.carNum" @change="() => handleValidate()" /> maxlength="15"
v-model.trim="form.carNum"
placeholder="请输入车牌号"
@input="handleInput"
style="text-transform: uppercase; letter-spacing: 2px"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
@@ -66,7 +71,7 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="费用" prop="cost"> <el-form-item label="费用" prop="cost">
<el-input v-model.number.trim="form.cost" placeholder="请输入费用"> <el-input maxlength="8" v-model.number.trim="form.cost" placeholder="请输入费用">
<template #suffix></template> <template #suffix></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -92,7 +97,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" /> <el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -109,11 +114,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue'; import PageHeader from '@/components/Pageheader/index.vue';
import LicensePlateInput from '@/components/LicensePlateInput/index.vue';
import { listArea } from '@/api/system/carArea'; import { listArea } from '@/api/system/carArea';
import { addParkingCost, getParkingCost, updateParkingCost } from '@/api/system/ParkingCost'; import { addParkingCost, getParkingCost, updateParkingCost, getParkingCostCarAreaApi } from '@/api/system/ParkingCost';
import { listParking } from '@/api/system/parking'; import { validator } from '@/utils/Reg';
import { LicensePlateValidator, validator } from '@/utils/Reg'; import { LicensePlateValidator2 } from '@/utils/Reg2';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method')); const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method'));
const { com_parking_charge } = toRefs<any>(proxy?.useDict('com_parking_charge')); const { com_parking_charge } = toRefs<any>(proxy?.useDict('com_parking_charge'));
@@ -135,7 +140,7 @@ const form = ref({
cost: null, // 费用 cost: null, // 费用
payMethod: '', // 支付方式 payMethod: '', // 支付方式
payerStatus: '0', // 缴纳人状态 payerStatus: '0', // 缴纳人状态
remark: '' // 备注 remark: '' // 备注 最多200个字符
}); });
const checkDate = ref([]); const checkDate = ref([]);
// 改变时间日期 // 改变时间日期
@@ -160,16 +165,16 @@ const rules = ref({
{ {
validator: (_: any, value: string, callback: any) => { validator: (_: any, value: string, callback: any) => {
if (!value) { if (!value) {
callback(); callback(new Error('请输入车牌号'));
return; return;
} }
if (!LicensePlateValidator.isValidPlate(value)) { if (!LicensePlateValidator2.isValidPlate(value)) {
callback(new Error('请输入正确的车牌号格式')); callback(new Error('请输入正确的车牌号'));
return; return;
} }
callback(); callback();
}, },
trigger: 'blur' // ✅ 只在失焦时验证╬N trigger: 'blur'
} }
], ],
startTime: [{ required: true, message: '请选择有效日期', trigger: 'blur' }], startTime: [{ required: true, message: '请选择有效日期', trigger: 'blur' }],
@@ -177,15 +182,18 @@ const rules = ref({
cost: [ cost: [
{ required: true, message: '请输入费用', trigger: 'blur' }, { required: true, message: '请输入费用', trigger: 'blur' },
{ {
validator: (_: any, value: number) => validator(value, 'money'), validator: (_: any, value: number, callback: any) => {
message: '请输入费用', if (value === null || value === undefined || value === 0) {
return callback(new Error('请输入费用'));
}
return validator(value, 'money');
},
message: '请输入费用, 保留2位小数',
trigger: 'blur' trigger: 'blur'
} }
] ]
}); });
function handleValidate() {
formRef.value.validateField('carNum');
}
const userid = ref(null); const userid = ref(null);
// 区域 // 区域
@@ -205,6 +213,7 @@ function init() {
...res.data ...res.data
}; };
checkDate.value = [form.value.startTime, form.value.endTime]; checkDate.value = [form.value.startTime, form.value.endTime];
handleArea(form.value.areaId);
}); });
} }
} }
@@ -212,12 +221,8 @@ init();
// 选择区域后 动态车位 // 选择区域后 动态车位
function handleArea(val: string) { function handleArea(val: string) {
listParking({ getParkingCostCarAreaApi({ areaId: val }).then((res) => {
areaId: val, parkingList.value = res.data;
pageNum: 1,
pageSize: 999999999
}).then((res) => {
parkingList.value = res.rows;
}); });
} }
@@ -240,6 +245,9 @@ const submitForm = () => {
} }
}); });
}; };
function handleInput(res: string) {
form.value.carNum = res.toUpperCase();
}
// 推出 // 推出
const cancelForm = () => { const cancelForm = () => {
router.back(); router.back();

View File

@@ -6,10 +6,10 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="缴费人" prop="payerName"> <el-form-item label="缴费人" prop="payerName">
<el-input v-model="queryParams.payerName" placeholder="请输入缴费人" clearable @keyup.enter="handleQuery" /> <el-input maxlength="12" v-model="queryParams.payerName" placeholder="请输入缴费人" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="车牌号" prop="carNum"> <el-form-item label="车牌号" prop="carNum">
<el-input v-model="queryParams.carNum" placeholder="请输入车牌号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="8" v-model="queryParams.carNum" placeholder="请输入车牌号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -43,7 +43,7 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input :rows="5" type="textarea" placeholder="请输入" v-model="form.remark"></el-input> <el-input :rows="5" maxlength="200" show-word-limit type="textarea" placeholder="请输入" v-model="form.remark"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>

View File

@@ -36,8 +36,8 @@
</template> </template>
<div class="question-title-area"> <div class="question-title-area">
<el-input v-model="form.title" placeholder="请输入问卷标题" class="title-input" /> <el-input maxlength="20" show-word-limit v-model="form.title" placeholder="请输入问卷标题" class="title-input" />
<el-input v-model="form.description" type="textarea" placeholder="请输入问卷描述(选填)" /> <el-input maxlength="200" show-word-limit v-model="form.description" type="textarea" placeholder="请输入问卷描述(选填)" />
</div> </div>
<draggable v-model="form.content" group="components" item-key="cid" class="question-list" @add="handleAddQuestion"> <draggable v-model="form.content" group="components" item-key="cid" class="question-list" @add="handleAddQuestion">

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="问卷标题" prop="title"> <el-form-item label="问卷标题" prop="title">
<el-input v-model="queryParams.title" placeholder="请输入问卷标题" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.title" placeholder="请输入问卷标题" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="参与范围" prop="scope"> <!-- <el-form-item label="参与范围" prop="scope">
<el-input v-model="queryParams.scope" placeholder="请输入参与范围 0全体业主 1部分业主" clearable @keyup.enter="handleQuery" /> <el-input v-model="queryParams.scope" placeholder="请输入参与范围 0全体业主 1部分业主" clearable @keyup.enter="handleQuery" />

View File

@@ -30,14 +30,14 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="报修标题" prop="item"> <el-form-item label="报修标题" prop="item">
<el-input v-model.trim="form.item" placeholder="请输入报修标题" /> <el-input maxlength="30" v-model.trim="form.item" placeholder="请输入报修标题" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="问题描述" prop="problem"> <el-form-item label="问题描述" prop="problem">
<el-input type="textarea" :rows="5" v-model.trim="form.problem" placeholder="请输入问题描述" /> <el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.problem" placeholder="请输入问题描述" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -82,6 +82,7 @@
v-model:file-list="fileList" v-model:file-list="fileList"
:action="uploadUrl" :action="uploadUrl"
list-type="picture-card" list-type="picture-card"
:limit="1"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:on-remove="handleRemove" :on-remove="handleRemove"
:before-upload="handleChangeFile" :before-upload="handleChangeFile"
@@ -109,7 +110,7 @@ import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue'; import PageHeader from '@/components/Pageheader/index.vue';
import { hasFormData } from '@/utils/house'; import { hasFormData } from '@/utils/house';
import Holder from '@/components/Holder/index.vue'; import Holder from '@/components/Holder/index.vue';
import { UploadFiles, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus'; import { UploadProps, UploadRawFile, UploadUserFile } from 'element-plus';
import { addRepair, getRepair, updateRepair, uploadRepairImages } from '@/api/system/Repair'; import { addRepair, getRepair, updateRepair, uploadRepairImages } from '@/api/system/Repair';
import { gettreelistRepairProject } from '@/api/system/RepairProject'; import { gettreelistRepairProject } from '@/api/system/RepairProject';
import { useHouseStore } from '@/store/modules/house'; import { useHouseStore } from '@/store/modules/house';

View File

@@ -8,7 +8,7 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="维修项目名" prop="projectName"> <el-form-item label="维修项目名" prop="projectName">
<el-input v-model.trim="form.projectName" placeholder="请输入维修项目名" /> <el-input maxlength="20" show-word-limit v-model.trim="form.projectName" placeholder="请输入维修项目名" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>

View File

@@ -30,7 +30,9 @@
<el-col :span="8"> <el-col :span="8">
<div class="carInfo_Item"> <div class="carInfo_Item">
<div class="label">问题描述</div> <div class="label">问题描述</div>
<div class="main">{{ form.problem }}</div> <div class="main" style="font-size: small; max-width: 200px">
<span>{{ form.problem }}</span>
</div>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
@@ -56,12 +58,6 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row class="mb-20px"> <el-row class="mb-20px">
<!-- <el-col :span="8">-->
<!-- <div class="carInfo_Item">-->
<!-- <div class="label">提交人</div>-->
<!-- <div class="main">{{ form.problem }}</div>-->
<!-- </div>-->
<!-- </el-col>-->
<el-col :span="8"> <el-col :span="8">
<div class="carInfo_Item"> <div class="carInfo_Item">
<div class="label">提交时间:</div> <div class="label">提交时间:</div>
@@ -69,22 +65,23 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<el-row v-if="form.problemImageUrl.trim() === ''"> <el-row>
<el-col :span="24"> <el-col :span="24">
<div class="carInfo_Item"> <div class="carInfo_Item">
<div class="label">附件:</div> <div class="label">附件:</div>
<div class="main fileImagebox"> <div class="main fileImagebox" v-if="form.problemImageUrlList.length > 0">
<el-image <el-image
:preview-teleported="true" :preview-teleported="true"
:zoom-rate="1.2" :zoom-rate="1.2"
:max-scale="7" :max-scale="7"
:min-scale="0.2" :min-scale="0.2"
:preview-src-list="form.problemImageUrl.split(',').filter(Boolean)" :preview-src-list="form.problemImageUrlList"
show-progress show-progress
:initial-index="0" :initial-index="0"
v-for="(item, index) in form.problemImageUrl.split(',').filter(Boolean)" v-for="(item, index) in form.problemImageUrlList"
:key="index" :key="index"
:src="splitImages(item)" :src="item"
lazy
class="carInfoImage" class="carInfoImage"
></el-image> ></el-image>
</div> </div>
@@ -106,6 +103,7 @@
<repairUser :is-multiple="false" :username="form.repairName" :userid="form.repairUserId" @change="handleChange"> </repairUser> <repairUser :is-multiple="false" :username="form.repairName" :userid="form.repairUserId" @change="handleChange"> </repairUser>
<div class="actions mt-5"> <div class="actions mt-5">
<el-button v-if="form.problemStatus === '0'" @click="handleSend" type="primary">确定派单</el-button> <el-button v-if="form.problemStatus === '0'" @click="handleSend" type="primary">确定派单</el-button>
<el-button v-if="form.problemStatus === '1'" @click="handleChangeRepairUser" type="primary">变更人员</el-button>
<el-button @click="backRouter">返回</el-button> <el-button @click="backRouter">返回</el-button>
</div> </div>
</div> </div>
@@ -123,32 +121,6 @@
</div> </div>
</template> </template>
<div class="h-full w-full"> <div class="h-full w-full">
<!-- <el-steps space="108px" direction="vertical" :active="activeStop">-->
<!-- <el-step>-->
<!-- <template #title>-->
<!-- <span>完成维修 </span>-->
<!-- </template>-->
<!-- </el-step>-->
<!-- <el-step>-->
<!-- <template #title>-->
<!-- <span>{{ reviewInfo.completeStatus === '0' ? '待维修' : '已维修' }} </span>-->
<!-- </template>-->
<!-- <template #description> {{ reviewInfo.completeTime ?? '维修人员进行维修' }}</template>-->
<!-- </el-step>-->
<!-- <el-step>-->
<!-- <template #title>-->
<!-- <span>{{ reviewInfo.allocateStatus === '0' ? '待分配' : '已分配' }} </span>-->
<!-- </template>-->
<!-- <template #description>{{ reviewInfo.allocateTime ?? '等待物业派单中' }} </template>-->
<!-- </el-step>-->
<!-- <el-step>-->
<!-- <template #title>-->
<!-- <span>已提交维护信息</span>-->
<!-- </template>-->
<!-- <template #description> {{ reviewInfo.submitTime ?? '' }} </template>-->
<!-- </el-step>-->
<!-- </el-steps>-->
<StepTimeline :steps="stepList"> <StepTimeline :steps="stepList">
<template #title="{ item }">{{ item.title }}</template> <template #title="{ item }">{{ item.title }}</template>
<template #subtitle="{ item }">{{ item.subtitle }}</template> <template #subtitle="{ item }">{{ item.subtitle }}</template>
@@ -169,14 +141,10 @@ import PageHeader from '@/components/Pageheader/index.vue';
import { getRepair, updateRepair } from '@/api/system/Repair'; import { getRepair, updateRepair } from '@/api/system/Repair';
import { RepairVO } from '@/api/system/Repair/type'; import { RepairVO } from '@/api/system/Repair/type';
import { listRepairProcess, updateRepairProcess } from '@/api/system/repairProcess'; import { listRepairProcess, updateRepairProcess } from '@/api/system/repairProcess';
import { splitImages } from '@/utils';
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const active = ref(0);
const activeStop = ref(0);
interface formType extends RepairVO { interface formType extends RepairVO {
problemImageUrlList: string[]; problemImageUrlList: string[];
} }
@@ -249,13 +217,12 @@ async function init() {
pageNum: 1 pageNum: 1
}).then((info) => { }).then((info) => {
reviewInfo.value = info.rows[info.rows.length - 1] || null; reviewInfo.value = info.rows[info.rows.length - 1] || null;
console.log(reviewInfo.value);
handleReview(); handleReview();
}); });
}); });
} }
// 处理审核 // 处理审核╬╬
function handleReview() { function handleReview() {
if (reviewInfo.value.submitStatus === '1') { if (reviewInfo.value.submitStatus === '1') {
// 提交完成 // 提交完成
@@ -269,7 +236,7 @@ function handleReview() {
// 分配完成 // 分配完成
stepList.value[1].status = 'completed'; stepList.value[1].status = 'completed';
stepList.value[1].title = '已分配'; stepList.value[1].title = '已分配';
stepList.value[1].subtitle = `${form.value.repairName ?? '---'} ${form.value.repairPhone ?? '---'}`; stepList.value[1].subtitle = `${form.value.repairName ?? ''} ${form.value.repairPhone ?? ''}`;
stepList.value[1].time = reviewInfo.value.allocateTime; stepList.value[1].time = reviewInfo.value.allocateTime;
stepList.value[2].status = 'pending'; stepList.value[2].status = 'pending';
@@ -295,28 +262,43 @@ if (route.query.id) {
/** 派单 */ /** 派单 */
function handleSend() { function handleSend() {
// 已分配 if (form.value.repairUserId && form.value.repairUserId.trim()) {
form.value.problemStatus = '1'; // 已分配
updateRepair(form.value).then(() => {
form.value.problemStatus = '1'; form.value.problemStatus = '1';
reviewInfo.value.allocateTime = new Date().toLocaleString().replaceAll('/', '-'); updateRepair(form.value).then(() => {
if (form.value.repairUserId) { form.value.problemStatus = '1';
reviewInfo.value.allocateStatus = '1'; reviewInfo.value.allocateTime = new Date().toLocaleString().replaceAll('/', '-');
} else { if (form.value.repairUserId) {
reviewInfo.value.allocateStatus = '0'; reviewInfo.value.allocateStatus = '1';
} } else {
updateRepairProcess(reviewInfo.value).then(() => { reviewInfo.value.allocateStatus = '0';
backRouter(); }
updateRepairProcess(reviewInfo.value).then(() => {
backRouter();
});
}); });
}); } else {
ElMessage.warning('请选择维修人员');
}
} }
// 是否变更人员
const isChangeUse = ref(false);
/** 选择维修人员 */ /** 选择维修人员 */
function handleChange(row) { function handleChange(row) {
const oldValue = form.value.repairUserId;
isChangeUse.value = oldValue !== '' && oldValue !== row;
form.value.repairUserId = row; form.value.repairUserId = row;
} }
function handleChangeRepairUser() {
if (form.value.repairUserId && form.value.repairUserId.trim()) {
handleSend();
} else {
ElMessage.warning('请选择维修人员');
}
}
/** 返回 */ /** 返回╬╬╬╬╬╬*/
function backRouter() { function backRouter() {
router.push({ router.push({
path: '/repair/repairlist' path: '/repair/repairlist'
@@ -350,7 +332,7 @@ function handleEdit() {
} }
.carInfo_Item { .carInfo_Item {
display: flex; display: flex;
align-items: center; align-items: flex-start;
font-size: 14px; font-size: 14px;
.label { .label {
font-weight: 600; font-weight: 600;
@@ -359,6 +341,9 @@ function handleEdit() {
padding-right: 10px; padding-right: 10px;
white-space: nowrap; white-space: nowrap;
} }
.main {
word-break: break-word;
}
.carInfoImage { .carInfoImage {
margin: 10px; margin: 10px;
width: 200px; width: 200px;

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :inline="true" label-width="100px" :model="queryParams"> <el-form ref="queryFormRef" :inline="true" label-width="100px" :model="queryParams">
<el-form-item label="维修项目名" prop="projectName"> <el-form-item label="维修项目名" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入维修项目名" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model.trim="queryParams.projectName" placeholder="请输入维修项目名" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -6,7 +6,7 @@
<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="itemName"> <el-form-item label="项目名称" prop="itemName">
<el-input v-model.trim="form.itemName" placeholder="请输入项目名称" /> <el-input maxlength="20" 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">
@@ -38,7 +38,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="费用单价" prop="fixedPrice"> <el-form-item label="费用单价" prop="fixedPrice">
<el-input v-model.trim="form.fixedPrice" :placeholder="placeHolderFun(form.typeId)" /> <el-input maxlength="10" v-model.trim="form.fixedPrice" :placeholder="placeHolderFun(form.typeId)" />
</el-form-item> </el-form-item>
<el-form-item label="计算精度" prop="accuracy"> <el-form-item label="计算精度" prop="accuracy">
<el-select v-model="form.accuracy"> <el-select v-model="form.accuracy">
@@ -57,7 +57,7 @@
</el-radio-group> </el-radio-group>
</el-form-item> --> </el-form-item> -->
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="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>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
<el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button>
@@ -103,7 +103,25 @@ const rules = ref({
itemName: [{ required: true, message: '请输入 项目名称', trigger: 'blur' }], itemName: [{ required: true, message: '请输入 项目名称', trigger: 'blur' }],
typeId: [{ required: true, message: '请选择 收费类型', trigger: 'blur' }], typeId: [{ required: true, message: '请选择 收费类型', trigger: 'blur' }],
billingType: [{ required: true, message: '请输入 计费方式', trigger: 'blur' }], billingType: [{ required: true, message: '请输入 计费方式', trigger: 'blur' }],
fixedPrice: [{ required: true, message: '请输入 费用单价', trigger: 'blur' }], fixedPrice: [
{ required: true, message: '请输入 费用单价', trigger: 'blur' },
{
validator: (_: any, value: string | number, callback: (arg0?: Error) => any) => {
if (value === '' || value === null) {
return callback(new Error('请输入费用单价'));
} else {
const val = Number(value);
if (Number.isNaN(val)) {
return callback(new Error('请输入数字'));
}
if (val <= 0) {
return callback(new Error('请输入大于0的数字'));
}
return callback();
}
}
}
],
formula: [{ required: true, message: '请选择 计费公式', trigger: 'blur' }], formula: [{ required: true, message: '请选择 计费公式', trigger: 'blur' }],
unit: [{ required: true, message: '请选择 计费单位', trigger: 'blur' }], unit: [{ required: true, message: '请选择 计费单位', trigger: 'blur' }],
accuracy: [{ required: true, message: '选择 计算精度', trigger: 'blur' }], accuracy: [{ required: true, message: '选择 计算精度', trigger: 'blur' }],

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" @submit.prevent="handleQuery"> <el-form ref="queryFormRef" :model="queryParams" :inline="true" @submit.prevent="handleQuery">
<el-form-item label="项目名称" prop="itemName"> <el-form-item label="项目名称" prop="itemName">
<el-input v-model="queryParams.itemName" placeholder="请输入项目名称" clearable @keyup.enter.prevent="handleQuery" /> <el-input maxlength="20" v-model="queryParams.itemName" placeholder="请输入项目名称" clearable @keyup.enter.prevent="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" label-width="120" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" label-width="120" :inline="true">
<el-form-item label="收费类型名称" prop="name"> <el-form-item label="收费类型名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入收费类型名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model.trim="queryParams.name" placeholder="请输入收费类型名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>
@@ -60,7 +60,7 @@
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="chargeTypeFormRef" :model="form" :rules="rules" label-width="100px"> <el-form ref="chargeTypeFormRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="收费类型名称" prop="name"> <el-form-item label="收费类型名称" prop="name">
<el-input v-model="form.name" placeholder="请输入收费类型名称" /> <el-input maxlength="20" v-model.trim="form.name" placeholder="请输入收费类型名称" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>

View File

@@ -12,7 +12,14 @@
</el-radio-group> </el-radio-group>
</el-form-item> </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"
placeholder="抄表月份"
v-model="form.recordMonth"
value-format="YYYY-MM"
format="YYYY-MM"
type="month"
/>
</el-form-item> </el-form-item>
<el-form-item label="起止日期" prop="price"> <el-form-item label="起止日期" prop="price">
<el-date-picker <el-date-picker

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="仪表名称" prop="houseId"> <el-form-item label="仪表名称" prop="houseId">
<el-input v-model="queryParams.houseId" placeholder="请输入仪表名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.houseId" placeholder="请输入仪表名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -6,7 +6,7 @@
<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="billName"> <el-form-item label="账单名称" prop="billName">
<el-input v-model.trim="form.billName" placeholder="请输入账单名称" /> <el-input maxlength="30" v-model.trim="form.billName" placeholder="请输入账单名称" />
</el-form-item> </el-form-item>
<el-form-item label="收费项目" prop="chargeItemId"> <el-form-item label="收费项目" prop="chargeItemId">
<el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)"> <el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)">
@@ -109,7 +109,7 @@
/> />
</el-form-item> --> </el-form-item> -->
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="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>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">

View File

@@ -10,7 +10,6 @@
<el-option v-for="(item, index) in chargeItems" :key="index" :value="item.id" :label="item.itemName"></el-option> <el-option v-for="(item, index) in chargeItems" :key="index" :value="item.id" :label="item.itemName"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>
<el-button @click="resetQuery">重置</el-button> <el-button @click="resetQuery">重置</el-button>

File diff suppressed because it is too large Load Diff

View File

@@ -5,23 +5,11 @@
<div v-show="showSearch" class="mb-[10px]"> <div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" label-width="100px" @submit.prevent="handleQuery" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" label-width="100px" @submit.prevent="handleQuery" :model="queryParams" :inline="true">
<!-- <el-form-item label="设备状态" prop="eleStatus"> <el-form-item label="设备编号" prop="deviceCode">
<el-select v-model="queryParams.eleStatus"> <el-input maxlength="25" v-model="queryParams.deviceCode" placeholder="请输入" clearable />
<el-option v-for="(item, index) in com_waterdevice_on_status" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="分合状态" prop="status">
<el-select v-model="queryParams.status">
<el-option
v-for="(item, index) in com_electricity_readrecord_status"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item> -->
<el-form-item label="房屋号" prop="houseName"> <el-form-item label="房屋号" prop="houseName">
<el-input v-model="queryParams.houseName" placeholder="请输入" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.houseName" placeholder="请输入" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -16,10 +16,10 @@
</el-select> </el-select>
</el-form-item> --> </el-form-item> -->
<el-form-item label="设备编号" prop="deviceCode"> <el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="queryParams.deviceCode" placeholder="请输入" clearable /> <el-input maxlength="25" v-model="queryParams.deviceCode" placeholder="请输入" clearable />
</el-form-item> </el-form-item>
<el-form-item label="房屋" prop="houseName"> <el-form-item label="房屋" prop="houseName">
<el-input clearable v-model="queryParams.houseName" placeholder="请输入" /> <el-input maxlength="20" clearable v-model="queryParams.houseName" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>
@@ -207,10 +207,10 @@
<!-- upload file --> <!-- upload file -->
<el-form v-else-if="dialogType === 'Upload'" ref="UploadFileformRef" :model="UploadFileform" :rules="UploadFileformRules" label-width="140px"> <el-form v-else-if="dialogType === 'Upload'" ref="UploadFileformRef" :model="UploadFileform" :rules="UploadFileformRules" label-width="140px">
<el-form-item label="LEN_A" prop="lenA"> <el-form-item label="LEN_A" prop="lenA">
<el-input v-model="UploadFileform.lenA"></el-input> <el-input maxlength="40" v-model="UploadFileform.lenA"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="CRC32_HEX_A" prop="crcA"> <el-form-item label="CRC32_HEX_A" prop="crcA">
<el-input v-model="UploadFileform.crcA"></el-input> <el-input maxlength="40" v-model="UploadFileform.crcA"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="上传 A槽更新 文件" prop="urlA"> <el-form-item label="上传 A槽更新 文件" prop="urlA">
<el-upload <el-upload
@@ -239,10 +239,10 @@
</el-form-item> </el-form-item>
<el-form-item label="LEN_B" prop="lenB"> <el-form-item label="LEN_B" prop="lenB">
<el-input v-model="UploadFileform.lenB"></el-input> <el-input maxlength="40" v-model="UploadFileform.lenB"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="CRC32_HEX_B" prop="crcB"> <el-form-item label="CRC32_HEX_B" prop="crcB">
<el-input v-model="UploadFileform.crcB"></el-input> <el-input maxlength="40" v-model="UploadFileform.crcB"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="上传 B槽更新 文件" prop="urlB"> <el-form-item label="上传 B槽更新 文件" prop="urlB">
<el-upload <el-upload
@@ -624,7 +624,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) {
@@ -649,13 +649,16 @@ function handleUpdate(id: string) {
// 解绑房屋 // 解绑房屋
function handleUnbind(data: WaterDeviceVO) { function handleUnbind(data: WaterDeviceVO) {
waterDeviceUnbind(data.deviceCode) // 提示
.then(() => { proxy?.$modal.confirm('确认解绑房屋吗?').then(() => {
ElMessage.success('解绑成功'); waterDeviceUnbind(data.deviceCode)
}) .then(() => {
.finally(() => { ElMessage.success('解绑成功');
getList(); })
}); .finally(() => {
getList();
});
});
} }
/** 提交按钮 */ /** 提交按钮 */

View File

@@ -1,12 +0,0 @@
<template>
<div class="p-2 h-full flex flex-col">
<pageHeader title="水表管理"></pageHeader>
<div class="flex-1 color-gray flex h-full font-size-6 flex-center">系统还在维护中敬请期待...</div>
</div>
</template>
<script setup lang="ts">
import pageHeader from '@/components/Pageheader/index.vue';
</script>
<style scoped lang="scss"></style>

View File

@@ -8,20 +8,20 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="区域名称" prop="areaName"> <el-form-item label="区域名称" prop="areaName">
<el-input v-model.trim="form.areaName" placeholder="请输入区域名称" /> <el-input maxlength="8" show-word-limit v-model.trim="form.areaName" placeholder="请输入区域名称" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="区域编号" prop="areaCode"> <el-form-item label="区域编号" prop="areaCode">
<el-input v-model.trim="form.areaCode" placeholder="请输入区域编号" /> <el-input maxlength="8" v-model.trim="form.areaCode" placeholder="请输入区域编号" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="区域面积" prop="area"> <el-form-item label="区域面积" prop="area">
<el-input v-model.number="form.area" placeholder="请输入区域面积"> <el-input maxlength="8" v-model.number.trim="form.area" placeholder="请输入区域面积">
<template #suffix></template> <template #suffix></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -29,14 +29,14 @@
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车位数量" prop="parkingCount"> <el-form-item label="车位数量" prop="parkingCount">
<el-input v-model.number="form.parkingCount" placeholder="请输入车位数量" /> <el-input maxlength="5" v-model.number.trim="form.parkingCount" placeholder="请输入车位数量" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="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>
</el-col> </el-col>
</el-row> </el-row>
@@ -69,7 +69,25 @@ const form = ref({
}); });
const rules = ref({ const rules = ref({
areaName: [{ required: true, message: '请输入区域名称', trigger: 'blur' }], areaName: [{ required: true, message: '请输入区域名称', trigger: 'blur' }],
areaCode: [{ required: true, message: '请输入区域编号', trigger: 'blur' }] areaCode: [{ required: true, message: '请输入区域编号', trigger: 'blur' }],
area: [
{ required: true, message: '请输入区域面积', trigger: 'blur' },
{
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
if (value === '' || value === null) {
return callback(new Error('请输入区域面积'));
}
const val = Number(value);
if (Number.isNaN(val)) {
return callback(new Error('请输入数字'));
}
if (val <= 0) {
return callback(new Error('请输入大于0的数字'));
}
return callback();
}
}
]
}); });
const parking = ref(null); const parking = ref(null);

View File

@@ -6,10 +6,10 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="区域名称" prop="areaName"> <el-form-item label="区域名称" prop="areaName">
<el-input v-model="queryParams.areaName" placeholder="请输入区域名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.areaName" placeholder="请输入区域名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="区域编号" prop="areaCode"> <el-form-item label="区域编号" prop="areaCode">
<el-input v-model="queryParams.areaCode" placeholder="请输入区域编号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.areaCode" placeholder="请输入区域编号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -5,49 +5,34 @@
<div class="title">基本信息</div> <div class="title">基本信息</div>
<div class="addBuildingFormBody"> <div class="addBuildingFormBody">
<el-form class="formBody" label-position="left" ref="formRef" :model="form" :rules="rules" label-width="130px"> <el-form class="formBody" label-position="left" ref="formRef" :model="form" :rules="rules" label-width="130px">
<!-- <el-row>
<el-col :span="11">
<el-form-item label="车辆区域" prop="areaId">
<el-select @change="changeAreaList" v-model="form.areaId" placeholder="请选择车辆区域">
<el-option v-for="item in carAreaList" :key="item.id" :label="`${item.areaName}(${item.areaCode})`" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="2"></el-col>
<el-col :span="11">
<el-form-item label="车位编号" prop="parkingId">
<el-select v-model="form.parkingId" placeholder="请选择车位编号">
<el-option v-for="item in parkingList" :key="item.id" :label="item.parkingCode" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-row> -->
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车牌号" prop="carNum" :validate-event="false"> <el-form-item label="车牌号" prop="carNum" :validate-event="false">
<!-- <el-input v-model.trim="form.carNum" placeholder="请输入车牌号" /> --> <el-input
<LicensePlateInput ref="carNumInputRef" required v-model="form.carNum" @change="() => handleValidate()" /> maxlength="10"
v-model.trim="form.carNum"
placeholder="请输入车牌号"
style="text-transform: uppercase; letter-spacing: 2px"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车辆品牌" prop="carBrand"> <el-form-item label="车辆品牌" prop="carBrand">
<el-input v-model.trim="form.carBrand" placeholder="请输入车辆品牌" /> <el-input maxlength="12" v-model.trim="form.carBrand" placeholder="请输入车辆品牌" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车辆型号" prop="carModel"> <el-form-item label="车辆型号" prop="carModel">
<el-input v-model.trim="form.carModel" placeholder="请输入补充车辆型号" /> <el-input maxlength="12" v-model.trim="form.carModel" placeholder="请输入补充车辆型号" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车身颜色" prop="carColor"> <el-form-item label="车身颜色" prop="carColor">
<el-input v-model.trim="form.carColor" placeholder="请输入车身颜色" /> <el-input maxlength="12" v-model.trim="form.carColor" placeholder="请输入车身颜色" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -62,6 +47,7 @@
name="file" name="file"
:headers="headerToken()" :headers="headerToken()"
:show-file-list="false" :show-file-list="false"
:limit="1"
:on-success="handleAvatarSuccess" :on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload" :before-upload="beforeAvatarUpload"
> >
@@ -98,7 +84,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" /> <el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -114,7 +100,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import LicensePlateInput from '@/components/LicensePlateInput/index.vue';
import Holder from '@/components/Holder/index.vue'; import Holder from '@/components/Holder/index.vue';
import PageHeader from '@/components/Pageheader/index.vue'; import PageHeader from '@/components/Pageheader/index.vue';
import { listArea } from '@/api/system/carArea'; import { listArea } from '@/api/system/carArea';
@@ -124,6 +109,7 @@ import { addCar, getCar, updateCar } from '@/api/system/cars';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import AppUser from '@/components/Holder/appUser.vue'; import AppUser from '@/components/Holder/appUser.vue';
import { Plus } from '@element-plus/icons-vue'; import { Plus } from '@element-plus/icons-vue';
import { LicensePlateValidator2 } from '@/utils/Reg2';
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/car/uploadImage'; const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/car/uploadImage';
@@ -154,6 +140,20 @@ const rules = ref({
required: true, required: true,
message: '请输入车牌号码', message: '请输入车牌号码',
trigger: ['blur'] trigger: ['blur']
},
{
validator: (_: any, value: string, callback: any) => {
if (!value) {
callback(new Error('请输入车牌号'));
return;
}
if (!LicensePlateValidator2.isValidPlate(value)) {
callback(new Error('请输入正确的车牌号'));
return;
}
callback();
},
trigger: 'blur'
} }
], ],
carBrand: [{ required: false, message: '请输入车辆品牌', trigger: 'blur' }] carBrand: [{ required: false, message: '请输入车辆品牌', trigger: 'blur' }]

View File

@@ -6,13 +6,13 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="车牌号" prop="carNum"> <el-form-item label="车牌号" prop="carNum">
<el-input v-model.trim="queryParams.carNum" placeholder="请输入车牌号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="12" v-model.trim="queryParams.carNum" placeholder="请输入车牌号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="车辆品牌" prop="carBrand"> <el-form-item label="车辆品牌" prop="carBrand">
<el-input v-model.trim="queryParams.carBrand" placeholder="请输入车辆品牌" clearable @keyup.enter="handleQuery" /> <el-input maxlength="12" v-model.trim="queryParams.carBrand" placeholder="请输入车辆品牌" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="车身颜色" prop="carColor"> <el-form-item label="车身颜色" prop="carColor">
<el-input v-model.trim="queryParams.carColor" placeholder="请输入车身颜色" clearable @keyup.enter="handleQuery" /> <el-input maxlength="12" v-model.trim="queryParams.carColor" placeholder="请输入车身颜色" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -11,16 +11,16 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="设备名称" prop="deviceName"> <el-form-item label="设备名称" prop="deviceName">
<el-input v-model.trim="form.deviceName" placeholder="请输入设备名称" /> <el-input maxlength="20" v-model.trim="form.deviceName" placeholder="请输入设备名称" />
</el-form-item> </el-form-item>
<el-form-item label="设备唯一编号" prop="deviceCode"> <el-form-item label="设备唯一编号" prop="deviceCode">
<el-input v-model.trim="form.deviceCode" placeholder="请输入设备唯一编号" /> <el-input maxlength="20" v-model.trim="form.deviceCode" placeholder="请输入设备唯一编号" />
</el-form-item> </el-form-item>
<el-form-item label="设备型号" prop="deviceModel"> <el-form-item label="设备型号" prop="deviceModel">
<el-input v-model.trim="form.deviceModel" placeholder="请输入设备型号" /> <el-input maxlength="20" v-model.trim="form.deviceModel" placeholder="请输入设备型号" />
</el-form-item> </el-form-item>
<el-form-item label="位置区域" prop="area"> <el-form-item label="位置区域" prop="area">
<el-input type="textarea" :rows="2" v-model.trim="form.area" placeholder="请输入位置区域" /> <el-input maxlength="100" show-word-limit type="textarea" :rows="2" v-model.trim="form.area" placeholder="请输入位置区域" />
</el-form-item> </el-form-item>
<el-form-item label="维护人员" prop="maintainUserIds"> <el-form-item label="维护人员" prop="maintainUserIds">
<repairUser <repairUser
@@ -56,10 +56,10 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="设备保质期" prop="shelfLife"> <el-form-item label="设备保质期" prop="shelfLife">
<el-input v-model.trim="form.shelfLife" placeholder="请输入" /> <el-input maxlength="20" v-model.trim="form.shelfLife" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :row="5" v-model.trim="form.remark" placeholder="请输入" /> <el-input maxlength="200" show-word-limit type="textarea" :row="5" v-model.trim="form.remark" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
<el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button>

View File

@@ -7,10 +7,10 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="设备名称" prop="deviceName"> <el-form-item label="设备名称" prop="deviceName">
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="设备编号" prop="deviceCode"> <el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" label-width="100" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" label-width="100" :model="queryParams" :inline="true">
<el-form-item label="设备分类名称" prop="categoryName"> <el-form-item label="设备分类名称" prop="categoryName">
<el-input v-model="queryParams.categoryName" placeholder="请输入设备分类名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.categoryName" placeholder="请输入设备分类名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>
@@ -56,7 +56,7 @@
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="deviceCategoryFormRef" :model="form" :rules="rules" label-width="120px"> <el-form ref="deviceCategoryFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="设备分类名称" prop="categoryName"> <el-form-item label="设备分类名称" prop="categoryName">
<el-input v-model="form.categoryName" placeholder="请输入设备分类名称" /> <el-input maxlength="20" show-word-limit v-model="form.categoryName" placeholder="请输入设备分类名称" />
</el-form-item> </el-form-item>
<el-form-item label="设备分类状态" prop="status"> <el-form-item label="设备分类状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">

View File

@@ -17,16 +17,16 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="设备名称" prop="deviceName"> <el-form-item label="设备名称" prop="deviceName">
<el-input v-model.trim="form.deviceName" placeholder="请输入设备名称" /> <el-input maxlength="20" v-model.trim="form.deviceName" placeholder="请输入设备名称" />
</el-form-item> </el-form-item>
<el-form-item label="设备编号" prop="deviceCode"> <el-form-item label="设备编号" prop="deviceCode">
<el-input v-model.trim="form.deviceCode" placeholder="请输入设备编号" /> <el-input maxlength="20" v-model.trim="form.deviceCode" placeholder="请输入设备编号" />
</el-form-item> </el-form-item>
<el-form-item label="设备型号" prop="deviceModel"> <el-form-item label="设备型号" prop="deviceModel">
<el-input v-model.trim="form.deviceModel" placeholder="请输入设备型号" /> <el-input maxlength="20" v-model.trim="form.deviceModel" placeholder="请输入设备型号" />
</el-form-item> </el-form-item>
<el-form-item label="位置区域" prop="area"> <el-form-item label="位置区域" prop="area">
<el-input type="textarea" :rows="2" v-model.trim="form.area" placeholder="请输入位置区域" /> <el-input maxlength="100" show-word-limit type="textarea" :rows="2" v-model.trim="form.area" placeholder="请输入位置区域" />
</el-form-item> </el-form-item>
<el-form-item label="维护人员" prop="maintainUserIds"> <el-form-item label="维护人员" prop="maintainUserIds">
<repairUser <repairUser
@@ -58,7 +58,7 @@
</repairUser> </repairUser>
</el-form-item> </el-form-item>
<el-form-item label="故障描述" prop="faultDesc"> <el-form-item label="故障描述" prop="faultDesc">
<el-input type="textarea" :rows="5" v-model.trim="form.faultDesc" placeholder="请输入" /> <el-input maxlength="100" show-word-limit type="textarea" :rows="2" v-model.trim="form.faultDesc" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item label="维修结果" prop="repairResult"> <el-form-item label="维修结果" prop="repairResult">
<el-radio-group v-model.trim="form.repairResult"> <el-radio-group v-model.trim="form.repairResult">
@@ -66,7 +66,7 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" /> <el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
@@ -136,7 +136,7 @@ function init() {
}; };
checkoutuser.value = []; checkoutuser.value = [];
checkoutuser.value = res.data.maintainUserList??[]; checkoutuser.value = res.data.maintainUserList ?? [];
}); });
} }
} }

View File

@@ -6,10 +6,10 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" label-width="100" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" label-width="100" :model="queryParams" :inline="true">
<el-form-item label="设备名称" prop="deviceName"> <el-form-item label="设备名称" prop="deviceName">
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="设备编号" prop="deviceCode"> <el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -10,23 +10,25 @@
<div class="addBuildingFormBody"> <div class="addBuildingFormBody">
<el-form class="formBody" ref="formRef" :model="form" :rules="rules" label-width="100px"> <el-form class="formBody" ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="楼栋名称" prop="buildingName"> <el-form-item label="楼栋名称" prop="buildingName">
<el-input v-model.trim="form.buildingName" placeholder="请输入楼栋名称"> <el-input maxlength="6" show-word-limit v-model.trim="form.buildingName" placeholder="请输入楼栋名称">
<template #append> <template #append>
<span></span> <span></span>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="楼栋朝向" prop="buildToward"> <el-form-item label="楼栋朝向" prop="buildToward">
<el-input v-model.trim="form.buildToward" placeholder="请输入楼栋朝向" /> <el-select v-model="form.buildToward" placeholder="请选择楼栋朝向">
<el-option v-for="item in houseFormat" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="楼高(m)" prop="buildTail"> <el-form-item label="楼高(m)" prop="buildTail">
<el-input v-model.trim="form.buildTall" placeholder="请输入楼高(m)" /> <el-input maxlength="4" v-model.trim="form.buildTall" placeholder="请输入楼高(m)" />
</el-form-item> </el-form-item>
<el-form-item label="楼栋结构" prop="buildStructure"> <el-form-item label="楼栋结构" prop="buildStructure">
<el-input v-model.trim="form.buildStructure" placeholder="请输入楼栋结构" /> <el-input maxlength="30" v-model.trim="form.buildStructure" placeholder="请输入楼栋结构" />
</el-form-item> </el-form-item>
<el-form-item label="楼层" prop="floorCount"> <el-form-item label="楼层" prop="floorCount">
<el-input-number :min="1" v-model.trim="form.floorCount" placeholder="楼层数" /> <el-input-number :max="200" :min="1" v-model.trim="form.floorCount" placeholder="楼层数" />
</el-form-item> </el-form-item>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
<el-button type="primary" @click="submitForm">确定</el-button> <el-button type="primary" @click="submitForm">确定</el-button>
@@ -46,7 +48,7 @@ import { useRouter } from 'vue-router';
import { useHouseStore } from '@/store/modules/house'; import { useHouseStore } from '@/store/modules/house';
const houseStore = useHouseStore(); const houseStore = useHouseStore();
const houseFormat = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const formRef = ref(); const formRef = ref();

View File

@@ -10,7 +10,7 @@
<el-option v-for="item in houseStore.currentBuildingInfoList" :key="item.id" :label="item.buildingName" :value="item.id" /> <el-option v-for="item in houseStore.currentBuildingInfoList" :key="item.id" :label="item.buildingName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="房屋用途" prop="houseUseTypeId"> <el-form-item label="房屋类型" prop="houseUseTypeId">
<el-select v-model="form.houseUseTypeId" placeholder="请选择"> <el-select v-model="form.houseUseTypeId" placeholder="请选择">
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
@@ -25,40 +25,39 @@
<el-option v-for="item in floors" :key="item.no" :label="item.name" :value="item.no" /> <el-option v-for="item in floors" :key="item.no" :label="item.name" :value="item.no" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="房间号" prop="houseNo"> <el-form-item label="房间号" prop="houseNo">
<el-input v-model.trim="form.houseNo" placeholder="请输入房间号" /> <el-input maxlength="15" v-model.trim="form.houseNo" placeholder="请输入房间号" />
</el-form-item> </el-form-item>
<el-form-item label="建筑面积" prop="houseArea"> <el-form-item label="建筑面积" prop="houseArea">
<div class="unitBox flex align-center"> <div class="unitBox flex align-center">
<el-input v-model.trim="form.houseArea" placeholder="请输入建筑面积" /> <el-input maxlength="8" v-model.trim.number="form.houseArea" placeholder="请输入建筑面积" />
<span></span> <span></span>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="套内面积" prop="internalArea"> <el-form-item label="套内面积" prop="internalArea">
<div class="unitBox flex align-center"> <div class="unitBox flex align-center">
<el-input v-model.trim="form.internalArea" placeholder="请输入套内面积" /> <el-input maxlength="8" v-model.trim.number="form.internalArea" placeholder="请输入套内面积" />
<span></span> <span></span>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="公摊面积" prop="shareArea"> <el-form-item label="公摊面积" prop="shareArea">
<div class="unitBox flex align-center"> <div class="unitBox flex align-center">
<el-input v-model.trim="form.shareArea" placeholder="请输入公摊面积" /> <el-input maxlength="8" v-model.trim.number="form.shareArea" placeholder="请输入公摊面积" />
<span></span> <span></span>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="房屋户型"> <el-form-item label="房屋户型">
<div class="houseTypebox"> <div class="houseTypebox">
<el-input v-model.trim="housetype[0]" placeholder="房间" /> <el-input maxlength="3" v-model.trim="housetype[0]" placeholder="房间" @change="changeHouseType($event, 0)" />
<span></span> <span></span>
<el-input v-model.trim="housetype[1]" placeholder="客厅" /> <el-input maxlength="3" v-model.trim="housetype[1]" placeholder="客厅" @change="changeHouseType($event, 1)" />
<span></span> <span></span>
<el-input v-model.trim="housetype[2]" placeholder="卫生间" /> <el-input maxlength="3" v-model.trim="housetype[2]" placeholder="卫生间" @change="changeHouseType($event, 2)" />
<span></span> <span></span>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="车位号" prop="parkingIds"> <el-form-item label="车位号" prop="parkingIds">
<el-select @change="(val) => console.log(val)" multiple v-model="form.parkingIds" class="m-2" placeholder="请选择车位号"> <el-select multiple v-model="form.parkingIds" class="m-2" placeholder="请选择车位号">
<el-option v-for="(item, index) in parkinglist" :key="index" :label="item.parkingName" :value="item.id" /> <el-option v-for="(item, index) in parkinglist" :key="index" :label="item.parkingName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -97,7 +96,7 @@ const form = ref<addHouseType>({
houseUseTypeId: '', // 房屋用途 houseUseTypeId: '', // 房屋用途
unitNoId: '', unitNoId: '',
floorNo: '', floorNo: '',
houseNo: '', // 房 houseNo: '', // 房
houseArea: '', //建筑面积 houseArea: '', //建筑面积
internalArea: '', //套内面积 internalArea: '', //套内面积
shareArea: '', // 公摊面积 shareArea: '', // 公摊面积
@@ -110,12 +109,79 @@ const rules = ref({
unitNoId: [{ required: true, message: '请选择单元', trigger: 'blur' }], unitNoId: [{ required: true, message: '请选择单元', trigger: 'blur' }],
floorNo: [{ required: true, message: '请选择楼层', trigger: 'blur' }], floorNo: [{ required: true, message: '请选择楼层', trigger: 'blur' }],
houseUseTypeId: [{ required: true, message: '请选择房屋用途', trigger: 'blur' }], houseUseTypeId: [{ required: true, message: '请选择房屋用途', trigger: 'blur' }],
houseArea: [{ required: true, message: '请输入建筑面积', trigger: 'blur' }],
buildingName: [{ required: true, message: '请输入房间号', trigger: 'blur' }], buildingName: [{ required: true, message: '请输入房间号', trigger: 'blur' }],
houseNo: [{ required: true, message: '请输入房间号', trigger: 'blur' }], houseNo: [{ required: true, message: '请输入房间号', trigger: 'blur' }],
buildingArea: [{ required: true, message: '请输入建筑面积', trigger: 'blur' }], buildingArea: [{ required: true, message: '请输入建筑面积', trigger: 'blur' }],
internalFloorArea: [{ required: true, message: '请输入套内面积', trigger: 'blur' }], internalFloorArea: [{ required: true, message: '请输入套内面积', trigger: 'blur' }],
CommonArea: [{ required: true, message: '请输入公摊面积', trigger: 'blur' }] CommonArea: [{ required: true, message: '请输入公摊面积', trigger: 'blur' }],
houseArea: [
{
required: true,
message: '请输入建筑面积',
trigger: 'blur'
},
{
validator: (_, value, callback) => {
if (value === '' || value === null) {
return callback(new Error('请输入建筑面积'));
} else {
const val = Number(value);
if (Number.isNaN(val)) {
return callback(new Error('请输入数字'));
}
if (val < 0 || val > 99999.99) {
ElMessage.error('房屋面积超出合法范围');
return;
}
return callback();
}
}
}
],
internalArea: [
{
required: false,
message: '请输入套内面积',
trigger: 'blur'
},
{
validator: (rule, value, callback) => {
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();
}
}
],
shareArea: [
{
required: false,
message: '请输入公摊面积',
trigger: 'blur'
},
{
validator: (rule, value, callback) => {
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();
}
}
]
}); });
const housetype = ref([]); const housetype = ref([]);
const units = ref([]); const units = ref([]);
@@ -168,7 +234,7 @@ async function geteditinfo() {
houseId: res.data.houseId, // 房屋id houseId: res.data.houseId, // 房屋id
unitNoId: res.data.unitNoId, unitNoId: res.data.unitNoId,
floorNo: res.data.floorNo, floorNo: res.data.floorNo,
houseNo: res.data.houseNo, // 房 houseNo: res.data.houseNo, // 房
houseArea: res.data.houseArea, //建筑面积 houseArea: res.data.houseArea, //建筑面积
internalArea: res.data.internalArea, //套内面积 internalArea: res.data.internalArea, //套内面积
storeroomId: res.data.storeroomId, //储藏室 storeroomId: res.data.storeroomId, //储藏室
@@ -231,6 +297,16 @@ function getStoreRoomlist() {
}); });
} }
// 客厅卫不能小于0个
function changeHouseType(val: string, index: number) {
const num = Number(val);
if (Number.isNaN(num)) {
housetype.value[index] = '0';
} else {
housetype.value[index] = num.toFixed(0);
}
}
const submitForm = () => { const submitForm = () => {
formRef.value?.validate(async (valid: boolean) => { formRef.value?.validate(async (valid: boolean) => {
if (valid) { if (valid) {
@@ -259,6 +335,7 @@ const submitForm = () => {
} }
}); });
}; };
const cancelForm = () => { const cancelForm = () => {
formRef?.value.resetFields(); formRef?.value.resetFields();
router.back(); router.back();

View File

@@ -3,7 +3,7 @@
<div class="TableBox p-5" v-if="houseStore.currentHouseInfoList !== null"> <div class="TableBox p-5" v-if="houseStore.currentHouseInfoList !== null">
<el-checkbox-group @change="handleChangeCheckhouses" v-model="houseStore.checkoutHouses"> <el-checkbox-group @change="handleChangeCheckhouses" v-model="houseStore.checkoutHouses">
<el-table border :data="houseStore.currentFloorInfoList"> <el-table border :data="houseStore.currentFloorInfoList">
<el-table-column align="center" fixed label="楼层\单元" max-width="100"> <el-table-column align="center" fixed label="楼层\单元" min-width="90">
<template #default="{ row }"> <template #default="{ row }">
<span>{{ row }}</span> <span>{{ row }}</span>
</template> </template>

View File

@@ -1,20 +1,6 @@
<template> <template>
<div class="UnitBox"> <div class="UnitBox">
<div class="Unit_top flex align-center justify-between"> <div class="Unit_top flex align-center justify-between">
<!-- <div>
<span class="text-size-16px text-color-black text-widget-bold mr-30px">
<strong>{{ houseStore.currentBuildingInfo?.buildingName }}</strong>
</span>
<span class="mr-15px" v-if="houseStore.currentBuildingInfo && houseStore.currentBuildingInfo?.buildToward"
>楼栋朝向:{{ houseStore.currentBuildingInfo?.buildToward ? `${houseStore.currentBuildingInfo?.buildToward}(m)` : '--' }}</span
>
<span class="mr-15px" v-if="houseStore.currentBuildingInfo && houseStore.currentBuildingInfo?.buildTall"
>楼高{{ houseStore.currentBuildingInfo?.buildTall ? `${houseStore.currentBuildingInfo?.buildTall}(m)` : '--' }}</span
>
<span class="mr-15px" v-if="houseStore.currentBuildingInfo && houseStore.currentBuildingInfo?.buildStructure"
>楼栋结构{{ houseStore.currentBuildingInfo?.buildStructure ? `${houseStore.currentBuildingInfo?.buildStructure}(m)` : '--' }}
</span>
</div> -->
<div style="text-wrap: nowrap"> <div style="text-wrap: nowrap">
<span class="text-size-16px text-color-black text-widget-bold mr-30px"> <span class="text-size-16px text-color-black text-widget-bold mr-30px">
<strong>{{ houseStore.currentBuildingInfo?.buildingName }}</strong> <strong>{{ houseStore.currentBuildingInfo?.buildingName }}</strong>
@@ -36,7 +22,7 @@
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
<div class="searchbox flex flex-items-center"> <div class="searchbox flex flex-items-center">
<el-input v-model="housename" class="searchinput" placeholder="请输入房屋号"></el-input> <el-input v-model="housename" maxlength="15" class="searchinput" placeholder="请输入房屋号"></el-input>
<el-button style="margin-left: 10px" type="primary" @click="handleSearchHouse">搜索</el-button> <el-button style="margin-left: 10px" type="primary" @click="handleSearchHouse">搜索</el-button>
<el-button @click="reset">重置</el-button> <el-button @click="reset">重置</el-button>
</div> </div>
@@ -49,10 +35,9 @@
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="unitNoFormRef" :model="form" :rules="rules" label-width="80px"> <el-form ref="unitNoFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="单元名称" prop="name"> <el-form-item label="单元名称" prop="name">
<el-input v-model="form.name" placeholder="请输入单元名称" /> <el-input maxlength="6" show-word-limit v-model.trim="form.name" placeholder="请输入单元名称" />
</el-form-item> </el-form-item>
<el-form-item label="楼栋" prop="buildingId"> <el-form-item label="楼栋" prop="buildingId">
<!-- <el-input v-model="form.buildingId" placeholder="请输入楼栋" /> -->
<el-select v-model="form.buildingId" placeholder="请选择"> <el-select v-model="form.buildingId" placeholder="请选择">
<el-option v-for="item in houseStore.currentBuildingInfoList" :key="item.id" :label="item.buildingName" :value="item.id" /> <el-option v-for="item in houseStore.currentBuildingInfoList" :key="item.id" :label="item.buildingName" :value="item.id" />
</el-select> </el-select>

View File

@@ -14,7 +14,7 @@
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="业主姓名" prop="rentalName"> <el-form-item label="业主姓名" prop="rentalName">
<el-input :disabled="HasName" v-model="form.rentalName" placeholder="请输入业主姓名" /> <el-input maxlength="20" v-model.trim="form.rentalName" placeholder="请输入业主姓名" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -22,24 +22,24 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="租赁状态" prop="rentalStatus"> <el-form-item label="租赁状态" prop="rentalStatus">
<el-select v-model.number="form.rentalStatus" placeholder="请选择"> <el-select v-model="form.rentalStatus" placeholder="请选择">
<el-option v-for="(item, index) in com_rental_status" :key="index" :label="item.label" :value="Number(item.value)" /> <el-option v-for="(item, index) in com_rental_status" :key="index" :label="item.label" :value="Number(item.value)" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="房屋用途" prop="houseUse"> <!-- <el-form-item label="房屋用途" prop="houseUse">-->
<el-select v-model.number="form.houseUse" placeholder="请选择"> <!-- <el-select v-model.trim="form.houseUse" placeholder="请选择">-->
<el-option v-for="(item, index) in com_house_use" :key="index" :label="item.label" :value="item.value" /> <!-- <el-option v-for="(item, index) in houseUseTypeList" :key="index" :label="item.name" :value="item.id" />-->
</el-select> <!-- </el-select>-->
</el-form-item> <!-- </el-form-item>-->
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="租金" prop="rent"> <el-form-item label="租金" prop="rent">
<el-input v-model="form.rent" placeholder="请输入租金"> <el-input maxlength="8" v-model.number.trim="form.rent" placeholder="请输入租金">
<template #suffix></template> <template #suffix></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -57,7 +57,7 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="房屋朝向" prop="type"> <el-form-item label="房屋朝向" prop="type">
<el-select v-model.number="form.houseFace" placeholder="请选择"> <el-select v-model="form.houseFace" placeholder="请选择">
<el-option v-for="(item, index) in houseFormat" :key="index" :label="item" :value="item" /> <el-option v-for="(item, index) in houseFormat" :key="index" :label="item" :value="item" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -65,7 +65,7 @@
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="房屋面积" prop="houseArea"> <el-form-item label="房屋面积" prop="houseArea">
<el-input v-model.number="form.houseArea" placeholder="请输入房屋面积"> <el-input maxlength="8" v-model.trim="form.houseArea" placeholder="请输入房屋面积">
<template #suffix> </template> <template #suffix> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -74,7 +74,7 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="房屋楼层" prop="floorNo"> <el-form-item label="房屋楼层" prop="floorNo">
<el-input-number v-model.number="form.floorNo" placeholder="请输入" /> <el-input-number :max="1000" v-model.number.trim="form.floorNo" placeholder="请输入" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
@@ -125,6 +125,8 @@
:multiple="true" :multiple="true"
:auto-upload="false" :auto-upload="false"
list-type="picture-card" list-type="picture-card"
:limit="9"
:on-exceed="handleExceed"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:on-remove="handleRemove" :on-remove="handleRemove"
:on-success="handleAvatarSuccess" :on-success="handleAvatarSuccess"
@@ -143,27 +145,27 @@
</el-row> </el-row>
<el-form-item label="补充房屋信息" prop="remark"> <el-form-item label="补充房屋信息" prop="remark">
<el-input type="textarea" :rows="5" v-model.number="form.supInfo" placeholder="请输入补充房屋信息" /> <el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model.trim="form.supInfo" placeholder="请输入补充房屋信息" />
</el-form-item> </el-form-item>
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="手机号" prop="phone"> <el-form-item label="手机号" prop="phone">
<el-input v-model.number="form.phone" placeholder="请输入手机号码" /> <el-input v-model.number.trim="form.phone" placeholder="请输入手机号码" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="微信" prop="vx"> <el-form-item label="微信" prop="vx">
<el-input v-model.number="form.vx" placeholder="请输入微信号码" /> <el-input maxlength="11" v-model.trim="form.vx" placeholder="请输入微信号码" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="邮箱" prop="email"> <!-- <el-form-item label="邮箱" prop="email">-->
<el-input v-model.number="form.email" placeholder="请输入邮箱" /> <!-- <el-input v-model.trim="form.email" placeholder="请输入邮箱" />-->
</el-form-item> <!-- </el-form-item>-->
</el-col> </el-col>
</el-row> </el-row>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
@@ -187,6 +189,7 @@ import { validator } from '@/utils/Reg';
import { useHouseStore } from '@/store/modules/house'; import { useHouseStore } from '@/store/modules/house';
import { listHouseFacilities } from '@/api/system/HouseFacilities'; import { listHouseFacilities } from '@/api/system/HouseFacilities';
import { Plus } from '@element-plus/icons-vue'; import { Plus } from '@element-plus/icons-vue';
import { listHouseUseType_add_house } from '@/api/system/houseUse';
const houseStore = useHouseStore(); const houseStore = useHouseStore();
@@ -194,13 +197,14 @@ const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/houseRental/uploadImages
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_rental_status } = toRefs<any>(proxy?.useDict('com_rental_status')); const { com_rental_status } = toRefs<any>(proxy?.useDict('com_rental_status'));
const { com_house_use } = toRefs<any>(proxy?.useDict('com_house_use')); // const { com_house_use } = toRefs<any>(proxy?.useDict('com_house_use'));&╬╬╥
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
const formRef = ref(); const formRef = ref();
const houseFormat = ['东', '西', '南', '北']; // 房屋朝向
const houseFormat = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
const form = ref({ const form = ref({
id: null, id: null,
houseId: null, houseId: null,
@@ -209,15 +213,15 @@ const form = ref({
houseFace: '', // 房屋朝向 houseFace: '', // 房屋朝向
rentalType: '0', // 整租合租 rentalType: '0', // 整租合租
phone: null, //手机号 phone: null, //手机号
houseArea: null, // 房屋面积 houseArea: 0, // 房屋面积
floorNo: null, //楼层号 floorNo: 1, //楼层号
inTime: '', //入住时间 inTime: '', //入住时间
facilities: '', //房屋设施 facilities: '', //房屋设施
houseImageUrl: '', //房屋图片 houseImageUrl: '', //房屋图片
supInfo: '', //补充租房信息 supInfo: '', //补充租房信息
vx: '', //微信 vx: '', //微信
houseUse: '0', //房屋用途 houseUse: '', //房屋用途
rentalStatus: 0, //租赁状态 rentalStatus: 1, //租赁状态
buildingId: null, //楼栋id buildingId: null, //楼栋id
unitNoId: null, //单元id unitNoId: null, //单元id
email: '' //邮箱 email: '' //邮箱
@@ -233,6 +237,59 @@ const rules = ref({
message: '请输入正确的手机号码', message: '请输入正确的手机号码',
trigger: 'blur' trigger: 'blur'
} }
],
email: [
{ required: false, message: '请输入邮箱', trigger: 'blur' },
{
validator: (_: any, val: string | number) => {
if (val === '') {
return true;
}
return validator(val, 'email');
},
message: '请输入正确的邮箱',
trigger: 'blur'
}
],
rent: [
{
required: false,
message: '请输入正确的租金',
trigger: 'blur'
},
{
validator: (_: any, val: string | number, callback: (arg0?: Error) => void) => {
if (val === '' || val === null) {
return callback();
}
if (validator(val, 'money')) {
return callback();
}
return callback(new Error('请输入正确的租金'));
}
}
],
houseArea: [
{
required: false,
message: '请输入房屋面积',
trigger: 'blur'
},
{
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
if (value === '' || value === null || value === 0) {
return callback(new Error('请输入房屋面积'));
}
const val = Number(value);
if (Number.isNaN(val)) {
return callback(new Error('请输入数字'));
}
if (val < 0) {
return callback(new Error('房屋面积不能小于0'));
}
return callback();
}
}
] ]
}); });
// ! 编辑租赁-================================================================================= // ! 编辑租赁-=================================================================================
@@ -265,7 +322,14 @@ async function getTreeData() {
} }
getTreeData(); getTreeData();
const HasName = ref(false); const houseUseTypeList = ref([]);
function getHouseUseType() {
listHouseUseType_add_house().then((res) => {
houseUseTypeList.value = res.data;
});
}
getHouseUseType();
// 获取房屋 // 获取房屋
function handleChange(val: CascaderValue) { function handleChange(val: CascaderValue) {
userHousePath.value = val; userHousePath.value = val;
@@ -273,11 +337,10 @@ function handleChange(val: CascaderValue) {
form.value.rentalName = ''; form.value.rentalName = '';
if (val[2]) { if (val[2]) {
getHouseOwnUser(val[2]).then((res) => { getHouseOwnUser(val[2]).then((res) => {
if (res.msg) { if (res.msg.trim()) {
form.value.rentalName = res.msg; form.value.rentalName = res.msg.trim();
HasName.value = true;
} else { } else {
HasName.value = false; form.value.rentalName = '';
} }
}); });
} }
@@ -304,6 +367,9 @@ const handleChangeFile = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
} }
fileList.value = uploadFiles; fileList.value = uploadFiles;
}; };
const handleExceed = () => {
ElMessage.warning('最多上传9张图片');
};
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => { const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!; dialogImageUrl.value = uploadFile.url!;
dialogVisible.value = true; dialogVisible.value = true;

View File

@@ -6,13 +6,13 @@
<el-card> <el-card>
<div class="h-full flex flex-align-center"> <div class="h-full flex flex-align-center">
<el-form label-width="120px" ref="queryFormRef" :model="queryParams" :inline="true"> <el-form label-width="120px" ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="房屋用途" prop="houseUse"> <el-form-item label="房屋类型" prop="houseUse">
<el-select v-model="queryParams.houseUse" placeholder="选择房屋用途" style="width: 240px"> <el-select v-model="queryParams.houseUse" placeholder="选择房屋类型" style="width: 240px">
<el-option v-for="item in com_house_use" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="发布人" prop="rentalName"> <el-form-item label="发布人" prop="rentalName">
<el-input v-model="queryParams.rentalName" placeholder="请输入" clearable @keyup.enter="handleQuery" /> <el-input maxlength="15" v-model="queryParams.rentalName" placeholder="请输入" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>
@@ -51,9 +51,10 @@
<el-table-column label="发布人" align="center" prop="rentalName" /> <el-table-column label="发布人" align="center" prop="rentalName" />
<el-table-column label="联系方式" align="center" prop="phone" /> <el-table-column label="联系方式" align="center" prop="phone" />
<el-table-column label="发布时间" align="center" prop="pubTime" /> <el-table-column label="发布时间" align="center" prop="pubTime" />
<el-table-column label="房屋用途" align="center" prop="houseUse"> <el-table-column label="房屋类型" align="center" prop="houseUse">
<template #default="{ row }"> <template #default="{ row }">
<DictTag :options="com_house_use" :value="row.houseUse"></DictTag> <!-- <DictTag :options="com_house_use" :value="row.houseUse"></DictTag>-->
<span>{{ handleHouseUse(row.houseUse) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="租赁方式" align="center" prop="rentalType"> <el-table-column label="租赁方式" align="center" prop="rentalType">
@@ -80,6 +81,7 @@ import Pageheader from '@/components/Pageheader/index.vue';
import { listHouseRental, delHouseRental } from '@/api/system/houseRental/index'; import { listHouseRental, delHouseRental } from '@/api/system/houseRental/index';
import { HouseRentalVO, HouseRentalQuery, HouseRentalForm } from '@/api/system/houseRental/type'; import { HouseRentalVO, HouseRentalQuery, HouseRentalForm } from '@/api/system/houseRental/type';
import { checkPermi } from '@/utils/permission'; import { checkPermi } from '@/utils/permission';
import { listHouseUseType_add_house } from '@/api/system/houseUse';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_house_use } = toRefs<any>(proxy?.useDict('com_house_use')); const { com_house_use } = toRefs<any>(proxy?.useDict('com_house_use'));
@@ -229,8 +231,19 @@ const handleDelete = async (row?: HouseRentalVO) => {
await getList(); await getList();
}; };
const houseUseTypeList = ref([]);
function getHouseUseType() {
listHouseUseType_add_house().then((res) => {
houseUseTypeList.value = res.data;
});
}
function handleHouseUse(houseUser: string) {
const item = houseUseTypeList.value.find((item) => item.id === houseUser);
return item?.name || '';
}
onMounted(() => { onMounted(() => {
getList(); getList();
getHouseUseType();
}); });
</script> </script>

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="用途名称" prop="name"> <el-form-item label="用途名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入用途名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.name" placeholder="请输入用途名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -42,7 +42,7 @@
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="houseUseTypeFormRef" :model="form" :rules="rules" label-width="80px"> <el-form ref="houseUseTypeFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="用途名称" prop="name"> <el-form-item label="用途名称" prop="name">
<el-input v-model="form.name" placeholder="请输入用途名称" /> <el-input maxlength="20" show-word-limit v-model="form.name" placeholder="请输入用途名称" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>

View File

@@ -6,10 +6,10 @@
<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="itemName"> <el-form-item label="项目名称" prop="itemName">
<el-input v-model.trim="form.itemName" placeholder="请输入项目名称" /> <el-input maxlength="20" v-model.trim="form.itemName" placeholder="请输入项目名称" />
</el-form-item> </el-form-item>
<el-form-item label="巡检标准" prop="inspectionStandard"> <el-form-item label="巡检标准" prop="inspectionStandard">
<el-input type="textarea" :rows="5" v-model.trim="form.inspectionStandard" placeholder="请输入巡检标准" /> <el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model.trim="form.inspectionStandard" placeholder="请输入巡检标准" />
</el-form-item> </el-form-item>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
<el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button>

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="项目名称" prop="itemName"> <el-form-item label="项目名称" prop="itemName">
<el-input v-model="queryParams.itemName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.itemName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -8,7 +8,7 @@
<div class="bodyBox"> <div class="bodyBox">
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" label-position="right"> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px" label-position="right">
<el-form-item label="巡检计划名称" prop="planName"> <el-form-item label="巡检计划名称" prop="planName">
<el-input v-model="form.planName" placeholder="请输入"></el-input> <el-input maxlength="20" v-model.trim="form.planName" placeholder="请输入"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="任务时间"> <el-form-item label="任务时间">
@@ -30,9 +30,6 @@
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="任务时间段"> <el-form-item label="任务时间段">
<!-- <el-select v-model="form.taskTime" placeholder="选择任务时间段" style="width: 100%">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select> -->
<div v-for="(_, index) in taskTime" :key="index" style="display: flex; align-items: center; margin-top: 10px"> <div v-for="(_, index) in taskTime" :key="index" style="display: flex; align-items: center; margin-top: 10px">
<el-time-picker <el-time-picker
v-model="taskTime[index]" v-model="taskTime[index]"
@@ -44,14 +41,6 @@
end-placeholder="结束时间" end-placeholder="结束时间"
style="width: 100%" style="width: 100%"
/> />
<!-- <el-button v-if="taskTime.length > 1" icon="Minus" circle style="margin-left: 10px" @click="removeTaskTime(index)"></el-button>
<el-button
v-if="taskTime.length === index + 1 && taskTime.length <= 8"
icon="Plus"
circle
style="margin-left: 10px"
@click="addTaskTime"
></el-button> -->
</div> </div>
</el-form-item> </el-form-item>
@@ -84,9 +73,7 @@ import { ref } from 'vue';
import { addPlan, getPlan, updatePlan } from '@/api/system/InspectionPlan'; import { addPlan, getPlan, updatePlan } from '@/api/system/InspectionPlan';
import { Check } from '@element-plus/icons-vue'; import { Check } from '@element-plus/icons-vue';
import MapWrapper from '@/components/Map/index.vue'; import MapWrapper from '@/components/Map/index.vue';
import { PointVO } from '@/api/system/InspectionPoint/type';
import { LngLat } from '@/components/Map/type'; import { LngLat } from '@/components/Map/type';
import { PlanVO } from '@/api/system/InspectionPlan/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_inspection_remind_tiime } = toRefs<any>(proxy?.useDict('com_inspection_remind_tiime')); const { com_inspection_remind_tiime } = toRefs<any>(proxy?.useDict('com_inspection_remind_tiime'));
@@ -186,7 +173,7 @@ function handleChangeMap(val: string) {
const find = playlist.value.find((item) => item.id === val); const find = playlist.value.find((item) => item.id === val);
if (!find) return; if (!find) return;
if (find.points && find.points.length > 0) { if (find.points && find.points.length > 0) {
const pointMap = new Map(find.points.map((p) => [p.id, p])); const pointMap = new Map<string, { location: string; pointName: string; id: string }>(find.points.map((p) => [p.id, p]));
const totalPointsList = find.totalPoints.split(',').filter(Boolean); const totalPointsList = find.totalPoints.split(',').filter(Boolean);
if (totalPointsList.length > 0) { if (totalPointsList.length > 0) {
totalPointsList.forEach((item) => { totalPointsList.forEach((item) => {

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" label-width="100px" :model="queryParams" @submit.prevent="handleQuery" :inline="true"> <el-form ref="queryFormRef" label-width="100px" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<el-form-item label="巡检计划名称" prop="planName"> <el-form-item label="巡检计划名称" prop="planName">
<el-input v-model="queryParams.planName" placeholder="请输入巡检计划名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.planName" placeholder="请输入巡检计划名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -6,7 +6,7 @@
<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="pointName"> <el-form-item label="巡检点名称" prop="pointName">
<el-input v-model.trim="form.pointName" placeholder="请输入巡检点名称" /> <el-input maxlength="20" v-model.trim="form.pointName" placeholder="请输入巡检点名称" />
</el-form-item> </el-form-item>
<el-form-item label="巡检项目" prop="itemId"> <el-form-item label="巡检项目" prop="itemId">
<div class="itemBox"> <div class="itemBox">

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form label-width="100px" ref="queryFormRef" @submit.prevent="handleQuery" :model="queryParams" :inline="true"> <el-form label-width="100px" ref="queryFormRef" @submit.prevent="handleQuery" :model="queryParams" :inline="true">
<el-form-item label="巡检点名称" prop="pointName"> <el-form-item label="巡检点名称" prop="pointName">
<el-input v-model="queryParams.pointName" placeholder="请输入巡检点名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.pointName" placeholder="请输入巡检点名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -21,7 +21,7 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="任务名称" prop="taskName"> <el-form-item label="任务名称" prop="taskName">
<el-input v-model="queryParams.taskName" placeholder="请输入任务名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.taskName" placeholder="请输入任务名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -6,7 +6,7 @@
<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="routeName"> <el-form-item label="巡检路线名称" prop="routeName">
<el-input v-model.trim="form.routeName" placeholder="请输入巡检路线名称" /> <el-input maxlength="20" v-model.trim="form.routeName" placeholder="请输入巡检路线名称" />
</el-form-item> </el-form-item>
<el-form-item label="巡检点"> <el-form-item label="巡检点">
<div class="itemBox"> <div class="itemBox">

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" label-width="120px" @submit.prevent="handleQuery" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" label-width="120px" @submit.prevent="handleQuery" :model="queryParams" :inline="true">
<el-form-item label="巡检路线名称" prop="routeName"> <el-form-item label="巡检路线名称" prop="routeName">
<el-input v-model="queryParams.routeName" placeholder="请输入巡检路线名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.routeName" placeholder="请输入巡检路线名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -8,7 +8,7 @@
<div class="bodyBox"> <div class="bodyBox">
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" label-position="right"> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px" label-position="right">
<el-form-item label="任务名称" prop="taskName"> <el-form-item label="任务名称" prop="taskName">
<el-input v-model="form.taskName" placeholder="请输入"></el-input> <el-input maxlength="20" v-model="form.taskName" placeholder="请输入"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="巡检人员" prop="inspectorId"> <el-form-item label="巡检人员" prop="inspectorId">
<div class="inspectorIdsBox"> <div class="inspectorIdsBox">
@@ -18,7 +18,14 @@
<el-icon><Delete /></el-icon> <el-icon><Delete /></el-icon>
</i> </i>
</div> </div>
<RepairUser @change="handleUserChange" returnvalue="*" :is-multiple="true" user-type="inspection" ref="RepairUserRef"> <RepairUser
titleName="巡检人员"
@change="handleUserChange"
returnvalue="*"
:is-multiple="true"
user-type="inspection"
ref="RepairUserRef"
>
<template #default> <template #default>
<div @click="handleAddUser" class="inspector_items add flex flex-items-center justify-center"> <div @click="handleAddUser" class="inspector_items add flex flex-items-center justify-center">
<el-icon><Plus /></el-icon> <el-icon><Plus /></el-icon>

View File

@@ -11,7 +11,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="巡检任务名称" prop="taskName"> <el-form-item label="巡检任务名称" prop="taskName">
<el-input v-model="queryParams.taskName" placeholder="请输入巡检任务名称" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.taskName" placeholder="请输入巡检任务名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="实际开始时间" prop="taskTime"> <!-- <el-form-item label="实际开始时间" prop="taskTime">
<el-date-picker <el-date-picker

View File

@@ -16,7 +16,7 @@
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车位编号" prop="parkingCode"> <el-form-item label="车位编号" prop="parkingCode">
<el-input v-model.trim="form.parkingCode" placeholder="请输入车位编号" /> <el-input maxlength="20" v-model.trim="form.parkingCode" placeholder="请输入车位编号" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -24,13 +24,13 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="车位面积" prop="parkingArea"> <el-form-item label="车位面积" prop="parkingArea">
<el-input v-model.number="form.parkingArea" placeholder="请输入车位面积" /> <el-input maxlength="8" v-model.number="form.parkingArea" placeholder="请输入车位面积" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="所属楼层" prop="parkingFloor"> <el-form-item label="所属楼层" prop="parkingFloor">
<el-input v-model.number="form.parkingFloor" placeholder="请输入所属楼层" /> <el-input maxlength="5" v-model.number="form.parkingFloor" placeholder="请输入所属楼层" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -64,13 +64,13 @@
<el-row v-if="form.contactType === 0"> <el-row v-if="form.contactType === 0">
<el-col :span="10"> <el-col :span="10">
<el-form-item label="联系人名称" prop="contactName"> <el-form-item label="联系人名称" prop="contactName">
<el-input v-model.trim="form.contactName"></el-input> <el-input maxlength="20" v-model.trim="form.contactName"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="10"> <el-col :span="10">
<el-form-item label="联系人电话" prop="contactPhone"> <el-form-item label="联系人电话" prop="contactPhone">
<el-input v-model.trim="form.contactPhone"></el-input> <el-input maxlength="11" v-model.trim="form.contactPhone"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -96,7 +96,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model.trim="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>
</el-col> </el-col>
</el-row> </el-row>
@@ -159,7 +159,25 @@ const rules = ref({
} }
} }
], ],
contactName: [{ required: true, message: '请输入联系人名称', trigger: 'blur' }] contactName: [{ required: true, message: '请输入联系人名称', trigger: 'blur' }],
parkingArea: [
{ required: true, message: '请输入车位面积', trigger: 'blur' },
{
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
if (value === '' || value === null) {
return callback(new Error('请输入车位面积'));
}
const val = Number(value);
if (Number.isNaN(val)) {
return callback(new Error('请输入数字'));
}
if (val <= 0) {
return callback(new Error('请输入大于0的数字'));
}
return callback();
}
}
]
}); });
const userid = ref(null); const userid = ref(null);

View File

@@ -16,7 +16,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="车位编号" prop="parkingCode"> <el-form-item label="车位编号" prop="parkingCode">
<el-input v-model="queryParams.parkingCode" placeholder="请输入车位编号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.parkingCode" placeholder="请输入车位编号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

View File

@@ -138,7 +138,7 @@
<div class="w-full h-full flex mt-2"> <div class="w-full h-full flex mt-2">
<div class="title">审批意见</div> <div class="title">审批意见</div>
<div class="preivewBodybox flex-1 ml-5"> <div class="preivewBodybox flex-1 ml-5">
<el-input v-model="form.propertyReviewFeedback" type="textarea" :rows="5"></el-input> <el-input maxlength="200" show-word-limit v-model="form.propertyReviewFeedback" type="textarea" :rows="5"></el-input>
<div class="actions mt-5"> <div class="actions mt-5">
<el-button :disabled="parkingReviewInfo.parking.checkStatus === '1'" type="primary" @click="handlePreview(1)">审核通过</el-button> <el-button :disabled="parkingReviewInfo.parking.checkStatus === '1'" type="primary" @click="handlePreview(1)">审核通过</el-button>
<el-button :disabled="parkingReviewInfo.parking.checkStatus === '1'" type="danger" @click="handlePreview(2)" <el-button :disabled="parkingReviewInfo.parking.checkStatus === '1'" type="danger" @click="handlePreview(2)"
@@ -163,20 +163,20 @@
</template> </template>
<div class="w-full h-50%"> <div class="w-full h-50%">
<el-steps space="200px" direction="vertical" :active="activeStop"> <el-steps space="200px" direction="vertical" :active="activeStop">
<el-step :description="parkingReviewInfo.parkingReviewProcess.submitTime"> <el-step :description="active <= 0 ? '' : parkingReviewInfo.parkingReviewProcess.submitTime">
<template #title> <template #title>
<span v-if="active === 0">未提交信息</span> <span v-if="active === 0">未提交信息</span>
<span v-if="active >= 1">已提交信息</span> <span v-if="active >= 1">已提交信息</span>
</template> </template>
</el-step> </el-step>
<el-step :description="parkingReviewInfo.parkingReviewProcess.propertyTime"> <el-step :description="active <= 2 ? '' : parkingReviewInfo.parkingReviewProcess.propertyTime">
<template #title> <template #title>
<span v-if="active <= 2">待审核</span> <span v-if="active <= 2">待审核</span>
<span v-if="active === 3">物业审核不通过</span> <span v-if="active === 3">物业审核不通过</span>
<span v-if="active >= 4">物业审核通过</span> <span v-if="active >= 4">物业审核通过</span>
</template> </template>
</el-step> </el-step>
<el-step :description="parkingReviewInfo.parkingReviewProcess.certificationTime"> <el-step :description="active <= 5 ? '' : parkingReviewInfo.parkingReviewProcess.certificationTime">
<template #title> <template #title>
<span v-if="active <= 5">未认证</span> <span v-if="active <= 5">未认证</span>
<span v-if="active === 6">已认证</span> <span v-if="active === 6">已认证</span>

View File

@@ -24,7 +24,7 @@
</div> </div>
<div class="userinfo_item"> <div class="userinfo_item">
<div class="title_item">证件类型</div> <div class="title_item">证件类型</div>
<span> 身份证 </span> <DictTag :options="com_id_card_type" :value="userInfo.idCardType"></DictTag>
</div> </div>
<div class="userinfo_item"> <div class="userinfo_item">
<div class="title_item">住户类型</div> <div class="title_item">住户类型</div>
@@ -145,7 +145,7 @@ import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_review } = toRefs<any>(proxy?.useDict('com_review')); const { com_review } = toRefs<any>(proxy?.useDict('com_review'));
const { com_sub_status } = toRefs<any>(proxy?.useDict('com_sub_status')); const { com_sub_status } = toRefs<any>(proxy?.useDict('com_sub_status'));
const { com_resident_relationship } = toRefs<any>(proxy?.useDict('com_resident_relationship')); const { com_resident_relationship, com_id_card_type } = toRefs<any>(proxy?.useDict('com_resident_relationship', 'com_id_card_type'));
const { com_certification_status } = toRefs<any>(proxy?.useDict('com_certification_status')); const { com_certification_status } = toRefs<any>(proxy?.useDict('com_certification_status'));
const userInfo = ref<ResidentVO>({ const userInfo = ref<ResidentVO>({
@@ -155,6 +155,7 @@ const userInfo = ref<ResidentVO>({
userId: null, userId: null,
nickName: '', nickName: '',
unitNoId: '', unitNoId: '',
idCardType: '0',
'id': null, 'id': null,
'name': '', 'name': '',
'type': '0', 'type': '0',

View File

@@ -8,13 +8,13 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="楼栋房屋" prop="houseId"> <el-form-item label="楼栋房屋" prop="houseId">
<el-cascader v-model="userHousepath" :options="treedata" @change="handleChange" /> <el-cascader v-model="userHousePath" :options="treeData" @change="handleChange" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="住户姓名" prop="name"> <el-form-item label="住户姓名" prop="name">
<el-input v-model="form.name" placeholder="请输入住户姓名" /> <el-input maxlength="15" show-word-limit v-model.trim="form.name" placeholder="请输入住户姓名" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -28,9 +28,26 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> </el-col>
</el-row>
<el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="身份证号码" prop="idCard"> <el-form-item label="证件类型" prop="idCardType">
<el-input v-model="form.idCard" placeholder="请输入证件号码" /> <el-select @change="handleChangeIdCardType" v-model="form.idCardType" placeholder="请选择证件">
<el-option v-for="item in com_id_card_type" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="2"></el-col>
<el-col :span="11">
<el-form-item label="身份证号码" prop="idCard" v-if="form.idCardType === '0'">
<el-input maxlength="20" v-model="form.idCard" placeholder="请输入证件号码" />
</el-form-item>
<el-form-item label="护照号码" prop="idCard" v-if="form.idCardType === '1'">
<el-input maxlength="30" v-model="form.idCard" placeholder="请输入证件号码" />
</el-form-item>
<el-form-item label="港澳通行证号码" prop="idCard" v-if="form.idCardType === '2'">
<el-input maxlength="20" v-model="form.idCard" placeholder="请输入证件号码" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -62,7 +79,7 @@
:on-success="handleAvatarSuccess" :on-success="handleAvatarSuccess"
:on-exceed="handleExceed" :on-exceed="handleExceed"
:on-error="handleError" :on-error="handleError"
:before-upload="handleBeforUpload" :before-upload="handleBeforeUpload"
:limit="1" :limit="1"
> >
<img alt="身份证正面照" v-if="form.cardImageFront" :src="form.cardImageFront" class="avatar" /> <img alt="身份证正面照" v-if="form.cardImageFront" :src="form.cardImageFront" class="avatar" />
@@ -82,7 +99,7 @@
:on-exceed="handleExceed2" :on-exceed="handleExceed2"
:on-success="handleAvatar2Success" :on-success="handleAvatar2Success"
:on-error="handleError2" :on-error="handleError2"
:before-upload="handleBeforUpload" :before-upload="handleBeforeUpload"
> >
<img alt="身份证背面照" v-if="form.cardImageBack" :src="form.cardImageBack" class="avatar" /> <img alt="身份证背面照" v-if="form.cardImageBack" :src="form.cardImageBack" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
@@ -92,7 +109,7 @@
</el-row> </el-row>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :row="5" v-model.number="form.remark" placeholder="请输入备注" /> <el-input type="textarea" maxlength="200" show-word-limit :row="5" v-model.trim="form.remark" placeholder="请输入备注" />
</el-form-item> </el-form-item>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
<el-button type="primary" @click="submitForm">确定</el-button> <el-button type="primary" @click="submitForm">确定</el-button>
@@ -106,9 +123,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue'; import PageHeader from '@/components/Pageheader/index.vue';
import { getHousePathById } from '@/utils/house';
import { ResidentForm } from '@/api/system/residentReviewProcess/resident/type'; import { ResidentForm } from '@/api/system/residentReviewProcess/resident/type';
import { CascaderValue, UploadFiles, UploadInstance, UploadProps, UploadRawFile } from 'element-plus'; import { CascaderValue, UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
import { genFileId } from 'element-plus'; import { genFileId } from 'element-plus';
import { addResident, getResident, updateResident } from '@/api/system/residentReviewProcess/resident'; import { addResident, getResident, updateResident } from '@/api/system/residentReviewProcess/resident';
import { validator } from '@/utils/Reg'; import { validator } from '@/utils/Reg';
@@ -120,7 +136,7 @@ const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/resident/uploadImage';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex')); const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
const { com_resident_relationship } = toRefs<any>(proxy?.useDict('com_resident_relationship')); const { com_resident_relationship, com_id_card_type } = toRefs<any>(proxy?.useDict('com_resident_relationship', 'com_id_card_type'));
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
@@ -134,21 +150,31 @@ const form = ref<ResidentForm>({
ownerRelationship: '0', // 与业主关系 ownerRelationship: '0', // 与业主关系
phone: null, //手机号 phone: null, //手机号
cardImageFront: '', cardImageFront: '',
idCardType: '0', // 证件类型
cardImageBack: '', cardImageBack: '',
remark: '' //备注 remark: '' //备注╬╬╬.╬╬╬╬╬
}); });
const userHousepath = ref<CascaderValue>([]); const userHousePath = ref<CascaderValue>([]);
const rules = ref({ const rules = ref({
houseId: [{ required: true, message: '请选择房屋', trigger: 'blur' }], houseId: [{ required: true, message: '请选择房屋', trigger: 'blur' }],
name: [{ required: true, message: '请输入名称', trigger: 'blur' }], name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
gender: [{ required: true, message: '请选择性别', trigger: 'blur' }], gender: [{ required: true, message: '请选择性别', trigger: 'blur' }],
cardImageFront: [{ required: true, message: '请上传身份证照片', trigger: 'blur' }], cardImageFront: [{ required: true, message: '请上传身份证照片', trigger: 'blur' }],
cardImageBack: [{ required: true, message: '请上传身份证照片', trigger: 'blur' }], cardImageBack: [{ required: true, message: '请上传身份证照片', trigger: 'blur' }],
idCardType: [{ required: true, message: '请选择证件类型', trigger: 'blur' }],
idCard: [ idCard: [
{ required: true, message: '请输入身份证号', trigger: 'blur' },
{ {
validator: (_, value) => validator(value, 'idCard'), validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
message: '请输入正确的18位身份证号码', if (form.value.idCardType === '0') {
return validator(value, 'idCard') ? callback() : callback(new Error('请输入正确的18位身份证号码'));
} else if (form.value.idCardType === '1') {
return validator(value, 'passport') ? callback() : callback(new Error('请输入正确的护照号码'));
} else if (form.value.idCardType === '2') {
return validator(value, 'hongkongPassport') ? callback() : callback(new Error('请输入正确的港澳通行证号码'));
}
return callback();
},
required: true,
trigger: 'blur' trigger: 'blur'
} }
], ],
@@ -156,24 +182,29 @@ const rules = ref({
phone: [ phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' }, { required: true, message: '请输入手机号', trigger: 'blur' },
{ {
validator: (_, value) => validator(value, 'phone'), validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
message: '请输入正确的手机号码', return validator(value, 'phone') ? callback() : callback(new Error('请输入正确的手机号码'));
},
trigger: 'blur' trigger: 'blur'
} }
] ]
}); });
// 切换证件类型
const treedata = ref([]); function handleChangeIdCardType() {
form.value.idCard = '';
}
// 总房屋 树状结构
const treeData = ref([]);
function getTree() { function getTree() {
houseStore.getCurrentVilageTreeHouse().then((res) => { houseStore.getCurrentVilageTreeHouse().then((res) => {
treedata.value = res; treeData.value = res;
gettreedata(); getTreeData();
}); });
} }
getTree(); getTree();
// !== 楼栋房屋 ============================================================================= // !== 楼栋房屋 =============================================================================
const userid = ref(null); const userid = ref(null);
function gettreedata() { function getTreeData() {
// !== 编辑用户 ============================================================================= // !== 编辑用户 =============================================================================
if (route.query.id) { if (route.query.id) {
userid.value = route.query.id; userid.value = route.query.id;
@@ -181,13 +212,13 @@ function gettreedata() {
form.value = { form.value = {
...res.data ...res.data
}; };
userHousepath.value = [form.value.buildingId, form.value.unitNoId, form.value.houseId]; userHousePath.value = [form.value.buildingId, form.value.unitNoId, form.value.houseId];
}); });
} }
} }
function handleChange(val: CascaderValue) { function handleChange(val: CascaderValue) {
userHousepath.value = val; userHousePath.value = val;
form.value.buildingId = val[0]; form.value.buildingId = val[0];
form.value.houseId = val[2]; form.value.houseId = val[2];
} }
@@ -196,12 +227,12 @@ function handleChange(val: CascaderValue) {
// 上传文件成功 // 上传文件成功
const upload = ref<UploadInstance>(); const upload = ref<UploadInstance>();
const upload2 = ref<UploadInstance>(); const upload2 = ref<UploadInstance>();
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => { const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
if (response.data && response.data.url) { if (response.data && response.data.url) {
form.value.cardImageFront = response.data.url; form.value.cardImageFront = response.data.url;
} }
}; };
const handleAvatar2Success: UploadProps['onSuccess'] = (response, uploadFile) => { const handleAvatar2Success: UploadProps['onSuccess'] = (response) => {
if (response.code === 500 && response.msg == '不允许重复提交,请稍候再试') { if (response.code === 500 && response.msg == '不允许重复提交,请稍候再试') {
ElMessage.error('上传频率过快,稍后再试'); ElMessage.error('上传频率过快,稍后再试');
return; return;
@@ -224,16 +255,12 @@ const handleExceed2: UploadProps['onExceed'] = (files) => {
upload2.value!.handleStart(file); upload2.value!.handleStart(file);
upload2.value?.submit(); upload2.value?.submit();
}; };
const handleError: UploadProps['onError'] = (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) => { const handleError: UploadProps['onError'] = () => {};
console.log(error); const handleError2: UploadProps['onError'] = () => {};
}; const blockedExits = ['.exe', '.bat', '.cmd', '.msi'];
const handleError2: UploadProps['onError'] = (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) => { const handleBeforeUpload = (uploadFile: UploadRawFile) => {
console.log(error);
};
const blockedExts = ['.exe', '.bat', '.cmd', '.msi'];
const handleBeforUpload = (uploadFile: UploadRawFile) => {
const ext = uploadFile.name.toLowerCase().slice(uploadFile.name.lastIndexOf('.')); const ext = uploadFile.name.toLowerCase().slice(uploadFile.name.lastIndexOf('.'));
if (blockedExts.includes(ext)) { if (blockedExits.includes(ext)) {
ElMessage.warning(`禁止上传 ${ext} 文件`); ElMessage.warning(`禁止上传 ${ext} 文件`);
return false; return false;
} }

View File

@@ -12,7 +12,7 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="公告标题" prop="noticeTitle"> <el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model.trim="form.noticeTitle" placeholder="请输入公告标题" /> <el-input maxlength="20" v-model.trim="form.noticeTitle" placeholder="请输入公告标题" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12">--> <!-- <el-col :span="12">-->

View File

@@ -6,17 +6,8 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="公告标题" prop="noticeTitle"> <el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" /> <el-input maxlength="20" v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="作者" prop="author">-->
<!-- <el-input v-model="queryParams.author" placeholder="请输入作者" clearable @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="发布人" prop="publishBy">-->
<!-- <el-input v-model="queryParams.publishBy" placeholder="请输入发布人" clearable @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="发布日期" prop="publishTime">-->
<!-- <el-date-picker clearable v-model="queryParams.publishTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择发布日期" />-->
<!-- </el-form-item>-->
<el-form-item> <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -29,13 +20,12 @@
<el-card shadow="never" class="flex-1"> <el-card shadow="never" class="flex-1">
<template #header> <template #header>
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<!-- <el-col :span="1.5">-->
<!-- <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:revenueNotice:export']">导出</el-button>-->
<!-- </el-col>-->
<right-toolbar <right-toolbar
:show-edit="checkPermi(['revenue:revenueNotice:edit'])" :show-edit="checkPermi(['revenue:revenueNotice:edit'])"
:show-delete="checkPermi(['revenue:revenueNotice:remove'])" :show-delete="checkPermi(['revenue:revenueNotice:remove'])"
:showAdd="checkPermi(['revenue:revenueNotice:add'])" :showAdd="checkPermi(['revenue:revenueNotice:add'])"
:disable-delete="multiple"
:disable-edit="single"
@update:add="handleAdd" @update:add="handleAdd"
@update:edit="handleUpdate()" @update:edit="handleUpdate()"
@update:delete="handleDelete()" @update:delete="handleDelete()"
@@ -46,19 +36,6 @@
<el-table v-loading="loading" border :data="revenueNoticeList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" border :data="revenueNoticeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="公告标题" align="center" prop="noticeTitle" /> <el-table-column label="公告标题" align="center" prop="noticeTitle" />
<!-- <el-table-column label="公告内容" align="center" prop="noticeContent" />-->
<!-- <el-table-column label="作者" align="center" prop="author" />-->
<!-- <el-table-column label="发布状态" align="center" prop="publishStatus">-->
<!-- <template #default="scope">-->
<!-- <dict-tag :options="com_publish_status" :value="scope.row.publishStatus"></dict-tag>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="发布人" align="center" prop="publishBy" />-->
<!-- <el-table-column label="发布日期" align="center" prop="publishTime" width="180">-->
<!-- <template #default="scope">-->
<!-- <span>{{ parseTime(scope.row.publishTime, '{y}-{m}-{d}') }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['revenue:revenueNotice:edit']">修改</el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['revenue:revenueNotice:edit']">修改</el-button>
@@ -113,18 +90,17 @@ import { listRevenueNotice, delRevenueNotice, addRevenueNotice, updateRevenueNot
import { RevenueNoticeVO, RevenueNoticeQuery, RevenueNoticeForm } from '@/api/system/revenueNotice/type'; import { RevenueNoticeVO, RevenueNoticeQuery, RevenueNoticeForm } from '@/api/system/revenueNotice/type';
import { checkPermi } from '@/utils/permission'; import { checkPermi } from '@/utils/permission';
import { NoticeVO } from '@/api/system/NoticePc/type'; import { NoticeVO } from '@/api/system/NoticePc/type';
import RightToolbar from '@/components/RightToolbar/index.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// const { com_publish_status } = toRefs<any>(proxy?.useDict('com_publish_status'));
const revenueNoticeList = ref<RevenueNoticeVO[]>([]); const revenueNoticeList = ref<RevenueNoticeVO[]>([]);
const buttonLoading = ref(false); 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 total = ref(0);
const single = ref(true); const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>(); const queryFormRef = ref<ElFormInstance>();
const revenueNoticeFormRef = ref<ElFormInstance>(); const revenueNoticeFormRef = ref<ElFormInstance>();

View File

@@ -6,18 +6,27 @@
<div class="addBuildingFormBody formBody"> <div class="addBuildingFormBody formBody">
<el-form ref="roleFormRef" :model="form" :rules="rules" label-width="100px"> <el-form ref="roleFormRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="角色名称" prop="roleName"> <el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" /> <el-input v-model.trim="form.roleName" placeholder="请输入角色名称" />
</el-form-item> </el-form-item>
<el-form-item prop="roleKey"> <el-form-item prop="roleKey">
<template #label> <template #label>
<span> <span>
<el-tooltip content="控制器中定义的权限字符" placement="top"> <el-tooltip content="控制器中定义的权限字符" placement="top">
<el-icon><question-filled /></el-icon> <el-icon><question-filled /></el-icon>
<template #content>
<div>权限字符用于标识角色的唯一字符串不能重复</div>
<div>内置权限字符</div>
<div>superadmin超级管理员</div>
<div>manage物业管理员</div>
<div>repair维修人员</div>
<div>complainUser投诉处理人员</div>
<div>inspection 巡检人员</div>
</template>
</el-tooltip> </el-tooltip>
权限字符 权限字符
</span> </span>
</template> </template>
<el-input v-model="form.roleKey" placeholder="请输入权限字符" /> <el-input v-model.trim="form.roleKey" placeholder="请输入权限字符" />
</el-form-item> </el-form-item>
<el-form-item label="角色顺序" prop="roleSort"> <el-form-item label="角色顺序" prop="roleSort">
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" /> <el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
@@ -44,7 +53,7 @@
</el-tree> </el-tree>
</el-form-item> </el-form-item>
<el-form-item label="备注"> <el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input> <el-input maxlength="200" show-word-limit v-model.trim="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="dialog-footer text-center"> <div class="dialog-footer text-center">

View File

@@ -19,9 +19,9 @@
<div class="cardbox"> <div class="cardbox">
<div>收入来源</div> <div>收入来源</div>
<div class="card_InfoAll"> <div class="card_InfoAll">
<div>应缴费用{{ formatMoneyWithUnit(sourceFrom.totalPayable, 3) }}</div> <div>应缴费用{{ sourceFrom.totalPayable }}</div>
<div>已收{{ formatMoneyWithUnit(sourceFrom.totalReceived, 3) }}</div> <div>已收{{ sourceFrom.totalReceived }}</div>
<div>待收{{ formatMoneyWithUnit(sourceFrom.totalPending, 3) }}</div> <div>待收{{ sourceFrom.totalPending }}</div>
</div> </div>
<div class="cardBody" style="display: flex; flex-wrap: wrap" v-if="sourceFromIsComputed"> <div class="cardBody" style="display: flex; flex-wrap: wrap" v-if="sourceFromIsComputed">
<RingProgress name="停车费" color="#1a75ff" :value="sourceFrom.parkingFeePercent"></RingProgress> <RingProgress name="停车费" color="#1a75ff" :value="sourceFrom.parkingFeePercent"></RingProgress>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="AddBuildingBox"> <div class="AddBuildingBox">
<PageHeader :title="storeRoomid ? '编辑储藏室' : '添加储藏室'"></PageHeader> <PageHeader :title="storeRoomId ? '编辑储藏室' : '添加储藏室'"></PageHeader>
<div class="AddBuildingBody"> <div class="AddBuildingBody">
<div class="title">基本信息</div> <div class="title">基本信息</div>
<div class="addBuildingFormBody"> <div class="addBuildingFormBody">
@@ -9,7 +9,7 @@
<el-col :span="11"> <el-col :span="11">
<el-form-item label="楼栋" prop="buildingId"> <el-form-item label="楼栋" prop="buildingId">
<el-select @change="handleChangeBuild" v-model="form.buildingId" placeholder="请选择楼栋"> <el-select @change="handleChangeBuild" v-model="form.buildingId" placeholder="请选择楼栋">
<el-option v-for="item in Buildinglists" :key="item.id" :label="item.buildingName" :value="item.id" /> <el-option v-for="item in BuildingLists" :key="item.id" :label="item.buildingName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -25,32 +25,43 @@
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="储藏室号" prop="storeroomNo"> <el-form-item label="储藏室号" prop="storeroomNo">
<el-input v-model="form.storeroomNo" placeholder="请输入储藏室号" /> <el-input maxlength="15" v-model.trim="form.storeroomNo" placeholder="请输入储藏室号" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="建筑面积" prop="houseArea"> <el-form-item label="建筑面积" prop="houseArea">
<el-input v-model="form.houseArea" placeholder="请输入建筑面积" /> <el-input maxlength="8" v-model="form.houseArea" placeholder="请输入建筑面积">
<template #append>
<span></span>
</template>
</el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="公摊面积" prop="shareArea"> <el-form-item label="公摊面积" prop="shareArea">
<el-input v-model="form.shareArea" placeholder="请输入公摊面积" /> <el-input maxlength="8" v-model="form.shareArea" placeholder="请输入公摊面积" >
<template #append>
<span></span>
</template>
</el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"></el-col> <el-col :span="2"></el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item label="实用面积" prop="internalArea"> <el-form-item label="实用面积" prop="internalArea">
<el-input v-model="form.internalArea" placeholder="请输入实用面积" /> <el-input maxlength="8" v-model="form.internalArea" placeholder="请输入实用面积" >
<template #append>
<span></span>
</template>
</el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="5" v-model="form.remark" placeholder="请输入备注" /> <el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model="form.remark" placeholder="请输入备注" />
</el-form-item> </el-form-item>
<el-form-item style="margin-top: 30px"> <el-form-item style="margin-top: 30px">
<el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button>
@@ -89,15 +100,69 @@ const form = ref<StoreroomVO>({
const rules = ref({ const rules = ref({
buildingId: [{ required: true, message: '请选择楼栋', trigger: 'blur' }], buildingId: [{ required: true, message: '请选择楼栋', trigger: 'blur' }],
unitNoId: [{ required: true, message: '请选择单元', trigger: 'blur' }], unitNoId: [{ required: true, message: '请选择单元', trigger: 'blur' }],
storeroomNo: [{ required: true, message: '请输入储藏室号', trigger: 'blur' }] storeroomNo: [{ required: true, message: '请输入储藏室号', trigger: 'blur' }],
houseArea: [
{ required: true, message: '请输入建筑面积', trigger: 'blur' },
{
validator: (_: any, value: string, callback: (arg0?: Error) => void) => {
if (value === '' || value === null) {
return callback(new Error('请输入建筑面积'));
}
const val = Number(value);
if (Number.isNaN(val)) {
return callback(new Error('请输入数字'));
}
if (val <= 0) {
return callback(new Error('请输入大于0的数字'));
}
return callback();
}
}
],
shareArea: [
{ 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();
}
}
],
internalArea: [
{ 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();
}
}
]
}); });
const storeRoomid = ref(null); const storeRoomId = ref(null);
const units = ref([]); const units = ref([]);
const Buildinglists = ref([]); const BuildingLists = ref([]);
// 获取储藏室信息 // 获取储藏室信息
function getStoreRoominfo(id: string) { function getStoreRoomInfo(id: string) {
getStoreroom(id).then((res) => { getStoreroom(id).then((res) => {
form.value = { form.value = {
...form.value, ...form.value,
@@ -114,14 +179,14 @@ function getStoreRoominfo(id: string) {
// 根据小区id获取楼栋单元 // 根据小区id获取楼栋单元
function init() { function init() {
getBuildinglists().then((res) => { getBuildinglists().then((res) => {
Buildinglists.value = res.rows; BuildingLists.value = res.rows;
}); });
} }
init(); init();
onMounted(() => { onMounted(() => {
if (route.query.id) { if (route.query.id) {
storeRoomid.value = route.query.id; storeRoomId.value = route.query.id;
getStoreRoominfo(storeRoomid.value); getStoreRoomInfo(storeRoomId.value);
} }
}); });
// 根据楼栋id获取单元 // 根据楼栋id获取单元
@@ -137,7 +202,7 @@ const submitForm = () => {
const data = { const data = {
...form.value ...form.value
}; };
if (storeRoomid.value !== null) { if (storeRoomId.value !== null) {
updateStoreroom(data).then(() => { updateStoreroom(data).then(() => {
ElMessage.success('修改成功'); ElMessage.success('修改成功');
cancelForm(); cancelForm();

View File

@@ -6,7 +6,7 @@
<el-card shadow="hover"> <el-card shadow="hover">
<el-form label-width="100" ref="queryFormRef" @submit.prevent="handleQuery" :model="queryParams" :inline="true"> <el-form label-width="100" ref="queryFormRef" @submit.prevent="handleQuery" :model="queryParams" :inline="true">
<el-form-item label="储藏室号" prop="storeroomNo"> <el-form-item label="储藏室号" prop="storeroomNo">
<el-input v-model="queryParams.storeroomNo" placeholder="请输入储藏室号" clearable @keyup.enter="handleQuery" /> <el-input maxlength="15" v-model="queryParams.storeroomNo" placeholder="请输入储藏室号" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button> <el-button type="primary" @click="handleQuery">搜索</el-button>

Some files were not shown because too many files have changed in this diff Show More