同步6/16
This commit is contained in:
@@ -18,8 +18,8 @@
|
||||
<el-form-item label="所在城市" prop="city">
|
||||
<el-cascader :options="pcaTextArrlist" v-model="city" @change="cityChange"> </el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="详细地址" prop="buildingArea">
|
||||
<el-input v-model.trim="form.address" placeholder="请输入详细地址" />
|
||||
<el-form-item label="完整详细地址" prop="buildingArea">
|
||||
<el-input v-model.trim="form.address" placeholder="请输入完整详细地址" />
|
||||
</el-form-item>
|
||||
<el-form-item label="建成时间" prop="buildingArea">
|
||||
<el-date-picker v-model="builtTime" type="date" placeholder="选择建成时间" value-format="YYYY-MM-DD" @change="changeBuiltTime" />
|
||||
@@ -184,7 +184,7 @@ const rules = ref({
|
||||
function getCommunityinfo() {
|
||||
const id = editId.value;
|
||||
getVillageByIdAPI(id).then((res) => {
|
||||
city.value = res.data.city.split('/');
|
||||
city.value = res.data.city ? res.data.city.split('/') : [];
|
||||
if (res.data.villageImageUrl) {
|
||||
villageImg.value = res.data.villageImageUrl
|
||||
.split(',')
|
||||
|
||||
@@ -13,7 +13,16 @@
|
||||
</div>
|
||||
<div class="communityBody">
|
||||
<div class="coummunity_card" v-for="(item, index) in list" :key="index">
|
||||
<el-image :src="item.villageImageUrl ? item.villageImageUrl.split(',')[0] : defaultVilageinfoImage">
|
||||
<el-image
|
||||
:zoom-rate="1.2"
|
||||
:max-scale="7"
|
||||
:min-scale="0.2"
|
||||
:preview-src-list="item.villageImageUrl ? item.villageImageUrl.split(',') : [defaultVilageinfoImage]"
|
||||
show-progress
|
||||
:initial-index="4"
|
||||
fit="cover"
|
||||
:src="item.villageImageUrl ? item.villageImageUrl.split(',')[0] : defaultVilageinfoImage"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-viewer-slot image-slot">
|
||||
<el-icon><Picture /></el-icon>
|
||||
|
||||
@@ -148,10 +148,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询测试单列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listDemo(queryParams.value);
|
||||
demoList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listDemo(queryParams.value)
|
||||
.then((res) => {
|
||||
demoList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
|
||||
@@ -8,16 +8,122 @@
|
||||
</template>
|
||||
<div class="addBuildingFormBody">
|
||||
<div class="formbox">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="150px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-col :span="13">
|
||||
<el-form-item label="活动标题" prop="title">
|
||||
<el-input v-model.trim="form.title" placeholder="请输入活动标题" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="11">
|
||||
<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="13">
|
||||
<el-form-item label="活动时间" prop="startTime">
|
||||
<el-date-picker
|
||||
v-model="activityTime"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
@update:model-value="
|
||||
(data) => {
|
||||
if (data && data.length > 0) {
|
||||
form.startTime = data[0];
|
||||
form.endTime = data[1];
|
||||
} else {
|
||||
form.startTime = '';
|
||||
form.endTime = '';
|
||||
}
|
||||
}
|
||||
"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始活动"
|
||||
end-placeholder="结束活动"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="活动地点" prop="address">
|
||||
<el-input v-model.trim="form.address" placeholder="请输入活动地点" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="报名截止日期" prop="deadline">
|
||||
<el-date-picker
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
v-model="deadline"
|
||||
@update:model-value="
|
||||
(data) => {
|
||||
if (data) {
|
||||
form.applyDeadline = data;
|
||||
} else {
|
||||
form.applyDeadline = '';
|
||||
}
|
||||
}
|
||||
"
|
||||
type="date"
|
||||
placeholder="请选择报名截止日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="作者" prop="author">
|
||||
<el-input v-model.trim="form.author" placeholder="请输入作者" />
|
||||
<el-form-item label="主办方" prop="organizer">
|
||||
<el-input v-model.trim="form.organizer" placeholder="请输入主办方" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系人" prop="contactName">
|
||||
<el-input v-model.trim="form.contactName" placeholder="请输入联系人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系方式" prop="contactName">
|
||||
<el-input v-model.trim="form.contactPhone" placeholder="请输入联系方式" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="活动名额" prop="quota">
|
||||
<div class="flex items-center">
|
||||
<el-input-number v-model.trim.number="form.quota" :min="0" placeholder="0代表无限" />
|
||||
<span class="ml-2 text-gray-500 text-sm" style="font-size: 12px">(填 <b>0</b> 代表<u>不限制名额</u>)</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="活动封面" prop="title">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
class="avatar-uploader"
|
||||
:action="uploadUrl"
|
||||
:show-file-list="false"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:on-exceed="handleExceed"
|
||||
:on-error="handleError"
|
||||
:limit="1"
|
||||
>
|
||||
<img v-if="form.coverImage" :src="form.coverImage" class="avatar" />
|
||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="招募要求">
|
||||
<el-input :row="8" type="textarea" v-model.trim="form.requirements" placeholder="请输入招募要求" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -29,6 +135,69 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- <el-row>
|
||||
<el-col>
|
||||
<el-form-item label="活动签到">
|
||||
<el-switch
|
||||
@change="
|
||||
(val) => {
|
||||
if (val) {
|
||||
initSignMap();
|
||||
}
|
||||
}
|
||||
"
|
||||
v-model="isSignin"
|
||||
active-text="签到"
|
||||
inactive-text="不签到"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="13">
|
||||
<el-form-item label="签到时间" prop="signinStartTime">
|
||||
<el-date-picker
|
||||
v-model="SigninTime"
|
||||
type="datetimerange"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
range-separator="至"
|
||||
@update:model-value="
|
||||
(data) => {
|
||||
if (data && data.length > 0) {
|
||||
form.signinStartTime = data[0];
|
||||
form.signinEndTime = data[1];
|
||||
} else {
|
||||
form.signinStartTime = '';
|
||||
form.signinEndTime = '';
|
||||
}
|
||||
}
|
||||
"
|
||||
start-placeholder="开始签到"
|
||||
end-placeholder="结束签到"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="isSignin">
|
||||
<el-col>
|
||||
<el-form-item label="签到设置">
|
||||
<div>
|
||||
<div>
|
||||
<el-button type="primary" v-if="isDraw === 0" @click="startDrawCircle">开始设置签到范围</el-button>
|
||||
<el-button type="success" v-if="isDraw === 1" @click="editCircle">编辑签到范围</el-button>
|
||||
<el-button type="warning" v-if="isDraw === 2" @click="stopDrawCircle">结束设置签到范围</el-button>
|
||||
<el-button type="danger" @click="clearCircle">清空签到范围</el-button>
|
||||
</div>
|
||||
<div v-loading="mapReady" class="SignMapbox">
|
||||
<div id="SignMap" style="height: 100%; width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row> -->
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||
<el-button @click="handleBack">返回</el-button>
|
||||
@@ -44,44 +213,281 @@
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addActivity, getActivity, updateActivity } from '@/api/system/Activity';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_repair_project_status } = toRefs<any>(proxy?.useDict('com_repair_project_status'));
|
||||
import { genFileId, UploadFiles, UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
|
||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/activity/uploadImage';
|
||||
|
||||
const aloaderkey = import.meta.env.VITE_GCJ02_KEY_GD;
|
||||
const VITE_GCJ02_JS_CODE_GD = import.meta.env.VITE_GCJ02_JS_CODE_GD;
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const formRef = ref();
|
||||
const form = ref({
|
||||
'id': null,
|
||||
// 标题
|
||||
'title': '',
|
||||
// 作者
|
||||
'author': '',
|
||||
// 内容
|
||||
'content': '',
|
||||
'status': '0'
|
||||
// 发布状态 0未发布 1己发布
|
||||
'status': '0',
|
||||
// 报名截止日期
|
||||
'applyDeadline': '',
|
||||
// 活动时间
|
||||
'startTime': '',
|
||||
'endTime': '',
|
||||
// 活动地点
|
||||
'address': '',
|
||||
// 主办方
|
||||
'organizer': '',
|
||||
// 联系人
|
||||
'contactName': '',
|
||||
// 联系方式
|
||||
'contactPhone': '',
|
||||
// 开始签到时间
|
||||
'signinStartTime': '',
|
||||
// 结束签到时间
|
||||
'signinEndTime': '',
|
||||
// 活动名额
|
||||
'quota': 0,
|
||||
// 积分奖励
|
||||
'pointsReward': 0,
|
||||
// 活动封面
|
||||
'coverImage': '',
|
||||
// 招募要求
|
||||
'requirements': ''
|
||||
|
||||
// 'SignInfo': {
|
||||
// lng: null, // 经度
|
||||
// lat: null, // 纬度
|
||||
// radius: null // 半径 m
|
||||
// }
|
||||
});
|
||||
const rules = {
|
||||
title: [{ required: true, message: '请输入活动标题', trigger: 'blur' }],
|
||||
author: [{ required: true, message: '请输入作者', trigger: 'blur' }],
|
||||
applyDeadline: [{ required: true, message: '请输入报名截止日期', trigger: 'blur' }],
|
||||
startTime: [{ required: true, message: '请选择开始日期', trigger: 'blur' }],
|
||||
endTime: [{ required: true, message: '请选择结束日期', trigger: 'blur' }],
|
||||
address: [{ required: true, message: '请输入活动地点', trigger: 'blur' }],
|
||||
organizer: [{ required: true, message: '请输入主办方', trigger: 'blur' }],
|
||||
contactName: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
|
||||
contactPhone: [{ required: true, message: '请输入联系方式', trigger: 'blur' }],
|
||||
coverImage: [{ required: true, message: '请上传活动封面', trigger: 'blur' }],
|
||||
content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
|
||||
};
|
||||
const userid = ref();
|
||||
// 报名截止日期
|
||||
const deadline = ref([]);
|
||||
// 有效签到时间
|
||||
const SigninTime = ref([]);
|
||||
// 活动时间
|
||||
const activityTime = ref([]);
|
||||
|
||||
// 上传文件
|
||||
const upload = ref<UploadInstance>();
|
||||
// 上传成功
|
||||
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
|
||||
if (response.data && response.data.url) {
|
||||
form.value.coverImage = response.data.url;
|
||||
}
|
||||
};
|
||||
|
||||
// 超出文件限制
|
||||
const handleExceed: UploadProps['onExceed'] = (files) => {
|
||||
upload.value!.clearFiles();
|
||||
const file = files[0] as UploadRawFile;
|
||||
file.uid = genFileId();
|
||||
upload.value!.handleStart(file);
|
||||
upload.value?.submit();
|
||||
};
|
||||
// 上传失败
|
||||
const handleError: UploadProps['onError'] = (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
|
||||
console.log(error);
|
||||
};
|
||||
|
||||
// ! 投诉 ====================================================================================================
|
||||
|
||||
// ! 签到 =======================================
|
||||
const isSignin = ref(false);
|
||||
let AMapLi = null;
|
||||
let map: any = null;
|
||||
let circle: any = null;
|
||||
let circleEditor: any = null;
|
||||
|
||||
let geocoder: any = null;
|
||||
const mapReady = ref(false);
|
||||
let mouseTool = null;
|
||||
|
||||
// 0 开始 1编辑 2结束
|
||||
const isDraw = ref(0);
|
||||
|
||||
onMounted(() => {
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
init();
|
||||
}
|
||||
});
|
||||
async function initSignMap() {
|
||||
try {
|
||||
mapReady.value = true;
|
||||
window._AMapSecurityConfig = { securityJsCode: VITE_GCJ02_JS_CODE_GD };
|
||||
console.log('开始执行 AMapLoader.load');
|
||||
const AMap = await AMapLoader.load({
|
||||
key: aloaderkey,
|
||||
version: '2.0',
|
||||
plugins: ['AMap.MouseTool', 'AMap.CircleEditor', 'AMap.Geolocation', 'AMap.Geocoder']
|
||||
});
|
||||
mapReady.value = false;
|
||||
console.log('AMapLoader.load 执行完毕');
|
||||
AMapLi = AMap;
|
||||
map = new AMap.Map('SignMap', {
|
||||
viewMode: '3D',
|
||||
zoom: 11,
|
||||
center: [116.397428, 39.90923]
|
||||
});
|
||||
|
||||
// 解析本地存储的城市信息
|
||||
const villageInfoStr = localStorage.getItem('villageInfo') || '{}';
|
||||
let city = '';
|
||||
try {
|
||||
const villageInfo = JSON.parse(villageInfoStr);
|
||||
city = (villageInfo?.city || '').trim();
|
||||
} catch (err) {
|
||||
console.warn('解析 villageInfo 失败', err);
|
||||
}
|
||||
// 初始化地理编码工具
|
||||
if (city.trim() !== '') {
|
||||
geocoder = new AMap.Geocoder({
|
||||
city: city.trim(),
|
||||
radius: 1000
|
||||
});
|
||||
getGeoCode(city.trim(), map);
|
||||
}
|
||||
|
||||
// 鼠标绘制工具
|
||||
mouseTool = new AMap.MouseTool(map);
|
||||
mouseTool.on('draw', (e: any) => {
|
||||
// 移除旧围栏
|
||||
if (circle) {
|
||||
map.remove(circle);
|
||||
}
|
||||
circle = e.obj;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('高德地图初始化失败:', error);
|
||||
}
|
||||
}
|
||||
// 获取 城市经纬度并定位中心
|
||||
const getGeoCode = (address, map) => {
|
||||
geocoder.getLocation(address, (status: string, result: any) => {
|
||||
if (status === 'complete' && result.geocodes.length > 0) {
|
||||
const geo = result.geocodes[0];
|
||||
const lng = geo.location.lng;
|
||||
const lat = geo.location.lat;
|
||||
map.setCenter([lng, lat]);
|
||||
map.setZoom(15);
|
||||
} else {
|
||||
console.log('未找到该地址');
|
||||
}
|
||||
});
|
||||
};
|
||||
// 开始绘制圆形
|
||||
const startDrawCircle = () => {
|
||||
resetCircle();
|
||||
if (!mouseTool) return;
|
||||
isDraw.value = 1; // 编辑
|
||||
mouseTool.circle({
|
||||
strokeColor: '#1890ff',
|
||||
strokeWeight: 3,
|
||||
fillColor: 'rgba(24, 144, 255, 0.2)',
|
||||
fillOpacity: 0.4
|
||||
});
|
||||
};
|
||||
// 停止绘制圆形
|
||||
const stopDrawCircle = () => {
|
||||
if (!mouseTool) return;
|
||||
if (mouseTool) {
|
||||
mouseTool.close(false);
|
||||
}
|
||||
if (circleEditor) {
|
||||
circleEditor.close();
|
||||
circleEditor = null;
|
||||
}
|
||||
isDraw.value = 0; // 开始
|
||||
mouseTool.close(false);
|
||||
if (circle) {
|
||||
const center = circle.getCenter();
|
||||
const radius = circle.getRadius();
|
||||
console.log('中心点:', [center.lng, center.lat]);
|
||||
console.log('半径:', radius, typeof radius);
|
||||
// form.value.SignInfo.lat = center.lat;
|
||||
// form.value.SignInfo.lng = center.lng;
|
||||
// form.value.SignInfo.radius = center.radius;
|
||||
}
|
||||
};
|
||||
|
||||
// 编辑 圆形
|
||||
const editCircle = () => {
|
||||
if (!circle) return;
|
||||
if (mouseTool) {
|
||||
mouseTool.close(false);
|
||||
}
|
||||
isDraw.value = 2; // 结束
|
||||
circleEditor = new AMapLi.CircleEditor(map, circle);
|
||||
circleEditor.open();
|
||||
};
|
||||
|
||||
// 删除圆形
|
||||
const clearCircle = () => {
|
||||
// resetCircle();
|
||||
isDraw.value = 0; // 开始
|
||||
ElMessage.success('全部清除');
|
||||
};
|
||||
// 重置
|
||||
const resetCircle = () => {
|
||||
// 不能绘画
|
||||
if (mouseTool) {
|
||||
mouseTool.close(false);
|
||||
}
|
||||
// 清除圆形
|
||||
if (circle) {
|
||||
map.remove(circle);
|
||||
circle = null;
|
||||
}
|
||||
// 不能编辑
|
||||
if (circleEditor) {
|
||||
circleEditor.close();
|
||||
circleEditor = null;
|
||||
}
|
||||
};
|
||||
|
||||
function init() {
|
||||
getActivity(userid.value).then((res) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
console.log(form.value);
|
||||
activityTime.value = [res.data.startTime, res.data.endTime];
|
||||
SigninTime.value = [res.data.signinStartTime, res.data.signinEndTime];
|
||||
deadline.value = [res.data.applyDeadline];
|
||||
|
||||
// if (res.data?.SignInfo !== null) {
|
||||
// isSignin.value = true;
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
init();
|
||||
}
|
||||
|
||||
// ! 提交========================================
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
console.log(form.value);
|
||||
// if (!isSignin.value) {
|
||||
// form.value.SignInfo = null;
|
||||
// }
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
if (userid.value) {
|
||||
@@ -105,12 +511,63 @@ function handleBack() {
|
||||
path: '/repair/Activity'
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 销毁地图及所有工具实例(防内存泄漏、重复初始化)
|
||||
*/
|
||||
function destroyMapInstance() {
|
||||
if (map) {
|
||||
map.destroy();
|
||||
map = null;
|
||||
}
|
||||
mouseTool = null;
|
||||
geocoder = null;
|
||||
circle = null;
|
||||
AMapLi = null;
|
||||
mapReady.value = false;
|
||||
}
|
||||
onUnmounted(() => {
|
||||
// destroyMapInstance();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.SignMapbox {
|
||||
height: 500px;
|
||||
width: 500px;
|
||||
margin-top: 10px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.ResidentMainBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.avatar-uploader {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 158px;
|
||||
height: 158px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar-uploader .avatar {
|
||||
width: 158px;
|
||||
height: 158px;
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
|
||||
.ResidentMainBody {
|
||||
margin-top: 20px;
|
||||
flex: 1;
|
||||
|
||||
@@ -145,10 +145,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询活动管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listActivity(queryParams.value);
|
||||
activityList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listActivity(queryParams.value)
|
||||
.then((res) => {
|
||||
activityList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
/** 发布按钮 */
|
||||
const handleSend = (row: ActivityVO) => {
|
||||
@@ -198,7 +202,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ActivityVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/repair/editActivity',
|
||||
query: {
|
||||
|
||||
@@ -64,7 +64,7 @@ function headerToken() {
|
||||
}
|
||||
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
const type = rawFile.type.split('/').pop();
|
||||
if (['png', 'jpg'].includes(type)) {
|
||||
if (['png', 'jpg', 'jpeg'].includes(type)) {
|
||||
if (rawFile.size / 1024 / 1024 <= 10) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -92,6 +92,7 @@ const form = ref({
|
||||
name: '', // 分类id、
|
||||
url: '', // 设备名称
|
||||
link: '', // 编号
|
||||
status: '1',
|
||||
byOrder: 1 // 区域
|
||||
});
|
||||
const rules = ref({
|
||||
@@ -108,6 +109,7 @@ function init() {
|
||||
id: res.data.id,
|
||||
name: res.data.name, // 分类id、
|
||||
url: res.data.url, // 设备名称
|
||||
status: res.data.status ?? '0',
|
||||
link: res.data.link, // 编号
|
||||
byOrder: res.data.byOrder // 区域
|
||||
};
|
||||
|
||||
@@ -67,14 +67,14 @@
|
||||
<!-- 0启用 1停用 -->
|
||||
<el-switch
|
||||
@change="(val: string) => handleSwitch(scope.row.id, val)"
|
||||
inactive-value="0"
|
||||
active-value="1"
|
||||
inactive-value="1"
|
||||
active-value="0"
|
||||
v-model="scope.row.status"
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排序" align="center" prop="byOrder" />
|
||||
<el-table-column label="添加时间" align="center" />
|
||||
<el-table-column label="添加时间" align="center" prop="createTime" />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['banner:banner:edit']">修改</el-button>
|
||||
@@ -158,10 +158,14 @@ const { queryParams, form } = toRefs(data);
|
||||
/** 查询Banner图管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listBanner(queryParams.value);
|
||||
bannerList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listBanner(queryParams.value)
|
||||
.then((res) => {
|
||||
bannerList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
|
||||
@@ -10,36 +10,54 @@
|
||||
<span>投诉信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-full CarinfoBox">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">投诉类型</div>
|
||||
<div class="main">{{ form.type }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="CarinfoBox">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">投诉类型</div>
|
||||
<div class="main">{{ form.type }}</div>
|
||||
</div>
|
||||
|
||||
<div class="carinfo_item">
|
||||
<div class="label">问题描述</div>
|
||||
<div class="main">{{ form.problemDes }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">投诉人姓名</div>
|
||||
<div class="main">{{ form.complaintName }}</div>
|
||||
</div>
|
||||
|
||||
<div class="carinfo_item">
|
||||
<div class="label">投诉人姓名</div>
|
||||
<div class="main">{{ form.complaintName }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">手机号码</div>
|
||||
<div class="main">{{ form.phone }}</div>
|
||||
</div>
|
||||
|
||||
<div class="carinfo_item">
|
||||
<div class="label">手机号码</div>
|
||||
<div class="main">{{ form.phone }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">投诉时间</div>
|
||||
<div class="main">{{ form.createTime }}</div>
|
||||
</div>
|
||||
|
||||
<div class="carinfo_item">
|
||||
<div class="label">投诉时间</div>
|
||||
<div class="main">{{ form.createTime }}</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">处理状态</div>
|
||||
<div class="main">
|
||||
<DictTag :options="com_complaint_status" :value="form.status"></DictTag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="carinfo_item">
|
||||
<div class="label">处理状态</div>
|
||||
<div class="main">
|
||||
<DictTag :options="com_complaint_status" :value="form.status"></DictTag>
|
||||
<div class="CarinfoBox signle">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">问题描述</div>
|
||||
<div class="main">{{ form.problemDes }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="CarinfoBox signle">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">问题照片</div>
|
||||
<div class="main">
|
||||
<el-image
|
||||
v-for="(item, index) in problemIamgeUrllist"
|
||||
:key="index"
|
||||
:src="item"
|
||||
:preview-teleported="true"
|
||||
:preview-src-list="problemIamgeUrllist"
|
||||
style="width: 120px; height: 120px; margin-right: 10px"
|
||||
></el-image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,11 +75,18 @@
|
||||
<el-form ref="formRef" :rules="rules" class="m-auto" :inline="false" label-width="100px" :model="form">
|
||||
<el-form-item label="处理状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="(item, index) in com_complaint_status" :key="index" :value="item.value">{{ item.label }}</el-radio>
|
||||
<!-- <el-radio v-for="(item, index) in com_complaint_status" :key="index" :value="item.value">{{ item.label }}</el-radio> -->
|
||||
<el-radio value="1">处理完成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="处理人员" prop="handleId">
|
||||
<repairUser :userid="form.handleId" returnvalue="value" @change="handleChange"></repairUser>
|
||||
<repairUser
|
||||
:is-multiple="false"
|
||||
:username="form.handleName"
|
||||
:userid="form.handleId ?? ''"
|
||||
returnvalue="*"
|
||||
@change="handleChange"
|
||||
></repairUser>
|
||||
</el-form-item>
|
||||
<el-form-item label="处理描述" prop="handleContent">
|
||||
<el-input type="textarea" :rows="5" v-model="form.handleContent"></el-input>
|
||||
@@ -104,10 +129,11 @@ const form = ref({
|
||||
'createTime': null
|
||||
});
|
||||
const rules = {
|
||||
status: [{ required: true, message: '选择投诉处理状态', trigger: 'blur' }]
|
||||
status: [{ required: true, message: '选择投诉处理状态', trigger: 'blur' }],
|
||||
handleContent: [{ required: true, message: '投诉处理内容不能为空', trigger: 'blur' }]
|
||||
};
|
||||
const userid = ref();
|
||||
const complaintyTyplist = ref([]);
|
||||
const problemIamgeUrllist = ref([]);
|
||||
// ! 投诉 ====================================================================================================
|
||||
async function init() {
|
||||
const res2 = await listComplaintType();
|
||||
@@ -116,6 +142,8 @@ async function init() {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
problemIamgeUrllist.value = res.data.problemImageUrl ? res.data.problemImageUrl.split(',') : [];
|
||||
form.value.status = '1';
|
||||
const find = res2.rows.find((item) => item.id === form.value.typeId);
|
||||
if (find) {
|
||||
form.value.type = find.name;
|
||||
@@ -129,6 +157,7 @@ if (route.query.id) {
|
||||
}
|
||||
|
||||
function handleChange(pop) {
|
||||
console.log(pop);
|
||||
form.value.handleId = pop.userId;
|
||||
form.value.handleName = pop.nickName;
|
||||
}
|
||||
@@ -171,13 +200,21 @@ function handleBack() {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.carinfo_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.label {
|
||||
margin-right: 20px;
|
||||
min-width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
&.signle {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
grid-template-rows: repeat(1, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.formbox {
|
||||
|
||||
@@ -21,12 +21,11 @@
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card class="flex-1" shadow="never">
|
||||
<el-table v-loading="loading" border :data="complaintList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="投诉类型" align="center" prop="typeName" />
|
||||
<el-table-column label="问题描述" align="center" prop="problemDes" />
|
||||
<el-table-column label="问题描述" show-overflow-tooltip align="center" prop="problemDes" />
|
||||
<el-table-column label="投诉人姓名" align="center" prop="complaintName" />
|
||||
<el-table-column label="手机号" align="center" prop="phone" />
|
||||
<el-table-column label="投诉时间" align="center" prop="createTime" />
|
||||
@@ -113,10 +112,14 @@ const getList = async () => {
|
||||
loading.value = true;
|
||||
const res2 = await listComplaintType();
|
||||
complaintyTyplist.value = res2.rows;
|
||||
const res = await listComplaint(queryParams.value);
|
||||
complaintList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listComplaint(queryParams.value)
|
||||
.then((res) => {
|
||||
complaintList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div class="p-2 h-full flex flex-col">
|
||||
<Pageheader title="投诉类型管理"></Pageheader>
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card shadow="never">
|
||||
<el-card shadow="never" class="flex-1">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<!-- <el-col :span="1.5">
|
||||
@@ -131,10 +131,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询投诉类型管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listComplaintType(queryParams.value);
|
||||
complaintTypeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listComplaintType(queryParams.value)
|
||||
.then((res) => {
|
||||
complaintTypeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -196,3 +200,9 @@ onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -55,19 +55,19 @@
|
||||
<el-table v-loading="loading" border :data="decorationList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="小区名称" align="center" prop="villageName" />
|
||||
<el-table-column label="房屋号" align="center" prop="houseName" />
|
||||
<el-table-column label="房屋号" show-overflow-tooltip align="center" prop="houseName" />
|
||||
<el-table-column label="申请人姓名" align="center" prop="applyName" />
|
||||
<el-table-column label="装修公司" align="center" prop="decorationCompany" />
|
||||
<el-table-column label="装修内容" align="center" prop="decorationContent" />
|
||||
<el-table-column label="装修押金" align="center" prop="decorationDeposit" />
|
||||
<el-table-column label="验收结果" align="center" prop="inspectionResult">
|
||||
<el-table-column label="装修押金" width="120" align="center" prop="decorationDeposit" />
|
||||
<el-table-column label="验收结果" width="100" align="center" prop="inspectionResult">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_decoration_status" :value="Number(scope.row.inspectionResult)"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请时间" align="center" prop="createTime" />
|
||||
<el-table-column label="申请时间" width="170" align="center" prop="createTime" />
|
||||
<el-table-column label="验收人" align="center" prop="inspectionName" />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<el-table-column label="操作" width="170" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
@@ -245,7 +245,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: DecorationVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/repair/editDecoration',
|
||||
query: {
|
||||
|
||||
@@ -53,6 +53,30 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="附属材料">
|
||||
<el-upload
|
||||
:auto-upload="false"
|
||||
class="upload-demo"
|
||||
:file-list="fileList"
|
||||
:action="uploadUrl"
|
||||
:multiple="true"
|
||||
ref="uploadRef"
|
||||
name="files"
|
||||
:headers="headerToken()"
|
||||
:show-file-list="true"
|
||||
:on-remove="handleAvatarRemove"
|
||||
:on-change="handleProgress"
|
||||
>
|
||||
<div class="uploadBtn flex flex-items-center">
|
||||
<el-icon><Upload /></el-icon>
|
||||
<span>上传文件</span>
|
||||
</div>
|
||||
</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>
|
||||
@@ -64,11 +88,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addHandleLog, getHandleLog, updateHandleLog } from '@/api/system/HandleLog';
|
||||
import { addHandleLog, getHandleLog, updateHandleLog, uploadAttachments } from '@/api/system/HandleLog';
|
||||
import { UploadFiles, UploadProps, UploadUserFile } from 'element-plus';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Upload } from '@element-plus/icons-vue'; // 确保引入图标
|
||||
|
||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/handleLog/uploadAttachments';
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const formRef = ref();
|
||||
@@ -78,28 +108,137 @@ const form = ref({
|
||||
'seekName': '',
|
||||
'phone': '',
|
||||
'handleTime': '',
|
||||
handleLogFileList: [],
|
||||
'handlePosition': ''
|
||||
});
|
||||
const rules = {
|
||||
content: [{ required: true, message: '请输入办事内容', trigger: 'blur' }],
|
||||
seekName: [{ required: true, message: '请选择求助人', trigger: 'blur' }],
|
||||
handlePosition: [{ required: true, message: '请输入办事地点', trigger: 'blur' }],
|
||||
handleTime: [{ required: true, message: '请输入办事时间', trigger: 'blur' }]
|
||||
seekName: [{ required: true, message: '请选择求助人', trigger: 'blur' }]
|
||||
};
|
||||
const userid = ref();
|
||||
|
||||
// ! 富文本 =============================================================================================================
|
||||
function handleContent(val: string) {
|
||||
form.value.content = val.trim();
|
||||
}
|
||||
// ! 富文本 =============================================================================================================
|
||||
interface CustomUploadFile extends UploadUserFile {
|
||||
ossId?: string;
|
||||
}
|
||||
|
||||
const fileList = ref<CustomUploadFile[]>([]);
|
||||
|
||||
function headerToken() {
|
||||
const useStore = useUserStore();
|
||||
return {
|
||||
Authorization: 'Bearer ' + useStore.token
|
||||
};
|
||||
}
|
||||
|
||||
const handleAvatarRemove: UploadProps['onRemove'] = (uploadFile: UploadUserFile, uploadFiles: UploadFiles) => {
|
||||
fileList.value = uploadFiles;
|
||||
};
|
||||
|
||||
// 定义大小限制常量 (单位: MB)
|
||||
const MAX_SINGLE_FILE_SIZE = 10 * 1024 * 1024; // 10MB in bytes
|
||||
const MAX_TOTAL_FILE_SIZE = 20 * 1024 * 1024; // 20MB in bytes
|
||||
// 添加一个锁,防止 on-change 递归调用导致重复提示
|
||||
const isChecking = ref(false);
|
||||
const handleProgress: UploadProps['onChange'] = (uploadFile: UploadUserFile, uploadFiles: UploadFiles) => {
|
||||
// 如果正在校验中,直接返回,避免重复执行
|
||||
if (isChecking.value) return;
|
||||
|
||||
// 加锁
|
||||
isChecking.value = true;
|
||||
// 创建一个新数组来存储校验通过的文件
|
||||
const validFiles: CustomUploadFile[] = [];
|
||||
let newFilesTotalSize = 0;
|
||||
let hasError = false;
|
||||
let errorMsg = '';
|
||||
|
||||
// 1. 遍历所有文件,筛选出符合单文件大小要求的文件,并计算新文件总大小
|
||||
for (const file of uploadFiles) {
|
||||
// 只校验新上传的文件 (有 raw 属性)
|
||||
if (file.raw) {
|
||||
// 检查单个文件大小
|
||||
if (file.raw.size > MAX_SINGLE_FILE_SIZE) {
|
||||
// 如果发现单个文件超标,标记错误,并不将该文件加入 validFiles
|
||||
if (!hasError) {
|
||||
errorMsg = `文件 ${file.name} 大小超过 10MB,已自动移除`;
|
||||
hasError = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
newFilesTotalSize += file.raw.size;
|
||||
}
|
||||
// 将非超标文件(包括旧文件和未超标的新文件)暂时加入
|
||||
console.log(file);
|
||||
validFiles.push({
|
||||
...file,
|
||||
ossId: (file as CustomUploadFile).ossId ?? null
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 如果存在单文件超标的情况,先处理这部分逻辑
|
||||
if (hasError) {
|
||||
ElMessage.error(errorMsg);
|
||||
// 更新 fileList 为移除了超标文件的列表
|
||||
fileList.value = validFiles;
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 检查新文件总大小是否超过 20MB
|
||||
if (newFilesTotalSize > MAX_TOTAL_FILE_SIZE) {
|
||||
ElMessage.error(`所有新上传文件的总大小不能超过 20MB,当前已选新文件总大小约为 ${(newFilesTotalSize / 1024 / 1024).toFixed(2)}MB`);
|
||||
|
||||
// 策略:移除最后添加的那个导致超标的文件
|
||||
// 注意:这里需要找到最后添加的那个文件。uploadFile 参数就是当前触发的文件
|
||||
// 但如果是一次性选择多个文件,uploadFile 可能是其中一个。
|
||||
// 更稳妥的方式是:如果总和超标,则移除所有新文件中最后加入的那个,或者提示用户手动减少。
|
||||
// 这里我们尝试移除最后加入的一个新文件
|
||||
|
||||
// 找出所有新文件
|
||||
const newFiles = validFiles.filter((f) => f.raw);
|
||||
if (newFiles.length > 0) {
|
||||
// 移除最后一个新文件
|
||||
const lastNewFile = newFiles[newFiles.length - 1];
|
||||
const filteredFiles = validFiles.filter((f) => f.uid !== lastNewFile.uid);
|
||||
fileList.value = filteredFiles;
|
||||
} else {
|
||||
// 理论上不会走到这里,因为如果没有新文件,总大小不会增加
|
||||
fileList.value = validFiles;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 校验全部通过,更新 fileList
|
||||
// 只有当 validFiles 与当前 fileList 不同时才赋值,避免不必要的触发
|
||||
if (validFiles.length !== fileList.value.length || validFiles.some((f, i) => f.uid !== fileList.value[i]?.uid)) {
|
||||
fileList.value = validFiles;
|
||||
}
|
||||
|
||||
// 解锁,允许下一次变更触发校验
|
||||
// 使用 nextTick 或 setTimeout 确保 DOM 更新后再解锁,防止极快连续操作的问题
|
||||
setTimeout(() => {
|
||||
isChecking.value = false;
|
||||
}, 100);
|
||||
};
|
||||
|
||||
// ! 初始 ====================================================================================================
|
||||
function init() {
|
||||
console.log('init');
|
||||
getHandleLog(userid.value).then((res) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
fileList.value = res.data.handleLogFileList.map((item) => {
|
||||
return {
|
||||
name: item.fileName,
|
||||
url: item.filePath,
|
||||
ossId: item.ossId
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -109,7 +248,48 @@ if (route.query.id) {
|
||||
}
|
||||
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
const submitForm = async () => {
|
||||
// 筛选出需要上传的新文件
|
||||
const newFiles = fileList.value.filter((item) => item.raw);
|
||||
const oldFiles = fileList.value
|
||||
.filter((item) => !item.raw)
|
||||
.map((item) => {
|
||||
return {
|
||||
fileName: item.name,
|
||||
filePath: item.url,
|
||||
ossId: item.ossId
|
||||
};
|
||||
});
|
||||
const files = [...oldFiles];
|
||||
console.log('oldFiles', files);
|
||||
if (newFiles.length > 0) {
|
||||
const formData = new FormData();
|
||||
newFiles.forEach((item) => {
|
||||
if (item.raw) {
|
||||
formData.append('files', item.raw);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const res = await uploadAttachments(formData);
|
||||
if (res.data && res.data.success && res.data.success.length > 0) {
|
||||
res.data.success.forEach((item) => {
|
||||
const obj = {
|
||||
fileName: item.fileName,
|
||||
filePath: item.url,
|
||||
ossId: item.ossId
|
||||
};
|
||||
files.push(obj);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('上传失败', error);
|
||||
ElMessage.error('文件上传失败');
|
||||
return; // 上传失败则终止提交
|
||||
}
|
||||
}
|
||||
|
||||
form.value.handleLogFileList = files;
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
if (userid.value) {
|
||||
@@ -146,6 +326,34 @@ function handleBack() {
|
||||
.formbox {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
|
||||
.upload-demo {
|
||||
width: 100%;
|
||||
min-width: 200px;
|
||||
&:deep(.el-upload) {
|
||||
width: 100%;
|
||||
}
|
||||
&:deep(.el-upload-list) {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
.uploadBtn {
|
||||
height: 30px;
|
||||
line-height: 20px;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
color: rgba(16, 16, 16, 1);
|
||||
padding-left: 20px;
|
||||
font-size: 14px;
|
||||
border: 1px solid rgba(204, 204, 204, 1);
|
||||
width: 100%;
|
||||
border: 1px solid #ccc;
|
||||
span {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-date-editor.el-input, .el-date-editor.el-input__wrapper) {
|
||||
|
||||
@@ -20,19 +20,6 @@
|
||||
<el-card class="flex-1" shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['repair:add:handlelog']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['repair:edit:handlelog']"
|
||||
>修改</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['handleLog:handleLog:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col> -->
|
||||
<right-toolbar
|
||||
:disable-delete="multiple"
|
||||
:disable-edit="single"
|
||||
@@ -55,12 +42,17 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="求助人" align="center" prop="seekName" width="120" />
|
||||
<el-table-column label="联系方式" align="center" prop="phone" width="120" />
|
||||
<el-table-column label="办事地点" align="center" prop="handlePosition" />
|
||||
<el-table-column label="办事时间" align="center" prop="handleTime" width="120">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="办事地点" align="center" prop="handlePosition" />
|
||||
<el-table-column label="附属材料" width="100" align="center" prop="handlePosition">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="openDiage(scope.row)" link>点击查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['handleLog:handleLog:edit']">编辑</el-button>
|
||||
@@ -70,6 +62,22 @@
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
<!-- 添加或修改办事记录对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<ul class="ulbox" v-if="dialog.files.length > 0">
|
||||
<li @click="handleDown(item)" class="files_item" v-for="(item, index) in dialog.files" :key="index">
|
||||
<div>
|
||||
{{ item.fileName }}
|
||||
</div>
|
||||
<span class="clickdown">点击下载</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="ulbox" v-else>
|
||||
<li class="files_item_no">
|
||||
<div>暂无数据</div>
|
||||
</li>
|
||||
</ul>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
@@ -123,10 +131,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询办事记录列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listHandleLog(queryParams.value);
|
||||
handleLogList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listHandleLog(queryParams.value)
|
||||
.then((res) => {
|
||||
handleLogList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -158,7 +170,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: HandleLogVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row ? row.id : ids.value[0];
|
||||
router.push({
|
||||
path: '/repair/editHandleLog',
|
||||
query: {
|
||||
@@ -175,7 +187,21 @@ const handleDelete = async (row?: HandleLogVO) => {
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
};
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
files: []
|
||||
});
|
||||
|
||||
const openDiage = (row) => {
|
||||
dialog.visible = true;
|
||||
dialog.title = '查看附属材料';
|
||||
console.log(row);
|
||||
dialog.files = row.handleLogFileList ?? [];
|
||||
};
|
||||
const handleDown = (item) => {
|
||||
proxy?.$download.oss(item.ossId);
|
||||
};
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
@@ -185,4 +211,36 @@ onMounted(() => {
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
.ulbox {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.files_item_no {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 10px;
|
||||
}
|
||||
.files_item {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
background-color: #f5f5f5;
|
||||
color: #409eff;
|
||||
.clickdown {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
.clickdown {
|
||||
color: #cccc;
|
||||
font-size: small;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -133,10 +133,14 @@ const { queryParams, form } = toRefs(data);
|
||||
/** 查询房屋设施管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listHouseFacilities(queryParams.value);
|
||||
houseFacilitiesList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listHouseFacilities(queryParams.value)
|
||||
.then((res) => {
|
||||
houseFacilitiesList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -180,27 +184,11 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: HouseFacilitiesVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/system/addHouseFacilities',
|
||||
query: {
|
||||
id: row.id
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
houseFacilitiesFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (form.value.id) {
|
||||
await updateHouseFacilities(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await addHouseFacilities(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="办理人" prop="handleName">
|
||||
<el-input v-model.number="form.handleName" placeholder="请输入办理人姓名" />
|
||||
<el-input v-model="form.handleName" placeholder="请输入办理人姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
@@ -105,7 +105,7 @@ const form = ref({
|
||||
cardCode: '', // 月卡编号
|
||||
cardName: null, // 持卡人姓名
|
||||
phone: '', // 手机号
|
||||
carNum: null, // 绑定车牌号
|
||||
carNum: '', // 绑定车牌号
|
||||
handleName: '', // 办理人姓名
|
||||
cost: null, // 费用/元
|
||||
payMethod: '', // 支付方式
|
||||
@@ -128,6 +128,14 @@ const rules = ref({
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
handleName: [
|
||||
{ required: true, message: '请输入姓名', trigger: 'blur' },
|
||||
{
|
||||
validator: (_, value) => validator(value, 'ChineseName'),
|
||||
message: '请输入正确的中文姓名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||
{
|
||||
@@ -145,7 +153,7 @@ const rules = ref({
|
||||
return;
|
||||
}
|
||||
if (!LicensePlateValidator.isValidPlate(value)) {
|
||||
callback(new Error('请输入正确的车牌号格式'));
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
@@ -159,7 +167,8 @@ const rules = ref({
|
||||
{
|
||||
validator: (_, value) => validator(value, 'money'),
|
||||
message: '请输入正确的金额,最多两位小数',
|
||||
trigger: 'blur'
|
||||
trigger: 'blur',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -54,19 +54,19 @@
|
||||
<el-table v-loading="loading" border :data="monthCardList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="月卡编号" align="center" prop="cardCode" v-if="true" />
|
||||
<el-table-column label="办理时间" align="center" prop="handleTime" width="180">
|
||||
<el-table-column label="办理时间" align="center" prop="handleTime" width="150">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="业主" align="center" prop="cardName" />
|
||||
<el-table-column label="绑定车牌号" align="center" prop="carNum" />
|
||||
<el-table-column label="剩余有效天数" align="center" prop="handleName">
|
||||
<el-table-column label="业主" align="center" prop="cardName" width="150" />
|
||||
<el-table-column label="绑定车牌号" align="center" prop="carNum" width="150" />
|
||||
<el-table-column label="剩余有效天数" align="center" prop="handleName" width="120">
|
||||
<template #default="scope">
|
||||
{{ diffDays(scope.row.startTime, scope.row.endTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付方式" align="center" prop="payMethod">
|
||||
<el-table-column label="支付方式" align="center" prop="payMethod" width="150">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_pay_method" :value="scope.row.payMethod" />
|
||||
</template>
|
||||
@@ -76,7 +76,7 @@
|
||||
<dict-tag :options="com_pay_method" :value="scope.row.payMethod" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="备注" align="center" prop="remark"></el-table-column>
|
||||
<el-table-column label="备注" show-overflow-tooltip align="center" prop="remark"></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="handleUpdate(scope.row)" v-hasPermi="['monthCard:monthCard:edit']">修改</el-button>
|
||||
@@ -206,10 +206,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询月卡管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listMonthCard(queryParams.value);
|
||||
monthCardList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listMonthCard(queryParams.value)
|
||||
.then((res) => {
|
||||
monthCardList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
|
||||
@@ -143,10 +143,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询公告信息列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listNotice(queryParams.value);
|
||||
noticeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listNotice(queryParams.value)
|
||||
.then((res) => {
|
||||
noticeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -177,7 +181,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: NoticeVO) => {
|
||||
const _id = row.noticeId || ids.value[0];
|
||||
const _id = row?.noticeId || ids.value[0];
|
||||
router.push({
|
||||
path: '/repair/editNoticePc',
|
||||
query: {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<h3 class="title">
|
||||
代办 <span v-if="todonum !== 0">({{ todonum }})</span>
|
||||
</h3>
|
||||
<el-button link type="primary">清除未读</el-button>
|
||||
<el-button link type="primary">全部已读</el-button>
|
||||
</div>
|
||||
<div class="flex" v-else-if="activeTabs === 2">
|
||||
<h3 class="title">
|
||||
@@ -36,6 +36,7 @@
|
||||
</h3>
|
||||
<el-button link type="primary">清除未读</el-button>
|
||||
</div>
|
||||
|
||||
<ul v-if="activeTabs === 1">
|
||||
<li
|
||||
v-for="(item, index) in awaittoList"
|
||||
@@ -49,59 +50,66 @@
|
||||
<div class="info">{{ item.content }},保修标题:{{ item.item }}</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul v-else-if="activeTabs === 2">
|
||||
<li
|
||||
v-for="(item, index) in noticelist"
|
||||
:key="index"
|
||||
@click="handleDisable(item)"
|
||||
@click="handleRead(item)"
|
||||
:class="{
|
||||
disable: item.disabled
|
||||
disable: !isdisable(item)
|
||||
}"
|
||||
>
|
||||
<div class="subtitle">报修工单通知</div>
|
||||
<div class="info">您有一条新的报修工单需要处理,保修标题:下水道堵塞</div>
|
||||
</li>
|
||||
</ul>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="init" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getNotificationList } from '@/api/system/Notification/index';
|
||||
import pagination from '@/components/Pagination/index.vue';
|
||||
import { getNotificationList, NotificationVo, ReadNotificationByID } from '@/api/system/Notification/index';
|
||||
import { ref } from 'vue';
|
||||
|
||||
// 1 代办 2通知
|
||||
const activeTabs = ref(1);
|
||||
|
||||
function handleClick(tab: number) {
|
||||
activeTabs.value = tab;
|
||||
}
|
||||
|
||||
const todonum = computed(() => {
|
||||
return awaittoList.value.filter((item) => isdisable(item)).length;
|
||||
});
|
||||
const noticnum = computed(() => {
|
||||
return noticelist.value.filter((item) => isdisable(item)).length;
|
||||
});
|
||||
const total = ref(0);
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
|
||||
function handleClick(tab: number) {
|
||||
activeTabs.value = tab;
|
||||
}
|
||||
|
||||
function isdisable(item) {
|
||||
return item.repairIsCheck ? item.repairIsCheck === '1' : item.manageIsCheck === '1';
|
||||
}
|
||||
const noticelist = ref([]);
|
||||
const awaittoList = ref([]);
|
||||
const awaittoList = ref<NotificationVo[]>([]);
|
||||
function init() {
|
||||
getNotificationList({
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
}).then((res) => {
|
||||
awaittoList.value = res.data;
|
||||
getNotificationList(queryParams.value).then((res) => {
|
||||
awaittoList.value = res.rows;
|
||||
total.value = res.total;
|
||||
});
|
||||
}
|
||||
init();
|
||||
|
||||
function handleRead(row) {}
|
||||
function handleDisable(row) {
|
||||
row.disabled = true;
|
||||
function handleRead(row: NotificationVo) {
|
||||
ReadNotificationByID([row.id]).then(() => {
|
||||
init();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -112,6 +120,7 @@ function handleDisable(row) {
|
||||
display: flex;
|
||||
font-size: 0.8rem;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
.lefttabs {
|
||||
width: 275px;
|
||||
height: 100%;
|
||||
|
||||
@@ -166,10 +166,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
// 停车缴费
|
||||
const res = await listParkingCost(queryParams.value);
|
||||
parkingCostList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listParkingCost(queryParams.value)
|
||||
.then((res) => {
|
||||
parkingCostList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -200,7 +204,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ParkingCostVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/carArea/editParkingCost',
|
||||
query: {
|
||||
|
||||
@@ -10,39 +10,22 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="参与范围" prop="cardName">
|
||||
<el-radio-group v-model="form.scope">
|
||||
<el-radio v-for="item in com_questionnaire_scope" :value="item.value" :label="item.label" :key="item.value"></el-radio>
|
||||
</el-radio-group>
|
||||
<div class="flex flex-items-center">
|
||||
<el-radio-group v-model="form.scope">
|
||||
<el-radio v-for="item in com_questionnaire_scope" :value="item.value" :label="item.label" :key="item.value"></el-radio>
|
||||
</el-radio-group>
|
||||
<Holder v-if="form.scope === '1'" returnvalue="id" ref="HolderRef" :isMultiple="true" :userid="checkoutUses" @change="handleSelect">
|
||||
<template #default>
|
||||
<el-button type="primary" link @click="OpenUseTablesfun">选择业主</el-button>
|
||||
</template>
|
||||
</Holder>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="form.scope === '1'">
|
||||
<el-col :span="12">
|
||||
<ul class="checkoutSideUsesbox">
|
||||
<li v-for="(item, index) in checkoutUses" :key="index">
|
||||
<div>
|
||||
<span>姓名:</span>
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
<el-icon @click="delteUse(item.id)">
|
||||
<Delete></Delete>
|
||||
</el-icon>
|
||||
</li>
|
||||
<Holder returnvalue="*" ref="HolderRef" :isMultiple="true" :userid="checkoutUses" @change="handleSelect">
|
||||
<template #default>
|
||||
<li @click="OpenUseTablesfun" class="add justify-center">
|
||||
<el-icon>
|
||||
<DocumentAdd></DocumentAdd>
|
||||
</el-icon>
|
||||
<span>添加业主</span>
|
||||
</li>
|
||||
</template>
|
||||
</Holder>
|
||||
</ul>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="时间范围" prop="timedata">
|
||||
<el-date-picker
|
||||
v-model="timedata"
|
||||
@@ -104,18 +87,18 @@ const timedata = ref([]);
|
||||
// 打开
|
||||
const HolderRef = ref<InstanceType<typeof Holder>>();
|
||||
function OpenUseTablesfun() {
|
||||
HolderRef.value.open();
|
||||
HolderRef.value.open(form.value.residents.split(',').filter((item) => item));
|
||||
}
|
||||
// 多选
|
||||
const checkoutUses = ref([]);
|
||||
function handleSelect(val) {
|
||||
checkoutUses.value = val;
|
||||
form.value.residents = val.map((item) => item.id).join(',');
|
||||
}
|
||||
// 删除
|
||||
function delteUse(id: string | number) {
|
||||
checkoutUses.value = checkoutUses.value.filter((item) => item.id !== id);
|
||||
form.value.residents = val
|
||||
.map((item) => item)
|
||||
.filter((item) => item)
|
||||
.join(',');
|
||||
}
|
||||
|
||||
// ! 编辑问卷 ------------------------------------------------------------------------
|
||||
const questionnaireEditRef = ref<InstanceType<typeof QuestionnaireEdit>>();
|
||||
const editData = ref<QuestionComponentnaireForm>(null);
|
||||
@@ -155,15 +138,7 @@ async function handleEdit(id: string | number) {
|
||||
checkoutUses.value = res.data.residents
|
||||
.split(',')
|
||||
.filter((item) => item)
|
||||
.map((item) => {
|
||||
const find = tableData.value.find((useritem) => useritem.id == item);
|
||||
if (find) {
|
||||
return {
|
||||
name: find.name,
|
||||
id: item
|
||||
};
|
||||
}
|
||||
});
|
||||
.map((item) => item);
|
||||
timedata.value = [res.data.startTime, res.data.endTime];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- TODO 删除问题 -->
|
||||
<el-card class="flex-1" shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
@@ -98,7 +98,7 @@ const questionnaireList = ref<QuestionnaireVO[]>([]);
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
const ids = ref<Array<string>>([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
@@ -141,10 +141,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询问卷调查列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listQuestionnaire(queryParams.value);
|
||||
questionnaireList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listQuestionnaire(queryParams.value)
|
||||
.then((res) => {
|
||||
questionnaireList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -188,7 +192,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: QuestionnaireVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/repair/editQuestionnaire',
|
||||
query: {
|
||||
@@ -226,21 +230,23 @@ const submitForm = () => {
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: QuestionnaireVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
await proxy?.$modal.confirm('是否确认删除问卷调查?').finally(() => (loading.value = false));
|
||||
await delQuestionnaire(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
};
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
proxy?.download(
|
||||
'questionnaire/questionnaire/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`questionnaire_${new Date().getTime()}.xlsx`
|
||||
);
|
||||
await proxy?.$modal
|
||||
.confirm('是否确认删除问卷调查?')
|
||||
.then(() => {
|
||||
delQuestionnaire(_ids, true).catch(async (res) => {
|
||||
const content = res.msg.replace(/\n/g, '<br/>');
|
||||
await proxy?.$modal
|
||||
.confirm(content)
|
||||
.then(() => {
|
||||
delQuestionnaire(_ids, false).then(() => {
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
getList();
|
||||
});
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
});
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -27,7 +27,13 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="报修标题" prop="item">
|
||||
<el-input 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">
|
||||
@@ -38,7 +44,19 @@
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="报修人" prop="residentId">
|
||||
<Holder :userid="form.residentId" @change="handleChangeResident"></Holder>
|
||||
<Holder :isMultiple="false" :userid="form.residentId ?? ''" ref="HolderRef" @change="handleChange">
|
||||
<template #default>
|
||||
<div class="residentBox" @click="choiceResidentFun">
|
||||
<div class="defaultbox" v-if="form.residentId === '' || form.residentId === null">
|
||||
<span>请选择</span>
|
||||
<el-icon><Search /></el-icon>
|
||||
</div>
|
||||
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
|
||||
<span>姓名:{{ form?.residentName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Holder>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -88,9 +106,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addMonthCard, getMonthCard, updateMonthCard } from '@/api/system/MonthCard';
|
||||
import { getVillageTree } from '@/api/system/house';
|
||||
import { getCommunitylistAPI } from '@/api/system/community';
|
||||
import { convertBuildingToTree, hasFormData } from '@/utils/house';
|
||||
import Holder from '@/components/Holder/index.vue';
|
||||
import { UploadProps, UploadUserFile } from 'element-plus';
|
||||
@@ -114,8 +129,10 @@ const form = ref({
|
||||
id: null,
|
||||
houseId: null, // 关联房屋id
|
||||
maintenanceItemId: null, // 维修项目id
|
||||
item: '', // 标题项目名称
|
||||
problem: '', // 问题描述
|
||||
residentId: null, // 报修人id(住户表id)
|
||||
residentId: '', // 报修人id(住户表id)
|
||||
residentName: '', // 报修人姓名
|
||||
phone: null, // 报手机号码
|
||||
problemImageUrl: '', // 问题图片地址
|
||||
problemStatus: '0', // 0 已提交 1已分配 2维修中 3维修完成
|
||||
@@ -143,7 +160,7 @@ const currentviliage = ref();
|
||||
const maintenanceItemTreeData = ref();
|
||||
function init() {
|
||||
gettreelistRepairProject().then((res) => {
|
||||
maintenanceItemTreeData.value = res.data;
|
||||
maintenanceItemTreeData.value = handleTreeDisable(res.data);
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
form.value.id = userid.value;
|
||||
@@ -168,6 +185,21 @@ function init() {
|
||||
}
|
||||
init();
|
||||
|
||||
function handleTreeDisable(TreeData) {
|
||||
const arr = TreeData.map((item) => {
|
||||
if (item.status === '1') {
|
||||
item.disabled = true;
|
||||
} else {
|
||||
item.disabled = false;
|
||||
}
|
||||
if (item && item.children && item.children.length > 0) {
|
||||
item.children = handleTreeDisable(item.children);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
// ! 上传图片 =--==================================================================
|
||||
const fileList = ref<UploadUserFile[]>([]);
|
||||
|
||||
@@ -184,8 +216,21 @@ const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
|
||||
};
|
||||
|
||||
// !== 选择报修人 ====================================================================
|
||||
function handleChangeResident(val: string | number) {
|
||||
form.value.residentId = val;
|
||||
const holderInfo = ref(null);
|
||||
const HolderRef = ref<typeof Holder>(null);
|
||||
function choiceResidentFun() {
|
||||
HolderRef.value.open([form.value.residentId]);
|
||||
}
|
||||
// 选择住户
|
||||
function handleChange(pop) {
|
||||
holderInfo.value = null;
|
||||
holderInfo.value = pop;
|
||||
form.value.residentId = '';
|
||||
form.value.residentName = '';
|
||||
if (pop !== null) {
|
||||
form.value.residentId = holderInfo.value.id;
|
||||
form.value.residentName = holderInfo.value.name;
|
||||
}
|
||||
}
|
||||
|
||||
// !== 房屋 ===========================================================================
|
||||
@@ -314,4 +359,21 @@ const cancelForm = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
.residentBox {
|
||||
width: 385px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
.defaultbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #f4f8ff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="AddBuildingBox">
|
||||
<PageHeader :title="userid ? '编辑车辆信息' : '添加车辆信息'"></PageHeader>
|
||||
<PageHeader></PageHeader>
|
||||
<div class="AddBuildingBody">
|
||||
<div class="title">基本信息</div>
|
||||
<div class="addBuildingFormBody">
|
||||
@@ -41,7 +41,7 @@
|
||||
<el-col :span="11">
|
||||
<el-form-item label="隶属父级" prop="email">
|
||||
<el-select @change="handleChange" v-model="form.parentId" placeholder="请选择隶属父级" style="width: 240px">
|
||||
<el-option v-for="item in options" :key="item.id" :label="item.projectName" :value="item.id" />
|
||||
<el-option v-for="item in options" :key="item.id" :disabled="item.disabled" :label="item.projectName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -59,7 +59,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addRepairProject, listRepairProject, updateRepairProject } from '@/api/system/RepairProject';
|
||||
import { addRepairProject, getRepairProject, listRepairProject, updateRepairProject } from '@/api/system/RepairProject';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_repair_project_types } = toRefs<any>(proxy?.useDict('com_repair_project_types'));
|
||||
const { com_repair_project_status } = toRefs<any>(proxy?.useDict('com_repair_project_status'));
|
||||
@@ -88,6 +88,7 @@ const userid = ref(null);
|
||||
const options = ref([]);
|
||||
|
||||
function handleChange(val) {
|
||||
if (!val) return;
|
||||
const find = options.value.find((item) => item.id === val);
|
||||
if (find) {
|
||||
form.value.projectType = find.projectType;
|
||||
@@ -95,7 +96,7 @@ function handleChange(val) {
|
||||
}
|
||||
// != ==========================================
|
||||
|
||||
function init() {
|
||||
async function init() {
|
||||
form.value = {
|
||||
id: null,
|
||||
projectName: null, // 项目名称
|
||||
@@ -104,22 +105,26 @@ function init() {
|
||||
projectLevel: 0, //项目层级
|
||||
status: '0' //状态
|
||||
};
|
||||
listRepairProject().then((res) => {
|
||||
const arr = res.rows.filter((ite) => ite.projectLevel === 0);
|
||||
options.value = arr;
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
const find = res.rows.find((item) => item.id === userid.value);
|
||||
if (find) {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...find,
|
||||
projectLevel: find.projectLevel
|
||||
};
|
||||
handleChange(find.parentId);
|
||||
}
|
||||
}
|
||||
});
|
||||
const res = await listRepairProject();
|
||||
const arr = res.rows.filter((ite) => ite.projectLevel === 0);
|
||||
options.value = arr;
|
||||
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
getRepairProject(userid.value).then((res) => {
|
||||
form.value = res.data;
|
||||
form.value.status = res.data.status ?? '0' + '';
|
||||
options.value = options.value.map((ite) => {
|
||||
if (ite.id === res.data.id) {
|
||||
ite.disabled = true;
|
||||
} else {
|
||||
ite.disabled = false;
|
||||
}
|
||||
return ite;
|
||||
});
|
||||
handleChange(res.data.parentId);
|
||||
});
|
||||
}
|
||||
}
|
||||
init();
|
||||
// !== 提交 =============================================================================
|
||||
|
||||
@@ -60,16 +60,17 @@
|
||||
|
||||
<el-table v-loading="loading" border :data="repairList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="报修房屋" align="center" prop="houseName" />
|
||||
<el-table-column label="报修房屋" align="center" show-overflow-tooltip prop="houseName" />
|
||||
<el-table-column label="维修项目" align="center" prop="maintenanceItemName" />
|
||||
<el-table-column label="标题" align="center" prop="item" />
|
||||
<el-table-column label="问题描述" align="center" prop="problem" />
|
||||
<el-table-column label="报修人" align="center" prop="residentName" />
|
||||
<el-table-column label="预约日期" align="center" prop="orderDate" width="180">
|
||||
<el-table-column label="报修人" width="100" align="center" prop="residentName" />
|
||||
<el-table-column label="预约日期" align="center" prop="orderDate" width="150">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.orderDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="维修状态" align="center" prop="problemStatus">
|
||||
<el-table-column label="维修状态" align="center" width="100" prop="problemStatus">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_repair_status" :value="scope.row.problemStatus || ''"></dict-tag>
|
||||
</template>
|
||||
@@ -94,8 +95,6 @@
|
||||
<script setup name="Repair" lang="ts">
|
||||
import { listRepair, delRepair } from '@/api/system/Repair/index';
|
||||
import { RepairVO, RepairQuery, RepairForm } from '@/api/system/Repair/type';
|
||||
import { listRepairProject } from '@/api/system/RepairProject';
|
||||
import { listResident } from '@/api/system/resident';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
@@ -103,7 +102,7 @@ const { com_repair_status } = toRefs<any>(proxy?.useDict('com_repair_status'));
|
||||
|
||||
interface repairlistType extends RepairVO {
|
||||
maintenanceItemPath?: string;
|
||||
residentName?: string;
|
||||
residentName: string;
|
||||
}
|
||||
const repairList = ref<repairlistType[]>([]);
|
||||
const loading = ref(true);
|
||||
@@ -164,10 +163,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询报修管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listRepair(queryParams.value);
|
||||
repairList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listRepair(queryParams.value)
|
||||
.then((res) => {
|
||||
repairList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -178,6 +181,8 @@ const handleQuery = () => {
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryParams.value.problemStatus = '';
|
||||
queryParams.value.orderDate = '';
|
||||
queryFormRef.value?.resetFields();
|
||||
handleQuery();
|
||||
};
|
||||
@@ -198,7 +203,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: RepairVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/repair/editRepair',
|
||||
query: {
|
||||
@@ -208,7 +213,7 @@ const handleUpdate = async (row?: RepairVO) => {
|
||||
};
|
||||
/** 分配人员 */
|
||||
const handleShare = (row) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/repair/repairMain',
|
||||
query: {
|
||||
|
||||
@@ -15,28 +15,30 @@
|
||||
</template>
|
||||
<div class="w-full h-full CarinfoBox">
|
||||
<el-row class="mb-20px">
|
||||
<el-col :span="8">
|
||||
<el-col :span="10">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">报修房屋</div>
|
||||
<div class="main">{{ form.house }}</div>
|
||||
<div class="main">{{ form.houseName }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="4"></el-col>
|
||||
<el-col :span="10">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">维修项目</div>
|
||||
<div class="main">{{ form.maintenanceItem }}</div>
|
||||
<div class="main">{{ form.maintenanceItemName }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row class="mb-20px">
|
||||
<el-col :span="8">
|
||||
<el-col :span="10">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">报修人</div>
|
||||
<div class="main">{{ form.residentName }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="4"></el-col>
|
||||
<el-col :span="10">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">手机号码</div>
|
||||
<div class="main">{{ form.phone }}</div>
|
||||
@@ -59,7 +61,7 @@
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-row v-if="form.problemImageUrl.trim() === ''">
|
||||
<el-col :span="24">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">附件</div>
|
||||
@@ -69,10 +71,10 @@
|
||||
:zoom-rate="1.2"
|
||||
:max-scale="7"
|
||||
:min-scale="0.2"
|
||||
:preview-src-list="form.problemImageUrlList"
|
||||
:preview-src-list="form.problemImageUrl.split(',').filter((item) => item)"
|
||||
show-progress
|
||||
:initial-index="0"
|
||||
v-for="(item, index) in form.problemImageUrlList"
|
||||
v-for="(item, index) in form.problemImageUrl.split(',').filter((item) => item)"
|
||||
:key="index"
|
||||
:src="splitImages(item)"
|
||||
class="carinfoImage"
|
||||
@@ -93,9 +95,9 @@
|
||||
<div class="preivewBody w-full h-full flex flex-items-start mt-2">
|
||||
<div class="title">维修师傅</div>
|
||||
<div class="preivewBodybox flex-1 ml-5">
|
||||
<repairUser :userid="form.repairId" @change="handleChange"></repairUser>
|
||||
<repairUser :is-multiple="false" :username="form.repairName" :userid="form.repairUserId" @change="handleChange"> </repairUser>
|
||||
<div class="actions mt-5">
|
||||
<el-button @click="handleSend" type="primary">确定派单</el-button>
|
||||
<el-button v-if="form.problemStatus === '0'" @click="handleSend" type="primary">确定派单</el-button>
|
||||
<el-button @click="backRouter">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -150,17 +152,10 @@ import { ref } from 'vue';
|
||||
import repairUser from '@/components/Holder/repairUser.vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { getRepair, updateRepair } from '@/api/system/Repair';
|
||||
import { getHousePathById } from '@/utils/house';
|
||||
import { listRepairProject } from '@/api/system/RepairProject';
|
||||
import { listResident } from '@/api/system/resident';
|
||||
import { RepairVO } from '@/api/system/Repair/type';
|
||||
import { useHouseStore } from '@/store/modules/house';
|
||||
import { listRepairProcess, updateRepairProcess } from '@/api/system/repairProcess';
|
||||
import { getRepairProcess, listRepairProcess, updateRepairProcess } from '@/api/system/repairProcess';
|
||||
import { splitImages } from '@/utils';
|
||||
|
||||
const houseStore = useHouseStore();
|
||||
const { treedata } = storeToRefs(houseStore);
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
@@ -168,32 +163,41 @@ const active = ref(0);
|
||||
const activeStop = ref(0);
|
||||
|
||||
interface formType extends RepairVO {
|
||||
maintenanceItem?: string;
|
||||
residentName?: string;
|
||||
problemImageUrlList?: string[];
|
||||
house?: string;
|
||||
problemImageUrlList: string[];
|
||||
}
|
||||
|
||||
const form = ref<formType>({
|
||||
'id': null,
|
||||
'houseId': null,
|
||||
'id': '',
|
||||
'houseId': '',
|
||||
'maintenanceItemId': null,
|
||||
'maintenanceItemName': null,
|
||||
'problem': '',
|
||||
'residentId': null,
|
||||
'phone': null,
|
||||
'residentId': '',
|
||||
'residentName': null,
|
||||
'phone': '',
|
||||
'orderDate': '',
|
||||
'problemImageUrl': '',
|
||||
'problemStatus': '0',
|
||||
'problemStatus': '',
|
||||
'repairDes': '',
|
||||
'repairImageUrl': '',
|
||||
'repairId': null
|
||||
'repairId': '',
|
||||
'repairName': '',
|
||||
'houseName': '',
|
||||
'repairUserId': '',
|
||||
'item': null,
|
||||
'projectType': null,
|
||||
'updateTime': '',
|
||||
'projectTypeStr': '',
|
||||
'repairIsCheck': '1',
|
||||
'manageIsCheck': '1',
|
||||
'isCheckStr': null,
|
||||
'repairPhone': null,
|
||||
'repairRoleName': null,
|
||||
'repairStatus': null,
|
||||
'createTime': null,
|
||||
problemImageUrlList: []
|
||||
});
|
||||
const userid = ref();
|
||||
|
||||
// 维修项目
|
||||
const projectlist = ref([]);
|
||||
// 住户
|
||||
const residentList = ref([]);
|
||||
// 审核流程
|
||||
const reviewInfo = ref({
|
||||
'id': '',
|
||||
@@ -207,39 +211,28 @@ const reviewInfo = ref({
|
||||
});
|
||||
// ! 房屋 ====================================================================================================
|
||||
async function init() {
|
||||
// 项目
|
||||
const projectres = await listRepairProject();
|
||||
projectlist.value = projectres.rows;
|
||||
// 住户
|
||||
const residentlistres = await listResident();
|
||||
residentList.value = residentlistres.rows;
|
||||
// 报修详情
|
||||
const res = await getRepair(userid.value);
|
||||
form.value = res.data;
|
||||
const find = projectlist.value.find((item) => item.id === form.value.maintenanceItemId);
|
||||
if (find) {
|
||||
if (find.parentId) {
|
||||
const find2 = projectlist.value.find((item) => item.id === find.parentId);
|
||||
form.value.maintenanceItem = find2.projectName + ' - ' + find.projectName;
|
||||
} else {
|
||||
form.value.maintenanceItem = find.projectName;
|
||||
getRepair(userid.value).then((res) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
try {
|
||||
form.value.problemImageUrlList = form.value.problemImageUrl.split(',').filter((item) => item);
|
||||
} catch {
|
||||
form.value.problemImageUrlList = [];
|
||||
}
|
||||
}
|
||||
|
||||
const houseinfo = getHousePathById(treedata.value, form.value.houseId, 'label');
|
||||
form.value.house = houseinfo.join(' - ');
|
||||
|
||||
const residentinfo = residentList.value.find((item) => item.id === form.value.residentId);
|
||||
form.value.residentName = residentinfo.name;
|
||||
|
||||
form.value.problemImageUrlList = form.value.problemImageUrl.split(',').filter((item) => item);
|
||||
|
||||
// 获取保修审核状态
|
||||
const info = await listRepairProcess({ repairId: form.value.id, pageNum: 1, pageSize: 999999 });
|
||||
if (info && info.rows.length > 0) {
|
||||
reviewInfo.value = info.rows.pop();
|
||||
handleReview();
|
||||
}
|
||||
// 获取保修审核状态
|
||||
listRepairProcess({
|
||||
repairId: res.data.id,
|
||||
pageSize: 9999,
|
||||
pageNum: 1
|
||||
}).then((info) => {
|
||||
reviewInfo.value = info.rows[info.rows.length - 1] || null;
|
||||
console.log(reviewInfo.value);
|
||||
handleReview();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 处理审核
|
||||
@@ -269,10 +262,12 @@ if (route.query.id) {
|
||||
|
||||
/** 派单 */
|
||||
function handleSend() {
|
||||
// 已分配
|
||||
form.value.problemStatus = '1';
|
||||
updateRepair(form.value).then(() => {
|
||||
form.value.problemStatus = '1';
|
||||
reviewInfo.value.allocateTime = new Date().toLocaleString().replaceAll('/', '-');
|
||||
if (form.value.repairId) {
|
||||
if (form.value.repairUserId) {
|
||||
reviewInfo.value.allocateStatus = '1';
|
||||
} else {
|
||||
reviewInfo.value.allocateStatus = '0';
|
||||
@@ -285,7 +280,7 @@ function handleSend() {
|
||||
|
||||
/** 选择维修人员 */
|
||||
function handleChange(row) {
|
||||
form.value.repairId = row;
|
||||
form.value.repairUserId = row;
|
||||
}
|
||||
|
||||
/** 返回 */
|
||||
@@ -327,8 +322,9 @@ function handleEdit() {
|
||||
.label {
|
||||
font-weight: 600;
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
text-align: left;
|
||||
padding-right: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.carinfoImage {
|
||||
margin: 10px;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
:disable-delete="multiple"
|
||||
:disable-edit="single"
|
||||
:show-add="checkPermi(['repairProject:repairProject:add'])"
|
||||
:show-edit="checkPermi(['repairProject:repairProject:edit'])"
|
||||
:show-edit="false"
|
||||
:show-delete="checkPermi(['repairProject:repairProject:remove'])"
|
||||
@update:add="handleAdd"
|
||||
@update:edit="handleUpdate()"
|
||||
|
||||
@@ -19,17 +19,26 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="计算公式" prop="formula">
|
||||
<el-select v-model="form.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>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="计量单位" prop="unit">
|
||||
<el-form-item label="计量单位" prop="unit" v-if="form.formula !== '2'">
|
||||
<el-select v-model="form.unit">
|
||||
<el-option v-for="(item, index) in com_charge_item_unit" :key="index" :value="item.value" :label="item.label"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="费用单价" prop="fixedPrice">
|
||||
<el-input v-model.trim="form.fixedPrice" placeholder="请输入费用单价" />
|
||||
<el-input v-model.trim="form.fixedPrice" :placeholder="placeHolderFun(form.typeId)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="计算精度" prop="accuracy">
|
||||
<el-select v-model="form.accuracy">
|
||||
@@ -41,16 +50,15 @@
|
||||
<el-option v-for="(item, index) in com_charge_item_carry_method" :key="index" :value="item.value" :label="item.label"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用/停用" prop="status">
|
||||
<!-- <el-form-item label="启用/停用" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio value="0" label="启用"></el-radio>
|
||||
<el-radio value="1" label="停用"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item style="margin-top: 30px">
|
||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||
<el-button @click="cancelForm">返回</el-button>
|
||||
@@ -119,6 +127,9 @@ if (route.query.id) {
|
||||
// !== 提交 =============================================================================
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
if (form.value.formula === '2') {
|
||||
form.value.unit = null;
|
||||
}
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
if (userid.value) {
|
||||
@@ -139,6 +150,12 @@ const submitForm = () => {
|
||||
const cancelForm = () => {
|
||||
router.back();
|
||||
};
|
||||
|
||||
// 车位费 物业费
|
||||
const typeNamelist = ref(['2049026520314445826']);
|
||||
function placeHolderFun(typeId: string) {
|
||||
return typeNamelist.value.includes(typeId) ? '请输入每日费用单价' : '请输入费用单价';
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -36,38 +36,39 @@
|
||||
<el-table v-loading="loading" border :data="chargeItemList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="项目名称" align="center" prop="itemName" />
|
||||
<el-table-column label="计费方式" align="center" prop="billingType">
|
||||
<el-table-column label="计费方式" width="100" align="center" prop="billingType">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_charge_item_method" :value="scope.row.billingType"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计算公式" align="center" prop="formula">
|
||||
<el-table-column label="计算公式" width="100" align="center" prop="formula">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_charge_item_formula" :value="scope.row.formula"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" align="center" prop="fixedPrice">
|
||||
<el-table-column label="单价" width="100" align="center" prop="fixedPrice">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price }}
|
||||
<dict-tag :options="com_charge_item_unit" :value="scope.row.fixedPrice"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计量单位" align="center" prop="unit">
|
||||
<el-table-column label="计量单位" width="100" align="center" prop="unit">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
||||
<dict-tag v-if="scope.row.unit" :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计算精度" align="center" prop="accuracy">
|
||||
<el-table-column label="计算精度" width="120" align="center" prop="accuracy">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_charge_item_precision" :value="scope.row.accuracy"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="进位方式" align="center" prop="carryMethod">
|
||||
<el-table-column label="进位方式" width="100" align="center" prop="carryMethod">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_charge_item_carry_method" :value="scope.row.carryMethod"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<el-table-column label="状态" width="100" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
@change="(val: string) => handleSwitch(val, scope.row)"
|
||||
@@ -77,6 +78,7 @@
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" show-overflow-tooltip align="center" prop="remark" />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['chargeItem:chargeItem:edit']">编辑</el-button>
|
||||
@@ -138,10 +140,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询收费项目管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listChargeItem(queryParams.value);
|
||||
chargeItemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listChargeItem(queryParams.value)
|
||||
.then((res) => {
|
||||
chargeItemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -185,10 +191,11 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ChargeItemVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/sdb/editchargeItem',
|
||||
query: {
|
||||
id: row.id
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -214,23 +214,12 @@ const submitForm = () => {
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: ChargeTypeVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
await proxy?.$modal.confirm('是否确认删除收费类型编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||
await proxy?.$modal.confirm('是否确认删除该收费类型?').finally(() => (loading.value = false));
|
||||
await delChargeType(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
};
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
proxy?.download(
|
||||
'chargeType/chargeType/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`chargeType_${new Date().getTime()}.xlsx`
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<el-input v-model.trim="form.billName" placeholder="请输入账单名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="收费项目" prop="chargeItemId">
|
||||
<el-select v-model="form.chargeItemId" @change="handleChange">
|
||||
<el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)">
|
||||
<el-option
|
||||
:disabled="item.status === '1'"
|
||||
v-for="(item, index) in chargeitemlist"
|
||||
@@ -21,20 +21,23 @@
|
||||
</el-form-item>
|
||||
<!-- 水费,电费, 收费范围为 房屋 -->
|
||||
<el-form-item label="收费范围" prop="chargeScope" v-if="typeNamelist.includes(typeName)">
|
||||
<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>
|
||||
<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
|
||||
:disabled="!form.chargeItemId"
|
||||
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>
|
||||
</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>
|
||||
@@ -45,6 +48,7 @@
|
||||
<div class="flex flex-col flex-items-end">
|
||||
<el-radio
|
||||
style="margin-right: 0"
|
||||
:disabled="!form.chargeItemId"
|
||||
v-for="(item, index) in com_questionnaire_scope"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
@@ -65,7 +69,11 @@
|
||||
</el-form-item>
|
||||
<!-- 业主选择 -->
|
||||
<el-form-item v-if="form.chargeScope === '1' && !typeNamelist.includes(typeName)">
|
||||
<div class="residentBox">
|
||||
<!-- 业主选择 车位费用 -->
|
||||
<div class="residentBox" v-if="typeName === HandleTypeId.Resident.Parking">
|
||||
<CarUser returnvalue="parkingId" ref="ParkinguserRef" :isMultiple="true" @change="handleCheckPaking"></CarUser>
|
||||
</div>
|
||||
<div class="residentBox" v-else>
|
||||
<UserHolder returnvalue="residentId" ref="userRef" :isMultiple="true" @change="handleCheckUser"></UserHolder>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -74,18 +82,32 @@
|
||||
<el-option v-for="(item, index) in com_bill_charge_period" :key="index" :value="item.value" :label="item.label"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="起止日期" prop="price">
|
||||
<el-form-item label="起止日期" prop="startDate">
|
||||
<el-date-picker
|
||||
v-model="StartEndDate"
|
||||
unlink-panels
|
||||
@update:model-value="handleDate"
|
||||
:value-format="datepicker[form.chargePeriod].format"
|
||||
:format="datepicker[form.chargePeriod].format"
|
||||
:type="datepicker[form.chargePeriod].type"
|
||||
@clear="handleClear"
|
||||
:value-format="datepicker[2].format"
|
||||
:format="datepicker[2].format"
|
||||
:type="datepicker[2].type"
|
||||
range-separator="到"
|
||||
start-placeholder="开始"
|
||||
end-placeholder="结束"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="结束日期" prop="price">
|
||||
<el-date-picker
|
||||
v-model="StartEndDate"
|
||||
@update:model-value="handleDate"
|
||||
:value-format="datepicker[2].format"
|
||||
:format="datepicker[2].format"
|
||||
:type="datepicker[2].type"
|
||||
range-separator="到"
|
||||
start-placeholder="开始"
|
||||
end-placeholder="结束"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
@@ -102,14 +124,16 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import House from '@/components/Holder/house.vue';
|
||||
import UserHolder from '@/components/Holder/user.vue';
|
||||
import CarUser from '@/components/Holder/CarUser.vue';
|
||||
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||||
import { getBill, updateBill, addBill, BillHouse, listBillHouse, queryResidentList_holder } from '@/api/system/SdbBill';
|
||||
import type { DatePickerType } from 'element-plus';
|
||||
import { formatDate2 } from '@/utils';
|
||||
import { Delete } from '@element-plus/icons-vue';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
||||
@@ -137,7 +161,8 @@ const form = ref({
|
||||
'chargePeriod': '2', // 费用周期
|
||||
houseIds: [], // 部分房屋
|
||||
residentIds: [], // 部分业主
|
||||
charegeTypeId: '', // typeid
|
||||
parkingIds: [],
|
||||
chargeTypeId: '', // typeid
|
||||
'startDate': '', // 开始
|
||||
'endDate': '', // 结束
|
||||
'remark': ''
|
||||
@@ -154,10 +179,18 @@ const userid = ref(null);
|
||||
// 开始结束日期
|
||||
const StartEndDate = ref([]);
|
||||
function handleDate(val: string[]) {
|
||||
form.value.startDate = formatDate2(val[0]);
|
||||
form.value.endDate = formatDate2(val[1]);
|
||||
if (val === null || val.length === 0) {
|
||||
form.value.startDate = '';
|
||||
form.value.endDate = '';
|
||||
} else {
|
||||
form.value.startDate = val[0] + ' 00:00:00';
|
||||
form.value.endDate = val[1] + ' 23:59:59';
|
||||
}
|
||||
}
|
||||
function handleClear() {
|
||||
form.value.startDate = '';
|
||||
form.value.endDate = '';
|
||||
}
|
||||
|
||||
// 收费类型
|
||||
const chargeitemlist = ref([]);
|
||||
|
||||
@@ -166,62 +199,74 @@ const chargeitemlist = ref([]);
|
||||
// // 住户列表
|
||||
// const userlist = ref([]);
|
||||
async function init() {
|
||||
listChargeItem().then((res) => {
|
||||
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;
|
||||
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
getBill(userid.value).then((res) => {
|
||||
if (!res.data) return;
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
// TODO 没有住户参数
|
||||
form.value.houseIds = res.data.houseIds || [];
|
||||
form.value.residentIds = res.data.residentIds || [];
|
||||
form.value.parkingIds = res.data.parkingIds || [];
|
||||
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 = [];
|
||||
checkoutUser.value = [];
|
||||
checkoutParking.value = [];
|
||||
checkoutHouses.value = form.value.houseIds.filter((item) => item);
|
||||
checkoutUser.value = form.value.residentIds.filter((item) => item);
|
||||
checkoutParking.value = form.value.parkingIds.filter((item) => item);
|
||||
handleChange(form.value.chargeItemId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 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;
|
||||
getBill(userid.value).then((res) => {
|
||||
if (!res.data) return;
|
||||
form.value = {
|
||||
...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.filter((item) => item);
|
||||
handleChange(form.value.chargeItemId);
|
||||
});
|
||||
}
|
||||
}
|
||||
init();
|
||||
|
||||
const typeNamelist = ref(['2049026484272791553', '2049026503017136129']);
|
||||
const HandleTypeId = {
|
||||
/** 显示房屋 */
|
||||
'House': {
|
||||
/** 水费 */
|
||||
'Water': '2049026484272791553',
|
||||
/** 电费 */
|
||||
'Electricity': '2049026503017136129'
|
||||
},
|
||||
/** 显示业主 */
|
||||
'Resident': {
|
||||
/** 车位费 */
|
||||
'Parking': '2049026574236418050'
|
||||
}
|
||||
};
|
||||
// 符合类型: 显示房屋,选择房屋
|
||||
const typeNamelist = ref([HandleTypeId.House.Water, HandleTypeId.House.Electricity]);
|
||||
const typeName = ref('');
|
||||
// 获取收费类型id
|
||||
function handleChange(val: string) {
|
||||
function handleChange(val: string, callback: boolean = false) {
|
||||
const find = chargeitemlist.value.find((item) => item.id === val);
|
||||
if (find) {
|
||||
form.value.charegeTypeId = find.typeId;
|
||||
form.value.chargeTypeId = find.typeId;
|
||||
typeName.value = find.typeId;
|
||||
handleClearCheckout();
|
||||
if (callback) {
|
||||
handleClearCheckout();
|
||||
}
|
||||
}
|
||||
}
|
||||
// !== 业主 =============================================================================
|
||||
|
||||
// 打开
|
||||
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(checkoutHouses.value);
|
||||
} else if (val === 'user') {
|
||||
userRef.value.open(checkoutUser.value);
|
||||
}
|
||||
}
|
||||
// 多选
|
||||
const checkoutHouses = ref<string[]>([]);
|
||||
function handleSelect(val: string[]) {
|
||||
@@ -233,9 +278,15 @@ const checkoutUser = ref([]);
|
||||
/** 添加 业主 */
|
||||
function handleCheckUser(val: string[]) {
|
||||
checkoutUser.value = val;
|
||||
console.log(val);
|
||||
form.value.residentIds = val;
|
||||
}
|
||||
const checkoutParking = ref([]);
|
||||
/** 添加 车位业主 */
|
||||
function handleCheckPaking(val: string[]) {
|
||||
checkoutParking.value = val;
|
||||
console.log(val);
|
||||
form.value.parkingIds = val;
|
||||
}
|
||||
|
||||
/** 清空 */
|
||||
function handleClearCheckout() {
|
||||
@@ -244,10 +295,27 @@ function handleClearCheckout() {
|
||||
form.value.residentIds = [];
|
||||
form.value.houseIds = [];
|
||||
}
|
||||
|
||||
// 打开
|
||||
const HolderRef = ref<InstanceType<typeof House>>();
|
||||
const userRef = ref<InstanceType<typeof UserHolder>>();
|
||||
const ParkinguserRef = ref<InstanceType<typeof CarUser>>();
|
||||
function OpenUseTablesfun(val: string) {
|
||||
if (val === 'house') {
|
||||
HolderRef.value.open(checkoutHouses.value);
|
||||
} else if (val === 'user') {
|
||||
if (typeName.value === HandleTypeId.Resident.Parking) {
|
||||
ParkinguserRef.value.open(checkoutParking.value);
|
||||
} else {
|
||||
userRef.value.open(checkoutUser.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
// !== 业主 =============================================================================
|
||||
|
||||
// !== 提交 =============================================================================
|
||||
const submitForm = () => {
|
||||
console.log(form.value);
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
if (userid.value) {
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
<el-option v-for="(item, index) in chargeItems" :key="index" :value="item.id" :label="item.itemName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="精确查询" prop="type">
|
||||
<el-select style="width: 150px; margin-right: 10px" v-model="queryParams.type">
|
||||
<el-option v-for="(item, index) in com_bill_search_filter" :key="index" :value="item.value" :label="item.label"></el-option>
|
||||
</el-select>
|
||||
<el-input v-model="queryParams.billCode" placeholder="请输入" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
@@ -27,17 +22,6 @@
|
||||
<el-card class="flex-1" shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['bill:bill:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['bill:bill:edit']">编辑</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:bill:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col> -->
|
||||
<right-toolbar :show-add="checkPermi(['bill:bill:add'])" :show-edit="false" :show-delete="false" @update:add="handleAdd"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
@@ -57,11 +41,6 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收费项目" align="center" prop="chargeItemName" />
|
||||
<!-- <el-table-column label="收费周期" align="center" prop="chargePeriod" width="80">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_bill_charge_period" :value="scope.row.chargePeriod"></dict-tag>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="起止时间" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.startDate, '{y}/{m}/{d}') }}</span> -
|
||||
@@ -70,23 +49,20 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" align="center" width="180">
|
||||
<template #default="scope">
|
||||
<div class="flex justify-center">
|
||||
<div class="flex justify-center" v-if="scope.row.unit">
|
||||
<span>{{ scope.row.fixedPrice }}</span> /
|
||||
<dict-tag :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
||||
</div>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="数量" align="center" prop="chargePeriod" />
|
||||
<el-table-column label="费用合计" align="center" prop="chargePeriod" /> -->
|
||||
<el-table-column label="操作" width="120" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['bill:bill:edit']">编辑</el-button>
|
||||
<el-button link type="primary" @click="handleMain(scope.row)" v-hasPermi="['bill:bill:query']">详情</el-button>
|
||||
<!-- <el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['system:bill: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>
|
||||
</div>
|
||||
@@ -99,14 +75,11 @@ import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_bill_search_filter } = toRefs<any>(proxy?.useDict('com_bill_search_filter'));
|
||||
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
||||
// const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
||||
const { com_bill_charge_scope_house } = toRefs<any>(proxy?.useDict('com_bill_charge_scope_house'));
|
||||
const { com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_unit'));
|
||||
|
||||
const billList = ref<BillVO[]>([]);
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
@@ -115,12 +88,6 @@ const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const billFormRef = ref<ElFormInstance>();
|
||||
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const ShowHouselist = ['2049026484272791553', '2049026503017136129'];
|
||||
|
||||
@@ -143,8 +110,6 @@ const data = reactive<PageData<BillForm, BillQuery>>({
|
||||
pageSize: 20,
|
||||
chargeItemId: '',
|
||||
billCode: ''
|
||||
// type: '',
|
||||
// value: ''
|
||||
}
|
||||
});
|
||||
|
||||
@@ -152,7 +117,7 @@ const { queryParams, form } = toRefs(data);
|
||||
|
||||
const chargeItems = ref([]);
|
||||
function init() {
|
||||
listChargeItem().then((res) => {
|
||||
listChargeItem({}).then((res) => {
|
||||
chargeItems.value = res.rows;
|
||||
});
|
||||
}
|
||||
@@ -217,14 +182,6 @@ function handleMain(row) {
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: BillVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
await proxy?.$modal.confirm('是否确认删除账单管理编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||
await delBill(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
|
||||
@@ -8,26 +8,24 @@
|
||||
<el-form-item label="账单名称" prop="billName">
|
||||
<el-input disabled v-model.trim="form.billName" placeholder="请输入账单名称" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="收费项目" prop="chargeItemId">
|
||||
<el-select disabled v-model="form.chargeItemId" @change="handleChange">
|
||||
<el-option v-for="(item, index) in chargeitemlist" :key="index" :value="item.id" :label="item.itemName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="收费范围" prop="chargeScope">
|
||||
|
||||
<el-form-item label="收费范围" prop="chargeScope" v-if="itemTypeincludes">
|
||||
<el-radio-group disabled 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>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.chargeScope === '1'">
|
||||
<div class="residentBox">
|
||||
<ul class="checkoutSideUsesbox">
|
||||
<li v-for="(item, index) in checkoutUses" :key="index">
|
||||
<span>{{ item.buildingName }} </span> / <span>{{ item.unitNo }}单元 </span> / <span>{{ item.floorNo }}楼 </span> /
|
||||
<span>{{ item.houseNo }}室</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<el-form-item label="收费范围" prop="chargeScope" v-else>
|
||||
<el-radio-group disabled 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>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="费用周期" prop="chargePeriod">
|
||||
<el-select disabled v-model="form.chargePeriod">
|
||||
<el-option v-for="(item, index) in com_bill_charge_period" :key="index" :value="item.value" :label="item.label"></el-option>
|
||||
@@ -71,6 +69,7 @@ import { Delete } from '@element-plus/icons-vue';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
||||
const { com_bill_charge_scope_house } = toRefs<any>(proxy?.useDict('com_bill_charge_scope_house'));
|
||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
||||
|
||||
type PickerConfig = {
|
||||
@@ -114,38 +113,47 @@ function handleDate(val: string[]) {
|
||||
form.value.endDate = formatDate2(val[1]);
|
||||
}
|
||||
const chargeitemlist = ref([]);
|
||||
// 电费 水费
|
||||
const typeNamelist = ref(['2049026484272791553', '2049026503017136129']);
|
||||
|
||||
const itemTypeincludes = computed(() => {
|
||||
return typeNamelist.value.includes(form.value.chargeItemId);
|
||||
});
|
||||
|
||||
const houselist = ref([]);
|
||||
|
||||
const checkoutUses = ref([]);
|
||||
async function init() {
|
||||
listChargeItem().then((res) => {
|
||||
const res1 = await listBillHouse({ pageNum: 1, pageSize: 999999 });
|
||||
houselist.value = res1.rows;
|
||||
|
||||
listChargeItem().then(async (res) => {
|
||||
chargeitemlist.value = res.rows;
|
||||
});
|
||||
const res = await listBillHouse({ pageNum: 1, pageSize: 999999 });
|
||||
houselist.value = res.rows;
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
getBill(userid.value).then((res) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
form.value.houseIds = res.data.houseIds || [];
|
||||
StartEndDate.value = [formatDate(res.data.startDate), formatDate(res.data.endDate)];
|
||||
checkoutUses.value = form.value.houseIds
|
||||
.map((item) => {
|
||||
if (item) {
|
||||
const find = houselist.value.find((it) => it.houseId === item);
|
||||
if (find) {
|
||||
return find;
|
||||
} else {
|
||||
return null;
|
||||
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
getBill(userid.value).then((res1) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res1.data
|
||||
};
|
||||
form.value.houseIds = res1.data.houseIds || [];
|
||||
StartEndDate.value = [formatDate(res1.data.startDate), formatDate(res1.data.endDate)];
|
||||
checkoutUses.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);
|
||||
});
|
||||
}
|
||||
})
|
||||
.filter((item) => item !== null);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
@@ -10,16 +10,19 @@
|
||||
<el-button type="primary" @click="openDiage">收款</el-button>
|
||||
<!-- <el-button>添加临时收费</el-button> -->
|
||||
<!-- <el-button>预存</el-button> -->
|
||||
<!-- <el-button>打印</el-button> -->
|
||||
<el-button @click="emit('Back')">返回</el-button>
|
||||
</div>
|
||||
<div class="tablebox">
|
||||
<el-table :data="tabledata" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column align="center" label="房屋/车位">
|
||||
<el-table-column align="center" label="收费名称">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.chargeTypeName === '停车费'">{{ scope.row.parkingName }}</div>
|
||||
<div v-else-if="scope.row.chargeTypeName === '电费' || scope.row.chargeTypeName === '水费'">{{ scope.row.houseName }}</div>
|
||||
<!-- <div v-if="scope.row.chargeTypeName === '车位费'">{{ scope.row.parkingName }}</div>
|
||||
<div v-else-if="scope.row.chargeTypeName === chargeTypeName.Electricity || scope.row.chargeTypeName === chargeTypeName.Water">
|
||||
{{ scope.row.houseName }}
|
||||
</div>
|
||||
<div v-else>--</div> -->
|
||||
<div>{{ scope.row.detailsName }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="收费项目" width="250">
|
||||
@@ -29,7 +32,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="收费周期" width="300">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.startDate }} -- {{ scope.row.endDate }}</div>
|
||||
<dict-tag :options="com_bill_charge_period" :value="scope.row.chargePeriod"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="单价" width="150">
|
||||
@@ -37,11 +40,6 @@
|
||||
<div>{{ scope.row.fixedPrice }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column align="center" label="数量">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.formula }}</div>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column align="center" label="缴费状态" width="120">
|
||||
<template #default="scope">
|
||||
<dict-tag v-if="!inglelist.includes(scope.row.chargeItemName)" :options="com_pay_status" :value="scope.row.payStatus"></dict-tag>
|
||||
@@ -50,8 +48,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="应缴金额" width="120">
|
||||
<template #default="scope">
|
||||
<div v-if="!inglelist.includes(scope.row.chargeItemName)">{{ scope.row.money ?? '--' }}</div>
|
||||
<div v-else>--</div>
|
||||
<div>{{ scope.row.amount ?? '--' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -65,9 +62,13 @@
|
||||
<div>
|
||||
<span>缴费人:{{ villageinfo.villageName ?? '---' }}-{{ props.query.houseName }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>账单名称: </span>
|
||||
<span style="text-wrap: wrap; text-indent: 2rem">{{ from.billResidentId.map((item) => item.chargeItemName).join('、 ') }}</span>
|
||||
<div class="flex">
|
||||
<span>收费名称: </span>
|
||||
<div>
|
||||
<div v-for="(item, index) in from.billResidentId" :key="index" style="text-wrap: wrap; margin-bottom: 5px">
|
||||
<span style="text-decoration: underline">{{ item.detailsName }} ;</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>应收合计:¥{{ from.allCost }}</span>
|
||||
@@ -78,7 +79,7 @@
|
||||
</div>
|
||||
<el-form ref="formRef" :model="from" label-width="100px">
|
||||
<el-form-item label="费用合计" prop="allCost">
|
||||
<el-input v-model="from.allCost">
|
||||
<el-input v-model="from.allCost" disabled>
|
||||
<template #suffix>
|
||||
<span>元</span>
|
||||
</template>
|
||||
@@ -108,16 +109,20 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { billlistType, billQuery } from '@/api/system/SdbCashier';
|
||||
import { billlistType, billQuery, billEdit } from '@/api/system/SdbCashier';
|
||||
import { moneyAdd } from '@/utils/money';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_pay_method, com_pay_status } = toRefs<any>(proxy?.useDict('com_pay_method', 'com_pay_status'));
|
||||
|
||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
||||
const villageinfo = JSON.parse(localStorage.getItem('villageInfo') || '{}');
|
||||
|
||||
// 隐藏收费金额的 类型列表
|
||||
const inglelist = ['电费', '水费'];
|
||||
|
||||
enum chargeTypeName {
|
||||
'Water' = '水费',
|
||||
'Electricity' = '电费'
|
||||
}
|
||||
type querytype = {
|
||||
residentId: string;
|
||||
residentName: string;
|
||||
@@ -190,6 +195,7 @@ const openDiage = () => {
|
||||
ElMessage.warning('请至少选择一条账单进行收款');
|
||||
return;
|
||||
}
|
||||
|
||||
from.value = {
|
||||
allCost: 0,
|
||||
payStatus: '0',
|
||||
@@ -197,10 +203,9 @@ const openDiage = () => {
|
||||
payType: '0',
|
||||
remark: ''
|
||||
};
|
||||
console.log(ids.value);
|
||||
ids.value.forEach((item) => {
|
||||
from.value.billResidentId.push(item);
|
||||
from.value.allCost += Number(item.money);
|
||||
from.value.allCost = moneyAdd(from.value.allCost, item.amount);
|
||||
});
|
||||
dialog.visible = true;
|
||||
};
|
||||
@@ -210,19 +215,23 @@ const closepay = () => {
|
||||
};
|
||||
const submitForm = () => {
|
||||
buttonLoading.value = true;
|
||||
if (from.value.payStatus === '0') {
|
||||
setTimeout(() => {
|
||||
buttonLoading.value = false;
|
||||
closepay();
|
||||
}, 1000);
|
||||
} else {
|
||||
}
|
||||
const obj = {
|
||||
'detailsId': from.value.billResidentId.map((item) => item.detailsId),
|
||||
'payType': from.value.payType,
|
||||
'payStatus': from.value.payStatus
|
||||
};
|
||||
billEdit(obj).then(() => {
|
||||
ElMessage.success('缴费成功');
|
||||
buttonLoading.value = false;
|
||||
getList();
|
||||
closepay();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.cashierbox {
|
||||
font-size: 0.8rem;
|
||||
font-size: 16px;
|
||||
.el-button {
|
||||
width: 100px;
|
||||
height: 35px;
|
||||
|
||||
@@ -2,17 +2,14 @@
|
||||
<el-card style="margin-top: 20px; height: 100%">
|
||||
<div class="p-2 flex flex-col cashierbox h-full">
|
||||
<div class="tablebox">
|
||||
<el-table :data="tabledata">
|
||||
<div style="margin-bottom: 20px">
|
||||
<el-button @click="printPiaoju" type="primary">打印票据</el-button>
|
||||
</div>
|
||||
<el-table :data="tabledata" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column align="center" label="序号" width="80">
|
||||
<el-table-column align="center" label="收费名称">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.$index }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="房屋/车位/车辆">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.houseName">{{ scope.row.parkingName }}</div>
|
||||
<div v-else-if="scope.row.parkingName">{{ scope.row.parkingName }}</div>
|
||||
<div>{{ scope.row.detailsName }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="收费项目">
|
||||
@@ -22,17 +19,16 @@
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="收费周期">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.startDate }} -- {{ scope.row.endDate }}</div>
|
||||
<dict-tag :options="com_bill_charge_period" :value="scope.row.chargePeriod"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="单价">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.fixedPrice }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="数量">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.formula }}</div>
|
||||
<div class="flex flex-items-center justify-center">
|
||||
<div>{{ scope.row.fixedPrice ?? '--' }}</div>
|
||||
<span v-show="Boolean(scope.row.unit)">/</span>
|
||||
<dict-tag v-show="Boolean(scope.row.unit)" :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="缴费状态">
|
||||
@@ -40,69 +36,92 @@
|
||||
<dict-tag :options="com_pay_status" :value="scope.row.payStatus"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="应缴金额">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.money }}</div>
|
||||
<div>{{ scope.row.amount }}</div>
|
||||
</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" />
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog :title="dialog_print.title" v-model="dialog_print.visible" width="1200px" append-to-body>
|
||||
<template #header>
|
||||
<div class="flex" style="justify-content: space-between; padding: 0 20px">
|
||||
<div class="title">票据打印</div>
|
||||
<el-button type="primary" :loading="isLoading" @click="confimPrint">打印</el-button>
|
||||
<!-- <el-button type="primary" v-print="printOption">打印</el-button> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 添加或修改电 设备对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<div class="payinfo">
|
||||
<div>
|
||||
<span>缴费人:北境碧桂园小区-A栋1单元102-张姗</span>
|
||||
<div class="printBox" id="printBox-Bill">
|
||||
<div class="title">{{ print_form.title }}</div>
|
||||
<div class="nav gridbox">
|
||||
<div>单据日期:{{ print_form.printDate }}</div>
|
||||
<div>房号:{{ print_form.HouseName }}</div>
|
||||
<div>产权人:{{ print_form.residentName }}</div>
|
||||
<div>No.</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>账单名称:2025年车位费、2025年上半年物业费 </span>
|
||||
</div>
|
||||
<div>
|
||||
<span>应收合计:¥1600.00 </span>
|
||||
</div>
|
||||
<div>
|
||||
<span>应缴合计:¥1600.00 </span>
|
||||
<div class="tablebox">
|
||||
<table border class="printTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>收费项目</th>
|
||||
<th>收费标准</th>
|
||||
<th>账单时间</th>
|
||||
<th>面积</th>
|
||||
<th style="width: 80px">应收金额</th>
|
||||
<th style="width: 80px">实收金额</th>
|
||||
<th>收款方式</th>
|
||||
<th style="width: 80px">备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in print_form.detailsList" :key="index">
|
||||
<td>{{ item.chargeItemName }}</td>
|
||||
<td>{{ item.billName }}</td>
|
||||
<td>{{ item.detailsTime }}</td>
|
||||
<td>{{ item.useCount }}</td>
|
||||
<td style="width: 80px">{{ item.account }}</td>
|
||||
<td style="width: 80px">{{ item.account }}</td>
|
||||
<td>{{ item.payType }}</td>
|
||||
<td style="width: 80px">{{ item.remark }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>合计</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td style="width: 80px">{{ print_form.totalAccount }}</td>
|
||||
<td style="width: 80px">{{ print_form.totalAccount }}</td>
|
||||
<td style="width: 80px"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="font-size: 10px">说明:本收据收款单位和收款具签章方为有效,本收据手写无效</p>
|
||||
<div class="flex flex-items-center" style="font-size: 12px">
|
||||
<div class="flex-1">交款人:</div>
|
||||
<div class="flex-1 flex flex-items-center">
|
||||
<span style="white-space: nowrap">收款人: </span>
|
||||
<el-input v-model="inHomenyUse" v-if="!isPrint" placeholder="请输入收款人姓名" style="width: 150px"></el-input>
|
||||
<span style="white-space: nowrap" v-else> {{ inHomelyUse }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-form ref="formRef" :model="from" label-width="100px">
|
||||
<el-form-item label="费用合计" prop="allCost">
|
||||
<el-input v-model="from.allCost">
|
||||
<template #suffix>
|
||||
<span>元</span>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="缴纳状态" prop="startTime">
|
||||
<el-radio-group v-model="from.deviceType">
|
||||
<el-radio v-for="dict in com_pay_status" :key="dict.value" :label="dict.label"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付方式" prop="endTime">
|
||||
<el-select v-model="from.deviceType" placeholder="请选择">
|
||||
<el-option v-for="dict in com_pay_method" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" :rows="5" v-model="from.remark"></el-input>
|
||||
</el-form-item>
|
||||
<div class="flex justify-end">
|
||||
<el-button @click="closepay">取消</el-button>
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">提交</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { billlistType, billQuery } from '@/api/system/SdbCashier';
|
||||
import { billlistType, billPrint, BillPrintType, billQuery } from '@/api/system/SdbCashier';
|
||||
import { printTicketDiv } from '@/utils/print';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_pay_method, com_pay_status } = toRefs<any>(proxy?.useDict('com_pay_method', 'com_pay_status'));
|
||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
||||
const { com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_unit'));
|
||||
|
||||
type querytype = {
|
||||
residentId: string;
|
||||
@@ -123,7 +142,7 @@ const props = defineProps({
|
||||
}
|
||||
}
|
||||
});
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
const ids = ref<Array<billlistType>>([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(100);
|
||||
@@ -131,21 +150,22 @@ const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
const tabledata = ref([]);
|
||||
const tabledata = ref<billlistType[]>([]);
|
||||
// 支付状态 0未缴纳 1已缴纳 2缴纳失败
|
||||
const getList = () => {
|
||||
billQuery({
|
||||
residentId: props.query.residentId,
|
||||
'payStatus': '1'
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
tabledata.value = res.rows;
|
||||
total.value = res.total;
|
||||
});
|
||||
};
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: billlistType[]) => {
|
||||
ids.value = selection.map((item) => item.residentId);
|
||||
ids.value = [];
|
||||
ids.value = selection;
|
||||
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
@@ -156,43 +176,89 @@ onMounted(() => {
|
||||
|
||||
const emit = defineEmits(['Back']);
|
||||
|
||||
const formRef = ref();
|
||||
const dialog = reactive<DialogOption>({
|
||||
// 打印票据
|
||||
const isPrint = ref(false);
|
||||
const dialog_print = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: '收款'
|
||||
title: '票据打印'
|
||||
});
|
||||
const buttonLoading = ref(false);
|
||||
|
||||
const from = ref({
|
||||
allCost: null,
|
||||
sex: null,
|
||||
deviceType: null,
|
||||
remark: ''
|
||||
const inHomelyUse = ref('');
|
||||
const print_form = ref<BillPrintType>({
|
||||
'totalAccount': '',
|
||||
'residentName': '',
|
||||
'detailsList': [],
|
||||
'printDate': '',
|
||||
'HouseName': '',
|
||||
'title': ''
|
||||
});
|
||||
|
||||
const openDiage = () => {
|
||||
from.value = {
|
||||
allCost: null,
|
||||
sex: null,
|
||||
deviceType: null,
|
||||
remark: ''
|
||||
function printPiaoju() {
|
||||
if (ids.value.length <= 0) {
|
||||
ElMessage.warning('请至少选择一条账单进行打印票据');
|
||||
return;
|
||||
}
|
||||
isPrint.value = false;
|
||||
inHomenyUse.value = '';
|
||||
const query = {
|
||||
'residentId': props.query.residentId,
|
||||
'detailsIds': [...ids.value.map((item) => item.detailsId)]
|
||||
};
|
||||
dialog.visible = true;
|
||||
};
|
||||
const closepay = () => {
|
||||
dialog.visible = false;
|
||||
dialog.title = '';
|
||||
};
|
||||
const submitForm = () => {
|
||||
buttonLoading.value = true;
|
||||
billPrint(query).then((res) => {
|
||||
print_form.value = res.data;
|
||||
dialog_print.visible = true;
|
||||
});
|
||||
}
|
||||
const isLoading = ref(false);
|
||||
function confimPrint() {
|
||||
isLoading.value = true;
|
||||
isPrint.value = true;
|
||||
setTimeout(() => {
|
||||
buttonLoading.value = false;
|
||||
closepay();
|
||||
printTicketDiv('printBox-Bill', '票据打印', () => {
|
||||
isPrint.value = false;
|
||||
isLoading.value = false;
|
||||
});
|
||||
}, 1000);
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.printBox {
|
||||
color: rgba(0, 0, 0, 1);
|
||||
padding-top: 5px;
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 10px;
|
||||
text-indent: 5em;
|
||||
}
|
||||
.nav {
|
||||
font-size: 12px;
|
||||
&.gridbox {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
&.flexbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.tablebox {
|
||||
font-size: 10px;
|
||||
.printTable {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #000;
|
||||
th,
|
||||
td {
|
||||
text-align: center;
|
||||
min-width: 140px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cashierbox {
|
||||
font-size: 0.8rem;
|
||||
.el-button {
|
||||
|
||||
@@ -1,316 +1,617 @@
|
||||
<template>
|
||||
<div class="p-2 h-full flex flex-col">
|
||||
<Pageheader title="收银台管理"></Pageheader>
|
||||
<div class="" v-if="isSearch">
|
||||
<p class="actionsmain">
|
||||
功能说明:可根据住户姓名、房屋号、手机号,快速搜索对应的未缴费用,修改未缴费用的优惠及滞纳金金额,完成对未缴费用的收取。
|
||||
</p>
|
||||
<div class="contanier flex-center">
|
||||
<div class="h-full flex-1 flex flex-items-start">
|
||||
<div class="typebox">
|
||||
<el-select v-model="searchType" @change="handleChangeSearchType">
|
||||
<el-option v-for="(item, index) in com_cashier_type" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
<PageHeader></PageHeader>
|
||||
<div class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
||||
<div>
|
||||
<el-form-item label="小区" prop="villageId">
|
||||
<el-select @change="handleChangeVillage" v-model="queryParams.villageId" placeholder="请选择小区">
|
||||
<el-option v-for="(item, index) in villageList" :key="index" :value="item.villageId" :label="item.villageName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="楼栋" prop="buildingId">
|
||||
<el-select @change="handleChangeBuilding" v-model="queryParams.buildingId" placeholder="请选择楼栋">
|
||||
<el-option v-for="(item, index) in buildingList" :key="index" :value="item.id" :label="item.buildingName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="单元" prop="unitNoId">
|
||||
<el-select @change="handleChangeUnit" v-model="queryParams.unitNoId" placeholder="请选择单元">
|
||||
<el-option v-for="(item, index) in unitList" :key="index" :value="item.unitNoId" :label="item.unitNoName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item @change="handleChangeHouseNo" label="房号" prop="houseId">
|
||||
<el-select v-model="queryParams.houseId" placeholder="请选择收费项目">
|
||||
<el-option-group v-for="group in houseList" :key="group.floorNo" :label="String(group.floorNo) + ' 楼'">
|
||||
<el-option v-for="item in group.houses" :key="item.houseId" :label="item.houseNo" :value="item.houseId" />
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="searchBox">
|
||||
<el-input clearable v-model="searchValue" @keyup.enter="getlist">
|
||||
<template #suffix>
|
||||
<el-icon @click="getlist" class="cursor-pointer">
|
||||
<Search></Search>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<div class="listbox" v-if="onceSearch || Searching">
|
||||
<div class="list_item">
|
||||
<div class="title">
|
||||
<DictTag :options="com_cashier_type" :value="LazysearchType"></DictTag>
|
||||
</div>
|
||||
<div class="list_body" v-loading="Searching" v-if="list.length > 0 || Searching">
|
||||
<div class="list_value" @click="searchclick(item)" v-for="(item, index) in list" :key="index">
|
||||
{{ item.houseName }}-{{ item.residentName }}-{{ item.phone }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex h-full items-center justify-center">
|
||||
<span class="noData">暂无数据</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-form-item label="收费项目" prop="itemId">
|
||||
<el-select v-model="queryParams.chargeItemId" placeholder="请选择收费项目">
|
||||
<el-option v-for="(item, index) in chargeItems" :key="index" :value="item.id" :label="item.itemName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="缴费周期" prop="period">
|
||||
<el-select v-model="queryParams.period" placeholder="请选择收费项目">
|
||||
<el-option v-for="(item, index) in com_bill_charge_period" :key="index" :value="item.value" :label="item.label"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="业主姓名" prop="residentName">
|
||||
<el-input v-model.trim="queryParams.residentName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div style="text-align: right">
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
<div class="actionsBox">
|
||||
<div class="tabs-box">
|
||||
<div
|
||||
class="tabs-items"
|
||||
v-for="(item, index) in tabs"
|
||||
:key="index"
|
||||
:class="{
|
||||
active: activeTabs === item.value
|
||||
}"
|
||||
@click="changeTabs(item.value)"
|
||||
>
|
||||
{{ item.type }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<el-button @click="handleIncome(false)">收费</el-button>
|
||||
<el-button @click="printPIaoJuByOnly(false)">打印票据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-card class="flex-1" shadow="never">
|
||||
<el-table v-loading="loading" border :data="tableData" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="收费项目" align="center" prop="billCode">
|
||||
<template #default="scope">
|
||||
{{ scope.row.chargeItemName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收费名称" align="center" prop="detailsName">
|
||||
<template #default="scope">
|
||||
<div style="text-align: left">
|
||||
<span>{{ scope.row.detailsName }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收费周期" width="80" align="center" prop="chargePeriod">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_bill_charge_period" :value="scope.row.chargePeriod"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" width="100" align="center" prop="fixedPrice">
|
||||
<template #default="scope">
|
||||
<div class="flex justify-center">
|
||||
<span>
|
||||
{{ scope.row.fixedPrice }}
|
||||
</span>
|
||||
<span> / </span>
|
||||
<dict-tag :options="com_charge_item_unit" :value="scope.row.chargePeriod"></dict-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="应收金额" width="100" align="center" prop="amount" />
|
||||
<el-table-column label="缴费状态" width="80" align="center" prop="payStatus">
|
||||
<template #default="scope">
|
||||
<DictTag :options="com_pay_status" :value="scope.row.payStatus"></DictTag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="应缴金额" width="100" align="center" prop="amount" />
|
||||
<el-table-column label="实缴金额" width="100" align="center" prop="amount" />
|
||||
<el-table-column label="缴费人" align="center" prop="residentName" />
|
||||
<el-table-column label="缴费时间" align="center" prop="" />
|
||||
<el-table-column label="操作" width="220" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" v-if="scope.row.payStatus === '0'" @click="handleIncome(scope.row)" v-hasPermi="['bill:bill:edit']"
|
||||
>收费</el-button
|
||||
>
|
||||
<el-button link type="primary" v-if="scope.row.payStatus === '1'" @click="printPIaoJuByOnly(scope.row)" v-hasPermi="['bill:bill:query']"
|
||||
>打印票据</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>
|
||||
<div class="payInfo">
|
||||
<div>
|
||||
<div>缴费人: {{ inComeFrom.residentName }}</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span>收费名称: </span>
|
||||
<div>
|
||||
<div v-for="(item, index) in inComeFrom.billResidentId" :key="index" style="text-wrap: wrap; margin-bottom: 5px">
|
||||
<span style="text-decoration: underline">{{ item.detailsName }} ;</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>应收合计:¥{{ inComeFrom.allCost }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>应缴合计:¥{{ inComeFrom.allCost }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-form ref="formRef" :model="inComeFrom" label-width="100px">
|
||||
<el-form-item label="费用合计" prop="allCost">
|
||||
<el-input v-model="inComeFrom.allCost" disabled>
|
||||
<template #suffix>
|
||||
<span>元</span>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="缴纳状态" prop="payStatus">
|
||||
<el-radio-group v-model="inComeFrom.payStatus">
|
||||
<el-radio v-for="dict in com_pay_status" :key="dict.value" :label="dict.label" :value="dict.value"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付方式" prop="payType">
|
||||
<el-select v-model="inComeFrom.payType" placeholder="请选择">
|
||||
<el-option v-for="dict in com_pay_method" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" :rows="5" v-model="inComeFrom.remark"></el-input>
|
||||
</el-form-item>
|
||||
<div class="flex justify-end">
|
||||
<el-button @click="closer">取消</el-button>
|
||||
<el-button @click="submitForm" :loading="buttonLoading" type="primary">提交</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<el-dialog :title="dialog_print.title" v-model="dialog_print.visible" width="1200px" append-to-body>
|
||||
<template #header>
|
||||
<div class="flex" style="justify-content: space-between; padding: 0 20px">
|
||||
<div class="title">票据打印</div>
|
||||
<el-button type="primary" :loading="isLoading" @click="conFimPrint">打印</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="printBox" id="printBox-Bill">
|
||||
<div class="title">{{ print_form.title }}</div>
|
||||
<div class="nav gridBox">
|
||||
<div>单据日期:{{ print_form.printDate }}</div>
|
||||
<div>房号:{{ print_form.HouseName }}</div>
|
||||
<div>产权人:{{ print_form.residentName }}</div>
|
||||
<div>No.</div>
|
||||
</div>
|
||||
<div class="tableBox">
|
||||
<table class="printTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>收费项目</th>
|
||||
<th>收费标准</th>
|
||||
<th>账单时间</th>
|
||||
<th>面积</th>
|
||||
<th style="width: 80px">应收金额</th>
|
||||
<th style="width: 80px">实收金额</th>
|
||||
<th>收款方式</th>
|
||||
<th style="width: 80px">备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in print_form.detailsList" :key="index">
|
||||
<td>{{ item.chargeItemName }}</td>
|
||||
<td>{{ item.billName }}</td>
|
||||
<td>{{ item.detailsTime }}</td>
|
||||
<td>{{ item.useCount }}</td>
|
||||
<td style="width: 80px">{{ item.account }}</td>
|
||||
<td style="width: 80px">{{ item.account }}</td>
|
||||
<td>{{ item.payType }}</td>
|
||||
<td style="width: 80px">{{ item.remark }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>合计</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td style="width: 80px">{{ print_form.totalAccount }}</td>
|
||||
<td style="width: 80px">{{ print_form.totalAccount }}</td>
|
||||
<td style="width: 80px"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="font-size: 10px">说明:本收据收款单位和收款具签章方为有效,本收据手写无效</p>
|
||||
<div class="flex flex-items-center" style="font-size: 12px">
|
||||
<div class="flex-1">交款人:</div>
|
||||
<div class="flex-1 flex flex-items-center">
|
||||
<span style="white-space: nowrap">收款人: </span>
|
||||
<el-input v-model="inHomelyUse" v-if="!isPrint" placeholder="请输入收款人姓名" style="width: 150px"></el-input>
|
||||
<span style="white-space: nowrap" v-else> {{ inHomelyUse }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else style="margin-top: 20px; height: calc(100% - 210px)">
|
||||
<div class="tabsbox">
|
||||
<div
|
||||
@click="handleChecout(item.value)"
|
||||
v-for="(item, index) in tabs"
|
||||
:key="index"
|
||||
class="tabs_item"
|
||||
:class="{ active: checkouttabs === item.value }"
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-full">
|
||||
<cashier :query="checkeditem" @Back="handleBack" v-if="checkouttabs === 'cashier'"></cashier>
|
||||
<history :query="checkeditem" v-if="checkouttabs === 'history'"></history>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// TODO 预存
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { Component, ref } from 'vue';
|
||||
|
||||
import cashier from './cashier.vue';
|
||||
import history from './history.vue';
|
||||
import { cashQuery } from '@/api/system/SdbCashier';
|
||||
|
||||
/** 当前状态 搜索后 搜索前 */
|
||||
const isSearch = ref(true);
|
||||
/** 为了loading 搜索结果 添加防抖 */
|
||||
const Searching = ref(false);
|
||||
const onceSearch = ref(false);
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import pagination from '@/components/Pagination/index.vue';
|
||||
import DictTag from '@/components/DictTag/index.vue';
|
||||
import { getBuildinglists, getHouselistAPI } from '@/api/system/house';
|
||||
import { getCommunitylistAPI } from '@/api/system/community';
|
||||
import { billEdit, billlistType, billPrint, BillPrintType, billQuery } from '@/api/system/SdbCashier';
|
||||
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||||
import { ref } from 'vue';
|
||||
import { printTicketDiv } from '@/utils/print';
|
||||
import { moneyAdd } from '@/utils/money';
|
||||
import { BuildingUnitlist, BuildingVo, FloorsType, HouseType } from '@/api/system/house/type';
|
||||
import { ChargeItemVO } from '@/api/system/SdbChargeItem/type';
|
||||
import { communitylist_rows_type } from '@/api/system/community/type';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_cashier_type } = toRefs<any>(proxy?.useDict('com_cashier_type'));
|
||||
console.log(com_cashier_type);
|
||||
/** 房屋 住户 车辆 车位 */
|
||||
const com_cashier_type_list = ref(['houseName', 'residentName']);
|
||||
const searchform = ref();
|
||||
const searchValue = ref('');
|
||||
const searchType = ref('houseName');
|
||||
const LazysearchType = ref('');
|
||||
function handleChangeSearchType() {
|
||||
list.value = [];
|
||||
searchValue.value = '';
|
||||
}
|
||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
||||
const { com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_unit'));
|
||||
const { com_pay_status, com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_status', 'com_pay_method'));
|
||||
|
||||
const list = ref<querytype[]>([]);
|
||||
// ! ===================================================================================
|
||||
// 先定义 Tab 项类型
|
||||
type TabValue = 'cashier' | 'history';
|
||||
interface TabItem {
|
||||
name: string;
|
||||
value: TabValue;
|
||||
component: Component;
|
||||
}
|
||||
const checkouttabs = ref<TabValue>('cashier');
|
||||
const tabs: TabItem[] = [
|
||||
const loading = ref(false);
|
||||
const ids = ref<Array<billlistType>>([]);
|
||||
const total = ref(0);
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const activeTabs = ref(null);
|
||||
const tabs = [
|
||||
{
|
||||
name: '收银台',
|
||||
value: 'cashier',
|
||||
component: cashier
|
||||
value: null,
|
||||
type: '全部'
|
||||
},
|
||||
{
|
||||
name: '历史缴费',
|
||||
value: 'history',
|
||||
component: history
|
||||
value: 0,
|
||||
type: '待缴纳'
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
type: '已缴纳'
|
||||
}
|
||||
];
|
||||
type querytype = {
|
||||
residentId: string;
|
||||
residentName: string;
|
||||
houseName: string;
|
||||
phone: string;
|
||||
};
|
||||
const checkeditem = ref<querytype>({
|
||||
'residentId': '',
|
||||
'residentName': '',
|
||||
'houseName': '',
|
||||
'phone': ''
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
payStatus: null,
|
||||
villageId: undefined,
|
||||
buildingId: undefined,
|
||||
unitNoId: undefined,
|
||||
houseId: undefined,
|
||||
residentName: undefined,
|
||||
chargeItemId: undefined,
|
||||
period: undefined
|
||||
});
|
||||
const searchclick = (row: querytype) => {
|
||||
checkeditem.value = row;
|
||||
isSearch.value = false;
|
||||
handleChecout('cashier');
|
||||
};
|
||||
function handleChecout(index: TabValue) {
|
||||
checkouttabs.value = index;
|
||||
const villageList = ref<communitylist_rows_type[]>([]);
|
||||
const buildingList = ref<BuildingVo[]>([]);
|
||||
const unitList = ref<BuildingUnitlist[]>([]);
|
||||
const houseList = ref<FloorsType[]>([]);
|
||||
const chargeItems = ref<ChargeItemVO[]>([]);
|
||||
|
||||
const tableData = ref([]);
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
// 切换 账单类型
|
||||
function changeTabs(value: number) {
|
||||
activeTabs.value = value;
|
||||
queryParams.value.payStatus = value;
|
||||
getList();
|
||||
}
|
||||
// 选择小区
|
||||
function handleChangeVillage(val: string) {
|
||||
queryParams.value.unitNoId = undefined;
|
||||
queryParams.value.buildingId = undefined;
|
||||
buildingList.value = [];
|
||||
unitList.value = [];
|
||||
if (val) {
|
||||
getBuildinglists({
|
||||
villageId: val
|
||||
}).then((res) => {
|
||||
buildingList.value = res.rows;
|
||||
handleChargeItem(val);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ! ===================================================================================
|
||||
// 用于追踪最新请求的标识
|
||||
let latestRequestId = 0;
|
||||
function getlist() {
|
||||
// 生成当前请求的唯一ID
|
||||
const currentRequestId = ++latestRequestId;
|
||||
const currenttime = Date.now();
|
||||
// 获取收费项目
|
||||
function handleChargeItem(id: string) {
|
||||
listChargeItem({
|
||||
villageId: id
|
||||
}).then((res) => {
|
||||
chargeItems.value = res.rows;
|
||||
});
|
||||
}
|
||||
|
||||
Searching.value = true;
|
||||
searchform.value = {};
|
||||
searchform.value[searchType.value] = searchValue.value;
|
||||
// 选择楼栋
|
||||
function handleChangeBuilding(val: string): void {
|
||||
queryParams.value.unitNoId = undefined;
|
||||
unitList.value = [];
|
||||
getHouselistAPI(val).then((res) => {
|
||||
unitList.value = res.data.units;
|
||||
});
|
||||
}
|
||||
// 选择 单元
|
||||
function handleChangeUnit(val: string) {
|
||||
const find = unitList.value.find((item) => item.unitNoId === val);
|
||||
houseList.value = [];
|
||||
if (find) {
|
||||
houseList.value = find.floors;
|
||||
}
|
||||
}
|
||||
// 选择房屋
|
||||
function handleChangeHouseNo() {}
|
||||
|
||||
let lastdata = [];
|
||||
cashQuery(searchform.value)
|
||||
// 获取列表
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
billQuery(queryParams.value)
|
||||
.then((res) => {
|
||||
// 检查是否是最新的请求,防止竞态条件
|
||||
if (currentRequestId === latestRequestId) {
|
||||
lastdata = res.data;
|
||||
}
|
||||
tableData.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
if (currentRequestId === latestRequestId) {
|
||||
LazysearchType.value = searchType.value;
|
||||
onceSearch.value = true;
|
||||
// 计算已过去的时间
|
||||
const elapsedTime = Date.now() - currenttime;
|
||||
const minLoadingTime = 300;
|
||||
if (elapsedTime < minLoadingTime) {
|
||||
setTimeout(() => {
|
||||
// 再次检查,防止在等待期间发起了新请求
|
||||
if (currentRequestId === latestRequestId) {
|
||||
list.value = lastdata;
|
||||
Searching.value = false;
|
||||
}
|
||||
}, minLoadingTime - elapsedTime);
|
||||
} else {
|
||||
list.value = lastdata;
|
||||
Searching.value = false;
|
||||
}
|
||||
}
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
// ! ===================================================================================
|
||||
const handleBack = () => {
|
||||
isSearch.value = true;
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
// ! ===================================================================================
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
queryParams.value = {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
payStatus: null,
|
||||
villageId: undefined,
|
||||
buildingId: undefined,
|
||||
unitNoId: undefined,
|
||||
houseId: undefined,
|
||||
chargeItemId: undefined,
|
||||
period: undefined,
|
||||
residentName: undefined
|
||||
};
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: billlistType[]) => {
|
||||
ids.value = selection.map((item) => item);
|
||||
};
|
||||
const buttonLoading = ref(false);
|
||||
// 收费表单
|
||||
const inComeFrom = ref({
|
||||
allCost: null, // 金额
|
||||
billResidentId: [], // 账单id
|
||||
payStatus: '0', // 0:未缴 1:已缴
|
||||
payType: '0', // 0:微信 1:支付宝 2 线下
|
||||
remark: '',
|
||||
residentName: '' // 缴费人
|
||||
});
|
||||
// 收费 --------------------------------------------------------------
|
||||
/** 收费 */
|
||||
function handleIncome(row: billlistType | false) {
|
||||
console.log(ids.value);
|
||||
inComeFrom.value.allCost = 0;
|
||||
inComeFrom.value.billResidentId = [];
|
||||
inComeFrom.value.residentName = '';
|
||||
if (row) {
|
||||
inComeFrom.value.allCost = row.amount;
|
||||
inComeFrom.value.billResidentId = [row];
|
||||
inComeFrom.value.residentName = row.residentName;
|
||||
} else {
|
||||
const set = new Set();
|
||||
ids.value.forEach((item) => {
|
||||
set.add(item.residentId);
|
||||
});
|
||||
if (set.size > 1) {
|
||||
ElMessage.warning('缴费人不一致,重新选择');
|
||||
return;
|
||||
} else if (set.size === 1) {
|
||||
inComeFrom.value.residentName = ids.value[0].residentName;
|
||||
ids.value.forEach((item) => {
|
||||
inComeFrom.value.billResidentId.push(item);
|
||||
inComeFrom.value.allCost = moneyAdd(inComeFrom.value.allCost, item.amount);
|
||||
});
|
||||
console.log(inComeFrom.value);
|
||||
}
|
||||
}
|
||||
dialog.visible = true;
|
||||
}
|
||||
const closer = () => {
|
||||
dialog.visible = false;
|
||||
dialog.title = '';
|
||||
};
|
||||
const submitForm = () => {
|
||||
buttonLoading.value = true;
|
||||
const obj = {
|
||||
'detailsId': inComeFrom.value.billResidentId.map((item) => item.detailsId),
|
||||
'payType': inComeFrom.value.payType,
|
||||
'payStatus': inComeFrom.value.payStatus
|
||||
};
|
||||
billEdit(obj)
|
||||
.then(() => {
|
||||
ElMessage.success('缴费成功');
|
||||
getList();
|
||||
closer();
|
||||
})
|
||||
.finally(() => {
|
||||
buttonLoading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
// 打印票据--------------------------------------------------------------
|
||||
const isPrint = ref(false);
|
||||
const dialog_print = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: '票据打印'
|
||||
});
|
||||
// 收款人
|
||||
const inHomelyUse = ref('');
|
||||
const print_form = ref<BillPrintType>({
|
||||
'totalAccount': '',
|
||||
'residentName': '',
|
||||
'detailsList': [],
|
||||
'printDate': '',
|
||||
'HouseName': '',
|
||||
'title': ''
|
||||
});
|
||||
|
||||
function printPIaoJuByOnly(row: billlistType | false) {
|
||||
isPrint.value = false;
|
||||
inHomelyUse.value = '';
|
||||
let query = null;
|
||||
if (row) {
|
||||
query = {
|
||||
'residentId': row.residentId,
|
||||
'detailsIds': [row.detailsId]
|
||||
};
|
||||
} else {
|
||||
let residentId = null;
|
||||
const set = new Set();
|
||||
ids.value.forEach((item) => {
|
||||
set.add(item.residentId);
|
||||
});
|
||||
if (set.size > 1) {
|
||||
ElMessage.warning('缴费人不一致,重新选择');
|
||||
return;
|
||||
} else if (set.size === 1) {
|
||||
residentId = Array.from(set).at(0);
|
||||
query = {
|
||||
'residentId': residentId,
|
||||
'detailsIds': ids.value.map((item) => item.detailsId)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
billPrint(query).then((res) => {
|
||||
print_form.value = res.data;
|
||||
dialog_print.visible = true;
|
||||
});
|
||||
}
|
||||
const isLoading = ref(false);
|
||||
function conFimPrint() {
|
||||
isLoading.value = true;
|
||||
isPrint.value = true;
|
||||
setTimeout(() => {
|
||||
printTicketDiv('printBox-Bill', '票据打印', () => {
|
||||
isPrint.value = false;
|
||||
isLoading.value = false;
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
// 全部小区
|
||||
getCommunitylistAPI().then((res) => {
|
||||
villageList.value = res.rows;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.noData {
|
||||
color: #999999;
|
||||
<style lang="scss" scoped>
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
.tabsbox {
|
||||
height: 60px;
|
||||
.actionsBox {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
height: 50px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.tabs-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
.tabs_item {
|
||||
|
||||
.tabs-items {
|
||||
width: 70px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
margin-right: 40px;
|
||||
font-size: 0.8rem;
|
||||
border-bottom: 2px solid transparent;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
margin-right: 10px;
|
||||
|
||||
&:hover {
|
||||
color: #40a0ff98;
|
||||
border-bottom-color: #40a0ff98;
|
||||
opacity: 0.5;
|
||||
color: #1a75ff;
|
||||
border-bottom-color: #1a75ff;
|
||||
}
|
||||
&.active {
|
||||
color: #409eff;
|
||||
border-bottom-color: #409eff;
|
||||
border-bottom: 1px solid;
|
||||
border-bottom-color: #1a75ff;
|
||||
color: #1a75ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actionsmain {
|
||||
font-size: 0.9rem;
|
||||
color: #000;
|
||||
padding-left: 30px;
|
||||
.payInfo {
|
||||
color: rgba(0, 0, 0, 1);
|
||||
margin-top: 20px;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 30px;
|
||||
border-bottom: 1px solid #d2d2d2;
|
||||
& > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.contanier {
|
||||
width: 900px;
|
||||
min-height: 200px;
|
||||
margin: 100px auto;
|
||||
.typebox {
|
||||
width: 140px;
|
||||
height: 40px;
|
||||
:deep(.el-select__wrapper) {
|
||||
width: 140px;
|
||||
height: 50px;
|
||||
line-height: 20px;
|
||||
border-radius: 5px 0px 0px 5px;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
color: rgba(16, 16, 16, 1);
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
.printBox {
|
||||
color: rgba(0, 0, 0, 1);
|
||||
padding-top: 5px;
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 10px;
|
||||
text-indent: 5em;
|
||||
}
|
||||
.nav {
|
||||
font-size: 12px;
|
||||
&.gridBox {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
&.flexbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.searchBox {
|
||||
flex: 1;
|
||||
background-color: #fff;
|
||||
&:deep(.el-input__wrapper) {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
border-radius: 0px 5px 5px 0px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.listbox {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
min-height: 200px;
|
||||
margin-top: -2px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0px 0px 5px 5px;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
color: rgba(16, 16, 16, 1);
|
||||
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.list_item {
|
||||
padding-bottom: 30px;
|
||||
height: 400px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
flex-direction: column;
|
||||
.title {
|
||||
color: rgba(48, 49, 51, 1);
|
||||
font-size: 1rem;
|
||||
font-weight: 450;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-bottom: 1px solid rgba(204, 204, 204, 1);
|
||||
}
|
||||
.list_body {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
.list_value {
|
||||
min-height: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-bottom: 1px solid rgba(204, 204, 204, 1);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #cccccc33;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tableBox {
|
||||
font-size: 10px;
|
||||
.printTable {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #000;
|
||||
th,
|
||||
td {
|
||||
text-align: center;
|
||||
min-width: 140px;
|
||||
height: 40px;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
.cashierbox {
|
||||
font-size: 0.8rem;
|
||||
.el-button {
|
||||
width: 100px;
|
||||
height: 35px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.actionsbox {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.tablebox {
|
||||
margin-top: 20px;
|
||||
height: 100%;
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
</style>
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
<el-dropdown-item @click="handleMarkqrcode" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
||||
<span>批量生成条形码</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="handleMarkQrcodeZip" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
||||
<span>批量下载条形码</span>
|
||||
</el-dropdown-item>
|
||||
<!-- </el-dropdown-menu> -->
|
||||
<!-- <el-dropdown-item v-hasPermi="['equipment:addqrcode:electricitydevice']">
|
||||
<div @click="handleMarkqrcode">批量更新固件</div>
|
||||
@@ -74,15 +77,15 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="分合状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<div class="readRecord" v-if="scope.row.waterRecord">
|
||||
<DictTag :options="com_electricity_readrecord_status" :value="scope.row.waterRecord.status"></DictTag>
|
||||
<div class="readRecord" v-if="scope.row.electricityRecord">
|
||||
<DictTag :options="com_electricity_readrecord_status" :value="scope.row.electricityRecord.status"></DictTag>
|
||||
</div>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="房屋号" align="center" prop="houseName" />
|
||||
<el-table-column label="余额" width="100" align="center" prop="elePrice">
|
||||
<template #defaul="scope">
|
||||
<el-table-column label="余额" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.electricityRecord">{{ scope.row.electricityRecord.balance }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
@@ -106,7 +109,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="抄表时间" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.waterRecord ? scope.row.waterRecord.readTime : '--' }}</span>
|
||||
<span>{{ scope.row.electricityRecord ? scope.row.electricityRecord.readTime : '--' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column width="150" label="启停" align="center" prop="deleted" v-hasPermi="['equipment:isUse:electricitydevice']">
|
||||
@@ -265,8 +268,8 @@ import { useUserStore } from '@/store/modules/user';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
import { Upload } from '@element-plus/icons-vue';
|
||||
import { CascaderValue, tourEmits, UploadProps, UploadRawFile } from 'element-plus';
|
||||
import { exportImagesToZip } from '@/utils/exportZip';
|
||||
|
||||
const huhao = 3096371295;
|
||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/electricityDevice/upload';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
@@ -408,7 +411,7 @@ const EditHouseform = ref({
|
||||
/** 批量生成 条形码 */
|
||||
function handleMarkqrcode() {
|
||||
if (ids.value.length > 0) {
|
||||
ElectricityDeviceMakerQrcode(ids.value).then((res) => {
|
||||
ElectricityDeviceMakerQrcode(ids.value).then(() => {
|
||||
ElMessage.success('批量生成成功');
|
||||
getList();
|
||||
});
|
||||
@@ -416,6 +419,28 @@ function handleMarkqrcode() {
|
||||
ElMessage.warning('请选择设备');
|
||||
}
|
||||
}
|
||||
/** 批量下载条形码 */
|
||||
function handleMarkQrcodeZip() {
|
||||
if (ids.value.length > 0) {
|
||||
const selectedIds = new Set(ids.value.map((item) => item.id));
|
||||
const matchedList = ElectricityDeviceList.value.filter((item) => {
|
||||
return selectedIds.has(item.id) && item.url;
|
||||
});
|
||||
produceQRzip(matchedList);
|
||||
} else {
|
||||
ElMessage.warning('请选择设备');
|
||||
}
|
||||
}
|
||||
function produceQRzip(vals: ElectricityDeviceVO[]) {
|
||||
const arr = vals.map((item) => {
|
||||
return {
|
||||
name: item.deviceCode,
|
||||
url: item.url
|
||||
};
|
||||
});
|
||||
exportImagesToZip(arr, 'ele_images');
|
||||
}
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: ElectricityDeviceVO[]) => {
|
||||
ids.value = selection.map((item) => {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<pageheader></pageheader>
|
||||
<el-card class="flex-1 mt-10px" shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" style="font-size: 0.8rem; font-weight: 450">
|
||||
<el-row 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="12"></el-col>
|
||||
<el-col :span="8"> 房屋号: {{ housename }} </el-col>
|
||||
<el-col :span="8"></el-col>
|
||||
<el-col :span="4" class="flex">
|
||||
<el-button @click="confinem">返回</el-button>
|
||||
<el-button type="warning" @click="handleExport">导出数据</el-button>
|
||||
|
||||
142
src/views/system/Sdb/statistics/electricity.vue
Normal file
142
src/views/system/Sdb/statistics/electricity.vue
Normal file
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div class="flex flex-col h-full p-2">
|
||||
<pageheader></pageheader>
|
||||
<el-card class="flex-1 mt-10px" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<el-form class="demo-form-inline" :inline="true">
|
||||
<el-form-item label="查询日期">
|
||||
<el-date-picker
|
||||
clearable
|
||||
v-model="SearchTime"
|
||||
@change="
|
||||
(val) => {
|
||||
if (!val) {
|
||||
queryParams.startDate = '';
|
||||
queryParams.endDate = '';
|
||||
return;
|
||||
}
|
||||
SearchTime = val;
|
||||
const days = val;
|
||||
const [star, end] = days.map((item) => item.split(' ')[0]);
|
||||
queryParams.startDate = star + ' 00:00:00';
|
||||
queryParams.endDate = end + ' 23:59:59';
|
||||
}
|
||||
"
|
||||
type="daterange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
format="YYYY-MM-DD"
|
||||
range-separator="到"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="" v-hasPermi="['electricity:topupRecord:list']">
|
||||
<el-button type="primary" @click="getList">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button @click="handleExport" v-hasPermi="['electricity:topupRecord:export']" type="warning">导出统计</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-table v-loading="loading" border :data="topupRecordList">
|
||||
<el-table-column label="充值时间" align="center" prop="rechargeTime">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.rechargeTime">{{ scope.row.rechargeTime }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="小区名称" align="center" prop="villageName">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.villageName">{{ scope.row.villageName }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="户主" align="center" prop="residentName">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.residentName">{{ scope.row.residentName }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="房号" align="center" prop="houseName">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.houseName">{{ scope.row.houseName }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" align="center" prop="fixedPrice">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.fixedPrice && scope.row.unit">
|
||||
<span>{{ scope.row.fixedPrice }}</span>
|
||||
<span>/</span>
|
||||
<span>{{ scope.row.unit }}</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>---</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="设备编号" align="center" prop="deviceCode" />
|
||||
<el-table-column label="订单号" align="center" prop="orderId" />
|
||||
<el-table-column label="充值金额" align="center" prop="rechargeAmount" />
|
||||
<el-table-column label="缴费方式" align="center" prop="topUpType" />
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getElectricityTopupRecordByDate, type TopupRecordList } from '@/api/system/SdbTopupRecord/index';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const topupRecordList = ref<TopupRecordList[]>([]);
|
||||
const loading = ref(false);
|
||||
const total = ref(0);
|
||||
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
startDate: '',
|
||||
endDate: ''
|
||||
}
|
||||
});
|
||||
const SearchTime = ref([]);
|
||||
|
||||
const { queryParams } = toRefs(data);
|
||||
/** 查询充值记录列表 */
|
||||
const getList = async () => {
|
||||
if (!checkPermi(['electricity:topupRecord:list'])) return;
|
||||
loading.value = true;
|
||||
const res = await getElectricityTopupRecordByDate(queryParams.value);
|
||||
topupRecordList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
proxy?.download(
|
||||
'/topupRecord/electricity/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`花开物业电费统计表.xlsx`
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
143
src/views/system/Sdb/statistics/index.vue
Normal file
143
src/views/system/Sdb/statistics/index.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<div class="flex flex-col h-full p-2">
|
||||
<pageheader></pageheader>
|
||||
<el-card class="flex-1 mt-10px" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<el-form class="demo-form-inline" :inline="true">
|
||||
<el-form-item label="查询日期">
|
||||
<el-date-picker
|
||||
clearable
|
||||
v-model="SearchTime"
|
||||
@change="
|
||||
(val) => {
|
||||
if (!val) {
|
||||
queryParams.startDate = '';
|
||||
queryParams.endDate = '';
|
||||
return;
|
||||
}
|
||||
SearchTime = val;
|
||||
const days = val;
|
||||
const [star, end] = days.map((item) => item.split(' ')[0]);
|
||||
queryParams.startDate = star + ' 00:00:00';
|
||||
queryParams.endDate = end + ' 23:59:59';
|
||||
}
|
||||
"
|
||||
type="daterange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
format="YYYY-MM-DD"
|
||||
range-separator="到"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="" v-hasPermi="['water:topupRecord:list']">
|
||||
<el-button type="primary" @click="getList">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button @click="handleExport" v-hasPermi="['water:topupRecord:export']" type="warning">导出统计</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-table v-loading="loading" border :data="topupRecordList">
|
||||
<el-table-column label="充值时间" align="center" prop="rechargeTime">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.rechargeTime">{{ scope.row.rechargeTime }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="小区名称" align="center" prop="villageName">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.villageName">{{ scope.row.villageName }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="户主" align="center" prop="residentName">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.residentName">{{ scope.row.residentName }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="房号" align="center" prop="houseName">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.houseName">{{ scope.row.houseName }}</span>
|
||||
<span v-else>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" align="center" prop="fixedPrice">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.fixedPrice && scope.row.unit">
|
||||
<span>{{ scope.row.fixedPrice }}</span>
|
||||
<span>/</span>
|
||||
<span>{{ scope.row.unit }}</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>---</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="设备编号" align="center" prop="deviceCode" />
|
||||
<el-table-column label="订单号" align="center" prop="orderId" />
|
||||
<el-table-column label="充值金额" align="center" prop="rechargeAmount" />
|
||||
<el-table-column label="缴费方式" align="center" prop="topUpType" />
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getTopupRecordByDate, type TopupRecordList } from '@/api/system/SdbTopupRecord/index';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const topupRecordList = ref<TopupRecordList[]>([]);
|
||||
const loading = ref(false);
|
||||
const total = ref(0);
|
||||
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
startDate: '',
|
||||
endDate: ''
|
||||
}
|
||||
});
|
||||
const SearchTime = ref([]);
|
||||
|
||||
const { queryParams } = toRefs(data);
|
||||
/** 查询充值记录列表 */
|
||||
const getList = async () => {
|
||||
if (!checkPermi(['water:topupRecord:list'])) return;
|
||||
loading.value = true;
|
||||
const res = await getTopupRecordByDate(queryParams.value);
|
||||
topupRecordList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
// exportTopupRecordByDate();
|
||||
proxy?.download(
|
||||
'/topupRecord/water/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`花开物业水费统计表.xlsx`
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -10,10 +10,10 @@
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="14">
|
||||
<div class="grid grid-cols-3 grid-rows-3">
|
||||
<div class="carinfo_body grid grid-cols-3 grid-rows-3">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">访问房屋:</div>
|
||||
<div class="main">{{ form.houseName }}</div>
|
||||
<div class="main housename" :title="form.houseName">{{ form.houseName }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">访客姓名:</div>
|
||||
@@ -31,7 +31,9 @@
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">访问日期:</div>
|
||||
<div class="main">{{ form.startTime }} - {{ form.endTime }}</div>
|
||||
<div class="main" style="text-wrap: wrap">
|
||||
<span>{{ form.startTime }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">访问时长:</div>
|
||||
@@ -50,13 +52,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="5"></el-col>
|
||||
<el-col :span="4">
|
||||
<el-col :span="4"></el-col>
|
||||
<el-col :span="5">
|
||||
<div class="flex">
|
||||
<div>通行证:</div>
|
||||
<div class="labelpass">通行证:</div>
|
||||
<div class="content-imageBox">
|
||||
<i class="bordertopline"></i>
|
||||
<el-image :src="form.url"></el-image>
|
||||
<el-image style="height: 100%; width: 100%" :src="form.url"></el-image>
|
||||
<i class="borderline"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -87,7 +89,6 @@ import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { getVisitor } from '@/api/system/Visitor';
|
||||
import { formatTimeDiff } from '@/utils/time';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
|
||||
|
||||
@@ -156,15 +157,28 @@ function back() {
|
||||
margin: 20px 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.carinfo_body {
|
||||
gap: 20px;
|
||||
}
|
||||
.carinfo_item {
|
||||
margin-bottom: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.label {
|
||||
width: 150px;
|
||||
text-align: right;
|
||||
width: 100px;
|
||||
font-weight: bolder;
|
||||
margin-right: 30px;
|
||||
text-align: left;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
.main {
|
||||
font-size: small;
|
||||
cursor: default;
|
||||
&.housename {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,12 +203,15 @@ function back() {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
.labelpass {
|
||||
width: 70px;
|
||||
}
|
||||
.content-imageBox {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
padding: 3px;
|
||||
margin-left: 20px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
@@ -53,9 +53,13 @@
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="区域名称" align="center" prop="areaName" />
|
||||
<el-table-column label="区域编号" align="center" prop="areaCode" />
|
||||
<el-table-column label="面积" align="center" prop="area" />
|
||||
<el-table-column label="车位数量" align="center" prop="parkingCount" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="面积" align="center" prop="area" width="90">
|
||||
<template #default="scope">
|
||||
{{ scope.row.area + ' m²' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="车位数量" align="center" prop="parkingCount" width="90" />
|
||||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['area:area:edit']">修改</el-button>
|
||||
@@ -122,10 +126,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询车位区域管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listArea(queryParams.value);
|
||||
areaList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listArea(queryParams.value)
|
||||
.then((res) => {
|
||||
areaList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -156,7 +164,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: AreaVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row ? row.id : ids.value[0];
|
||||
router.push({
|
||||
path: '/carArea/editCarArea',
|
||||
query: {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="title">基本信息</div>
|
||||
<div class="addBuildingFormBody">
|
||||
<el-form class="formBody" label-position="left" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
||||
<el-row>
|
||||
<!-- <el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="车辆区域" prop="areaId">
|
||||
<el-select @change="changeArealist" v-model="form.areaId" placeholder="请选择车辆区域">
|
||||
@@ -15,13 +15,13 @@
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="车位号" prop="parkingId">
|
||||
<el-select v-model="form.parkingId" placeholder="请选择车位号">
|
||||
<el-form-item label="车位编号" prop="parkingId">
|
||||
<el-select v-model="form.parkingId" placeholder="请选择车位编号">
|
||||
<el-option v-for="item in parkinglist" :key="item.id" :label="item.parkingCode" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-row> -->
|
||||
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
@@ -79,11 +79,23 @@
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="持有人">
|
||||
<!-- 公共组件 持有人 -->
|
||||
<Holder :userid="form.residentId ?? ''" @change="handleChange"></Holder>
|
||||
<AppUser :isMultiple="false" ref="HolderRef" @change="handleChange">
|
||||
<template #default>
|
||||
<div class="residentBox" @click="choiceResidentFun">
|
||||
<div class="defaultbox" v-if="form.residentId === ''">
|
||||
<span>请选择</span>
|
||||
<el-icon><Search /></el-icon>
|
||||
</div>
|
||||
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
|
||||
<span>姓名:{{ form?.residentName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AppUser>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
@@ -111,7 +123,7 @@ import { listParking } from '@/api/system/parking';
|
||||
import { UploadFiles, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus';
|
||||
import { addCar, getCar, updateCar, uploadCar } from '@/api/system/cars';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { LicensePlateValidator, validator } from '@/utils/Reg';
|
||||
import AppUser from '@/components/Holder/appUser.vue';
|
||||
|
||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/car/uploadImage';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
@@ -124,6 +136,7 @@ const form = ref({
|
||||
id: null,
|
||||
areaId: null, // 区域id
|
||||
residentId: '', // 车位id
|
||||
residentName: '', // 持有人姓名
|
||||
parkingId: null, // 持有人id
|
||||
carNum: '', //车牌号
|
||||
carBrand: '', //车辆品牌
|
||||
@@ -141,20 +154,6 @@ const rules = ref({
|
||||
required: true,
|
||||
message: '请输入车牌号码',
|
||||
trigger: ['blur']
|
||||
},
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (!value) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
if (!LicensePlateValidator.isValidPlate(value)) {
|
||||
callback(new Error('请输入正确的车牌号格式'));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
},
|
||||
trigger: 'blur' // ✅ 只在失焦时验证
|
||||
}
|
||||
],
|
||||
carBrand: [{ required: true, message: '请输入车辆品牌', trigger: 'blur' }]
|
||||
@@ -171,7 +170,9 @@ function headerToken() {
|
||||
const userid = ref('');
|
||||
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
const type = rawFile.type.split('/').pop();
|
||||
if (['png', 'jpg'].includes(type)) {
|
||||
console.log('type', type);
|
||||
console.log('rawFile', rawFile);
|
||||
if (['png', 'jpg', 'jpeg'].includes(type)) {
|
||||
if (rawFile.size / 1024 / 1024 <= 10) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -179,7 +180,7 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ElMessage.warning('图片格式不是 png/jpg 格式, 请重新上传');
|
||||
ElMessage.warning('图片格式不是 png/jpg/jpeg 格式, 请重新上传');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -207,6 +208,7 @@ if (route.query.id) {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
changeArealist(res.data.areaId);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -250,10 +252,26 @@ const submitForm = () => {
|
||||
const cancelForm = () => {
|
||||
router.back();
|
||||
};
|
||||
|
||||
const holderInfo = ref(null);
|
||||
const HolderRef = ref<typeof Holder>(null);
|
||||
function choiceResidentFun() {
|
||||
if (form.value.residentId) {
|
||||
HolderRef.value.open([...form.value.residentId]);
|
||||
} else {
|
||||
HolderRef.value.open([]);
|
||||
}
|
||||
}
|
||||
// 选择住户
|
||||
function handleChange(pop) {
|
||||
form.value.residentId = pop;
|
||||
holderInfo.value = null;
|
||||
holderInfo.value = pop;
|
||||
form.value.residentId = '';
|
||||
form.value.residentName = '';
|
||||
console.log(pop);
|
||||
if (pop !== null) {
|
||||
form.value.residentId = pop.user_id;
|
||||
form.value.residentName = pop.user_name;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
@@ -328,4 +346,22 @@ function handleChange(pop) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.residentBox {
|
||||
width: 385px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
.defaultbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #f4f8ff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -50,14 +50,14 @@
|
||||
|
||||
<el-table v-loading="loading" border :data="carList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="车牌号" align="center" prop="carNum" />
|
||||
<el-table-column label="车辆品牌" align="center" prop="carBrand" />
|
||||
<el-table-column label="车辆型号" align="center" prop="carModel" />
|
||||
<el-table-column label="车身颜色" align="center" prop="carColor" />
|
||||
<el-table-column label="持有人" align="center" prop="residentId">
|
||||
<el-table-column label="车牌号" width="155" align="center" prop="carNum" />
|
||||
<el-table-column label="车辆品牌" width="155" align="center" prop="carBrand" />
|
||||
<el-table-column label="车辆型号" width="155" align="center" prop="carModel" />
|
||||
<el-table-column label="车身颜色" width="125" align="center" prop="carColor" />
|
||||
<el-table-column label="持有人" width="155" align="center" prop="residentId">
|
||||
<template #default="scope"> {{ getResidentName(scope.row.residentId) }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['car:car:edit']">修改</el-button>
|
||||
@@ -143,11 +143,17 @@ const getResidentName = (id: string) => {
|
||||
/** 查询车辆管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listCar(queryParams.value);
|
||||
|
||||
listCar(queryParams.value)
|
||||
.then((res) => {
|
||||
carList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
const res1 = await listResident();
|
||||
ResidentList.value = res1.rows;
|
||||
carList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<template #header>
|
||||
<div class="dict-card__header">
|
||||
<div class="dict-card__title">字典管理</div>
|
||||
<right-toolbar v-model:show-search="showTypeSearch" @query-table="getTypeList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -106,7 +105,6 @@
|
||||
字典数据
|
||||
<span class="dict-card__subtitle">{{ currentDictLabel }}</span>
|
||||
</div>
|
||||
<right-toolbar v-model:show-search="showDataSearch" @query-table="getDataList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -196,10 +196,11 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: DeviceVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
router.push({
|
||||
path: '/equipment/editArchive',
|
||||
query: {
|
||||
id: row.id
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -233,7 +234,7 @@ const submitForm = () => {
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: DeviceVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
await proxy?.$modal.confirm('是否确认删除设备编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||
await proxy?.$modal.confirm('是否确认删除该设备?').finally(() => (loading.value = false));
|
||||
await delDevice(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="title flex flex-items-center justify-between">
|
||||
<div>
|
||||
<span>基本信息</span>
|
||||
<el-button class="ml-10px" link type="primary"> 编辑</el-button>
|
||||
<el-button class="ml-10px" link type="primary" @click="editDevice"> 编辑</el-button>
|
||||
</div>
|
||||
<el-button @click="cancelForm"> 返回</el-button>
|
||||
</div>
|
||||
@@ -146,18 +146,30 @@ init();
|
||||
|
||||
async function getlist() {
|
||||
loading.value = true;
|
||||
const rows = await listDeviceRepair();
|
||||
deviceRepairList.value = rows.rows;
|
||||
deviceRepairList.value.forEach((item) => {
|
||||
item.maintainUserNames = item.maintainUserList
|
||||
.map((i) => i.nickName)
|
||||
.filter((i) => i)
|
||||
.join(',');
|
||||
});
|
||||
total.value = rows.total;
|
||||
loading.value = false;
|
||||
listDeviceRepair()
|
||||
.then((rows) => {
|
||||
deviceRepairList.value = rows.rows;
|
||||
deviceRepairList.value.forEach((item) => {
|
||||
item.maintainUserNames = item.maintainUserList
|
||||
.map((i) => i.nickName)
|
||||
.filter((i) => i)
|
||||
.join(',');
|
||||
});
|
||||
total.value = rows.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function editDevice() {
|
||||
router.push({
|
||||
path: '/equipment/editArchive',
|
||||
query: {
|
||||
id: form.value.id
|
||||
}
|
||||
});
|
||||
}
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: DeviceRepairVO) => {
|
||||
const _ids = row?.id;
|
||||
@@ -222,6 +234,7 @@ const cancelForm = () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.label {
|
||||
font-size: 15px;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -20,24 +20,11 @@
|
||||
<el-card class="flex-1" shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:deviceCategory:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:deviceCategory:edit']"
|
||||
>修改</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:deviceCategory:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col> -->
|
||||
<right-toolbar
|
||||
:disable-delete="multiple"
|
||||
:disable-edit="single"
|
||||
:show-add="checkPermi(['system:deviceCategory:add'])"
|
||||
:show-edit="checkPermi(['system:deviceCategory:edit'])"
|
||||
:show-edit="false"
|
||||
:show-delete="checkPermi(['system:deviceCategory:remove'])"
|
||||
@update:add="handleAdd"
|
||||
@update:edit="handleUpdate()"
|
||||
@@ -56,7 +43,6 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="添加时间" align="center" prop="createTime" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['system:deviceCategory:edit']">编辑</el-button>
|
||||
@@ -78,9 +64,9 @@
|
||||
<el-radio v-for="(item, index) in com_equipment_device_category" :key="index" :value="Number(item.value)" :label="item.label"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<!-- <el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
@@ -140,10 +126,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询设备分类列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listDeviceCategory(queryParams.value);
|
||||
deviceCategoryList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listDeviceCategory(queryParams.value)
|
||||
.then((res) => {
|
||||
deviceCategoryList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
|
||||
@@ -7,7 +7,13 @@
|
||||
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
||||
<el-form-item label="维修设备" prop="deviceId">
|
||||
<el-select v-model="form.deviceId">
|
||||
<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"
|
||||
:disabled="item.status === 1"
|
||||
:value="item.id"
|
||||
:label="item.categoryName"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备名称" prop="deviceName">
|
||||
@@ -101,7 +107,8 @@ const form = ref({
|
||||
});
|
||||
const rules = ref({
|
||||
deviceId: [{ required: true, message: '请选择 设备类型', trigger: 'blur' }],
|
||||
deviceName: [{ required: true, message: '请输入 设备名称', trigger: 'blur' }]
|
||||
deviceName: [{ required: true, message: '请输入 设备名称', trigger: 'blur' }],
|
||||
faultDesc: [{ required: true, message: '请输入 故障描述', trigger: 'blur' }]
|
||||
});
|
||||
const userid = ref(null);
|
||||
|
||||
@@ -210,6 +217,7 @@ const cancelForm = () => {
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
min-width: 100px;
|
||||
&.add {
|
||||
cursor: pointer;
|
||||
border-style: dashed;
|
||||
|
||||
@@ -147,18 +147,22 @@ const { queryParams, form } = toRefs(data);
|
||||
// TODO 设备维修记录 用户id有,用户信息没有
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listDeviceRepair(queryParams.value);
|
||||
deviceRepairList.value = res.rows;
|
||||
deviceRepairList.value.forEach((item) => {
|
||||
if (item.maintainUserList && item.maintainUserList.length > 0) {
|
||||
item.maintainUserNames = item.maintainUserList
|
||||
.map((i) => i.nickName)
|
||||
.filter((i) => i)
|
||||
.join(',');
|
||||
}
|
||||
});
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listDeviceRepair(queryParams.value)
|
||||
.then((res) => {
|
||||
deviceRepairList.value = res.rows;
|
||||
deviceRepairList.value.forEach((item) => {
|
||||
if (item.maintainUserList && item.maintainUserList.length > 0) {
|
||||
item.maintainUserNames = item.maintainUserList
|
||||
.map((i) => i.nickName)
|
||||
.filter((i) => i)
|
||||
.join(',');
|
||||
}
|
||||
});
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -202,10 +206,12 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: DeviceRepairVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
|
||||
router.push({
|
||||
path: '/equipment/editEquipmentRepair',
|
||||
query: {
|
||||
id: row.id
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="flex flex-items-center">
|
||||
<h5>设备信息</h5>
|
||||
<div style="font-size: 0.9rem; margin-left: 20px" class="mr-5px">{{ form.id }}</div>
|
||||
<el-button class="ml-10px" link type="primary"> 编辑</el-button>
|
||||
<el-button class="ml-10px" link type="primary" @click="editDeviceRecode"> 编辑</el-button>
|
||||
</div>
|
||||
<el-button @click="cancelForm"> 返回</el-button>
|
||||
</div>
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<div class="info_item">
|
||||
<div class="label">维修时间:</div>
|
||||
<span class="value">{{ form.createTime }}</span>
|
||||
<span class="value">{{ form.repairTime }}</span>
|
||||
</div>
|
||||
<div></div>
|
||||
<div class="info_item">
|
||||
@@ -86,6 +86,7 @@ const form = ref({
|
||||
repairResult: '', // 设备维护人员
|
||||
faultDesc: '', // 设备维护人员
|
||||
createTime: '', // 设备维护人员
|
||||
repairTime: '', // 设备维护人员
|
||||
remark: '' // 备注
|
||||
});
|
||||
|
||||
@@ -108,6 +109,7 @@ function init() {
|
||||
maintainUserIds: res.data.maintainUserIds,
|
||||
remark: res.data.remark,
|
||||
createTime: res.data.createTime,
|
||||
repairTime: res.data.repairTime,
|
||||
maintainUserListName: ''
|
||||
};
|
||||
if (res.data.maintainUserList && res.data.maintainUserList.length > 0) {
|
||||
@@ -121,6 +123,15 @@ function init() {
|
||||
}
|
||||
init();
|
||||
|
||||
function editDeviceRecode() {
|
||||
router.push({
|
||||
path: '/equipment/editEquipmentRepair',
|
||||
query: {
|
||||
id: form.value.id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 推出
|
||||
const cancelForm = () => {
|
||||
router.back();
|
||||
@@ -157,7 +168,7 @@ const cancelForm = () => {
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
font-size: 0.98rem;
|
||||
font-size: 0.8rem;
|
||||
.info_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -20,53 +20,53 @@
|
||||
<el-option v-for="item in units" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="楼层" prop="floor">
|
||||
<el-form-item label="楼层" prop="floorNo">
|
||||
<el-select v-model.number="form.floorNo" placeholder="请选择">
|
||||
<el-option v-for="item in floors" :key="item.no" :label="item.name" :value="item.no" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="房间号" prop="houseNo">
|
||||
<el-input v-model="form.houseNo" placeholder="请输入房间号" />
|
||||
<el-input v-model.trim="form.houseNo" placeholder="请输入房间号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="建筑面积" prop="houseArea">
|
||||
<div class="unitBox flex align-center">
|
||||
<el-input v-model="form.houseArea" placeholder="请输入建筑面积" />
|
||||
<el-input v-model.trim="form.houseArea" placeholder="请输入建筑面积" />
|
||||
<span>㎡</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="套内面积" prop="internalArea">
|
||||
<div class="unitBox flex align-center">
|
||||
<el-input v-model="form.internalArea" placeholder="请输入套内面积" />
|
||||
<el-input v-model.trim="form.internalArea" placeholder="请输入套内面积" />
|
||||
<span>㎡</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="公摊面积" prop="shareArea">
|
||||
<div class="unitBox flex align-center">
|
||||
<el-input v-model="form.shareArea" placeholder="请输入公摊面积" />
|
||||
<el-input v-model.trim="form.shareArea" placeholder="请输入公摊面积" />
|
||||
<span>㎡</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="房屋户型">
|
||||
<div class="houseTypebox">
|
||||
<el-input v-model="housetype[0]" placeholder="房间" />
|
||||
<el-input v-model.trim="housetype[0]" placeholder="房间" />
|
||||
<span>室</span>
|
||||
<el-input v-model="housetype[1]" placeholder="客厅" />
|
||||
<el-input v-model.trim="housetype[1]" placeholder="客厅" />
|
||||
<span>厅</span>
|
||||
<el-input v-model="housetype[2]" placeholder="卫生间" />
|
||||
<el-input v-model.trim="housetype[2]" placeholder="卫生间" />
|
||||
<span>卫</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="车位号" prop="parkingId">
|
||||
<el-select v-model="form.parkingId" class="m-2" placeholder="请选择车位号">
|
||||
<el-option v-for="item in parkinglist" :key="item.id" :label="item.parkingName" :value="item.id" />
|
||||
<el-form-item label="车位号" prop="parkingIds">
|
||||
<el-select @change="(val) => console.log(val)" multiple v-model="form.parkingIds" class="m-2" placeholder="请选择车位号">
|
||||
<el-option v-for="(item, index) in parkinglist" :key="index" :label="item.parkingName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="储藏室" prop="storeroomId">
|
||||
<el-select v-model="form.storeroomId" class="m-2" placeholder="请选择储藏室">
|
||||
<el-option v-for="item in storeRoomlist" :key="item.id" :label="item.storeroomName" :value="item.id" />
|
||||
<el-option v-for="(item, index) in storeRoomlist" :key="index" :label="item.storeroomName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-top: 30px">
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
<el-button @click="cancelForm">取消</el-button>
|
||||
@@ -81,16 +81,13 @@
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { useHouseStore } from '@/store/modules/house';
|
||||
import { addHouseAPI, EditHouseApi, getBuildingOnly, getHouseApi, getHouselistAPI } from '@/api/system/house';
|
||||
import { addHouseAPI, EditHouseApi, getHouseApi } from '@/api/system/house';
|
||||
import { addHouseType } from '@/api/system/house/type';
|
||||
import { GetVillageListParking, listParking } from '@/api/system/parking';
|
||||
import { GetVillagelistStoreroom, listStoreroom } from '@/api/system/storeroom';
|
||||
import { listHouseUseType } from '@/api/system/houseUse';
|
||||
import { GetVillageListParking } from '@/api/system/parking';
|
||||
import { GetVillagelistStoreroom } from '@/api/system/storeroom';
|
||||
import { listHouseUseType_add_house } from '@/api/system/houseUse';
|
||||
import { getByBUildingidtoUnitNo } from '@/api/system/houseUnit';
|
||||
|
||||
// const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
// const { com_build_use } = toRefs<any>(proxy?.useDict('com_build_use'));
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const houseStore = useHouseStore();
|
||||
@@ -106,14 +103,16 @@ const form = ref<addHouseType>({
|
||||
shareArea: '', // 公摊面积
|
||||
houseType: '', // 房屋户型
|
||||
storeroomId: '', // 储藏室
|
||||
parkingId: '' // 车位
|
||||
parkingIds: [] // 车位
|
||||
});
|
||||
const rules = ref({
|
||||
buildingId: [{ required: true, message: '请输入楼栋', trigger: 'blur' }],
|
||||
unitNoId: [{ required: true, message: '请选择单元', trigger: 'blur' }],
|
||||
floorNo: [{ required: true, message: '请选择楼层', trigger: 'blur' }],
|
||||
houseUseTypeId: [{ required: true, message: '请选择房屋用途', trigger: 'blur' }],
|
||||
houseArea: [{ required: true, message: '请输入建筑面积', trigger: 'blur' }],
|
||||
buildingName: [{ required: true, message: '请输入房间号', trigger: 'blur' }],
|
||||
houseNo: [{ required: true, message: '请输入房间号', trigger: 'blur' }],
|
||||
buildingArea: [{ required: true, message: '请输入建筑面积', trigger: 'blur' }],
|
||||
internalFloorArea: [{ required: true, message: '请输入套内面积', trigger: 'blur' }],
|
||||
CommonArea: [{ required: true, message: '请输入公摊面积', trigger: 'blur' }]
|
||||
@@ -137,29 +136,31 @@ const queryChangestore = ref({
|
||||
});
|
||||
const villageid = localStorage.getItem('villageid');
|
||||
async function init() {
|
||||
if (route.query.id) {
|
||||
houseid.value = route.query.id;
|
||||
}
|
||||
nextTick(() => geteditinfo());
|
||||
}
|
||||
init();
|
||||
|
||||
const houseUseTypeList = ref([]);
|
||||
async function geteditinfo() {
|
||||
listHouseUseType({
|
||||
pageNum: 1,
|
||||
pageSize: 99999
|
||||
}).then((res) => {
|
||||
houseUseTypeList.value = res.rows;
|
||||
listHouseUseType_add_house().then((res) => {
|
||||
houseUseTypeList.value = res.data;
|
||||
});
|
||||
// 车位列表 = 当前房屋绑定车位 + 无人绑定车位
|
||||
GetVillageListParking(villageid, houseid.value).then((res) => {
|
||||
parkinglist.value = res.data;
|
||||
});
|
||||
GetVillagelistStoreroom({
|
||||
...queryChangestore.value,
|
||||
villageid: villageid,
|
||||
houseId: houseid.value
|
||||
}).then((res) => {
|
||||
storeRoomlist.value = res.data.filter((item) => item);
|
||||
});
|
||||
|
||||
if (route.query.id) {
|
||||
houseid.value = route.query.id;
|
||||
// const res = await GetVillageListParking(villageid, houseid.value);
|
||||
// parkinglist.value = res.data;
|
||||
// GetVillagelistStoreroom({
|
||||
// ...queryChangestore.value,
|
||||
// villageid: villageid,
|
||||
// houseId: houseid.value
|
||||
// }).then((res1) => {
|
||||
// storeRoomlist.value = res1.data;
|
||||
// });
|
||||
getHouseApi(houseid.value).then((res) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
@@ -171,23 +172,14 @@ async function geteditinfo() {
|
||||
houseArea: res.data.houseArea, //建筑面积
|
||||
internalArea: res.data.internalArea, //套内面积
|
||||
storeroomId: res.data.storeroomId, //储藏室
|
||||
parkingId: res.data.parkingId, //车位
|
||||
parkingIds: res.data.parkingIds ?? [], //车位
|
||||
houseUseTypeId: res.data.houseUseTypeId,
|
||||
shareArea: res.data.shareArea // 公摊面积
|
||||
};
|
||||
housetype.value = res.data.houseType.split('');
|
||||
// handlechangeBuild(form.value.buildingId);
|
||||
console.log(housetype.value);
|
||||
housetype.value = res.data.houseType ? res.data.houseType.split('') : [];
|
||||
queryChangestore.value.buildingId = form.value.buildingId;
|
||||
changeBuild(res.data.buildingId);
|
||||
});
|
||||
} else {
|
||||
// const res = await GetVillageListParking(villageid);
|
||||
// parkinglist.value = res.data;
|
||||
// const res1 = await GetVillagelistStoreroom({
|
||||
// ...queryChangestore.value,
|
||||
// villageid: villageid
|
||||
// });
|
||||
// storeRoomlist.value = res1.data;
|
||||
}
|
||||
}
|
||||
// 选择楼栋
|
||||
@@ -195,12 +187,12 @@ function handlechangeBuild(id: string) {
|
||||
queryChangestore.value.buildingId = id;
|
||||
form.value.unitNoId = '';
|
||||
form.value.floorNo = '';
|
||||
|
||||
changeBuild(id);
|
||||
// getStoreRoomlist();
|
||||
getStoreRoomlist();
|
||||
}
|
||||
|
||||
function changeBuild(id: string) {
|
||||
// 根据楼栋id获取单元
|
||||
const arr = houseStore.currentBuildingInfoList;
|
||||
const find = arr.find((item) => item.id === id);
|
||||
if (find) {
|
||||
@@ -211,16 +203,20 @@ function changeBuild(id: string) {
|
||||
};
|
||||
});
|
||||
}
|
||||
// 获取单元
|
||||
getByBUildingidtoUnitNo(id).then((res) => {
|
||||
units.value = [];
|
||||
units.value = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
// change unitNoId
|
||||
function changeUnitNo(id: string) {
|
||||
form.value.unitNoId = '';
|
||||
form.value.unitNoId = id;
|
||||
queryChangestore.value.unitNoId = id;
|
||||
form.value.floorNo = '';
|
||||
// getStoreRoomlist();
|
||||
getStoreRoomlist();
|
||||
}
|
||||
|
||||
// 查询储藏室列表
|
||||
@@ -252,7 +248,7 @@ const submitForm = () => {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
addHouseAPI(data).then((res) => {
|
||||
addHouseAPI(data).then(() => {
|
||||
ElMessage.success('添加成功');
|
||||
houseStore.updateCureentBuilding();
|
||||
router.push({
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">单元:</div>
|
||||
<div class="value">{{ HouseInfo.house?.unitNoName ?? '--' }} 单元</div>
|
||||
<div class="value">{{ HouseInfo.house?.unitNoName ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">楼层:</div>
|
||||
<div class="value">{{ HouseInfo.house?.floorNo ?? '--' }} 层</div>
|
||||
<div class="value">{{ HouseInfo.house?.floorNo ? HouseInfo.house?.floorNo + ' 层' : '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">建筑面积:</div>
|
||||
@@ -54,34 +54,36 @@
|
||||
<span>储藏室信息 </span>
|
||||
<el-button v-hasPermi="['storeroom:storeroom:edit']" type="primary" text v-if="HouseInfo.storeroom" @click="editStoreRoom">编辑</el-button>
|
||||
</div>
|
||||
<div class="addBuildingFormBody" v-if="HouseInfo.storeroom">
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">楼栋:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.buildingName ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">单元:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.unitNo ?? '--' }} 单元</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">储藏室号:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.unitNo ?? '--' }} 楼</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">建筑面积:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.houseArea ?? '--' }}㎡</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">公摊面积:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.shareArea ?? '--' }}㎡</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">实用面积:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.internalArea ?? '--' }}㎡</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">备注:</div>
|
||||
<div class="value"></div>
|
||||
<div class="" v-if="HouseInfo.storeroom">
|
||||
<div class="addBuildingFormBody">
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">楼栋:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.buildingName ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">单元:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.unitNoName ? `${HouseInfo.storeroom?.unitNoName} 单元` : '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">储藏室号:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.storeroomNo ? `${HouseInfo.storeroom?.storeroomNo}` : '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">建筑面积:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.houseArea ? HouseInfo.storeroom?.houseArea + ' ㎡' : '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">公摊面积:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.shareArea ? HouseInfo.storeroom?.shareArea + ' ㎡' : '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">实用面积:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.internalArea ? HouseInfo.storeroom?.internalArea + ' ㎡' : '--' }}㎡</div>
|
||||
</div>
|
||||
<div class="descriptionsbox" style="grid-column-start: 1; grid-column-end: 4">
|
||||
<div class="label">备注:</div>
|
||||
<div class="value">{{ HouseInfo.storeroom?.remark ?? '--' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="w-full h-full flex flex-center min-h-4rem">
|
||||
@@ -92,63 +94,34 @@
|
||||
<div class="AddBuildingBody">
|
||||
<div class="title">
|
||||
<span>车位信息</span>
|
||||
<el-button v-hasPermi="['parking:parking:edit']" type="primary" text @click="handleEditParking" v-if="HouseInfo.parking">编辑</el-button>
|
||||
</div>
|
||||
<div class="addBuildingFormBody" v-if="HouseInfo.parking">
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">区域:</div>
|
||||
<div class="value">{{ HouseInfo.parking?.areaName ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">车位编号:</div>
|
||||
<div class="value">{{ HouseInfo.parking?.parkingCode ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">车位面积:</div>
|
||||
<div class="value">{{ HouseInfo.parking?.parkingArea ?? '--' }} ㎡</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">楼层:</div>
|
||||
<div class="value">{{ HouseInfo.parking?.parkingFloor ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">车位类型:</div>
|
||||
<div class="value">
|
||||
<dict-tag :options="com_parking_type" :value="HouseInfo.parking.type" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">车位状态:</div>
|
||||
<div class="value">
|
||||
<dict-tag :options="com_parking_status" :value="HouseInfo.parking.parkingStatus" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">持有人:</div>
|
||||
<div class="value">
|
||||
<span>{{ HouseInfo.parking?.residentName ?? '--' }}</span>
|
||||
<el-button
|
||||
v-hasPermi="['parking:parking:edit']"
|
||||
type="primary"
|
||||
text
|
||||
@click="handleEditUser(HouseInfo.parking.residentId)"
|
||||
v-if="HouseInfo.parking"
|
||||
>编辑</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">添加时间:</div>
|
||||
<div class="value">{{ HouseInfo.parking?.createTime ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">添加人:</div>
|
||||
<div class="value">{{ HouseInfo.parking?.createName ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">备注:</div>
|
||||
<div class="value">{{ HouseInfo.parking?.remark ?? '--' }}</div>
|
||||
</div>
|
||||
<div class="" v-if="HouseInfo.parkingList.length > 0">
|
||||
<el-table :data="HouseInfo.parkingList">
|
||||
<el-table-column align="center" prop="areaName" label="区域" />
|
||||
<el-table-column align="center" prop="parkingCode" label="车位编号" />
|
||||
<el-table-column align="center" width="100" prop="parkingArea" label="车位面积">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.parkingArea ?? '--' }} /㎡</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" width="50" prop="parkingFloor" label="楼层" />
|
||||
<el-table-column align="center" width="100" prop="type" label="车位类型">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_parking_type" :value="scope.row.type"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" width="100" prop="parkingStatus" label="车位状态">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_parking_status" :value="scope.row.parkingStatus"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="residentName" label="持有人">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleEditUser(scope.row.residentId)">{{ scope.row.residentName }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" show-overflow-tooltip prop="remark" label="备注" />
|
||||
</el-table>
|
||||
</div>
|
||||
<div v-else class="w-full h-full flex flex-center min-h-4rem">
|
||||
<span style="color: #999; font-weight: 500; font-size: 1.1rem; letter-spacing: 10px">暂无信息</span>
|
||||
@@ -161,12 +134,22 @@
|
||||
</div>
|
||||
<div>
|
||||
<el-table :data="HouseInfo.chargeItemList" style="width: 100%">
|
||||
<el-table-column prop="date" label="收费项目" />
|
||||
<el-table-column prop="name" label="收费标准" />
|
||||
<el-table-column prop="name" label="开始时间" />
|
||||
<el-table-column prop="name" label="结束时间" />
|
||||
<el-table-column prop="name" label="备注" />
|
||||
<el-table-column prop="address" label="操作" />
|
||||
<el-table-column prop="itemName" label="收费项目" />
|
||||
<el-table-column prop="name" label="收费标准">
|
||||
<template #default="scope">
|
||||
<div class="flex">
|
||||
<span>{{ scope.row.fixedPrice }}</span> /
|
||||
<dict-tag :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="开始时间" />
|
||||
<el-table-column prop="name" label="结束时间">
|
||||
<template #default>
|
||||
<span>---</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -232,6 +215,7 @@ const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
|
||||
const { com_pay_status } = toRefs<any>(proxy?.useDict('com_pay_status'));
|
||||
const { com_parking_type } = toRefs<any>(proxy?.useDict('com_parking_type'));
|
||||
const { com_parking_status } = toRefs<any>(proxy?.useDict('com_parking_status'));
|
||||
const { com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_unit'));
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -240,7 +224,7 @@ const HouseInfo = ref<Data>({
|
||||
billResidentList: [],
|
||||
chargeItemList: [],
|
||||
house: null,
|
||||
parking: null,
|
||||
parkingList: [],
|
||||
residentList: [],
|
||||
storeroom: null
|
||||
});
|
||||
@@ -316,7 +300,9 @@ init();
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-rows: repeat(3, 1fr);
|
||||
|
||||
&.remarkbuildingformbody {
|
||||
display: block;
|
||||
}
|
||||
.descriptionsbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<span class="pointer" @click="handleAddBuilding" v-hasPermi="['system:building:add']">+增加楼栋</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
<ul class="flex-1 overflow-y-auto overflow-x-hidden">
|
||||
<li
|
||||
v-for="(item, index) in currentBuildingInfoList"
|
||||
:class="{
|
||||
@@ -14,7 +14,7 @@
|
||||
}"
|
||||
:key="index"
|
||||
>
|
||||
<div class="buildingname" @click="switchBuilding(item.id ?? null)">{{ item.buildingName ?? '' }}</div>
|
||||
<div class="buildingname" :title="item.buildingName ?? ''" @click="switchBuilding(item.id ?? null)">{{ item.buildingName ?? '' }}</div>
|
||||
<div class="buildactions flex align-center justify-around">
|
||||
<el-icon class="pointer hover-color-blue" @click="editBuilding(item.id)" v-hasPermi="['system:building:edit']"><Setting /></el-icon>
|
||||
<el-icon class="pointer hover-color-red" @click="deleteBuilding(item.id)" v-hasPermi="['system:building:remove']"><Delete /></el-icon>
|
||||
@@ -67,6 +67,9 @@ $primary_color: #1978fe;
|
||||
border-radius: 2px;
|
||||
color: rgba(0, 0, 0, 1);
|
||||
margin-right: 10px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.buildingheader {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
@@ -78,6 +81,9 @@ $primary_color: #1978fe;
|
||||
}
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
color: rgba(16, 16, 16, 1);
|
||||
@@ -87,15 +93,17 @@ $primary_color: #1978fe;
|
||||
background-color: #1978fe0c;
|
||||
}
|
||||
.buildingname {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
padding: 0 20px 0 0;
|
||||
padding: 0 10px 0 5px;
|
||||
cursor: pointer;
|
||||
flex: 1;
|
||||
max-width: 175px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
text-align: right;
|
||||
}
|
||||
.buildactions {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 75px;
|
||||
font-size: 15px;
|
||||
padding: 15px 0;
|
||||
|
||||
@@ -1,46 +1,88 @@
|
||||
<template>
|
||||
<div class="house-list">
|
||||
<div class="house flex align-center" @contextmenu="contextMenu.open($event, house.houseId)" v-for="house in list.houses" :key="house.houseId">
|
||||
<div class="flex flex-center">
|
||||
<el-checkbox :label="house.houseNo" :value="house.houseId" />
|
||||
<div class="calp" @click="handleCalp($event, house.houseId)">···</div>
|
||||
<div class="house flex align-center" @contextmenu="handleContextMenu($event, house.houseId)" v-for="house in sortedHouses" :key="house.houseId">
|
||||
<div class="w-full flex items-center justify-between">
|
||||
<el-checkbox :title="house.houseNo" :label="house.houseNo" :value="house.houseId" />
|
||||
<div class="circlebox" @click="handleContextMenu($event, house.houseId)">
|
||||
<div class="circle"></div>
|
||||
<div class="circle"></div>
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右键菜单组件 -->
|
||||
<ContextMenu ref="contextMenu" :menu="menuList" @select="handleSelect" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ContextMenu from '@/components/ContextMenu/index.vue';
|
||||
import { ref } from 'vue';
|
||||
import type { FloorsType, HouseType } from '@/api/system/house/type';
|
||||
import type { FloorsType } from '@/api/system/house/type';
|
||||
const props = defineProps<{
|
||||
unit: FloorsType[];
|
||||
fIdx: number | string;
|
||||
menuList: {
|
||||
label: string;
|
||||
value: string;
|
||||
}[];
|
||||
}>();
|
||||
const list = props.unit.find((item) => item.floorNo === props.fIdx) ?? { floorNo: '', houses: [] };
|
||||
// 菜单ref
|
||||
const contextMenu = ref();
|
||||
// 点击事件
|
||||
const handleSelect = (data: { type: string; value: string }) => {
|
||||
emit('contextmenufun', data);
|
||||
|
||||
// 使用 computed 获取当前楼层数据,确保响应式
|
||||
const currentFloor = computed(() => {
|
||||
return props.unit.find((item) => item.floorNo === props.fIdx) ?? { floorNo: '', houses: [] };
|
||||
});
|
||||
|
||||
// 存储排序后的结果
|
||||
const sortedHouses = ref(currentFloor.value.houses);
|
||||
|
||||
// 轻量级比较函数:优先尝试数字比较,失败则使用 localeCompare
|
||||
const compareHouseNo = (a: string, b: string) => {
|
||||
// 如果都是纯数字,直接数字比较最快
|
||||
const numA = Number(a);
|
||||
const numB = Number(b);
|
||||
if (!isNaN(numA) && !isNaN(numB)) {
|
||||
return numA - numB;
|
||||
}
|
||||
// 否则使用自然排序
|
||||
return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
|
||||
};
|
||||
|
||||
// 监听数据源变化,仅当 houses 数组引用或内容变化时重新排序
|
||||
watch(
|
||||
() => currentFloor.value.houses,
|
||||
(newHouses) => {
|
||||
// 创建副本并排序
|
||||
sortedHouses.value = [...newHouses].sort((a, b) => compareHouseNo(a.houseNo, b.houseNo));
|
||||
},
|
||||
{ immediate: true, deep: false } // deep: false 因为我们要替换整个数组引用
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
contextmenufun: [value: { type: string; value: string }];
|
||||
// 新增事件:通知父组件打开菜单
|
||||
openMenu: [data: { event: MouseEvent; houseId: string }];
|
||||
}>();
|
||||
|
||||
const handleCalp = (event: MouseEvent, houseid: string) => {
|
||||
contextMenu.value.open(event, houseid);
|
||||
// 处理右键点击,向上传递事件对象和ID
|
||||
const handleContextMenu = (event: MouseEvent, houseId: string) => {
|
||||
event.preventDefault(); // 阻止默认浏览器菜单
|
||||
emit('openMenu', { event, houseId });
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.circlebox {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
$circleSize: 3px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
.circle {
|
||||
width: $circleSize;
|
||||
height: $circleSize;
|
||||
border-radius: 50%;
|
||||
background-color: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
.house-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -52,13 +94,24 @@ const handleCalp = (event: MouseEvent, houseid: string) => {
|
||||
|
||||
.house {
|
||||
min-width: 100px;
|
||||
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin: 5px;
|
||||
padding-left: 10px;
|
||||
padding: 0 10px;
|
||||
|
||||
&:deep(.el-checkbox) {
|
||||
max-width: 200px;
|
||||
.el-checkbox__label {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.house:hover {
|
||||
background: #e8f3ff;
|
||||
border-color: #409eff;
|
||||
@@ -75,19 +128,4 @@ const handleCalp = (event: MouseEvent, houseid: string) => {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.calp {
|
||||
margin-left: 10px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
letter-spacing: -3px;
|
||||
transform: rotateZ(90deg) scale(0.8);
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<div class="TableBox p-5 h-full" v-if="houseStore.currentHouseInfoList !== null">
|
||||
<div class="tablebox1 h-full flex-1">
|
||||
<div class="TableBox p-5" v-if="houseStore.currentHouseInfoList !== null">
|
||||
<el-checkbox-group @change="handleChangeCheckhouses" v-model="houseStore.checkoutHouses">
|
||||
<el-table border :data="houseStore.currentFloorInfoList">
|
||||
<el-table-column align="center" fixed label="楼层\单元" max-width="100">
|
||||
@@ -15,18 +15,28 @@
|
||||
:key="index"
|
||||
>
|
||||
<template #header>
|
||||
<span>{{ unit.unitNoName }}</span>
|
||||
<el-button link type="primary" icon="Edit" @click="HandleEditUnit(unit)"></el-button>
|
||||
<el-button link type="danger" icon="Delete" style="margin-left: 0" @click="HandleDeleteUnit(unit)"></el-button>
|
||||
<div class="flex align-center justify-center">
|
||||
<div class="houseName" :title="unit.unitNoName">{{ unit.unitNoName }}</div>
|
||||
<el-button v-hasPermi="['unitNo:unitNo:edit']" link type="primary" icon="Edit" @click="HandleEditUnit(unit)"></el-button>
|
||||
<el-button
|
||||
v-hasPermi="['unitNo:unitNo:remove']"
|
||||
link
|
||||
type="danger"
|
||||
icon="Delete"
|
||||
style="margin-left: 0"
|
||||
@click="HandleDeleteUnit(unit)"
|
||||
></el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="{ row }">
|
||||
<houseItem @contextmenufun="contextMenuFun" :menu-list="menutlist" :unit="unit.floors" :f-idx="row"></houseItem>
|
||||
<houseItem @openMenu="handleOpenMenu" :unit="unit.floors" :f-idx="row"></houseItem>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div v-else class="nodata">暂无房屋</div>
|
||||
<ContextMenu ref="contextMenuRef" :menu="menutlist" @select="contextMenuFun" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -36,6 +46,8 @@ import houseItem from './houseItem.vue';
|
||||
import { useHouseStore } from '@/store/modules/house';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
|
||||
import ContextMenu from '@/components/ContextMenu/index.vue';
|
||||
|
||||
const houseStore = useHouseStore();
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
@@ -57,6 +69,17 @@ if (checkPermi(['system:house:ByIdList'])) {
|
||||
if (checkPermi(['system:house:remove'])) {
|
||||
menutlist.push({ label: '删除', value: 'delete' });
|
||||
}
|
||||
|
||||
const contextMenuRef = ref();
|
||||
|
||||
// 处理子组件抛出的打开菜单事件
|
||||
const handleOpenMenu = ({ event, houseId }: { event: MouseEvent; houseId: string }) => {
|
||||
// 调用唯一 ContextMenu 实例的 open 方法
|
||||
// 注意:这里需要确保 ContextMenu 组件暴露了 open 方法,或者我们修改 ContextMenu 为受控模式
|
||||
if (contextMenuRef.value) {
|
||||
contextMenuRef.value.open(event, houseId);
|
||||
}
|
||||
};
|
||||
function handleChangeCheckhouses(val: string[]) {
|
||||
houseStore.checkoutHousesFun([]);
|
||||
houseStore.checkoutHousesFun(val);
|
||||
@@ -104,9 +127,35 @@ function HandleDeleteUnit(unit) {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.TableBox {
|
||||
.el-table {
|
||||
height: calc(100% - 500px);
|
||||
.tablebox1 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
.TableBox {
|
||||
height: 100%;
|
||||
.el-checkbox-group {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.el-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.houseName {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-weight: 600;
|
||||
max-width: 300px;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nodata {
|
||||
|
||||
@@ -15,31 +15,24 @@
|
||||
>楼栋结构:{{ houseStore.currentBuildingInfo?.buildStructure ? `${houseStore.currentBuildingInfo?.buildStructure}(m)` : '--' }}
|
||||
</span>
|
||||
</div> -->
|
||||
<div>
|
||||
<div style="text-wrap: nowrap">
|
||||
<span class="text-size-16px text-color-black text-widget-bold mr-30px">
|
||||
<strong>{{ houseStore.currentBuildingInfo?.buildingName }}</strong>
|
||||
</span>
|
||||
<span class="mr-15px"
|
||||
>楼栋朝向:{{ houseStore.currentBuildingInfo?.buildToward ? `${houseStore.currentBuildingInfo?.buildToward}` : '--' }}</span
|
||||
>楼栋朝向:{{ houseStore.currentBuildingInfo?.buildToward ? `${houseStore.currentBuildingInfo?.buildToward}` : ' --' }}</span
|
||||
>
|
||||
<span class="mr-15px">楼高:{{ houseStore.currentBuildingInfo?.buildTall ? `${houseStore.currentBuildingInfo?.buildTall}(m)` : '--' }}</span>
|
||||
<span class="mr-15px">楼高:{{ houseStore.currentBuildingInfo?.buildTall ? `${houseStore.currentBuildingInfo?.buildTall}(m)` : ' --' }}</span>
|
||||
<span class="mr-15px"
|
||||
>楼栋结构:{{ houseStore.currentBuildingInfo?.buildStructure ? `${houseStore.currentBuildingInfo?.buildStructure}` : '--' }}
|
||||
>楼栋结构:{{ houseStore.currentBuildingInfo?.buildStructure ? `${houseStore.currentBuildingInfo?.buildStructure}` : ' --' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="rightActions flex flex-items-center">
|
||||
<span class="mr-20px" @click="handleAddUnit" v-hasPermi="['system:house:add']">+添加单元</span>
|
||||
<div style="text-wrap: nowrap" class="rightActions flex flex-items-center">
|
||||
<span class="mr-20px" @click="handleAddUnit" v-hasPermi="['unitNo:unitNo:add']">+添加单元</span>
|
||||
<span class="mr-20px" @click="handleAddHouse" v-hasPermi="['system:house:add']">+增加房屋</span>
|
||||
<!-- <span class="mr-20px">收费标准设置</span> -->
|
||||
<span @click="deleteAllhouse" v-hasPermi="['system:house:remove']">删除</span>
|
||||
<el-select
|
||||
clearable
|
||||
@clear="handleClearUse"
|
||||
@change="handleChangeUse"
|
||||
v-model="houseUse"
|
||||
placeholder="筛选房屋类型"
|
||||
style="width: 180px; margin: 0 10px"
|
||||
>
|
||||
<span @click="deleteAllhouse" v-hasPermi="['system:house:remove']">批量删除房屋</span>
|
||||
<el-select clearable @clear="handleClearUse" @change="handleChangeUse" v-model="houseUse" placeholder="筛选房屋类型" class="selectbox">
|
||||
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<div class="searchbox flex flex-items-center">
|
||||
@@ -49,9 +42,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="UnitBody">
|
||||
<TableUnit @edit-unit="handleEditUnit" @delete-unit="handleDelete"></TableUnit>
|
||||
</div>
|
||||
<!-- <div class="UnitBody"> -->
|
||||
<TableUnit @edit-unit="handleEditUnit" @delete-unit="handleDelete"></TableUnit>
|
||||
<!-- </div> -->
|
||||
<!-- 添加或修改单元对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="unitNoFormRef" :model="form" :rules="rules" label-width="80px">
|
||||
@@ -79,7 +72,7 @@
|
||||
import { deleteHouseApi } from '@/api/system/house';
|
||||
import TableUnit from './components/table.vue';
|
||||
import { useHouseStore } from '@/store/modules/house';
|
||||
import { listHouseUseType } from '@/api/system/houseUse';
|
||||
import { listHouseUseType, listHouseUseType_add_house } from '@/api/system/houseUse';
|
||||
import { addUnitNo, delUnitNo, getUnitNo, updateUnitNo } from '@/api/system/houseUnit';
|
||||
import { UnitNoVO } from '@/api/system/houseUnit/type';
|
||||
|
||||
@@ -96,11 +89,8 @@ const houseUseTypeList = ref([]);
|
||||
* 获取房屋 类型
|
||||
*/
|
||||
function init() {
|
||||
listHouseUseType({
|
||||
pageNum: 1,
|
||||
pageSize: 99999
|
||||
}).then((res) => {
|
||||
houseUseTypeList.value = res.rows;
|
||||
listHouseUseType_add_house().then((res) => {
|
||||
houseUseTypeList.value = res.data;
|
||||
});
|
||||
}
|
||||
init();
|
||||
@@ -228,6 +218,8 @@ $primary_color: #1978fe;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
|
||||
.Unit_top {
|
||||
padding: 20px;
|
||||
height: 60px;
|
||||
@@ -238,15 +230,24 @@ $primary_color: #1978fe;
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selectbox {
|
||||
width: 150px;
|
||||
margin: 0 10px;
|
||||
@media (max-width: 1550px) {
|
||||
width: 120px;
|
||||
}
|
||||
@media (max-width: 1400px) {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
.searchbox {
|
||||
.searchinput {
|
||||
width: 250px;
|
||||
@media (max-width: 1200px) {
|
||||
width: 50px;
|
||||
@media (max-width: 1550px) {
|
||||
width: 130px;
|
||||
}
|
||||
@media (max-width: 1400px) {
|
||||
width: 130px;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,6 +257,7 @@ $primary_color: #1978fe;
|
||||
flex: 1;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="p-2 houselist">
|
||||
<div class="p-2 houselist flex flex-col">
|
||||
<PageHeader>
|
||||
<template #content>
|
||||
<div class="houseAdressBox">
|
||||
<span class="mr-50px">当前小区:{{ currentVilageInfo && currentVilageInfo.villageName }}</span>
|
||||
<span>小区地址:{{ currentVilageInfo && currentVilageInfo.city }} {{ currentVilageInfo && currentVilageInfo.address }}</span>
|
||||
<span>小区地址: {{ currentVilageInfo && currentVilageInfo.address }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</PageHeader>
|
||||
@@ -21,8 +21,10 @@ import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { useHouseStore } from '@/store/modules/house';
|
||||
|
||||
const houseStore = useHouseStore();
|
||||
const { buildingtype, currentVilageInfo } = storeToRefs(houseStore);
|
||||
const { currentVilageInfo } = storeToRefs(houseStore);
|
||||
|
||||
function init() {
|
||||
houseStore.getviliageinfo(localStorage.getItem('villageid'));
|
||||
houseStore.initHouse();
|
||||
}
|
||||
init();
|
||||
@@ -32,13 +34,13 @@ init();
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.houselist {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
height: calc(100vh - 84px);
|
||||
min-height: calc(100vh - 84px);
|
||||
height: 100%;
|
||||
.houseBody {
|
||||
height: calc(100% - 200px);
|
||||
flex: 1;
|
||||
margin-top: 10px;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.houseAdressBox {
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="租户姓名" prop="rentalName">
|
||||
<el-input v-model="form.rentalName" placeholder="请输入住户姓名" />
|
||||
<el-form-item label="业主姓名" prop="rentalName">
|
||||
<el-input disabled v-model="form.rentalName" placeholder="请输入业主姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -94,7 +94,7 @@
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="房屋设施" prop="type">
|
||||
<div class="housedevicesbox">
|
||||
<div class="housedevicesbox" v-if="housefacilities.length > 0">
|
||||
<div
|
||||
v-for="item in housefacilities"
|
||||
:key="item.id"
|
||||
@@ -108,6 +108,7 @@
|
||||
<span class="ml-2">{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else style="color: gray"> 无</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -181,7 +182,7 @@ import { HouseRentalVO } from '@/api/system/houseRental/type';
|
||||
import { CascaderValue, UploadInstance, UploadProps, UploadUserFile } from 'element-plus';
|
||||
|
||||
import { getHousePathById, hasFormData, splitStringUrl } from '@/utils/house';
|
||||
import { addHouseRental, getHouseRental, updateHouseRental, uploadHouseImage } from '@/api/system/houseRental';
|
||||
import { addHouseRental, getHouseOwnUser, getHouseRental, updateHouseRental, uploadHouseImage } from '@/api/system/houseRental';
|
||||
import { validator } from '@/utils/Reg';
|
||||
import { useHouseStore } from '@/store/modules/house';
|
||||
import { listHouseFacilities } from '@/api/system/HouseFacilities';
|
||||
@@ -241,7 +242,12 @@ const housefacilities = ref([]);
|
||||
// !== 楼栋房屋 =============================================================================
|
||||
async function gettreedata() {
|
||||
const reslist = await listHouseFacilities();
|
||||
housefacilities.value = reslist.rows;
|
||||
housefacilities.value = reslist.rows
|
||||
.map((item) => {
|
||||
if (item.status !== '1') return item;
|
||||
return false;
|
||||
})
|
||||
.filter((item) => item !== false);
|
||||
|
||||
treedata.value = await houseStore.getCurrentVilageTreeHouse();
|
||||
if (route.query.id) {
|
||||
@@ -265,6 +271,10 @@ gettreedata();
|
||||
function handleChange(val: CascaderValue) {
|
||||
userHousepath.value = val;
|
||||
form.value.houseId = val[2];
|
||||
|
||||
getHouseOwnUser(val[2]).then((res) => {
|
||||
form.value.rentalName = res.msg;
|
||||
});
|
||||
}
|
||||
// !== 上传文件 =============================================================================
|
||||
const fileList = ref<UploadUserFile[]>([]);
|
||||
|
||||
@@ -51,12 +51,23 @@
|
||||
<span style="margin-right: 10px" v-for="item in HouseInfo.facilitieslist" :key="item">{{ handlefacilities(item) }} </span>
|
||||
</div>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="10">
|
||||
<el-row :span="24">
|
||||
<el-col :span="24">
|
||||
<div class="descriptionsbox">
|
||||
<div class="label">房屋照片:</div>
|
||||
<div class="value grid grid-cols-4 gap-4">
|
||||
<el-image v-for="(item, index) in HouseInfo.houseImageUrls" :key="index" :src="splitImages(item)" class="houseImage"></el-image>
|
||||
<div class="value">
|
||||
<el-image
|
||||
v-for="(item, index) in HouseInfo.houseImageUrls"
|
||||
:key="index"
|
||||
:zoom-rate="1.2"
|
||||
:max-scale="7"
|
||||
:min-scale="0.2"
|
||||
:src="item"
|
||||
:preview-src-list="HouseInfo.houseImageUrls"
|
||||
show-progress
|
||||
:initial-index="0"
|
||||
class="houseImage"
|
||||
></el-image>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -199,6 +210,8 @@ function handlBack() {
|
||||
.houseImage {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
margin: 10px 5px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.descriptionsbox {
|
||||
display: flex;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<el-option v-for="item in com_house_use" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="发布人" prop="houseId">
|
||||
<el-form-item label="发布人" prop="rentalName">
|
||||
<el-input v-model="queryParams.rentalName" placeholder="请输入" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -163,10 +163,14 @@ const { queryParams, form } = toRefs(data);
|
||||
/** 查询房屋租赁管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listHouseRental(queryParams.value);
|
||||
houseRentalList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listHouseRental(queryParams.value)
|
||||
.then((res) => {
|
||||
houseRentalList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -190,6 +194,8 @@ const handleQuery = () => {
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
queryParams.value.houseUse = '';
|
||||
queryParams.value.rentalName = '';
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
@@ -209,7 +215,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: HouseRentalVO) => {
|
||||
const id = row.id || ids.value[0];
|
||||
const id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/house/edithouseRental',
|
||||
query: {
|
||||
|
||||
@@ -150,10 +150,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询单元列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listUnitNo(queryParams.value);
|
||||
unitNoList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listUnitNo(queryParams.value)
|
||||
.then((res) => {
|
||||
unitNoList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<el-dropdown-item :disabled="single" v-if="checkPermi(['houseUseType:houseUseType:edit'])" @click="handleUpdate">
|
||||
<div>编辑</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="single" v-if="checkPermi(['houseUseType:houseUseType:delete'])" @click="handleDelete">
|
||||
<el-dropdown-item :disabled="multiple" v-if="checkPermi(['houseUseType:houseUseType:delete'])" @click="handleDelete">
|
||||
<div>批量删除</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="checkPermi(['houseUseType:houseUseType:export'])" @click="handleExport">
|
||||
@@ -112,10 +112,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询房屋类型列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listHouseUseType(queryParams.value);
|
||||
houseUseTypeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listHouseUseType(queryParams.value)
|
||||
.then((res) => {
|
||||
houseUseTypeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -186,7 +190,7 @@ const submitForm = () => {
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: HouseUseTypeVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
await proxy?.$modal.confirm('是否确认删除房屋类型编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||
await proxy?.$modal.confirm('是否确认删除该房屋类型?').finally(() => (loading.value = false));
|
||||
await delHouseUseType(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
|
||||
@@ -78,10 +78,14 @@ const { queryParams } = toRefs(data);
|
||||
const getList = async () => {
|
||||
queryParams.value.statDate = starDate.value.join('-');
|
||||
loading.value = true;
|
||||
const res = await listItem(queryParams.value);
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listItem(queryParams.value)
|
||||
.then((res) => {
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
|
||||
@@ -20,17 +20,6 @@
|
||||
<el-card class="flex-1" shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:item:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:item:edit']">编辑</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:item:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
<right-toolbar
|
||||
:disable-delete="multiple"
|
||||
:disable-edit="single"
|
||||
@@ -53,8 +42,8 @@
|
||||
<el-switch
|
||||
@change="(val: string) => handleChange(val, scope.row.id)"
|
||||
v-model="scope.row.status"
|
||||
active-value="1"
|
||||
inactive-value="0"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -137,10 +126,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询巡检项目列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listItem(queryParams.value);
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listItem(queryParams.value)
|
||||
.then((res) => {
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -185,10 +178,11 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ItemVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/inspection/editItem',
|
||||
query: {
|
||||
id: row.id
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -78,10 +78,14 @@ const { queryParams } = toRefs(data);
|
||||
const getList = async () => {
|
||||
queryParams.value.statDate = starDate.value.join('-');
|
||||
loading.value = true;
|
||||
const res = await listItem(queryParams.value);
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listItem(queryParams.value)
|
||||
.then((res) => {
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
|
||||
@@ -39,11 +39,19 @@
|
||||
is-range
|
||||
range-separator="到"
|
||||
start-placeholder="开始时间"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm:00"
|
||||
end-placeholder="结束时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-button v-if="taskTime.length > 1" icon="Minus" circle style="margin-left: 10px" @click="removeTaskTime(index)"></el-button>
|
||||
<el-button v-if="taskTime.length === index + 1" icon="Plus" circle style="margin-left: 10px" @click="addTaskTime"></el-button>
|
||||
<!-- <el-button v-if="taskTime.length > 1" icon="Minus" circle style="margin-left: 10px" @click="removeTaskTime(index)"></el-button>
|
||||
<el-button
|
||||
v-if="taskTime.length === index + 1 && taskTime.length <= 8"
|
||||
icon="Plus"
|
||||
circle
|
||||
style="margin-left: 10px"
|
||||
@click="addTaskTime"
|
||||
></el-button> -->
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
@@ -52,12 +60,6 @@
|
||||
<el-option v-for="item in com_inspection_remind_tiime" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="巡检设置">
|
||||
<el-radio-group v-model="form.inspectSetting">
|
||||
<el-radio label="必须拍照" value="1" />
|
||||
<el-radio label="允许跳检" value="0" />
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="计划路线">
|
||||
<el-select @change="handlChangeMap" v-model="form.routeIds" placeholder="请选择" style="width: 100%">
|
||||
<el-option v-for="item in planlist" :key="item.value" :label="item.routeName" :value="item.id" />
|
||||
@@ -75,15 +77,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// TODO 巡检计划 添加
|
||||
import { listRoute } from '@/api/system/InspectionRoute';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { numToWeek } from '@/utils/time';
|
||||
import { Delete } from '@element-plus/icons-vue';
|
||||
import { ref } from 'vue';
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import { addPlan, getPlan, updatePlan } from '@/api/system/InspectionPlan';
|
||||
import { getVillageByIdAPI } from '@/api/system/community';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_inspection_remind_tiime } = toRefs<any>(proxy?.useDict('com_inspection_remind_tiime'));
|
||||
|
||||
@@ -98,7 +98,7 @@ const form = ref({
|
||||
executeDay: '', // 执行周期具体的周几
|
||||
remindTime: '', // 提醒时间
|
||||
routeIds: '', // 计划路线id
|
||||
inspectSetting: '1' // 巡检设置
|
||||
inspectSetting: 0 // 巡检设置
|
||||
});
|
||||
const rules = ref({
|
||||
planName: [{ required: true, message: '请输入巡检计划名称', trigger: 'blur' }],
|
||||
@@ -108,16 +108,6 @@ const rules = ref({
|
||||
// 初始化 taskTime,确保至少有一个时间段
|
||||
const taskTime = ref<[string, string][]>([['', '']]);
|
||||
|
||||
// 新增时间段
|
||||
function addTaskTime() {
|
||||
taskTime.value.push(['', '']);
|
||||
}
|
||||
|
||||
// 删除时间段
|
||||
function removeTaskTime(index: number) {
|
||||
taskTime.value.splice(index, 1);
|
||||
}
|
||||
|
||||
// 选择周几
|
||||
const checkoutWeek = ref([]);
|
||||
function checkoutWeekFun(val: number) {
|
||||
@@ -129,13 +119,6 @@ function checkoutWeekFun(val: number) {
|
||||
}
|
||||
}
|
||||
|
||||
// 任务时间
|
||||
const options = ref([
|
||||
{
|
||||
value: '09:00-11:00; 13:00-15:00',
|
||||
label: '09:00-11:00; 13:00-15:00'
|
||||
}
|
||||
]);
|
||||
// 提醒时间
|
||||
|
||||
// 巡检计划id
|
||||
@@ -158,7 +141,7 @@ async function init() {
|
||||
executeDay: res.data.executeDay, // 执行周期具体的周几
|
||||
remindTime: res.data.remindTime, // 提醒时间
|
||||
routeIds: res.data.routeIds, // 计划路线id
|
||||
inspectSetting: String(res.data.inspectSetting) // 巡检设置
|
||||
inspectSetting: res.data.inspectSetting // 巡检设置
|
||||
};
|
||||
checkoutWeek.value = res.data.executeDay
|
||||
.split(',')
|
||||
@@ -245,11 +228,14 @@ function handlChangeMap(val) {
|
||||
}
|
||||
}
|
||||
}
|
||||
const aloaderkey = import.meta.env.VITE_GCJ02_KEY_GD;
|
||||
const VITE_GCJ02_JS_CODE_GD = import.meta.env.VITE_GCJ02_JS_CODE_GD;
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
window._AMapSecurityConfig = { securityJsCode: '09534b3534d8da53968529a9ce164118' };
|
||||
window._AMapSecurityConfig = { securityJsCode: VITE_GCJ02_JS_CODE_GD };
|
||||
AMapLoader.load({
|
||||
key: '8e302fe1be5f4db62bc734db23dca149',
|
||||
key: aloaderkey,
|
||||
version: '2.0',
|
||||
plugins: ['AMap.Scale', 'AMap.Marker']
|
||||
}).then(async (AMap) => {
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
></el-switch>
|
||||
<!-- 0关闭 1开启 -->
|
||||
<!-- 1关闭 0开启 -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="110" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
@@ -148,17 +148,21 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询巡检计划列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listPlan(queryParams.value);
|
||||
planList.value = res.rows;
|
||||
planList.value.forEach((item) => {
|
||||
item.routeNames = item.routeList.map((item) => item.routeName).join(',');
|
||||
item.executeDayNames = item.executeDay
|
||||
.split(',')
|
||||
.sort((a, b) => Number(a) - Number(b))
|
||||
.map((item) => Number(item));
|
||||
});
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listPlan(queryParams.value)
|
||||
.then((res) => {
|
||||
planList.value = res.rows;
|
||||
planList.value.forEach((item) => {
|
||||
item.routeNames = item.routeList.map((item) => item.routeName).join(',');
|
||||
item.executeDayNames = item.executeDay
|
||||
.split(',')
|
||||
.sort((a, b) => Number(a) - Number(b))
|
||||
.map((item) => Number(item));
|
||||
});
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -202,10 +206,12 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: PlanVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
|
||||
router.push({
|
||||
path: '/inspection/editPlan',
|
||||
query: {
|
||||
id: row.id
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -216,22 +222,6 @@ function handleChangeStatus(id: string, status: string) {
|
||||
getList();
|
||||
});
|
||||
}
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
planFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (form.value.id) {
|
||||
await updatePlan(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await addPlan(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: PlanVO) => {
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="打卡方式" prop="checkMode">
|
||||
<!-- <el-form-item label="打卡方式" prop="checkMode">
|
||||
<el-select v-model="form.checkMode" placeholder="请选择打卡方式" clearable>
|
||||
<el-option v-for="dict in com_inspection_point_checkmode" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="巡检点状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="item in com_inspection_point_status" :value="item.value" :key="item.value" :label="item.value">{{
|
||||
@@ -67,7 +67,7 @@ import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import { getVillageByIdAPI } from '@/api/system/community';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_inspection_point_checkmode } = toRefs<any>(proxy?.useDict('com_inspection_point_checkmode'));
|
||||
// const { com_inspection_point_checkmode } = toRefs<any>(proxy?.useDict('com_inspection_point_checkmode'));
|
||||
const { com_inspection_point_status } = toRefs<any>(proxy?.useDict('com_inspection_point_status'));
|
||||
|
||||
const router = useRouter();
|
||||
@@ -79,6 +79,7 @@ const form = ref({
|
||||
pointName: '',
|
||||
itemId: '',
|
||||
location: '',
|
||||
locationName: '',
|
||||
status: '0',
|
||||
checkMode: '9999'
|
||||
});
|
||||
@@ -106,7 +107,11 @@ function checkoutItem(id: string) {
|
||||
}
|
||||
function init() {
|
||||
// 获取巡检项目列表
|
||||
listItem().then((res) => {
|
||||
listItem({
|
||||
status: '0',
|
||||
pageNum: 1,
|
||||
pageSize: 9999
|
||||
}).then((res) => {
|
||||
pointItemlist.value = res.rows;
|
||||
});
|
||||
|
||||
@@ -157,27 +162,31 @@ const mapReady = ref(false);
|
||||
const map = ref(null);
|
||||
const marker = ref(null);
|
||||
const villageid = localStorage.getItem('villageid');
|
||||
const aloaderkey = import.meta.env.VITE_GCJ02_KEY_GD;
|
||||
const VITE_GCJ02_JS_CODE_GD = import.meta.env.VITE_GCJ02_JS_CODE_GD;
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
|
||||
window._AMapSecurityConfig = { securityJsCode: '09534b3534d8da53968529a9ce164118' };
|
||||
window._AMapSecurityConfig = { securityJsCode: VITE_GCJ02_JS_CODE_GD };
|
||||
|
||||
AMapLoader.load({
|
||||
key: '8e302fe1be5f4db62bc734db23dca149',
|
||||
key: aloaderkey,
|
||||
version: '2.0',
|
||||
plugins: ['AMap.Scale', 'AMap.Marker']
|
||||
}).then(async (AMap) => {
|
||||
const villageinfo = await getVillageByIdAPI(villageid);
|
||||
const city = villageinfo.data.city.replaceAll('/', '');
|
||||
map.value = new AMap.Map('containerMap', {
|
||||
viewMode: '3D',
|
||||
zoom: 11,
|
||||
center: [116.397428, 39.90923]
|
||||
});
|
||||
|
||||
AMap.plugin('AMap.Geocoder', function () {
|
||||
const city = villageinfo.data.city.replaceAll('/', '');
|
||||
const geocoder = new AMap.Geocoder({
|
||||
city: city // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
|
||||
});
|
||||
|
||||
const address = villageinfo.data.address;
|
||||
|
||||
geocoder.getLocation(address, function (status, result) {
|
||||
geocoder.getLocation(city, function (status, result) {
|
||||
if (status === 'complete' && result.info === 'OK') {
|
||||
// result中对应详细地理坐标信息
|
||||
map.value.setCenter(result.geocodes[0].location.toArray());
|
||||
@@ -185,14 +194,8 @@ onMounted(async () => {
|
||||
});
|
||||
});
|
||||
|
||||
map.value = new AMap.Map('containerMap', {
|
||||
viewMode: '3D',
|
||||
zoom: 11,
|
||||
center: [116.397428, 39.90923]
|
||||
});
|
||||
|
||||
mapReady.value = true;
|
||||
handleMap(AMap);
|
||||
handleMap(AMap, city);
|
||||
initLocation(AMap);
|
||||
});
|
||||
});
|
||||
@@ -206,11 +209,21 @@ function clearLocation() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleMap(AMap) {
|
||||
function handleMap(AMap, city = '010') {
|
||||
// 添加点击事件
|
||||
map.value.on('click', (e) => {
|
||||
const lnglat = e.lnglat;
|
||||
form.value.location = `${lnglat.lng},${lnglat.lat}`;
|
||||
const lnglatarr = [lnglat.lng, lnglat.lat];
|
||||
const geocoder = new AMap.Geocoder({
|
||||
city: city // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
|
||||
});
|
||||
geocoder.getAddress(lnglatarr, function (status, result) {
|
||||
if (status === 'complete' && result.info === 'OK') {
|
||||
// result为对应的地理位置详细信息
|
||||
form.value.locationName = result.regeocode.formattedAddress;
|
||||
}
|
||||
});
|
||||
// 如果有 marker.value,先移除
|
||||
if (marker.value) {
|
||||
map.value.remove(marker.value);
|
||||
|
||||
@@ -143,10 +143,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询巡检点列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listPoint(queryParams.value);
|
||||
pointList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listPoint(queryParams.value)
|
||||
.then((res) => {
|
||||
pointList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
@@ -190,27 +194,11 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: PointVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/inspection/editInspectionPoint',
|
||||
query: {
|
||||
id: row?.id
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
pointFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (form.value.id) {
|
||||
await updatePoint(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await addPoint(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
</div>
|
||||
<div class="infobox">
|
||||
<div class="label">开始时间 :</div>
|
||||
<div class="value">{{ form.actualStartTime }}</div>
|
||||
<!-- <div class="value">{{ form.actualStartTime }}</div> -->
|
||||
<div class="value">{{ form.taskTime.split(' - ')[0] }}</div>
|
||||
</div>
|
||||
<div class="infobox">
|
||||
<div class="label">结束时间 :</div>
|
||||
<div class="value">{{ form.actualEndTime }}</div>
|
||||
<!-- <div class="value">{{ form.actualEndTime }}</div> -->
|
||||
<div class="value">{{ form.taskTime.split(' - ')[1] }}</div>
|
||||
</div>
|
||||
<div class="infobox">
|
||||
<div class="label">执行状态 :</div>
|
||||
@@ -46,13 +48,55 @@
|
||||
<div class="AddBuildingBody">
|
||||
<div class="title">巡检记录</div>
|
||||
<div class="">
|
||||
<el-table :data="form.details" style="width: 100%">
|
||||
<div class="timequerybox">
|
||||
<div class="label">筛选日期:</div>
|
||||
<el-date-picker
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD"
|
||||
clearable
|
||||
:disabled-date="disabledDate"
|
||||
v-model="date"
|
||||
type="date"
|
||||
placeholder="选择查看日期"
|
||||
/>
|
||||
<el-button style="margin-left: 10px" @click="querySeale">查询</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:default-sort="{
|
||||
prop: 'checkTime',
|
||||
order: 'descending'
|
||||
}"
|
||||
:data="form.details"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column type="index" align="center" label="序号" width="85" />
|
||||
<el-table-column prop="pointName" align="center" label="巡检点" />
|
||||
<el-table-column prop="checkTime" align="center" label=" 巡检时间" />
|
||||
<el-table-column prop="location" align="center" label="巡检地址" />
|
||||
<el-table-column prop="checkResult" align="center" label="巡检结果" />
|
||||
<el-table-column prop="photos" align="center" label="图片" />
|
||||
<el-table-column sortable prop="checkTime" align="center" label=" 巡检时间" />
|
||||
<el-table-column prop="status" align="center" label="巡检状态">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status === 0" type="success">正常</el-tag>
|
||||
<el-tag v-else type="danger">异常</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="location" align="center" label="巡检地址" /> -->
|
||||
<el-table-column prop="remark" align="left" label="巡检结果" />
|
||||
<el-table-column label="图片">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-image
|
||||
v-for="(item, index) in scope.row.photoslist"
|
||||
:key="index"
|
||||
:src="item"
|
||||
:preview-src-list="scope.row.photoslist"
|
||||
show-progress
|
||||
fit="cover"
|
||||
:initial-index="0"
|
||||
:preview-teleported="true"
|
||||
style="width: 80px; height: 50px; margin-right: 10px"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,6 +108,7 @@ import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { getRecord } from '@/api/system/InspectionRecord';
|
||||
import { RecordVO } from '@/api/system/InspectionRecord/type';
|
||||
import { formatDate } from '@/utils/time';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_inspection_task_status } = toRefs<any>(proxy?.useDict('com_inspection_task_status'));
|
||||
@@ -74,51 +119,98 @@ const route = useRoute();
|
||||
const formRef = ref();
|
||||
const form = ref<RecordVO>({
|
||||
taskName: '',
|
||||
taskTime: '',
|
||||
inspectorName: '',
|
||||
planName: '',
|
||||
actualStartTime: '',
|
||||
actualEndTime: '',
|
||||
createByName: '',
|
||||
details: [],
|
||||
status: '0',
|
||||
createTime: '',
|
||||
updateTime: ''
|
||||
});
|
||||
const userid = ref(null);
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
getRecord(userid.value).then((res) => {
|
||||
|
||||
const date = ref<string | null>(null);
|
||||
// 设置默认日期的函数
|
||||
const setDefaultDate = () => {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
console.log(!form.value.taskTime);
|
||||
if (!form.value.taskTime) {
|
||||
console.log('date', formatDate(today, 'YYYY-MM-DD'));
|
||||
date.value = formatDate(today, 'YYYY-MM-DD');
|
||||
return;
|
||||
}
|
||||
|
||||
const timeRange = form.value.taskTime.split(' - ');
|
||||
const startDate = new Date(timeRange[0]);
|
||||
startDate.setHours(0, 0, 0, 0);
|
||||
|
||||
const endDate = new Date(timeRange[1]);
|
||||
endDate.setHours(0, 0, 0, 0);
|
||||
|
||||
// 逻辑:优先选今天;如果今天不在范围内,选开始日期
|
||||
if (today.getTime() >= startDate.getTime() && today.getTime() <= endDate.getTime()) {
|
||||
date.value = formatDate(today, 'YYYY-MM-DD');
|
||||
} else if (today.getTime() < startDate.getTime()) {
|
||||
// 今天早于开始时间,默认选开始时间
|
||||
date.value = formatDate(startDate, 'YYYY-MM-DD');
|
||||
} else {
|
||||
// 今天晚于结束时间,默认选结束时间
|
||||
date.value = formatDate(endDate, 'YYYY-MM-DD');
|
||||
}
|
||||
};
|
||||
|
||||
// 禁用 form.value.taskTime.split(' - ') 范围外的所有日期,包括边界日期(开始和结束当天)
|
||||
const disabledDate = (time: Date) => {
|
||||
if (!form.value.taskTime || !form.value.taskTime.includes(' - ')) {
|
||||
return true; // 如果没有有效时间范围,默认禁用
|
||||
}
|
||||
|
||||
const timeRange = form.value.taskTime.split(' - ');
|
||||
|
||||
// 获取开始日期的零点时间戳
|
||||
const startDate = new Date(timeRange[0]);
|
||||
startDate.setHours(0, 0, 0, 0);
|
||||
|
||||
// 获取结束日期的零点时间戳
|
||||
const endDate = new Date(timeRange[1]);
|
||||
endDate.setHours(0, 0, 0, 0);
|
||||
|
||||
// 获取当前选择日期的零点时间戳
|
||||
const selectDate = new Date(time);
|
||||
selectDate.setHours(0, 0, 0, 0);
|
||||
|
||||
// 禁用早于开始日期 或 晚于结束日期的日期
|
||||
// 注意:这里使用 < 和 >,意味着等于开始或结束日期时返回 false(不禁用/可选)
|
||||
return selectDate.getTime() < startDate.getTime() || selectDate.getTime() > endDate.getTime();
|
||||
};
|
||||
// ! table
|
||||
function querySeale() {
|
||||
getRecord(userid.value, date.value).then((res) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
if (form.value.details.length > 0) {
|
||||
form.value.details.forEach((item) => {
|
||||
item.photoslist = item.imgUrl.split(',');
|
||||
item.photoslist = item.photoslist.filter((item) => item);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ! table
|
||||
const tableData = [
|
||||
{
|
||||
date: '2016-05-03',
|
||||
name: 'Tom',
|
||||
address: 'No. 189, Grove St, Los Angeles'
|
||||
},
|
||||
{
|
||||
date: '2016-05-02',
|
||||
name: 'Tom',
|
||||
address: 'No. 189, Grove St, Los Angeles'
|
||||
},
|
||||
{
|
||||
date: '2016-05-04',
|
||||
name: 'Tom',
|
||||
address: 'No. 189, Grove St, Los Angeles'
|
||||
},
|
||||
{
|
||||
date: '2016-05-01',
|
||||
name: 'Tom',
|
||||
address: 'No. 189, Grove St, Los Angeles'
|
||||
function init() {
|
||||
setDefaultDate();
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
querySeale();
|
||||
}
|
||||
];
|
||||
// ! table
|
||||
|
||||
}
|
||||
init();
|
||||
// 推出
|
||||
const cancelForm = () => {
|
||||
router.back();
|
||||
@@ -166,5 +258,16 @@ const cancelForm = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timequerybox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.label {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -43,17 +43,18 @@
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="任务名称" align="center" prop="taskName" />
|
||||
<el-table-column label="巡检人员" align="center" prop="inspectorName" />
|
||||
<el-table-column label="任务开始时间" align="center" prop="startTime" width="180">
|
||||
<!-- <el-table-column label="任务周期" align="center" prop="taskTime" /> -->
|
||||
<el-table-column label="任务开始时间" align="center" prop="taskTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.actualStartTime, '{y}-{m}-{d}') }}</span>
|
||||
<span>{{ scope.row.taskTime.split(' - ')[0] }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务结束时间" align="center" prop="endTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.actualEndTime, '{y}-{m}-{d}') }}</span>
|
||||
<span>{{ scope.row.taskTime.split(' - ')[1] }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="执行状态" align="center" prop="status">
|
||||
<el-table-column label="执行状态" align="center" prop="status" width="120">
|
||||
<template #default="scope">
|
||||
<DictTag :options="com_inspection_task_status" :value="scope.row.status"></DictTag>
|
||||
</template>
|
||||
@@ -72,9 +73,8 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Record" lang="ts">
|
||||
import { listRecord, getRecord, delRecord, addRecord, updateRecord } from '@/api/system/InspectionRecord/index';
|
||||
import { listRecord, delRecord, addRecord, updateRecord } from '@/api/system/InspectionRecord/index';
|
||||
import { RecordVO, RecordQuery, RecordForm } from '@/api/system/InspectionRecord/type';
|
||||
import { getUserByRoleKey } from '@/api/system/user';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_inspection_task_status } = toRefs<any>(proxy?.useDict('com_inspection_task_status'));
|
||||
@@ -124,11 +124,14 @@ const { queryParams, form } = toRefs(data);
|
||||
/** 查询巡检记录主列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
|
||||
const res = await listRecord(queryParams.value);
|
||||
recordList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listRecord(queryParams.value)
|
||||
.then((res) => {
|
||||
recordList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
// 处理日期选择
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
<el-form-item label="巡检路线名称" prop="routeName">
|
||||
<el-input v-model.trim="form.routeName" placeholder="请输入巡检路线名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="巡检路线描述" prop="description">
|
||||
<!-- <el-form-item label="巡检路线描述" prop="description">
|
||||
<el-input type="textarea" :rows="3" v-model.trim="form.description" placeholder="请输入巡检路线描述" />
|
||||
</el-form-item>
|
||||
<el-form-item label="预计巡检时长" prop="estimatedTime">
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="预计巡检时长" prop="estimatedTime">
|
||||
<el-input v-model.trim.number="form.estimatedTime" placeholder="预计巡检时长">
|
||||
<template #append>分钟</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="巡检路线状态" prop="routeStatus">
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="巡检路线状态" prop="routeStatus">
|
||||
<el-radio-group v-model="form.routeStatus">
|
||||
<el-radio v-for="(item, index) in com_inspection_route_status" :key="index" :value="item.value" :label="item.label"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="巡检点">
|
||||
<div class="itembox">
|
||||
<div
|
||||
@@ -57,19 +57,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, toRefs, nextTick } from 'vue';
|
||||
import { getCurrentInstance, ComponentInternalInstance } from 'vue';
|
||||
import { ref, nextTick } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addPoint, getPoint, listPoint, updatePoint } from '@/api/system/InspectionPoint';
|
||||
import { listPoint } from '@/api/system/InspectionPoint';
|
||||
import { onMounted, onUnmounted } from 'vue';
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import { addRoute, getRoute, updateRoute } from '@/api/system/InspectionRoute';
|
||||
import { getVillageByIdAPI } from '@/api/system/community';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_inspection_route_status } = toRefs<any>(proxy?.useDict('com_inspection_route_status'));
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
@@ -193,7 +189,7 @@ function init() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 巡检路线开关
|
||||
// ! map
|
||||
const mapReady = ref(false);
|
||||
const AMapLib = ref(null);
|
||||
@@ -203,28 +199,26 @@ const markers = ref<Record<string, any>>({});
|
||||
const mouseTool = ref(null);
|
||||
const drawnPolylines = ref([]); // 存所有线条
|
||||
const villageid = localStorage.getItem('villageid');
|
||||
const aloaderkey = import.meta.env.VITE_GCJ02_KEY_GD;
|
||||
const VITE_GCJ02_JS_CODE_GD = import.meta.env.VITE_GCJ02_JS_CODE_GD;
|
||||
onMounted(async () => {
|
||||
// 获取巡检点列表
|
||||
if (!routeid.value) {
|
||||
listPoint().then((res) => {
|
||||
listPoint({}).then((res) => {
|
||||
pointslist.value = res.rows;
|
||||
});
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
window._AMapSecurityConfig = { securityJsCode: '09534b3534d8da53968529a9ce164118' };
|
||||
|
||||
window._AMapSecurityConfig = { securityJsCode: VITE_GCJ02_JS_CODE_GD };
|
||||
AMapLoader.load({
|
||||
key: '8e302fe1be5f4db62bc734db23dca149',
|
||||
key: aloaderkey,
|
||||
version: '2.0',
|
||||
plugins: ['AMap.Scale', 'AMap.Marker']
|
||||
}).then(async (AMap) => {
|
||||
AMapLib.value = AMap;
|
||||
map.value = new AMap.Map('containerMap', {
|
||||
viewMode: '3D',
|
||||
zoom: 11,
|
||||
center: [116.397428, 39.90923]
|
||||
zoom: 11
|
||||
});
|
||||
|
||||
const villageinfo = await getVillageByIdAPI(villageid);
|
||||
@@ -233,10 +227,7 @@ onMounted(async () => {
|
||||
const geocoder = new AMap.Geocoder({
|
||||
city: city // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
|
||||
});
|
||||
|
||||
const address = villageinfo.data.address;
|
||||
|
||||
geocoder.getLocation(address, function (status, result) {
|
||||
geocoder.getLocation(city, function (status, result) {
|
||||
if (status === 'complete' && result.info === 'OK') {
|
||||
// result中对应详细地理坐标信息
|
||||
map.value.setCenter(result.geocodes[0].location.toArray());
|
||||
@@ -331,8 +322,10 @@ function clearAll() {
|
||||
// !!! 核心:获取绘制的路线经纬度数组
|
||||
function getPolylinePath() {
|
||||
if (drawnPolylines.value.length === 0) return [];
|
||||
const lastLine = drawnPolylines.value.pop();
|
||||
const path = lastLine.getPath().map((p) => [p.lng, p.lat]);
|
||||
// 获取最后一条线
|
||||
const lastPolyline = drawnPolylines.value[drawnPolylines.value.length - 1];
|
||||
// const lastLine = drawnPolylines.value.pop();
|
||||
const path = lastPolyline.getPath().map((p) => [p.lng, p.lat]);
|
||||
return path;
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -47,19 +47,25 @@
|
||||
<el-table v-loading="loading" border :data="routeList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="巡检路线名称" width="220" align="center" prop="routeName" />
|
||||
<el-table-column label="路线描述" align="center" prop="description" />
|
||||
<!-- <el-table-column label="路线描述" align="center" prop="description" /> -->
|
||||
<el-table-column label="巡检点" align="center" prop="pointNames" show-overflow-tooltip />
|
||||
<el-table-column label="预计巡检时长(分钟)" width="140" align="center" prop="estimatedTime" />
|
||||
<!-- <el-table-column label="预计巡检时长(分钟)" width="140" align="center" prop="estimatedTime" /> -->
|
||||
<el-table-column label="巡检路线状态" width="120" align="center" prop="routeStatus">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_inspection_route_status" :value="scope.row.routeStatus"></dict-tag>
|
||||
<!-- <dict-tag :options="com_inspection_route_status" :value="scope.row.routeStatus"></dict-tag> -->
|
||||
<el-switch
|
||||
v-model="scope.row.routeStatus"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
@change="(val) => switchchangebtn(scope.row.id, val)"
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="起点经度" width="120" align="center" prop="startLng" />
|
||||
<el-table-column label="起点纬度" width="120" align="center" prop="startLat" />
|
||||
<el-table-column label="终点经度" width="120" align="center" prop="endLng" />
|
||||
<el-table-column label="终点纬度" width="120" align="center" prop="endLat" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<!-- <el-table-column label="起点经度" width="120" align="center" prop="startLng" /> -->
|
||||
<!-- <el-table-column label="起点纬度" width="120" align="center" prop="startLat" /> -->
|
||||
<!-- <el-table-column label="终点经度" width="120" align="center" prop="endLng" /> -->
|
||||
<!-- <el-table-column label="终点纬度" width="120" align="center" prop="endLat" /> -->
|
||||
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['system:route:edit']">修改</el-button>
|
||||
@@ -74,7 +80,7 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Route" lang="ts">
|
||||
import { listRoute, getRoute, delRoute, addRoute, updateRoute } from '@/api/system/InspectionRoute/index';
|
||||
import { listRoute, getRoute, delRoute, addRoute, updateRoute, changeStatusRoute } from '@/api/system/InspectionRoute/index';
|
||||
import { RouteVO, RouteQuery, RouteForm } from '@/api/system/InspectionRoute/type';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
|
||||
@@ -191,27 +197,21 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: RouteVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/Inspection/editRoute',
|
||||
query: { id: row?.id }
|
||||
query: { id: _ids }
|
||||
});
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
routeFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (form.value.id) {
|
||||
await updateRoute(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await addRoute(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
}
|
||||
});
|
||||
const switchchangebtn = (id, val) => {
|
||||
changeStatusRoute(id, val)
|
||||
.then(() => {
|
||||
ElMessage.success('修改成功');
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.error('修改失败');
|
||||
});
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
|
||||
@@ -80,10 +80,14 @@ const { queryParams } = toRefs(data);
|
||||
/** 查询巡检路线列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await list_statapi(queryParams.value);
|
||||
routeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
list_statapi(queryParams.value)
|
||||
.then((res) => {
|
||||
routeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
|
||||
@@ -33,7 +33,14 @@
|
||||
range-separator="到"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
v-model="form.taskTime"
|
||||
v-model="taskTime"
|
||||
@update:model-value="
|
||||
(val) => {
|
||||
if (val.length > 0) {
|
||||
form.taskTime = val.join(' - ');
|
||||
}
|
||||
}
|
||||
"
|
||||
type="daterange"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
@@ -93,6 +100,7 @@ const form = ref({
|
||||
remindTime: '', // 提醒时间
|
||||
planId: '' // 计划路线id
|
||||
});
|
||||
const taskTime = ref([]);
|
||||
const rules = ref({
|
||||
taskName: [{ required: true, message: '请输入巡检任务名称', trigger: 'blur' }],
|
||||
taskTime: [{ required: true, message: '请选择巡检任务时间', trigger: 'blur' }],
|
||||
@@ -134,10 +142,11 @@ async function init() {
|
||||
id: res.data.id,
|
||||
taskName: res.data.taskName, // 巡检计划名称
|
||||
inspectorId: res.data.inspectorId, // 巡检人员
|
||||
taskTime: res.data.taskTime, // 巡检人员
|
||||
taskTime: '', // 巡检人员
|
||||
remindTime: res.data.remindTime, // 提醒时间
|
||||
planId: res.data.planId // 计划路线id
|
||||
};
|
||||
taskTime.value = res.data.taskTime ? res.data.taskTime.split(' - ') : [];
|
||||
checkoutUserlist.value = Array.isArray(res.data.inspectorInfo) ? res.data.inspectorInfo : [res.data.inspectorInfo];
|
||||
handlChangeMap(res.data.planId);
|
||||
});
|
||||
@@ -239,11 +248,13 @@ function handleRoute(route: RouteVO) {
|
||||
maploading.value = false;
|
||||
}
|
||||
|
||||
const aloaderkey = import.meta.env.VITE_GCJ02_KEY_GD;
|
||||
const VITE_GCJ02_JS_CODE_GD = import.meta.env.VITE_GCJ02_JS_CODE_GD;
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
window._AMapSecurityConfig = { securityJsCode: '09534b3534d8da53968529a9ce164118' };
|
||||
window._AMapSecurityConfig = { securityJsCode: VITE_GCJ02_JS_CODE_GD };
|
||||
AMapLoader.load({
|
||||
key: '8e302fe1be5f4db62bc734db23dca149',
|
||||
key: aloaderkey,
|
||||
version: '2.0',
|
||||
plugins: ['AMap.Scale', 'AMap.Marker']
|
||||
}).then(async (AMap) => {
|
||||
@@ -258,6 +269,11 @@ onMounted(async () => {
|
||||
});
|
||||
const formRef = ref();
|
||||
function submit() {
|
||||
if (taskTime.value.length > 0) {
|
||||
form.value.taskTime = taskTime.value.join(' - ');
|
||||
} else {
|
||||
form.value.taskTime = '';
|
||||
}
|
||||
form.value.inspectorId = checkoutUserlist.value.map((item) => item.userId).join(',');
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
|
||||
@@ -63,11 +63,6 @@
|
||||
<el-table-column label="巡检任务名称" align="center" prop="taskName" />
|
||||
<el-table-column label="巡检人员" align="center" prop="inspectorName" />
|
||||
<el-table-column label="起止日期" align="center" prop="taskTime" />
|
||||
<el-table-column label="巡检设置" align="center" prop="inspectSetting">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_inspection_plan_setting" :value="scope.row.inspectSetting"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_inspection_task_status" :value="scope.row.status"></dict-tag>
|
||||
@@ -78,7 +73,7 @@
|
||||
<dict-tag :options="com_inspection_remind_tiime" :value="scope.row.remindTime"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关联巡检计划" align="center" prop="planId" />
|
||||
<el-table-column label="关联巡检计划" align="center" prop="planName" />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['system:task:edit']">编辑</el-button>
|
||||
@@ -99,7 +94,6 @@ import { checkPermi } from '@/utils/permission';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_inspection_task_status } = toRefs<any>(proxy?.useDict('com_inspection_task_status'));
|
||||
const { com_inspection_plan_setting } = toRefs<any>(proxy?.useDict('com_inspection_plan_setting'));
|
||||
const { com_inspection_remind_tiime } = toRefs<any>(proxy?.useDict('com_inspection_remind_tiime'));
|
||||
const router = useRouter();
|
||||
const taskList = ref<TaskVO[]>([]);
|
||||
@@ -143,16 +137,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询巡检任务列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listTask(queryParams.value);
|
||||
taskList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset();
|
||||
dialog.visible = false;
|
||||
listTask(queryParams.value)
|
||||
.then((res) => {
|
||||
taskList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 表单重置 */
|
||||
@@ -189,27 +181,11 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: TaskVO) => {
|
||||
const _ids = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/inspection/editTask',
|
||||
query: {
|
||||
id: row.id
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
taskFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (form.value.id) {
|
||||
await updateTask(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await addTask(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -223,17 +199,6 @@ const handleDelete = async (row?: TaskVO) => {
|
||||
await getList();
|
||||
};
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
proxy?.download(
|
||||
'system/task/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`task_${new Date().getTime()}.xlsx`
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
|
||||
@@ -77,10 +77,14 @@ const { queryParams } = toRefs(data);
|
||||
const getList = async () => {
|
||||
queryParams.value.statDate = starDate.value.join('-');
|
||||
loading.value = true;
|
||||
const res = await listItem(queryParams.value);
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listItem(queryParams.value)
|
||||
.then((res) => {
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
ref="menuTableRef"
|
||||
v-loading="loading"
|
||||
@@ -284,7 +283,7 @@
|
||||
:check-strictly="false"
|
||||
empty-text="加载中,请稍候"
|
||||
:default-expanded-keys="[0]"
|
||||
:props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
|
||||
:props="{ value: 'menuId', label: 'menuName', children: 'children' }"
|
||||
/>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div class="p-2 flex flex-col h-full">
|
||||
<pageheader></pageheader>
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
@@ -8,9 +8,9 @@
|
||||
<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="createByName">
|
||||
<!-- <el-form-item label="操作人员" prop="createByName">
|
||||
<el-input v-model="queryParams.createByName" placeholder="请输入操作人员" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="类型" prop="noticeType">
|
||||
<el-select v-model="queryParams.noticeType" placeholder="公告类型" clearable>
|
||||
<el-option v-for="dict in sys_notice_type" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
@@ -25,30 +25,37 @@
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card shadow="hover">
|
||||
<el-card shadow="hover" class="flex-1">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button v-hasPermi="['system:notice:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button v-hasPermi="['system:notice:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
|
||||
>修改</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button v-hasPermi="['system:notice:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
|
||||
删除
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
|
||||
<right-toolbar
|
||||
:disable-delete="multiple"
|
||||
:disable-edit="single"
|
||||
:show-add="checkPermi(['system:notice:add'])"
|
||||
:show-edit="checkPermi(['system:notice:edit'])"
|
||||
:show-delete="checkPermi(['system:notice:remove'])"
|
||||
@update:add="handleAdd"
|
||||
@update:edit="handleUpdate()"
|
||||
@update:delete="handleDelete()"
|
||||
></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" border :data="noticeList" @selection-change="handleSelectionChange">
|
||||
<el-table
|
||||
:default-sort="{ prop: 'createTime', order: 'descending' }"
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="noticeList"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column v-if="false" label="序号" align="center" prop="noticeId" width="100" />
|
||||
<el-table-column label="公告标题" align="center" prop="noticeTitle" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="公告标题" align="center" prop="noticeTitle" width="300" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="内容" align="center" prop="noticeContent">
|
||||
<template #default="scope">
|
||||
<div v-html="scope.row.noticeContent" class="noticeBox"></div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="公告类型" align="center" prop="noticeType" width="100">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_notice_type" :value="scope.row.noticeType" />
|
||||
@@ -59,20 +66,16 @@
|
||||
<dict-tag :options="sys_notice_status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建者" align="center" prop="createByName" width="100" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="100">
|
||||
<!-- <el-table-column label="创建者" align="center" prop="createByName" width="100" /> -->
|
||||
<el-table-column label="创建时间" sortable align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ proxy.parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
||||
<span>{{ scope.row.createTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<el-table-column label="操作" width="400" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button v-hasPermi="['system:notice:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button v-hasPermi="['system:notice:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
|
||||
</el-tooltip>
|
||||
<el-button v-hasPermi="['system:notice:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-button v-hasPermi="['system:notice:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -122,6 +125,7 @@
|
||||
<script setup name="Notice" lang="ts">
|
||||
import { listNotice, getNotice, delNotice, addNotice, updateNotice } from '@/api/system/notice';
|
||||
import { NoticeForm, NoticeQuery, NoticeVO } from '@/api/system/notice/types';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict('sys_notice_status', 'sys_notice_type'));
|
||||
@@ -172,10 +176,14 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
/** 查询公告列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listNotice(queryParams.value);
|
||||
noticeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listNotice(queryParams.value)
|
||||
.then((res) => {
|
||||
noticeList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
@@ -242,3 +250,14 @@ onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
|
||||
.noticeBox {
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div class="p-2 h-full flex flex-col">
|
||||
<pageheader></pageheader>
|
||||
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
@@ -38,7 +38,7 @@
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card shadow="hover">
|
||||
<el-card shadow="hover" class="flex-1">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
@@ -332,3 +332,9 @@ onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="车位类型" prop="type">
|
||||
<el-radio-group v-model="form.type">
|
||||
<el-radio v-for="dict in com_parking_type" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-select v-model="form.type">
|
||||
<el-option v-for="dict in com_parking_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
@@ -52,10 +52,44 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="持有人类型" prop="contactType">
|
||||
<el-radio-group v-model="form.contactType">
|
||||
<el-radio :value="1">业主</el-radio>
|
||||
<el-radio :value="0">非业主</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="form.contactType === 0">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="联系人名称" prop="contactName">
|
||||
<el-input v-model.trim="form.contactName"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="联系人电话" prop="contactPhone">
|
||||
<el-input v-model.trim="form.contactPhone"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-else>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="持有人" prop="residentId">
|
||||
<!-- 公共组件 持有人 -->
|
||||
<Holder :userid="form.residentId" @change="handleChange"></Holder>
|
||||
<Holder :isMultiple="false" :userid="form.residentId ?? ''" ref="HolderRef" @change="handleChange">
|
||||
<template #default>
|
||||
<div class="residentBox" @click="choiceResidentFun">
|
||||
<div class="defaultbox" v-if="form.residentId == null || form.residentId === ''">
|
||||
<span>请选择</span>
|
||||
<el-icon><Search /></el-icon>
|
||||
</div>
|
||||
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
|
||||
<span>姓名:{{ form?.residentName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Holder>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -82,6 +116,7 @@ import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addParking, getParking, updateParking } from '@/api/system/parking';
|
||||
import { listArea } from '@/api/system/carArea';
|
||||
import { validator } from '@/utils/Reg';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_parking_type } = toRefs<any>(proxy?.useDict('com_parking_type'));
|
||||
@@ -98,17 +133,37 @@ const form = ref({
|
||||
parkingFloor: null, // 车位楼层
|
||||
type: '0', // 车位类型
|
||||
residentId: '', // 住户id
|
||||
residentName: '', // 住户名
|
||||
parkingStatus: '', // 车位状态
|
||||
remark: '', // 备注
|
||||
parkingCode: '' // 车位编码
|
||||
parkingCode: '', // 车位编码
|
||||
|
||||
contactName: '', // 联系人名称
|
||||
contactPhone: '', // 联系人手机
|
||||
contactType: 1 // 联系人类型 0 非业主 1 业主
|
||||
});
|
||||
const rules = ref({
|
||||
areaId: [{ required: true, message: '请选择车位区域', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '请选择车位类型', trigger: 'blur' }],
|
||||
parkingCode: [{ required: true, message: '请输入车位编号', trigger: 'blur' }]
|
||||
parkingCode: [{ required: true, message: '请输入车位编号', trigger: 'blur' }],
|
||||
residentId: [{ required: true, message: '请选择持有人', trigger: 'blur' }],
|
||||
contactPhone: [
|
||||
{ required: true, message: '请输入联系人电话', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (!validator(value, 'phone')) {
|
||||
callback(new Error('请输入正确的手机号码'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
contactName: [{ required: true, message: '请输入联系人名称', trigger: 'blur' }]
|
||||
});
|
||||
|
||||
const userid = ref(null);
|
||||
const HolderRef = ref<typeof Holder>(null);
|
||||
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
@@ -131,23 +186,39 @@ const getAreaList = async () => {
|
||||
getAreaList();
|
||||
|
||||
const holderInfo = ref(null);
|
||||
function choiceResidentFun() {
|
||||
if (form.value.residentId) {
|
||||
HolderRef.value.open([...form.value.residentId]);
|
||||
} else {
|
||||
HolderRef.value.open([]);
|
||||
}
|
||||
}
|
||||
function handleChange(pop) {
|
||||
holderInfo.value = null;
|
||||
holderInfo.value = pop;
|
||||
console.log(pop);
|
||||
form.value.residentId = '';
|
||||
form.value.residentName = '';
|
||||
if (pop !== null) {
|
||||
form.value.residentId = holderInfo.value.id;
|
||||
form.value.residentName = holderInfo.value.name;
|
||||
}
|
||||
}
|
||||
|
||||
// !== 提交 =============================================================================
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
console.log(form.value);
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
console.log(valid);
|
||||
if (valid) {
|
||||
form.value.residentId = holderInfo.value;
|
||||
if (userid.value) {
|
||||
updateParking(form.value).then((res) => {
|
||||
updateParking(form.value).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
cancelForm();
|
||||
});
|
||||
} else {
|
||||
addParking(form.value).then((res) => {
|
||||
addParking(form.value).then(() => {
|
||||
ElMessage.success('添加成功');
|
||||
cancelForm();
|
||||
});
|
||||
@@ -206,4 +277,21 @@ const cancelForm = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
.residentBox {
|
||||
width: 385px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
.defaultbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #f4f8ff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -77,15 +77,21 @@
|
||||
<el-table-column label="持有人" align="center" prop="residentName" />
|
||||
<el-table-column label="审核状态" align="center" prop="checkStatus">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="com_review" :value="scope.row.checkStatus" />
|
||||
<dict-tag :options="com_review" :value="scope.row.checkStatus ?? '0'" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="180" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" v-if="scope.row.checkStatus === '0'" @click="handleMain(scope.row)" v-hasPermi="['parking:parking:query']"
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
v-if="scope.row.checkStatus === '0'"
|
||||
@click="handleReview(scope.row)"
|
||||
v-hasPermi="['parking:parking:query']"
|
||||
>审核</el-button
|
||||
>
|
||||
<el-button link type="primary" v-else @click="handleMain(scope.row)">详情</el-button>
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['parking:parking:edit']">编辑</el-button>
|
||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['parking:parking:remove']">删除</el-button>
|
||||
</template>
|
||||
@@ -99,7 +105,7 @@
|
||||
|
||||
<script setup name="Parking" lang="ts">
|
||||
import Pageheader from '@/components/Pageheader/index.vue';
|
||||
import { listParking, getParking, delParking, addParking, updateParking } from '@/api/system/parking/index';
|
||||
import { listParking, delParking } from '@/api/system/parking/index';
|
||||
import { ParkingVO, ParkingQuery, ParkingForm } from '@/api/system/parking/type';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
|
||||
@@ -122,14 +128,14 @@ const queryFormRef = ref<ElFormInstance>();
|
||||
const initFormData: ParkingForm = {
|
||||
id: undefined,
|
||||
areaId: undefined,
|
||||
parkingCode: undefined,
|
||||
parkingCode: '',
|
||||
parkingArea: undefined,
|
||||
parkingStatus: undefined,
|
||||
parkingStatus: '',
|
||||
type: undefined,
|
||||
residentId: undefined,
|
||||
addTime: undefined,
|
||||
addBy: undefined,
|
||||
checkStatus: undefined,
|
||||
checkStatus: '',
|
||||
remark: undefined,
|
||||
createBy: undefined,
|
||||
createTime: undefined,
|
||||
@@ -158,17 +164,16 @@ const AreaList = ref([]);
|
||||
/** 查询车位管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listParking(queryParams.value);
|
||||
parkingList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listParking(queryParams.value)
|
||||
.then((res) => {
|
||||
parkingList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
function getAreaInfoById(id: string) {
|
||||
const obj = AreaList.value.find((item) => item.id === id);
|
||||
return `${obj.areaName}${obj.areaCode}`;
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
@@ -197,7 +202,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ParkingVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row ? row.id : ids.value[0];
|
||||
router.push({
|
||||
path: '/carArea/editParking',
|
||||
query: {
|
||||
@@ -206,6 +211,15 @@ const handleUpdate = async (row?: ParkingVO) => {
|
||||
});
|
||||
};
|
||||
/** 审核按钮操作 */
|
||||
const handleReview = async (row?: ParkingVO) => {
|
||||
router.push({
|
||||
path: '/carArea/parkingReview',
|
||||
query: {
|
||||
id: row.id
|
||||
}
|
||||
});
|
||||
};
|
||||
/** 车位审核 */
|
||||
const handleMain = async (row?: ParkingVO) => {
|
||||
router.push({
|
||||
path: '/carArea/parkMain',
|
||||
@@ -217,7 +231,7 @@ const handleMain = async (row?: ParkingVO) => {
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: ParkingVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
const _ids = row ? row.id : ids.value;
|
||||
await proxy?.$modal.confirm('该信息删除后无法恢复,确定要删除吗?').finally(() => (loading.value = false));
|
||||
await delParking(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="ResidentMainBox p-2 w-full h-full">
|
||||
<PageHeader title="车位详情"></PageHeader>
|
||||
<PageHeader></PageHeader>
|
||||
<div class="ResidentMainBody">
|
||||
<el-row :span="24" :gutter="20">
|
||||
<el-col :span="16">
|
||||
<el-col :span="24">
|
||||
<!-- 车位信息 -->
|
||||
<div class="mb-10">
|
||||
<el-card>
|
||||
@@ -43,7 +43,12 @@
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">持有人:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.residentId }}</div>
|
||||
<div class="main">
|
||||
<span>
|
||||
{{ parkingReviewinfo.parking.residentName }}
|
||||
</span>
|
||||
<el-button type="primary" link style="font-size: smaller">详情</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">添加时间:</div>
|
||||
@@ -123,71 +128,6 @@
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<div class="">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-full flex mt-2">
|
||||
<div class="title">审批意见</div>
|
||||
<div class="preivewBodybox flex-1 ml-5">
|
||||
<el-input v-model="form.propertyReviewFeedback" type="textarea" :rows="5"></el-input>
|
||||
<div class="actions mt-5">
|
||||
<el-button :disabled="!Boolean(parkingReviewinfo.car && parkingReviewinfo.parking.id)" type="primary" @click="handlePreivew(1)"
|
||||
>审核通过</el-button
|
||||
>
|
||||
<el-button :disabled="!Boolean(parkingReviewinfo.car && parkingReviewinfo.parking.id)" type="danger" @click="handlePreivew(0)"
|
||||
>审核不通过</el-button
|
||||
>
|
||||
<el-button @click="handlBacK">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card style="position: relative" class="h-full">
|
||||
<template #header>
|
||||
<div class="asideCardHeader w-full h-full">
|
||||
<div class="cardSubtitle">
|
||||
<div class="line"></div>
|
||||
<div class="subtitle">审批流程</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-50%">
|
||||
<el-steps space="200px" direction="vertical" :active="activeStop">
|
||||
<el-step :description="parkingReviewinfo.parkingReviewProcess.submitTime">
|
||||
<template #title>
|
||||
<span v-if="active === 0">未提交信息</span>
|
||||
<span v-if="active >= 1">已提交信息</span>
|
||||
</template>
|
||||
</el-step>
|
||||
<el-step :description="parkingReviewinfo.parkingReviewProcess.propertyTime">
|
||||
<template #title>
|
||||
<span v-if="active <= 2">待审核</span>
|
||||
<span v-if="active === 3">物业审核不通过</span>
|
||||
<span v-if="active >= 4">物业审核通过</span>
|
||||
</template>
|
||||
</el-step>
|
||||
<el-step :description="parkingReviewinfo.parkingReviewProcess.certificationTime">
|
||||
<template #title>
|
||||
<span v-if="active <= 5">未认证</span>
|
||||
<span v-if="active === 6">已认证</span>
|
||||
</template>
|
||||
</el-step>
|
||||
<el-step>
|
||||
<template #title>
|
||||
<span v-if="active <= 5">审核未完成</span>
|
||||
<span v-else>审核完成</span>
|
||||
</template>
|
||||
</el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
@@ -205,23 +145,22 @@ const { com_parking_type } = toRefs<any>(proxy?.useDict('com_parking_type'));
|
||||
/** 住户审核状态 */
|
||||
enum reviewStatus {
|
||||
/** 未提交 */
|
||||
unSubmit = 0,
|
||||
unSubmit = '0',
|
||||
/** 已提交 */
|
||||
Submited = 1,
|
||||
Submited = '1',
|
||||
/** 待认证 */
|
||||
awaitReview = 2,
|
||||
awaitReview = '2',
|
||||
/** 认证不通过 */
|
||||
unReviewPass = 3,
|
||||
unReviewPass = '3',
|
||||
/** 认证通过 */
|
||||
ReviewPass = 4,
|
||||
ReviewPass = '4',
|
||||
/** 未认证 */
|
||||
uncertification = 5,
|
||||
uncertification = '5',
|
||||
/** 已认证 */
|
||||
Certification = 6
|
||||
Certification = '6'
|
||||
}
|
||||
type activeType = reviewStatus;
|
||||
|
||||
const active = ref<activeType>(0);
|
||||
const active = ref(0);
|
||||
const activeStop = ref(0);
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
@@ -319,18 +258,18 @@ function handleActivestaus(rews) {
|
||||
activeStop.value = 1;
|
||||
// 待认证
|
||||
if (rews.propertyStatus === 0) {
|
||||
active.value = reviewStatus.awaitReview;
|
||||
active.value = 2;
|
||||
} else if (rews.propertyStatus === 1) {
|
||||
active.value = reviewStatus.unReviewPass;
|
||||
active.value = 3;
|
||||
} else if (rews.propertyStatus === 2) {
|
||||
active.value = reviewStatus.ReviewPass;
|
||||
active.value = 4;
|
||||
activeStop.value = 2;
|
||||
|
||||
// 审核
|
||||
if (rews.certificationStatus === 0) {
|
||||
active.value = reviewStatus.uncertification;
|
||||
active.value = 5;
|
||||
} else if (rews.certificationStatus === 1) {
|
||||
active.value = reviewStatus.Certification;
|
||||
active.value = 6;
|
||||
activeStop.value = 4;
|
||||
}
|
||||
}
|
||||
|
||||
410
src/views/system/parking/parkReview.vue
Normal file
410
src/views/system/parking/parkReview.vue
Normal file
@@ -0,0 +1,410 @@
|
||||
<template>
|
||||
<div class="ResidentMainBox p-2 w-full h-full">
|
||||
<PageHeader></PageHeader>
|
||||
<div class="ResidentMainBody">
|
||||
<el-row :span="24" :gutter="20">
|
||||
<el-col :span="16">
|
||||
<!-- 车位信息 -->
|
||||
<div class="mb-10">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>车位信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-full CarinfoBox gridbox">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">区域:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.areaName }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车位编号:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.parkingCode }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车位面积:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.parkingArea }} ㎡</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">楼层:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.parkingFloor }} 层</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车位类型:</div>
|
||||
<div class="main">
|
||||
<dict-tag :options="com_parking_type" :value="parkingReviewinfo.parking.type" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车位状态:</div>
|
||||
<div class="main">
|
||||
<DictTag :options="com_parking_status" :value="parkingReviewinfo.parking.parkingStatus"></DictTag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">持有人:</div>
|
||||
<div class="main">
|
||||
<span>
|
||||
{{ parkingReviewinfo.parking.residentName }}
|
||||
</span>
|
||||
<el-button type="primary" link style="font-size: smaller">详情</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">添加时间:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.createTime }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">添加人:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.createName }}</div>
|
||||
</div>
|
||||
<div class="carinfo_item">
|
||||
<div class="label">备注:</div>
|
||||
<div class="main">{{ parkingReviewinfo.parking.remark }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<!-- 车辆信息 -->
|
||||
<div class="mb-10">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>车辆信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-full CarinfoBox" v-if="parkingReviewinfo.car">
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车牌号:</div>
|
||||
<div class="main">浙B·N6688</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车辆品牌:</div>
|
||||
<div class="main">宝马</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车辆型号</div>
|
||||
<div class="main">X5</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="mt-30px mb-30px">
|
||||
<el-col :span="8">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">车身颜色:</div>
|
||||
<div class="main">白色</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="carinfo_item">
|
||||
<div class="label">备注:</div>
|
||||
<div class="main">无</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8"> </el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<div class="carinfo_item flex-items-start">
|
||||
<div class="label">车辆照片:</div>
|
||||
<div class="main">
|
||||
<el-image
|
||||
class="carinfoImage"
|
||||
src="https://ts1.tc.mm.bing.net/th?id=ORMS.76ee9c7ea9fe203b608f9048f54b3cbd&pid=Wdp&w=268&h=140&qlt=90&c=1&rs=1&dpr=1&p=0"
|
||||
></el-image>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="w-full h-full CarinfoBox flex flex-center min-h-17rem" v-else>
|
||||
<span style="color: #999; font-weight: 500; font-size: larger; letter-spacing: 10px">暂无信息</span>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<div class="">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-full flex mt-2">
|
||||
<div class="title">审批意见</div>
|
||||
<div class="preivewBodybox flex-1 ml-5">
|
||||
<el-input v-model="form.propertyReviewFeedback" type="textarea" :rows="5"></el-input>
|
||||
<div class="actions mt-5">
|
||||
<el-button :disabled="!Boolean(parkingReviewinfo.car && parkingReviewinfo.parking.id)" type="primary" @click="handlePreivew(1)"
|
||||
>审核通过</el-button
|
||||
>
|
||||
<el-button :disabled="!Boolean(parkingReviewinfo.car && parkingReviewinfo.parking.id)" type="danger" @click="handlePreivew(0)"
|
||||
>审核不通过</el-button
|
||||
>
|
||||
<el-button @click="handlBacK">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card style="position: relative" class="h-full">
|
||||
<template #header>
|
||||
<div class="asideCardHeader w-full h-full">
|
||||
<div class="cardSubtitle">
|
||||
<div class="line"></div>
|
||||
<div class="subtitle">审批流程</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-50%">
|
||||
<el-steps space="200px" direction="vertical" :active="activeStop">
|
||||
<el-step :description="parkingReviewinfo.parkingReviewProcess.submitTime">
|
||||
<template #title>
|
||||
<span v-if="active === 0">未提交信息</span>
|
||||
<span v-if="active >= 1">已提交信息</span>
|
||||
</template>
|
||||
</el-step>
|
||||
<el-step :description="parkingReviewinfo.parkingReviewProcess.propertyTime">
|
||||
<template #title>
|
||||
<span v-if="active <= 2">待审核</span>
|
||||
<span v-if="active === 3">物业审核不通过</span>
|
||||
<span v-if="active >= 4">物业审核通过</span>
|
||||
</template>
|
||||
</el-step>
|
||||
<el-step :description="parkingReviewinfo.parkingReviewProcess.certificationTime">
|
||||
<template #title>
|
||||
<span v-if="active <= 5">未认证</span>
|
||||
<span v-if="active === 6">已认证</span>
|
||||
</template>
|
||||
</el-step>
|
||||
<el-step>
|
||||
<template #title>
|
||||
<span v-if="active <= 5">审核未完成</span>
|
||||
<span v-else>审核完成</span>
|
||||
</template>
|
||||
</el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { getParkingReview, getParkingReviewInfo } from '@/api/system/parking';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_parking_status } = toRefs<any>(proxy?.useDict('com_parking_status'));
|
||||
const { com_parking_type } = toRefs<any>(proxy?.useDict('com_parking_type'));
|
||||
|
||||
/** 住户审核状态 */
|
||||
enum reviewStatus {
|
||||
/** 未提交 */
|
||||
unSubmit = '0',
|
||||
/** 已提交 */
|
||||
Submited = '1',
|
||||
/** 待认证 */
|
||||
awaitReview = '2',
|
||||
/** 认证不通过 */
|
||||
unReviewPass = '3',
|
||||
/** 认证通过 */
|
||||
ReviewPass = '4',
|
||||
/** 未认证 */
|
||||
uncertification = '5',
|
||||
/** 已认证 */
|
||||
Certification = '6'
|
||||
}
|
||||
|
||||
const active = ref(0);
|
||||
const activeStop = ref(0);
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const id = ref('');
|
||||
|
||||
type parkingReviewType = {
|
||||
parking: {
|
||||
id: string;
|
||||
areaId: string;
|
||||
areaName: string;
|
||||
villageId: string;
|
||||
villageName: string;
|
||||
parkingCode: string;
|
||||
parkingArea: any;
|
||||
parkingStatus: string;
|
||||
type: string;
|
||||
residentId: any;
|
||||
residentName: any;
|
||||
parkingFloor: string;
|
||||
createName: string;
|
||||
checkStatus: string;
|
||||
remark: string;
|
||||
createTime: string;
|
||||
delFlag: any;
|
||||
};
|
||||
car: any;
|
||||
parkingReviewProcess: {
|
||||
submitStatus: null;
|
||||
propertyStatus: null;
|
||||
certificationStatus: null;
|
||||
submitTime: string;
|
||||
propertyTime: string;
|
||||
certificationTime: string;
|
||||
};
|
||||
};
|
||||
|
||||
const parkingReviewinfo = ref<parkingReviewType>({
|
||||
parking: {
|
||||
'id': '',
|
||||
'areaId': '',
|
||||
'areaName': '',
|
||||
'villageId': '',
|
||||
'villageName': '',
|
||||
'parkingCode': '',
|
||||
'parkingArea': null,
|
||||
'parkingStatus': '',
|
||||
'type': '',
|
||||
'residentId': null,
|
||||
'residentName': null,
|
||||
'parkingFloor': '',
|
||||
'createName': '',
|
||||
'checkStatus': '',
|
||||
'remark': '',
|
||||
'createTime': '',
|
||||
'delFlag': null
|
||||
},
|
||||
car: null,
|
||||
parkingReviewProcess: {
|
||||
submitStatus: null,
|
||||
propertyStatus: null,
|
||||
certificationStatus: null,
|
||||
submitTime: null,
|
||||
propertyTime: null,
|
||||
certificationTime: null
|
||||
}
|
||||
});
|
||||
|
||||
const form = ref({
|
||||
propertyReviewFeedback: '',
|
||||
propertyStatus: '0'
|
||||
});
|
||||
function getInfo() {
|
||||
if (route.query.id) {
|
||||
id.value = route.query.id as string;
|
||||
getParkingReviewInfo(id.value).then((res) => {
|
||||
parkingReviewinfo.value = res.data;
|
||||
handleActivestaus(res.data.parkingReviewProcess);
|
||||
});
|
||||
}
|
||||
}
|
||||
getInfo();
|
||||
|
||||
function handleActivestaus(rews) {
|
||||
if (!rews) {
|
||||
activeStop.value = 0;
|
||||
active.value = 0;
|
||||
return;
|
||||
}
|
||||
// 提交
|
||||
if (rews.submitStatus === reviewStatus.unSubmit) {
|
||||
activeStop.value = 0;
|
||||
active.value = 0;
|
||||
} else if (rews.submitStatus === reviewStatus.Submited) {
|
||||
active.value = 1;
|
||||
activeStop.value = 1;
|
||||
// 待认证
|
||||
if (rews.propertyStatus === 0) {
|
||||
active.value = 2;
|
||||
} else if (rews.propertyStatus === 1) {
|
||||
active.value = 3;
|
||||
} else if (rews.propertyStatus === 2) {
|
||||
active.value = 4;
|
||||
activeStop.value = 2;
|
||||
|
||||
// 审核
|
||||
if (rews.certificationStatus === 0) {
|
||||
active.value = 5;
|
||||
} else if (rews.certificationStatus === 1) {
|
||||
active.value = 6;
|
||||
activeStop.value = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 审核状态
|
||||
// 物业审核状态 0 待审核 1审核通过 2审核未通过
|
||||
function handlePreivew(status: number) {
|
||||
getParkingReview({
|
||||
...form.value,
|
||||
propertyStatus: status,
|
||||
id: id.value
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
}
|
||||
function handlBacK() {
|
||||
router.back();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ResidentMainBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.ResidentMainBody {
|
||||
flex: 1;
|
||||
margin-top: 20px;
|
||||
.CarinfoBox {
|
||||
&.gridbox {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-rows: repeat(4, 1fr);
|
||||
gap: 20px;
|
||||
row-gap: 40px;
|
||||
}
|
||||
.carinfo_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
.label {
|
||||
font-weight: 600;
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.carinfoImage {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&: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>
|
||||
@@ -1,209 +0,0 @@
|
||||
<template>
|
||||
<div class="AddBuildingBox">
|
||||
<PageHeader :title="userid ? '编辑月卡' : '添加月卡'"></PageHeader>
|
||||
<div class="AddBuildingBody">
|
||||
<div class="title">基本信息</div>
|
||||
<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-form-item label="月卡编号" prop="cardCode">
|
||||
<el-input v-model.trim="form.cardCode" placeholder="请输入月卡编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="持卡人姓名" prop="cardName">
|
||||
<el-input v-model.trim="form.cardName" placeholder="请输入持卡人姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="手机号码" prop="phone">
|
||||
<el-input v-model.number="form.phone" placeholder="请输入手机号码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="绑定车牌号" prop="carNum">
|
||||
<el-input v-model.number="form.carNum" placeholder="请输入车牌号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="办理人" prop="handleName">
|
||||
<el-input v-model.number="form.handleName" placeholder="请输入办理人姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="有效日期" prop="phone">
|
||||
<el-date-picker
|
||||
range-separator="到"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
v-model="checkDate"
|
||||
type="daterange"
|
||||
placeholder="选择日期"
|
||||
@change="handlDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="费用" prop="cost">
|
||||
<el-input v-model.number="form.cost" placeholder="请输入费用">
|
||||
<template #suffix>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="支付方式" prop="payMethod">
|
||||
<el-select v-model="form.payMethod" placeholder="请选择支付方式" clearable>
|
||||
<el-option v-for="dict in com_pay_method" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item style="margin-top: 30px">
|
||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||
<el-button @click="cancelForm">返回</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { addMonthCard, getMonthCard, updateMonthCard } from '@/api/system/MonthCard';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method'));
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const formRef = ref();
|
||||
const form = ref({
|
||||
id: null,
|
||||
cardCode: '', // 月卡编号
|
||||
cardName: null, // 持卡人姓名
|
||||
phone: '', // 手机号
|
||||
carNum: null, // 绑定车牌号
|
||||
handleName: '', // 办理人姓名
|
||||
cost: null, // 费用/元
|
||||
payMethod: '', // 支付方式
|
||||
remark: '', // 备注
|
||||
startTime: '', // 开始日期
|
||||
endTime: '' // 结束日期
|
||||
});
|
||||
const checkDate = ref([]);
|
||||
function handlDate() {
|
||||
form.value.startTime = checkDate.value[0];
|
||||
form.value.endTime = checkDate.value[1];
|
||||
}
|
||||
const rules = ref({
|
||||
cardCode: [{ required: true, message: '请输入月卡编号', trigger: 'blur' }],
|
||||
cardName: [{ required: true, message: '请输入持卡人姓名', trigger: 'blur' }],
|
||||
phone: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
|
||||
carNum: [{ required: true, message: '请绑定车牌号', trigger: 'blur' }],
|
||||
startTime: [{ required: true, message: '请选择有效日期', trigger: 'blur' }],
|
||||
payMethod: [{ required: true, message: '请选择支付方式', trigger: 'blur' }],
|
||||
cost: [{ required: true, message: '请输入费用', trigger: 'blur' }]
|
||||
});
|
||||
const userid = ref(null);
|
||||
if (route.query.id) {
|
||||
userid.value = route.query.id;
|
||||
getMonthCard(userid.value).then((res) => {
|
||||
form.value = {
|
||||
...form.value,
|
||||
...res.data
|
||||
};
|
||||
});
|
||||
}
|
||||
// !== 提交 =============================================================================
|
||||
// 提交
|
||||
const submitForm = () => {
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
if (userid.value) {
|
||||
updateMonthCard(form.value).then((res) => {
|
||||
ElMessage.success('编辑成功');
|
||||
cancelForm();
|
||||
});
|
||||
} else {
|
||||
addMonthCard(form.value).then((res) => {
|
||||
ElMessage.success('添加成功');
|
||||
|
||||
cancelForm();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 推出
|
||||
const cancelForm = () => {
|
||||
router.back();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.AddBuildingBox {
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.AddBuildingBody {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
background-color: white;
|
||||
padding: 15px;
|
||||
.title {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding-left: 20px;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
color: rgba(16, 16, 16, 1);
|
||||
border-bottom: 1px solid #bbbbbb;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.formBody {
|
||||
width: 1050px;
|
||||
margin: 0 auto;
|
||||
&:deep(.el-form-item__content, .el-select, .el-input) {
|
||||
width: 350px !important;
|
||||
margin-right: 10px;
|
||||
.el-cascader {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
.el-button {
|
||||
width: 80px;
|
||||
height: 35px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -260,10 +260,14 @@ const handleNodeClick = (data: DeptVO) => {
|
||||
/** 查询岗位列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listPost(queryParams.value);
|
||||
postList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listPost(queryParams.value)
|
||||
.then((res) => {
|
||||
postList.value = res.rows;
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
|
||||
@@ -30,14 +30,14 @@
|
||||
<div class="title_item">住户类型:</div>
|
||||
<DictTag :options="com_resident_relationship" :value="userInfo.type"></DictTag>
|
||||
</div>
|
||||
<div class="userinfo_item">
|
||||
<!-- <div class="userinfo_item">
|
||||
<div class="title_item">住户来源:</div>
|
||||
<span> {{ userInfo.name }} </span>
|
||||
</div>
|
||||
<div class="userinfo_item">
|
||||
</div> -->
|
||||
<!-- <div class="userinfo_item">
|
||||
<div class="title_item">注册时间:</div>
|
||||
<span> {{ userInfo.name }} </span>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="userinfo_item img">
|
||||
<div class="title_item">身份证正面:</div>
|
||||
<div class="userinfo_itme_img">
|
||||
@@ -58,21 +58,19 @@
|
||||
<div class="title_item">证件号码:</div>
|
||||
<span> {{ userInfo.idCard }} </span>
|
||||
</div>
|
||||
<div class="userinfo_item">
|
||||
<div class="title_item">备注:</div>
|
||||
<span> {{ userInfo.remark ?? '无' }} </span>
|
||||
</div>
|
||||
<div class="userinfo_item">
|
||||
<div class="title_item">提交审核时间:</div>
|
||||
<span> 去丽丽 </span>
|
||||
</div>
|
||||
<div class="userinfo_item img">
|
||||
<div class="title_item">身份证背面:</div>
|
||||
<div class="userinfo_itme_img">
|
||||
<el-image class="w-full h-full" fit="fill" :src="`/${userInfo.cardImageFront}`"></el-image>
|
||||
<el-image class="w-full h-full" fit="fill" :src="userInfo.cardImageBack"></el-image>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="userinfo_item">
|
||||
<div class="title_item">备注:</div>
|
||||
<span> {{ userInfo.remark ?? '无' }} </span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
@@ -143,7 +141,6 @@ 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 { splitImages } from '@/utils';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { com_review } = toRefs<any>(proxy?.useDict('com_review'));
|
||||
@@ -156,6 +153,7 @@ const userInfo = ref<ResidentVO>({
|
||||
villageId: '',
|
||||
buildingId: '',
|
||||
userId: null,
|
||||
nickName: '',
|
||||
'id': null,
|
||||
'name': '',
|
||||
'type': null,
|
||||
@@ -270,9 +268,7 @@ function update() {
|
||||
}
|
||||
const router = useRouter();
|
||||
function backRoute() {
|
||||
router.push({
|
||||
path: '/house/resident'
|
||||
});
|
||||
router.back();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="与业主的关系" prop="type">
|
||||
<el-select v-model.number="form.type" class="m-2" placeholder="请选择">
|
||||
<el-form-item label="与业主的关系" prop="ownerRelationship">
|
||||
<el-select v-model="form.ownerRelationship" class="m-2" placeholder="请选择">
|
||||
<el-option v-for="item in com_resident_relationship" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -127,7 +127,7 @@ const form = ref<ResidentForm>({
|
||||
name: '',
|
||||
gender: '0',
|
||||
idCard: '',
|
||||
type: '0', // 与业主关系 0业主
|
||||
ownerRelationship: '0', // 与业主关系
|
||||
phone: null, //手机号
|
||||
cardImageFront: '',
|
||||
cardImageBack: '',
|
||||
@@ -148,7 +148,7 @@ const rules = ref({
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
type: [{ required: true, message: '请选择与业主关系', trigger: 'blur' }],
|
||||
ownerRelationship: [{ required: true, message: '请选择与业主关系', trigger: 'blur' }],
|
||||
phone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||
{
|
||||
@@ -199,6 +199,10 @@ const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) =>
|
||||
}
|
||||
};
|
||||
const handleAvatar2Success: UploadProps['onSuccess'] = (response, uploadFile) => {
|
||||
if (response.code === 500 && response.msg == '不允许重复提交,请稍候再试') {
|
||||
ElMessage.error('上传频率过快,稍后再试');
|
||||
return;
|
||||
}
|
||||
if (response.data && response.data.url) {
|
||||
form.value.cardImageBack = response.data.url;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<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">
|
||||
<el-form-item label="住户类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请输入住户类型" style="width: 240px">
|
||||
<el-form ref="queryFormRef" label-width="120" label-position="left" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
||||
<el-form-item label="与主业主关系" prop="ownerRelationship">
|
||||
<el-select v-model="queryParams.ownerRelationship" placeholder="请选择与主业主关系" style="width: 240px">
|
||||
<el-option v-for="item in com_resident_relationship" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -62,12 +62,18 @@
|
||||
<el-table class="tablebox" v-loading="loading" border :data="residentList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="姓名" min-width="120" align="center" prop="name" />
|
||||
<el-table-column label="类型" min-width="120" align="center" prop="type">
|
||||
<el-table-column label="类型" width="100" align="center" prop="type">
|
||||
<template #default="scope">
|
||||
<DictTag :value="scope.row.type" :options="com_resident_relationship"></DictTag>
|
||||
<el-tag v-if="scope.row.type === '0'" type="success">业主</el-tag>
|
||||
<el-tag v-else type="danger">租户</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="120" align="center" prop="status">
|
||||
<el-table-column label="与主业主关系" min-width="120" align="center" prop="ownerRelationship">
|
||||
<template #default="scope">
|
||||
<DictTag :value="scope.row.ownerRelationship" :options="com_resident_relationship"></DictTag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="120" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<DictTag :value="scope.row.status" :options="com_review"></DictTag>
|
||||
</template>
|
||||
@@ -154,7 +160,7 @@ const queryFormRef = ref<ElFormInstance>();
|
||||
const initFormData: ResidentForm = {
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
type: undefined,
|
||||
ownerRelationship: undefined,
|
||||
gender: undefined,
|
||||
idCard: undefined,
|
||||
phone: undefined,
|
||||
@@ -173,63 +179,14 @@ const data = reactive<PageData<ResidentForm, ResidentQuery>>({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
date: '',
|
||||
type: null,
|
||||
ownerRelationship: null,
|
||||
status: null,
|
||||
|
||||
houseId: null,
|
||||
buildingId: null,
|
||||
unitNo: null
|
||||
unitNoId: null
|
||||
}
|
||||
});
|
||||
const disabledDate = (time: Date) => {
|
||||
return time.getTime() > Date.now();
|
||||
};
|
||||
const shortcuts = [
|
||||
{
|
||||
text: '今天',
|
||||
value: new Date()
|
||||
},
|
||||
{
|
||||
text: '昨天',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 1);
|
||||
return date;
|
||||
}
|
||||
},
|
||||
{
|
||||
text: ' 近3天',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 3);
|
||||
return date;
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '最近一周',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 7);
|
||||
return date;
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '最近一个月',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setMonth(date.getMonth() - 1);
|
||||
return date;
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '最近三个月',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setMonth(date.getMonth() - 3); // 真正减3个月,不是90天!
|
||||
return date;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const { queryParams, form } = toRefs(data);
|
||||
|
||||
@@ -245,7 +202,7 @@ const handleNodeClick = (data: Tree, node) => {
|
||||
const obj2 = {
|
||||
[data.type]: data.value
|
||||
};
|
||||
if (data.type === 'unitNo') {
|
||||
if (data.type === 'unitNoId') {
|
||||
obj2[node.parent.data.type] = node.parent.data.value;
|
||||
}
|
||||
queryParams.value = {
|
||||
@@ -253,7 +210,7 @@ const handleNodeClick = (data: Tree, node) => {
|
||||
...{
|
||||
houseId: null,
|
||||
buildingId: null,
|
||||
unitNo: null
|
||||
unitNoId: null
|
||||
},
|
||||
...obj2
|
||||
};
|
||||
@@ -279,14 +236,18 @@ gettree();
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
residentList.value = [];
|
||||
const res = await listResident(queryParams.value);
|
||||
residentList.value = res.rows;
|
||||
residentList.value.forEach((item) => {
|
||||
const arr = getHousePathById(treedata.value, item.houseId, 'label');
|
||||
item.houseAddress = arr.join(' ');
|
||||
});
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
listResident(queryParams.value)
|
||||
.then((res) => {
|
||||
residentList.value = res.rows;
|
||||
residentList.value.forEach((item) => {
|
||||
const arr = getHousePathById(treedata.value, item.houseId, 'label');
|
||||
item.houseAddress = arr.join(' ');
|
||||
});
|
||||
total.value = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
getList();
|
||||
@@ -299,7 +260,7 @@ const handleQuery = () => {
|
||||
...{
|
||||
houseId: null,
|
||||
buildingId: null,
|
||||
unitNo: null
|
||||
unitNoId: null
|
||||
}
|
||||
};
|
||||
getList();
|
||||
@@ -313,7 +274,7 @@ const resetQuery = () => {
|
||||
...{
|
||||
houseId: null,
|
||||
buildingId: null,
|
||||
unitNo: null
|
||||
unitNoId: null
|
||||
}
|
||||
};
|
||||
handleQuery();
|
||||
@@ -335,7 +296,7 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ResidentVO) => {
|
||||
const _id = row.id || ids.value[0];
|
||||
const _id = row?.id || ids.value[0];
|
||||
router.push({
|
||||
path: '/house/editResident',
|
||||
query: {
|
||||
|
||||
@@ -121,11 +121,35 @@ const getMenuTreeselect = async () => {
|
||||
/** 根据角色ID查询菜单树结构 */
|
||||
const getRoleMenuTreeselect = (roleId: string | number) => {
|
||||
return roleMenuTreeselect(roleId).then((res): RoleMenuTree => {
|
||||
console.log(res.data);
|
||||
menuOptions.value = res.data.menus;
|
||||
// const arr = handleHiddeMenu(res.data.menus);
|
||||
// menuOptions.value = arr;
|
||||
return res.data;
|
||||
});
|
||||
};
|
||||
|
||||
function handleHiddeMenu(menu: MenuTreeOption[]) {
|
||||
const arr = [];
|
||||
menu.forEach((item) => {
|
||||
let obj = null;
|
||||
if (item.id !== '2051835471292702721') {
|
||||
obj = {
|
||||
...item,
|
||||
children: []
|
||||
};
|
||||
if (item.children && item.children.length > 0) {
|
||||
obj.children = handleHiddeMenu(item.children);
|
||||
}
|
||||
} else {
|
||||
obj = null;
|
||||
console.log('找到了', item);
|
||||
}
|
||||
if (obj) arr.push(obj);
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
/** 树权限(展开/折叠)*/
|
||||
const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => {
|
||||
if (type == 'menu') {
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Close" @click="handleClose">关闭</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
<el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
|
||||
<el-table ref="roleTableRef" border v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
|
||||
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="200" />
|
||||
<el-table-column label="显示顺序" prop="roleSort" width="100" />
|
||||
<el-table-column label="状态" align="center" width="100">
|
||||
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="显示顺序" prop="roleSort" />
|
||||
<el-table-column label="状态" align="center">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
||||
</template>
|
||||
|
||||
@@ -3,86 +3,103 @@
|
||||
<div class="flex flex-items-center searchBox">
|
||||
<div class="searchLabel">选择日期</div>
|
||||
<el-date-picker
|
||||
v-model="date"
|
||||
v-model="dataTime"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="yyyy-MM-dd"
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD"
|
||||
style="width: 400px; margin-right: 10px"
|
||||
></el-date-picker>
|
||||
<el-button type="primary">查询</el-button>
|
||||
<el-button>重置</el-button>
|
||||
<el-button type="primary" @click="querySearch">查询</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; position: relative; z-index: 2">
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="14" :xl="14">
|
||||
<div class="cardbox">
|
||||
<div>收入来源</div>
|
||||
<div class="card_infoall">
|
||||
<div>应缴费用:{{ formatMoneyWithUnit(form.totalDue) }}</div>
|
||||
<div>已收:{{ formatMoneyWithUnit(form.totalPaid) }}</div>
|
||||
<div>待收:{{ formatMoneyWithUnit(form.totalUnpaid) }}</div>
|
||||
</div>
|
||||
<div class="cardbody" style="height: 165px">
|
||||
<div
|
||||
v-for="(opt, index) in incomeChartOptions"
|
||||
:key="index"
|
||||
class="chart-item flex flex-col items-center"
|
||||
style="width: 165px; height: 100%"
|
||||
>
|
||||
<Echarts :options="opt.options as EChartsOption" style="width: 100%; height: 165px"></Echarts>
|
||||
<!-- 如果需要额外显示名称,可以在这里加 div,但图表中心已显示 -->
|
||||
<div class="chart-item-name">{{ opt.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="14" :xl="14">
|
||||
<div class="cardbox">
|
||||
<div>收入来源</div>
|
||||
<div class="cardbody" style="height: 200px">
|
||||
<div class="flex flex-col flex-items-center flex-1">
|
||||
<Echarts :options="options"></Echarts>
|
||||
<div>停车费</div>
|
||||
</div>
|
||||
<div class="flex flex-col flex-items-center flex-1">
|
||||
<Echarts :options="options"></Echarts>
|
||||
<div>物业费</div>
|
||||
</div>
|
||||
<div class="flex flex-col flex-items-center flex-1">
|
||||
<Echarts :options="options"></Echarts>
|
||||
<div>商铺租金</div>
|
||||
</div>
|
||||
<div class="flex flex-col flex-items-center flex-1">
|
||||
<Echarts :options="options"></Echarts>
|
||||
<div>水电费</div>
|
||||
</div>
|
||||
<div class="flex flex-col flex-items-center flex-1">
|
||||
<Echarts :options="options"></Echarts>
|
||||
<div>维修费</div>
|
||||
<el-col :lg="10" :xl="10">
|
||||
<div class="cardbox">
|
||||
<div>欠费分布</div>
|
||||
<div class="cardbody w-full" style="height: 150px">
|
||||
<Echarts :options="options2"></Echarts>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :lg="10" :xl="8">
|
||||
<div class="cardbox">
|
||||
<div>缴费方式</div>
|
||||
<div class="cardbody w-full" style="height: 150px">
|
||||
<Echarts :options="options2"></Echarts>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; position: relative; z-index: 2">
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="12" :xl="14">
|
||||
<div class="cardbox w-full">
|
||||
<div>欠费分布</div>
|
||||
<div class="cardbody w-full" style="height: 330px">
|
||||
<Echarts :options="options3"></Echarts>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="" style="height: 20px"></div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="14" :xl="14">
|
||||
<div class="cardbox w-full" style="height: 400px">
|
||||
<Echarts :options="options3"></Echarts>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :lg="10" :xl="8">
|
||||
<div class="cardbox w-full" style="height: 400px">
|
||||
<div class="" style="height: 50px; margin-bottom: 20px">缴费方式</div>
|
||||
<div flex flex-items-center justify-center>
|
||||
<ul class="legendbox">
|
||||
<li>小程序</li>
|
||||
<li>物业缴费</li>
|
||||
<li>手机APP</li>
|
||||
</ul>
|
||||
<ul class="circlebox">
|
||||
<li>70%</li>
|
||||
<li>20%</li>
|
||||
<li>10%</li>
|
||||
</ul>
|
||||
</el-col>
|
||||
<el-col :lg="12" :xl="10">
|
||||
<div class="cardbox w-full" style="height: 400px">
|
||||
<div style="height: 50px; margin-bottom: 20px">缴费来源</div>
|
||||
<div flex flex-items-center justify-center>
|
||||
<ul class="legendbox">
|
||||
<li v-for="(item, index) in paytypelist" :key="index">
|
||||
<i
|
||||
:style="{
|
||||
backgroundColor: item.color
|
||||
}"
|
||||
></i>
|
||||
<span class="ml-2">{{ item.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="circlebox">
|
||||
<li :data-level="index" :style="{ backgroundColor: item.color }" v-for="(item, index) in paytypelist" :key="index">
|
||||
{{ item.number }}%
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="" style="height: 20px"></div>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<div class="cardbox w-full" style="height: 450px">
|
||||
<Echarts :options="flowLineOption"></Echarts>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div style="position: relative; z-index: 2">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<!-- <div class="cardbox w-full" style="height: 450px">
|
||||
<Echarts :options="flowLineOption"></Echarts>
|
||||
</div> -->
|
||||
<div class="cardbox w-full">
|
||||
<div>缴费走势分析</div>
|
||||
<div class="cardbody w-full" style="height: 400px">
|
||||
<Echarts :options="flowLineOption"></Echarts>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<Teleport to="body">
|
||||
<i v-if="open" class="bgColor"></i>
|
||||
</Teleport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -90,88 +107,52 @@
|
||||
// TODO 缴费分析
|
||||
import { ref } from 'vue';
|
||||
import Echarts from '@/components/Echarts/index.vue';
|
||||
import { formatMoneyWithUnit } from '@/utils/money';
|
||||
import { EChartsOption } from 'echarts';
|
||||
import { getLast7Days, getLastNDays } from '@/utils/time';
|
||||
import { getLast7Days, getPastDayDate } from '@/utils/time';
|
||||
import { income_statsApi } from '@/api/system/Payment/index';
|
||||
|
||||
const date = ref('');
|
||||
|
||||
/** 入住情况 */
|
||||
const options = shallowRef<EChartsOption>({
|
||||
tooltip: { show: false },
|
||||
series: [
|
||||
// 1. 底层细圆环(灰色底色)
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['60%', '80%'], // 细一点
|
||||
clockwise: true,
|
||||
data: [100],
|
||||
itemStyle: { color: '#ebeef5' },
|
||||
emphasis: { disabled: true },
|
||||
label: { show: false }
|
||||
},
|
||||
// 2. 上层粗圆环(进度条)
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['60%', '85%'], // 粗一点
|
||||
clockwise: true,
|
||||
itemStyle: {
|
||||
color: '#409eff',
|
||||
borderRadius: 10
|
||||
},
|
||||
emphasis: { disabled: true },
|
||||
label: {
|
||||
show: true,
|
||||
position: 'center',
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
formatter: '85%'
|
||||
},
|
||||
data: [{ value: 85 }, { value: 15, itemStyle: { color: 'transparent' } }]
|
||||
}
|
||||
]
|
||||
const open = ref(false);
|
||||
const dataTime = ref('2025-01-01');
|
||||
const form = ref({
|
||||
'totalDue': '',
|
||||
'totalPaid': '',
|
||||
'totalUnpaid': '',
|
||||
'paidPercentage': '',
|
||||
'payWx': null,
|
||||
'payZfb': null,
|
||||
'payOffline': null,
|
||||
'totalPay': null,
|
||||
'feeTypeStats': [],
|
||||
'dailyStats': []
|
||||
});
|
||||
|
||||
/** 入住类型 */
|
||||
const options1 = shallowRef<EChartsOption>({
|
||||
legend: {
|
||||
top: 'center',
|
||||
left: '0',
|
||||
orient: 'vertical',
|
||||
itemGap: 50
|
||||
const defaultDay = 30; // 默认查询近30天数据
|
||||
|
||||
/** 收入来源 */
|
||||
/** 收入来源图表配置 */
|
||||
const incomeChartOptions = ref<
|
||||
{
|
||||
name: string;
|
||||
options?: EChartsOption;
|
||||
}[]
|
||||
>([
|
||||
{
|
||||
'name': '停车费'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['50%', '100%'],
|
||||
avoidLabelOverlap: false,
|
||||
left: '50%',
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
show: false
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: false,
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{ value: 25, name: '业主', itemStyle: { color: '#0a74fe' } },
|
||||
{ value: 25, name: '租户', itemStyle: { color: '#fe3d4e' } },
|
||||
{ value: 25, name: '亲属', itemStyle: { color: '#00cf7f' } },
|
||||
{ value: 25, name: '其他', itemStyle: { color: '#f48e3b' } }
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
{
|
||||
'name': '物业费'
|
||||
},
|
||||
{
|
||||
'name': '水电费'
|
||||
},
|
||||
{
|
||||
'name': '商铺租金'
|
||||
},
|
||||
{
|
||||
'name': '维修费'
|
||||
}
|
||||
]);
|
||||
|
||||
/** 缴费方式 */
|
||||
const options2 = shallowRef<EChartsOption>({
|
||||
@@ -216,60 +197,100 @@ const options2 = shallowRef<EChartsOption>({
|
||||
]
|
||||
});
|
||||
|
||||
// ! 年龄分布 -------------------------------------------------------------------------------------
|
||||
const agesX = ['6岁以下', '6-11岁', '11-14岁', '15-24岁', '25-30岁', '31-40岁', '41-50岁', '51-61岁', '61-65岁', '65-70岁', '70岁以上'];
|
||||
const agesData = [520, 680, 460, 750, 1350, 1860, 1420, 960, 630, 380, 210];
|
||||
// 🔥 关键:灰色背景数据 = 最大值 - 真实数据(互补100%)
|
||||
const maxValue = 2000; // 设定总高度(可自行调整)
|
||||
const middleHeight = 20;
|
||||
const barwidth = '10%';
|
||||
const bgData = agesData.map((item) => maxValue - item - middleHeight);
|
||||
const bgData2 = agesData.map((item) => middleHeight);
|
||||
/** 年龄分布 */
|
||||
// 【新增】定义12个月份
|
||||
const monthX = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
|
||||
/** 欠费分布 散点图 */
|
||||
/** 欠费分布 散点图 (带特效版) */
|
||||
const options3 = shallowRef<EChartsOption>({
|
||||
title: {
|
||||
text: '年龄分布',
|
||||
left: 0,
|
||||
top: 0,
|
||||
textStyle: { fontSize: 14, fontWeight: 'normal' }
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: (params: any) => {
|
||||
return `${monthX[params.value[0]]}<br/>欠费金额: <b>${params.value[1]}</b> 万元`;
|
||||
},
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||
borderColor: '#eee',
|
||||
textStyle: { color: '#333' }
|
||||
},
|
||||
xAxis: {},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
left: '1%',
|
||||
right: '2%',
|
||||
top: '12%',
|
||||
bottom: '8%',
|
||||
bottom: '12%',
|
||||
containLabel: true
|
||||
},
|
||||
yAxis: {},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: monthX,
|
||||
boundaryGap: false,
|
||||
axisTick: {
|
||||
alignWithLabel: true,
|
||||
length: 5, // 刻度线长度
|
||||
lineStyle: { color: '#ccc' }
|
||||
},
|
||||
axisLine: { lineStyle: { color: '#eee' }, onZero: false },
|
||||
axisLabel: {
|
||||
color: '#666',
|
||||
interval: 0, // 强制显示所有月份
|
||||
margin: 12 // 标签与轴线的距离
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#f0f0f0',
|
||||
type: 'dashed',
|
||||
width: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '金额(万元)',
|
||||
nameTextStyle: { color: '#999', padding: [0, 0, 0, 10] },
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#f0f0f0',
|
||||
type: 'dashed' // 虚线网格更轻盈
|
||||
}
|
||||
},
|
||||
axisLabel: { color: '#999', margin: 20 }
|
||||
},
|
||||
series: [
|
||||
{
|
||||
symbolSize: 20,
|
||||
name: '欠费金额',
|
||||
type: 'scatter',
|
||||
symbolSize: (data: any) => {
|
||||
const value = data[1];
|
||||
return Math.min(Math.max(value * 1.5, 10), 40);
|
||||
},
|
||||
itemStyle: {
|
||||
color: (params: any) => {
|
||||
const index = params.dataIndex;
|
||||
if (index % 2 === 0) {
|
||||
return '#739ff0';
|
||||
} else {
|
||||
return '#86c9d0';
|
||||
}
|
||||
}
|
||||
},
|
||||
// 【特效 2】高亮状态(鼠标悬停)
|
||||
emphasis: {
|
||||
scale: 1.2 // 悬停时额外放大
|
||||
},
|
||||
data: [
|
||||
[10.0, 8.04],
|
||||
[8.07, 6.95],
|
||||
[13.0, 7.58],
|
||||
[9.05, 8.81],
|
||||
[11.0, 8.33],
|
||||
[14.0, 7.66],
|
||||
[13.4, 6.81],
|
||||
[10.0, 6.33],
|
||||
[14.0, 8.96],
|
||||
[12.5, 6.82],
|
||||
[9.15, 7.2],
|
||||
[11.5, 7.2],
|
||||
[3.03, 4.23],
|
||||
[12.2, 7.83],
|
||||
[2.02, 4.47],
|
||||
[1.05, 3.33],
|
||||
[4.05, 4.96],
|
||||
[6.03, 7.24],
|
||||
[12.0, 6.26],
|
||||
[12.0, 8.84],
|
||||
[7.08, 5.82],
|
||||
[5.02, 5.68]
|
||||
],
|
||||
type: 'scatter'
|
||||
[0, 12.5],
|
||||
[1, 10.2],
|
||||
[2, 15.8],
|
||||
[3, 9.5],
|
||||
[4, 11.0],
|
||||
[5, 18.3],
|
||||
[6, 14.2],
|
||||
[7, 16.5],
|
||||
[8, 13.1],
|
||||
[9, 10.8],
|
||||
[10, 12.4],
|
||||
[11, 19.6]
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -284,12 +305,6 @@ const outData = [121, 85, 142, 71, 135, 93, 116, 66, 148, 104];
|
||||
|
||||
/** 进十日缴费数量情况 - 平滑折线图 */
|
||||
const flowLineOption = shallowRef<EChartsOption>({
|
||||
title: {
|
||||
text: '进十日缴费数量趋势',
|
||||
left: 0,
|
||||
top: 0,
|
||||
textStyle: { fontSize: 14, fontWeight: 'normal' }
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
confine: true
|
||||
@@ -369,11 +384,225 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
]
|
||||
});
|
||||
// ! 进十日缴费数量情况 -------------------------------------------------------------------------------------
|
||||
|
||||
const paytypelist = ref([
|
||||
{ label: '微信', value: 'payWx', number: 0, color: '#4a3afe' },
|
||||
{ label: '支付宝', value: 'payZfb', number: 0, color: '#1e1b39' },
|
||||
{ label: '线下', value: 'payOffline', number: 0, color: '#c893fd' }
|
||||
]);
|
||||
|
||||
function getlist() {
|
||||
const startData = getPastDayDate(defaultDay);
|
||||
income_statsApi(dataTime.value === '' ? startData : dataTime.value).then((res) => {
|
||||
form.value = res.data;
|
||||
const { payOffline, payWx, payZfb, feeTypeStats, dailyStats } = res.data;
|
||||
|
||||
const total = (payOffline ?? 0) + (payWx ?? 0) + (payZfb ?? 0);
|
||||
if (total > 0) {
|
||||
form.value.payOffline = Number.isNaN((payOffline / total) * 100) ? 0 : ((payOffline / total) * 100).toFixed(2);
|
||||
form.value.payWx = Number.isNaN((payWx / total) * 100) ? 0 : ((payWx / total) * 100).toFixed(2);
|
||||
form.value.payZfb = Number.isNaN((payZfb / total) * 100) ? 0 : ((payWx / total) * 100).toFixed(2);
|
||||
|
||||
paytypelist.value[0].number = form.value.payOffline;
|
||||
paytypelist.value[1].number = form.value.payWx;
|
||||
paytypelist.value[2].number = form.value.payZfb;
|
||||
paytypelist.value.sort((a, b) => Number(b.number) - Number(a.number));
|
||||
}
|
||||
|
||||
// 收入来源
|
||||
// 2. 处理收入来源 (新逻辑)
|
||||
if (feeTypeStats && Array.isArray(feeTypeStats)) {
|
||||
updateIncomeChart(feeTypeStats);
|
||||
}
|
||||
|
||||
// 3. 【新增】处理缴费走势 (近十日缴费情况)
|
||||
if (dailyStats && Array.isArray(dailyStats)) {
|
||||
updateFlowLineChart(dailyStats);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 更新缴费走势图表
|
||||
* @param stats 后端返回的 dailyStats 数组
|
||||
*/
|
||||
function updateFlowLineChart(stats: any[]) {
|
||||
if (!stats.length) {
|
||||
flowLineOption.value.series = [];
|
||||
flowLineOption.value.xAxis.data = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// 提取数据
|
||||
const dates = stats.map((item) => item.statDate);
|
||||
const paidData = stats.map((item) => Number(item.totalPaid) || 0);
|
||||
const unpaidData = stats.map((item) => Number(item.totalUnpaid) || 0);
|
||||
|
||||
// 更新图表配置
|
||||
// 使用 shallowRef 时,建议替换整个对象或确保深层属性被正确追踪
|
||||
// 这里我们直接修改 series 和 xAxis 的数据
|
||||
flowLineOption.value = {
|
||||
...flowLineOption.value,
|
||||
xAxis: {
|
||||
...flowLineOption.value.xAxis,
|
||||
data: dates
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '已缴费',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: paidData,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
itemStyle: { color: '#f94144' },
|
||||
lineStyle: { width: 4 },
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: '#fbd7d9' },
|
||||
{ offset: 1, color: '#fbd7d9' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '未缴费',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: unpaidData,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
itemStyle: { color: '#f9c74f' },
|
||||
lineStyle: { width: 4 },
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: '#fcf2dc' },
|
||||
{ offset: 1, color: '#fcf2dc' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 更新收入来源图表数组
|
||||
* @param stats 后端返回的 feeTypeStats 数组
|
||||
*/
|
||||
function updateIncomeChart(stats: any[]) {
|
||||
let statslist = stats;
|
||||
if (statslist.length === 0) {
|
||||
incomeChartOptions.value = [];
|
||||
statslist = [
|
||||
{
|
||||
'feeName': '停车费'
|
||||
},
|
||||
{
|
||||
'feeName': '物业费'
|
||||
},
|
||||
{
|
||||
'feeName': '水电费'
|
||||
},
|
||||
{
|
||||
'feeName': '商铺租金'
|
||||
},
|
||||
{
|
||||
'feeName': '维修费'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// 【修改点 2】映射生成多个独立的 ECharts 配置
|
||||
incomeChartOptions.value = statslist.map((item, index) => {
|
||||
const percentage = Number(item.paidPercentage) || 0;
|
||||
const color = '#409eff';
|
||||
return {
|
||||
name: item.feeName, // 图表名称
|
||||
options: {
|
||||
tooltip: {
|
||||
show: false,
|
||||
trigger: 'item',
|
||||
formatter: '{b}: {c}%'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['50%', '70%'], // 环形大小
|
||||
center: ['50%', '50%'], // 每个图表各自居中
|
||||
select: {
|
||||
scale: false
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: 100 - percentage,
|
||||
itemStyle: {
|
||||
color: '#ebeef5' // 背景色
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
color: '#ebeef5'
|
||||
},
|
||||
scale: false
|
||||
}
|
||||
},
|
||||
{
|
||||
value: percentage,
|
||||
name: item.feeName,
|
||||
itemStyle: { color: color },
|
||||
label: {
|
||||
show: true,
|
||||
position: 'center', // 显示在圆环中心
|
||||
formatter: '{c}%', // 显示百分比数值
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
color: '#4ce19c'
|
||||
},
|
||||
emphasis: {
|
||||
scale: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
});
|
||||
console.log(incomeChartOptions.value);
|
||||
}
|
||||
function querySearch() {
|
||||
getlist();
|
||||
}
|
||||
function reset() {
|
||||
dataTime.value = '';
|
||||
querySearch();
|
||||
}
|
||||
onMounted(() => {
|
||||
open.value = true;
|
||||
getlist();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
open.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.personnel {
|
||||
background: linear-gradient(180deg, #deedff 0%, #f8f9fe 50%);
|
||||
overflow: auto;
|
||||
.el-button {
|
||||
width: 80px;
|
||||
height: 32px;
|
||||
@@ -386,7 +615,7 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
width: 100px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
// 入住清空
|
||||
/* 入住清空 */
|
||||
.cardbox {
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
|
||||
border-radius: 16px 16px 16px 16px;
|
||||
@@ -394,11 +623,35 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
font-size: 20px;
|
||||
padding: 20px;
|
||||
min-height: 275px;
|
||||
@media (max-width: 1600px) {
|
||||
font-size: 18px;
|
||||
}
|
||||
@media (max-width: 1300px) {
|
||||
font-size: 20px;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.card_infoall {
|
||||
padding-left: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
font-size: 14px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.cardbody {
|
||||
padding: 0 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.chart-item {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.card_leftbox {
|
||||
text-align: center;
|
||||
.labelbox {
|
||||
@@ -417,7 +670,7 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
}
|
||||
|
||||
.legendbox {
|
||||
font-size: 0.8rem;
|
||||
font-size: 15px;
|
||||
li {
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
@@ -426,8 +679,8 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
line-height: 50px;
|
||||
text-align: left;
|
||||
padding-left: 30px;
|
||||
&::after {
|
||||
content: '';
|
||||
i {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
@@ -436,18 +689,6 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: #c893fd;
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
&::after {
|
||||
background: #4a3aff;
|
||||
}
|
||||
}
|
||||
&:last-of-type {
|
||||
&::after {
|
||||
background: #1e1b39;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -459,40 +700,55 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
transform: translateY(-40px);
|
||||
li {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border-radius: 50%;
|
||||
background-color: #c893fd;
|
||||
border: 3px solid white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 450;
|
||||
transition: all 0.3s ease; // 添加过渡动画
|
||||
|
||||
// 默认样式 (作为 Level 1 或基础样式)
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
font-size: 1.2rem;
|
||||
right: 40px;
|
||||
top: 40px;
|
||||
z-index: 10;
|
||||
&:nth-child(1) {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
right: inherit;
|
||||
left: 0px;
|
||||
font-size: 2rem;
|
||||
top: 30px;
|
||||
z-index: 9;
|
||||
background-color: #4a3aff;
|
||||
background-color: #c893fd; // 默认颜色,会被 data-bg 覆盖
|
||||
|
||||
// Level 0: 最大值 (排序后的第一个)
|
||||
&[data-level='0'] {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
left: 0;
|
||||
top: 15px;
|
||||
right: auto;
|
||||
font-size: 1.8rem;
|
||||
z-index: 9; // 层级最低,
|
||||
}
|
||||
&:nth-child(3) {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
left: inherit;
|
||||
top: inherit;
|
||||
right: 50px;
|
||||
font-size: 1.1rem;
|
||||
bottom: -20px;
|
||||
z-index: 11;
|
||||
background-color: #1e1b39;
|
||||
|
||||
// Level 1: 中间值
|
||||
&[data-level='1'] {
|
||||
width: 130px;
|
||||
height: 130px;
|
||||
left: 150px; // 重叠在大球右侧
|
||||
top: 0;
|
||||
right: auto;
|
||||
font-size: 1.3rem;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
// Level 2: 最小值
|
||||
&[data-level='2'] {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
left: 150px; // 更靠右
|
||||
top: 100px; // 靠下
|
||||
right: auto;
|
||||
font-size: 1rem;
|
||||
z-index: 11; // 层级最高,浮在最上面
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,20 @@
|
||||
v-model="date"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="yyyy-MM-dd"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 400px; margin-right: 10px"
|
||||
></el-date-picker>
|
||||
<el-button type="primary">查询</el-button>
|
||||
<el-button>重置</el-button>
|
||||
<el-button type="primary" @click="querySelect">查询</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :lg="7" :xl="8">
|
||||
|
||||
<el-row :gutter="20" style="position: relative; z-index: 2">
|
||||
<el-col :lg="8" :xl="8">
|
||||
<div class="cardbox">
|
||||
<div>入住情况</div>
|
||||
<div class="cardbody" style="height: 200px">
|
||||
<div class="card_leftbox">
|
||||
<div class="valuebox">4889</div>
|
||||
<div class="valuebox">{{ movein.totalResident }}</div>
|
||||
<div class="labelbox">入住人数</div>
|
||||
</div>
|
||||
<div class="echartsbox h-full">
|
||||
@@ -27,15 +28,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :lg="9" :xl="8">
|
||||
<el-col :lg="10" :xl="8">
|
||||
<div class="cardbox">
|
||||
<div>住户分析情况</div>
|
||||
<div>住户类型情况</div>
|
||||
<div class="cardbody w-full" style="height: 150px">
|
||||
<Echarts :options="options1"></Echarts>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :lg="8" :xl="8">
|
||||
<el-col :lg="6" :xl="8">
|
||||
<div class="cardbox">
|
||||
<div>男女比例</div>
|
||||
<div class="cardbody w-full" style="height: 150px">
|
||||
@@ -45,39 +46,51 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row style="margin-top: 20px" :gutter="20">
|
||||
<el-col :lg="16" :xl="16">
|
||||
<el-row style="margin-top: 20px; position: relative; z-index: 2" :gutter="20">
|
||||
<el-col :lg="24" :xl="24">
|
||||
<div class="cardbox w-full" style="height: 400px">
|
||||
<Echarts :options="options3"></Echarts>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :lg="8" :xl="8">
|
||||
<div class="cardbox w-full" style="height: 400px">
|
||||
<Echarts :options="options4"></Echarts>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 20px">
|
||||
<el-row style="margin-top: 20px; position: relative; z-index: 2">
|
||||
<el-col :span="24">
|
||||
<div class="cardbox w-full" style="height: 450px">
|
||||
<Echarts :options="flowLineOption"></Echarts>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<Teleport to="body">
|
||||
<i v-if="open" class="bgColor"></i>
|
||||
</Teleport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// TODO 人员分析
|
||||
|
||||
import { ref } from 'vue';
|
||||
import Echarts from '@/components/Echarts/index.vue';
|
||||
import { EChartsOption } from 'echarts';
|
||||
import { getLast7Days, getLastNDays } from '@/utils/time';
|
||||
import { get_movein_moveout_list, get_movein_user_sex, get_movein_user_type, user_movein_list } from '@/api/system/Personnel';
|
||||
|
||||
const date = ref('');
|
||||
const open = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
open.value = true;
|
||||
});
|
||||
onUnmounted(() => {
|
||||
open.value = false;
|
||||
});
|
||||
|
||||
function reset() {
|
||||
date.value = '';
|
||||
}
|
||||
|
||||
/** 入住情况 */
|
||||
const options = shallowRef<EChartsOption>({
|
||||
const options = ref<EChartsOption>({
|
||||
tooltip: { show: false },
|
||||
series: [
|
||||
// 1. 底层细圆环(灰色底色)
|
||||
@@ -97,7 +110,7 @@ const options = shallowRef<EChartsOption>({
|
||||
clockwise: true,
|
||||
itemStyle: {
|
||||
color: '#409eff',
|
||||
borderRadius: 10
|
||||
borderRadius: 2
|
||||
},
|
||||
emphasis: { disabled: true },
|
||||
label: {
|
||||
@@ -105,44 +118,27 @@ const options = shallowRef<EChartsOption>({
|
||||
position: 'center',
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
formatter: ' 85% \n 入住率'
|
||||
color: '#333',
|
||||
// 【新增】富文本样式配置,可以分别控制两行的样式
|
||||
rich: {
|
||||
rate: {
|
||||
color: 'rgba(63, 223, 149, 1)',
|
||||
fontSize: 20, // 百分比用主题色
|
||||
padding: [0, 0, 10, 0] // 下边距,拉开与文字的距离
|
||||
},
|
||||
title: {
|
||||
fontSize: 14,
|
||||
color: 'rgba(0, 0, 0, 1)' // 文字用灰色
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [{ value: 85 }, { value: 15, itemStyle: { color: 'transparent' } }]
|
||||
}
|
||||
]
|
||||
});
|
||||
function getRingOption(percent) {
|
||||
return {
|
||||
tooltip: { show: false },
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['78%', '88%'],
|
||||
data: [100],
|
||||
itemStyle: { color: '#ebeef5' },
|
||||
emphasis: { disabled: true },
|
||||
label: { show: false }
|
||||
},
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['75%', '90%'],
|
||||
itemStyle: { color: '#409eff', borderRadius: 10 },
|
||||
emphasis: { disabled: true },
|
||||
label: {
|
||||
show: true,
|
||||
position: 'center',
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
formatter: percent + '%'
|
||||
},
|
||||
data: [{ value: percent }, { value: 100 - percent, itemStyle: { color: 'transparent' } }]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/** 入住类型 */
|
||||
const options1 = shallowRef<EChartsOption>({
|
||||
const options1 = ref<EChartsOption>({
|
||||
legend: {
|
||||
top: 'center',
|
||||
left: '0',
|
||||
@@ -184,7 +180,7 @@ const options1 = shallowRef<EChartsOption>({
|
||||
});
|
||||
|
||||
/** 男女比例 */
|
||||
const options2 = shallowRef<EChartsOption>({
|
||||
const options2 = ref<EChartsOption>({
|
||||
legend: {
|
||||
top: 'center',
|
||||
left: '0',
|
||||
@@ -296,54 +292,18 @@ const options3 = shallowRef<EChartsOption>({
|
||||
]
|
||||
});
|
||||
// ! 年龄分布 -------------------------------------------------------------------------------------
|
||||
// ! 职业分布比例 -------------------------------------------------------------------------------------
|
||||
// 真实小区职业分布数据(上班族最多,依次递减)
|
||||
const realData = [120, 260, 580, 620, 1480];
|
||||
const options4 = shallowRef<EChartsOption>({
|
||||
title: {
|
||||
text: '职业分布比例',
|
||||
left: '0',
|
||||
top: '0',
|
||||
textStyle: { fontSize: 16, fontWeight: 'bold' }
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01]
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: ['其他', '自由职业', '学生', '全职妈妈', '上班族']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '2011',
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
color: '#fe3d4e'
|
||||
},
|
||||
data: realData
|
||||
}
|
||||
]
|
||||
});
|
||||
// ! 职业分布比例 -------------------------------------------------------------------------------------
|
||||
|
||||
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||
// 近10天日期
|
||||
const dayX = getLast7Days(10);
|
||||
const dayX = ref([]);
|
||||
|
||||
// 小区真实规模:人员流入 / 流出 数据
|
||||
// 【全新打乱随机数据】小区人员流入 / 流出
|
||||
const inData = [132, 76, 158, 91, 125, 68, 143, 84, 107, 162];
|
||||
const outData = [95, 136, 72, 118, 83, 149, 65, 124, 101, 77];
|
||||
const inData = ref([]);
|
||||
const outData = ref([]);
|
||||
|
||||
/** 近十天人员流入流出 - 平滑折线图 */
|
||||
const flowLineOption = shallowRef<EChartsOption>({
|
||||
const flowLineOption = ref<EChartsOption>({
|
||||
title: {
|
||||
text: '近十日人员流动趋势',
|
||||
left: 0,
|
||||
@@ -368,7 +328,7 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: dayX,
|
||||
data: dayX.value,
|
||||
boundaryGap: false,
|
||||
axisLine: { lineStyle: { color: '#eee' } }
|
||||
},
|
||||
@@ -384,7 +344,7 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
name: '人员流入',
|
||||
type: 'line',
|
||||
smooth: true, // 平滑折线 核心
|
||||
data: inData,
|
||||
data: inData.value,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
itemStyle: { color: '#f94144' },
|
||||
@@ -407,7 +367,7 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
name: '人员流出',
|
||||
type: 'line',
|
||||
smooth: true, // 平滑折线 核心
|
||||
data: outData,
|
||||
data: outData.value,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
itemStyle: { color: '#f9c74f' },
|
||||
@@ -428,11 +388,174 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
}
|
||||
]
|
||||
});
|
||||
function flowLineOptionFun(days: string[], indata: number[], outdata: number[]): EChartsOption {
|
||||
return {
|
||||
title: {
|
||||
text: '近十日人员流动趋势',
|
||||
left: 0,
|
||||
top: 0,
|
||||
textStyle: { fontSize: 14, fontWeight: 'normal' }
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
confine: true
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
top: '12%',
|
||||
bottom: '8%',
|
||||
containLabel: true
|
||||
},
|
||||
legend: {
|
||||
data: ['人员流入', '人员流出'],
|
||||
right: 10,
|
||||
top: 0
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: days,
|
||||
boundaryGap: false,
|
||||
axisLine: { lineStyle: { color: '#eee' } }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: { color: '#eee' }
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '人员流入',
|
||||
type: 'line',
|
||||
smooth: true, // 平滑折线 核心
|
||||
data: indata,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
itemStyle: { color: '#f94144' },
|
||||
lineStyle: { width: 4 },
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: '#fbd7d9' },
|
||||
{ offset: 1, color: '#fbd7d9' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '人员流出',
|
||||
type: 'line',
|
||||
smooth: true, // 平滑折线 核心
|
||||
data: outdata,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
itemStyle: { color: '#f9c74f' },
|
||||
lineStyle: { width: 4 },
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: '#fcf2dc' },
|
||||
{ offset: 1, color: '#fcf2dc' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
// ! 人员流动情况 -------------------------------------------------------------------------------------
|
||||
|
||||
const movein = ref({
|
||||
totalResident: 0,
|
||||
totalHouse: 0
|
||||
});
|
||||
function init() {
|
||||
// 获取入住情况
|
||||
moveinFun();
|
||||
// 入住类型
|
||||
moveinUserType();
|
||||
|
||||
moveinUserSex();
|
||||
moveinUserMoveinOut();
|
||||
}
|
||||
init();
|
||||
function querySelect() {
|
||||
init();
|
||||
}
|
||||
|
||||
function moveinFun() {
|
||||
user_movein_list({
|
||||
datetime: date.value
|
||||
}).then((res) => {
|
||||
// 获取入住情况
|
||||
movein.value.totalResident = res.data.occupancyCount;
|
||||
movein.value.totalHouse = res.data.totalHouse;
|
||||
options.value.series[1].data = [
|
||||
{ value: res.data.occupiedHouse },
|
||||
{ value: res.data.totalHouse - res.data.occupiedHouse, itemStyle: { color: 'transparent' } }
|
||||
];
|
||||
options.value.series[1].label.formatter = () => {
|
||||
const total = res.data.totalHouse;
|
||||
const occupied = res.data.occupiedHouse || 0; // 确保有值
|
||||
// 计算入住率,防止除以0
|
||||
const rate = total > 0 ? ((occupied / total) * 100).toFixed(1) : '0.0';
|
||||
// 返回带换行符的字符串:第一行是百分比,第二行是文字
|
||||
return `{rate|${rate}%}\n{title|入住率}`;
|
||||
};
|
||||
options.value = { ...options.value };
|
||||
});
|
||||
}
|
||||
// 获取住户类型
|
||||
function moveinUserType() {
|
||||
get_movein_user_type({
|
||||
datetime: date.value
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
}
|
||||
// 住户性别
|
||||
function moveinUserSex() {
|
||||
get_movein_user_sex({
|
||||
datetime: date.value
|
||||
}).then((res) => {
|
||||
options2.value.series[0].data = [
|
||||
{ value: res.man, name: '男', itemStyle: { color: '#0a74fe' } },
|
||||
{ value: res.woman, name: '女', itemStyle: { color: '#f74043' } }
|
||||
];
|
||||
});
|
||||
}
|
||||
// 迁入迁出
|
||||
function moveinUserMoveinOut() {
|
||||
// 判断 date.value 是否为今天
|
||||
if (date.value === '') {
|
||||
date.value = getLastNDays(7)[0];
|
||||
}
|
||||
get_movein_moveout_list({
|
||||
date: date.value
|
||||
}).then((res) => {
|
||||
dayX.value = res.data.map((item) => item.date);
|
||||
inData.value = res.data.map((item) => item.moveInCount);
|
||||
outData.value = res.data.map((item) => item.moveOutCount);
|
||||
flowLineOption.value = flowLineOptionFun(dayX.value, inData.value, outData.value);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.personnel {
|
||||
position: relative;
|
||||
background: linear-gradient(180deg, #deedff 0%, #f8f9fe 50%);
|
||||
.el-button {
|
||||
width: 80px;
|
||||
@@ -454,6 +577,9 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
font-size: 20px;
|
||||
padding: 20px;
|
||||
min-height: 275px;
|
||||
@media (max-width: 1200px) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.cardbody {
|
||||
padding: 0 30px;
|
||||
display: flex;
|
||||
@@ -469,6 +595,7 @@ const flowLineOption = shallowRef<EChartsOption>({
|
||||
font-weight: 600;
|
||||
font-size: 36px;
|
||||
color: #222222;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
.echartsbox {
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="单元" prop="unit">
|
||||
<el-select v-model="form.unitNo" placeholder="请选择单元">
|
||||
<el-option v-for="item in units" :key="item.no" :label="item.name" :value="item.no" />
|
||||
<el-form-item label="单元" prop="unitNoId">
|
||||
<el-select v-model="form.unitNoId" placeholder="请选择单元">
|
||||
<el-option v-for="item in units" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -25,7 +25,7 @@
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item label="储藏室号" prop="storeroomNo">
|
||||
<el-input v-model.number="form.storeroomNo" placeholder="请输入储藏室号" />
|
||||
<el-input v-model="form.storeroomNo" placeholder="请输入储藏室号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2"></el-col>
|
||||
@@ -68,6 +68,7 @@ import PageHeader from '@/components/Pageheader/index.vue';
|
||||
import { getBuildinglistAPI, getBuildinglists, getBuildingOnly, getHouselistAPI } from '@/api/system/house';
|
||||
import { addStoreroom, getStoreroom, updateStoreroom } from '@/api/system/storeroom';
|
||||
import { StoreroomVO } from '@/api/system/storeroom/types';
|
||||
import { getByBUildingidtoUnitNo } from '@/api/system/houseUnit';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -75,7 +76,8 @@ const formRef = ref();
|
||||
const form = ref<StoreroomVO>({
|
||||
id: null,
|
||||
buildingId: '',
|
||||
unitNo: '',
|
||||
unitNoId: '',
|
||||
unitName: '',
|
||||
storeroomNo: '',
|
||||
houseArea: null,
|
||||
shareArea: null,
|
||||
@@ -86,7 +88,7 @@ const form = ref<StoreroomVO>({
|
||||
});
|
||||
const rules = ref({
|
||||
buildingId: [{ required: true, message: '请选择楼栋', trigger: 'blur' }],
|
||||
unitNo: [{ required: true, message: '请选择单元', trigger: 'blur' }],
|
||||
unitNoId: [{ required: true, message: '请选择单元', trigger: 'blur' }],
|
||||
storeroomNo: [{ required: true, message: '请输入储藏室号', trigger: 'blur' }]
|
||||
});
|
||||
|
||||
@@ -103,9 +105,10 @@ function getStoreRoominfo(id: string) {
|
||||
};
|
||||
if (form.value.buildingId) {
|
||||
handleChangeBuild(form.value.buildingId, () => {
|
||||
form.value.unitNo = res.data.unitNo;
|
||||
form.value.unitNoId = res.data.unitNoId;
|
||||
});
|
||||
}
|
||||
console.log(form.value);
|
||||
});
|
||||
}
|
||||
// 根据小区id获取楼栋单元
|
||||
@@ -123,13 +126,8 @@ onMounted(() => {
|
||||
});
|
||||
// 根据楼栋id获取单元
|
||||
function handleChangeBuild(val: string, callback?: () => void) {
|
||||
getBuildingOnly(val).then((res) => {
|
||||
units.value = Array.from({ length: res.data.unitCount }).map((_, index) => {
|
||||
return {
|
||||
no: index + 1,
|
||||
name: index + 1 + '单元'
|
||||
};
|
||||
});
|
||||
getByBUildingidtoUnitNo(val).then((res) => {
|
||||
units.value = res.data;
|
||||
callback && callback();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,14 +48,14 @@
|
||||
|
||||
<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="单元号" align="center" prop="unitNo" />
|
||||
<el-table-column label="储藏室号" align="center" prop="storeroomNo" />
|
||||
<el-table-column label="建筑面积(㎡)" align="center" prop="houseArea" />
|
||||
<el-table-column label="公摊面积(㎡)" align="center" prop="shareArea" />
|
||||
<el-table-column label="实用面积(㎡)" align="center" prop="internalArea" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<el-table-column label="楼栋名" width="150" align="center" prop="buildingName" />
|
||||
<el-table-column label="单元号" show-overflow-tooltip width="150" align="center" prop="unitName" />
|
||||
<el-table-column label="储藏室号" width="150" align="center" prop="storeroomNo" />
|
||||
<el-table-column label="建筑面积(㎡)" width="100" align="center" prop="houseArea" />
|
||||
<el-table-column label="公摊面积(㎡)" width="100" align="center" prop="shareArea" />
|
||||
<el-table-column label="实用面积(㎡)" width="100" align="center" prop="internalArea" />
|
||||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['storeroom:storeroom:edit']">修改</el-button>
|
||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['storeroom:storeroom:remove']">删除</el-button>
|
||||
@@ -70,9 +70,8 @@
|
||||
|
||||
<script setup name="Storeroom" lang="ts">
|
||||
import Pageheader from '@/components/Pageheader/index.vue';
|
||||
import { listStoreroom, getStoreroom, delStoreroom, addStoreroom, updateStoreroom } from '@/api/system/storeroom/index';
|
||||
import { listStoreroom, delStoreroom } from '@/api/system/storeroom/index';
|
||||
import { StoreroomVO, StoreroomQuery, StoreroomForm } from '@/api/system/storeroom/types';
|
||||
import { getBuildinglists } from '@/api/system/house';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
@@ -129,14 +128,6 @@ const data = reactive<PageData<StoreroomForm, StoreroomQuery>>({
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
const buildinglist = ref([]);
|
||||
function getbudilinglist() {
|
||||
getBuildinglists().then((res) => {
|
||||
buildinglist.value = res.rows;
|
||||
});
|
||||
}
|
||||
getbudilinglist();
|
||||
|
||||
/** 查询储藏室管理列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
|
||||
@@ -67,7 +67,6 @@ import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
||||
const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
|
||||
|
||||
const router = useRouter();
|
||||
@@ -107,7 +106,8 @@ const rules = ref({
|
||||
{
|
||||
validator: (_, val) => validator(val, 'phone'),
|
||||
message: '请输入正确的手机号码',
|
||||
trigger: 'blur'
|
||||
trigger: 'blur',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }]
|
||||
|
||||
@@ -63,8 +63,8 @@
|
||||
|
||||
<right-toolbar :show-add="checkPermi(['system:user:add'])" @update:add="handleAdd" more-title="更多" :columns="columns">
|
||||
<template #dropdown>
|
||||
<el-dropdown-item v-if="checkPermi(['system:user:edit'])" :disabled="single" @click="handleUpdate()">修改</el-dropdown-item>
|
||||
<el-dropdown-item v-if="checkPermi(['system:user:remove'])" :disabled="multiple" @click="handleDelete()">删除</el-dropdown-item>
|
||||
<!-- <el-dropdown-item v-if="checkPermi(['system:user:edit'])" :disabled="single" @click="handleUpdate()">修改</el-dropdown-item> -->
|
||||
<!-- <el-dropdown-item v-if="checkPermi(['system:user:remove'])" :disabled="multiple" @click="handleDelete()">删除</el-dropdown-item> -->
|
||||
<el-dropdown-item @click="importTemplate">下载模板</el-dropdown-item>
|
||||
<!-- 注意 由于el-dropdown-item标签是延迟加载的 所以v-has-permi自定义标签不生效 需要使用v-if调用方法执行 -->
|
||||
<el-dropdown-item v-if="checkPermi(['system:user:import'])" @click="handleImport">导入数据</el-dropdown-item>
|
||||
|
||||
374
src/views/system/version/index.vue
Normal file
374
src/views/system/version/index.vue
Normal file
@@ -0,0 +1,374 @@
|
||||
<template>
|
||||
<div class="p-2 h-full flex flex-col">
|
||||
<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="channel">
|
||||
<el-select v-model="queryParams.channel" placeholder="请选择">
|
||||
<el-option label="花开物业App" value="resident"></el-option>
|
||||
<el-option label="花开管家App" value="butler"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="应用类型" prop="platform">
|
||||
<el-select v-model="queryParams.platform" placeholder="请选择">
|
||||
<el-option label="iOS" value="ios"></el-option>
|
||||
<el-option label="Android" value="android"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本号" prop="versionCode">
|
||||
<el-input v-model="queryParams.versionCode" placeholder="请输入版本号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="版本名称" prop="versionName">
|
||||
<el-input v-model="queryParams.versionName" placeholder="请输入版本名称" clearable @keyup.enter="handleQuery" />
|
||||
</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="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:version:add']">新增</el-button>
|
||||
</el-col>
|
||||
<!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> -->
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
:default-sort="{ prop: 'versionCode', order: 'descending' }"
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="versionList"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="应用名称" sortable align="center" prop="channel">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.channel === 'resident'">花开物业App</span>
|
||||
<span v-else-if="scope.row.channel === 'butler'">花开管家App</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="版本类型" align="center" prop="platform">
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.platform === 'ios'">ios</el-tag>
|
||||
<el-tag type="primary" v-else>android</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="版本号" sortable align="center" prop="versionCode" />
|
||||
<el-table-column label="版本名称" sortable align="center" prop="versionName" />
|
||||
<el-table-column label="最低支持版本" sortable align="center" prop="minVersionName" />
|
||||
<el-table-column label="下载地址" align="center" prop="downloadUrl" />
|
||||
<el-table-column label="更新日志" align="center" prop="releaseNotes" />
|
||||
<el-table-column label="停用/启用" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
@change="(val: string) => switchVersion(scope.row.id, val)"
|
||||
v-model="scope.row.status"
|
||||
active-value="1"
|
||||
inactive-value="0"
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" />
|
||||
</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="650px" append-to-body>
|
||||
<el-form ref="versionFormRef" :model="form" :rules="rules" label-width="130px">
|
||||
<el-form-item label="App端" prop="channel">
|
||||
<el-select @change="handleGetVersionlast" v-model="form.channel" placeholder="请选择">
|
||||
<el-option label="花开管家App" value="butler"></el-option>
|
||||
<el-option label="花开物业App" value="resident"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="App类型" prop="platform">
|
||||
<el-radio-group @change="handleChangePlatform" v-model="form.platform">
|
||||
<el-radio :value="appType.android">Android</el-radio>
|
||||
<el-radio :value="appType.ios">ios</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本名称" prop="versionName">
|
||||
<el-input v-model="form.versionName" placeholder="请输入版本名称例如:1.2.0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最低支持版本" prop="minVersionCode">
|
||||
<el-select v-if="getlastVersionlist.length > 0" v-model="form.minVersionCode" placeholder="请输入最低支持版本">
|
||||
<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-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="更新日志" prop="releaseNotes">
|
||||
<el-input v-model="form.releaseNotes" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="低版本强制更新">
|
||||
<div>
|
||||
<el-switch
|
||||
v-model="form.updateType"
|
||||
:active-value="updateType.force"
|
||||
active-text="开启"
|
||||
:inactive-value="updateType.optional"
|
||||
inactive-text="停止"
|
||||
></el-switch>
|
||||
<p class="tips">
|
||||
<strong style="color: #000">配合最低支持版本使用</strong> 开启后: <br />低于最低版→启用强制(无取消,不更退出 APP);<br />高于最低版→普通弹窗可选取消。
|
||||
</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="更新地址" prop="downloadUrl" v-if="form.platform === appType.ios">
|
||||
<el-input v-model="form.downloadUrl" placeholder="请输入App Store 链接" />
|
||||
</el-form-item>
|
||||
<div v-else-if="form.platform === appType.android">
|
||||
<el-form-item label="更新类型">
|
||||
<el-radio-group v-model="form.method">
|
||||
<el-radio-button :value="updatePackageType.apk">整包更新(apk)</el-radio-button>
|
||||
<el-radio-button :value="updatePackageType.wgt">热更新(wgt)</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传安装包地址" prop="downloadUrl">
|
||||
<el-input v-model="form.downloadUrl" placeholder="请输入更新地址" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</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="Version" lang="ts">
|
||||
import { listVersion, addVersion, getPastVersion, switchVersion } from '@/api/system/version/index';
|
||||
import { VersionVO, VersionQuery, VersionForm } from '@/api/system/version/type';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const versionList = ref<VersionVO[]>([]);
|
||||
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 versionFormRef = ref<ElFormInstance>();
|
||||
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const initFormData: VersionForm = {
|
||||
id: undefined,
|
||||
platform: 'android',
|
||||
versionCode: undefined,
|
||||
versionName: undefined,
|
||||
minVersionCode: '1.0.0',
|
||||
updateType: undefined,
|
||||
method: 'apk',
|
||||
downloadUrl: undefined,
|
||||
releaseNotes: undefined,
|
||||
fileSize: undefined,
|
||||
status: undefined,
|
||||
channel: undefined
|
||||
};
|
||||
const data = reactive<PageData<VersionForm, VersionQuery>>({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
platform: undefined,
|
||||
versionCode: undefined,
|
||||
versionName: undefined,
|
||||
minVersionCode: undefined,
|
||||
updateType: undefined,
|
||||
downloadUrl: undefined,
|
||||
releaseNotes: undefined,
|
||||
fileSize: undefined,
|
||||
status: undefined,
|
||||
channel: undefined
|
||||
},
|
||||
rules: {
|
||||
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' }],
|
||||
downloadUrl: [{ required: true, message: '安装包地址不能为空', trigger: 'blur' }]
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
enum appType {
|
||||
/** ios */
|
||||
ios = 'ios',
|
||||
/** android */
|
||||
android = 'android'
|
||||
}
|
||||
/** 更新包类型 */
|
||||
enum updatePackageType {
|
||||
/** 整包更新 */
|
||||
apk = 'apk',
|
||||
/** 热更新 */
|
||||
wgt = 'wgt'
|
||||
}
|
||||
enum updateType {
|
||||
/** 强制更新 */
|
||||
force = '0',
|
||||
/** 可选更新 */
|
||||
optional = '1'
|
||||
}
|
||||
const getlastVersionlist = ref([]);
|
||||
|
||||
/**
|
||||
* 判断当前版本是否需要更新到最新版本。
|
||||
* 比较逻辑为:如果当前版本号小于或等于最新版本号,则认为需要更新。
|
||||
*
|
||||
* @param {string} current - 当前版本号字符串,格式为点分十进制(如 "1.2.3")
|
||||
* @param {string} latest - 最新版本号字符串,格式为点分十进制(如 "1.2.4")
|
||||
* @returns {boolean} 如果当前版本小于或等于最新版本,返回 true;否则返回 false
|
||||
*/
|
||||
function needUpdate(current, latest) {
|
||||
// 将版本号字符串分割并转换为数字数组
|
||||
const c = current.split('.').map(Number);
|
||||
const l = latest.split('.').map(Number);
|
||||
const max = Math.max(c.length, l.length);
|
||||
|
||||
// 逐段比较版本号,若当前段小于最新段则需更新,大于则无需更新
|
||||
for (let i = 0; i < max; i++) {
|
||||
const cv = c[i] || 0;
|
||||
const lv = l[i] || 0;
|
||||
if (cv <= lv) return true;
|
||||
if (cv > lv) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 查询【请填写功能名称】列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listVersion(queryParams.value);
|
||||
versionList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset();
|
||||
dialog.visible = false;
|
||||
};
|
||||
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
form.value = { ...initFormData };
|
||||
versionFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
form.value = { ...initFormData };
|
||||
queryFormRef.value?.resetFields();
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: VersionVO[]) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
reset();
|
||||
dialog.visible = true;
|
||||
dialog.title = '添加版本';
|
||||
};
|
||||
|
||||
function handleChangePlatform() {
|
||||
form.value.minVersionCode = '1.0.0';
|
||||
form.value.updateType = updateType.optional;
|
||||
form.value.method = updatePackageType.apk;
|
||||
form.value.downloadUrl = '';
|
||||
handleGetVersionlast();
|
||||
}
|
||||
|
||||
function handleGetVersionlast() {
|
||||
getPastVersion(form.value.platform, form.value.channel).then((res) => {
|
||||
getlastVersionlist.value = res.data;
|
||||
form.value.minVersionCode = getlastVersionlist.value[getlastVersionlist.value.length - 1]
|
||||
? getlastVersionlist.value[getlastVersionlist.value.length - 1].versionCode
|
||||
: null;
|
||||
});
|
||||
}
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
if (!form.value.minVersionCode) {
|
||||
ElMessage.error('请选择最低支持版本');
|
||||
return;
|
||||
}
|
||||
|
||||
versionFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
await addVersion(form.value).finally(() => (buttonLoading.value = false));
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-table {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
|
||||
.uploadFileBox {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
color: rgba(16, 16, 16, 1);
|
||||
border: 1px solid #ccc;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
border: 1px solid #409eff;
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
@@ -5,11 +5,11 @@
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
||||
<el-form-item label="选择品牌" prop="brand">
|
||||
<el-input v-model="queryParams.brand" placeholder="请输入物料名称" clearable @keyup.enter="handleQuery" />
|
||||
<el-form-item label="品牌名称" prop="brand">
|
||||
<el-input v-model="queryParams.brand" placeholder="请输入品牌" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="选择型号" prop="model">
|
||||
<el-input v-model="queryParams.model" placeholder="请输入物料名称" clearable @keyup.enter="handleQuery" />
|
||||
<el-form-item label="型号名称" prop="model">
|
||||
<el-input v-model="queryParams.model" placeholder="请输入型号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料名称" prop="materialName">
|
||||
<el-input v-model="queryParams.materialName" placeholder="请输入物料名称" clearable @keyup.enter="handleQuery" />
|
||||
@@ -30,7 +30,7 @@
|
||||
:disable-delete="multiple"
|
||||
:disable-edit="single"
|
||||
:show-add="false"
|
||||
:show-edit="checkPermi(['warehouse:edit:inventory'])"
|
||||
:show-edit="false"
|
||||
:show-delete="false"
|
||||
@update:add="handleAdd"
|
||||
@update:edit="handleUpdate()"
|
||||
@@ -133,10 +133,11 @@ const handleAdd = () => {
|
||||
};
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: MaterialVO) => {
|
||||
const _ids = row?.materialId;
|
||||
router.push({
|
||||
path: '/warehouse/editInventory',
|
||||
query: {
|
||||
id: row.materialId
|
||||
id: _ids
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user