房屋详情,单元变更

This commit is contained in:
Zy
2026-05-21 14:13:28 +08:00
parent 9645412534
commit 38274ab612
68 changed files with 1867 additions and 568 deletions

View File

@@ -21,65 +21,52 @@
</el-form-item>
<!-- 水费电费 收费范围为 房屋 -->
<el-form-item label="收费范围" prop="chargeScope" v-if="typeNamelist.includes(typeName)">
<el-radio-group v-model="form.chargeScope">
<el-radio v-for="(item, index) in com_bill_charge_scope_house" :key="index" :value="item.value" :label="item.label"></el-radio>
</el-radio-group>
<div @click="handleClearCheckout" v-if="form.chargeScope === '1'" class="ml-10px cursor-pointer color-red">清空</div>
<div class="flex flex-row flex-items-end">
<el-radio-group v-model="form.chargeScope">
<div class="flex flex-col flex-items-end">
<el-radio
style="margin-right: 0"
v-for="(item, index) in com_bill_charge_scope_house"
:key="index"
:value="item.value"
:label="item.label"
></el-radio>
</div>
</el-radio-group>
<div style="height: 32px">
<el-button @click="OpenUseTablesfun('house')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
</div>
</div>
</el-form-item>
<!-- 其他费用 收费范围为 业主 -->
<el-form-item label="收费范围" prop="chargeScope" v-else>
<el-radio-group v-model="form.chargeScope">
<el-radio v-for="(item, index) in com_questionnaire_scope" :key="index" :value="item.value" :label="item.label"></el-radio>
</el-radio-group>
<div @click="handleClearCheckout" v-if="form.chargeScope === '1'" class="ml-10px cursor-pointer color-red">清空</div>
<div class="flex flex-row flex-items-end">
<el-radio-group v-model="form.chargeScope">
<div class="flex flex-col flex-items-end">
<el-radio
style="margin-right: 0"
v-for="(item, index) in com_questionnaire_scope"
:key="index"
:value="item.value"
:label="item.label"
></el-radio>
</div>
</el-radio-group>
<div style="height: 32px">
<el-button @click="OpenUseTablesfun('user')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
</div>
</div>
</el-form-item>
<!-- 房屋选择 -->
<el-form-item v-if="form.chargeScope === '1' && typeNamelist.includes(typeName)">
<div class="residentBox">
<ul class="checkoutSideUsesbox">
<li v-for="(item, index) in checkoutHouses" :key="index">
<span>{{ item.buildingName }}/</span>
<span>{{ item.unitNo }}单元/</span>
<span>{{ item.floorNo }}/</span>
<span>{{ item.houseNo }}</span>
<el-icon @click="deleteHouse(item.houseId)">
<Delete></Delete>
</el-icon>
</li>
<House returnvalue="*" ref="HolderRef" :isMultiple="true" :userid="form.houseIds.join(',')" @change="handleSelect">
<template #default>
<li @click="OpenUseTablesfun('house')" class="add justify-center">
<el-icon>
<DocumentAdd></DocumentAdd>
</el-icon>
<span>添加房屋</span>
</li>
</template>
</House>
</ul>
<House returnvalue="houseId" ref="HolderRef" :isMultiple="true" @change="handleSelect"> </House>
</div>
</el-form-item>
<!-- 业主选择 -->
<el-form-item v-if="form.chargeScope === '1' && !typeNamelist.includes(typeName)">
<div class="residentBox">
<ul class="checkoutSideUsesbox">
<li v-for="(item, index) in checkoutUser" :key="index">
<span>{{ item.house_name }} / {{ item.residentName }} / {{ item.phone }}</span>
<el-icon @click="delteUser(item.residentId)">
<Delete></Delete>
</el-icon>
</li>
<UserHolder returnvalue="*" ref="userRef" :isMultiple="true" :userid="form.residentIds" @change="handleCheckUser">
<template #default>
<li @click="OpenUseTablesfun('user')" class="add justify-center">
<el-icon>
<DocumentAdd></DocumentAdd>
</el-icon>
<span>添加业主</span>
</li>
</template>
</UserHolder>
</ul>
<UserHolder returnvalue="residentId" ref="userRef" :isMultiple="true" @change="handleCheckUser"></UserHolder>
</div>
</el-form-item>
<el-form-item label="费用周期" prop="chargePeriod">
@@ -174,19 +161,19 @@ function handleDate(val: string[]) {
// 收费类型
const chargeitemlist = ref([]);
// 房屋列表
const houselist = ref([]);
// 住户列表
const userlist = ref([]);
// // 房屋列表
// const houselist = ref([]);
// // 住户列表
// const userlist = ref([]);
async function init() {
listChargeItem().then((res) => {
chargeitemlist.value = res.rows;
});
const res = await listBillHouse({ pageNum: 1, pageSize: 999999 });
houselist.value = res.rows;
const res2 = await queryResidentList_holder({ pageNum: 1, pageSize: 999999 });
userlist.value = res2.rows;
// const res = await listBillHouse({ pageNum: 1, pageSize: 999999 });
// houselist.value = res.rows;
// const res2 = await queryResidentList_holder({ pageNum: 1, pageSize: 999999 });
// userlist.value = res2.rows;
if (route.query.id) {
userid.value = route.query.id;
@@ -196,31 +183,20 @@ async function init() {
...form.value,
...res.data
};
// TODO 没有住户参数
form.value.houseIds = res.data.houseIds || [];
form.value.residentIds = res.data.residentIds || [];
form.value.startDate = formatDate2(form.value.startDate);
form.value.endDate = formatDate2(form.value.endDate);
StartEndDate.value = [form.value.startDate, form.value.endDate];
// TODO houseid 有默认值, 需要处理
// TODO residentids 添加,
checkoutHouses.value = form.value.houseIds
.map((item) => {
if (item) {
const find = houselist.value.find((it) => it.houseId === item);
if (find) {
return find;
} else {
return null;
}
}
})
.filter((item) => item !== null);
checkoutHouses.value = form.value.houseIds.filter((item) => item);
handleChange(form.value.chargeItemId);
});
}
}
onMounted(() => {
init();
});
init();
const typeNamelist = ref(['2049026484272791553', '2049026503017136129']);
const typeName = ref('');
@@ -239,33 +215,26 @@ function handleChange(val: string) {
const HolderRef = ref<InstanceType<typeof House>>();
const userRef = ref<InstanceType<typeof UserHolder>>();
function OpenUseTablesfun(val: string) {
console.log(val);
if (val === 'house') {
HolderRef.value.open();
HolderRef.value.open(checkoutHouses.value);
} else if (val === 'user') {
userRef.value.open();
userRef.value.open(checkoutUser.value);
}
}
// 多选
const checkoutHouses = ref<BillHouse[]>([]);
function handleSelect(val: BillHouse[]) {
const checkoutHouses = ref<string[]>([]);
function handleSelect(val: string[]) {
checkoutHouses.value = val;
form.value.houseIds = checkoutHouses.value.map((item) => item.houseId);
form.value.houseIds = checkoutHouses.value.map((item) => item).filter((item) => item);
}
// 多选
const checkoutUser = ref([]);
/** 添加 业主 */
function handleCheckUser(val) {
function handleCheckUser(val: string[]) {
checkoutUser.value = val;
form.value.residentIds = checkoutUser.value.map((item) => item.residentId);
}
/** 删除房屋 */
function deleteHouse(id: string) {
checkoutHouses.value = checkoutHouses.value.filter((item) => item.houseId !== id);
}
/** 删除业主 */
function delteUser(id: string) {
checkoutUser.value = checkoutUser.value.filter((item) => item.residentId !== id);
console.log(val);
form.value.residentIds = val;
}
/** 清空 */

View File

@@ -122,7 +122,7 @@ const dialog = reactive<DialogOption>({
title: ''
});
const ShowHouselist = ['2049026484272791553'];
const ShowHouselist = ['2049026484272791553', '2049026503017136129'];
const initFormData: BillForm = {
id: undefined,

View File

@@ -61,7 +61,6 @@
</template>
<script setup lang="ts">
// TODO 添加临时收费
// TODO 预存
import { Search } from '@element-plus/icons-vue';
import { Component, ref } from 'vue';

View File

@@ -131,13 +131,13 @@
<el-button link type="primary" @click="handleOpenDialog('usedWater', scope.row)" v-hasPermi="['equipment:useWater:electricitydevice']"
>用电量</el-button
>
<el-button
<!-- <el-button
link
type="primary"
@click="handleOpenDialog('Upload', scope.row)"
v-hasPermi="['equipment:updatehardware:electricitydevice']"
>更新固件</el-button
>
> -->
<el-button
link
type="primary"

View File

@@ -6,9 +6,10 @@
<el-row :gutter="10" style="font-size: 0.8rem; font-weight: 450">
<el-col :span="4"> 设备号 {{ routeid }} </el-col>
<el-col :span="4"> 房屋号 {{ housename }} </el-col>
<el-col :span="14"></el-col>
<el-col :span="2">
<el-col :span="12"></el-col>
<el-col :span="4" class="flex">
<el-button @click="confinem">返回</el-button>
<el-button type="warning" @click="handleExport">导出数据</el-button>
</el-col>
</el-row>
</template>
@@ -35,6 +36,7 @@ import { TopupRecordVO, TopupRecordQuery, TopupRecordForm } from '@/api/system/S
const router = useRouter();
const route = useRoute();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const routeid = ref(null);
const topupRecordList = ref<TopupRecordVO[]>([]);
@@ -46,6 +48,7 @@ const initFormData: TopupRecordForm = {
deviceCode: undefined,
type: undefined
};
const data = reactive<PageData<TopupRecordForm, TopupRecordQuery>>({
form: { ...initFormData },
queryParams: {
@@ -82,6 +85,17 @@ onMounted(() => {
const confinem = () => {
router.back();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'/topupRecord/export',
{
...queryParams.value
},
`${queryParams.value.type === '2' ? '水表' : '电表'}${routeid.value}-充值记录.xlsx`
);
};
</script>
<style lang="scss" scoped>

View File

@@ -44,8 +44,8 @@
<el-dropdown-item @click="handleMarkQrcodeZip">
<span>批量下载条形码</span>
</el-dropdown-item>
<!-- <el-dropdown-item v-hasPermi="['equipment:addqrcode:electricitydevice']">
<div @click="handleMarkqrcode">批量更新固件</div>
<!-- <el-dropdown-item v-hasPermi="['equipment:updatehardware:waterdevice']">
<div @click="handleMarkUpload">批量更新固件</div>
</el-dropdown-item> -->
</template>
</right-toolbar>
@@ -127,7 +127,7 @@
<el-button link type="primary" @click="handleOpenDialog('Upload', scope.row)" v-hasPermi="['equipment:updatehardware:waterdevice']"
>更新固件</el-button
>
<el-button link type="primary" @click="handleUpdate(scope.row.deviceCode)">最新抄表记录</el-button>
<!-- <el-button link type="primary" @click="handleUpdate(scope.row.deviceCode)">最新抄表记录</el-button> -->
<el-button link type="primary" @click="handleOpenDialog('UpdateHouse', scope.row)" v-hasPermi="['equipment:edithouse:waterdevice']"
>绑定房屋</el-button
@@ -197,15 +197,23 @@
</el-form>
<!-- upload file -->
<el-form v-else-if="dialogType === 'Upload'" ref="UploadFileformRef" :model="UploadFileform" :rules="UploadFileformRules" label-width="140px">
<el-form-item label="上传 A槽更新 文件" prop="fileA">
<el-form-item label="LEN_A" prop="lenA">
<el-input v-model="UploadFileform.lenA"></el-input>
</el-form-item>
<el-form-item label="CRC32_HEX_A" prop="crcA">
<el-input v-model="UploadFileform.crcA"></el-input>
</el-form-item>
<el-form-item label="上传 A槽更新 文件" prop="urlA">
<el-upload
ref="uploadRef"
ref="uploadARef"
accept=".bin"
:action="uploadAUrl"
name="file"
:headers="headerToken()"
:limit="1"
:show-file-list="true"
class="upload-demo"
:on-exceed="handleExceedA"
:on-success="handleAvatarSuccessA"
:before-upload="beforeAvatarUpload"
>
@@ -220,15 +228,24 @@
</template>
</el-upload>
</el-form-item>
<el-form-item label="上传 B槽更新 文件" prop="fileB">
<el-form-item label="LEN_B" prop="lenB">
<el-input v-model="UploadFileform.lenB"></el-input>
</el-form-item>
<el-form-item label="CRC32_HEX_B" prop="crcB">
<el-input v-model="UploadFileform.crcB"></el-input>
</el-form-item>
<el-form-item label="上传 B槽更新 文件" prop="urlB">
<el-upload
ref="uploadRef"
ref="uploadBRef"
accept=".bin"
:action="uploadBUrl"
name="file"
:limit="1"
:headers="headerToken()"
:show-file-list="true"
class="upload-demo"
:on-exceed="handleExceedB"
:on-success="handleAvatarSuccessB"
:before-upload="beforeAvatarUpload"
>
@@ -301,6 +318,7 @@ import { Upload } from '@element-plus/icons-vue';
import { CascaderValue, UploadProps, UploadRawFile } from 'element-plus';
import { checkPermi } from '@/utils/permission';
import { exportImagesToZip } from '@/utils/exportZip';
import { genFileId } from 'element-plus';
const uploadAUrl = import.meta.env.VITE_APP_BASE_API + '/waterDevice/uploadA';
const uploadBUrl = import.meta.env.VITE_APP_BASE_API + '/waterDevice/uploadB';
@@ -390,14 +408,20 @@ const rules = {
// ? 上传固件 ==============================================================================================
const UploadFileformRef = ref(null);
const uploadRef = ref();
const uploadBRef = ref();
const uploadARef = ref();
const UploadFileform = ref({
deviceCodes: [],
urlA: '',
urlB: ''
lenA: '',
crcA: '',
urlB: '',
crcB: '',
lenB: ''
});
const UploadFileformRules = {
file: [{ required: true, message: '更新文件不能为空', trigger: 'blur' }]
urlA: [{ required: true, message: 'A更新文件不能为空', trigger: 'blur' }],
urlB: [{ required: true, message: 'B更新文件不能为空', trigger: 'blur' }]
};
function headerToken() {
const useStore = useUserStore();
@@ -431,16 +455,27 @@ const handleAvatarSuccessA: UploadProps['onSuccess'] = (response: any) => {
const handleAvatarSuccessB: UploadProps['onSuccess'] = (response: any) => {
UploadFileform.value.urlB = response.data.url;
};
const handleExceedB: UploadProps['onExceed'] = (files) => {
uploadBRef.value!.clearFiles();
const file = files[0] as UploadRawFile;
file.uid = genFileId();
uploadBRef.value!.handleStart(file);
uploadBRef.value!.submit();
};
const handleExceedA: UploadProps['onExceed'] = (files) => {
uploadARef.value!.clearFiles();
const file = files[0] as UploadRawFile;
file.uid = genFileId();
uploadARef.value!.handleStart(file);
uploadARef.value!.submit();
};
// ? 上传固件 ==============================================================================================
// * 编辑房屋 ==============================================================================================
// 编辑房屋
const EditHouseformRef = ref(null);
const EditHouseformRules = {
fileA: [{ required: true, message: 'A文件不能为空', trigger: 'blur' }],
fileB: [{ required: true, message: 'B文件不能为空', trigger: 'blur' }]
};
const EditHouseformRules = {};
const EditHouseform = ref({
id: '',
deviceCode: '',
@@ -483,6 +518,17 @@ function handleMarkQrcodeZip() {
ElMessage.warning('请选择设备');
}
}
function handleMarkUpload() {
if (ids.value.length > 0) {
reset();
UploadFileform.value.deviceCodes = ids.value.map((item) => item.deviceCode).filter((item) => item);
dialog.title = '固件上传';
dialog.visible = true;
dialogType.value = 'Upload';
} else {
ElMessage.warning('请选择设备');
}
}
function produceQRzip(vals: WaterDeviceVO[]) {
const arr = vals.map((item) => {
@@ -623,7 +669,14 @@ const submitForm = () => {
}
});
} else if (dialogType.value === 'Upload') {
WaterDeviceUpdateBin(UploadFileform.value);
UploadFileformRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
await WaterDeviceUpdateBin(UploadFileform.value).finally(() => (buttonLoading.value = false));
proxy?.$modal.msgSuccess('操作成功');
unSubmit();
}
});
}
};
const unSubmit = () => {
@@ -653,6 +706,10 @@ const reset = () => {
UploadFileform.value.deviceCodes = [];
UploadFileform.value.urlA = '';
UploadFileform.value.urlB = '';
UploadFileform.value.lenA = '';
UploadFileform.value.crcA = '';
UploadFileform.value.lenB = '';
UploadFileform.value.crcB = '';
// 上传 清空
UploadFileformRef.value?.resetFields();