7/17 添加公区收益

This commit is contained in:
Zy
2026-07-21 17:32:22 +08:00
parent 37970c547b
commit 0c4c9676b5
41 changed files with 1583 additions and 132 deletions

View File

@@ -108,7 +108,7 @@ import repairUser from '@/components/Holder/repairUser.vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { getComplaint, updateComplaint } from '@/api/system/Complaint';
import { listComplaintType } from '@/api/system/ComplainType';
import { ResidentVO } from '@/api/system/resident/type';
import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_complaint_status } = toRefs<any>(proxy?.useDict('com_complaint_status'));

View File

@@ -57,23 +57,25 @@
<el-col :span="12">
<el-form-item label="附属材料">
<el-upload
:auto-upload="false"
class="upload-demo"
:file-list="fileList"
:action="uploadUrl"
:multiple="true"
:auto-upload="false"
ref="uploadRef"
:show-file-list="true"
name="files"
:headers="headerToken()"
:show-file-list="true"
:on-remove="handleAvatarRemove"
:on-change="handleProgress"
:before-upload="beforeAvatarUpload"
accept=".doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.bmp,.webp"
>
<div class="uploadBtn flex flex-items-center">
<el-icon><Upload /></el-icon>
<span>上传文件</span>
</div>
<template #tip>仅支持doc/docx/xls/xlsx/jpg/png/gif等</template>
</el-upload>
</el-form-item>
</el-col>
@@ -144,14 +146,16 @@ const handleAvatarRemove: UploadProps['onRemove'] = (uploadFile: UploadUserFile,
// 定义大小限制常量 (单位: MB)
const MAX_SINGLE_FILE_SIZE = 10 * 1024 * 1024; // 10MB in bytes
const MAX_TOTAL_FILE_SIZE = 20 * 1024 * 1024; // 20MB in bytes
// 禁止的危险文件后缀
const forbidSuffix = ['exe', 'msi', 'bat', 'cmd', 'sh', 'apk', 'dmg'];
const uploadRef = ref();
// 添加一个锁,防止 on-change 递归调用导致重复提示
const isChecking = ref(false);
const handleProgress: UploadProps['onChange'] = (uploadFile: UploadUserFile, uploadFiles: UploadFiles) => {
// 如果正在校验中,直接返回,避免重复执行
if (!beforeAvatarUpload(uploadFile)) {
uploadRef.value.handleRemove(uploadFile);
return;
}
if (isChecking.value) return;
// 加锁
isChecking.value = true;
// 创建一个新数组来存储校验通过的文件
@@ -229,12 +233,41 @@ const handleProgress: UploadProps['onChange'] = (uploadFile: UploadUserFile, upl
};
const blockedExts = ['.exe', '.bat', '.cmd', '.msi'];
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
const allowExts = [
// word
'.doc',
'.docx',
'.dot',
'.dotx',
// excel
'.xls',
'.xlsx',
'.xlsm',
'.xlsb',
// img
'.jpg',
'.jpeg',
'.png',
'.gif',
'.bmp',
'.webp',
// 专业/矢量图
'.psd',
'.ai',
'.svg',
'.tif',
'.tiff'
];
const beforeAvatarUpload = (rawFile: UploadUserFile) => {
const ext = rawFile.name.toLowerCase().slice(rawFile.name.lastIndexOf('.'));
if (blockedExts.includes(ext)) {
ElMessage.warning(`禁止上传 ${ext} 文件`);
return false;
}
if (!allowExts.includes(ext)) {
ElMessage.warning('只能上传word,excel,图片等文件');
return false;
}
return true;
};

View File

@@ -48,6 +48,7 @@
:height="500"
:min-height="300"
:read-only="false"
type="url"
:file-size="5"
/>
</el-form-item>
@@ -71,7 +72,6 @@ import PageHeader from '@/components/Pageheader/index.vue';
import { addNotice, getNotice } from '@/api/system/NoticePc';
import { updateNotice } from '@/api/system/NoticePc';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_noticepc_level } = toRefs<any>(proxy?.useDict('com_noticepc_level'));
const { com_publish_status } = toRefs<any>(proxy?.useDict('com_publish_status'));
const route = useRoute();
@@ -94,6 +94,7 @@ const rules = {
const userid = ref();
// ! 富文本 =============================================================================================================
function handleContent(val: string) {
console.log(val);
form.value.noticeContent = val.trim();
}
// ! 富文本 =============================================================================================================
@@ -134,9 +135,7 @@ const submitForm = () => {
// 返回
function handleBack() {
router.push({
path: '/repair/noticepc'
});
router.back();
}
</script>

View File

@@ -47,23 +47,23 @@
<dict-tag :options="com_publish_status" :value="scope.row.publishStatus"></dict-tag>
</template>
</el-table-column>
<el-table-column label="已读" width="120" align="center" prop="readNum">
<el-table-column label="已读" align="center" prop="readNum">
<template #default="scope">
<span>{{ scope.row.readNum ?? '--' }} </span>
</template>
</el-table-column>
<el-table-column label="未读" width="120" align="center" prop="unReadNum">
<el-table-column label="未读" align="center" prop="unReadNum">
<template #default="scope">
<span>{{ scope.row.unReadNum ?? '--' }} </span>
</template>
</el-table-column>
<el-table-column label="发布人" align="center" prop="publishBy" />
<el-table-column label="发布日期" align="center" prop="publishTime" width="100">
<template #default="scope">
<span>{{ parseTime(scope.row.publishTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="220" fixed="right" class-name="small-padding fixed-width">
<!-- <el-table-column label="发布人" align="center" prop="publishBy" />-->
<!-- <el-table-column label="发布日期" align="center" prop="publishTime" width="100">-->
<!-- <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">
<template #default="scope">
<el-button link type="primary" @click="handleMain(scope.row)">详情</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['notice:notice:edit']">编辑</el-button>
@@ -94,7 +94,6 @@ import { NoticeVO, NoticeQuery, NoticeForm } from '@/api/system/NoticePc/type';
import { checkPermi } from '@/utils/permission';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_noticepc_level } = toRefs<any>(proxy?.useDict('com_noticepc_level'));
const { com_publish_status } = toRefs<any>(proxy?.useDict('com_publish_status'));
const noticeList = ref<NoticeVO[]>([]);

View File

@@ -73,7 +73,7 @@ const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnair
const router = useRouter();
const route = useRoute();
import { listResident } from '@/api/system/resident';
import { listResident } from '@/api/system/residentReviewProcess/resident';
const form = ref({
scope: '0',

View File

@@ -218,7 +218,7 @@
</el-form-item>
</div>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" show-word-limit maxlength="100" :rows="10" v-model="inComeFrom.remark"></el-input>
<el-input type="textarea" show-word-limit maxlength="100" :rows="5" v-model="inComeFrom.remark"></el-input>
</el-form-item>
<div class="flex justify-end">
<el-button @click="closer">取消</el-button>
@@ -234,7 +234,7 @@
</div>
</template>
<div class="printBox" id="printBox-Bill">
<div class="printBox" id="printBox-Bill" style="padding: 0; margin: 0">
<div class="title">{{ print_form.title }}</div>
<div class="nav gridBox">
<div>单据日期{{ print_form.printDate }}</div>
@@ -254,7 +254,7 @@
<th style="min-width: 80px">优免金额</th>
<th style="min-width: 80px">实收金额</th>
<th style="min-width: 80px">收款方式</th>
<th style="width: 200px">备注</th>
<th style="min-width: 100px">备注</th>
</tr>
</thead>
<tbody>
@@ -283,7 +283,7 @@
</tbody>
</table>
<p style="font-size: 10px">说明本收据收款单位和收款具签章方为有效本收据手写无效</p>
<div class="flex flex-items-center" style="font-size: 12px">
<div class="flex flex-items-center" style="font-size: 12px; margin-bottom: 0">
<div class="flex-1">交款人</div>
<div class="flex-1 flex flex-items-center">
<span style="white-space: nowrap">收款人 </span>
@@ -488,6 +488,7 @@ function initInComeFrom() {
discount: 0, // 优惠金额
residentName: '' // 缴费人
};
totalDiscountAmount.value = 0;
isMore = false;
}
// 改变优惠方式
@@ -598,6 +599,7 @@ function handleIncome(row: billlistType | false) {
inComeFrom.value.allCost = row.amount;
inComeFrom.value.billResidentId = [row];
inComeFrom.value.residentName = row.residentName;
totalDiscountAmount.value = Number(row.amount);
} else {
if (ids.value.length <= 0) return ElMessage.warning('请选择账单');
const set = new Set();

View File

@@ -267,7 +267,6 @@ function handleChange(pop) {
holderInfo.value = pop;
form.value.userId = '';
form.value.userName = '';
console.log(pop);
if (pop !== null) {
form.value.userId = pop.user_id;
form.value.userName = pop.user_name;

View File

@@ -66,7 +66,7 @@
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/resident';
import { listResident } from '@/api/system/residentReviewProcess/resident';
import { checkPermi } from '@/utils/permission';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;

View File

@@ -299,7 +299,7 @@ const handleChangeFile = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
const ext = uploadFile.name.toLowerCase().slice(uploadFile.name.lastIndexOf('.'));
if (blockedExts.includes(ext)) {
ElMessage.warning(`禁止上传 ${ext} 文件`);
fileList.value = uploadFiles.filter((f) => f.uid !== uploadFile.uid);
uploadRef.value.handleRemove(uploadFile);
return;
}
fileList.value = uploadFiles;

View File

@@ -34,12 +34,14 @@
</el-col>
<el-col :span="14"></el-col>
<el-col :span="5" style="text-align: right">
<el-button type="warning" @click="exportCurrentPage">导出当前页</el-button>
<el-button type="warning" @click="exportAll">导出所有</el-button>
<el-button type="primary" @click="exportChecked">导出选中</el-button>
<el-button type="primary" @click="exportCurrentPage">导出当前页</el-button>
<el-button type="primary" @click="exportAll">导出所有</el-button>
</el-col>
</el-row>
</template>
<el-table v-loading="loading" border :data="itemList">
<el-table v-loading="loading" border row-key="id" :data="itemList" @selectionChange="handleChange">
<el-table-column type="selection" width="55" />
<el-table-column label="日期" width="100" align="center" prop="statDate" />
<el-table-column label="计划巡检任务" width="120" align="center" prop="totalPlans" />
<el-table-column label="按时完成" align="center" prop="completedTasks" />
@@ -126,6 +128,26 @@ const exportAll = () => {
`巡检日报_${new Date().toLocaleString()}.xlsx`
);
};
const multipleSelection = ref([]);
function handleChange(val) {
multipleSelection.value = val;
}
const exportChecked = () => {
if (multipleSelection.value.length > 0) {
const listValue = multipleSelection.value.map((item) => item.id);
console.log(listValue);
proxy?.download(
'/inspection/data/export/selected',
{
list: listValue.join(','),
dataType: '1'
},
`巡检日报_选中${listValue.length}条数据_${new Date().toLocaleString()}.xlsx`,
);
} else {
ElMessage.warning('请选择数据');
}
};
onMounted(() => {
getList();

View File

@@ -34,13 +34,15 @@
</el-col>
<el-col :span="14"> </el-col>
<el-col :span="5" style="text-align: right">
<el-button type="warning" @click="exportCurrentPage">导出当前页</el-button>
<el-button type="warning" @click="exportAll">导出所有</el-button>
<el-button type="primary" @click="exportCurrentPage">导出当前页</el-button>
<el-button type="primary" @click="exportAll">导出所有</el-button>
<el-button type="primary" @click="exportChecked">导出选中</el-button>
</el-col>
</el-row>
</template>
<el-table v-loading="loading" border :data="itemList">
<el-table v-loading="loading" border :data="itemList" @selectionChange="handleChange">
<el-table-column type="selection" width="55" />
<el-table-column label="日期" width="100" align="center" prop="statDate" />
<el-table-column label="计划巡检任务" width="120" align="center" prop="totalPlans" />
<el-table-column label="按时完成" align="center" prop="completedTasks" />
@@ -125,6 +127,26 @@ const exportAll = () => {
`巡检月报_${new Date().toLocaleString()}.xlsx`
);
};
const multipleSelection = ref([]);
function handleChange(val) {
multipleSelection.value = val;
}
const exportChecked = () => {
if (multipleSelection.value.length > 0) {
const listValue = multipleSelection.value.map((item) => item.id);
console.log(listValue);
proxy?.download(
'/inspection/data/export/selected',
{
list: listValue.join(','),
dataType: '3'
},
`巡检月报_选中${listValue.length}条数据_${new Date().toLocaleString()}.xlsx`
);
} else {
ElMessage.warning('请选择数据');
}
};
onMounted(() => {
getList();
});

View File

@@ -34,13 +34,15 @@
</el-col>
<el-col :span="14"> </el-col>
<el-col :span="5" style="text-align: right">
<el-button type="warning" @click="exportCurrentPage">导出当前页</el-button>
<el-button type="warning" @click="exportAll">导出所有</el-button>
<el-button type="primary" @click="exportCurrentPage">导出当前页</el-button>
<el-button type="primary" @click="exportAll">导出所有</el-button>
<el-button type="primary" @click="exportChecked">导出选中</el-button>
</el-col>
</el-row>
</template>
<el-table v-loading="loading" border :data="itemList">
<el-table v-loading="loading" border :data="itemList" @selectionChange="handleChange">
<el-table-column type="selection" width="55" />
<el-table-column label="日期" width="120" align="center" prop="statDate" />
<el-table-column label="计划巡检任务" width="120" align="center" prop="totalPlans" />
<el-table-column label="按时完成" align="center" prop="completedTasks" />
@@ -129,6 +131,27 @@ const exportAll = () => {
onMounted(() => {
getList();
});
const multipleSelection = ref([]);
function handleChange(val) {
multipleSelection.value = val;
}
const exportChecked = () => {
if (multipleSelection.value.length > 0) {
const listValue = multipleSelection.value.map((item) => item.id);
console.log(listValue);
proxy?.download(
'/inspection/data/export/selected',
{
list: listValue.join(','),
dataType: '2'
},
`巡检周报_选中${listValue.length}条数据_${new Date().toLocaleString()}.xlsx`
);
} else {
ElMessage.warning('请选择数据');
}
};
</script>
<style lang="scss" scoped>

View File

@@ -139,8 +139,8 @@
<script setup lang="ts">
import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { getResident, getresidentReviewlistAPI, UpdateResidentReviewAPI } from '@/api/system/resident';
import { ResidentVO } from '@/api/system/resident/type';
import { getResident, getresidentReviewlistAPI, UpdateResidentReviewAPI } from '@/api/system/residentReviewProcess/resident';
import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_review } = toRefs<any>(proxy?.useDict('com_review'));

View File

@@ -107,10 +107,10 @@
import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { getHousePathById } from '@/utils/house';
import { ResidentForm } from '@/api/system/resident/type';
import { ResidentForm } from '@/api/system/residentReviewProcess/resident/type';
import { CascaderValue, UploadFiles, UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
import { genFileId } from 'element-plus';
import { addResident, getResident, updateResident } from '@/api/system/resident';
import { addResident, getResident, updateResident } from '@/api/system/residentReviewProcess/resident';
import { validator } from '@/utils/Reg';
import { useHouseStore } from '@/store/modules/house';
import { Plus } from '@element-plus/icons-vue';

View File

@@ -96,8 +96,8 @@ import pageHeader from '@/components/Pageheader/index.vue';
import RightToolbar from '@/components/RightToolbar/index.vue';
import DictTag from '@/components/DictTag/index.vue';
import { listResident, delResident } from '@/api/system/resident';
import { ResidentVO, ResidentQuery, ResidentForm } from '@/api/system/resident/type';
import { listResident, delResident } from '@/api/system/residentReviewProcess/resident';
import { ResidentVO, ResidentQuery, ResidentForm } from '@/api/system/residentReviewProcess/resident/type';
import { useHouseStore } from '@/store/modules/house';
import { checkPermi } from '@/utils/permission';

View File

@@ -0,0 +1,259 @@
<template>
<div class="ResidentMainBox p-2 w-full">
<PageHeader></PageHeader>
<div class="ResidentMainBody">
<el-card>
<template #header>
<div class="title">基本信息</div>
</template>
<div class="addBuildingFormBody">
<div class="formbox">
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-row>
<el-col :span="12">
<el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model.trim="form.noticeTitle" placeholder="请输入公告标题" />
</el-form-item>
</el-col>
<!-- <el-col :span="12">-->
<!-- <el-form-item label="作者" prop="author">-->
<!-- <el-input v-model.trim="form.author" placeholder="请输入作者" />-->
<!-- </el-form-item>-->
<!-- </el-col>-->
</el-row>
<el-row>
<!-- <el-col :span="12">-->
<!-- <el-form-item label="公告紧急程度" prop="urgencyLevel">-->
<!-- <el-select v-model="form.urgencyLevel" clearable placeholder="请选择公告紧急程度">-->
<!-- <el-option v-for="dict in com_noticepc_level" :key="dict.value" :label="dict.label" :value="Number(dict.value)" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<!-- <el-col :span="12">-->
<!-- <el-form-item label="是否发布" prop="publishStatus">-->
<!-- <el-radio-group v-model="form.publishStatus">-->
<!-- <el-radio v-for="dict in com_publish_status" :key="dict.value" :value="Number(dict.value)">{{-->
<!-- dict.value === '0' ? dict.label : '发布'-->
<!-- }}</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
</el-row>
<el-row>
<el-col>
<el-form-item label="公告详情" prop="noticeContent">
<editor
@update:model-value="handleContent"
:model-value="form.noticeContent"
:height="500"
:min-height="300"
:read-only="false"
type="url"
:file-size="5"
/>
</el-form-item>
</el-col>
</el-row>
<!-- <el-row>-->
<!-- <el-col>-->
<!-- <el-form-item label="附加上传">-->
<!-- <el-upload-->
<!-- v-model:file-list="fileList"-->
<!-- class="upload-demo"-->
<!-- name="files"-->
<!-- :action="uploadUrl"-->
<!-- :headers="headerToken()"-->
<!-- :on-success="handleAvatarSuccess"-->
<!-- :on-remove="handleRemove"-->
<!-- :before-upload="beforeAvatarUpload"-->
<!-- >-->
<!-- <el-button type="primary">上传附件</el-button>-->
<!-- </el-upload>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<!-- </el-row>-->
<el-form-item>
<el-button type="primary" @click="submitForm">立即发布</el-button>
<el-button @click="handleBack">返回</el-button>
</el-form-item>
</el-form>
</div>
</div>
</el-card>
</div>
</div>
</template>
<script setup lang="ts">
import editor from '@/components/Editor/index.vue';
import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { addRevenueNotice, getRevenueNotice, updateRevenueNotice } from '@/api/system/revenueNotice';
import { ElMessage } from 'element-plus';
// import { useUserStore } from '@/store/modules/user';
// const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/revenueNotice/uploadAttachments';
// const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// const { com_publish_status } = toRefs<any>(proxy?.useDict('com_publish_status'));
// const useStore = useUserStore();
// function headerToken() {
// return {
// Authorization: 'Bearer ' + useStore.token
// };
// }
const route = useRoute();
const router = useRouter();
const formRef = ref();
const form = ref({
'id': null,
'author': '',
'noticeTitle': '',
'urgencyLevel': 0,
'publishStatus': 1,
'noticeContent': '',
attachments: []
});
const rules = {
noticeTitle: [{ required: true, message: '请输入公告标题', trigger: 'blur' }],
urgencyLevel: [{ required: true, message: '请选择紧急程度', trigger: 'blur' }],
author: [{ required: true, message: '请输入作者名称', trigger: 'blur' }],
noticeContent: [{ required: true, message: '请输入公告内容', trigger: 'blur' }]
};
const userid = ref();
function handleContent(val: string) {
form.value.noticeContent = val.trim();
}
// ! 投诉 ====================================================================================================
function init() {
getRevenueNotice(userid.value).then((res) => {
form.value = {
...form.value,
...res.data
};
// fileList.value = form.value.attachments.map((item) => {
// return {
// name: item.fileName,
// url: item.fileUrl
// };
// });
});
}
if (route.query.id) {
userid.value = route.query.id;
init();
}
// interface myUploadUserFile extends UploadUserFile {
// response: {
// code: number;
// msg: string;
// data: {
// success: {
// fileName: string;
// url: string;
// ossId: string;
// }[];
// error: string[];
// };
// };
// }
// const fileList = ref<myUploadUserFile[]>([]);
//
// const blockedExts = ['.exe', '.bat', '.cmd', '.msi'];
// const beforeAvatarUpload = (rawFile: UploadUserFile) => {
// const ext = rawFile.name.toLowerCase().slice(rawFile.name.lastIndexOf('.'));
// if (blockedExts.includes(ext)) {
// ElMessage.warning(`禁止上传 ${ext} 文件`);
// return false;
// }
// return true;
// };
// const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile, uploadFiles) => {};
// const handleRemove: UploadProps['onRemove'] = (_, uploadFiles) => {};
// 提交
const submitForm = () => {
form.value.attachments = [];
// if (fileList.value.length > 0) {
// fileList.value.forEach((item, index) => {
// if (item.response) {
// const file = item.response.data.success[0];
// const ext = file.fileName.toLowerCase().slice(file.fileName.lastIndexOf('.'));
// form.value.attachments.push({
// fileName: file.fileName,
// fileUrl: file.url,
// fileType: ext.split('.')[1],
// sort: index
// });
// } else {
// const ext = item.fileName.toLowerCase().slice(item.fileName.lastIndexOf('.'));
// form.value.attachments.push({
// fileName: item.fileName,
// fileUrl: item.url,
// fileType: ext.split('.')[1],
// sort: index
// });
// }
// });
// }
formRef.value?.validate(async (valid: boolean) => {
if (valid) {
if (userid.value) {
updateRevenueNotice(form.value).then(() => {
ElMessage.success('编辑成功');
handleBack();
});
} else {
addRevenueNotice(form.value).then(() => {
ElMessage.success('添加成功');
handleBack();
});
}
}
});
};
// 返回
function handleBack() {
router.back();
}
</script>
<style scoped lang="scss">
.ResidentMainBox {
display: flex;
flex-direction: column;
.ResidentMainBody {
margin-top: 20px;
flex: 1;
.formbox {
width: 1000px;
margin: 0 auto;
.upload-demo {
width: 100%;
}
}
&:deep(div.el-step__head.is-process) {
& > div.el-step__line {
width: 0;
border: 1px dashed gray;
background: transparent;
}
}
&:deep(.el-step.is-vertical .el-step__line) {
top: 20px;
}
&:deep(div.el-step__head.is-finish) {
& > div.el-step__line {
width: 0;
border: 1px solid var(--el-color-primary);
background: transparent;
}
}
}
}
</style>

View File

@@ -0,0 +1,276 @@
<template>
<div class="flex flex-col h-full p-2">
<pageHeader></pageHeader>
<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" :inline="true">
<el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" />
</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-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never" class="flex-1">
<template #header>
<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
:show-edit="checkPermi(['revenue:revenueNotice:edit'])"
:show-delete="checkPermi(['revenue:revenueNotice:remove'])"
:showAdd="checkPermi(['revenue:revenueNotice:add'])"
@update:add="handleAdd"
@update:edit="handleUpdate()"
@update:delete="handleDelete()"
></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="revenueNoticeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<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">
<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="Delete" @click="handleDelete(scope.row)" v-hasPermi="['revenue:revenueNotice:remove']"
>删除</el-button
>
</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>
<!-- 添加或修改公区收益通知对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="revenueNoticeFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model="form.noticeTitle" placeholder="请输入公告标题" />
</el-form-item>
<el-form-item label="公告内容">
<editor v-model="form.noticeContent" :min-height="192" />
</el-form-item>
<el-form-item label="作者" prop="author">
<el-input v-model="form.author" placeholder="请输入作者" />
</el-form-item>
<el-form-item label="紧急程度 0=普通 1=紧急 2=非常紧急" prop="urgencyLevel">
<el-input v-model="form.urgencyLevel" placeholder="请输入紧急程度" />
</el-form-item>
<el-form-item label="发布人" prop="publishBy">
<el-input v-model="form.publishBy" placeholder="请输入发布人" />
</el-form-item>
<el-form-item label="发布日期" prop="publishTime">
<el-date-picker clearable v-model="form.publishTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择发布日期">
</el-date-picker>
</el-form-item>
<el-form-item label="所属小区id" prop="villageId">
<el-input v-model="form.villageId" placeholder="请输入所属小区id" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="RevenueNotice" lang="ts">
import pageHeader from '@/components/Pageheader/index.vue';
import { listRevenueNotice, delRevenueNotice, addRevenueNotice, updateRevenueNotice } from '@/api/system/revenueNotice';
import { RevenueNoticeVO, RevenueNoticeQuery, RevenueNoticeForm } from '@/api/system/revenueNotice/type';
import { checkPermi } from '@/utils/permission';
import { NoticeVO } from '@/api/system/NoticePc/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// const { com_publish_status } = toRefs<any>(proxy?.useDict('com_publish_status'));
const revenueNoticeList = ref<RevenueNoticeVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const revenueNoticeFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: RevenueNoticeForm = {
noticeId: undefined,
noticeTitle: undefined,
noticeContent: undefined,
author: undefined,
urgencyLevel: undefined,
publishStatus: undefined,
publishBy: undefined,
publishTime: undefined,
villageId: undefined
};
const data = reactive<PageData<RevenueNoticeForm, RevenueNoticeQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
noticeTitle: undefined,
noticeContent: undefined,
author: undefined,
urgencyLevel: undefined,
publishStatus: undefined,
publishBy: undefined,
publishTime: undefined,
villageId: undefined,
params: {}
},
rules: {
noticeTitle: [{ required: true, message: '公告标题不能为空', trigger: 'blur' }],
urgencyLevel: [{ required: true, message: '紧急程度', trigger: 'blur' }],
publishStatus: [{ required: true, message: '发布状态', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询公区收益通知列表 */
const getList = async () => {
loading.value = true;
const res = await listRevenueNotice(queryParams.value);
revenueNoticeList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
revenueNoticeFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: RevenueNoticeVO[]) => {
ids.value = selection.map((item) => item.noticeId);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
const router = useRouter();
/** 新增按钮操作 */
const handleAdd = () => {
router.push({
path: '/repair/addRevenueNotice'
});
};
/** 修改按钮操作 */
const handleUpdate = (row?: NoticeVO) => {
const _id = row?.noticeId || ids.value[0];
router.push({
path: '/repair/editRevenueNotice',
query: {
id: _id
}
});
};
/** 提交按钮 */
const submitForm = () => {
revenueNoticeFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.noticeId) {
await updateRevenueNotice(form.value).finally(() => (buttonLoading.value = false));
} else {
await addRevenueNotice(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: RevenueNoticeVO) => {
const _noticeIds = row?.noticeId || ids.value;
await proxy?.$modal.confirm('是否确认删除该公区收益通知?').finally(() => (loading.value = false));
await delRevenueNotice(_noticeIds);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
// const handleExport = () => {
// proxy?.download(
// 'system/revenueNotice/export',
// {
// ...queryParams.value
// },
// `revenueNotice_${new Date().getTime()}.xlsx`
// );
// };
onMounted(() => {
getList();
});
</script>
<style scoped lang="scss">
.el-table {
height: calc(100% - 80px);
}
</style>

View File

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

View File

@@ -72,7 +72,6 @@ import { listStock } from '@/api/system/Tstock';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const materialList = ref<MaterialVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
@@ -135,7 +134,7 @@ const handleAdd = () => {
});
};
/** 修改按钮操作 */
const handleUpdate = async (row?: MaterialVO) => {
const handleUpdate = (row?: MaterialVO) => {
const _ids = row?.materialId;
router.push({
path: '/warehouse/editInventory',

View File

@@ -35,8 +35,6 @@ import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { getMaterial, updateMaterial, addMaterial } from '@/api/system/Tmaterial';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();

View File

@@ -8,13 +8,13 @@
<el-form-item label="供应商名称" prop="supplierName">
<el-input v-model.trim="form.supplierName" placeholder="请输入供应商名称" />
</el-form-item>
<el-form-item label="联系人" prop="contactPerson">
<el-form-item label="联系人">
<el-input v-model.trim="form.contactPerson" placeholder="请输入联系人" />
</el-form-item>
<el-form-item label="联系电话" prop="contactPhone">
<el-form-item label="联系电话">
<el-input v-model.trim="form.contactPhone" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-form-item label="邮箱">
<el-input v-model.trim="form.email" placeholder="请输入邮箱" />
</el-form-item>
<el-form-item label="地址" prop="address">
@@ -39,8 +39,6 @@ import PageHeader from '@/components/Pageheader/index.vue';
import { getSupplier, updateSupplier, addSupplier } from '@/api/system/Tsupplier';
import { validator } from '@/utils/Reg';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();

View File

@@ -10,13 +10,13 @@
</el-form-item>
<el-form-item label="归属小区" prop="villageId">
<el-select v-model="form.villageId" placeholder="请选择归属小区">
<el-option v-for="(item, index) in cummunitylist" :key="index" :label="item.villageName" :value="item.villageId" />
<el-option v-for="(item, index) in communityList" :key="index" :label="item.villageName" :value="item.villageId" />
</el-select>
</el-form-item>
<el-form-item label="联系人" prop="contactPerson">
<el-form-item label="联系人">
<el-input v-model.trim="form.contactPerson" placeholder="请输入联系人" />
</el-form-item>
<el-form-item label="联系电话" prop="contactPhone">
<el-form-item label="联系电话">
<el-input v-model.trim="form.contactPhone" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="地址" prop="address">
@@ -42,8 +42,6 @@ import { getCommunitylistAPI } from '@/api/system/community';
import { addWarehouse, getWarehouse, updateWarehouse } from '@/api/system/Twarehouse';
import { validator } from '@/utils/Reg';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();
@@ -63,7 +61,7 @@ const rules = ref({
contactPhone: [
{ required: true, message: '请输入 联系电话', trigger: 'blur' },
{
validator: (_, value) => validator(value, 'phone'),
validator: (_: any, value: string | number) => validator(value, 'phone'),
message: '请输入正确的电话号码',
trigger: 'blur'
}
@@ -74,10 +72,10 @@ const rules = ref({
const userid = ref(null);
// 小区列表
const cummunitylist = ref([]);
const communityList = ref([]);
function init() {
getCommunitylistAPI().then((res) => {
cummunitylist.value = res.rows;
communityList.value = res.rows;
});
if (route.query.id) {
userid.value = route.query.id;
@@ -103,12 +101,12 @@ const submitForm = () => {
formRef.value?.validate(async (valid: boolean) => {
if (valid) {
if (userid.value) {
updateWarehouse(form.value).then((res) => {
updateWarehouse(form.value).then(() => {
ElMessage.success('编辑成功');
cancelForm();
});
} else {
addWarehouse(form.value).then((res) => {
addWarehouse(form.value).then(() => {
ElMessage.success('添加成功');
cancelForm();
});

View File

@@ -0,0 +1,210 @@
<template>
<div class="echarts">
<div class="nav flex flex-items-center justify-between">
<div>
<span class="ecarts_title">收费情况</span>
</div>
<div class="flex flex-items-center justify-center">
<el-date-picker
v-model="time"
type="daterange"
range-separator=""
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
start-placeholder="开始日期"
@update:model-value="handleChangeDate"
end-placeholder="结束日期"
/>
</div>
</div>
<div class="echartsBody flex flex-items-center justify-between">
<div class="flex-1 h-full echartsItems">
<Echarts :options="options"></Echarts>
</div>
<div class="flex-1 h-full">
<div class="echartsMoneyItem">
<div class="label">应收</div>
<div class="value"> {{ feeForm.receivableAmount }}</div>
</div>
<div class="echartsMoneyItem">
<div class="label">已收</div>
<div class="value"> {{ feeForm.receivedAmount }}</div>
</div>
<div class="echartsMoneyItem">
<div class="label">待收</div>
<div class="value"> {{ feeForm.unpaidAmount }}</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import Echarts from '@/components/Echarts/index.vue';
import { EChartsOption } from 'echarts';
import { paymentRateApi } from '@/api/workflow';
import { getLastNDays } from '@/utils/time';
const time = ref([getLastNDays(30).at(0), getLastNDays(0).at(length - 1)]);
const value = ref(0);
const feeForm = ref({
'receivableAmount': '',
'receivablePercent': '',
'receivedAmount': '',
'receivedPercent': '',
'unpaidAmount': '',
'unpaidPercent': ''
});
const options = ref<EChartsOption>({
tooltip: {
show: false,
trigger: 'item',
formatter: '{b}: {c}%'
},
series: [
{
type: 'pie',
radius: ['50%', '80%'], // 环形大小
center: ['50%', '50%'], // 每个图表各自居中
labelLine: {
show: false
},
data: [
{
value: 100 - value.value,
itemStyle: {
color: '#ebeef5' // 背景色
},
emphasis: {
itemStyle: {
color: '#ebeef5'
},
scale: false
}
},
{
value: value.value,
name: '收费率',
itemStyle: { color: '#1684fc', borderRadius: 8, borderColor: '#1684fc', borderWidth: 0 },
label: {
show: true,
position: 'center', // 显示在圆环中心
formatter: '{c}%', // 显示百分比数值
fontSize: 25
},
emphasis: {
scale: true
}
}
]
}
]
});
function handleChangeDate(date: string[]) {
if (date) {
paymentRateApi(date[0], date[1]).then((res) => {
feeForm.value = res.data;
options.value = updateOptions(res.data.receivedPercent) as EChartsOption;
});
}
}
handleChangeDate(time.value);
function updateOptions(value: string) {
return {
tooltip: {
show: false,
trigger: 'item',
formatter: '{b}: {c}%'
},
title: {
show: true,
text: '收费率',
left: 'left'
},
series: [
{
type: 'pie',
radius: ['50%', '80%'], // 环形大小
center: ['50%', '50%'], // 每个图表各自居中
labelLine: {
show: false
},
startAngle: 90,
clockwise: false,
data: [
{
value: 100 - Number(value),
itemStyle: {
color: '#ebeef5' // 背景色
},
emphasis: {
itemStyle: {
color: '#ebeef5'
},
scale: false
}
},
{
value: Number(value),
name: '收费率',
itemStyle: { color: '#1684fc', borderRadius: 8, borderColor: '#1684fc', borderWidth: 0 },
label: {
show: true,
position: 'center',
formatter: '{c}%',
fontSize: 25
},
emphasis: {
scale: true
}
}
]
}
]
};
}
</script>
<style lang="scss" scoped>
.echarts {
height: 512px;
flex: 1;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
box-sizing: border-box;
padding: 19px 23px;
box-shadow: 0px 2px 6px 0px rgba(26, 117, 255, 0.15);
border-radius: 10px;
.echartsBody {
margin-top: 40px;
.echartsItems {
border-right: 1px solid #dedede;
}
.echartsMoneyItem {
box-sizing: border-box;
border-bottom: 1px solid #dedede;
padding: 17px 34px;
height: 126px;
&:last-child {
border-bottom: none;
}
.label {
color: rgba(16, 16, 16, 1);
font-size: 16px;
height: 23px;
line-height: 23px;
margin-bottom: 10px;
}
.value {
color: rgba(16, 16, 16, 1);
font-size: 1.5rem;
height: 50px;
line-height: 50px;
font-weight: 600;
}
}
}
}
</style>

View File

@@ -31,7 +31,7 @@ const handleRoute = () => {
.echarts {
margin-right: 20px;
flex: 1;
height: 450px;
height: 512px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
border: 2px solid #ffffff;
border-radius: 12px;

View File

@@ -71,6 +71,31 @@ function headerToken() {
};
}
const blockedExts = ['.exe', '.bat', '.cmd', '.msi'];
const allowExts = [
// word
'.doc',
'.docx',
'.dot',
'.dotx',
// excel
'.xls',
'.xlsx',
'.xlsm',
'.xlsb',
// img
'.jpg',
'.jpeg',
'.png',
'.gif',
'.bmp',
'.webp',
// 专业/矢量图
'.psd',
'.ai',
'.svg',
'.tif',
'.tiff'
];
const handleAvatarRemove: UploadProps['onRemove'] = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
fileList.value = uploadFiles;
};
@@ -78,7 +103,12 @@ const handleProgress: UploadProps['onChange'] = (uploadFile: UploadFile, uploadF
const ext = uploadFile.name.toLowerCase().slice(uploadFile.name.lastIndexOf('.'));
if (blockedExts.includes(ext)) {
ElMessage.warning(`禁止上传 ${ext} 文件`);
fileList.value = uploadFiles.filter((f) => f.uid !== uploadFile.uid);
uploadRef.value.handleRemove(uploadFile);
return;
}
if (!allowExts.includes(ext)) {
ElMessage.warning('只允许上传word,excel和图片文件');
uploadRef.value.handleRemove(uploadFile);
return;
}
fileList.value = uploadFiles;

View File

@@ -57,7 +57,7 @@
</template>
<script lang="ts" setup>
import { delResident, listResident } from '@/api/system/resident';
import { delResident, listResident } from '@/api/system/residentReviewProcess/resident';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_resident_type } = toRefs<any>(proxy?.useDict('com_resident_type'));

View File

@@ -7,8 +7,7 @@
<VillageAllInfo :list="list"></VillageAllInfo>
<div class="echartsbox flex flex-items-center">
<repairechartsAll></repairechartsAll>
<repairechartsAll></repairechartsAll>
<inandoutEcharts></inandoutEcharts>
<feeOverview></feeOverview>
</div>
</el-col>
<!-- tabs -->
@@ -80,6 +79,7 @@ import weatherVue from './components/weather.vue';
import userTable from './components/usertable.vue';
import quick from './components/quick.vue';
import todo from './components/todo.vue';
import feeOverview from './components/feeOverview.vue';
import inandoutEcharts from './components/inandout.vue';
import repairechartsAll from './components/repairechartsAll.vue';