8/25 dev bug

This commit is contained in:
Zy
2026-08-25 17:18:28 +08:00
parent 981d059ceb
commit b83735e993
37 changed files with 505 additions and 302 deletions

View File

@@ -106,7 +106,7 @@ export interface HouseRentalForm extends BaseEntity {
houseImageUrl: string; //房屋图片
supInfo: string; //补充租房信息
vx: string; //微信
houseUse: string; //房屋用途
houseUse?: string; //房屋用途
rentalStatus: number; //租赁状态
buildingId: string; //楼栋id
unitNoId: string; //单元id

View File

@@ -1,10 +1,18 @@
import request from '@/utils/request';
import { Response } from '@/api/system/report/dailyFeeReport/type';
import { FilterResponse, Response } from '@/api/system/report/dailyFeeReport/type';
export const getDailyFeeReportList = (data = {}): Promise<Response> => {
return request({
url: '/dailyFeeReport/list',
method: 'GET',
params: data
method: 'POST',
data: data
});
};
// 获取动态查询数据
export const getDailyFeeReportDynamicList = (data = {}): Promise<FilterResponse> => {
return request({
url: '/dailyFeeReport/filters',
method: 'GET',
data: data
});
};

View File

@@ -33,3 +33,16 @@ export type ChargeTypeAmounts = {
startDate?: string;
};
};
export type FilterResponse = {
code: number;
data: {
'field': string;
'label': string;
'type': string;
'placeholder': string;
'chargeTypeName': null;
'subField': null;
}[];
msg: string;
};

View File

@@ -7,7 +7,6 @@ import { ResidentVO, ResidentForm, ResidentQuery } from '@/api/system/residentRe
* @param query
* @returns {*}
*/
export const listResident = (query?: ResidentQuery | {}): AxiosPromise<ResidentVO[]> => {
return request({
url: '/resident/list',

View File

@@ -18,12 +18,12 @@ export interface ResidentVO {
nickName: string;
/**
* 0业主 1租户
* 0 业主 1 租户
*/
type: string;
/**
* 0 男性 1女性
* 0 男性 1 女性
*/
gender: string;
@@ -104,15 +104,15 @@ export interface ResidentForm extends BaseEntity {
name?: string;
/**
* 0业主
* 1亲属
* 2租户
* 3朋友
* 0 业主
* 1 亲属
* 2 租户
* 3 朋友
*/
ownerRelationship?: string;
/**
* 0 男性 1女性
* 0 男性 1 女性
*/
gender?: string;

View File

@@ -63,10 +63,10 @@ export const delVersion = (id: string | number | Array<string | number>) => {
};
/** 获取过往版本 */
export const getPastVersion = (platform: string, appChannel: string, channel: string = 'xiaomi') => {
export const getPastVersion = (platform: string, appChannel: string) => {
return request({
url: `/api/app/getPastVersion?platform=${platform}&appChannel=${appChannel}&channel=${channel}`,
method: 'get'
url: `/api/app/getPastVersion?platform=${platform}&appChannel=${appChannel}`,
method: 'get',
});
};
/** 切换版本启停 */

View File

@@ -373,6 +373,12 @@ onUnmounted(() => {
width: 40px;
font-size: 12px;
}
:deep(.ql-snow .ql-editor) {
white-space: pre-wrap;
/* 允许在数字内部断开,消除“整串数字集体跳下一行” */
word-break: break-all;
overflow-wrap: break-word;
}
:deep(.ql-snow .ql-toolbar button.ql-file::before) {
all: unset !important;
content: '附件';
@@ -385,6 +391,7 @@ onUnmounted(() => {
.editor {
max-width: 800px;
}
.editor,
.ql-toolbar {
white-space: pre-wrap !important;

View File

@@ -11,19 +11,23 @@
</div>
</div>
<el-dialog @close="conback" 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" style="margin-bottom: 20px">
<div class="flex flex-items-center flex-1" style="max-width: 200px">
<div style="width: 120px">住户类型</div>
<el-select v-model="queryParams.ownerRelationship" placeholder="请选择" clearable>
<el-option v-for="dict in com_resident_relationship" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</div>
<div class="mr-5 flex-1" style="margin: 0 20px">
<!-- <div class="flex flex-items-center flex-1" style="max-width: 200px">-->
<!-- <div style="width: 120px">住户类型</div>-->
<!-- <el-select v-model="queryParams.ownerRelationship" placeholder="请选择" clearable>-->
<!-- <el-option v-for="dict in com_resident_relationship" :key="dict.value" :label="dict.label" :value="dict.value" />-->
<!-- </el-select>-->
<!-- </div>-->
<!-- <div class="mr-5 flex-1" style="margin: 0 20px">-->
<!-- <el-input maxlength="30" clearable v-model="queryParams.name" placeholder="请输入住户姓名" />-->
<!-- </div>-->
<div class="flex flex-items-center flex-1" style="max-width: 300px; margin: 0 20px">
<div style="width: 120px">住户姓名</div>
<el-input maxlength="30" clearable v-model="queryParams.name" placeholder="请输入住户姓名" />
</div>
<div>
<el-button type="primary" @click="getlist">查询</el-button>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</div>
</nav>
@@ -64,10 +68,10 @@
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getlist"
@pagination="getList"
/>
<div>
<el-button @click="conback">退出</el-button>
<el-button @click="conBack">退出</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</div>
</div>
@@ -77,19 +81,8 @@
<script setup lang="ts">
import { listResident } from '@/api/system/residentReviewProcess/resident';
import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
import { ResidentQuery, ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
import { useHouseStore } from '@/store/modules/house';
const houseStore = useHouseStore();
const treedata = ref([]);
function init() {
houseStore.getCurrentVilageTreeHouse().then((res) => {
treedata.value = res;
});
}
init();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_resident_type } = toRefs<any>(proxy?.useDict('com_resident_type'));
@@ -198,7 +191,7 @@ const handleUserSelection = () => {
if (isMultiple.value && Array.isArray(props.userid)) {
// 多选回显
const selectedItems: tableType[] = [];
props.userid.forEach((id) => {
props.userid.forEach((id: string | number) => {
const findItem = tableData.value.find((item) => item.id == id || item.userId == id);
if (findItem) {
selectedItems.push(findItem);
@@ -222,12 +215,12 @@ const handleUserSelection = () => {
// 打开选择框
function choiceResidentFun() {
// 初始化
getlist();
getList();
dialog.value.dialogVisible = true;
}
// 获取列表
function getlist() {
function getList() {
loading.value = true;
listResident(queryParams.value)
.then((res) => {
@@ -253,11 +246,11 @@ function resetQuery() {
buildingId: null,
unitNo: null
};
getlist();
getList();
}
// 退出
function conback() {
function conBack() {
dialog.value.dialogVisible = false;
resetQuery();
}
@@ -297,7 +290,7 @@ function confirm() {
}
defineExpose({
open: (arr) => {
open: (arr?: string[], params: ResidentQuery | {} = {}) => {
if (arr && arr.length > 0) {
multipleSelection.value = arr.map((id) => ({
id: id
@@ -305,7 +298,12 @@ defineExpose({
} else {
multipleSelection.value = [];
}
getlist();
queryParams.value = {
...queryParams.value,
...params
};
console.log(queryParams.value);
getList();
dialog.value.dialogVisible = true;
}
});

View File

@@ -36,8 +36,15 @@
<el-button @click="resetQuery">重置</el-button>
</div>
</nav>
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table v-loading="loading" ref="multipleTableRef" :data="tableData" border>
<el-table-column width="55" align="center">
<template #header>
<el-checkbox v-model="isSelectAll" :indeterminate="isIndeterminate" @change="handleSelectAllChange" />
</template>
<template #default="scope">
<el-checkbox :model-value="isRowSelected(scope.row)" @change="(val: boolean) => handleRowCheckChange(scope.row, val)" />
</template>
</el-table-column>
<el-table-column label="序号" align="center" width="55" type="index" />
<el-table-column label="楼栋号" align="center">
<template #default="scope">
@@ -70,7 +77,7 @@
<div class="dialog-footer flex flex-items-center flex-justify-between">
<pagination
style="margin-top: 0"
layout="total, prev, pager, next, jumper"
layout="sizes, prev, pager, next, jumper"
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
@@ -79,7 +86,7 @@
/>
<div>
<el-button @click="conback">退出</el-button>
<el-button type="primary" @click="confirm"> 确定 </el-button>
<el-button type="primary" @click="confirm" :loading="loading"> 确定 </el-button>
</div>
</div>
</template>
@@ -89,7 +96,7 @@
<script setup lang="ts">
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
import { BillUserlist, queryResidentList_holder } from '@/api/system/SdbBill';
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
import { ComponentInternalInstance, getCurrentInstance, ref, toRefs } from 'vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
@@ -125,7 +132,7 @@ const dialog = ref({
const queryParams = ref({
pageNum: 1,
pageSize: 10,
pageSize: 5,
buildingId: null,
residentName: null,
@@ -137,53 +144,104 @@ const multipleTableRef = ref();
const tableData = ref<BillUserlist[]>([]);
const total = ref(0);
const loading = ref(false);
const isFetching = ref(false);
// 存储选中项
/** 存储所有选中项(跨页累计,非全选模式使用) */
const multipleSelection = ref<BillUserlist[]>([]);
/** 是否已跨页全选(标记模式,不实际持有全部数据) */
const isSelectAll = ref(false);
/** 表头复选框半选状态(部分选中时为 true */
const isIndeterminate = ref(false);
/** 全选模式下被手动取消勾选的 residentId 列表 */
const deselectedIds = ref<string[]>([]);
const isMultiple = computed(() => props.isMultiple ?? false);
// 优化 handleUserSelection避免重复查找
const handleUserSelection = () => {
isFetching.value = true;
if (!multipleTableRef.value || !tableData.value.length) {
isFetching.value = false;
/** 判断某行是否已选中 */
function isRowSelected(row: BillUserlist): boolean {
if (isSelectAll.value) {
// 全选模式:只要不在取消列表中就算选中
return !deselectedIds.value.includes(row.residentId);
}
return multipleSelection.value.some((item) => item.residentId === row.residentId);
}
/** 更新表头复选框状态:全选 / 半选 / 空 */
function updateIndeterminate() {
if (isSelectAll.value) {
// 全选模式下:有取消勾选的行 → 半选,否则 → 全选
isIndeterminate.value = deselectedIds.value.length > 0;
return;
}
const rowsToSelect = tableData.value.filter((row) => {
return multipleSelection.value.some((selected) => selected.residentId === row.residentId);
});
multipleTableRef.value.clearSelection();
if (rowsToSelect.length > 0) {
nextTick(() => {
rowsToSelect.forEach((row) => {
multipleTableRef.value?.toggleRowSelection(row, true);
});
isFetching.value = false;
});
const selectedCount = multipleSelection.value.length;
const totalCount = total.value;
if (selectedCount === 0) {
isIndeterminate.value = false;
} else if (totalCount > 0 && selectedCount >= totalCount) {
// 手动逐行全选 → 切换为全选标记模式,释放 multipleSelection 内存
isSelectAll.value = true;
isIndeterminate.value = false;
deselectedIds.value = [];
multipleSelection.value = [];
} else {
isFetching.value = false;
isIndeterminate.value = true;
}
};
}
/** 跨页全选 / 取消全选(仅设标记,不拉取数据) */
function handleSelectAllChange(val: boolean) {
if (val) {
isSelectAll.value = true;
deselectedIds.value = [];
multipleSelection.value = [];
} else {
isSelectAll.value = false;
deselectedIds.value = [];
multipleSelection.value = [];
}
updateIndeterminate();
}
/** 单行勾选 / 取消勾选 */
function handleRowCheckChange(row: BillUserlist, checked: boolean) {
if (isSelectAll.value) {
// 全选模式:维护取消列表
if (checked) {
deselectedIds.value = deselectedIds.value.filter((id) => id !== row.residentId);
} else {
if (!deselectedIds.value.includes(row.residentId)) {
deselectedIds.value.push(row.residentId);
}
}
} else {
// 非全选模式:维护选中列表
if (checked) {
if (!isRowSelected(row)) {
multipleSelection.value.push(row);
}
} else {
multipleSelection.value = multipleSelection.value.filter((item) => item.residentId !== row.residentId);
}
}
updateIndeterminate();
}
// ====================== 方法 ======================
// 获取列表
function getList() {
isFetching.value = true; // 加锁
loading.value = true;
queryResidentList_holder(queryParams.value)
.then((res) => {
tableData.value = res.rows;
total.value = res.total;
handleUserSelection();
updateIndeterminate();
})
.catch((error) => {
console.error('获取用户列表失败:', error);
})
.finally(() => {
loading.value = false;
isFetching.value = false; // 加锁
});
}
@@ -215,37 +273,6 @@ function handleChangeBuilding(val: string) {
function handleChangeUnit() {
getList();
}
// ==============================================
// ✅ 新增:处理 selection-change多选专用
// ==============================================
function handleSelectionChange(selection: BillUserlist[]) {
if (isFetching.value) return;
if (isMultiple.value) {
const currentSelectedIds = new Set(selection.map((item) => item.residentId));
const otherPageSelections = multipleSelection.value.filter((item) => {
const isCurrentPageItem = tableData.value.some((row) => row.residentId === item.residentId);
if (isCurrentPageItem) {
return currentSelectedIds.has(item.residentId);
} else {
return true;
}
});
// 3. 合并:其他页保留的 + 当前页新选中的
const finalSelection = [...otherPageSelections, ...selection];
// 4. 去重(以防万一)
const uniqueMap = new Map();
finalSelection.forEach((item) => uniqueMap.set(item.residentId, item));
multipleSelection.value = Array.from(uniqueMap.values());
console.log(multipleSelection.value.map((item) => item.residentId));
} else {
// --- 单选逻辑 ---
if (selection.length > 0) {
multipleSelection.value = [selection[selection.length - 1]];
} else {
multipleSelection.value = [];
}
}
}
// 重置查询
function resetQuery() {
queryParams.value = {
@@ -256,6 +283,7 @@ function resetQuery() {
residentName: null,
houseNo: null
};
resetSelection();
getList();
}
@@ -265,41 +293,82 @@ function conback() {
resetQuery();
}
// ==============================================
// ✅ 核心修改:根据 returnvalue 返回对应的值
// ==============================================
function confirm() {
dialog.value.dialogVisible = false;
/** 重置所有选中状态 */
function resetSelection() {
multipleSelection.value = [];
isSelectAll.value = false;
isIndeterminate.value = false;
deselectedIds.value = [];
}
/** 根据 returnvalue 发射选中结果 */
function emitResult(data: BillUserlist[]) {
if (isMultiple.value) {
// 多选
if (returnvalue.value === '*') {
// ✅ 返回整个对象数组
emit('change', multipleSelection.value);
emit('change', data);
} else {
// 返回指定字段数组
emit(
'change',
multipleSelection.value.map((item) => item[returnvalue.value as keyof BillUserlist])
data.map((item) => item[returnvalue.value as keyof BillUserlist])
);
}
} else {
// 单选
if (returnvalue.value === '*') {
// ✅ 返回整个对象
emit('change', multipleSelection.value[0]);
emit('change', data[0]);
} else {
// 返回指定字段
emit('change', multipleSelection.value[0][returnvalue.value as keyof BillUserlist]);
emit('change', data[0]?.[returnvalue.value as keyof BillUserlist]);
}
}
}
multipleSelection.value = [];
multipleTableRef.value.clearSelection();
/** 确定:全选模式下按需拉取全部数据,非全选模式直接使用已选列表 */
async function confirm() {
if (isSelectAll.value) {
// 全选模式:此时才真正拉取全部数据,排除已取消勾选的行
loading.value = true;
try {
const res = await queryResidentList_holder({
...queryParams.value,
pageNum: 1,
pageSize: total.value || undefined
});
const allData: BillUserlist[] = res.rows || [];
const filteredData = allData.filter((item) => !deselectedIds.value.includes(item.residentId));
dialog.value.dialogVisible = false;
emitResult(filteredData);
} catch (error) {
console.error('获取全部数据失败:', error);
} finally {
loading.value = false;
}
} else {
// 非全选模式:直接使用已收集的选中列表
dialog.value.dialogVisible = false;
emitResult(multipleSelection.value);
}
resetSelection();
}
defineExpose({
open: (arr: string[] = []) => {
userid.value = arr;
// 重置查询条件,避免残留上次的筛选条件
queryParams.value = {
pageNum: 1,
pageSize: 10,
buildingId: null,
residentName: null,
houseNo: null,
unitNoId: null
};
// 立即清空旧列表数据,避免闪烁
tableData.value = [];
total.value = 0;
// 重置全选标记
isSelectAll.value = false;
deselectedIds.value = [];
// 根据传入的 ID 数组初始化选中状态
if (arr && arr.length > 0) {
multipleSelection.value = arr.map(
(id) =>
@@ -307,8 +376,10 @@ defineExpose({
residentId: id
}) as BillUserlist
);
isIndeterminate.value = true;
} else {
multipleSelection.value = [];
isIndeterminate.value = false;
}
getList();

View File

@@ -2,8 +2,10 @@
<div class="top-right-btn" :style="style">
<div class="flex items-center">
<!-- 添加按钮 -->
<el-button :disabled="props.disableAdd" v-if="props.showAdd" icon="Plus" type="primary" @click="toggleSearch()"> 新建 </el-button>
<el-button :disabled="props.disableAdd" v-if="props.showAdd" icon="Plus" type="primary" @click="toggleSearch()">
{{ props.addTitle }}
</el-button>
<slot name="actions"></slot>
<!-- 批量操作下拉框 -->
<el-dropdown v-if="props.showDelete || props.showEdit || $slots.dropdown" trigger="click" style="margin-left: 10px">
<el-button @click.stop="refresh"> {{ props.moreTitle }} </el-button>
@@ -12,8 +14,12 @@
<template #dropdown>
<!-- 这里直接渲染不嵌套插槽 -->
<el-dropdown-menu v-if="!$slots.dropdown">
<el-dropdown-item :disabled="props.disableEdit" v-if="props.showEdit" @click="emits('update:edit')"> 编辑 </el-dropdown-item>
<el-dropdown-item :disabled="props.disableDelete" v-if="props.showDelete" @click="emits('update:delete')"> 批量删除 </el-dropdown-item>
<el-dropdown-item :disabled="props.disableEdit" v-if="props.showEdit" @click="emits('update:edit')">
{{ props.editTitle }}
</el-dropdown-item>
<el-dropdown-item :disabled="props.disableDelete" v-if="props.showDelete" @click="emits('update:delete')">
{{ props.deleteTitle }}
</el-dropdown-item>
</el-dropdown-menu>
<!-- 外部自定义内容直接渲染不包任何多余标签 -->
<template v-else>
@@ -58,6 +64,10 @@ const props = defineProps({
showDelete: propTypes.bool.def(true),
showEdit: propTypes.bool.def(true),
addTitle: propTypes.string.def('新建'),
editTitle: propTypes.string.def('编辑'),
deleteTitle: propTypes.string.def('批量删除'),
disableAdd: propTypes.bool.def(false),
disableDelete: propTypes.bool.def(false),
disableEdit: propTypes.bool.def(false)

0
src/enums/permission.ts Normal file
View File

View File

@@ -37,7 +37,7 @@
<el-dropdown-item divided command="changecommunity" v-if="isShow">
<span>{{ proxy.$t('navbar.community') }}</span>
</el-dropdown-item>
<router-link to="/system/user/profile" v-if="isShow">
<router-link to="/system/user/profile" v-if="isShow" v-has-permi="['system:user:profile']">
<el-dropdown-item>{{ proxy.$t('navbar.personalCenter') }}</el-dropdown-item>
</router-link>
<el-dropdown-item :divided="isShow" command="logout">

View File

@@ -479,6 +479,8 @@ const cancelForm = () => {
<style scoped lang="scss">
.box {
background: #deedff;
height: 100%;
overflow: hidden;
.header {
display: flex;
align-items: center;

View File

@@ -19,7 +19,7 @@
:min-scale="0.2"
:preview-src-list="item.villageImageUrl ? item.villageImageUrl.split(',') : [defaultVilageinfoImage]"
show-progress
:initial-index="4"
:initial-index="0"
fit="cover"
:src="item.villageImageUrl ? item.villageImageUrl.split(',')[0] : defaultVilageinfoImage"
>

View File

@@ -1,6 +1,6 @@
<template>
<div class="ResidentMainBox p-2 w-full">
<PageHeader title="活动"></PageHeader>
<PageHeader></PageHeader>
<div class="ResidentMainBody">
<el-card>
<template #header>
@@ -15,9 +15,31 @@
<el-input maxlength="30" v-model.trim="form.title" placeholder="请输入活动标题" />
</el-form-item>
</el-col>
<!-- <el-col :span="11">-->
<!-- <el-form-item label="活动作者" prop="author">-->
<!-- <el-input maxlength="20" v-model.trim="form.author" placeholder="请输入活动作者" />-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="11">
<el-form-item label="活动作者" prop="author">
<el-input maxlength="20" v-model.trim="form.author" placeholder="请输入活动作者" />
<el-form-item label="报名截止日期" prop="applyDeadline">
<el-date-picker
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
v-model="deadline"
style="width: 100%"
:disabled-date="disabledDate"
@update:model-value="
(data) => {
if (data) {
form.applyDeadline = data;
} else {
form.applyDeadline = '';
}
}
"
type="datetime"
placeholder="请选择报名截止日期"
/>
</el-form-item>
</el-col>
</el-row>
@@ -53,42 +75,43 @@
</el-col>
</el-row>
<el-row>
<el-col :span="11">
<el-form-item label="报名截止日期" prop="applyDeadline">
<el-col :span="13">
<el-form-item label="签到时间" prop="signinStartTime">
<el-date-picker
v-model="SigninTime"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
v-model="deadline"
:disabled-date="disabledDate"
@update:model-value="
(data) => {
@change="
(data: string[] | null) => {
if (data) {
form.applyDeadline = data;
form.signinStartTime = data[0];
form.signinEndTime = data[1];
} else {
form.applyDeadline = '';
form.signinStartTime = '';
form.signinEndTime = '';
}
}
"
type="datetime"
placeholder="请选择报名截止日期"
type="datetimerange"
range-separator=""
start-placeholder="开始签到"
end-placeholder="结束签到"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-col :span="11">
<el-form-item label="主办方" prop="organizer">
<el-input maxlength="20" v-model.trim="form.organizer" placeholder="请输入主办方" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-col :span="13">
<el-form-item label="联系人" prop="contactName">
<el-input maxlength="20" v-model.trim="form.contactName" placeholder="请输入联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="11">
<el-form-item label="联系方式" prop="contactPhone">
<el-input maxlength="20" v-model.trim="form.contactPhone" placeholder="请输入联系方式" />
</el-form-item>
@@ -124,23 +147,18 @@
</el-upload>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="招募要求">
<el-input
maxlength="200"
show-word-limit
:row="8"
type="textarea"
v-model.trim="form.requirements"
placeholder="请输入招募要求"
/>
</el-row>
<el-row>
<el-col>
<el-form-item label="招募要求" prop="requirements">
<editor v-model="form.requirements" :height="200" :min-height="200" :read-only="false" :file-size="5" :type="'url'" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col>
<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="300" :min-height="300" :read-only="false" :file-size="5" :type="'url'" />
</el-form-item>
</el-col>
</el-row>
@@ -209,7 +227,7 @@
</el-col>
</el-row> -->
<el-form-item>
<el-button type="warning" @click="submitForm('0')">保存为草稿</el-button>
<!-- <el-button type="warning" @click="submitForm('0')">保存为草稿</el-button>-->
<el-button type="primary" @click="submitForm('1')">发布</el-button>
<el-button @click="handleBack">返回</el-button>
</el-form-item>
@@ -293,6 +311,8 @@ const rules = {
applyDeadline: [{ required: true, message: '请输入报名截止日期', trigger: 'blur' }],
startTime: [{ required: true, message: '请选择开始日期', trigger: 'blur' }],
endTime: [{ required: true, message: '请选择结束日期', trigger: 'blur' }],
signinStartTime: [{ required: true, message: '请选择开始签到时间', trigger: 'blur' }],
signinEndTime: [{ required: true, message: '请选择结束签到时间', trigger: 'blur' }],
address: [{ required: true, message: '请输入活动地点', trigger: 'blur' }],
organizer: [
{ required: true, message: '请输入主办方', trigger: 'blur' },

View File

@@ -33,7 +33,7 @@
<el-input v-model.trim="form.link" placeholder="请输入跳转链接" />
</el-form-item>
<el-form-item label="排序号" prop="byOrder">
<el-input-number v-model.trim="form.byOrder" placeholder="请输入" />
<el-input-number :min="0" :max="9999" v-model.trim="form.byOrder" placeholder="请输入" />
</el-form-item>
<el-form-item style="margin-top: 30px">
<el-button type="primary" @click="submitForm">提交</el-button>

View File

@@ -70,9 +70,9 @@
<span>属性配置</span>
</div>
</template>
<el-form style="position: sticky; top: 60px" label-width="80px">
<el-form-item label="题目标题">
<el-input maxlength="20" v-model.trim="activeQuestion.title" placeholder="请输入题目标题" />
<el-form :rules="rules" :model="activeQuestion" style="position: sticky; top: 60px" label-width="80px">
<el-form-item label="题目标题" prop="title">
<el-input maxlength="50" v-model.trim="activeQuestion.title" placeholder="请输入题目标题" />
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model.trim="activeQuestion.required" />
@@ -87,9 +87,13 @@
placeholder="选项内容"
style="width: 200px; margin-right: 10px; margin-bottom: 10px"
/>
<el-button link type="danger" :icon="Delete" @click="activeQuestion.options.splice(idx, 1)"> 删除 </el-button>
<el-button link type="danger" v-if="activeQuestion.options.length > 2" :icon="Delete" @click="activeQuestion.options.splice(idx, 1)">
删除
</el-button>
</div>
<el-button type="primary" @click="activeQuestion.options.push({ label: '选项' })"> 添加选项 </el-button>
<el-button type="primary" @click="activeQuestion.options.push({ label: '选项' + (activeQuestion.options.length + 1) })">
添加选项
</el-button>
</template>
</el-form>
</el-card>
@@ -141,6 +145,10 @@ const form = ref<QuestionComponentnaireForm>({
content: []
});
const rules = ref({
title: [{ required: true, message: '请输入问卷标题', trigger: 'blur' }]
});
const activeIndex = ref<number>(-1);
// ==================== 计算属性 ====================
@@ -190,10 +198,15 @@ function deleteQuestion(index: number): void {
// ==================== 业务方法 ====================
/** 表单验证 */
function validateForm(): boolean {
// 验证问卷标题
if (!form.value.title.trim()) {
ElMessage.error('请输入问卷标题');
return false;
}
if (form.value.content.some((item) => item.title === '')) {
ElMessage.error('请填写所有题目标题');
return false;
}
return true;
}

View File

@@ -6,12 +6,12 @@
<div class="addBuildingFormBody">
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
<el-row>
<el-col :span="11">
<el-col :span="11" v-if="type === 'private'">
<el-form-item label="关联房屋" prop="houseId">
<el-cascader v-model="form.houseId" :options="treedata" @change="handleChangeHouse" />
</el-form-item>
</el-col>
<el-col :span="2"></el-col>
<el-col :span="2" v-if="type === 'private'"></el-col>
<el-col :span="11">
<el-form-item label="维修项目" prop="maintenanceItemId">
<el-cascader
@@ -27,13 +27,13 @@
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="报修标题" prop="item">
<el-input maxlength="30" v-model.trim="form.item" placeholder="请输入报修标题" />
</el-form-item>
</el-col>
</el-row>
<!-- <el-row>-->
<!-- <el-col :span="24">-->
<!-- <el-form-item label="报修标题" prop="item">-->
<!-- <el-input maxlength="30" v-model.trim="form.item" placeholder="请输入报修标题" />-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<!-- </el-row>-->
<el-row>
<el-col :span="24">
<el-form-item label="问题描述" prop="problem">
@@ -63,14 +63,20 @@
<el-row>
<el-col :span="12">
<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-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="预约日期" prop="orderDate">
<el-date-picker v-model="form.orderDate" type="datetime" placeholder="年/月/日 时:分:秒" value-format="YYYY-MM-DD HH:mm:ss" />
<el-date-picker
:disabled-date="disabledDate"
v-model="form.orderDate"
type="datetime"
placeholder="年/月/日 时:分:秒"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
</el-row>
@@ -142,8 +148,12 @@ const form = ref({
repairImageUrl: '', // 维修图片url
orderDate: '' // 预约日期
});
const type = ref('private');
onMounted(() => {
type.value = (route.query.type as 'public' | 'private') || 'private';
});
const rules = ref({
houseId: [{ required: true, message: '请选择关联房屋', trigger: 'blur' }],
houseId: [{ required: type.value === 'private', message: '请选择关联房屋', trigger: 'blur' }],
maintenanceItemId: [{ required: true, message: '请选择维修项目', trigger: 'blur' }],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
@@ -155,9 +165,12 @@ const rules = ref({
],
problem: [{ required: true, message: '请输入问题描述', trigger: 'blur' }]
});
const userid = ref(null);
// 报修项目 tree 结构
const maintenanceItemTreeData = ref();
function init() {
gettreelistRepairProject().then((res) => {
maintenanceItemTreeData.value = handleTreeDisable(res.data);
@@ -195,15 +208,13 @@ function handleTreeDisable(TreeData: RepairProjectVO[]) {
});
}
// ! 上传图片 =--==================================================================
// ! 上传图片 ===================================================================
const fileList = ref<UploadUserFile[]>([]);
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles);
};
const handleRemove: UploadProps['onRemove'] = () => {};
const blockedExits = ['.exe', '.bat', '.cmd', '.msi'];
const allUploadExits = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'];
const handleChangeFile: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
@@ -231,7 +242,10 @@ const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
const holderInfo = ref(null);
const HolderRef = ref<typeof Holder>(null);
function choiceResidentFun() {
HolderRef.value.open([form.value.residentId]);
HolderRef.value.open([form.value.residentId], {
ownerRelationship: '0',
status: '1'
});
}
// 选择住户
function handleChange(pop) {
@@ -301,6 +315,11 @@ const submitForm = () => {
});
};
// 禁用日期
const disabledDate = (time: Date) => {
return time.getTime() <= Date.now();
};
const sendForm = (str: string) => {
form.value.problemImageUrl = str;
if (userid.value) {
@@ -345,7 +364,7 @@ const cancelForm = () => {
}
.formBody {
width: 1050px;
width: 800px;
margin: 0 auto;
&:deep(.el-date-editor.el-input) {

View File

@@ -38,10 +38,15 @@
:show-add="checkPermi(['repair:repair:add'])"
:show-edit="checkPermi(['repair:repair:edit'])"
:show-delete="checkPermi(['repair:repair:remove'])"
add-title="个人报修"
@update:add="handleAdd"
@update:edit="handleUpdate()"
@update:delete="handleDelete()"
></right-toolbar>
>
<template #actions>
<el-button type="default" icon="Plus" v-hasPermi="['repair:repair:add']" @click="handleAdd('public')">公共报修</el-button>
</template>
</right-toolbar>
</el-row>
</template>
@@ -77,7 +82,6 @@
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
</div>
@@ -190,19 +194,40 @@ const handleSelectionChange = (selection: RepairVO[]) => {
};
/** 新增按钮操作 */
const handleAdd = () => {
const handleAdd = (type: 'public' | 'private' = 'private') => {
router.push({
path: '/repair/addRepair'
path: '/repair/addRepair',
query: {
type
}
});
};
/** 修改按钮操作 */
const handleUpdate = (row?: RepairVO) => {
const _id = row?.id || ids.value[0];
let type: string;
// 如果有行数据根据houseId判断类型
if (row) {
if (row.houseId) {
type = 'private';
} else {
type = 'public';
}
} else {
// 多选编辑时,根据第一个选中的行判断类型
const item = repairList.value.find((item) => item.id === _id);
if (item) {
type = item.houseId ? 'private' : 'public';
} else {
type = 'private';
}
}
router.push({
path: '/repair/editRepair',
query: {
id: _id
id: _id,
type
}
});
};

View File

@@ -26,13 +26,6 @@
</el-form-item>
<el-form-item label="计算公式" prop="formula">
<el-select
@change="
(val) => {
if (val === '2') {
form.unit = null;
}
}
"
v-model="form.formula"
>
<el-option v-for="(item, index) in com_charge_item_formula" :key="index" :value="item.value" :label="item.label"></el-option>
@@ -162,7 +155,7 @@ if (route.query.id) {
// 提交
const submitForm = () => {
if (form.value.formula === '2') {
form.value.unit = null;
form.value.unit = '';
}
formRef.value?.validate(async (valid: boolean) => {
if (valid) {

View File

@@ -10,13 +10,16 @@
</el-form-item>
<el-form-item label="收费项目" prop="chargeItemId">
<el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)">
<el-option
:disabled="item.status === '1'"
v-for="(item, index) in chargeItemList"
:key="index"
:value="item.id"
:label="item.itemName"
></el-option>
<el-option :disabled="item.status === '1'" v-for="(item, index) in chargeItemList" :key="index" :value="item.id" :label="item.itemName">
<div class="flex flex-row justify-between" style="font-size: 13px">
<span>{{ item.itemName }}</span>
<div class="flex flex-items-baseline" style="color: var(--el-text-color-secondary)">
<span>{{ item.fixedPrice }} </span>
<span style="margin: 0 5px" v-if="item.unit">/</span>
<dict-tag v-if="item.unit" :options="com_charge_item_unit" :value="item.unit"></dict-tag>
</div>
</div>
</el-option>
</el-select>
</el-form-item>
<!-- 水费电费 收费范围为 房屋 -->
@@ -160,10 +163,11 @@ import { getBill, updateBill, addBill } from '@/api/system/SdbBill';
import type { DatePickerType } from 'element-plus';
import { formatDate2 } from '@/utils';
import { QuestionFilled } from '@element-plus/icons-vue';
import DictTag from '@/components/DictTag/index.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_bill_charge_scope_house, com_questionnaire_scope, com_bill_charge_period } = toRefs<any>(
proxy?.useDict('com_bill_charge_scope_house', 'com_questionnaire_scope', 'com_bill_charge_period')
const { com_bill_charge_scope_house, com_questionnaire_scope, com_bill_charge_period, com_charge_item_unit } = toRefs<any>(
proxy?.useDict('com_bill_charge_scope_house', 'com_questionnaire_scope', 'com_bill_charge_period', 'com_charge_item_unit')
);
type PickerConfig = {
@@ -188,7 +192,7 @@ const form = ref({
houseIds: [], // 部分房屋
residentIds: [], // 部分业主
parkingIds: [],
chargeTypeId: '', // typeid
chargeTypeId: '', // 收费类型
periodCalcType: '0', // 周期计算维度
'startDate': '', // 开始
'endDate': '', // 结束
@@ -320,6 +324,7 @@ function handleSelect(val: string[]) {
const checkoutUser = ref([]);
/** 添加 业主 */
function handleCheckUser(val: string[]) {
console.log(val);
checkoutUser.value = val;
form.value.residentIds = val;
}

View File

@@ -138,10 +138,7 @@ import { listBill, manualGenerateApi } from '@/api/system/SdbBill';
import { BillVO, BillQuery, BillForm } from '@/api/system/SdbBill/type';
import { listChargeItem } from '@/api/system/SdbChargeItem';
import { checkPermi } from '@/utils/permission';
// import House from '@/components/Holder/house.vue';
import { ref } from 'vue';
// import UserHolder from '@/components/Holder/user.vue';
// import CarUser from '@/components/Holder/CarUser.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
@@ -241,7 +238,7 @@ const handleUpdate = (row?: BillVO) => {
}
});
};
// 详情
function handleMain(row: BillVO) {
router.push({
path: '/sdb/sdbbillMain',
@@ -283,6 +280,7 @@ const BillForm = ref<{
// function handleSelect(val: string[]) {
// BillForm.value.houseId = val;
// }
// 生成账单
function handleChange(row: BillVO) {
clearChangeBillForm();
BillVisible.value = true;
@@ -300,6 +298,7 @@ function handleChange(row: BillVO) {
BillForm.value['year'] = [];
}
}
// 生成账单
function handleChangeApi() {
manualGenerateApi(BillForm.value).then((res) => {
ElMessage.success(res.msg);
@@ -307,6 +306,7 @@ function handleChangeApi() {
BillVisible.value = false;
});
}
// 清空表单
function clearChangeBillForm() {
BillForm.value = {
periodCalcType: undefined,
@@ -317,16 +317,10 @@ function clearChangeBillForm() {
houseId: []
};
}
// 禁用月份
function handleDisableMonth(date: Date) {
if (!BillForm.value.startDate || !BillForm.value.endDate) return false;
return date.getTime() < new Date(BillForm.value.startDate).getTime() || date.getTime() > new Date(BillForm.value.endDate).getTime();
}
const myQuarter = ref('2026-2');
function onQuarterChange(val: string) {
console.log(val);
return date.getTime() > new Date(BillForm.value.endDate).getTime();
}
onMounted(() => {

View File

@@ -157,7 +157,7 @@
<span v-if="scope.row.payStatus === '0'">未缴纳</span>
<span v-else-if="scope.row.payStatus === '1'">已缴纳</span>
<span v-else-if="scope.row.payStatus === '2'">缴纳失败</span>
<span v-else>部分缴纳</span>
<span v-else-if="scope.row.payStatus === '3'">部分缴纳</span>
</template>
</el-table-column>
<el-table-column label="应缴金额" width="100" align="center" prop="amount" />
@@ -276,7 +276,7 @@
<el-form-item label="缴纳状态" prop="payStatus">
<el-radio-group v-model="inComeFrom.payStatus">
<el-radio value="1" label="已缴纳"></el-radio>
<el-radio value="2" label="部分缴纳"></el-radio>
<el-radio value="3" label="部分缴纳"></el-radio>
</el-radio-group>
</el-form-item>
@@ -602,7 +602,6 @@ function getList() {
.then((res) => {
tableData.value = res.rows;
total.value = res.total;
handleSelectBill(res.rows);
})
.finally(() => {
loading.value = false;
@@ -695,7 +694,7 @@ function initInComeFrom() {
allCost: 0, // 总金额
billResidentId: [], // 账单id
payStatus: '1', // 0:未缴 1:已缴 2: 缴纳失败 3: 部分缴纳
payType: '2', // 0:微信 1:支付宝 2 线下
payType: '2', // 0:微信 1:支付宝
remark: '',
discountMethod: 0, // 优惠方式 0 不优惠 1 比例 2 金额
discountRate: '0', // 优惠比例 10 === 10%
@@ -892,12 +891,19 @@ const submitForm = () => {
return;
}
buttonLoading.value = true;
// 部分缴纳时 不管
// 部分缴纳时 判断 支付金额 和 预计支付金额 是否相等 ,相等 则 可选择 部分缴纳 方式
console.log(totalPayAmount.value, payListAllAmount.value, eqMoney(totalPayAmount.value, payListAllAmount.value), inComeFrom.value.payStatus);
if (inComeFrom.value.payStatus === '3') {
if (eqMoney(totalPayAmount.value, payListAllAmount.value)) {
buttonLoading.value = false;
return ElMessage.warning('实缴金额等于应收金额时,请选择 【已缴纳】 状态');
}
}
// 已缴纳时 判断 支付金额 和 预计支付金额 是否相等
if (inComeFrom.value.payStatus === '1') {
if (!eqMoney(totalPayAmount.value, payListAllAmount.value)) {
buttonLoading.value = false;
return ElMessage.warning('支付金额不足,选择 部分缴纳 方式');
return ElMessage.warning('支付金额不足,选择 部分缴纳】 状态');
}
}
const obj = {
@@ -1090,8 +1096,6 @@ const totalAll = ref({
totalAccount: '0', // 总金额
TotalUnPaymentAmount: '0' // 未收金额
});
// 多选时 统计总金额,优惠总金额,实付总金额
function handleSelectBill() {}
function handleChangePayTypeId(val: string, index: number) {
// 【可选兜底校验】防止异常数据出现重复

View File

@@ -66,7 +66,6 @@
import Pageheader from '@/components/Pageheader/index.vue';
import { listCar, delCar } from '@/api/system/cars/index';
import { CarVO, CarQuery, CarForm } from '@/api/system/cars/type';
import { listResident } from '@/api/system/residentReviewProcess/resident';
import { checkPermi } from '@/utils/permission';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;

View File

@@ -7,7 +7,7 @@
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
<el-form-item label="设备分类" prop="categoryId">
<el-select v-model="form.categoryId">
<el-option v-for="(item, index) in deviceCategorylist" :key="index" :value="item.id" :label="item.categoryName"></el-option>
<el-option v-for="(item, index) in deviceCategoryList" :key="index" :value="item.id" :label="item.categoryName"></el-option>
</el-select>
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
@@ -25,7 +25,7 @@
<el-form-item label="维护人员" prop="maintainUserIds">
<repairUser
userType="repair"
:userid="checkoutuseid"
:userid="checkoutUseId"
ref="repairUserRef"
returnvalue="*"
:is-multiple="true"
@@ -33,7 +33,7 @@
@change="handleCheckoutUser"
>
<template #default>
<div class="checkoutuserbox flex flex-items-center justify-around" v-for="(item, index) in checkoutuser" :key="index">
<div class="checkoutUserBox flex flex-items-center justify-around" v-for="(item, index) in checkoutUser" :key="index">
<span>{{ item.nickName }}</span>
<div @click="handleDelete(item.id)">
<el-icon>
@@ -41,7 +41,7 @@
</el-icon>
</div>
</div>
<div class="checkoutuserbox add flex flex-items-center justify-center" @click="() => repairUserRef.open()">
<div class="checkoutUserBox add flex flex-items-center justify-center" @click="() => repairUserRef.open()">
<el-icon>
<Plus></Plus>
</el-icon>
@@ -106,10 +106,10 @@ const rules = ref({
});
const userid = ref(null);
const deviceCategorylist = ref([]);
const deviceCategoryList = ref([]);
function init() {
listDeviceCategory().then((res) => {
deviceCategorylist.value = res.rows;
deviceCategoryList.value = res.rows;
});
if (route.query.id) {
userid.value = route.query.id;
@@ -127,33 +127,33 @@ function init() {
remark: res.data.remark
};
checkoutuser.value = [];
checkoutuser.value = res.data.maintainUserList;
checkoutUser.value = [];
checkoutUser.value = res.data.maintainUserList ?? [];
});
}
}
init();
const checkoutuseid = computed(() => {
return checkoutuser.value
const checkoutUseId = computed(() => {
return checkoutUser.value
.map((item) => item.userId)
.filter((item) => item)
.join(',');
});
const checkoutuser = ref([]);
function handleCheckoutUser(row) {
checkoutuser.value = row;
const checkoutUser = ref([]);
function handleCheckoutUser(row: string[]) {
checkoutUser.value = row;
}
function handleDelete(id: string) {
checkoutuser.value = checkoutuser.value.filter((item) => item.id !== id);
checkoutUser.value = checkoutUser.value.filter((item) => item.id !== id);
}
// !== 提交 =============================================================================
// 提交
const submitForm = () => {
form.value.maintainUserIds = checkoutuser.value
.map((itme) => itme.userId)
form.value.maintainUserIds = checkoutUser.value
.map((item) => item.userId)
.filter((item) => item)
.join(',');
formRef.value?.validate(async (valid: boolean) => {
@@ -205,7 +205,7 @@ const cancelForm = () => {
width: 650px;
margin: 0 auto;
.checkoutuserbox {
.checkoutUserBox {
width: 120px;
margin: 5px;
border: 1px solid #ccc;

View File

@@ -237,10 +237,14 @@ const cancelForm = () => {
font-size: 15px;
.label {
width: 100px;
min-width: 100px;
text-align: right;
}
.value {
font-weight: normal;
white-space: wrap;
word-break: break-word;
font-size: 14px;
}
}
}

View File

@@ -138,7 +138,10 @@
<el-table-column prop="name" label="收费标准">
<template #default="scope">
<div class="flex">
<span>{{ scope.row.fixedPrice }}</span> /
<span>{{ scope.row.fixedPrice }}</span>
<span v-if="scope.row.fixedPrice && scope.row.unit">/</span>
<span v-else>---</span>
<dict-tag :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
</div>
</template>

View File

@@ -197,7 +197,6 @@ const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/houseRental/uploadImages
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_rental_method } = toRefs<any>(proxy?.useDict('com_rental_method'));
const { com_rental_status } = toRefs<any>(proxy?.useDict('com_rental_status'));
// const { com_house_use } = toRefs<any>(proxy?.useDict('com_house_use'));&╬╬╥
const router = useRouter();
const route = useRoute();
@@ -220,7 +219,6 @@ const form = ref({
houseImageUrl: '', //房屋图片
supInfo: '', //补充租房信息
vx: '', //微信
houseUse: '', //房屋用途
rentalStatus: 1, //租赁状态
buildingId: null, //楼栋id
unitNoId: null, //单元id

View File

@@ -112,7 +112,7 @@
<el-input maxlength="20" show-word-limit v-model.trim="form.contractNo" placeholder="请输入合同编号" />
</el-form-item>
<el-form-item label="合同状态" prop="contractStatus">
<el-input show-word-limit maxlength="200" v-model.trim="form.contractStatus" placeholder="请输入合同状态" />
<el-input show-word-limit maxlength="40" v-model.trim="form.contractStatus" placeholder="请输入合同状态" />
</el-form-item>
<el-form-item label="租赁起始日" prop="leaseStartDate">
<el-date-picker
@@ -413,14 +413,13 @@ function sign(row: HouseRentalVO) {
form.value.villageName = info.villageName;
form.value.houseName = row.name;
form.value.houseArea = row.houseArea;
form.value.tenantPhone = '';
form.value.tenantPhone = row.signingList?.[0].tenantPhone || '';
form.value.houseId = row.houseId;
form.value.villageId = info.villageId;
form.value.rentalId = row.id;
if (row.signingList && row.signingList.length > 0) {
const names = row.signingList[0].contractName ? row.signingList[0].contractName.split(',') : [];
const list = row.signingList[0].contractUrl ? row.signingList[0].contractUrl.split(',') : [];
console.log(list);
if (list.length > 0) {
showImgList.value = list.map((item, index) => {
return {
@@ -451,12 +450,12 @@ const MAX_UPLOAD_FILES = 9;
const showImgList = ref([]);
// 超出总数量拦截,不再只限制单次选择
const handleExceed = () => {
ElMessage.warning(`最多只能上传 ${MAX_UPLOAD_FILES} 张轮播图`);
ElMessage.warning(`最多只能上传 ${MAX_UPLOAD_FILES} 个附件`);
};
const handleChange = (file: UploadUserFile) => {
// 实时判断当前已存在图片总数
if (showImgList.value.length > MAX_UPLOAD_FILES) {
ElMessage.warning(`最多上传${MAX_UPLOAD_FILES},无法继续添加`);
ElMessage.warning(`最多上传${MAX_UPLOAD_FILES}个附件,无法继续添加`);
// 清除刚选中的文件,防止缓存残留
uploadRef.value?.handleRemove(file);
return;

View File

@@ -232,11 +232,18 @@ const getAreaList = async () => {
getAreaList();
const holderInfo = ref(null);
function choiceResidentFun() {
if (form.value.residentId) {
HolderRef.value.open([...form.value.residentId]);
HolderRef.value.open([...form.value.residentId], {
ownerRelationship: '0',
status: '1'
});
} else {
HolderRef.value.open([]);
HolderRef.value.open([], {
ownerRelationship: '0',
status: '1'
});
}
}
function handleChange(pop) {

View File

@@ -38,11 +38,11 @@
</el-select>
</el-form-item>
</div>
<div class="line"></div>
<div class="line" v-if="queryParams.chargeTypeFilters.length > 0"></div>
<el-scrollbar>
<div style="width: fit-content">
<!-- 搜索条件 应收/已收/未收 -->
<!-- 搜索条件 应收/已收/未收 -->
<div class="queryBox_over">
<el-form-item
:label="`${item.chargeTypeName}(应收)`"
@@ -472,7 +472,7 @@ const formRules = computed<FormRules>(() => {
trigger: 'blur'
}
];
// 房
// 房
dynamicRules[`roomNumber`] = [
{
validator: (_: any, value: string, callback: (error?: any) => void) => {

View File

@@ -4,21 +4,11 @@
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<div class="flex justify-between">
<div>
<el-form-item label="项目" prop="chargeItemId">
<el-select v-model="queryParams.villageId" placeholder="请选择">
<el-option v-for="item in villageList" :key="item.villageId" :label="item.villageName" :value="item.villageId" />
</el-select>
</el-form-item>
<el-form-item label="房屋类型" prop="houseUseTypeId">
<el-select v-model="queryParams.houseUseTypeId" placeholder="请选择">
<el-option v-for="item in houseUseList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="客户" prop="customerName">
<el-input v-model.trim="queryParams.customerName"></el-input>
<el-form label-width="auto" ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
<div class="flex justify-between flex-wrap">
<div v-for="(item, index) in queryParamsList" :key="index">
<el-form-item :label="item[ite].label" :prop="item[ite].parameter" v-for="(ite, ind) in Object.keys(item)" :key="ind">
<el-input v-model.trim="queryParams[item[ite].parameter]" :placeholder="item[ite].placeholder"></el-input>
</el-form-item>
</div>
<div>
@@ -114,7 +104,7 @@ import pageHeader from '@/components/Pageheader/index.vue';
import { getCommunitylistAPI } from '@/api/system/community';
import { ColumnConfig, exportToExcel } from '@/utils/xlsx';
import { listHouseUseType } from '@/api/system/houseUse';
import { getDailyFeeReportList } from '@/api/system/report/dailyFeeReport';
import { getDailyFeeReportDynamicList, getDailyFeeReportList } from '@/api/system/report/dailyFeeReport';
import { Datum } from '@/api/system/report/dailyFeeReport/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -124,18 +114,6 @@ const showSearch = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const data = reactive({
queryParams: {
pageNum: 1,
pageSize: 10,
villageId: '',
houseUseTypeId: '',
customerName: ''
}
});
const { queryParams } = toRefs(data);
// 查询小区
const villageList = ref([]);
function getAllVillage() {
@@ -152,6 +130,42 @@ function getHouseUseList() {
});
}
const queryParams = ref({
pageNum: 1,
pageSize: 10
});
// 参数列表
const queryParamsList = ref([]);
function getQueryParams() {
getDailyFeeReportDynamicList().then((res) => {
const obj = {};
const list = res.data.map((item) => {
const obj2 = {};
const list = item.field.split(',') ?? [];
console.log(list);
list.forEach((item2) => {
obj[item2] = '';
obj2[item2] = {
label: item.label,
parameter: item2,
placeholder: item.placeholder,
type: item.type,
subField: item.subField
};
});
return obj2;
});
queryParams.value = {
...queryParams.value,
...obj
};
queryParamsList.value = list;
console.log(list);
});
}
const rowChargeTypesList = ref([]);
/** 查询电抄记录列表 */
@@ -166,7 +180,7 @@ const getList = async () => {
});
getDailyFeeReportList(search)
.then((res) => {
ArrearsDetailList.value = [...res.rows];
ArrearsDetailList.value = [...(res.rows ?? [])];
rowChargeTypesList.value = Object.keys(res.rows[0].chargeTypeAmounts);
total.value = res.total;
})
@@ -193,10 +207,7 @@ const resetQuery = () => {
queryFormRef.value?.resetFields();
queryParams.value = {
pageNum: 1,
pageSize: 10,
villageId: '-1',
houseUseTypeId: '',
customerName: ''
pageSize: 10
};
handleQuery();
};
@@ -285,6 +296,7 @@ onMounted(() => {
getList();
getHouseUseList();
getAllVillage();
getQueryParams();
});
</script>

View File

@@ -27,8 +27,8 @@
<DictTag :options="com_id_card_type" :value="userInfo.idCardType"></DictTag>
</div>
<div class="userinfo_item">
<div class="title_item">住户类型</div>
<DictTag :options="com_resident_relationship" :value="userInfo.type"></DictTag>
<div class="title_item">与主业主关系</div>
<DictTag :options="com_resident_relationship" :value="userInfo.ownerRelationship"></DictTag>
</div>
<!-- <div class="userinfo_item">
<div class="title_item">住户来源</div>
@@ -163,6 +163,7 @@ const userInfo = ref<ResidentVO>({
nickName: '',
unitNoId: '',
idCardType: '0',
ownerRelationship: '0',
'id': null,
'name': '',
'type': '0',

View File

@@ -33,7 +33,7 @@
</el-row>
</template>
<el-table class="tablebody" v-loading="loading" border :data="storeroomList" @selection-change="handleSelectionChange">
<el-table class="tableBody" v-loading="loading" border :data="storeroomList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="楼栋名" align="center" prop="buildingName" />
<el-table-column label="单元号" show-overflow-tooltip align="center" prop="unitName" />
@@ -101,8 +101,7 @@ const data = reactive<PageData<StoreroomForm, StoreroomQuery>>({
shareArea: undefined,
internalArea: undefined,
houseId: undefined,
status: undefined,
params: {}
status: undefined
},
rules: {
storeroomNo: [{ required: true, message: '储藏室号不能为空', trigger: 'blur' }]
@@ -179,7 +178,7 @@ onMounted(() => {
flex: 1;
display: flex;
flex-direction: column;
.tablebody {
.tableBody {
flex: 1;
display: flex;
flex-direction: column;

View File

@@ -12,7 +12,7 @@
<el-input maxlength="16" show-word-limit v-model.trim="form.userName" placeholder="请输入登录账号" />
</el-form-item>
<el-form-item label="登录密码" v-if="form.userId == undefined" prop="password">
<el-input type="password" clearable v-model.trim="form.password" placeholder="请输入" />
<el-input type="password" show-password clearable v-model.trim="form.password" placeholder="请输入" />
</el-form-item>
<el-form-item label="员工性别" prop="chargeScope">
<el-select v-model="form.sex" placeholder="请选择">

View File

@@ -565,7 +565,7 @@ onMounted(() => {
...JSON.parse(sessionStorage.getItem('queryParams') || '{}')
};
getViliageList(); // 初始化部门数据
getList(); // 初始化列表数据╬«>
getList(); // 初始化列表数据
proxy?.getConfigKey('sys.user.initPassword').then((response) => {
initPassword.value = response.data;
});

View File

@@ -101,7 +101,7 @@
<el-option v-for="(item, index) in getlastVersionlist" :key="index" :label="item.versionName" :value="item.versionCode"></el-option>
</el-select>
<el-select v-else v-model="form.minVersionCode" placeholder="请输入最低支持版本">
<el-option label="1.0.0" :value="1"></el-option>
<el-option label="1.0.0" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="渠道" prop="channel">
@@ -112,7 +112,7 @@
<el-radio v-if="form.platform !== appType.ios" value="vivo">vivo</el-radio>
<el-radio v-if="form.platform !== appType.ios" value="yyb">应用宝</el-radio>
<el-radio v-if="form.platform !== appType.ios" value="honor">荣耀</el-radio>
<el-radio value="ios">ios</el-radio>
<el-radio v-else value="ios">ios</el-radio>
</el-radio-group>
</el-form-item>
@@ -192,7 +192,7 @@ const initFormData: VersionForm = {
downloadUrl: undefined,
releaseNotes: undefined,
fileSize: undefined,
appChannel: undefined,
appChannel: 'resident',
status: undefined,
channel: undefined
};
@@ -207,7 +207,7 @@ const data = reactive<PageData<VersionForm, VersionQuery>>({
appChannel: undefined
},
rules: {
channel: [{ required: true, message: 'App应用不能为空', trigger: 'blur' }],
channel: [{ required: true, message: 'App渠道不能为空', trigger: 'blur' }],
platform: [{ required: true, message: 'App类型不能为空', trigger: 'blur' }],
versionCode: [{ required: true, message: '版本号不能为空', trigger: 'blur' }],
versionName: [{ required: true, message: '版本名称不能为空', trigger: 'blur' }],
@@ -314,7 +314,7 @@ function handleChangePlatform() {
form.value.updateType = updateType.optional;
form.value.method = updatePackageType.apk;
form.value.downloadUrl = '';
form.value.channel = '';
if (form.value.platform === 'ios') {
form.value.channel = 'ios';
handleChangeChannel(form.value.channel);