Merge branch 'dev' into report

# Conflicts:
#	src/views/system/Sdb/SdbCashier/index.vue
#	src/views/system/houseRental/index.vue
This commit is contained in:
Zy
2026-08-14 15:05:47 +08:00
43 changed files with 844 additions and 386 deletions

View File

@@ -1,6 +1,6 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ChargeTypeVO, ChargeTypeForm, ChargeTypeQuery } from './type';
import { ChargeTypeVO, ChargeTypeForm, ChargeTypeQuery, ChargeTypeRelationQuery } from './type';
/**
* 查询收费类型列表
@@ -61,3 +61,37 @@ export const delChargeType = (id: string | number | Array<string | number>) => {
method: 'delete'
});
};
/**
* 查询收费类型关联列表
* @param query
*/
export const getChargeTypeRelation = (query?: ChargeTypeRelationQuery) => {
return request({
url: '/chargeType/relation/list',
method: 'get'
});
};
/**
* 新增收费类型关联
* @param data
*/
export const addChargeTypeRelation = (data: ChargeTypeRelationQuery) => {
return request({
url: '/chargeType/relation',
method: 'POST',
data: data
});
};
/**
* 新增收费类型关联
* @param data
*/
export const editChargeTypeRelation = (data: ChargeTypeRelationQuery) => {
return request({
url: '/chargeType/relation',
method: 'PUT',
data: data
});
};

View File

@@ -64,3 +64,20 @@ export interface ChargeType2Query extends PageQuery {
*/
params?: any;
}
export interface ChargeTypeRelationQuery {
/**
* 主收费类型表id
*/
masterTypeId?: string;
/**
* 子收费类型表id
*/
slaveTypeIds?: string;
id?: string;
// 状态 0启用 1停用
status?: string;
}

View File

@@ -74,8 +74,18 @@ export interface PayMentMethod {
'wechatPercent': string;
'alipayAmount': string;
'alipayPercent': string;
'offlineAmount': string;
'offlinePercent': string;
'yidangAmount': string;
'yidangPercent': string;
'cashAmount': string;
'cashPercent': string;
'unionPayAmount': string;
'unionPayPercent': string;
'transferAmount': string;
'transferPercent': string;
'depositOffsetAmount': string;
'depositOffsetAmountPercent': string;
'propertyOffsetAmount': string;
'propertyOffsetAmountPercent': string;
}
// 缴费方式
export const payment_methodApi = (datetime?: string): AxiosPromise<PayMentMethod> => {

View File

@@ -77,9 +77,21 @@ export const billPrint = (data: { 'detailsIds': string[]; 'residentId': string }
});
};
// 删除账单
export const billDelete = (ids: string | string[]) => {
return request({
url: `/cash/bill/${ids}`,
method: 'DELETE'
});
};
export type BillPrintType = {
'totalAccount': string;
'residentName': string;
'payTypeSummary': {
'payType': string;
'payAmount': string;
}[];
'detailsList': {
'detailsId': string;
'chargeItemName': string;

View File

@@ -1,6 +1,6 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { HouseRentalVO, HouseRentalForm, HouseRentalQuery } from '@/api/system/houseRental/type';
import { HouseRentalVO, HouseRentalForm, HouseRentalQuery, HouseRentalSigningVO } from '@/api/system/houseRental/type';
/**
* 查询房屋租赁管理列表
@@ -103,7 +103,7 @@ export const changeHouseRedientStatus = (houseId: string): AxiosPromise<uploadHo
* 房屋租赁管理 签约
* @param data
*/
export const HouseRedientSign = (data: HouseRentalForm): AxiosPromise<uploadHouseImagetype> => {
export const HouseRedientSign = (data: HouseRentalSigningVO): AxiosPromise<uploadHouseImagetype> => {
return request({
url: `/houseRental/sign`,
method: 'POST',

View File

@@ -124,6 +124,7 @@ export interface HouseRentalSigningVO {
'tenantPhone': string;
'chargeMode': string;
'chargeStandard': string;
'contractName': string;
'contractStatus': string;
'leaseStartDate': string;
'leaseEndDate': string;

View File

@@ -102,3 +102,25 @@ export const GetVillageListParking = (villageid: string, houseId: string = undef
}
});
};
/**
* 查询 车位持有人信息
* @returns {*}
* @param residentId
*/
export const getParkingResidentInfo = (
residentId: string
): AxiosPromise<{
id: '';
name: '';
type: '';
status: '';
idCard: '';
phone: '';
houseName: '';
}> => {
return request({
url: `/car/holder/${residentId}`,
method: 'GET'
});
};

View File

@@ -12,14 +12,14 @@
</div>
<el-dialog @close="conback" append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
<nav class="flex flex-items-center mb-8">
<div class="flex flex-items-center mr-5 flex-1">
<nav class="flex flex-items-center mb-8" style="margin-bottom: 20px">
<div class="flex flex-items-center flex-1" style="max-width: 200px">
<div style="width: 120px">住户类型</div>
<el-select v-model="queryParams.ownerRelationship" placeholder="请选择" clearable>
<el-option v-for="dict in com_resident_relationship" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</div>
<div class="mr-5 flex-1">
<div class="mr-5 flex-1" style="margin: 0 20px">
<el-input maxlength="30" clearable v-model="queryParams.name" placeholder="请输入住户姓名" />
</div>
<div>
@@ -47,7 +47,7 @@
<dict-tag :options="com_certification_status" :value="row.status" />
</template>
</el-table-column>
<el-table-column label="证件号码" align="center" prop="idCard" />
<el-table-column label="证件号码" width="165" align="center" prop="idCard" />
<el-table-column label="手机号码" align="center" prop="phone" />
<el-table-column label="房间" show-overflow-tooltip align="center">
<template #default="{ row }">
@@ -116,8 +116,6 @@ const props = defineProps<{
const isMultiple = computed(() => props.isMultiple ?? false);
const returnvalue = computed(() => props.returnvalue ?? '*'); // 👈 默认 userId
const { userid } = toRefs(props);
const dialog = ref({
dialogVisible: false,
dialogTitle: '选择住户'

View File

@@ -1,5 +1,7 @@
<template>
<div :class="{ hidden: hidden }" class="pagination-container">
<span class="total"> {{ total }} </span>
<slot name="pageContent"></slot>
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
@@ -67,7 +69,15 @@ function handleCurrentChange(val: number) {
</script>
<style lang="scss" scoped>
.total {
color: var(--el-text-color-regular);
font-weight: 400;
font-size: 14px;
margin: 0 15px 0 0;
}
.pagination-container {
display: flex;
align-items: center;
.el-pagination {
float: v-bind(float);
}

View File

@@ -23,6 +23,8 @@ const reg = {
passport: /^[EG]\d{8}$/,
/** 港澳通行证 */
hongkongPassport: /^[CHMW]\d{8}$/,
/** 微信 */
vx: /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/,
/** 年龄 */
age: /^[0-9]\d{0,2}$/,
/** 数字 */

View File

@@ -32,11 +32,6 @@
<el-form-item label="小区面积" prop="villageArea">
<el-input maxlength="8" v-model.trim="form.villageArea" placeholder="请输入小区面积"><template #append></template> </el-input>
</el-form-item>
<el-form-item label="车位数量" prop="parkingSpaceCount">
<el-input maxlength="8" v-model.trim="form.parkingSpaceCount" placeholder="请输入车位数量">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item style="width: 100%" label="小区图片">
<el-upload
accept=".jpg, .png"
@@ -360,6 +355,7 @@ async function handleUploadChange(file: UploadFile) {
ElMessage.error(isUpload.type);
return;
} else if (typeof isUpload === 'boolean' && isUpload === true) {
console.log(file);
villageImg.value.push(file.raw);
}
}
@@ -369,7 +365,12 @@ function handleExceed() {
}
/** 移除钩子 */
const handleRemove = (file: UploadFile) => {
villageImg.value = villageImg.value.filter((item) => item.uid !== file.uid);
const fileToRemoveIndex = villageImg.value.findIndex((item) => item.uid === file.uid);
if (fileToRemoveIndex === -1) {
return;
}
uploadRef.value.handleRemove(villageImg.value[fileToRemoveIndex]);
villageImg.value.splice(fileToRemoveIndex, 1);
};
// 改变时间

View File

@@ -54,11 +54,12 @@
</el-row>
<el-row>
<el-col :span="11">
<el-form-item label="报名截止日期" prop="deadline">
<el-form-item label="报名截止日期" prop="applyDeadline">
<el-date-picker
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
v-model="deadline"
:disabled-date="disabledDate"
@update:model-value="
(data) => {
if (data) {
@@ -208,7 +209,8 @@
</el-col>
</el-row> -->
<el-form-item>
<el-button type="primary" @click="submitForm">提交</el-button>
<el-button type="warning" @click="submitForm('0')">保存为草稿</el-button>
<el-button type="primary" @click="submitForm('1')">发布</el-button>
<el-button @click="handleBack">返回</el-button>
</el-form-item>
</el-form>
@@ -312,6 +314,14 @@ const rules = {
coverImage: [{ required: true, message: '请上传活动封面', trigger: 'blur' }],
content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
};
const disabledDate = (time: string) => {
const today = new Date();
today.setHours(0, 0, 0, 0);
const selectDate = new Date(time);
return selectDate.getTime() < today.getTime();
};
const userid = ref();
// 报名截止日期
const deadline = ref([]);
@@ -525,9 +535,9 @@ function init() {
});
}
// ! 提交========================================
// 提交
const submitForm = () => {
const submitForm = (status: string) => {
form.value.status = status;
console.log(form.value);
// if (!isSignin.value) {
// form.value.SignInfo = null;

View File

@@ -54,7 +54,7 @@
</template>
</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">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['monthCard:monthCard:edit']">修改</el-button>
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['monthCard:monthCard:remove']">删除</el-button>

View File

@@ -77,8 +77,8 @@
:min-scale="0.2"
:preview-src-list="form.problemImageUrlList"
show-progress
:initial-index="0"
v-for="(item, index) in form.problemImageUrlList"
:initial-index="index"
:key="index"
:src="item"
lazy

View File

@@ -20,6 +20,10 @@
<el-card class="flex-1" shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="22"> </el-col>
<el-col :span="2">
<div class="flex justify-end items-center">
<el-button style="margin-right: 10px" type="primary" @click="handleContainer">关联收费</el-button>
<right-toolbar
:disable-delete="multiple"
:disable-edit="single"
@@ -30,6 +34,8 @@
@update:edit="handleUpdate()"
@update:delete="handleDelete()"
></right-toolbar>
</div>
</el-col>
</el-row>
</template>
@@ -70,15 +76,64 @@
</div>
</template>
</el-dialog>
<el-dialog :title="dialog2.title" v-model="dialog2.visible" width="500px" append-to-body>
<el-form ref="chargeTypeForm2Ref" :model="form2" :rules="rules2" label-width="100px">
<el-form-item label="主收费类型">
<el-select
@change="handleChangeMasterType"
style="width: 220px; margin-right: 10px"
v-model="form2.masterTypeId"
placeholder="请选择收费类型"
>
<el-option v-for="item in TypeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="次收费类型" v-for="(_, index) in slaveTypeIdsList" :key="index">
<div class="flex flex-items-center">
<el-select
@change="handleChangeMasterType"
style="width: 220px; margin-right: 10px"
v-model="slaveTypeIdsList[index]"
placeholder="请选择收费类型"
>
<el-option :disabled="item.disabled" v-for="item in TypeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<div class="addBox" @click="handleAddType" v-if="index === 0 && slaveTypeIdsList.length < TypeList.length - 1">
<el-icon size="23" color="#ffffff"><Plus /></el-icon>
</div>
<el-icon @click="deleteType(index)" v-else-if="slaveTypeIdsList.length > 1" size="24" color="red"><Delete /></el-icon>
</div>
</el-form-item>
<el-form-item label="是否启用关联">
<el-switch v-model="form2.status" active-value="0" inactive-value="1" active-text="启用" inactive-text="禁用" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading2" type="primary" @click="submitForm2"> </el-button>
<el-button @click="cancel2"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ChargeType" lang="ts">
import PageHeader from '@/components/Pageheader/index.vue';
import pagination from '@/components/Pagination/index.vue';
import { listChargeType, getChargeType, delChargeType, addChargeType, updateChargeType } from '@/api/system/ChargeType';
import {
listChargeType,
getChargeType,
delChargeType,
addChargeType,
updateChargeType,
getChargeTypeRelation,
addChargeTypeRelation,
editChargeTypeRelation
} from '@/api/system/ChargeType';
import { ChargeTypeVO, ChargeTypeForm, ChargeType2Query } from '@/api/system/ChargeType/type';
import { checkPermi } from '@/utils/permission';
import { Delete, Plus } from '@element-plus/icons-vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -110,8 +165,7 @@ const data = reactive<PageData<ChargeTypeForm, ChargeType2Query>>({
pageNum: 1,
pageSize: 10,
name: undefined,
status: undefined,
params: {}
status: undefined
}
});
@@ -209,6 +263,85 @@ const handleDelete = async (row?: ChargeTypeVO) => {
await getList();
};
const dialog2 = ref({
visible: false,
title: ''
});
const form2 = ref({
'id': undefined,
'masterTypeId': undefined,
'status': '0',
'slaveTypeIds': undefined,
'remark': undefined
});
const rules2 = {};
// 子收费类型
const slaveTypeIdsList = ref([null]);
// 收费类型
const TypeList = ref([]);
// 关联收费
function handleContainer() {
TypeList.value = chargeTypeList.value.map((item) => {
return {
...item,
disabled: false
};
});
getChargeTypeRelation().then((res) => {
if (res.rows.length > 0) {
form2.value = res.rows[0];
slaveTypeIdsList.value = form2.value.slaveTypeIds.split(',');
handleChangeMasterType();
}
});
dialog2.value.visible = true;
dialog2.value.title = '关联收费';
}
function handleChangeMasterType() {
const selectedValues = [form2.value.masterTypeId, ...slaveTypeIdsList.value.filter((item) => item !== null && item !== undefined && item !== '')];
// 根据当前选中状态重新计算 disabled
TypeList.value.forEach((item) => {
item.disabled = selectedValues.includes(item.id);
});
}
function handleAddType() {
slaveTypeIdsList.value.length++;
}
function deleteType(index: number) {
slaveTypeIdsList.value.splice(index, 1);
}
function cancel2() {
dialog2.value.visible = false;
TypeList.value = [];
slaveTypeIdsList.value = [null];
dialog2.value.title = '';
}
const buttonLoading2 = ref(false);
function submitForm2() {
form2.value.slaveTypeIds = slaveTypeIdsList.value.filter((item) => item !== null).join(',');
buttonLoading2.value = true;
if (form2.value.id) {
// edit
editChargeTypeRelation(form2.value)
.then(() => {
proxy?.$modal.msgSuccess('操作成功');
cancel2();
getList();
})
.finally(() => (buttonLoading2.value = false));
} else {
// add
addChargeTypeRelation(form2.value)
.then(() => {
proxy?.$modal.msgSuccess('操作成功');
cancel2();
getList();
})
.finally(() => (buttonLoading2.value = false));
}
}
onMounted(() => {
getList();
});
@@ -218,4 +351,13 @@ onMounted(() => {
.el-table {
height: calc(100% - 80px);
}
.addBox {
width: 24px;
height: 24px;
background-color: rgba(26, 117, 255, 1);
line-height: 24px;
text-align: center;
border-radius: 50%;
}
</style>

View File

@@ -40,17 +40,23 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="缴费周期" prop="chargePeriod">
<el-form-item label="缴费周期">
<el-date-picker
v-model="chargePeriod"
type="daterange"
v-model="queryParams.startDate"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
range-separator=""
start-placeholder="开始日期"
@clear="handleClearChargePeriod"
end-placeholder="结束日期"
placeholder="请选择缴费日期"
@clear="handleClearChargePeriod('start')"
placeholder="请选择开始缴费日期"
/>
<el-date-picker
v-model="queryParams.endDate"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
@clear="handleClearChargePeriod('end')"
style="margin-left: 10px"
placeholder="请选择结束缴费日期"
/>
</el-form-item>
<el-form-item label="房屋分类" prop="houseUseTypeId">
@@ -58,17 +64,23 @@
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="缴费时间" prop="payTime">
<el-form-item label="缴费时间">
<el-date-picker
v-model="payTime"
type="datetimerange"
v-model="queryParams.payTimeBegin"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
range-separator=""
start-placeholder="开始日期"
@clear="handleClearPayTime"
end-placeholder="结束日期"
placeholder="请选择缴费日期"
@clear="handleClearPayTime('payTimeBegin')"
placeholder="请选择开始缴费时间"
/>
<el-date-picker
v-model="queryParams.payTimeEnd"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
@clear="handleClearPayTime('payTimeEnd')"
style="margin-left: 10px"
placeholder="请选择结束缴费时间"
/>
</el-form-item>
<el-form-item label="业主姓名" prop="residentName">
@@ -101,6 +113,7 @@
<div class="actions">
<el-button @click="handleIncome(false)" :disabled="!single">收费</el-button>
<el-button @click="printPIaoJuByOnly(false)" :disabled="!printSingle">打印票据</el-button>
<el-button @click="handleDelete(false)">批量删除</el-button>
</div>
</div>
<el-card class="flex-1" shadow="never">
@@ -133,7 +146,7 @@
</div>
</template>
</el-table-column>
<el-table-column label="数量" width="80" align="center" prop="quantity">
<el-table-column label="数量" width="85" align="center" prop="quantity">
<template #default="scope">
<span>{{ scope.row.quantity }}</span>
</template>
@@ -151,25 +164,23 @@
<el-table-column label="优惠金额" width="100" align="center" prop="singleDiscountAmount" />
<el-table-column label="实缴金额" width="100" align="center" prop="actualAccount" />
<el-table-column label="缴费人" width="120" align="center" prop="residentName" />
<el-table-column label="缴费时间" width="200" align="center" prop="payTime" />
<el-table-column label="缴费时间" align="center" prop="payTime" />
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="操作" width="110" align="center" fixed="right" class-name="small-padding fixed-width">
<el-table-column label="操作" width="150" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" v-if="scope.row.payStatus !== '1'" @click="handleIncome(scope.row)" v-has-permi="['bill:bill:edit']"
>收款</el-button
>
<el-button link type="success" v-if="scope.row.payStatus === '1'" @click="printPIaoJuByOnly(scope.row)" v-has-permi="['bill:bill:query']"
>打印票据</el-button
>
<el-button link type="primary" v-if="scope.row.payStatus !== '1'" @click="handleIncome(scope.row)">收款</el-button>
<el-button link type="success" v-if="scope.row.payStatus === '1'" @click="printPIaoJuByOnly(scope.row)">打印票据</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="footerBox">
<div class="totalBox">
<span>合计</span>
<span>应收{{ totalAll.totalAccount }}</span>
<span style="padding: 0 20px">实收{{ totalAll.TotalPaymentAmount }}</span>
<span>优惠{{ totalAll.totalDiscountAmount }}</span>
<span style="padding: 0 10px">应收{{ totalAll.totalAccount }}</span>
<span style="padding: 0 10px">实收{{ totalAll.TotalPaymentAmount }}</span>
<span style="padding: 0 10px">优惠{{ totalAll.totalDiscountAmount }}</span>
<span style="padding: 0 10px">未收{{ totalAll.TotalUnPaymentAmount }}</span>
</div>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
@@ -399,6 +410,14 @@
<td></td>
<td></td>
</tr>
<tr>
<td>支付明细</td>
<td colspan="8" style="text-align: left; padding: 0 10px">
<span v-for="(item, index) in print_form.payTypeSummary" :key="index"
>{{ item.payType }}: {{ item.payAmount }} ; &nbsp; &nbsp;</span
>
</td>
</tr>
</tbody>
</table>
<p style="font-size: 10px">说明本收据收款单位和收款具签章方为有效本收据手写无效</p>
@@ -422,7 +441,7 @@ import pagination from '@/components/Pagination/index.vue';
import DictTag from '@/components/DictTag/index.vue';
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
import { getCommunitylistAPI } from '@/api/system/community';
import { billEdit, billlistType, billPrint, BillPrintType, billQuery } from '@/api/system/SdbCashier';
import { billDelete, billEdit, billlistType, billPrint, BillPrintType, billQuery } from '@/api/system/SdbCashier';
import { listChargeItem } from '@/api/system/SdbChargeItem';
import { ref } from 'vue';
import { add, div, eq, eqMoney, gtMoney, ltMoney, minMoney, moneyAdd, mul, sub, sum, toBig } from '@/utils/money';
@@ -475,8 +494,6 @@ const queryParams = ref({
unitNoId: undefined,
// 房屋id
houseId: undefined,
// 缴费周期
chargePeriod: undefined,
// 房屋类型id
houseUseTypeId: undefined,
// 缴费时间
@@ -496,11 +513,6 @@ const queryParams = ref({
endDate: undefined
});
// 缴费周期
const chargePeriod = ref([]);
// 缴费时间
const payTime = ref([]);
const villageList = ref<communitylist_rows_type[]>([]); // 小区列表
const buildingList = ref<BuildingVo[]>([]); // 楼栋列表
const unitList = ref<BuildingUnitlist[]>([]); // 单元列表
@@ -571,21 +583,20 @@ function handleChangeUnit(val: string) {
function handleChangeHouseNo() {}
// 清空缴费时间
function handleClearPayTime() {
payTime.value = [];
function handleClearPayTime(type: 'payTimeBegin' | 'payTimeEnd') {
queryParams.value[type] = undefined;
}
// 清空缴费周期
function handleClearChargePeriod() {
chargePeriod.value = [];
function handleClearChargePeriod(type: 'start' | 'end' = 'start') {
if (type === 'start') {
queryParams.value.startDate = undefined;
} else {
queryParams.value.endDate = undefined;
}
}
// 获取列表
function getList() {
loading.value = true;
queryParams.value.payTimeBegin = payTime.value[0] ? payTime.value[0] : undefined;
queryParams.value.payTimeEnd = payTime.value[1] ? payTime.value[1] : undefined;
queryParams.value.startDate = chargePeriod.value[0] ? chargePeriod.value[0] : undefined;
queryParams.value.endDate = chargePeriod.value[1] ? chargePeriod.value[1] : undefined;
billQuery(queryParams.value)
.then((res) => {
tableData.value = res.rows;
@@ -605,10 +616,8 @@ const handleQuery = () => {
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
payTime.value = [];
chargePeriod.value = [];
queryParams.value = {
chargePeriod: undefined,
startDate: undefined,
payTime: undefined,
pageNum: 1,
pageSize: 20,
@@ -623,7 +632,6 @@ const resetQuery = () => {
residentName: undefined,
payTimeBegin: undefined,
payTimeEnd: undefined,
startDate: undefined,
endDate: undefined
};
queryParams.value.villageId = villageId;
@@ -680,9 +688,10 @@ function initInComeFrom() {
residentName: '' // 缴费人
};
totalAll.value = {
totalDiscountAmount: 0,
TotalPaymentAmount: 0,
totalAccount: 0
totalDiscountAmount: 0, // 总优惠金额
TotalPaymentAmount: 0, // 总实收金额
totalAccount: 0, // 总金额
TotalUnPaymentAmount: 0 // 未收金额
};
payList.value = [
{
@@ -869,7 +878,7 @@ const closer = () => {
};
// 提交
const submitForm = () => {
if (!handlePayListIsEmpt()) {
if (!handlePayListIsEmpty()) {
ElMessage.warning('请填写完整支付方式和支付金额');
return;
}
@@ -917,6 +926,7 @@ const print_form = ref<BillPrintType>({
totalActualAccount: '',
'totalAccount': '',
'residentName': '',
'payTypeSummary': [],
'detailsList': [],
'printDate': '',
'HouseName': '',
@@ -1033,6 +1043,26 @@ function conFimPrint() {
}, 100);
}
// 删除
async function handleDelete(row: billlistType | false) {
if (row) {
await proxy?.$modal.confirm('该信息删除后无法恢复,确定要删除吗?');
billDelete(row.detailsId).then(() => {
ElMessage.success('删除成功');
getList();
});
} else {
if (ids.value.length <= 0) {
return ElMessage.warning('请选择账单!');
}
await proxy?.$modal.confirm('该信息删除后无法恢复,确定要删除吗?');
billDelete(ids.value.map((item) => item.detailsId)).then(() => {
ElMessage.success('删除成功');
getList();
});
}
}
onMounted(() => {
queryParams.value.villageId = villageId;
getList();
@@ -1046,16 +1076,19 @@ onMounted(() => {
// 总 表单
const totalAll = ref({
totalDiscountAmount: 0,
TotalPaymentAmount: 0,
totalAccount: 0
totalDiscountAmount: 0, // 总优惠金额
TotalPaymentAmount: 0, // 总实收金额
totalAccount: 0, // 总金额
TotalUnPaymentAmount: 0 // 未收金额
});
// 多选时 统计总金额,优惠总金额,实付总金额
function handleSelectBill(val: billlistType[]) {
totalAll.value.totalAccount = sum(val.map((item) => item.amount ?? 0));
totalAll.value.TotalPaymentAmount = sum(val.map((item) => item.actualAccount ?? 0));
totalAll.value.totalDiscountAmount = sum(val.map((item) => item.singleDiscountAmount ?? 0));
totalAll.value.TotalUnPaymentAmount = sum(val.map((item) => item.needPayAmount ?? 0));
}
function handleChangePayTypeId(val: string, index: number) {
// 【可选兜底校验】防止异常数据出现重复
const repeatCount = usedPayValues.value.filter((v) => v === val).length;
@@ -1117,7 +1150,7 @@ function handleChangePay(val: string, index: number = -1) {
}
}
function handlePayListIsEmpt() {
function handlePayListIsEmpty() {
if (payList.value.length === 0) {
ElMessage.warning('请添加支付方式');
return false;
@@ -1131,10 +1164,7 @@ function handlePayListIsEmpt() {
item.payAmount === undefined ||
item.payAmount === ''
);
if (invalidIndex !== -1) {
return false;
}
return true;
return invalidIndex === -1;
}
// 校验数字

View File

@@ -10,15 +10,14 @@
clearable
v-model="SearchTime"
@change="
(val) => {
(val: string[]) => {
if (!val) {
queryParams.startDate = '';
queryParams.endDate = '';
return;
}
SearchTime = val;
const days = val;
const [star, end] = days.map((item) => item.split(' ')[0]);
const [star, end] = val.map((item) => item.split(' ')[0]);
queryParams.startDate = star + ' 00:00:00';
queryParams.endDate = end + ' 23:59:59';
}
@@ -38,7 +37,7 @@
<el-button @click="handleExport" v-has-permi="['water:topupRecord:export']" type="warning">导出统计</el-button>
</div>
</template>
<el-table v-loading="loading" border :data="topupRecordList">
<el-table :span-method="handleSpanMethod" 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>
@@ -80,17 +79,43 @@
<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" />
<div class="flex flex-items-center justify-end">
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList">
<template #pageContent>
<div class="totalMoney">共计 {{ totalMoney }} </div>
</template>
</pagination>
</div>
</el-card>
</div>
</template>
<script setup lang="ts">
import { getTopupRecordByDate, type TopupRecordList } from '@/api/system/SdbTopupRecord/index';
import { getTopupRecordByDate, type TopupRecordList } from '@/api/system/SdbTopupRecord';
import { checkPermi } from '@/utils/permission';
import { sum } from '@/utils/money';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const topupRecordList = ref<TopupRecordList[]>([]);
function handleSpanMethod({ rowIndex, columnIndex }) {
if (rowIndex === topupRecordList.value.length - 1) {
const rowspan = 7;
if (columnIndex === 0) {
return [1, rowspan];
}
if (columnIndex < rowspan) {
return [0, 0];
}
if (columnIndex === 8) {
return [0, 0];
}
if (columnIndex === 7) {
return [1, 2];
}
}
return [1, 1];
}
const loading = ref(false);
const total = ref(0);
@@ -105,14 +130,27 @@ const data = reactive({
const SearchTime = ref([]);
const { queryParams } = toRefs(data);
const totalMoney = ref(0);
/** 查询充值记录列表 */
const getList = async () => {
if (!checkPermi(['water:topupRecord:list'])) return;
loading.value = true;
const res = await getTopupRecordByDate(queryParams.value);
topupRecordList.value = res.rows;
topupRecordList.value[topupRecordList.value.length - 1].rechargeTime = '合计';
total.value = res.total;
loading.value = false;
totalMoney.value = sum(
topupRecordList.value.map((item) => {
if (item.id) {
return item.rechargeAmount;
} else {
return 0;
}
})
);
};
onMounted(() => {
@@ -121,7 +159,6 @@ onMounted(() => {
/** 导出按钮操作 */
const handleExport = () => {
// exportTopupRecordByDate();
proxy?.download(
'/topupRecord/water/export',
{
@@ -140,4 +177,14 @@ const handleExport = () => {
.el-form-item {
margin-bottom: 0;
}
.totalMoney {
min-width: 77px;
height: 20px;
line-height: 20px;
color: rgba(79, 79, 79, 1);
font-size: 14px;
text-align: left;
margin: 0 26px;
}
</style>

View File

@@ -40,15 +40,15 @@
<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" width="90">
<el-table-column label="面积" align="center" prop="area" >
<template #default="scope">
<span v-if="scope.row.area">{{ scope.row.area + ' m²' }}</span>
<span v-else> --- </span>
</template>
</el-table-column>
<el-table-column label="车位数量" align="center" prop="parkingCount" width="90" />
<el-table-column label="车位数量" align="center" prop="parkingCount" />
<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">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['area:area:edit']">修改</el-button>
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['area:area:remove']">删除</el-button>

View File

@@ -41,15 +41,15 @@
<el-table v-loading="loading" border :data="carList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<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="userName">
<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="userName">
<template #default="scope"> {{ scope.row.userName }} </template>
</el-table-column>
<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">
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['car:car:edit']">修改</el-button>
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['car:car:remove']">删除</el-button>

View File

@@ -156,7 +156,7 @@
<el-col :span="2"></el-col>
<el-col :span="11">
<el-form-item label="微信" prop="vx">
<el-input maxlength="11" v-model.trim="form.vx" placeholder="请输入微信号码" />
<el-input maxlength="20" v-model.trim="form.vx" placeholder="请输入微信号码" />
</el-form-item>
</el-col>
</el-row>
@@ -279,6 +279,20 @@ const rules = ref({
}
}
],
vx: [
{ required: false, message: '请输入微信号码', trigger: 'blur' },
{
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
if (value === '' || value === null || value === 0) {
return callback();
}
if (validator(value, 'vx')) {
return callback(new Error('请输入正确的微信号码'));
}
return callback();
}
}
],
houseArea: [
{
required: false,

View File

@@ -68,19 +68,10 @@
</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" v-if="scope.row.status === '0'" @click="sign(scope.row)" v-has-permi="['houseRental:houseRental:edit']"
>签约</el-button
>
<el-button
link
type="primary"
v-if="scope.row.status === '0'"
@click="putOnSale(scope.row)"
v-has-permi="['houseRental:houseRental:edit']"
>上架</el-button
>
<el-button link type="primary" v-else @click="putOnSale(scope.row)" v-has-permi="['houseRental:houseRental:edit']">下架</el-button>
<el-button link type="primary" @click="handleMain(scope.row)" v-has-permi="['houseRental:houseRental:edit']">详情</el-button>
<el-button link type="primary" v-if="scope.row.status === '0'" @click="sign(scope.row)">签约</el-button>
<el-button link type="primary" v-if="scope.row.status === '0'" @click="putOnSale(scope.row)">上架</el-button>
<el-button link type="primary" v-else @click="putOnSale(scope.row)">下架</el-button>
<el-button link type="primary" @click="handleMain(scope.row)">详情</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['houseRental:houseRental:query']">编辑</el-button>
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['houseRental:houseRental:remove']">删除</el-button>
</template>
@@ -108,16 +99,16 @@
<el-input disabled maxlength="20" show-word-limit v-model.trim="form.houseArea" placeholder="请输入面积" />
</el-form-item>
<el-form-item label="收费模式" prop="chargeMode">
<el-input v-model.trim="form.chargeMode" placeholder="请输入收费模式" />
<el-input v-model.trim="form.chargeMode" show-word-limit placeholder="请输入收费模式" maxlength="200" />
</el-form-item>
<el-form-item label="收费标准" prop="chargeStandard">
<el-input v-model.trim="form.chargeStandard" placeholder="请输入收费标准" />
<el-input v-model.trim="form.chargeStandard" show-word-limit placeholder="请输入收费标准" maxlength="200" />
</el-form-item>
<el-form-item label="合同编号" prop="contractNo">
<el-input maxlength="20" show-word-limit v-model.trim="form.contractNo" placeholder="请输入合同编号" />
</el-form-item>
<el-form-item label="合同状态" prop="contractStatus">
<el-input v-model.trim="form.contractStatus" placeholder="请输入合同状态" />
<el-input show-word-limit maxlength="200" v-model.trim="form.contractStatus" placeholder="请输入合同状态" />
</el-form-item>
<el-form-item label="租赁起始日" prop="leaseStartDate">
<el-date-picker
@@ -147,9 +138,11 @@
:show-file-list="true"
v-model:file-list="showImgList"
name="files"
:limit="MAX_UPLOAD_FILES"
:onChange="handleChange"
:onExceed="handleExceed"
:multiple="true"
:on-preview="handlePreview"
:auto-upload="false"
drag
:action="uploadApi"
@@ -175,7 +168,7 @@
<script setup name="HouseRental" lang="ts">
import pageHeader from '@/components/Pageheader/index.vue';
import { changeHouseRedientStatus, delHouseRental, HouseRedientSign, HouseRedientSignUpload, listHouseRental } from '@/api/system/houseRental';
import { HouseRentalForm, HouseRentalQuery, HouseRentalVO } from '@/api/system/houseRental/type';
import { HouseRentalQuery, HouseRentalSigningVO, HouseRentalVO } from '@/api/system/houseRental/type';
import { checkPermi } from '@/utils/permission';
import { listHouseUseType_add_house } from '@/api/system/houseUse';
import { validator } from '@/utils/Reg';
@@ -183,8 +176,7 @@ import { UploadFilled } from '@element-plus/icons-vue';
import { ElMessage, UploadUserFile } from 'element-plus';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_rental_status } = toRefs<any>(proxy?.useDict('com_rental_status'));
const { com_rental_method } = toRefs<any>(proxy?.useDict('com_rental_method'));
const { com_rental_status, com_rental_method } = toRefs<any>(proxy?.useDict('com_rental_status', 'com_rental_method'));
const uploadApi = '/houseRental/uploadImages';
const router = useRouter();
@@ -206,7 +198,7 @@ const dialog = reactive<DialogOption>({
title: ''
});
type HouseRentalFormType = HouseRentalForm & {
type HouseRentalFormType = HouseRentalSigningVO & {
villageName?: string;
houseName?: string;
houseArea?: number;
@@ -214,6 +206,9 @@ type HouseRentalFormType = HouseRentalForm & {
};
const initFormData: HouseRentalFormType = {
contractName: '',
'createTime': undefined,
'id': undefined,
'rentalId': undefined,
'contractNo': undefined,
'tenantName': undefined,
@@ -286,7 +281,7 @@ const data = reactive<PageData<HouseRentalFormType, HouseRentalQuery>>({
const { queryParams, form, rules } = toRefs(data);
/** 查询房屋租赁管理列表╬₧2╬╬ */
/** 查询房屋租赁管理列表 */
const getList = async () => {
loading.value = true;
listHouseRental(queryParams.value)
@@ -299,7 +294,7 @@ const getList = async () => {
});
};
/** 取消按钮 */
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
@@ -339,6 +334,10 @@ const handleAdd = () => {
});
};
function handlePreview(uploadFile: UploadFile) {
window.open(uploadFile.url);
}
/** 修改按钮操作 */
const handleUpdate = (row?: HouseRentalVO) => {
const id = row?.id || ids.value[0];
@@ -394,10 +393,11 @@ function sign(row: HouseRentalVO) {
form.value.villageId = info.villageId;
form.value.rentalId = row.id;
if (row.signingList && row.signingList.length > 0) {
const names = row.signingList[0].contractName ? row.signingList[0].contractName.split(',') : [];
showImgList.value = row.signingList[0].contractUrl.split(',').map((item, index) => {
return {
uid: index,
name: row.contractName.split(',')[index],
name: names[index] || item.split('.com/')[1].split('/')[3],
url: item,
isLink: true
};
@@ -424,7 +424,7 @@ const handleExceed = () => {
};
const handleChange = (file: UploadUserFile) => {
// 实时判断当前已存在图片总数
if (showImgList.value.length >= MAX_UPLOAD_FILES) {
if (showImgList.value.length > MAX_UPLOAD_FILES) {
ElMessage.warning(`最多上传${MAX_UPLOAD_FILES}张,无法继续添加`);
// 清除刚选中的文件,防止缓存残留
uploadRef.value?.handleRemove(file);

View File

@@ -46,7 +46,7 @@
<div class="echartsbox flex h-full flex-col">
<div class="echartsactions">
<div
@click="handleEcartsData(item)"
@click="handleEchartsData(item)"
:class="{ active: activeEchartsindex === item.key }"
class="echartsactions_item"
v-for="(item, index) in ecartslist"
@@ -65,11 +65,7 @@
<el-table v-loading="loading" border :data="itemList">
<el-table-column fixed="left" label="日期" width="100" align="center" prop="statDate" />
<el-table-column label="计划巡检任务" width="110" align="center" prop="totalPlans" />
<el-table-column label="按时完成" align="center" prop="completedTasks">
<template #default="scope">
{{ scope.row.completedTasks - scope.row.outCompletedTasks }}
</template>
</el-table-column>
<el-table-column label="按时完成" align="center" prop="completedTasks" />
<el-table-column label="超时完成" align="center" prop="outCompletedTasks" />
<el-table-column label="超时未完成" width="110" align="center" prop="outUncompletedTasks" />
<el-table-column label="进行中" align="center" prop="activeTask" />
@@ -91,9 +87,10 @@
<script setup name="Item" lang="ts">
import EchartsCompontent from '@/components/Echarts/index.vue';
import { listItem, type Request } from '@/api/system/Inspection/index';
import { getNaturalDayDiff, getLastNDays, diffDays, formatDate } from '@/utils/time';
import { listItem, type Request } from '@/api/system/Inspection';
import { diffDays, formatDate, getLastNDays, getNaturalDayDiff } from '@/utils/time';
import { EChartsOption } from 'echarts';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const itemList = ref<any[]>([]);
@@ -101,8 +98,6 @@ const loading = ref(true);
const showSearch = ref(true);
const total = ref(100);
const queryFormRef = ref<ElFormInstance>();
const layout = document.body.clientWidth <= 1500 ? 'total, sizes, prev, pager, next' : 'total, sizes, prev, pager, next,';
const disabledDate = (time: Date) => {
return time.getTime() > Date.now();
@@ -207,14 +202,14 @@ const options = computed<EChartsOption>(() => ({
series: activeSeries.value // 动态系列
}));
//
const diffday = ref(0);
const diffDay = ref(0);
const activeSeries = ref();
const xAxislist = ref([]);
// join Echarts Options object
function handleEcartsOptions(data, name, colorlist = ['#1a75ff', '#f2f9ff']) {
function handleEchartsOptions(data: number[], name: string, colorList: string[] = ['#1a75ff', '#f2f9ff']) {
activeSeries.value = null;
const obj = {
activeSeries.value = {
data: data,
type: 'line' as const,
smooth: true,
@@ -226,31 +221,30 @@ function handleEcartsOptions(data, name, colorlist = ['#1a75ff', '#f2f9ff']) {
y: 0,
x2: 0,
y2: 1, // 从上到下渐变
colorStops: colorlist.map((item, index) => {
colorStops: colorList.map((item, index) => {
return {
offset: index / colorlist.length,
offset: index / colorList.length,
color: item
};
})
}
},
lineStyle: {
color: colorlist[0]
color: colorList[0]
},
itemStyle: {
color: colorlist[0]
color: colorList[0]
},
label: {
show: true,
color: colorlist[0],
color: colorList[0],
position: 'top'
}
};
activeSeries.value = obj;
}
// echarts tabs switch
function handleEcartsData(row: (typeof ecartslist.value)[number]) {
function handleEchartsData(row: (typeof ecartslist.value)[number]) {
activeEchartsindex.value = row.key;
if (row) {
xAxislist.value = [];
@@ -264,16 +258,16 @@ function handleEcartsData(row: (typeof ecartslist.value)[number]) {
});
// 根据 x 轴日期生成数据数组
const xAxisDates = getLastNDays(diffday.value, undefined, 'YYYY/MM/DD'); // 确保格式为 ['2024-04-16', ...]
const xAxisDates = getLastNDays(diffDay.value, undefined, 'YYYY/MM/DD'); // 确保格式为 ['2024-04-16', ...]
const arr = xAxisDates.map((date) => dataMap.get(date) || 0);
xAxislist.value = xAxisDates;
handleEcartsOptions(arr, row.name, [row.color]);
handleEchartsOptions(arr, row.name, [row.color]);
}
}
// 选择日期
function handleStateDate(val) {
diffday.value = diffDays(val);
function handleStateDate(val: string) {
diffDay.value = diffDays(val);
queryParams.value.statDate = `${formatDate(new Date(val), 'YYYY/MM/DD')}-${formatDate(new Date(), 'YYYY/MM/DD')}`;
getList();
}
@@ -282,10 +276,10 @@ function handleStateDate(val) {
const day = 1000 * 60 * 60 * 24;
// search options
function handleQueryDay(val: number) {
const newday = new Date(); // 当前日期
const time = new Date(newday.getTime() - val * day); // 指定日期
diffday.value = val; // 差值
diffday.value = getNaturalDayDiff(time, newday);
const newDay = new Date(); // 当前日期
const time = new Date(newDay.getTime() - val * day); // 指定日期
diffDay.value = val; // 差值
diffDay.value = getNaturalDayDiff(time, newDay);
queryParams.value.statDate = formatDate(time, 'YYYY/MM/DD');
getList();
}
@@ -305,15 +299,16 @@ const getList = async () => {
itemList.value.forEach((item) => {
list.value[0].value += item.totalPlans ?? 0;
list.value[1].value += item.totalTasks ?? 0;
list.value[2].value += item.completedTasks ?? 0;
list.value[4].value += item.outUncompletedTasks ?? 0;
const num = item.outCompletedTasks + item.completedTasks || 0;
list.value[2].value += num;
});
if (!Number.isNaN(+list.value[2].value) && !Number.isNaN(+list.value[1].value)) {
const num = Number(list.value[2].value) / Number(list.value[1].value);
list.value[3].value = Math.min((Number.isNaN(num) ? 0 : num) * 100, 100).toFixed(2) + '%';
}
handleEcartsData(ecartslist.value.find((item) => item.key === activeEchartsindex.value));
handleEchartsData(ecartslist.value.find((item) => item.key === activeEchartsindex.value));
total.value = res.total;
loading.value = false;
};

View File

@@ -11,7 +11,7 @@
<el-input maxlength="20" v-model.trim="form.planName" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="任务时间">
<el-form-item label="任务时间" prop="executeDay">
<div class="flex flex-wrap">
<div
class="week-items"
@@ -29,26 +29,26 @@
</div>
</div>
</el-form-item>
<el-form-item label="任务时间段">
<el-form-item label="任务时间段" prop="taskTime">
<div v-for="(_, index) in taskTime" :key="index" style="display: flex; align-items: center; margin-top: 10px">
<el-time-picker
v-model="taskTime[index]"
@update:model-value="
(val: string[]) => {
const time = val.filter((t) => t[0] && t[1]);
form.taskTime = `${time[0]}-${time[1]}`;
}
"
is-range
range-separator=""
start-placeholder="开始时间"
format="HH:mm"
value-format="HH:mm:00"
value-format="HH:mm"
end-placeholder="结束时间"
style="width: 100%"
/>
</div>
</el-form-item>
<el-form-item label="提醒时间">
<el-select v-model="form.remindTime" placeholder="请选择" style="width: 100%">
<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="计划路线" prop="routeIds">
<el-select @change="handleChangeMap" v-model="form.routeIds" placeholder="请选择" style="width: 100%">
<el-option v-for="item in playlist" :key="item.value" :label="item.routeName" :value="item.id" />
@@ -75,9 +75,6 @@ import { Check } from '@element-plus/icons-vue';
import MapWrapper from '@/components/Map/index.vue';
import { LngLat } from '@/components/Map/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_inspection_remind_tiime } = toRefs<any>(proxy?.useDict('com_inspection_remind_tiime'));
const route = useRoute();
const router = useRouter();
@@ -94,6 +91,8 @@ const form = ref({
const rules = ref({
planName: [{ required: true, message: '请输入巡检计划名称', trigger: 'blur' }],
inspectorIds: [{ required: true, message: '请选择巡检人员', trigger: 'blur' }],
executeDay: [{ required: true, message: '请选择时间', trigger: 'blur' }],
taskTime: [{ required: true, message: '请选择巡检时间段', trigger: 'blur' }],
routeIds: [{ required: true, message: '请选择路线', trigger: 'blur' }]
});
// 初始化 taskTime确保至少有一个时间段
@@ -195,10 +194,6 @@ onMounted(() => {
const formRef = ref();
function submit() {
// 将二维数组转换为字符串,例如 "09:00-11:00; 13:00-15:00"
form.value.taskTime = taskTime.value
.filter((t) => t[0] && t[1]) // 过滤掉未填写的
.map((t) => `${t[0]}-${t[1]}`)
.join('; ');
formRef.value?.validate(async (valid: boolean) => {
if (valid) {

View File

@@ -263,7 +263,7 @@ const cancelForm = () => {
display: flex;
align-items: center;
.label {
width: 100px;
width: 120px;
text-align: right;
margin-right: 10px;
}

View File

@@ -41,14 +41,14 @@
<el-table-column label="计划巡检任务" align="center" prop="totalTasks" />
<el-table-column label="按时完成" align="center" prop="completedTasks">
<template #default="scope">
{{ scope.row.completedTasks - scope.row.outCompletedTasks }}
{{ scope.row.completedTasks }}
</template>
</el-table-column>
<el-table-column label="超时完成" align="center" prop="outCompletedTasks" />
<el-table-column label="超时未完成" align="center" prop="outUncompletedTasks"></el-table-column>
<el-table-column label="进行中" align="center" prop="activeTask" />
<el-table-column label="未开始" align="center" prop="pendingTask" />
<el-table-column label="完成率" align="center" prop="onTimeRateDisplay" />
<el-table-column label="完成率" align="center" prop="completionRateDisplay" />
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
@@ -77,7 +77,7 @@ const data = reactive({
const checkdata = ref([]);
const { queryParams } = toRefs(data);
/** 查询巡检路线列表 */
/** 查询巡检路线列表 ╬╬╬*/
const getList = async () => {
loading.value = true;
list_statapi(queryParams.value)

View File

@@ -20,7 +20,6 @@
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="11">
<el-form-item label="车位面积" prop="parkingArea">

View File

@@ -45,12 +45,13 @@
<div class="label">添加时间</div>
<div class="main">{{ parkingReviewInfo.parking.createTime }}</div>
</div>
<div class="carInfo_item" v-if="parkingReviewInfo.parking.residentName">
<div class="carInfo_item">
<div class="label">业主持有人</div>
<div class="main">
<span>
{{ parkingReviewInfo.parking.residentName }}
</span>
<el-button @click="getUserInfo" type="primary" link style="font-size: smaller; margin-left: 15px">详情</el-button>
</div>
</div>
</div>
@@ -83,19 +84,19 @@
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车牌号</div>
<div class="main">浙B·N6688</div>
<div class="main">{{ parkingReviewInfo.car.carNum }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车辆品牌</div>
<div class="main">宝马</div>
<div class="main">{{ parkingReviewInfo.car.carBrand }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车辆型号</div>
<div class="main">X5</div>
<div class="main">{{ parkingReviewInfo.car.carModel }}</div>
</div>
</el-col>
</el-row>
@@ -103,13 +104,13 @@
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车身颜色</div>
<div class="main">白色</div>
<div class="main">{{ parkingReviewInfo.car.carColor }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="carInfo_item">
<div class="label">备注</div>
<div class="main"></div>
<div class="main">{{ parkingReviewInfo.car.remark }}</div>
</div>
</el-col>
<el-col :span="8"> </el-col>
@@ -120,8 +121,13 @@
<div class="label">车辆照片</div>
<div class="main">
<el-image
v-for="(item, index) in parkingReviewInfo.car.carImageUrlList"
:key="index"
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"
:src="item"
:initial-index="index"
:preview-src-list="parkingReviewInfo.car.carImageUrlList"
preview-teleported
></el-image>
</div>
</div>
@@ -136,20 +142,97 @@
</el-col>
</el-row>
</div>
<el-dialog width="500" @close="handleClose" v-model="MainForm.visible" title="车位持有人详情">
<div class="item">
<div class="label">姓名</div>
<div class="value">{{ MainFormInfo.name }}</div>
</div>
<div class="item">
<div class="label">类型</div>
<div class="value">
<DictTag :value="MainFormInfo.type" :options="com_resident_relationship"></DictTag>
</div>
</div>
<div class="item">
<div class="label">状态</div>
<div class="value">
<DictTag :value="MainFormInfo.status" :options="com_review"></DictTag>
</div>
</div>
<div class="item">
<div class="label">证件号码</div>
<div class="value">{{ MainFormInfo.idCard }}</div>
</div>
<div class="item">
<div class="label">手机号码</div>
<div class="value">{{ MainFormInfo.phone }}</div>
</div>
<div class="item">
<div class="label">房间</div>
<div class="value">{{ MainFormInfo.houseName }}</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">关闭</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { getParkingReviewInfo } from '@/api/system/parking';
import { getParkingReviewInfo, getParkingResidentInfo } from '@/api/system/parking';
import DictTag from '@/components/DictTag/index.vue';
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'));
const { com_parking_status, com_parking_type, com_review, com_resident_relationship } = toRefs<any>(
proxy?.useDict('com_parking_status', 'com_parking_type', 'com_review', 'com_resident_relationship')
);
const route = useRoute();
const id = ref('');
const MainForm = ref({
visible: false
});
// 持有人信息
const MainFormInfo = ref({
id: '',
name: '',
type: '',
status: '',
idCard: '',
phone: '',
houseName: ''
});
// 重置模态框
function resetMainFormInfo() {
MainFormInfo.value = {
id: '',
name: '',
type: '',
status: '',
idCard: '',
phone: '',
houseName: ''
};
}
// 查询 持有人信息
function getUserInfo() {
resetMainFormInfo();
getParkingResidentInfo(parkingReviewInfo.value.parking.residentId).then((res) => {
MainFormInfo.value = res.data;
});
MainForm.value.visible = true;
}
// 关闭模态框
function handleClose() {
resetMainFormInfo();
MainForm.value.visible = false;
}
type parkingReviewType = {
parking: {
id: string;
@@ -172,7 +255,24 @@ type parkingReviewType = {
createTime: string;
delFlag: any;
};
car: any;
car: {
'id': string;
'areaId': null;
'villageId': string;
'parkingId': string;
'residentId': null;
'residentName': null;
'carNum': string;
'carBrand': string;
'carModel': string;
'carColor': string;
'remark': null;
'carImageUrl': string;
'userName': null;
'userId': string;
carImageUrlList?: string[];
};
parkingReviewProcess: {
submitStatus: null;
propertyStatus: null;
@@ -205,7 +305,22 @@ const parkingReviewInfo = ref<parkingReviewType>({
'createTime': '',
'delFlag': null
},
car: null,
car: {
'id': '',
'areaId': null,
'villageId': '',
'parkingId': '',
'residentId': null,
'residentName': null,
'carNum': '',
'carBrand': '',
'carModel': '',
'carColor': '',
'remark': null,
'carImageUrl': '',
'userName': null,
'userId': ''
},
parkingReviewProcess: {
submitStatus: null,
propertyStatus: null,
@@ -220,6 +335,9 @@ function getInfo() {
if (route.query.id) {
id.value = route.query.id as string;
getParkingReviewInfo(id.value).then((res) => {
if (res.data.car) {
res.data.car.carImageUrlList = res.data.car.carImageUrl.split(',').filter(Boolean) ?? [];
}
parkingReviewInfo.value = res.data;
});
}
@@ -233,6 +351,19 @@ getInfo();
.ResidentMainBox {
display: flex;
flex-direction: column;
.item {
display: flex;
align-items: center;
margin-bottom: 20px;
.label {
width: 120px;
text-align: right;
font-weight: bold;
margin-right: 10px;
}
}
.ResidentMainBody {
flex: 1;
margin-top: 20px;
@@ -260,6 +391,7 @@ getInfo();
}
}
}
&:deep(div.el-step__head.is-process) {
& > div.el-step__line {
width: 0;

View File

@@ -47,7 +47,6 @@
<span>
{{ parkingReviewInfo.parking.residentName }}
</span>
<el-button type="primary" link style="font-size: smaller">详情</el-button>
</div>
</div>
<div class="carInfo_item">
@@ -66,7 +65,7 @@
</el-card>
</div>
<!-- 车辆信息 -->
<div class="mb-10">
<div class="mb-10" v-if="!showCar">
<el-card>
<template #header>
<div class="card-header">
@@ -78,19 +77,19 @@
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车牌号</div>
<div class="main">浙B·N6688</div>
<div class="main">{{ parkingReviewInfo.car.carNum }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车辆品牌</div>
<div class="main">宝马</div>
<div class="main">{{ parkingReviewInfo.car.carBrand }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车辆型号</div>
<div class="main">X5</div>
<div class="main">{{ parkingReviewInfo.car.carModel }}</div>
</div>
</el-col>
</el-row>
@@ -98,13 +97,13 @@
<el-col :span="8">
<div class="carInfo_item">
<div class="label">车身颜色</div>
<div class="main">白色</div>
<div class="main">{{ parkingReviewInfo.car.carColor }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="carInfo_item">
<div class="label">备注</div>
<div class="main"></div>
<div class="main">{{ parkingReviewInfo.car.remark }}</div>
</div>
</el-col>
<el-col :span="8"> </el-col>
@@ -115,8 +114,13 @@
<div class="label">车辆照片</div>
<div class="main">
<el-image
v-for="(item, index) in parkingReviewInfo.car.carImageUrlList"
:key="index"
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"
:src="item"
:initial-index="index"
:preview-src-list="parkingReviewInfo.car.carImageUrlList"
preview-teleported
></el-image>
</div>
</div>
@@ -205,6 +209,8 @@ 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'));
const showCar = true;
/** 住户 提交状态 */
enum submitStatus {
/** 未提交 */
@@ -239,7 +245,23 @@ const id = ref('');
type parkingReviewType = {
parking: parkingType;
car: any;
car: {
'id': string;
'areaId': null;
'villageId': string;
'parkingId': string;
'residentId': null;
'residentName': null;
'carNum': string;
'carBrand': string;
'carModel': string;
'carColor': string;
'remark': null;
'carImageUrl': string;
'userName': null;
'userId': string;
carImageUrlList?: string[];
};
parkingReviewProcess: parkingReviewProcess;
};
@@ -271,7 +293,6 @@ type parkingReviewProcess = {
propertyTime: string;
certificationTime: string;
};
const parkingReviewInfo = ref<parkingReviewType>({
parking: {
'id': '',
@@ -291,7 +312,22 @@ const parkingReviewInfo = ref<parkingReviewType>({
'remark': '',
'createTime': ''
},
car: null,
car: {
'id': '',
'areaId': null,
'villageId': '',
'parkingId': '',
'residentId': null,
'residentName': null,
'carNum': '',
'carBrand': '',
'carModel': '',
'carColor': '',
'remark': null,
'carImageUrl': '',
'userName': null,
'userId': ''
},
parkingReviewProcess: {
id: null,
submitStatus: null,
@@ -312,6 +348,9 @@ function getInfo() {
if (route.query.id) {
id.value = route.query.id as string;
getParkingReviewInfo(id.value).then((res) => {
if (res.data.car) {
res.data.car.carImageUrlList = res.data.car.carImageUrl.split(',').filter(Boolean) ?? [];
}
parkingReviewInfo.value = res.data;
handleActiveStaus(res.data.parkingReviewProcess);
});

View File

@@ -85,7 +85,14 @@
<div class="w-full h-full flex mt-2">
<div class="title">审批意见</div>
<div class="preivewBodybox">
<el-input v-model="reviewInfo.propertyReviewFeedback" placeholder="请输入" type="textarea" :rows="5"></el-input>
<el-input
maxlength="200"
show-word-limit
v-model.trim="reviewInfo.propertyReviewFeedback"
placeholder="请输入"
type="textarea"
:rows="5"
></el-input>
<div class="actions">
<el-button type="primary" @click="updatePass('1')">审核通过</el-button>
<el-button type="danger" @click="updatePass('2')">审核不通过</el-button>

View File

@@ -183,7 +183,12 @@ const options2 = shallowRef<EChartsOption>({
data: [
{ value: 0, name: '支付宝', itemStyle: { color: '#0a74fe' } },
{ value: 0, name: '微信', itemStyle: { color: '#f74043' } },
{ value: 0, name: '线下', itemStyle: { color: '#fcd152' } }
{ value: 0, name: '宜当付', itemStyle: { color: '#fcd152' } },
{ value: 0, name: '现金', itemStyle: { color: '#fcd152' } },
{ value: 0, name: '银联', itemStyle: { color: '#fcd152' } },
{ value: 0, name: '转账', itemStyle: { color: '#fcd152' } },
{ value: 0, name: '押金抵顶', itemStyle: { color: '#fcd152' } },
{ value: 0, name: '房产抵顶', itemStyle: { color: '#fcd152' } }
]
}
]
@@ -214,7 +219,12 @@ function updatePayMethod(dataFrom: PayMentMethod): EChartsOption {
data: [
{ value: Number(dataFrom.alipayAmount) ?? 0, name: '支付宝', itemStyle: { color: '#0a74fe' } },
{ value: Number(dataFrom.wechatAmount) ?? 0, name: '微信', itemStyle: { color: '#f74043' } },
{ value: Number(dataFrom.offlineAmount) ?? 0, name: '线下', itemStyle: { color: '#fcd152' } }
{ value: Number(dataFrom.yidangAmount) ?? 0, name: '宜当付', itemStyle: { color: '#fcd152' } },
{ value: Number(dataFrom.cashAmount) ?? 0, name: '现金', itemStyle: { color: '#4b5cc4' } },
{ value: Number(dataFrom.unionPayAmount) ?? 0, name: '银联', itemStyle: { color: '#8d4bbb' } },
{ value: Number(dataFrom.transferAmount) ?? 0, name: '转账', itemStyle: { color: '#424c50' } },
{ value: Number(dataFrom.depositOffsetAmount) ?? 0, name: '押金抵顶', itemStyle: { color: '#00bc12' } },
{ value: Number(dataFrom.propertyOffsetAmount) ?? 0, name: '房产抵顶', itemStyle: { color: '#ff7500' } }
]
}
]
@@ -504,8 +514,17 @@ const payMethodFrom = ref({
'wechatPercent': '0',
'alipayAmount': '0',
'alipayPercent': '0',
'offlineAmount': '0',
'offlinePercent': '0'
'yidangAmount': '0',
'yidangPercent': '0',
'cashAmount': '0',
'cashPercent': '0',
'unionPayPercent': '0',
'transferAmount': '0',
'transferPercent': '0',
'depositOffsetAmount': '0',
'depositOffsetAmountPercent': '0',
'propertyOffsetAmount': '0',
'propertyOffsetAmountPercent': '0'
});
function getList() {

View File

@@ -35,14 +35,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="楼栋名" 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="buildingName" />
<el-table-column label="单元号" show-overflow-tooltip align="center" prop="unitName" />
<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" show-overflow-tooltip />
<el-table-column label="操作" width="150" align="center" fixed="right" class-name="small-padding fixed-width">
<el-table-column label="操作" width="150" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['storeroom:storeroom:edit']">修改</el-button>
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['storeroom:storeroom:remove']">删除</el-button>

View File

@@ -21,11 +21,9 @@
{{ form.costPrice }}
</el-form-item>
<el-form-item label="当前库存" prop="stockNum">
<el-input-number v-model="form.stockNum" placeholder="请输入当前库存" />
{{ form.stockNum }}
</el-form-item>
<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>
@@ -37,7 +35,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import PageHeader from '@/components/Pageheader/index.vue';
import { listStockMain, listStockUpdate } from '@/api/system/Tstock';
import { listStockMain } from '@/api/system/Tstock';
const router = useRouter();
const route = useRoute();
@@ -70,18 +68,18 @@ if (route.query.id) {
}
// !== 提交 =============================================================================
// 提交
const submitForm = () => {
formRef.value?.validate(async (valid: boolean) => {
if (valid) {
if (userid.value) {
listStockUpdate(form.value).then((res) => {
ElMessage.success('编辑成功');
cancelForm();
});
}
}
});
};
// const submitForm = () => {
// formRef.value?.validate(async (valid: boolean) => {
// if (valid) {
// if (userid.value) {
// listStockUpdate(form.value).then(() => {
// ElMessage.success('编辑成功');
// cancelForm();
// });
// }
// }
// });
// };
// 推出
const cancelForm = () => {
router.back();

View File

@@ -50,7 +50,7 @@
<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-has-permi="['warehouse:edit:inventory']">编辑</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['warehouse:edit:inventory']">查看</el-button>
</template>
</el-table-column>
</el-table>

View File

@@ -31,11 +31,11 @@
<el-option v-for="(item, index) in warehouselist" :key="index" :label="item.warehouseName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="出库状态" prop="operateStatus">
<el-radio-group v-model="form.operateStatus">
<el-radio v-for="(item, index) in com_stock_out_status" :key="index" :value="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- <el-form-item label="出库状态" prop="operateStatus">-->
<!-- <el-radio-group v-model="form.operateStatus">-->
<!-- <el-radio v-for="(item, index) in com_stock_out_status" :key="index" :value="item.value">{{ item.label }}</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<el-form-item label="领用人" prop="leader">
<el-input maxlength="20" v-model.trim="form.leader" placeholder="请输入领用人" />
</el-form-item>
@@ -62,12 +62,12 @@
<el-table-column label="出库价" align="center">
<template #default="scope">
<!-- <el-input v-model.trim.number="scope.row.outPrice"></el-input> -->
<el-input-number maxlength="7" v-model="scope.row.outPrice" :min="0" placeholder="价格" />
<el-input-number :min="0" :max="9999999" maxlength="7" v-model.trim.number="scope.row.outPrice" placeholder="价格" />
</template>
</el-table-column>
<el-table-column label="数量" align="center" prop="inNo">
<template #default="scope">
<el-input-number maxlength="7" v-model="scope.row.outNum" :min="0" placeholder="个数" />
<el-input-number :max="9999999" maxlength="7" v-model.trim.number="scope.row.outNum" :min="0" placeholder="个数" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark">
@@ -95,10 +95,7 @@ import { listSupplier } from '@/api/system/Tsupplier';
import { listWarehouse } from '@/api/system/Twarehouse';
import { MaterialVO } from '@/api/system/Tmaterial/type';
import { addStockOut, getStockOut, updateStockOut } from '@/api/system/TissueOut';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_stock_out_status } = toRefs<any>(proxy?.useDict('com_stock_out_status'));
interface tabletype extends MaterialVO {
interface tableType extends MaterialVO {
costPrice?: number; // 成本价
inNum?: number; // 成本价
}
@@ -111,13 +108,13 @@ const formRef = ref();
const form = ref({
id: null,
outNo: null, //
operateStatus: '0', //
operateStatus: '1', //
outDate: '', // 出库日期
supplierId: '', // 供应商
warehouseId: '', // 出库仓库
leader: '', // 备注
remark: '', // 备注
items: [] as tabletype[] // 联系人
items: [] as tableType[] // 联系人
});
const itemsid = computed(() => {
return form.value.items.map((item) => item.id).join(',');

View File

@@ -20,14 +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-has-permi="['warehouse:add:issueout']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-has-permi="['system:stockOut:remove']"
>删除</el-button
>
</el-col> -->
<right-toolbar
:disable-delete="multiple"
:disable-edit="single"
@@ -66,7 +58,7 @@
</template>
<script setup name="StockOut" lang="ts">
import { listStockOut, delStockOut, addStockOut, updateStockOut } from '@/api/system/TissueOut/index';
import { listStockOut, delStockOut } from '@/api/system/TissueOut';
import { StockOutVO, StockOutQuery, StockOutForm } from '@/api/system/TissueOut/type';
import { checkPermi } from '@/utils/permission';
@@ -74,7 +66,6 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_stock_out_status } = toRefs<any>(proxy?.useDict('com_stock_out_status'));
const stockOutList = ref<StockOutVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
@@ -83,12 +74,6 @@ const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const stockOutFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: StockOutForm = {
id: undefined,
@@ -122,7 +107,7 @@ const data = reactive<PageData<StockOutForm, StockOutQuery>>({
}
});
const { queryParams, form, rules } = toRefs(data);
const { queryParams } = toRefs(data);
/** 查询出库主列表 */
const getList = async () => {
@@ -133,18 +118,6 @@ const getList = async () => {
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
stockOutFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
@@ -173,7 +146,7 @@ const handleAdd = () => {
};
/** 修改按钮操作 */
const handleMain = async (row?: StockOutVO) => {
const handleMain = (row?: StockOutVO) => {
router.push({
path: '/warehouse/stockoutMain',
query: {
@@ -181,22 +154,22 @@ const handleMain = async (row?: StockOutVO) => {
}
});
};
/** 提交按钮 */
const submitForm = () => {
stockOutFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateStockOut(form.value).finally(() => (buttonLoading.value = false));
} else {
await addStockOut(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
// /** 提交按钮 */
// const submitForm = () => {
// stockOutFormRef.value?.validate(async (valid: boolean) => {
// if (valid) {
// buttonLoading.value = true;
// if (form.value.id) {
// await updateStockOut(form.value).finally(() => (buttonLoading.value = false));
// } else {
// await addStockOut(form.value).finally(() => (buttonLoading.value = false));
// }
// proxy?.$modal.msgSuccess('操作成功');
// dialog.visible = false;
// await getList();
// }
// });
// };
/** 删除按钮操作 */
const handleDelete = async (row?: StockOutVO) => {
@@ -207,17 +180,6 @@ const handleDelete = async (row?: StockOutVO) => {
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'system/stockOut/export',
{
...queryParams.value
},
`stockOut_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});

View File

@@ -73,12 +73,12 @@ const submitForm = () => {
formRef.value?.validate(async (valid: boolean) => {
if (valid) {
if (userid.value) {
updateMaterial(form.value).then((res) => {
updateMaterial(form.value).then(() => {
ElMessage.success('编辑成功');
cancelForm();
});
} else {
addMaterial(form.value).then((res) => {
addMaterial(form.value).then(() => {
ElMessage.success('添加成功');
cancelForm();
});

View File

@@ -20,14 +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-has-permi="['system:material:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-has-permi="['system:material:remove']"
>删除</el-button
>
</el-col> -->
<right-toolbar
:disable-delete="multiple"
:disable-edit="single"
@@ -187,7 +179,7 @@ const handleAdd = () => {
};
/** 修改按钮操作 */
const handleUpdate = async (row?: MaterialVO) => {
const handleUpdate = (row?: MaterialVO) => {
const _id = row?.id || ids.value[0];
router.push({
path: '/warehouse/editMaterial',
@@ -222,18 +214,6 @@ const handleDelete = async (row?: MaterialVO) => {
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'system/material/export',
{
...queryParams.value
},
`material_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});

View File

@@ -13,13 +13,13 @@
<table border>
<tbody>
<tr>
<td style="width: 60px">序号</td>
<td style="width: 90px;">序号</td>
<td>物资名称</td>
<td>品牌</td>
<td>规格型号</td>
<td style="width: 40px">单位</td>
<td style="width: 80px">单位</td>
<td>供应商</td>
<td style="width: 40px">数量</td>
<td style="width: 80px">数量</td>
<td style="width: 80px">单价</td>
<td>合计</td>
<td>备注</td>
@@ -31,7 +31,7 @@
<td>{{ item.model }}</td>
<td>{{ item.unit }}</td>
<td>{{ form.supplierName }}</td>
<td>{{ item.stockNum }}</td>
<td>{{ item.inNum }}</td>
<td>{{ item.costPrice }}</td>
<td>{{ item.totalPrice }}</td>
<td>{{ item.remark }}</td>

View File

@@ -31,11 +31,11 @@
<el-option v-for="(item, index) in warehouselist" :key="index" :label="item.warehouseName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="入库状态" prop="operateStatus">
<el-radio-group v-model="form.operateStatus">
<el-radio v-for="(item, index) in com_stock_in_status" :key="index" :value="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- <el-form-item label="入库状态" prop="operateStatus">-->
<!-- <el-radio-group v-model="form.operateStatus">-->
<!-- <el-radio v-for="(item, index) in com_stock_in_status" :key="index" :value="item.value">{{ item.label }}</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<el-form-item label="制单人" prop="leader">
<el-input maxlength="20" v-model.trim="form.leader" placeholder="请输入制单人" />
</el-form-item>
@@ -61,12 +61,18 @@
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="成本价" align="center" prop="inNo">
<template #default="scope">
<el-input maxlength="7" v-model.trim.number="scope.row.costPrice" placeholder="请输入"></el-input>
<el-input-number
maxlength="7"
:min="0"
:max="9999999"
v-model.trim.number="scope.row.costPrice"
placeholder="请输入"
></el-input-number>
</template>
</el-table-column>
<el-table-column label="数量" align="center" prop="inNo">
<template #default="scope">
<el-input maxlength="7" v-model.trim.number="scope.row.inNum" placeholder="请输入"></el-input>
<el-input-number maxlength="7" :min="0" :max="9999999" v-model.trim.number="scope.row.inNum" placeholder="请输入"></el-input-number>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark">
@@ -95,10 +101,7 @@ import { listWarehouse } from '@/api/system/Twarehouse';
import { addStockIn, getStockIn, updateStockIn } from '@/api/system/TPurchaseIn';
import { MaterialVO } from '@/api/system/Tmaterial/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_stock_in_status } = toRefs<any>(proxy?.useDict('com_stock_in_status'));
interface tabletype extends MaterialVO {
interface tableType extends MaterialVO {
costPrice?: number; // 成本价
inNum?: number; // 成本价
}
@@ -117,7 +120,7 @@ const form = ref({
warehouseId: '', // 入库仓库
leader: '', // 备注
remark: '', // 备注
items: [] as tabletype[] // 联系人
items: [] as tableType[] // 联系人
});
const itemsid = computed(() => {
return form.value.items.map((item) => item.id).join(',');
@@ -159,7 +162,7 @@ function init() {
init();
function handleChangeitem(row: MaterialVO[]) {
const arr = row
form.value.items = row
.map((item) => {
if (!item.id) return null;
const find = form.value.items.find((i) => i.id === item.id);
@@ -177,7 +180,6 @@ function handleChangeitem(row: MaterialVO[]) {
}
})
.filter((item) => item !== null);
form.value.items = arr;
}
function handleDeleteRow(id: string) {
const findindex = form.value.items.findIndex((item) => item.id === id);

View File

@@ -57,7 +57,7 @@ const rules = ref({
contactPhone: [
{ required: false, message: '请输入 联系电话', trigger: 'blur' },
{
validator: (_, value) => {
validator: (_: any, value: string) => {
if (value === '') {
return true;
}
@@ -71,7 +71,7 @@ const rules = ref({
email: [
{ required: false, message: '请输入 邮箱', trigger: 'blur' },
{
validator: (_, value) => validator(value, 'email'),
validator: (_: any, value: string | number) => validator(value, 'email'),
message: '请输入正确的邮箱格式',
trigger: 'blur'
}
@@ -98,12 +98,12 @@ const submitForm = () => {
formRef.value?.validate(async (valid: boolean) => {
if (valid) {
if (userid.value) {
updateSupplier(form.value).then((res) => {
updateSupplier(form.value).then(() => {
ElMessage.success('编辑成功');
cancelForm();
});
} else {
addSupplier(form.value).then((res) => {
addSupplier(form.value).then(() => {
ElMessage.success('添加成功');
cancelForm();
});

View File

@@ -20,14 +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-has-permi="['warehouse:add:supplier']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-has-permi="['system:supplier:remove']"
>删除</el-button
>
</el-col> -->
<right-toolbar
:disable-delete="multiple"
:disable-edit="single"
@@ -92,7 +84,7 @@
</template>
<script setup name="Supplier" lang="ts">
import { listSupplier, delSupplier, addSupplier, updateSupplier } from '@/api/system/Tsupplier/index';
import { listSupplier, delSupplier, addSupplier, updateSupplier } from '@/api/system/Tsupplier';
import { SupplierVO, SupplierQuery, SupplierForm } from '@/api/system/Tsupplier/type';
import { checkPermi } from '@/utils/permission';
@@ -195,7 +187,7 @@ const handleAdd = () => {
};
/** 修改按钮操作 */
const handleUpdate = async (row?: SupplierVO) => {
const handleUpdate = (row?: SupplierVO) => {
const _ids = row?.id || ids.value[0];
router.push({
path: '/warehouse/editSupplier',
@@ -231,17 +223,6 @@ const handleDelete = async (row?: SupplierVO) => {
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'system/supplier/export',
{
...queryParams.value
},
`supplier_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});

View File

@@ -102,7 +102,7 @@
</template>
<script setup name="Warehouse" lang="ts">
import { listWarehouse, delWarehouse, addWarehouse, updateWarehouse } from '@/api/system/Twarehouse/index';
import { listWarehouse, delWarehouse, addWarehouse, updateWarehouse } from '@/api/system/Twarehouse';
import { WarehouseVO, WarehouseQuery, WarehouseForm } from '@/api/system/Twarehouse/type';
import { checkPermi } from '@/utils/permission';
@@ -207,7 +207,7 @@ const handleAdd = () => {
};
/** 修改按钮操作 */
const handleUpdate = async (row?: WarehouseVO) => {
const handleUpdate = (row?: WarehouseVO) => {
const _ids = row?.id || ids.value[0];
router.push({
path: '/warehouse/editWarehouse',
@@ -244,7 +244,7 @@ const handleDelete = async (row?: WarehouseVO) => {
};
// 切换状态
const handleChangeSwitch = (val: string, row) => {
const handleChangeSwitch = (val: string, row: WarehouseForm) => {
updateWarehouse(row)
.then(() => {
ElMessage.success('修改状态成功');

View File

@@ -4,7 +4,7 @@
<div class="iconbox">
<div
class="icon_box_text"
:title="`${weather_icon.title} ${weather_icon.wind_direction} ${weather_icon.wind_power} 温度${weather_icon.temperature}°C`"
:title="`${weather_icon.title} ${weather_icon.wind_direction} ${weather_icon.wind_power} 温度${weather_icon.temperature ?? ''}°C`"
>
{{ getWeatherIcon(weather_icon.iconvalue) }}
</div>
@@ -15,7 +15,9 @@
</div>
</div>
<div class="villageinfo flex-1">
<div class="villagename">{{ props.villageinfo.villageName }}</div>
<div class="villagename" :title="props.villageinfo.villageName">
{{ props.villageinfo.villageName }}
</div>
<div class="week">
<span style="padding-right: 10px">{{
new Intl.DateTimeFormat('zh-cn', {
@@ -74,7 +76,6 @@ const weather_icon = ref({
gap: 30px;
.tips {
font-size: small;
color: #ffffff77;
margin-top: 10px;
font-size: 0.8rem;
@@ -91,14 +92,11 @@ const weather_icon = ref({
position: relative;
z-index: 2;
cursor: default;
margin-right: 20px;
margin: 0 auto;
.icon_box_text {
width: 100%;
height: 100%;
line-height: 1;
font-size: 70px;
text-align: center;
display: flex;
justify-content: center;
@@ -113,6 +111,10 @@ const weather_icon = ref({
.villageinfo {
margin-left: 20px;
.villagename {
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 30px;
font-weight: 500;
font-size: 1.2rem;