Compare commits
11 Commits
981d059ceb
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cce5ad5e75 | ||
|
|
2f70107415 | ||
|
|
f6a7eb1b4e | ||
|
|
292ee1a6dd | ||
|
|
e8564269b0 | ||
|
|
de4bae3bc1 | ||
|
|
466ec4675e | ||
|
|
e4417f35b1 | ||
|
|
bfdfa05cd7 | ||
|
|
2ea75ee5ef | ||
|
|
b83735e993 |
@@ -9,9 +9,9 @@ VITE_APP_ENV='development'
|
|||||||
# 开发环境
|
# 开发环境
|
||||||
VITE_APP_BASE_API='/dev-api'
|
VITE_APP_BASE_API='/dev-api'
|
||||||
# # 开发环境 接口代理地址
|
# # 开发环境 接口代理地址
|
||||||
#VITE_APP_PROXY_API='http://192.168.1.222:8080'
|
VITE_APP_PROXY_API='http://192.168.0.222:8080'
|
||||||
# 开发环境 接口代理地址
|
# 开发环境 接口代理地址
|
||||||
VITE_APP_PROXY_API='http://192.168.1.6:8080'
|
#VITE_APP_PROXY_API='http://192.168.0.199:8080'
|
||||||
# 图片基础地址
|
# 图片基础地址
|
||||||
VITE_IMG_URL='http://192.168.1.222:8080'
|
VITE_IMG_URL='http://192.168.1.222:8080'
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ VITE_LOGIN_BACK_URL_WORKBENCH_TRUE=false
|
|||||||
VITE_APP_SHOW_WORK_PLATFORM=true
|
VITE_APP_SHOW_WORK_PLATFORM=true
|
||||||
|
|
||||||
# 地图类型 天地图 WGS84 高德地图 GCJ02, 高德地图 需要在高德地图官网申请key
|
# 地图类型 天地图 WGS84 高德地图 GCJ02, 高德地图 需要在高德地图官网申请key
|
||||||
VITE_APP_MAP_TYPE='GCJ02'
|
VITE_APP_MAP_TYPE='WGS84'
|
||||||
|
|
||||||
# 高德地图key 建议放入环境变量中,避免泄露
|
# 高德地图key 建议放入环境变量中,避免泄露
|
||||||
VITE_GCJ02_KEY_GD='8e302fe1be5f4db62bc734db23dca149'
|
VITE_GCJ02_KEY_GD='8e302fe1be5f4db62bc734db23dca149'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ export interface ChargeTypeVO {
|
|||||||
/**
|
/**
|
||||||
* 收费类型表id
|
* 收费类型表id
|
||||||
*/
|
*/
|
||||||
id: string | number;
|
id: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收费类型名称
|
* 收费类型名称
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ export const listItem = (query?: Request): AxiosPromise<any[]> => {
|
|||||||
params: query
|
params: query
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
export const overview = (query?: Request): AxiosPromise<any[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/inspection/data/generate/overview',
|
||||||
|
method: 'POST',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
export interface Request {
|
export interface Request {
|
||||||
/**
|
/**
|
||||||
* 进行中的任务数
|
* 进行中的任务数
|
||||||
@@ -73,7 +80,7 @@ export interface Request {
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const list_statapi = (query?: { taskTimeBegin: string; taskTimeEnd: string }): AxiosPromise<any[]> => {
|
export const list_statapi = (query?: { queryDateBegin: string; queryDateEnd: string }): AxiosPromise<any[]> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/inspection/data/role/stat',
|
url: '/inspection/data/role/stat',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
|||||||
@@ -70,6 +70,6 @@ export const changePlanStatus = (id: string, status: string) => {
|
|||||||
return request({
|
return request({
|
||||||
url: '/inspection/plan/changeStatus',
|
url: '/inspection/plan/changeStatus',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: { id, status }
|
params: { id, status }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ export interface RecordQuery extends PageQuery {
|
|||||||
* 任务名称
|
* 任务名称
|
||||||
*/
|
*/
|
||||||
taskName?: string;
|
taskName?: string;
|
||||||
|
|
||||||
|
taskTimeBegin?: string;
|
||||||
|
taskTimeEnd?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DetailsVo {
|
export interface DetailsVo {
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ export interface TaskQuery extends PageQuery {
|
|||||||
* 巡检任务名称
|
* 巡检任务名称
|
||||||
*/
|
*/
|
||||||
taskName?: string;
|
taskName?: string;
|
||||||
|
taskTimeBegin?: string;
|
||||||
|
taskTimeEnd?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关联巡检计划ID
|
* 关联巡检计划ID
|
||||||
|
|||||||
@@ -67,3 +67,33 @@ export const delQuestionnaire = (ids: string | string[], vailid: boolean = true)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* 查询问卷调查回答列表
|
||||||
|
*/
|
||||||
|
export const getQuestionnaireAnswer = (
|
||||||
|
{
|
||||||
|
pageSize,
|
||||||
|
pageNum,
|
||||||
|
questionnaireId
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
return request({
|
||||||
|
url: '/questionnaireAnswer/list',
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
pageSize,
|
||||||
|
pageNum,
|
||||||
|
questionnaireId,
|
||||||
|
answerStatus: '1'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 查询问卷调查回答详情
|
||||||
|
*/
|
||||||
|
export const getQuestionnaireAnswerMain = (id: string) => {
|
||||||
|
return request({
|
||||||
|
url: '/questionnaireAnswer/' + id,
|
||||||
|
method: 'GET'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from 'axios';
|
||||||
import { RepairProjectVO, RepairProjectForm, RepairProjectQuery } from './type';
|
import { RepairProjectVO, RepairProjectForm, RepairProjectQuery, RepairProjectQueryNoPage } from './type';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询报修维修项目管理列表
|
* 查询报修维修项目管理列表
|
||||||
@@ -67,7 +67,7 @@ export const delRepairProject = (id: string | number | Array<string | number>) =
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const gettreelistRepairProject = (query?: RepairProjectQuery): AxiosPromise<RepairProjectVO[]> => {
|
export const gettreelistRepairProject = (query?: RepairProjectQueryNoPage): AxiosPromise<RepairProjectVO[]> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/repairProject/treeList',
|
url: '/repairProject/treeList',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
|||||||
@@ -106,3 +106,34 @@ export interface RepairProjectQuery extends PageQuery {
|
|||||||
*/
|
*/
|
||||||
status?: string;
|
status?: string;
|
||||||
}
|
}
|
||||||
|
export interface RepairProjectQueryNoPage {
|
||||||
|
/**
|
||||||
|
* 维修项目名
|
||||||
|
*/
|
||||||
|
projectName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父级项目id
|
||||||
|
*/
|
||||||
|
parentId?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目类型 0公共报修 1个人报修
|
||||||
|
*/
|
||||||
|
projectType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目层级 0,1
|
||||||
|
*/
|
||||||
|
projectLevel?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序 (数越小越靠前)
|
||||||
|
*/
|
||||||
|
sortOrder?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 0启用 1停用
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ export const cashQuery = (data: { residentName?: string; queryType: number }): A
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type billlistType = {
|
export type billlistType = {
|
||||||
|
/**
|
||||||
|
* 类型 0 物业费 1 车位管理费 2 垃圾处理费 3 租金 4 押金
|
||||||
|
*/
|
||||||
|
detailsType: string;
|
||||||
|
unitNoId: string;
|
||||||
needPayAmount: string; // 需要支付金额
|
needPayAmount: string; // 需要支付金额
|
||||||
actualAccount: string; // 实际支付金额
|
actualAccount: string; // 实际支付金额
|
||||||
singleDiscountAmount: string; // 单笔优惠金额
|
singleDiscountAmount: string; // 单笔优惠金额
|
||||||
@@ -52,7 +57,7 @@ export type billlistType = {
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
* @param data
|
* @param data
|
||||||
*/
|
*/
|
||||||
export const billQuery = (data: { residentId?: string; payStatus: '0' | '1' }): AxiosPromise<billlistType[]> => {
|
export const billQuery = (data: { residentId?: string; payStatus?: '0' | '1' }): AxiosPromise<billlistType[]> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/cash/billList',
|
url: '/cash/billList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
@@ -79,9 +84,11 @@ export const billPrint = (data: { 'detailsIds': string[]; 'residentId': string }
|
|||||||
export const getAllAccount = (
|
export const getAllAccount = (
|
||||||
data = {}
|
data = {}
|
||||||
): AxiosPromise<{
|
): AxiosPromise<{
|
||||||
/** 总金额 */
|
/** 原始金额之和(应收+优惠) */
|
||||||
|
originalAmount: string;
|
||||||
|
/** 总 应收金额 */
|
||||||
'receivableAmount': string;
|
'receivableAmount': string;
|
||||||
/** 总实收金额 */
|
/** 总已收金额 */
|
||||||
'receivedAmount': string;
|
'receivedAmount': string;
|
||||||
/** 总优惠金额 */
|
/** 总优惠金额 */
|
||||||
'discountAmount': string;
|
'discountAmount': string;
|
||||||
@@ -106,7 +113,7 @@ export const billDelete = (ids: string | string[]) => {
|
|||||||
export type BillPrintType = {
|
export type BillPrintType = {
|
||||||
'totalAccount': string;
|
'totalAccount': string;
|
||||||
'residentName': string;
|
'residentName': string;
|
||||||
'payTypeSummary': {
|
'payTypeSummary'?: {
|
||||||
'payType': string;
|
'payType': string;
|
||||||
'payAmount': string;
|
'payAmount': string;
|
||||||
}[];
|
}[];
|
||||||
@@ -123,8 +130,8 @@ export type BillPrintType = {
|
|||||||
'remark': string;
|
'remark': string;
|
||||||
}[];
|
}[];
|
||||||
'printDate': string;
|
'printDate': string;
|
||||||
totalDiscountAmount: string;
|
totalDiscountAmount?: string;
|
||||||
totalActualAccount: string;
|
totalActualAccount?: string;
|
||||||
'HouseName': string;
|
'HouseName': string;
|
||||||
'title': string;
|
'title': string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -96,3 +96,63 @@ export const ElectricityDeviceUnbind = (deviceCode: string) => {
|
|||||||
method: 'PUT'
|
method: 'PUT'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* 充值
|
||||||
|
*/
|
||||||
|
export const ElectricityDeviceRecharge = (data: { 'deviceCode': string; 'amount': number }) => {
|
||||||
|
return request({
|
||||||
|
url: '/electricityDevice/recharge',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 设置电表价格
|
||||||
|
*/
|
||||||
|
export const setElectricityDevicePrice = (data: { 'deviceCode': string; 'price': number }) => {
|
||||||
|
return request({
|
||||||
|
url: '/electricityDevice/setPrice',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 设置电表开关状态
|
||||||
|
*/
|
||||||
|
export const setElectricityDeviceSwitchStatus = (data: { 'deviceCode': string; 'status': number }) => {
|
||||||
|
return request({
|
||||||
|
url: '/electricityDevice/controlSwitch',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 电表数据上传
|
||||||
|
*/
|
||||||
|
export const updateElectricityDeviceData = (data: { 'deviceCode': string }) => {
|
||||||
|
return request({
|
||||||
|
url: '/electricityDevice/triggerReport',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传电表设备
|
||||||
|
*/
|
||||||
|
export const uploadElectricityDevices = (data: FormData) => {
|
||||||
|
return request({
|
||||||
|
url: '/electricityDevice/importData',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 获取模板设备
|
||||||
|
*/
|
||||||
|
export const getElectricityDeviceFormartValue = () => {
|
||||||
|
return request({
|
||||||
|
url: '/electricityDevice/importTemplate',
|
||||||
|
method: 'POST'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -25,11 +25,30 @@ export interface ElectricityDeviceVO {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
url: string;
|
url: string;
|
||||||
|
/**
|
||||||
|
* 电价
|
||||||
|
*/
|
||||||
|
price: number | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
openid: string;
|
openid: string;
|
||||||
|
|
||||||
|
electricityRecord?: {
|
||||||
|
'id': string;
|
||||||
|
'deviceCode': string;
|
||||||
|
'totalEnergy': string;
|
||||||
|
'readTime': string;
|
||||||
|
'balance': string;
|
||||||
|
'status': string;
|
||||||
|
'event': string;
|
||||||
|
'rangeTime': string;
|
||||||
|
'rangeFee': number;
|
||||||
|
'price': number | null;
|
||||||
|
'type': number | null;
|
||||||
|
'updateTime': string | null;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ElectricityDeviceForm extends BaseEntity {
|
export interface ElectricityDeviceForm extends BaseEntity {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export interface MaterialVO {
|
|||||||
* 规格型号*
|
* 规格型号*
|
||||||
*/
|
*/
|
||||||
model: string;
|
model: string;
|
||||||
|
villageId: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计量单位
|
* 计量单位
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export interface SupplierVO {
|
|||||||
* 备注
|
* 备注
|
||||||
*/
|
*/
|
||||||
remark: string;
|
remark: string;
|
||||||
|
villageId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SupplierForm extends BaseEntity {
|
export interface SupplierForm extends BaseEntity {
|
||||||
|
|||||||
@@ -134,16 +134,20 @@ export interface BillResidentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface House {
|
export interface House {
|
||||||
buildingName: string;
|
'buildingName': string;
|
||||||
floorNo: number;
|
'unitNoName': string;
|
||||||
houseArea: string;
|
'houseId': string;
|
||||||
houseId: number;
|
'houseType': string;
|
||||||
houseNo: string;
|
'houseNo': string;
|
||||||
houseType: string;
|
'houseArea': string;
|
||||||
internalArea: string;
|
'floorNo': number;
|
||||||
shareArea: string;
|
'unitNoId': string;
|
||||||
unitNoName: string;
|
'villageName': string;
|
||||||
villageName: string;
|
'villageId': string;
|
||||||
|
'buildingId': string;
|
||||||
|
|
||||||
|
internalArea?: string;
|
||||||
|
shareArea?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResidentList {
|
export interface ResidentList {
|
||||||
|
|||||||
@@ -81,7 +81,13 @@ export const uploadHouseImage = (formData: FormData): AxiosPromise<uploadHouseIm
|
|||||||
data: formData
|
data: formData
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export const getHouseOwnUser = (houseId: string): AxiosPromise<uploadHouseImagetype> => {
|
export const getHouseOwnUser = (
|
||||||
|
houseId: string
|
||||||
|
): AxiosPromise<{
|
||||||
|
floorNo: number;
|
||||||
|
houseArea: number;
|
||||||
|
ownerName: string;
|
||||||
|
}> => {
|
||||||
return request({
|
return request({
|
||||||
url: `/houseRental/ownerName/${houseId}`,
|
url: `/houseRental/ownerName/${houseId}`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export interface HouseRentalForm extends BaseEntity {
|
|||||||
houseImageUrl: string; //房屋图片
|
houseImageUrl: string; //房屋图片
|
||||||
supInfo: string; //补充租房信息
|
supInfo: string; //补充租房信息
|
||||||
vx: string; //微信
|
vx: string; //微信
|
||||||
houseUse: string; //房屋用途
|
houseUse?: string; //房屋用途
|
||||||
rentalStatus: number; //租赁状态
|
rentalStatus: number; //租赁状态
|
||||||
buildingId: string; //楼栋id
|
buildingId: string; //楼栋id
|
||||||
unitNoId: string; //单元id
|
unitNoId: string; //单元id
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export const getParkingReviewInfo = (id: string) => {
|
|||||||
/**
|
/**
|
||||||
* 查询小区内车位列表
|
* 查询小区内车位列表
|
||||||
* @param { string } villageid
|
* @param { string } villageid
|
||||||
* @param houseId
|
* @param { string } houseId
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { Response } from '@/api/system/report/dailyFeeReport/type';
|
import { FilterResponse, Response } from '@/api/system/report/dailyFeeReport/type';
|
||||||
|
|
||||||
export const getDailyFeeReportList = (data = {}): Promise<Response> => {
|
export const getDailyFeeReportList = (data = {}): Promise<Response> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/dailyFeeReport/list',
|
url: '/dailyFeeReport/list',
|
||||||
method: 'GET',
|
method: 'POST',
|
||||||
params: data
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取动态查询数据
|
||||||
|
export const getDailyFeeReportDynamicList = (data = {}): Promise<FilterResponse> => {
|
||||||
|
return request({
|
||||||
|
url: '/dailyFeeReport/filters',
|
||||||
|
method: 'GET',
|
||||||
|
data: data
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export type Datum = {
|
|||||||
houseName: string;
|
houseName: string;
|
||||||
payTime: string;
|
payTime: string;
|
||||||
propertyOffsetAmount: string;
|
propertyOffsetAmount: string;
|
||||||
remark: null;
|
remark: string;
|
||||||
residentName: string;
|
residentName: string;
|
||||||
transferAmount: string;
|
transferAmount: string;
|
||||||
unionPayAmount: string;
|
unionPayAmount: string;
|
||||||
@@ -33,3 +33,12 @@ export type ChargeTypeAmounts = {
|
|||||||
startDate?: string;
|
startDate?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FilterResponse = {
|
||||||
|
code: number;
|
||||||
|
data: {
|
||||||
|
'chargeTypeId': string;
|
||||||
|
'chargeTypeName': string;
|
||||||
|
}[];
|
||||||
|
msg: string;
|
||||||
|
};
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { ResidentVO, ResidentForm, ResidentQuery } from '@/api/system/residentRe
|
|||||||
* @param query
|
* @param query
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const listResident = (query?: ResidentQuery | {}): AxiosPromise<ResidentVO[]> => {
|
export const listResident = (query?: ResidentQuery | {}): AxiosPromise<ResidentVO[]> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/resident/list',
|
url: '/resident/list',
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export interface ResidentVO {
|
|||||||
id: string;
|
id: string;
|
||||||
unitNoId: string;
|
unitNoId: string;
|
||||||
idCardType: string;
|
idCardType: string;
|
||||||
|
ownerRelationship: string;
|
||||||
/**
|
/**
|
||||||
* 住户编号
|
* 住户编号
|
||||||
*/
|
*/
|
||||||
@@ -18,12 +19,12 @@ export interface ResidentVO {
|
|||||||
nickName: string;
|
nickName: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0业主 1租户
|
* 0 业主 1 租户
|
||||||
*/
|
*/
|
||||||
type: string;
|
type: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0 男性 1女性
|
* 0 男性 1 女性
|
||||||
*/
|
*/
|
||||||
gender: string;
|
gender: string;
|
||||||
|
|
||||||
@@ -104,15 +105,15 @@ export interface ResidentForm extends BaseEntity {
|
|||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0业主
|
* 0 业主
|
||||||
* 1亲属
|
* 1 亲属
|
||||||
* 2租户
|
* 2 租户
|
||||||
* 3朋友
|
* 3 朋友
|
||||||
*/
|
*/
|
||||||
ownerRelationship?: string;
|
ownerRelationship?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0 男性 1女性
|
* 0 男性 1 女性
|
||||||
*/
|
*/
|
||||||
gender?: string;
|
gender?: string;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ export interface StoreroomVO {
|
|||||||
* 单元号
|
* 单元号
|
||||||
*/
|
*/
|
||||||
unitNoId: string | number;
|
unitNoId: string | number;
|
||||||
|
/**
|
||||||
|
* 单元名
|
||||||
|
*/
|
||||||
unitName: string;
|
unitName: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -63,10 +63,10 @@ export const delVersion = (id: string | number | Array<string | number>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 获取过往版本 */
|
/** 获取过往版本 */
|
||||||
export const getPastVersion = (platform: string, appChannel: string, channel: string = 'xiaomi') => {
|
export const getPastVersion = (platform: string, appChannel: string) => {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/app/getPastVersion?platform=${platform}&appChannel=${appChannel}&channel=${channel}`,
|
url: `/api/app/getPastVersion?platform=${platform}&appChannel=${appChannel}`,
|
||||||
method: 'get'
|
method: 'get',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
/** 切换版本启停 */
|
/** 切换版本启停 */
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询小区概况
|
* 查询小区概况
|
||||||
@@ -335,7 +336,16 @@ type LifeIndices = {
|
|||||||
* 查询 快捷入口
|
* 查询 快捷入口
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
export const getQuicklyshortcut = (query?: {}) => {
|
export const getQuicklyshortcut = (query?: {}): AxiosPromise<
|
||||||
|
{
|
||||||
|
id: string;
|
||||||
|
menuId: string;
|
||||||
|
menuName: string;
|
||||||
|
menuPath: string;
|
||||||
|
menuIcon: string;
|
||||||
|
sortOrder: number;
|
||||||
|
}[]
|
||||||
|
> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/workSpace/shortcut/list',
|
url: '/workSpace/shortcut/list',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|||||||
@@ -373,6 +373,12 @@ onUnmounted(() => {
|
|||||||
width: 40px;
|
width: 40px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
:deep(.ql-snow .ql-editor) {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
/* 允许在数字内部断开,消除“整串数字集体跳下一行” */
|
||||||
|
word-break: break-all;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
:deep(.ql-snow .ql-toolbar button.ql-file::before) {
|
:deep(.ql-snow .ql-toolbar button.ql-file::before) {
|
||||||
all: unset !important;
|
all: unset !important;
|
||||||
content: '附件';
|
content: '附件';
|
||||||
@@ -385,6 +391,7 @@ onUnmounted(() => {
|
|||||||
.editor {
|
.editor {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor,
|
.editor,
|
||||||
.ql-toolbar {
|
.ql-toolbar {
|
||||||
white-space: pre-wrap !important;
|
white-space: pre-wrap !important;
|
||||||
|
|||||||
@@ -1,32 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot name="default" />
|
<slot name="default" />
|
||||||
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1050">
|
||||||
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
|
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="序号" align="center" width="55" type="index" />
|
<el-table-column align="center" label="序号" type="index" width="55" />
|
||||||
<el-table-column label="业主" align="center">
|
<el-table-column align="center" label="业主">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
|
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="性别" align="center">
|
<el-table-column align="center" label="性别">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="sys_user_sex" :value="scope.row.gender"></dict-tag>
|
<dict-tag :options="sys_user_sex" :value="scope.row.gender"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="手机号" align="center" prop="phone" />
|
<el-table-column align="center" label="手机号" prop="phone" />
|
||||||
<el-table-column label="车位" align="center" prop="parkingName" />
|
<el-table-column align="center" label="车位" prop="parkingName" />
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
<pagination
|
<pagination
|
||||||
style="margin-top: 0"
|
|
||||||
layout="total, prev, pager, next, jumper"
|
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
style="margin-top: 0"
|
||||||
@pagination="getlist"
|
@pagination="getlist"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
@@ -38,7 +37,7 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
|
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
|
||||||
@@ -175,7 +174,6 @@ function handleSelectionChange(selection: BillUserlist[]) {
|
|||||||
const uniqueMap = new Map();
|
const uniqueMap = new Map();
|
||||||
finalSelection.forEach((item) => uniqueMap.set(item.parkingId, item));
|
finalSelection.forEach((item) => uniqueMap.set(item.parkingId, item));
|
||||||
multipleSelection.value = Array.from(uniqueMap.values());
|
multipleSelection.value = Array.from(uniqueMap.values());
|
||||||
console.log(multipleSelection.value.map((item) => item.parkingId));
|
|
||||||
} else {
|
} else {
|
||||||
// --- 单选逻辑 ---
|
// --- 单选逻辑 ---
|
||||||
if (selection.length > 0) {
|
if (selection.length > 0) {
|
||||||
@@ -275,7 +273,6 @@ defineExpose({
|
|||||||
parkingId: id
|
parkingId: id
|
||||||
}) as BillUserlist
|
}) as BillUserlist
|
||||||
);
|
);
|
||||||
console.log(multipleSelection.value);
|
|
||||||
} else {
|
} else {
|
||||||
multipleSelection.value = [];
|
multipleSelection.value = [];
|
||||||
}
|
}
|
||||||
@@ -285,7 +282,7 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.residentBox {
|
.residentBox {
|
||||||
width: 385px;
|
width: 385px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot name="default" />
|
<slot name="default" />
|
||||||
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1050">
|
||||||
<nav class="flex flex-items-center mb-8 justify-between">
|
<nav class="flex flex-items-center mb-8 justify-between">
|
||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 80px; text-align: right; padding-right: 10px">业主账号</div>
|
<div style="width: 80px; text-align: right; padding-right: 10px">业主账号</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-input clearable @clear="handleClear" style="width: 200px" v-model="queryParams.userName" placeholder="请输入业主账号"></el-input>
|
<el-input v-model="queryParams.userName" clearable placeholder="请输入业主账号" style="width: 200px" @clear="handleClear"></el-input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 60px; text-align: right; padding-right: 10px">手机号</div>
|
<div style="width: 60px; text-align: right; padding-right: 10px">手机号</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-input clearable @clear="handleClear" style="width: 200px" v-model="queryParams.userPhone" placeholder="请输入手机号"></el-input>
|
<el-input v-model="queryParams.userPhone" clearable placeholder="请输入手机号" style="width: 200px" @clear="handleClear"></el-input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,24 +21,23 @@
|
|||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<el-table v-loading="loading" ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
|
<el-table ref="multipleTableRef" v-loading="loading" :data="tableData" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="业主" align="center">
|
<el-table-column align="center" label="业主">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.user_name ? scope.row.user_name : '---' }}</span>
|
<span>{{ scope.row.user_name ? scope.row.user_name : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="手机号" align="center" prop="user_phone" />
|
<el-table-column align="center" label="手机号" prop="user_phone" />
|
||||||
</el-table>
|
</el-table>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
<pagination
|
<pagination
|
||||||
style="margin-top: 0"
|
|
||||||
layout="total, prev, pager, next, jumper"
|
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
style="margin-top: 0"
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
@@ -50,7 +49,7 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import { ref, nextTick, toRefs } from 'vue';
|
import { ref, nextTick, toRefs } from 'vue';
|
||||||
import { AppUserList, getAppUser } from '@/api/system/cars';
|
import { AppUserList, getAppUser } from '@/api/system/cars';
|
||||||
@@ -167,7 +166,6 @@ function handleSelectionChange(selection: AppUserList[]) {
|
|||||||
const uniqueMap = new Map();
|
const uniqueMap = new Map();
|
||||||
finalSelection.forEach((item) => uniqueMap.set(item.user_id, item));
|
finalSelection.forEach((item) => uniqueMap.set(item.user_id, item));
|
||||||
multipleSelection.value = Array.from(uniqueMap.values());
|
multipleSelection.value = Array.from(uniqueMap.values());
|
||||||
console.log(multipleSelection.value.map((item) => item.user_id));
|
|
||||||
} else {
|
} else {
|
||||||
// --- 单选逻辑 ---
|
// --- 单选逻辑 ---
|
||||||
if (selection.length > 0) {
|
if (selection.length > 0) {
|
||||||
@@ -253,7 +251,7 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.residentBox {
|
.residentBox {
|
||||||
width: 385px;
|
width: 385px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
316
src/components/Holder/complainUser.vue
Normal file
316
src/components/Holder/complainUser.vue
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
<template>
|
||||||
|
<slot v-if="$slots.default" />
|
||||||
|
|
||||||
|
<div v-else class="residentBox" @click="choiceResidentFun">
|
||||||
|
<div v-if="multipleSelection.length === 0 && props.username === null" class="defaultBox">
|
||||||
|
<span>请选择</span>
|
||||||
|
<el-icon><Search /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
|
||||||
|
<span>姓名:{{ multipleSelection[0]?.nickName ?? props.username }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1050">
|
||||||
|
<nav class="flex flex-items-center mb-8">
|
||||||
|
<div class="flex flex-items-center">
|
||||||
|
<div style="width: 70px; text-align: right; padding-right: 10px">员工姓名</div>
|
||||||
|
<div class="mr-5 flex-1">
|
||||||
|
<el-input v-model="queryParams.nickName" clearable placeholder="请输入员工姓名" style="width: 170px" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-items-center">
|
||||||
|
<div style="width: 70px; text-align: right; padding-right: 10px">手机号</div>
|
||||||
|
<div class="mr-5 flex-1">
|
||||||
|
<el-input v-model="queryParams.phonenumber" clearable placeholder="请输入手机号" style="width: 170px" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="getList">查询</el-button>
|
||||||
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column align="center" label="序号" type="index" width="55" />
|
||||||
|
<el-table-column align="center" label="姓名" prop="nickName" />
|
||||||
|
<el-table-column align="center" label="性别" prop="sex" width="85">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-tag :options="sys_user_sex" :value="row.sex" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="角色" prop="roleName" />
|
||||||
|
<el-table-column v-if="props.userType == 'repair'" align="center" label="当前任务数量" prop="taskCount" />
|
||||||
|
<el-table-column align="center" label="手机号码" prop="phonenumber" />
|
||||||
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.status === '0' ? 'success' : 'danger'">{{ row.status === '0' ? '正常' : '停用' }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
style="margin-top: 0"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<el-button @click="conBack">退出</el-button>
|
||||||
|
<el-button type="primary" @click="confirm"> 确定 </el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
|
||||||
|
import { getUserByRoleKey } from '@/api/system/user';
|
||||||
|
import { ref, watch, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
|
||||||
|
|
||||||
|
interface tableType extends ResidentVO {
|
||||||
|
housePath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
userid: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
returnvalue: {
|
||||||
|
type: String,
|
||||||
|
default: 'userId'
|
||||||
|
},
|
||||||
|
titleName: {
|
||||||
|
type: String,
|
||||||
|
default: '选择投诉处理人员'
|
||||||
|
},
|
||||||
|
userType: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
isMultiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { userid, titleName, userType, returnvalue } = toRefs(props);
|
||||||
|
|
||||||
|
// ✅ 手动设置默认值(替代 withDefaults)
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [value: string | number | (string | number)[] | tableType | tableType[]]; // 支持返回数组
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const dialog = ref({
|
||||||
|
dialogVisible: false,
|
||||||
|
dialogTitle: titleName.value
|
||||||
|
});
|
||||||
|
|
||||||
|
const queryParams = ref({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
nickName: null,
|
||||||
|
phonenumber: null
|
||||||
|
});
|
||||||
|
|
||||||
|
const multipleTableRef = ref();
|
||||||
|
const tableData = ref<tableType[]>([]);
|
||||||
|
const total = ref(0);
|
||||||
|
const loading = ref(false);
|
||||||
|
const isFetching = ref(false); // 加锁,防止重复触发 selection-change
|
||||||
|
|
||||||
|
// 存储选中项
|
||||||
|
const multipleSelection = ref<tableType[]>([]);
|
||||||
|
|
||||||
|
const isMultiple = computed(() => props.isMultiple ?? false);
|
||||||
|
|
||||||
|
// 优化 handleUserSelection,避免重复查找
|
||||||
|
const handleUserSelection = () => {
|
||||||
|
isFetching.value = true;
|
||||||
|
if (tableData.value.length <= 0 || !multipleTableRef.value) {
|
||||||
|
isFetching.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rowsToSelect = tableData.value.filter((row) => {
|
||||||
|
return multipleSelection.value.some((selected) => selected.userId === row.userId);
|
||||||
|
});
|
||||||
|
multipleTableRef.value.clearSelection();
|
||||||
|
if (rowsToSelect.length > 0) {
|
||||||
|
nextTick(() => {
|
||||||
|
rowsToSelect.forEach((row) => {
|
||||||
|
multipleTableRef.value?.toggleRowSelection(row, true);
|
||||||
|
});
|
||||||
|
isFetching.value = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
isFetching.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听
|
||||||
|
// 监听优化:只在 userid 变化时触发
|
||||||
|
watch(userid, handleUserSelection, { immediate: true });
|
||||||
|
|
||||||
|
// ====================== 方法 ======================
|
||||||
|
// 打开选择框
|
||||||
|
function choiceResidentFun() {
|
||||||
|
dialog.value.dialogVisible = true;
|
||||||
|
multipleSelection.value = []; // 打开时清空之前的选择
|
||||||
|
if (typeof props.userid === 'string' && props.userid.trim() !== '') {
|
||||||
|
multipleSelection.value = [
|
||||||
|
{
|
||||||
|
userId: props.userid
|
||||||
|
} as ResidentVO
|
||||||
|
];
|
||||||
|
} else if (Array.isArray(props.userid)) {
|
||||||
|
multipleSelection.value = props.userid.map((id) => ({ userId: id })) as tableType[];
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取列表
|
||||||
|
function getList() {
|
||||||
|
loading.value = true;
|
||||||
|
getUserByRoleKey({
|
||||||
|
...queryParams.value,
|
||||||
|
roleKey: userType.value
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
tableData.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
handleUserSelection();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('获取用户列表失败:', error);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// ==============================================
|
||||||
|
// ✅ 新增:处理 selection-change(多选专用)
|
||||||
|
// ==============================================
|
||||||
|
function handleSelectionChange(selection: tableType[]) {
|
||||||
|
if (isFetching.value) return;
|
||||||
|
if (isMultiple.value) {
|
||||||
|
const currentSelectedIds = new Set(selection.map((item) => item.id));
|
||||||
|
const otherPageSelections = multipleSelection.value.filter((item) => {
|
||||||
|
const isCurrentPageItem = tableData.value.some((row) => row.id === item.id);
|
||||||
|
if (isCurrentPageItem) {
|
||||||
|
return currentSelectedIds.has(item.id);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 3. 合并:其他页保留的 + 当前页新选中的
|
||||||
|
const finalSelection = [...otherPageSelections, ...selection];
|
||||||
|
// 4. 去重(以防万一)
|
||||||
|
const uniqueMap = new Map();
|
||||||
|
finalSelection.forEach((item) => uniqueMap.set(item.id, item));
|
||||||
|
multipleSelection.value = Array.from(uniqueMap.values());
|
||||||
|
} else {
|
||||||
|
// --- 单选逻辑 ---
|
||||||
|
if (selection.length > 0) {
|
||||||
|
const lastSelected = selection[selection.length - 1];
|
||||||
|
multipleSelection.value = [lastSelected];
|
||||||
|
nextTick(() => {
|
||||||
|
if (selection.length > 1) {
|
||||||
|
multipleTableRef.value?.clearSelection();
|
||||||
|
multipleTableRef.value?.toggleRowSelection(lastSelected, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
multipleSelection.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 重置查询
|
||||||
|
function resetQuery() {
|
||||||
|
queryParams.value = {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
nickName: null,
|
||||||
|
phonenumber: null
|
||||||
|
};
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退出
|
||||||
|
function conBack() {
|
||||||
|
dialog.value.dialogVisible = false;
|
||||||
|
resetQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==============================================
|
||||||
|
// ✅ 核心修改:根据 returnvalue 返回对应的值
|
||||||
|
// ==============================================
|
||||||
|
function confirm() {
|
||||||
|
dialog.value.dialogVisible = false;
|
||||||
|
if (isMultiple.value) {
|
||||||
|
// 多选
|
||||||
|
if (returnvalue.value === '*') {
|
||||||
|
// ✅ 返回整个对象数组
|
||||||
|
emit('change', multipleSelection.value);
|
||||||
|
} else {
|
||||||
|
// 返回指定字段数组
|
||||||
|
emit(
|
||||||
|
'change',
|
||||||
|
multipleSelection.value.map((item) => item[returnvalue.value as keyof tableType])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 单选
|
||||||
|
if (returnvalue.value === '*') {
|
||||||
|
// ✅ 返回整个对象
|
||||||
|
emit('change', multipleSelection.value[multipleSelection.value.length - 1]);
|
||||||
|
} else {
|
||||||
|
// 返回指定字段
|
||||||
|
emit('change', multipleSelection.value[multipleSelection.value.length - 1][returnvalue.value as keyof tableType]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
// 初始化
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open: () => {
|
||||||
|
dialog.value.dialogVisible = true;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot name="default" />
|
<slot name="default" />
|
||||||
|
|
||||||
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1400">
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1400">
|
||||||
<nav class="flex flex-items-center mb-8 justify-between">
|
<nav class="flex flex-items-center mb-8 justify-between">
|
||||||
<!-- <div class="flex flex-items-center">
|
<!-- <div class="flex flex-items-center">
|
||||||
<div style="width: 70px; text-align: right; padding-right: 10px">房屋类型</div>
|
<div style="width: 70px; text-align: right; padding-right: 10px">房屋类型</div>
|
||||||
@@ -15,14 +15,14 @@
|
|||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<div style="width: 50px; text-align: right; padding-right: 10px">楼栋</div>
|
<div style="width: 50px; text-align: right; padding-right: 10px">楼栋</div>
|
||||||
<div class="flex-1"></div>
|
<div class="flex-1"></div>
|
||||||
<el-select @change="handleChangeBuilding" clearable style="width: 120px" v-model="queryParams.buildingId">
|
<el-select v-model="queryParams.buildingId" clearable style="width: 120px" @change="handleChangeBuilding">
|
||||||
<el-option v-for="(item, index) in buildingList" :key="index" :label="item.buildingName" :value="item.id"></el-option>
|
<el-option v-for="(item, index) in buildingList" :key="index" :label="item.buildingName" :value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 50px; text-align: right; padding-right: 10px">单元</div>
|
<div style="width: 50px; text-align: right; padding-right: 10px">单元</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-select @change="handleChangeUnit" clearable style="width: 120px" v-model="queryParams.unitNoId">
|
<el-select v-model="queryParams.unitNoId" clearable style="width: 120px" @change="handleChangeUnit">
|
||||||
<el-option v-for="(item, index) in unitList" :key="index" :label="item.unitNoName" :value="item.unitNoId"></el-option>
|
<el-option v-for="(item, index) in unitList" :key="index" :label="item.unitNoName" :value="item.unitNoId"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 80px; text-align: right; padding-right: 10px">房屋类型</div>
|
<div style="width: 80px; text-align: right; padding-right: 10px">房屋类型</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-select clearable @change="handleHouseUseChange" style="width: 120px" v-model="queryParams.houseUseTypeId">
|
<el-select v-model="queryParams.houseUseTypeId" clearable style="width: 120px" @change="handleHouseUseChange">
|
||||||
<el-option v-for="(item, index) in houseUseTypeList" :key="index" :label="item.name" :value="item.id"></el-option>
|
<el-option v-for="(item, index) in houseUseTypeList" :key="index" :label="item.name" :value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,13 +38,13 @@
|
|||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 60px; text-align: right; padding-right: 10px">房屋号</div>
|
<div style="width: 60px; text-align: right; padding-right: 10px">房屋号</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-input clearable @clear="handleClear" style="width: 120px" v-model="queryParams.houseNo" placeholder="请输入房屋号"></el-input>
|
<el-input v-model="queryParams.houseNo" clearable placeholder="请输入房屋号" style="width: 120px" @clear="handleClear"></el-input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 80px; text-align: right; padding-right: 10px">业主名称</div>
|
<div style="width: 80px; text-align: right; padding-right: 10px">业主名称</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-input clearable @clear="handleClear" style="width: 120px" v-model="queryParams.residentName" placeholder="请输入业主名称"></el-input>
|
<el-input v-model="queryParams.residentName" clearable placeholder="请输入业主名称" style="width: 120px" @clear="handleClear"></el-input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,21 +54,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<el-table
|
<el-table
|
||||||
style="height: 500px"
|
|
||||||
row-key="houseId"
|
|
||||||
v-loading="loading"
|
|
||||||
ref="multipleTableRef"
|
ref="multipleTableRef"
|
||||||
|
v-loading="loading"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
border
|
border
|
||||||
|
row-key="houseId"
|
||||||
|
style="height: 500px"
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="序号" align="center" width="55" type="index" />
|
<el-table-column align="center" label="序号" type="index" width="55" />
|
||||||
<el-table-column label="小区" align="center" prop="villageName" />
|
<el-table-column align="center" label="小区" prop="villageName" />
|
||||||
<el-table-column label="楼栋" align="center" prop="buildingName" />
|
<el-table-column align="center" label="楼栋" prop="buildingName" />
|
||||||
<el-table-column label="单元" align="center" prop="unitNoName" />
|
<el-table-column align="center" label="单元" prop="unitNoName" />
|
||||||
<el-table-column label="房间" align="center" prop="houseNo" />
|
<el-table-column align="center" label="房间" prop="houseNo" />
|
||||||
<el-table-column label="业主" align="center">
|
<el-table-column align="center" label="业主">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
|
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -77,12 +77,11 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
<pagination
|
<pagination
|
||||||
style="margin-top: 0"
|
|
||||||
layout="total, prev, sizes, pager, next, jumper"
|
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
style="margin-top: 0"
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
@@ -94,7 +93,7 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
|
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
|
||||||
import { listHouseUseType_add_house } from '@/api/system/houseUse';
|
import { listHouseUseType_add_house } from '@/api/system/houseUse';
|
||||||
import { BillHouse, listBillHouse } from '@/api/system/SdbBill';
|
import { BillHouse, listBillHouse } from '@/api/system/SdbBill';
|
||||||
@@ -263,7 +262,6 @@ function handleSelectionChange(selection: BillHouse[]) {
|
|||||||
const uniqueMap = new Map();
|
const uniqueMap = new Map();
|
||||||
finalSelection.forEach((item) => uniqueMap.set(item.houseId, item));
|
finalSelection.forEach((item) => uniqueMap.set(item.houseId, item));
|
||||||
multipleSelection.value = Array.from(uniqueMap.values());
|
multipleSelection.value = Array.from(uniqueMap.values());
|
||||||
console.log(multipleSelection.value.map((item) => item.houseId));
|
|
||||||
} else {
|
} else {
|
||||||
// ✅ 补充:单选模式下,selection-change 触发时,直接取最新的一项
|
// ✅ 补充:单选模式下,selection-change 触发时,直接取最新的一项
|
||||||
// 这样配合 handleRowClick 的 clearSelection + toggle 就能实现完美单选
|
// 这样配合 handleRowClick 的 clearSelection + toggle 就能实现完美单选
|
||||||
@@ -365,7 +363,7 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.residentBox {
|
.residentBox {
|
||||||
width: 385px;
|
width: 385px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<slot v-if="$slots.default" />
|
<slot v-if="$slots.default" />
|
||||||
|
|
||||||
<div v-else class="residentBox" @click="choiceResidentFun">
|
<div v-else class="residentBox" @click="choiceResidentFun">
|
||||||
<div class="defaultbox" v-if="multipleSelection.length === 0">
|
<div v-if="multipleSelection.length === 0" class="defaultbox">
|
||||||
<span>请选择</span>
|
<span>请选择</span>
|
||||||
<el-icon><Search /></el-icon>
|
<el-icon><Search /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -11,45 +11,49 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog @close="conback" append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1050" @close="conBack">
|
||||||
<nav class="flex flex-items-center mb-8" style="margin-bottom: 20px">
|
<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 class="flex flex-items-center flex-1" style="max-width: 200px">-->
|
||||||
<div style="width: 120px">住户类型</div>
|
<!-- <div style="width: 120px">住户类型</div>-->
|
||||||
<el-select v-model="queryParams.ownerRelationship" placeholder="请选择" clearable>
|
<!-- <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-option v-for="dict in com_resident_relationship" :key="dict.value" :label="dict.label" :value="dict.value" />-->
|
||||||
</el-select>
|
<!-- </el-select>-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="mr-5 flex-1" style="margin: 0 20px">
|
<!-- <div class="mr-5 flex-1" style="margin: 0 20px">-->
|
||||||
<el-input maxlength="30" clearable v-model="queryParams.name" placeholder="请输入住户姓名" />
|
<!-- <el-input maxlength="30" clearable v-model="queryParams.name" placeholder="请输入住户姓名" />-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<div class="flex flex-items-center flex-1" style="max-width: 300px; margin: 0 20px">
|
||||||
|
<div style="width: 120px">住户姓名</div>
|
||||||
|
<el-input v-model="queryParams.name" clearable maxlength="30" placeholder="请输入住户姓名" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-button type="primary" @click="getlist">查询</el-button>
|
<el-button type="primary" @click="getList">查询</el-button>
|
||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<el-table ref="multipleTableRef" row-key="id" :data="tableData" border @selection-change="handleSelectionChange">
|
<el-table ref="multipleTableRef" :data="tableData" border row-key="id" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="序号" align="center" width="55" type="index" />
|
<el-table-column align="center" label="序号" type="index" width="55" />
|
||||||
<el-table-column label="姓名" align="center" prop="name" />
|
<el-table-column align="center" label="姓名" prop="name" />
|
||||||
<el-table-column label="类型" align="center" width="85" prop="type">
|
<el-table-column align="center" label="类型" prop="type" width="85">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<dict-tag :options="com_resident_type" :value="row.type" />
|
<dict-tag :options="com_resident_type" :value="row.type" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="与业主关系" align="center" width="95" prop="ownerRelationship">
|
<el-table-column align="center" label="与业主关系" prop="ownerRelationship" width="95">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<dict-tag :options="com_resident_relationship" :value="row.ownerRelationship" />
|
<dict-tag :options="com_resident_relationship" :value="row.ownerRelationship" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="状态" align="center" width="85" prop="status">
|
<el-table-column align="center" label="状态" prop="status" width="85">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<dict-tag :options="com_certification_status" :value="row.status" />
|
<dict-tag :options="com_certification_status" :value="row.status" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="证件号码" width="165" align="center" prop="idCard" />
|
<el-table-column align="center" label="证件号码" prop="idCard" width="165" />
|
||||||
<el-table-column label="手机号码" align="center" prop="phone" />
|
<el-table-column align="center" label="手机号码" prop="phone" />
|
||||||
<el-table-column label="房间" show-overflow-tooltip align="center">
|
<el-table-column align="center" label="房间" show-overflow-tooltip>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
{{ row.houseName }}
|
{{ row.houseName }}
|
||||||
</template>
|
</template>
|
||||||
@@ -59,15 +63,15 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
<pagination
|
<pagination
|
||||||
style="margin-top: 0"
|
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
@pagination="getlist"
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
style="margin-top: 0"
|
||||||
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="conback">退出</el-button>
|
<el-button @click="conBack">退出</el-button>
|
||||||
<el-button type="primary" @click="confirm">确定</el-button>
|
<el-button type="primary" @click="confirm">确定</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,21 +79,10 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { listResident } from '@/api/system/residentReviewProcess/resident';
|
import { listResident } from '@/api/system/residentReviewProcess/resident';
|
||||||
import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
|
import { ResidentQuery, ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
|
||||||
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
|
||||||
|
|
||||||
const houseStore = useHouseStore();
|
|
||||||
|
|
||||||
const treedata = ref([]);
|
|
||||||
function init() {
|
|
||||||
houseStore.getCurrentVilageTreeHouse().then((res) => {
|
|
||||||
treedata.value = res;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_resident_type } = toRefs<any>(proxy?.useDict('com_resident_type'));
|
const { com_resident_type } = toRefs<any>(proxy?.useDict('com_resident_type'));
|
||||||
@@ -198,7 +191,7 @@ const handleUserSelection = () => {
|
|||||||
if (isMultiple.value && Array.isArray(props.userid)) {
|
if (isMultiple.value && Array.isArray(props.userid)) {
|
||||||
// 多选回显
|
// 多选回显
|
||||||
const selectedItems: tableType[] = [];
|
const selectedItems: tableType[] = [];
|
||||||
props.userid.forEach((id) => {
|
props.userid.forEach((id: string | number) => {
|
||||||
const findItem = tableData.value.find((item) => item.id == id || item.userId == id);
|
const findItem = tableData.value.find((item) => item.id == id || item.userId == id);
|
||||||
if (findItem) {
|
if (findItem) {
|
||||||
selectedItems.push(findItem);
|
selectedItems.push(findItem);
|
||||||
@@ -222,12 +215,12 @@ const handleUserSelection = () => {
|
|||||||
// 打开选择框
|
// 打开选择框
|
||||||
function choiceResidentFun() {
|
function choiceResidentFun() {
|
||||||
// 初始化
|
// 初始化
|
||||||
getlist();
|
getList();
|
||||||
dialog.value.dialogVisible = true;
|
dialog.value.dialogVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取列表
|
// 获取列表
|
||||||
function getlist() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
listResident(queryParams.value)
|
listResident(queryParams.value)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@@ -253,11 +246,11 @@ function resetQuery() {
|
|||||||
buildingId: null,
|
buildingId: null,
|
||||||
unitNo: null
|
unitNo: null
|
||||||
};
|
};
|
||||||
getlist();
|
getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 退出
|
// 退出
|
||||||
function conback() {
|
function conBack() {
|
||||||
dialog.value.dialogVisible = false;
|
dialog.value.dialogVisible = false;
|
||||||
resetQuery();
|
resetQuery();
|
||||||
}
|
}
|
||||||
@@ -282,7 +275,6 @@ function confirm() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 单选
|
// 单选
|
||||||
console.log(multipleSelection.value[0], multipleSelection.value);
|
|
||||||
if (returnvalue.value === '*') {
|
if (returnvalue.value === '*') {
|
||||||
// ✅ 返回整个对象
|
// ✅ 返回整个对象
|
||||||
emit('change', multipleSelection.value[0]);
|
emit('change', multipleSelection.value[0]);
|
||||||
@@ -297,7 +289,7 @@ function confirm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open: (arr) => {
|
open: (arr?: string[], params: ResidentQuery | {} = {}) => {
|
||||||
if (arr && arr.length > 0) {
|
if (arr && arr.length > 0) {
|
||||||
multipleSelection.value = arr.map((id) => ({
|
multipleSelection.value = arr.map((id) => ({
|
||||||
id: id
|
id: id
|
||||||
@@ -305,13 +297,17 @@ defineExpose({
|
|||||||
} else {
|
} else {
|
||||||
multipleSelection.value = [];
|
multipleSelection.value = [];
|
||||||
}
|
}
|
||||||
getlist();
|
queryParams.value = {
|
||||||
|
...queryParams.value,
|
||||||
|
...params
|
||||||
|
};
|
||||||
|
getList();
|
||||||
dialog.value.dialogVisible = true;
|
dialog.value.dialogVisible = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.residentBox {
|
.residentBox {
|
||||||
width: 385px;
|
width: 385px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot name="default" />
|
<slot name="default" />
|
||||||
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1050">
|
||||||
<nav class="flex flex-items-center mb-8">
|
<nav class="flex flex-items-center mb-8">
|
||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<div style="width: 70px; text-align: right; padding-right: 10px">物料名称</div>
|
<div style="width: 70px; text-align: right; padding-right: 10px">物料名称</div>
|
||||||
<div class="mr-5 flex-1">
|
<div class="mr-5 flex-1">
|
||||||
<el-input style="width: 170px" clearable v-model="queryParams.materialName" placeholder="请输入物料名称" />
|
<el-input v-model="queryParams.materialName" clearable placeholder="请输入物料名称" style="width: 170px" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<div style="width: 70px; text-align: right; padding-right: 10px">品牌</div>
|
<div style="width: 70px; text-align: right; padding-right: 10px">品牌</div>
|
||||||
<div class="mr-5 flex-1">
|
<div class="mr-5 flex-1">
|
||||||
<el-input style="width: 170px" clearable v-model="queryParams.brand" placeholder="请输入品牌" />
|
<el-input v-model="queryParams.brand" clearable placeholder="请输入品牌" style="width: 170px" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -19,46 +19,47 @@
|
|||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<el-table
|
<el-table ref="multipleTableRef" :data="tableData" border>
|
||||||
@select-all="handleSelectionChange"
|
<el-table-column align="center" width="55">
|
||||||
@row-click="handleRowClick"
|
<template #header>
|
||||||
ref="multipleTableRef"
|
<el-checkbox v-model="isSelectAll" :disabled="!isMultiple" :indeterminate="isIndeterminate" @change="handleSelectAllChange" />
|
||||||
:data="tableData"
|
</template>
|
||||||
border
|
<template #default="scope">
|
||||||
@selection-change="handleSelectionChange"
|
<el-checkbox :model-value="isRowSelected(scope.row)" @change="(val: boolean) => handleRowCheckChange(scope.row, val)" />
|
||||||
>
|
</template>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
</el-table-column>
|
||||||
<el-table-column label="物料名称" align="center" prop="materialName" />
|
<el-table-column align="center" label="物料名称" prop="materialName" />
|
||||||
<el-table-column label="品牌" align="center" prop="brand" />
|
<el-table-column align="center" label="品牌" prop="brand" />
|
||||||
<el-table-column label="规格型号" align="center" prop="model" />
|
<el-table-column align="center" label="规格型号" prop="model" />
|
||||||
<el-table-column label="单位" align="center" prop="unit" />
|
<el-table-column align="center" label="单位" prop="unit" />
|
||||||
<el-table-column label="备注" align="center" prop="remark" />
|
<el-table-column v-if="!isHidden" align="center" label="数量" prop="stockNum" />
|
||||||
|
<el-table-column align="center" label="所属小区" prop="villageName" />
|
||||||
|
<el-table-column align="center" label="备注" prop="remark" />
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
<pagination
|
<pagination
|
||||||
style="margin-top: 0"
|
|
||||||
layout="total, prev, pager, next, jumper"
|
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
style="margin-top: 0"
|
||||||
@pagination="getlist"
|
@pagination="getlist"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="conback">退出</el-button>
|
<el-button @click="conback">退出</el-button>
|
||||||
<el-button type="primary" @click="confirm"> 确定 </el-button>
|
<el-button :loading="loading" type="primary" @click="confirm"> 确定 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { listMaterial } from '@/api/system/Tmaterial';
|
import { listMaterial } from '@/api/system/Tmaterial';
|
||||||
import { MaterialVO } from '@/api/system/Tmaterial/type';
|
import { MaterialVO } from '@/api/system/Tmaterial/type';
|
||||||
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
import { ComponentInternalInstance, getCurrentInstance, ref, toRefs } from 'vue';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
@@ -78,6 +79,10 @@ const props = defineProps({
|
|||||||
isMultiple: {
|
isMultiple: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
isHidden: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -105,41 +110,87 @@ const tableData = ref<MaterialVO[]>([]);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
// 存储选中项
|
/** 存储所有选中项(跨页累计,非全选模式使用) */
|
||||||
const multipleSelection = ref<MaterialVO[]>([]);
|
const multipleSelection = ref<MaterialVO[]>([]);
|
||||||
// 多选
|
/** 是否已跨页全选(标记模式,不实际持有全部数据) */
|
||||||
|
const isSelectAll = ref(false);
|
||||||
|
/** 表头复选框半选状态(部分选中时为 true) */
|
||||||
|
const isIndeterminate = ref(false);
|
||||||
|
/** 全选模式下被手动取消勾选的 id 列表 */
|
||||||
|
const deselectedIds = ref<string[]>([]);
|
||||||
|
|
||||||
const isMultiple = computed(() => props.isMultiple ?? false);
|
const isMultiple = computed(() => props.isMultiple ?? false);
|
||||||
|
|
||||||
// 优化 handleUserSelection,避免重复查找
|
/** 判断某行是否已选中 */
|
||||||
const handleUserSelection = () => {
|
function isRowSelected(row: MaterialVO): boolean {
|
||||||
if (!userid.value || !tableData.value.length) return;
|
if (isSelectAll.value) {
|
||||||
|
// 全选模式:只要不在取消列表中就算选中
|
||||||
multipleSelection.value = [];
|
return !deselectedIds.value.includes(row.id);
|
||||||
if (userid.value.trim() !== '') {
|
|
||||||
const arr = userid.value.split(',');
|
|
||||||
arr.forEach((item) => {
|
|
||||||
const target = tableData.value.find((row) => row.id == item);
|
|
||||||
target && multipleSelection.value.push(target);
|
|
||||||
});
|
|
||||||
nextTick(() => {
|
|
||||||
if (multipleTableRef.value) {
|
|
||||||
multipleTableRef.value.clearSelection();
|
|
||||||
multipleSelection.value.forEach((item) => {
|
|
||||||
multipleTableRef.value.toggleRowSelection(item, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
return multipleSelection.value.some((item) => item.id === row.id);
|
||||||
|
}
|
||||||
|
|
||||||
// 监听
|
/** 更新表头复选框状态:全选 / 半选 / 空 */
|
||||||
// 监听优化:只在 userid 变化时触发
|
function updateIndeterminate() {
|
||||||
// watch(userid, handleUserSelection, { immediate: true });
|
if (isSelectAll.value) {
|
||||||
// watch(tableData, () => {
|
// 全选模式下:有取消勾选的行 → 半选,否则 → 全选
|
||||||
// if (userid.value) handleUserSelection(); // 仅在有 userid 时重新处理
|
isIndeterminate.value = deselectedIds.value.length > 0;
|
||||||
// });
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非全选模式:只要有已勾选的行即为半选。
|
||||||
|
// 注意:不能用 selectedCount >= total 去做“自动升级为全选”,
|
||||||
|
// 否则搜索/筛选后 total 变小,会把之前积累的 multipleSelection 误判并清空,覆盖已选数据。
|
||||||
|
isIndeterminate.value = multipleSelection.value.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 跨页全选 / 取消全选(仅设标记,不拉取数据) */
|
||||||
|
function handleSelectAllChange(val: boolean) {
|
||||||
|
isSelectAll.value = val;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
multipleSelection.value = [];
|
||||||
|
updateIndeterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 单行勾选 / 取消勾选 */
|
||||||
|
function handleRowCheckChange(row: MaterialVO, checked: boolean) {
|
||||||
|
if (!isMultiple.value) {
|
||||||
|
// 单选模式:仅保留当前行
|
||||||
|
if (checked) {
|
||||||
|
multipleSelection.value = [row];
|
||||||
|
} else {
|
||||||
|
multipleSelection.value = [];
|
||||||
|
}
|
||||||
|
isSelectAll.value = false;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
updateIndeterminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSelectAll.value) {
|
||||||
|
// 全选模式:维护取消列表
|
||||||
|
if (checked) {
|
||||||
|
deselectedIds.value = deselectedIds.value.filter((id) => id !== row.id);
|
||||||
|
} else {
|
||||||
|
if (!deselectedIds.value.includes(row.id)) {
|
||||||
|
deselectedIds.value.push(row.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非全选模式:维护选中列表
|
||||||
|
if (checked) {
|
||||||
|
if (!isRowSelected(row)) {
|
||||||
|
multipleSelection.value.push(row);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
multipleSelection.value = multipleSelection.value.filter((item) => item.id !== row.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateIndeterminate();
|
||||||
|
}
|
||||||
|
|
||||||
// ====================== 方法 ======================
|
// ====================== 方法 ======================
|
||||||
|
|
||||||
// 获取列表
|
// 获取列表
|
||||||
function getlist() {
|
function getlist() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@@ -147,46 +198,16 @@ function getlist() {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
tableData.value = res.rows;
|
tableData.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
|
updateIndeterminate();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('获取物料列表失败:', error);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==============================================
|
|
||||||
// ✅ 新增:处理 selection-change(多选专用)
|
|
||||||
// ==============================================
|
|
||||||
function handleSelectionChange(selection: MaterialVO[]) {
|
|
||||||
if (isMultiple.value) {
|
|
||||||
multipleSelection.value = selection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ==============================================
|
|
||||||
// 最佳单选方案:点击行选中,无报错、无循环、最稳定
|
|
||||||
// ==============================================
|
|
||||||
// 优化 handleRowClick,避免重复
|
|
||||||
function handleRowClick(row: MaterialVO) {
|
|
||||||
if (!multipleTableRef.value) return;
|
|
||||||
|
|
||||||
if (isMultiple.value) {
|
|
||||||
const index = multipleSelection.value.findIndex((item) => item.id === row.id);
|
|
||||||
if (index > -1) {
|
|
||||||
// 取消选中
|
|
||||||
multipleSelection.value.splice(index, 1);
|
|
||||||
multipleTableRef.value?.toggleRowSelection(row, false);
|
|
||||||
} else {
|
|
||||||
// 选中
|
|
||||||
multipleSelection.value.push(row);
|
|
||||||
multipleTableRef.value?.toggleRowSelection(row, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 【单选模式】先清空,再选中当前行
|
|
||||||
multipleSelection.value = [];
|
|
||||||
multipleTableRef.value.clearSelection();
|
|
||||||
multipleSelection.value = [row];
|
|
||||||
multipleTableRef.value.toggleRowSelection(row, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 重置查询
|
// 重置查询
|
||||||
function resetQuery() {
|
function resetQuery() {
|
||||||
queryParams.value = {
|
queryParams.value = {
|
||||||
@@ -195,6 +216,7 @@ function resetQuery() {
|
|||||||
brand: '',
|
brand: '',
|
||||||
materialName: ''
|
materialName: ''
|
||||||
};
|
};
|
||||||
|
resetSelection();
|
||||||
getlist();
|
getlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,49 +226,95 @@ function conback() {
|
|||||||
resetQuery();
|
resetQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==============================================
|
/** 重置所有选中状态 */
|
||||||
// ✅ 核心修改:根据 returnvalue 返回对应的值
|
function resetSelection() {
|
||||||
// ==============================================
|
multipleSelection.value = [];
|
||||||
function confirm() {
|
isSelectAll.value = false;
|
||||||
dialog.value.dialogVisible = false;
|
isIndeterminate.value = false;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据 returnvalue 发射选中结果 */
|
||||||
|
function emitResult(data: MaterialVO[]) {
|
||||||
if (isMultiple.value) {
|
if (isMultiple.value) {
|
||||||
// 多选
|
|
||||||
if (returnvalue.value === '*') {
|
if (returnvalue.value === '*') {
|
||||||
// ✅ 返回整个对象数组
|
emit('change', data);
|
||||||
emit('change', multipleSelection.value);
|
|
||||||
} else {
|
} else {
|
||||||
// 返回指定字段数组
|
|
||||||
emit(
|
emit(
|
||||||
'change',
|
'change',
|
||||||
multipleSelection.value.map((item) => item[returnvalue.value as keyof MaterialVO])
|
data.map((item) => item[returnvalue.value as keyof MaterialVO])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 单选
|
|
||||||
if (returnvalue.value === '*') {
|
if (returnvalue.value === '*') {
|
||||||
// ✅ 返回整个对象
|
emit('change', data[0]);
|
||||||
emit('change', multipleSelection.value[0]);
|
|
||||||
} else {
|
} else {
|
||||||
// 返回指定字段
|
emit('change', data[0]?.[returnvalue.value as keyof MaterialVO]);
|
||||||
emit('change', multipleSelection.value[0][returnvalue.value as keyof MaterialVO]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
multipleSelection.value = [];
|
|
||||||
multipleTableRef.value.clearSelection();
|
|
||||||
}
|
}
|
||||||
// 初始化
|
|
||||||
getlist();
|
/** 确定:全选模式下按需拉取全部数据,非全选模式直接使用已选列表 */
|
||||||
|
async function confirm() {
|
||||||
|
if (isMultiple.value && isSelectAll.value && total.value > 0) {
|
||||||
|
// 全选模式:此时才真正拉取全部数据,排除已取消勾选的行
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await listMaterial({
|
||||||
|
...queryParams.value,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: total.value
|
||||||
|
});
|
||||||
|
const allData: MaterialVO[] = res.rows || [];
|
||||||
|
const filteredData = allData.filter((item) => !deselectedIds.value.includes(item.id));
|
||||||
|
dialog.value.dialogVisible = false;
|
||||||
|
emitResult(filteredData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取全部物料数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非全选模式:直接使用已收集的选中列表
|
||||||
|
dialog.value.dialogVisible = false;
|
||||||
|
emitResult(multipleSelection.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSelection();
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open: () => {
|
open: () => {
|
||||||
|
// 重置查询条件,避免残留上次的筛选条件
|
||||||
|
queryParams.value = {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
brand: '',
|
||||||
|
materialName: ''
|
||||||
|
};
|
||||||
|
// 立即清空旧列表数据,避免闪烁
|
||||||
|
tableData.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
// 重置全选标记
|
||||||
|
isSelectAll.value = false;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
// 根据 userid(逗号分隔)初始化选中状态
|
||||||
|
const arr = userid.value ? userid.value.split(',').filter((id) => id) : [];
|
||||||
|
if (arr.length > 0) {
|
||||||
|
multipleSelection.value = arr.map((id) => ({ id }) as MaterialVO);
|
||||||
|
isIndeterminate.value = true;
|
||||||
|
} else {
|
||||||
|
multipleSelection.value = [];
|
||||||
|
isIndeterminate.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getlist();
|
||||||
dialog.value.dialogVisible = true;
|
dialog.value.dialogVisible = true;
|
||||||
handleUserSelection();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.residentBox {
|
.residentBox {
|
||||||
width: 385px;
|
width: 385px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -1,75 +1,74 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot v-if="$slots.default" />
|
<div>
|
||||||
|
<slot v-if="$slots.default" />
|
||||||
<div v-else class="residentBox" @click="choiceResidentFun">
|
<div v-else class="residentBox" @click="choiceResidentFun">
|
||||||
<div class="defaultBox" v-if="multipleSelection.length === 0 && props.username === null">
|
<div v-if="multipleSelection.length === 0 && props.username === null" class="defaultBox">
|
||||||
<span>请选择</span>
|
<span>请选择</span>
|
||||||
<el-icon><Search /></el-icon>
|
<el-icon><Search /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
|
||||||
|
<span>姓名:{{ multipleSelection[0]?.nickName ?? props.username }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1050">
|
||||||
<span>姓名:{{ multipleSelection[0]?.nickName ?? props.username }}</span>
|
<nav class="flex flex-items-center mb-8">
|
||||||
</div>
|
<div class="flex flex-items-center">
|
||||||
</div>
|
<div style="width: 70px; text-align: right; padding-right: 10px">员工姓名</div>
|
||||||
|
<div class="mr-5 flex-1">
|
||||||
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
|
<el-input v-model="queryParams.nickName" clearable placeholder="请输入员工姓名" style="width: 170px" />
|
||||||
<nav class="flex flex-items-center mb-8">
|
</div>
|
||||||
<div class="flex flex-items-center">
|
|
||||||
<div style="width: 70px; text-align: right; padding-right: 10px">员工姓名</div>
|
|
||||||
<div class="mr-5 flex-1">
|
|
||||||
<el-input style="width: 170px" clearable v-model="queryParams.nickName" placeholder="请输入员工姓名" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="flex flex-items-center">
|
||||||
<div class="flex flex-items-center">
|
<div style="width: 70px; text-align: right; padding-right: 10px">手机号</div>
|
||||||
<div style="width: 70px; text-align: right; padding-right: 10px">手机号</div>
|
<div class="mr-5 flex-1">
|
||||||
<div class="mr-5 flex-1">
|
<el-input v-model="queryParams.phonenumber" clearable placeholder="请输入手机号" style="width: 170px" />
|
||||||
<el-input style="width: 170px" clearable v-model="queryParams.phonenumber" placeholder="请输入手机号" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-button type="primary" @click="getList">查询</el-button>
|
|
||||||
<el-button @click="resetQuery">重置</el-button>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
|
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
|
||||||
<el-table-column label="序号" align="center" width="55" type="index" />
|
|
||||||
<el-table-column label="姓名" align="center" prop="nickName" />
|
|
||||||
<el-table-column label="性别" align="center" width="85" prop="sex">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<dict-tag :options="sys_user_sex" :value="row.sex" />
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="角色" align="center" prop="roleName" />
|
|
||||||
<el-table-column label="当前任务数量" align="center" prop="taskCount" v-if="props.userType == 'repair'" />
|
|
||||||
<el-table-column label="手机号码" align="center" prop="phonenumber" />
|
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-tag :type="row.status === '0' ? 'success' : 'danger'">{{ row.status === '0' ? '正常' : '停用' }}</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
|
||||||
<pagination
|
|
||||||
style="margin-top: 0"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
v-show="total > 0"
|
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="conBack">退出</el-button>
|
<el-button type="primary" @click="getList">查询</el-button>
|
||||||
<el-button type="primary" @click="confirm"> 确定 </el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
</template>
|
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
|
||||||
</el-dialog>
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column align="center" label="序号" type="index" width="55" />
|
||||||
|
<el-table-column align="center" label="姓名" prop="nickName" />
|
||||||
|
<el-table-column align="center" label="性别" prop="sex" width="85">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-tag :options="sys_user_sex" :value="row.sex" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="角色" prop="roleName" />
|
||||||
|
<el-table-column v-if="props.userType == 'repair'" align="center" label="当前任务数量" prop="taskCount" />
|
||||||
|
<el-table-column align="center" label="手机号码" prop="phonenumber" />
|
||||||
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.status === '0' ? 'success' : 'danger'">{{ row.status === '0' ? '正常' : '停用' }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
style="margin-top: 0"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<el-button @click="conBack">退出</el-button>
|
||||||
|
<el-button type="primary" @click="confirm"> 确定 </el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
|
import { ResidentVO } from '@/api/system/residentReviewProcess/resident/type';
|
||||||
import { getUserByRoleKey } from '@/api/system/user';
|
import { getUserByRoleKey } from '@/api/system/user';
|
||||||
import { ref, watch, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
import { ref, watch, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
||||||
@@ -141,7 +140,6 @@ const isMultiple = computed(() => props.isMultiple ?? false);
|
|||||||
// 优化 handleUserSelection,避免重复查找
|
// 优化 handleUserSelection,避免重复查找
|
||||||
const handleUserSelection = () => {
|
const handleUserSelection = () => {
|
||||||
isFetching.value = true;
|
isFetching.value = true;
|
||||||
console.log('获取列表');
|
|
||||||
if (tableData.value.length <= 0 || !multipleTableRef.value) {
|
if (tableData.value.length <= 0 || !multipleTableRef.value) {
|
||||||
isFetching.value = false;
|
isFetching.value = false;
|
||||||
return;
|
return;
|
||||||
@@ -223,7 +221,6 @@ function handleSelectionChange(selection: tableType[]) {
|
|||||||
const uniqueMap = new Map();
|
const uniqueMap = new Map();
|
||||||
finalSelection.forEach((item) => uniqueMap.set(item.id, item));
|
finalSelection.forEach((item) => uniqueMap.set(item.id, item));
|
||||||
multipleSelection.value = Array.from(uniqueMap.values());
|
multipleSelection.value = Array.from(uniqueMap.values());
|
||||||
console.log(multipleSelection.value.map((item) => item.id));
|
|
||||||
} else {
|
} else {
|
||||||
// --- 单选逻辑 ---
|
// --- 单选逻辑 ---
|
||||||
if (selection.length > 0) {
|
if (selection.length > 0) {
|
||||||
@@ -239,8 +236,6 @@ function handleSelectionChange(selection: tableType[]) {
|
|||||||
multipleSelection.value = [];
|
multipleSelection.value = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('handleSelectionChange', selection);
|
|
||||||
}
|
}
|
||||||
// 重置查询
|
// 重置查询
|
||||||
function resetQuery() {
|
function resetQuery() {
|
||||||
@@ -299,7 +294,7 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.residentBox {
|
.residentBox {
|
||||||
width: 385px;
|
width: 385px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot name="default" />
|
<slot name="default" />
|
||||||
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
|
<el-dialog v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body width="1050">
|
||||||
<nav class="flex flex-items-center mb-8 justify-between">
|
<nav class="flex flex-items-center mb-8 justify-between">
|
||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<div style="width: 50px; text-align: right; padding-right: 10px">楼栋</div>
|
<div style="width: 50px; text-align: right; padding-right: 10px">楼栋</div>
|
||||||
<div class="flex-1"></div>
|
<div class="flex-1"></div>
|
||||||
<el-select @change="handleChangeBuilding" clearable style="width: 120px" v-model="queryParams.buildingId">
|
<el-select v-model="queryParams.buildingId" clearable style="width: 120px" @change="handleChangeBuilding">
|
||||||
<el-option v-for="(item, index) in buildingList" :key="index" :label="item.buildingName" :value="item.id"></el-option>
|
<el-option v-for="(item, index) in buildingList" :key="index" :label="item.buildingName" :value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 50px; text-align: right; padding-right: 10px">单元</div>
|
<div style="width: 50px; text-align: right; padding-right: 10px">单元</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-select @change="handleChangeUnit" clearable style="width: 120px" v-model="queryParams.unitNoId">
|
<el-select v-model="queryParams.unitNoId" clearable style="width: 120px" @change="handleChangeUnit">
|
||||||
<el-option v-for="(item, index) in unitList" :key="index" :label="item.unitNoName" :value="item.unitNoId"></el-option>
|
<el-option v-for="(item, index) in unitList" :key="index" :label="item.unitNoName" :value="item.unitNoId"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,13 +21,13 @@
|
|||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 60px; text-align: right; padding-right: 10px">房屋号</div>
|
<div style="width: 60px; text-align: right; padding-right: 10px">房屋号</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-input clearable @clear="handleClear" style="width: 120px" v-model="queryParams.houseNo" placeholder="请输入房屋号"></el-input>
|
<el-input v-model="queryParams.houseNo" clearable placeholder="请输入房屋号" style="width: 120px" @clear="handleClear"></el-input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-items-center mr-20px">
|
<div class="flex flex-items-center mr-20px">
|
||||||
<div style="width: 80px; text-align: right; padding-right: 10px">业主名称</div>
|
<div style="width: 80px; text-align: right; padding-right: 10px">业主名称</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<el-input clearable @clear="handleClear" style="width: 120px" v-model="queryParams.residentName" placeholder="请输入业主名称"></el-input>
|
<el-input v-model="queryParams.residentName" clearable placeholder="请输入业主名称" style="width: 120px" @clear="handleClear"></el-input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -36,60 +36,66 @@
|
|||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<el-table ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
|
<el-table ref="multipleTableRef" v-loading="loading" :data="tableData" border>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" width="55">
|
||||||
<el-table-column label="序号" align="center" width="55" type="index" />
|
<template #header>
|
||||||
<el-table-column label="楼栋号" align="center">
|
<el-checkbox v-model="isSelectAll" :indeterminate="isIndeterminate" @change="handleSelectAllChange" />
|
||||||
|
</template>
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox :model-value="isRowSelected(scope.row)" @change="(val: boolean) => handleRowCheckChange(scope.row, val)" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="序号" type="index" width="55" />
|
||||||
|
<el-table-column align="center" label="楼栋号">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[0] : '---' }}</span>
|
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[0] : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="单元" align="center">
|
<el-table-column align="center" label="单元">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[1] : '---' }}</span>
|
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[1] : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="房间" align="center">
|
<el-table-column align="center" label="房间">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[2] : '---' }}</span>
|
<span>{{ scope.row.house_name ? scope.row.house_name.split('-')[2] : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="业主" align="center">
|
<el-table-column align="center" label="业主">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
|
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="性别" align="center">
|
<el-table-column align="center" label="性别">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="sys_user_sex" :value="scope.row.gender"></dict-tag>
|
<dict-tag :options="sys_user_sex" :value="scope.row.gender"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="手机号" align="center" prop="phone" />
|
<el-table-column align="center" label="手机号" prop="phone" />
|
||||||
</el-table>
|
</el-table>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
<div class="dialog-footer flex flex-items-center flex-justify-between">
|
||||||
<pagination
|
<pagination
|
||||||
style="margin-top: 0"
|
|
||||||
layout="total, prev, pager, next, jumper"
|
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
style="margin-top: 0"
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="conback">退出</el-button>
|
<el-button @click="conback">退出</el-button>
|
||||||
<el-button type="primary" @click="confirm"> 确定 </el-button>
|
<el-button :loading="loading" type="primary" @click="confirm"> 确定 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
|
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
|
||||||
import { BillUserlist, queryResidentList_holder } from '@/api/system/SdbBill';
|
import { BillUserlist, queryResidentList_holder } from '@/api/system/SdbBill';
|
||||||
import { ref, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
|
import { ComponentInternalInstance, getCurrentInstance, ref, toRefs } from 'vue';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
|
const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
|
||||||
@@ -137,53 +143,105 @@ const multipleTableRef = ref();
|
|||||||
const tableData = ref<BillUserlist[]>([]);
|
const tableData = ref<BillUserlist[]>([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const isFetching = ref(false);
|
|
||||||
// 存储选中项
|
/** 存储所有选中项(跨页累计,非全选模式使用) */
|
||||||
const multipleSelection = ref<BillUserlist[]>([]);
|
const multipleSelection = ref<BillUserlist[]>([]);
|
||||||
|
/** 是否已跨页全选(标记模式,不实际持有全部数据) */
|
||||||
|
const isSelectAll = ref(false);
|
||||||
|
/** 表头复选框半选状态(部分选中时为 true) */
|
||||||
|
const isIndeterminate = ref(false);
|
||||||
|
/** 全选模式下被手动取消勾选的 residentId 列表 */
|
||||||
|
const deselectedIds = ref<string[]>([]);
|
||||||
|
|
||||||
const isMultiple = computed(() => props.isMultiple ?? false);
|
const isMultiple = computed(() => props.isMultiple ?? false);
|
||||||
|
|
||||||
// 优化 handleUserSelection,避免重复查找
|
/** 判断某行是否已选中 */
|
||||||
const handleUserSelection = () => {
|
function isRowSelected(row: BillUserlist): boolean {
|
||||||
isFetching.value = true;
|
if (isSelectAll.value) {
|
||||||
if (!multipleTableRef.value || !tableData.value.length) {
|
// 全选模式:只要不在取消列表中就算选中
|
||||||
isFetching.value = false;
|
return !deselectedIds.value.includes(row.residentId);
|
||||||
|
}
|
||||||
|
return multipleSelection.value.some((item) => item.residentId === row.residentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新表头复选框状态:全选 / 半选 / 空 */
|
||||||
|
function updateIndeterminate() {
|
||||||
|
if (isSelectAll.value) {
|
||||||
|
// 全选模式下:有取消勾选的行 → 半选,否则 → 全选
|
||||||
|
isIndeterminate.value = deselectedIds.value.length > 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rowsToSelect = tableData.value.filter((row) => {
|
|
||||||
return multipleSelection.value.some((selected) => selected.residentId === row.residentId);
|
const selectedCount = multipleSelection.value.length;
|
||||||
});
|
const totalCount = total.value;
|
||||||
multipleTableRef.value.clearSelection();
|
|
||||||
if (rowsToSelect.length > 0) {
|
if (selectedCount === 0) {
|
||||||
nextTick(() => {
|
isIndeterminate.value = false;
|
||||||
rowsToSelect.forEach((row) => {
|
} else if (totalCount > 0 && selectedCount >= totalCount) {
|
||||||
multipleTableRef.value?.toggleRowSelection(row, true);
|
// 手动逐行全选 → 切换为全选标记模式,释放 multipleSelection 内存
|
||||||
});
|
isSelectAll.value = true;
|
||||||
isFetching.value = false;
|
isIndeterminate.value = false;
|
||||||
});
|
deselectedIds.value = [];
|
||||||
|
multipleSelection.value = [];
|
||||||
} else {
|
} else {
|
||||||
isFetching.value = false;
|
isIndeterminate.value = true;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/** 跨页全选 / 取消全选(仅设标记,不拉取数据) */
|
||||||
|
function handleSelectAllChange(val: boolean) {
|
||||||
|
if (val) {
|
||||||
|
isSelectAll.value = true;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
multipleSelection.value = [];
|
||||||
|
} else {
|
||||||
|
isSelectAll.value = false;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
multipleSelection.value = [];
|
||||||
|
}
|
||||||
|
updateIndeterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 单行勾选 / 取消勾选 */
|
||||||
|
function handleRowCheckChange(row: BillUserlist, checked: boolean) {
|
||||||
|
if (isSelectAll.value) {
|
||||||
|
// 全选模式:维护取消列表
|
||||||
|
if (checked) {
|
||||||
|
deselectedIds.value = deselectedIds.value.filter((id) => id !== row.residentId);
|
||||||
|
} else {
|
||||||
|
if (!deselectedIds.value.includes(row.residentId)) {
|
||||||
|
deselectedIds.value.push(row.residentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非全选模式:维护选中列表
|
||||||
|
if (checked) {
|
||||||
|
if (!isRowSelected(row)) {
|
||||||
|
multipleSelection.value.push(row);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
multipleSelection.value = multipleSelection.value.filter((item) => item.residentId !== row.residentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateIndeterminate();
|
||||||
|
}
|
||||||
|
|
||||||
// ====================== 方法 ======================
|
// ====================== 方法 ======================
|
||||||
|
|
||||||
// 获取列表
|
// 获取列表
|
||||||
function getList() {
|
function getList() {
|
||||||
isFetching.value = true; // 加锁
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
queryResidentList_holder(queryParams.value)
|
queryResidentList_holder(queryParams.value)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
tableData.value = res.rows;
|
tableData.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
handleUserSelection();
|
updateIndeterminate();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('获取用户列表失败:', error);
|
console.error('获取用户列表失败:', error);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
isFetching.value = false; // 加锁
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,37 +273,6 @@ function handleChangeBuilding(val: string) {
|
|||||||
function handleChangeUnit() {
|
function handleChangeUnit() {
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
// ==============================================
|
|
||||||
// ✅ 新增:处理 selection-change(多选专用)
|
|
||||||
// ==============================================
|
|
||||||
function handleSelectionChange(selection: BillUserlist[]) {
|
|
||||||
if (isFetching.value) return;
|
|
||||||
if (isMultiple.value) {
|
|
||||||
const currentSelectedIds = new Set(selection.map((item) => item.residentId));
|
|
||||||
const otherPageSelections = multipleSelection.value.filter((item) => {
|
|
||||||
const isCurrentPageItem = tableData.value.some((row) => row.residentId === item.residentId);
|
|
||||||
if (isCurrentPageItem) {
|
|
||||||
return currentSelectedIds.has(item.residentId);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 3. 合并:其他页保留的 + 当前页新选中的
|
|
||||||
const finalSelection = [...otherPageSelections, ...selection];
|
|
||||||
// 4. 去重(以防万一)
|
|
||||||
const uniqueMap = new Map();
|
|
||||||
finalSelection.forEach((item) => uniqueMap.set(item.residentId, item));
|
|
||||||
multipleSelection.value = Array.from(uniqueMap.values());
|
|
||||||
console.log(multipleSelection.value.map((item) => item.residentId));
|
|
||||||
} else {
|
|
||||||
// --- 单选逻辑 ---
|
|
||||||
if (selection.length > 0) {
|
|
||||||
multipleSelection.value = [selection[selection.length - 1]];
|
|
||||||
} else {
|
|
||||||
multipleSelection.value = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 重置查询
|
// 重置查询
|
||||||
function resetQuery() {
|
function resetQuery() {
|
||||||
queryParams.value = {
|
queryParams.value = {
|
||||||
@@ -256,6 +283,7 @@ function resetQuery() {
|
|||||||
residentName: null,
|
residentName: null,
|
||||||
houseNo: null
|
houseNo: null
|
||||||
};
|
};
|
||||||
|
resetSelection();
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,41 +293,82 @@ function conback() {
|
|||||||
resetQuery();
|
resetQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==============================================
|
/** 重置所有选中状态 */
|
||||||
// ✅ 核心修改:根据 returnvalue 返回对应的值
|
function resetSelection() {
|
||||||
// ==============================================
|
multipleSelection.value = [];
|
||||||
function confirm() {
|
isSelectAll.value = false;
|
||||||
dialog.value.dialogVisible = false;
|
isIndeterminate.value = false;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据 returnvalue 发射选中结果 */
|
||||||
|
function emitResult(data: BillUserlist[]) {
|
||||||
if (isMultiple.value) {
|
if (isMultiple.value) {
|
||||||
// 多选
|
|
||||||
if (returnvalue.value === '*') {
|
if (returnvalue.value === '*') {
|
||||||
// ✅ 返回整个对象数组
|
emit('change', data);
|
||||||
emit('change', multipleSelection.value);
|
|
||||||
} else {
|
} else {
|
||||||
// 返回指定字段数组
|
|
||||||
emit(
|
emit(
|
||||||
'change',
|
'change',
|
||||||
multipleSelection.value.map((item) => item[returnvalue.value as keyof BillUserlist])
|
data.map((item) => item[returnvalue.value as keyof BillUserlist])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 单选
|
|
||||||
if (returnvalue.value === '*') {
|
if (returnvalue.value === '*') {
|
||||||
// ✅ 返回整个对象
|
emit('change', data[0]);
|
||||||
emit('change', multipleSelection.value[0]);
|
|
||||||
} else {
|
} else {
|
||||||
// 返回指定字段
|
emit('change', data[0]?.[returnvalue.value as keyof BillUserlist]);
|
||||||
emit('change', multipleSelection.value[0][returnvalue.value as keyof BillUserlist]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
multipleSelection.value = [];
|
/** 确定:全选模式下按需拉取全部数据,非全选模式直接使用已选列表 */
|
||||||
multipleTableRef.value.clearSelection();
|
async function confirm() {
|
||||||
|
if (isSelectAll.value) {
|
||||||
|
// 全选模式:此时才真正拉取全部数据,排除已取消勾选的行
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await queryResidentList_holder({
|
||||||
|
...queryParams.value,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: total.value || undefined
|
||||||
|
});
|
||||||
|
const allData: BillUserlist[] = res.rows || [];
|
||||||
|
const filteredData = allData.filter((item) => !deselectedIds.value.includes(item.residentId));
|
||||||
|
dialog.value.dialogVisible = false;
|
||||||
|
emitResult(filteredData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取全部数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非全选模式:直接使用已收集的选中列表
|
||||||
|
dialog.value.dialogVisible = false;
|
||||||
|
emitResult(multipleSelection.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open: (arr: string[] = []) => {
|
open: (arr: string[] = []) => {
|
||||||
userid.value = arr;
|
userid.value = arr;
|
||||||
|
// 重置查询条件,避免残留上次的筛选条件
|
||||||
|
queryParams.value = {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
buildingId: null,
|
||||||
|
residentName: null,
|
||||||
|
houseNo: null,
|
||||||
|
unitNoId: null
|
||||||
|
};
|
||||||
|
// 立即清空旧列表数据,避免闪烁
|
||||||
|
tableData.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
// 重置全选标记
|
||||||
|
isSelectAll.value = false;
|
||||||
|
deselectedIds.value = [];
|
||||||
|
// 根据传入的 ID 数组初始化选中状态
|
||||||
if (arr && arr.length > 0) {
|
if (arr && arr.length > 0) {
|
||||||
multipleSelection.value = arr.map(
|
multipleSelection.value = arr.map(
|
||||||
(id) =>
|
(id) =>
|
||||||
@@ -307,8 +376,10 @@ defineExpose({
|
|||||||
residentId: id
|
residentId: id
|
||||||
}) as BillUserlist
|
}) as BillUserlist
|
||||||
);
|
);
|
||||||
|
isIndeterminate.value = true;
|
||||||
} else {
|
} else {
|
||||||
multipleSelection.value = [];
|
multipleSelection.value = [];
|
||||||
|
isIndeterminate.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getList();
|
getList();
|
||||||
@@ -318,7 +389,7 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.residentBox {
|
.residentBox {
|
||||||
width: 385px;
|
width: 385px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||||
import { getVillageByIdAPI } from '@/api/system/community';
|
import { getVillageByIdAPI } from '@/api/system/community';
|
||||||
import { onUnmounted, ref, watch, onMounted, nextTick } from 'vue';
|
import { onUnmounted, ref, watch, onMounted, nextTick } from 'vue';
|
||||||
@@ -320,7 +320,6 @@ onMounted(async () => {
|
|||||||
|
|
||||||
// 禁用状态不开启绘制/点击
|
// 禁用状态不开启绘制/点击
|
||||||
if (!props.disabled) {
|
if (!props.disabled) {
|
||||||
console.log(props.clickOrDraw);
|
|
||||||
props.clickOrDraw ? handleMap() : MapDrawLine();
|
props.clickOrDraw ? handleMap() : MapDrawLine();
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -355,10 +354,10 @@ onUnmounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="mapLoading" class="map" id="GD-Map"></div>
|
<div id="GD-Map" v-loading="mapLoading" class="map"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.map {
|
.map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 450px;
|
min-height: 450px;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="{ hidden: hidden }" class="pagination-container">
|
<div :class="{ hidden: hidden }" class="pagination-container">
|
||||||
<span class="total">共 {{ total }} 条</span>
|
<span v-if="!props.layout.includes('total')" class="total">共 {{ total }} 条</span>
|
||||||
<slot name="pageContent"></slot>
|
<slot name="pageContent"></slot>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
v-model:current-page="currentPage"
|
v-model:current-page="currentPage"
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Pagination" lang="ts">
|
<script lang="ts" name="Pagination" setup>
|
||||||
import { scrollTo } from '@/utils/scroll-to';
|
import { scrollTo } from '@/utils/scroll-to';
|
||||||
import { propTypes } from '@/utils/propTypes';
|
import { propTypes } from '@/utils/propTypes';
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="quarter-select">
|
<div class="quarter-select">
|
||||||
<!-- 输入框,点击弹出popover -->
|
<!-- 输入框,点击弹出popover -->
|
||||||
<el-popover v-model:visible="popoverVisible" placement="bottom-start" trigger="manual" width="240">
|
<el-popover v-model:visible="popoverVisible" placement="bottom-start" trigger="click" width="240">
|
||||||
<div class="quarter-panel">
|
<div class="quarter-panel">
|
||||||
<!-- 年份切换 -->
|
<!-- 年份切换 -->
|
||||||
<div class="year-header">
|
<div class="year-header">
|
||||||
<el-button icon="ArrowLeft" size="small" circle @click="prevYear" />
|
<el-button circle icon="ArrowLeft" size="small" @click="prevYear" />
|
||||||
<span class="current-year">{{ currentYear }}年</span>
|
<span class="current-year">{{ currentYear }}年</span>
|
||||||
<el-button icon="ArrowRight" size="small" circle @click="nextYear" />
|
<el-button circle icon="ArrowRight" size="small" @click="nextYear" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 四个季度按钮 -->
|
<!-- 四个季度按钮 -->
|
||||||
<div class="quarter-buttons">
|
<div class="quarter-buttons">
|
||||||
<el-button
|
<el-button
|
||||||
v-for="q in 4"
|
v-for="q in 4"
|
||||||
:key="q"
|
:key="q"
|
||||||
style="margin: 0"
|
:disabled="isDisabledQuarter()"
|
||||||
:type="isSelected(currentYear, q) ? 'primary' : ''"
|
:type="isSelected(currentYear, q) ? 'primary' : ''"
|
||||||
:disabled="isDisabledQuarter(currentYear, q)"
|
style="margin: 0"
|
||||||
@click="handleSelect(currentYear, q)"
|
@click="handleSelect(currentYear, q)"
|
||||||
>
|
>
|
||||||
第{{ q }}季度
|
第{{ q }}季度
|
||||||
@@ -27,19 +27,19 @@
|
|||||||
<template #reference>
|
<template #reference>
|
||||||
<el-input
|
<el-input
|
||||||
:model-value="displayText"
|
:model-value="displayText"
|
||||||
|
clearable
|
||||||
placeholder="请选择季度"
|
placeholder="请选择季度"
|
||||||
readonly
|
readonly
|
||||||
suffix-icon="Calendar"
|
suffix-icon="Calendar"
|
||||||
@click="popoverVisible = true"
|
|
||||||
clearable
|
|
||||||
@clear="handleClear"
|
@clear="handleClear"
|
||||||
|
@click="popoverVisible = true"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
|
|
||||||
// 外部v‑model绑定
|
// 外部v‑model绑定
|
||||||
@@ -55,7 +55,7 @@ const emit = defineEmits(['update:modelValue', 'change']);
|
|||||||
const popoverVisible = ref(false);
|
const popoverVisible = ref(false);
|
||||||
|
|
||||||
// 解析回显的季度值 2026‑1
|
// 解析回显的季度值 2026‑1
|
||||||
const parseQuarter = (str) => {
|
const parseQuarter = (str: any) => {
|
||||||
if (!str) return { year: new Date().getFullYear(), quarter: null };
|
if (!str) return { year: new Date().getFullYear(), quarter: null };
|
||||||
const [y, q] = str.split('-').map(Number);
|
const [y, q] = str.split('-').map(Number);
|
||||||
return { year: y, quarter: q };
|
return { year: y, quarter: q };
|
||||||
@@ -63,18 +63,16 @@ const parseQuarter = (str) => {
|
|||||||
|
|
||||||
const { year: initYear } = parseQuarter(props.modelValue);
|
const { year: initYear } = parseQuarter(props.modelValue);
|
||||||
const currentYear = ref(initYear);
|
const currentYear = ref(initYear);
|
||||||
console.log(currentYear.value, typeof currentYear.value);
|
|
||||||
|
|
||||||
// 输入框展示文本
|
// 输入框展示文本
|
||||||
const displayText = computed(() => {
|
const displayText = computed(() => {
|
||||||
if (!props.modelValue) return '';
|
if (!props.modelValue) return '';
|
||||||
console.log(props.modelValue, props.modelValue.trim().split('-'));
|
|
||||||
const [y, q] = props.modelValue.split('-').map(Number);
|
const [y, q] = props.modelValue.split('-').map(Number);
|
||||||
return `${y}年${q}季度`;
|
return `${y}年${q}季度`;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 是否选中该季度
|
// 是否选中该季度
|
||||||
const isSelected = (y, q) => {
|
const isSelected = (y: any, q: any) => {
|
||||||
return props.modelValue === `${y}-${q}`;
|
return props.modelValue === `${y}-${q}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,7 +89,7 @@ const prevYear = () => currentYear.value--;
|
|||||||
const nextYear = () => currentYear.value++;
|
const nextYear = () => currentYear.value++;
|
||||||
|
|
||||||
// 选中季度
|
// 选中季度
|
||||||
const handleSelect = (y, q) => {
|
const handleSelect = (y: any, q: any) => {
|
||||||
const val = `${y}-${q}`;
|
const val = `${y}-${q}`;
|
||||||
emit('update:modelValue', val);
|
emit('update:modelValue', val);
|
||||||
emit('change', val);
|
emit('change', val);
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
<div class="top-right-btn" :style="style">
|
<div class="top-right-btn" :style="style">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<!-- 添加按钮 -->
|
<!-- 添加按钮 -->
|
||||||
<el-button :disabled="props.disableAdd" v-if="props.showAdd" icon="Plus" type="primary" @click="toggleSearch()"> 新建 </el-button>
|
<el-button :disabled="props.disableAdd" v-if="props.showAdd" icon="Plus" type="primary" @click="toggleSearch()">
|
||||||
|
{{ props.addTitle }}
|
||||||
|
</el-button>
|
||||||
|
<slot name="actions"></slot>
|
||||||
<!-- 批量操作下拉框 -->
|
<!-- 批量操作下拉框 -->
|
||||||
<el-dropdown v-if="props.showDelete || props.showEdit || $slots.dropdown" trigger="click" style="margin-left: 10px">
|
<el-dropdown v-if="props.showDelete || props.showEdit || $slots.dropdown" trigger="click" style="margin-left: 10px">
|
||||||
<el-button @click.stop="refresh"> {{ props.moreTitle }} </el-button>
|
<el-button @click.stop="refresh"> {{ props.moreTitle }} </el-button>
|
||||||
@@ -12,8 +14,12 @@
|
|||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<!-- 这里直接渲染,不嵌套插槽 -->
|
<!-- 这里直接渲染,不嵌套插槽 -->
|
||||||
<el-dropdown-menu v-if="!$slots.dropdown">
|
<el-dropdown-menu v-if="!$slots.dropdown">
|
||||||
<el-dropdown-item :disabled="props.disableEdit" v-if="props.showEdit" @click="emits('update:edit')"> 编辑 </el-dropdown-item>
|
<el-dropdown-item :disabled="props.disableEdit" v-if="props.showEdit" @click="emits('update:edit')">
|
||||||
<el-dropdown-item :disabled="props.disableDelete" v-if="props.showDelete" @click="emits('update:delete')"> 批量删除 </el-dropdown-item>
|
{{ props.editTitle }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item :disabled="props.disableDelete" v-if="props.showDelete" @click="emits('update:delete')">
|
||||||
|
{{ props.deleteTitle }}
|
||||||
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
<!-- 外部自定义内容直接渲染,不包任何多余标签 -->
|
<!-- 外部自定义内容直接渲染,不包任何多余标签 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -58,6 +64,10 @@ const props = defineProps({
|
|||||||
showDelete: propTypes.bool.def(true),
|
showDelete: propTypes.bool.def(true),
|
||||||
showEdit: propTypes.bool.def(true),
|
showEdit: propTypes.bool.def(true),
|
||||||
|
|
||||||
|
addTitle: propTypes.string.def('新建'),
|
||||||
|
editTitle: propTypes.string.def('编辑'),
|
||||||
|
deleteTitle: propTypes.string.def('批量删除'),
|
||||||
|
|
||||||
disableAdd: propTypes.bool.def(false),
|
disableAdd: propTypes.bool.def(false),
|
||||||
disableDelete: propTypes.bool.def(false),
|
disableDelete: propTypes.bool.def(false),
|
||||||
disableEdit: propTypes.bool.def(false)
|
disableEdit: propTypes.bool.def(false)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="step-timeline">
|
<div class="step-timeline">
|
||||||
<div v-for="(item, index) in steps" :key="index" class="step-item" :class="item.status">
|
<div v-for="(item, index) in steps" :key="index" :class="item.status" class="step-item">
|
||||||
<div class="step-node">
|
<div class="step-node">
|
||||||
<div class="step-circle">
|
<div class="step-circle">
|
||||||
<el-icon v-if="item.status === 'completed'" :size="12"><Check /></el-icon>
|
<el-icon v-if="item.status === 'completed'" :size="12"><Check /></el-icon>
|
||||||
@@ -10,23 +10,23 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="step-content">
|
<div class="step-content">
|
||||||
<div class="step-title">
|
<div class="step-title">
|
||||||
<slot name="title" :item="item" :index="index"></slot>
|
<slot :index="index" :item="item" name="title"></slot>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="item.wrap === true">
|
<div v-if="item.wrap === true">
|
||||||
<div class="step-subtitle">
|
<div class="step-subtitle">
|
||||||
<slot name="subtitle" :item="item" :index="index"></slot>
|
<slot :index="index" :item="item" name="subtitle"></slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="step-time">
|
<div class="step-time">
|
||||||
<slot name="time" :item="item" :index="index"></slot>
|
<slot :index="index" :item="item" name="time"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<span>
|
<span>
|
||||||
<slot name="subtitle" :item="item" :index="index"></slot>
|
<slot :index="index" :item="item" name="subtitle"></slot>
|
||||||
</span>
|
</span>
|
||||||
|
<span> </span>
|
||||||
<span>
|
<span>
|
||||||
<slot name="time" :item="item" :index="index"></slot>
|
<slot :index="index" :item="item" name="time"></slot>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
0
src/enums/permission.ts
Normal file
0
src/enums/permission.ts
Normal file
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="navbar" :class="'nav' + navType">
|
<div :class="'nav' + navType" class="navbar">
|
||||||
<hamburger
|
<hamburger
|
||||||
v-show="Showhamburger"
|
v-show="Showhamburger"
|
||||||
id="hamburger-container"
|
id="hamburger-container"
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
<template v-if="appStore.device !== 'mobile'">
|
<template v-if="appStore.device !== 'mobile'">
|
||||||
<el-tooltip :content="proxy.$t('navbar.message')" effect="dark" placement="bottom">
|
<el-tooltip :content="proxy.$t('navbar.message')" effect="dark" placement="bottom">
|
||||||
<div>
|
<div>
|
||||||
<el-popover placement="bottom-end" trigger="click" transition="el-zoom-in-top" :width="400" :persistent="false">
|
<el-popover :persistent="false" :width="400" placement="bottom-end" transition="el-zoom-in-top" trigger="click">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-badge :value="newNotice > 0 ? newNotice : ''" :max="99">
|
<el-badge :max="99" :value="newNotice > 0 ? newNotice : ''">
|
||||||
<div class="right-menu-item hover-effect" style="display: block"><svg-icon icon-class="message" /></div>
|
<div class="right-menu-item hover-effect" style="display: block"><svg-icon icon-class="message" /></div>
|
||||||
</el-badge>
|
</el-badge>
|
||||||
</template>
|
</template>
|
||||||
@@ -29,15 +29,16 @@
|
|||||||
<div class="avatar-container">
|
<div class="avatar-container">
|
||||||
<el-dropdown class="right-menu-item hover-effect" trigger="click" @command="handleCommand">
|
<el-dropdown class="right-menu-item hover-effect" trigger="click" @command="handleCommand">
|
||||||
<div class="avatar-wrapper">
|
<div class="avatar-wrapper">
|
||||||
<img alt="头像" :src="userStore.avatar" class="user-avatar" />
|
<div class="username">{{ userStore.nickname }}</div>
|
||||||
|
<img :src="userStore.avatar" alt="头像" class="user-avatar" />
|
||||||
<el-icon><caret-bottom /></el-icon>
|
<el-icon><caret-bottom /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item divided command="changecommunity" v-if="isShow">
|
<el-dropdown-item v-if="isShow" command="changecommunity" divided>
|
||||||
<span>{{ proxy.$t('navbar.community') }}</span>
|
<span>{{ proxy.$t('navbar.community') }}</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<router-link to="/system/user/profile" v-if="isShow">
|
<router-link v-if="isShow" v-has-permi="['system:user:profile']" to="/system/user/profile">
|
||||||
<el-dropdown-item>{{ proxy.$t('navbar.personalCenter') }}</el-dropdown-item>
|
<el-dropdown-item>{{ proxy.$t('navbar.personalCenter') }}</el-dropdown-item>
|
||||||
</router-link>
|
</router-link>
|
||||||
<el-dropdown-item :divided="isShow" command="logout">
|
<el-dropdown-item :divided="isShow" command="logout">
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import hamburger from '@/components/Hamburger/index.vue';
|
import hamburger from '@/components/Hamburger/index.vue';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { useUserStore } from '@/store/modules/user';
|
import { useUserStore } from '@/store/modules/user';
|
||||||
@@ -61,7 +62,8 @@ import notice from './notice/index.vue';
|
|||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import { ElMessageBoxOptions } from 'element-plus/es/components/message-box/src/message-box.type';
|
import { ElMessageBoxOptions } from 'element-plus/es/components/message-box/src/message-box.type';
|
||||||
import { CaretBottom } from '@element-plus/icons-vue';
|
import { CaretBottom } from '@element-plus/icons-vue';
|
||||||
|
import { closeWebSocket } from '@/utils/websocket';
|
||||||
|
import { closeSSE } from '@/utils/sse';
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
Showhamburger: {
|
Showhamburger: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -93,6 +95,9 @@ const logout = async () => {
|
|||||||
type: 'warning'
|
type: 'warning'
|
||||||
} as ElMessageBoxOptions);
|
} as ElMessageBoxOptions);
|
||||||
userStore.logout().then(() => {
|
userStore.logout().then(() => {
|
||||||
|
// 关闭长连接
|
||||||
|
closeWebSocket();
|
||||||
|
closeSSE();
|
||||||
router.replace({
|
router.replace({
|
||||||
path: '/login',
|
path: '/login',
|
||||||
query: {
|
query: {
|
||||||
@@ -241,9 +246,14 @@ watch(
|
|||||||
|
|
||||||
.avatar-wrapper {
|
.avatar-wrapper {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
// margin-left: 20px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.username {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
.user-avatar {
|
.user-avatar {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
<div v-if="!item.hidden">
|
<div v-if="!item.hidden">
|
||||||
<template v-if="hasOneShowingChild(item, item.children) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
|
<template v-if="hasOneShowingChild(item, item.children) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
|
||||||
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
|
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
|
||||||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
|
<el-menu-item :class="{ 'submenu-title-noDropdown': !isNest }" :index="resolvePath(onlyOneChild.path)">
|
||||||
<svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" />
|
<svg-icon v-if="onlyOneChild.path === '/index'" :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" />
|
||||||
|
<div v-else style="margin-right: 14px; width: 14px"></div>
|
||||||
<template #title>
|
<template #title>
|
||||||
<span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span>
|
<span :title="hasTitle(onlyOneChild.meta.title)" class="menu-title">{{ onlyOneChild.meta.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</app-link>
|
</app-link>
|
||||||
@@ -14,22 +15,22 @@
|
|||||||
<el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
|
<el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
|
||||||
<template v-if="item.meta" #title>
|
<template v-if="item.meta" #title>
|
||||||
<svg-icon :icon-class="item.meta ? item.meta.icon : ''" />
|
<svg-icon :icon-class="item.meta ? item.meta.icon : ''" />
|
||||||
<span class="menu-title" :title="hasTitle(item.meta?.title)">{{ item.meta?.title }}</span>
|
<span :title="hasTitle(item.meta?.title)" class="menu-title">{{ item.meta?.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<sidebar-item
|
<sidebar-item
|
||||||
v-for="(child, index) in item.children"
|
v-for="(child, index) in item.children"
|
||||||
:key="child.path + index"
|
:key="child.path + index"
|
||||||
|
:base-path="resolvePath(child.path)"
|
||||||
:is-nest="true"
|
:is-nest="true"
|
||||||
:item="child"
|
:item="child"
|
||||||
:base-path="resolvePath(child.path)"
|
|
||||||
class="nest-menu"
|
class="nest-menu"
|
||||||
/>
|
/>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { isExternal } from '@/utils/validate';
|
import { isExternal } from '@/utils/validate';
|
||||||
import AppLink from './Link.vue';
|
import AppLink from './Link.vue';
|
||||||
import { getNormalPath } from '@/utils/ruoyi';
|
import { getNormalPath } from '@/utils/ruoyi';
|
||||||
@@ -49,9 +50,7 @@ const props = defineProps({
|
|||||||
default: ''
|
default: ''
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const onlyOneChild = ref<any>({});
|
const onlyOneChild = ref<any>({});
|
||||||
|
|
||||||
const hasOneShowingChild = (parent: RouteRecordRaw, children?: RouteRecordRaw[]) => {
|
const hasOneShowingChild = (parent: RouteRecordRaw, children?: RouteRecordRaw[]) => {
|
||||||
if (!children) {
|
if (!children) {
|
||||||
children = [];
|
children = [];
|
||||||
|
|||||||
@@ -4,24 +4,25 @@
|
|||||||
<el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper">
|
<el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper">
|
||||||
<transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in">
|
<transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in">
|
||||||
<el-menu
|
<el-menu
|
||||||
:default-active="activeMenu"
|
:active-text-color="theme"
|
||||||
:collapse="isCollapse"
|
|
||||||
:background-color="bgColor"
|
:background-color="bgColor"
|
||||||
|
:collapse="isCollapse"
|
||||||
|
:collapse-transition="false"
|
||||||
|
:default-active="activeMenu"
|
||||||
|
:popper-offset="12"
|
||||||
:text-color="textColor"
|
:text-color="textColor"
|
||||||
:unique-opened="true"
|
:unique-opened="true"
|
||||||
:active-text-color="theme"
|
|
||||||
:collapse-transition="false"
|
|
||||||
:popper-offset="12"
|
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
|
@select="handleMenuSelect"
|
||||||
>
|
>
|
||||||
<sidebar-item v-for="(r, index) in sidebarRouters" :key="r.path + index" :item="r" :base-path="r.path" />
|
<sidebar-item v-for="(r, index) in sidebarRouters" :key="r.path + index" :base-path="r.path" :item="r" />
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</transition>
|
</transition>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import Logo from './Logo.vue';
|
import Logo from './Logo.vue';
|
||||||
import SidebarItem from './SidebarItem.vue';
|
import SidebarItem from './SidebarItem.vue';
|
||||||
import variables from '@/assets/styles/variables.module.scss';
|
import variables from '@/assets/styles/variables.module.scss';
|
||||||
@@ -54,4 +55,22 @@ const activeMenu = computed(() => {
|
|||||||
const bgColor = '#dfedff';
|
const bgColor = '#dfedff';
|
||||||
// const bgColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground));
|
// const bgColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground));
|
||||||
const textColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuColor : variables.menuLightColor));
|
const textColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuColor : variables.menuLightColor));
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
// UI层菜单点击锁
|
||||||
|
const menuLoading = ref(false);
|
||||||
|
|
||||||
|
const handleMenuSelect = async (path: string) => {
|
||||||
|
if (menuLoading.value) return;
|
||||||
|
if (router.currentRoute.value.path === path) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
menuLoading.value = true;
|
||||||
|
await router.push(path);
|
||||||
|
} catch (e) {
|
||||||
|
// 捕获导航取消异常
|
||||||
|
} finally {
|
||||||
|
menuLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,38 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 👇 加这一层全局缩放容器 -->
|
<!-- 👇 加这一层全局缩放容器 -->
|
||||||
<div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
|
<div :class="classObj" :style="{ '--current-color': theme }" class="app-wrapper">
|
||||||
<side-bar class="sidebar-container" />
|
<side-bar class="sidebar-container" />
|
||||||
<div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container" id="main-container">
|
<div id="main-container" :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
|
||||||
<div class="navbarContant">
|
<div class="navbarContant">
|
||||||
<navbar ref="navbarRef" @set-layout="setLayout" />
|
<navbar ref="navbarRef" @set-layout="setLayout" />
|
||||||
</div>
|
</div>
|
||||||
<app-main />
|
<app-main />
|
||||||
<i class="bgColor" v-if="bgColorStore.isShow"></i>
|
<i v-if="bgColorStore.isShow" class="bgColor"></i>
|
||||||
<settings ref="settingRef" />
|
<settings ref="settingRef" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
<script setup lang="ts">
|
|
||||||
// ==========================================
|
|
||||||
// ✅ 第1步:统一 import
|
|
||||||
// ==========================================
|
|
||||||
import { ref, computed, watchEffect, onMounted, onUnmounted } from 'vue';
|
import { ref, computed, watchEffect, onMounted, onUnmounted } from 'vue';
|
||||||
import { useWindowSize } from '@vueuse/core';
|
import { useWindowSize } from '@vueuse/core';
|
||||||
import SideBar from './components/Sidebar/index.vue';
|
import SideBar from './components/Sidebar/index.vue';
|
||||||
import { AppMain, Navbar, Settings } from './components';
|
import { AppMain, Navbar, Settings } from './components';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
// import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
|
||||||
import { useBgColor } from '@/store/modules/bgColor';
|
import { useBgColor } from '@/store/modules/bgColor';
|
||||||
import { initWebSocket } from '@/utils/websocket';
|
import { initWebSocket, closeWebSocket } from '@/utils/websocket'; // 新增 closeWebSocket
|
||||||
import { initSSE } from '@/utils/sse';
|
import { initSSE, closeSSE } from '@/utils/sse'; // 引入 closeSSE
|
||||||
|
|
||||||
const bgColorStore = useBgColor();
|
const bgColorStore = useBgColor();
|
||||||
|
|
||||||
// ==========================================
|
// ======================缩放逻辑======================
|
||||||
// ✅ 第2步:缩放逻辑(从旧 script 移过来)
|
|
||||||
// ==========================================
|
|
||||||
const scale = ref(1);
|
const scale = ref(1);
|
||||||
const DESIGN_WIDTH = 1920;
|
const DESIGN_WIDTH = 1920;
|
||||||
|
|
||||||
@@ -44,17 +37,14 @@ const calcScale = () => {
|
|||||||
scale.value = ratio;
|
scale.value = ratio;
|
||||||
};
|
};
|
||||||
|
|
||||||
let timer: any = null;
|
let timer: number | null = null;
|
||||||
const resize = () => {
|
const resize = () => {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
timer = setTimeout(calcScale, 100);
|
timer = window.setTimeout(calcScale, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ==========================================
|
// ======================生命周期======================
|
||||||
// ✅ 第3步:生命周期钩子(统一写在这里)
|
|
||||||
// ==========================================
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 缩放初始化
|
|
||||||
calcScale();
|
calcScale();
|
||||||
window.addEventListener('resize', resize);
|
window.addEventListener('resize', resize);
|
||||||
|
|
||||||
@@ -68,24 +58,18 @@ onMounted(() => {
|
|||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener('resize', resize);
|
window.removeEventListener('resize', resize);
|
||||||
clearTimeout(timer);
|
if (timer) clearTimeout(timer);
|
||||||
|
|
||||||
|
closeWebSocket();
|
||||||
|
closeSSE();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ==========================================
|
// ======================原有业务逻辑======================
|
||||||
// ✅ 第4步:原有业务逻辑
|
|
||||||
// ==========================================
|
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
const theme = computed(() => settingsStore.theme);
|
const theme = computed(() => settingsStore.theme);
|
||||||
const sidebar = computed(() => useAppStore().sidebar);
|
const sidebar = computed(() => useAppStore().sidebar);
|
||||||
const device = computed(() => useAppStore().device);
|
const device = computed(() => useAppStore().device);
|
||||||
const needTagsView = computed(() => settingsStore.tagsView);
|
const needTagsView = computed(() => settingsStore.tagsView);
|
||||||
// const fixedHeader = computed(() => settingsStore.fixedHeader);
|
|
||||||
// const layout = computed(() => settingsStore.navType);
|
|
||||||
|
|
||||||
// const showSidebar = computed(() => {
|
|
||||||
// if (sidebar.value.hide) return false;
|
|
||||||
// return layout.value === NavTypeEnum.LEFT || layout.value === NavTypeEnum.MIX;
|
|
||||||
// });
|
|
||||||
|
|
||||||
const classObj = computed(() => ({
|
const classObj = computed(() => ({
|
||||||
hideSidebar: !sidebar.value.opened,
|
hideSidebar: !sidebar.value.opened,
|
||||||
@@ -112,10 +96,6 @@ watchEffect(() => {
|
|||||||
const navbarRef = ref<InstanceType<typeof Navbar>>();
|
const navbarRef = ref<InstanceType<typeof Navbar>>();
|
||||||
const settingRef = ref<InstanceType<typeof Settings>>();
|
const settingRef = ref<InstanceType<typeof Settings>>();
|
||||||
|
|
||||||
// const handleClickOutside = () => {
|
|
||||||
// useAppStore().closeSideBar({ withoutAnimation: false });
|
|
||||||
// };
|
|
||||||
|
|
||||||
const setLayout = () => {
|
const setLayout = () => {
|
||||||
settingRef.value?.openSetting();
|
settingRef.value?.openSetting();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,13 +17,12 @@ const whiteList = ['/login', '/register', '/social-callback', '/register*', '/re
|
|||||||
|
|
||||||
// 全局标记:动态路由是否已经添加过(只加载一次!)
|
// 全局标记:动态路由是否已经添加过(只加载一次!)
|
||||||
let isDynamicRoutesAdded = false;
|
let isDynamicRoutesAdded = false;
|
||||||
|
// ✅ 新增:导航锁,防止多个路由导航并发执行
|
||||||
|
let isNavigating = false;
|
||||||
|
|
||||||
// 判断是否在白名单
|
|
||||||
const isWhiteList = (path: string) => {
|
|
||||||
return whiteList.some((pattern) => isPathMatch(pattern, path));
|
|
||||||
};
|
|
||||||
// ✅ 关键修改:记录当前已添加的动态路由名称列表
|
// ✅ 关键修改:记录当前已添加的动态路由名称列表
|
||||||
let currentDynamicRouteNames: string[] = [];
|
let currentDynamicRouteNames: string[] = [];
|
||||||
|
|
||||||
// ✅ 关键修改:清除所有已记录的动态路由
|
// ✅ 关键修改:清除所有已记录的动态路由
|
||||||
const removeDynamicRoutes = () => {
|
const removeDynamicRoutes = () => {
|
||||||
currentDynamicRouteNames.forEach((name) => {
|
currentDynamicRouteNames.forEach((name) => {
|
||||||
@@ -31,85 +30,111 @@ const removeDynamicRoutes = () => {
|
|||||||
router.removeRoute(name);
|
router.removeRoute(name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 清空记录数组
|
|
||||||
currentDynamicRouteNames = [];
|
currentDynamicRouteNames = [];
|
||||||
};
|
};
|
||||||
router.beforeEach(async (to, from) => {
|
|
||||||
NProgress.start();
|
|
||||||
|
|
||||||
|
// 判断是否在白名单
|
||||||
|
const isWhiteList = (path: string) => {
|
||||||
|
return whiteList.some((pattern) => isPathMatch(pattern, path));
|
||||||
|
};
|
||||||
|
|
||||||
|
router.beforeEach(async (to, from) => {
|
||||||
|
// ========== 导航锁核心 ==========
|
||||||
|
// 如果正在导航,直接终止本次跳转,防止并发多个守卫
|
||||||
|
if (isNavigating) {
|
||||||
|
NProgress.done();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
isNavigating = true;
|
||||||
|
|
||||||
|
NProgress.start();
|
||||||
const hasToken = getToken();
|
const hasToken = getToken();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const permissionStore = usePermissionStore();
|
const permissionStore = usePermissionStore();
|
||||||
|
|
||||||
if (hasToken) {
|
try {
|
||||||
// 设置标题
|
if (hasToken) {
|
||||||
to.meta.title && useSettingsStore().setTitle(to.meta.title as string);
|
// 设置标题
|
||||||
|
to.meta.title && useSettingsStore().setTitle(to.meta.title as string);
|
||||||
|
|
||||||
// 已登录 且 去登录页 → 跳首页
|
// 已登录 且 去登录页 → 跳首页
|
||||||
if (to.path === '/login') {
|
if (to.path === '/login') {
|
||||||
NProgress.done();
|
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 白名单页面直接放行
|
|
||||||
if (isWhiteList(to.path)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (userStore.roles.length === 0) {
|
|
||||||
isRelogin.show = true;
|
|
||||||
removeDynamicRoutes();
|
|
||||||
|
|
||||||
// 获取用户信息
|
|
||||||
const [err] = await tos(userStore.getInfo());
|
|
||||||
if (err) {
|
|
||||||
await userStore.logout();
|
|
||||||
ElMessage.error(err);
|
|
||||||
isDynamicRoutesAdded = false;
|
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
isRelogin.show = false;
|
// 白名单页面直接放行
|
||||||
permissionStore.resetRoutes();
|
if (isWhiteList(to.path)) {
|
||||||
// 生成动态路由
|
return;
|
||||||
const accessRoutes = await permissionStore.generateRoutes();
|
|
||||||
// 添加路由(避免重复添加)
|
|
||||||
accessRoutes.forEach((route) => {
|
|
||||||
if (route.name && router.hasRoute(route.name)) {
|
|
||||||
router.removeRoute(route.name);
|
|
||||||
}
|
|
||||||
if (!isHttp(route.path) && !router.hasRoute(route.name)) {
|
|
||||||
router.addRoute(route);
|
|
||||||
// 记录顶层路由名称
|
|
||||||
if (route.name) {
|
|
||||||
currentDynamicRouteNames.push(route.name as string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// ✅ 标记:路由已添加
|
|
||||||
isDynamicRoutesAdded = true;
|
|
||||||
|
|
||||||
// 管理员登录强制跳转
|
|
||||||
if (from.path === '/login') {
|
|
||||||
return { path: '/community/communitylist', replace: true };
|
|
||||||
} else {
|
|
||||||
// 重新进入当前路由(让新添加的路由生效)
|
|
||||||
return { ...to, replace: true };
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// 未登录
|
|
||||||
isDynamicRoutesAdded = false;
|
|
||||||
|
|
||||||
if (isWhiteList(to.path)) {
|
// roles为空,需要拉取用户信息+构建动态路由(只执行一次)
|
||||||
|
if (userStore.roles.length === 0) {
|
||||||
|
isRelogin.show = true;
|
||||||
|
removeDynamicRoutes();
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
const [err] = await tos(userStore.getInfo());
|
||||||
|
if (err) {
|
||||||
|
await userStore.logout();
|
||||||
|
ElMessage.error(err);
|
||||||
|
isDynamicRoutesAdded = false;
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
isRelogin.show = false;
|
||||||
|
permissionStore.resetRoutes();
|
||||||
|
|
||||||
|
// 生成动态路由
|
||||||
|
const accessRoutes = await permissionStore.generateRoutes();
|
||||||
|
// 添加路由(避免重复添加)
|
||||||
|
accessRoutes.forEach((route) => {
|
||||||
|
if (route.name && router.hasRoute(route.name)) {
|
||||||
|
router.removeRoute(route.name);
|
||||||
|
}
|
||||||
|
if (!isHttp(route.path) && !router.hasRoute(route.name)) {
|
||||||
|
router.addRoute(route);
|
||||||
|
// 记录顶层路由名称
|
||||||
|
if (route.name) {
|
||||||
|
currentDynamicRouteNames.push(route.name as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
isDynamicRoutesAdded = true;
|
||||||
|
|
||||||
|
// 登录页跳转进来,直接跳首页;其他情况重新触发导航加载动态路由
|
||||||
|
if (from.path === '/login') {
|
||||||
|
return '/community/communitylist';
|
||||||
|
} else {
|
||||||
|
// 这里replace仅在首次加载路由时执行;后续菜单切换不会走到这里
|
||||||
|
return { ...to, replace: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 已经有角色、动态路由已经构建完成:直接放行菜单切换,不会再走上面的动态路由构建逻辑
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
NProgress.done();
|
// 未登录
|
||||||
return `/login`;
|
isDynamicRoutesAdded = false;
|
||||||
|
if (isWhiteList(to.path)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return `/login`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('路由守卫异常:', err);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
// ✅ 无论成功失败,必须释放导航锁
|
||||||
|
isNavigating = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.afterEach(() => {
|
router.afterEach(() => {
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ✅ 导航发生错误的时候,也要释放锁(路由跳转报错时afterEach不一定执行)
|
||||||
|
router.onError(() => {
|
||||||
|
isNavigating = false;
|
||||||
|
NProgress.done();
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ export const useBgColor = defineStore('backgroundColor', () => {
|
|||||||
const isShow = ref(false);
|
const isShow = ref(false);
|
||||||
const toggleBgColor = (bol: boolean = false) => {
|
const toggleBgColor = (bol: boolean = false) => {
|
||||||
isShow.value = bol;
|
isShow.value = bol;
|
||||||
console.log(isShow.value);
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
toggleBgColor,
|
toggleBgColor,
|
||||||
|
|||||||
@@ -146,9 +146,6 @@ export const useHouseStore = defineStore(
|
|||||||
// 获取当前 楼栋的所有信息
|
// 获取当前 楼栋的所有信息
|
||||||
const res3 = await getHouselistAPI(currentBuildingInfo.value.id, houseName, houseUseTypeId);
|
const res3 = await getHouselistAPI(currentBuildingInfo.value.id, houseName, houseUseTypeId);
|
||||||
currentHouseInfoList.value = res3.data;
|
currentHouseInfoList.value = res3.data;
|
||||||
|
|
||||||
console.log(res3.data);
|
|
||||||
|
|
||||||
floorslist.value = null;
|
floorslist.value = null;
|
||||||
floorslist.value = new Set();
|
floorslist.value = new Set();
|
||||||
// 得到所有的有房屋的 楼层 数组
|
// 得到所有的有房屋的 楼层 数组
|
||||||
@@ -208,7 +205,6 @@ export const useHouseStore = defineStore(
|
|||||||
floorslist.value.add(floor.floorNo);
|
floorslist.value.add(floor.floorNo);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
console.log(units);
|
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -256,7 +252,6 @@ export const useHouseStore = defineStore(
|
|||||||
treedata.value = [];
|
treedata.value = [];
|
||||||
const res = await getVillageTree(villageid);
|
const res = await getVillageTree(villageid);
|
||||||
treedata.value = convertBuildingToTree(res.data.buildings || []);
|
treedata.value = convertBuildingToTree(res.data.buildings || []);
|
||||||
|
|
||||||
buildHousePathCache(treedata.value);
|
buildHousePathCache(treedata.value);
|
||||||
return treedata.value;
|
return treedata.value;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const reg = {
|
|||||||
number: /^[0-9]+$/,
|
number: /^[0-9]+$/,
|
||||||
// 完整版:所有emoji+肤色修饰+组合连接符+全部颜文字符号
|
// 完整版:所有emoji+肤色修饰+组合连接符+全部颜文字符号
|
||||||
fullFilterReg:
|
fullFilterReg:
|
||||||
/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{1F900}-\u{1F9FF}\u{1F3FB}-\u{1F3FF}\u{200D}。「」、・~ー『』「」・ヽヾゝゞ〆゛゜○●△▲□■◇◆◎▽▼┐┌└┘╮╭╰╯┬┴┼│─╱╲╳︵︶︹︺︿﹀︽︾﹁﹂﹃﹄ァ-ヺヽヾ]/gu
|
/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{1F900}-\u{1F9FF}\u{1F3FB}-\u{1F3FF}\u{200D}。「」、・~ー『』「」・ヽヾゝゞ〆゛゜○●△▲□■◇◆◎▽▼┐┌└┘╮╭╰╯┬┴┼│─╱╲╳︵︶︹︺︿﹀︽︾﹁﹂﹃﹄ァ-ヺヽヾ]/u
|
||||||
};
|
};
|
||||||
// 自动推导 TS 类型(最标准)
|
// 自动推导 TS 类型(最标准)
|
||||||
export type RegType = keyof typeof reg;
|
export type RegType = keyof typeof reg;
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ export function buildHousePathCache(treeData: Tree[]) {
|
|||||||
*/
|
*/
|
||||||
export function getHousePathById(houseId: string | number, fieldKey: ValidTreeKey = 'value'): (string | number)[] {
|
export function getHousePathById(houseId: string | number, fieldKey: ValidTreeKey = 'value'): (string | number)[] {
|
||||||
const id = String(houseId);
|
const id = String(houseId);
|
||||||
console.log(pathCache);
|
|
||||||
const cacheMap = pathCache.get(fieldKey);
|
const cacheMap = pathCache.get(fieldKey);
|
||||||
if (!cacheMap) return [];
|
if (!cacheMap) return [];
|
||||||
return cacheMap.get(id) ?? [];
|
return cacheMap.get(id) ?? [];
|
||||||
|
|||||||
66
src/utils/html.ts
Normal file
66
src/utils/html.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* 剥离 HTML 标签,提取纯文本
|
||||||
|
* - 自动将 <img>/<video>/<audio> 替换为 [图片]/[视频]/[音频] 占位
|
||||||
|
* - 自动解码 & 等 HTML entity
|
||||||
|
* - 自动合并多余空白
|
||||||
|
* - 可按需截断
|
||||||
|
*/
|
||||||
|
export function stripHtml(html: string | null | undefined, maxLen?: number): string {
|
||||||
|
if (!html) return '';
|
||||||
|
|
||||||
|
let text: string = html;
|
||||||
|
|
||||||
|
// 1. 媒体标签替换为占位符(保留语义提示)
|
||||||
|
text = text
|
||||||
|
.replace(/<img[^>]*>/gi, '[图片]')
|
||||||
|
.replace(/<video[^>]*>.*?<\/video>/gi, '[视频]')
|
||||||
|
.replace(/<audio[^>]*>.*?<\/audio>/gi, '[音频]')
|
||||||
|
.replace(/<iframe[^>]*>.*?<\/iframe>/gi, '[嵌入内容]');
|
||||||
|
|
||||||
|
// 2. 剥离所有剩余 HTML 标签(<p> <br> <div> ...)
|
||||||
|
text = text.replace(/<[^>]+>/g, '');
|
||||||
|
|
||||||
|
// 3. HTML entity 解码
|
||||||
|
text = decodeHtmlEntity(text);
|
||||||
|
|
||||||
|
// 4. 合并多余空白(多个空格/换行 → 单个空格)
|
||||||
|
text = text.replace(/\s+/g, ' ').trim();
|
||||||
|
|
||||||
|
// 5. 截断
|
||||||
|
if (maxLen && text.length > maxLen) {
|
||||||
|
text = text.slice(0, maxLen) + '...';
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解码 HTML 实体
|
||||||
|
* 浏览器环境用 DOMParser,非浏览器环境用正则 fallback
|
||||||
|
*/
|
||||||
|
function decodeHtmlEntity(str: string): string {
|
||||||
|
if (typeof DOMParser === 'undefined') {
|
||||||
|
const entityMap: Record<string, string> = {
|
||||||
|
' ': ' ',
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
''': "'",
|
||||||
|
''': "'",
|
||||||
|
'/': '/',
|
||||||
|
'©': '©',
|
||||||
|
'®': '®'
|
||||||
|
};
|
||||||
|
return str.replace(/&[a-z]+;|&#\d+;|&#x[0-9a-f]+;/gi, (match) => {
|
||||||
|
if (entityMap[match]) return entityMap[match];
|
||||||
|
const num = match.match(/&#(\d+);/)?.[1];
|
||||||
|
if (num) return String.fromCharCode(Number(num));
|
||||||
|
const hex = match.match(/&#x([0-9a-f]+);/i)?.[1];
|
||||||
|
if (hex) return String.fromCharCode(parseInt(hex, 16));
|
||||||
|
return match;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const doc = new DOMParser().parseFromString(str, 'text/html');
|
||||||
|
return doc.documentElement.textContent ?? '';
|
||||||
|
}
|
||||||
@@ -59,14 +59,14 @@ export function printVueDiv(elementId: string, title: string = '打印') {
|
|||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
table-layout: fixed; /* 固定表格布局,防止列变形 */
|
/*table-layout: fixed; !* 固定表格布局,防止列变形 *!*/
|
||||||
}
|
}
|
||||||
table td, table th {
|
table td, table th {
|
||||||
border: 1px solid #333;
|
border: 1px solid #333;
|
||||||
font-size: 9px; /* 表格字体最小化 */
|
font-size: 9px; /* 表格字体最小化 */
|
||||||
text-align: center;
|
text-align: center;
|
||||||
white-space: nowrap; /* ✅ 禁止文字自动换行(核心) */
|
/*white-space: nowrap; !* ✅ 禁止文字自动换行(核心) *!*/
|
||||||
overflow: hidden;
|
/*overflow: hidden;*/
|
||||||
}
|
}
|
||||||
/* 适配合并列 */
|
/* 适配合并列 */
|
||||||
td[colspan], th[colspan] {
|
td[colspan], th[colspan] {
|
||||||
@@ -85,7 +85,7 @@ export function printVueDiv(elementId: string, title: string = '打印') {
|
|||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
color: rgba(48, 49, 51, 1);
|
color: rgba(48, 49, 51, 1);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin-bottom: 50px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
@@ -99,29 +99,33 @@ export function printVueDiv(elementId: string, title: string = '打印') {
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
color: rgba(48, 49, 51, 1);
|
color: rgba(48, 49, 51, 1);
|
||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
border: 1px solid #dddddd;
|
border: 1px solid #dddddd;
|
||||||
}
|
}
|
||||||
td {
|
td {
|
||||||
border: 1px solid #dddddd;
|
border: 1px solid #dddddd;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
line-height: 45px;
|
line-height: normal;
|
||||||
background-color: rgba(255, 255, 255, 1);
|
background-color: rgba(255, 255, 255, 1);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 450;
|
font-size: 16px;
|
||||||
}
|
font-weight: 450;
|
||||||
|
}
|
||||||
|
|
||||||
.footertr td {
|
.footertr td {
|
||||||
height: 90px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.foorter {
|
.foorter {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
width: 85%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
|
||||||
gap: 30px;
|
gap: 30px;
|
||||||
margin-top: 30px;
|
margin: 20px auto 0;
|
||||||
|
}
|
||||||
|
.formark {
|
||||||
|
font-size: smaller;
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -51,7 +51,11 @@ const whiteVillageId = [
|
|||||||
|
|
||||||
'/paidInExpenses/*',
|
'/paidInExpenses/*',
|
||||||
// 租赁管理明细
|
// 租赁管理明细
|
||||||
'/leaseManagementDetail/*'
|
'/leaseManagementDetail/*',
|
||||||
|
'/warehouse/*',
|
||||||
|
|
||||||
|
// 电表启停
|
||||||
|
'/electricityDevice/controlSwitch'
|
||||||
// '/building/list'
|
// '/building/list'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
108
src/utils/sse.ts
108
src/utils/sse.ts
@@ -1,15 +1,40 @@
|
|||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { ElNotification } from 'element-plus';
|
import { ElNotification } from 'element-plus';
|
||||||
import { useNoticeStore } from '@/store/modules/notice';
|
import { useNoticeStore } from '@/store/modules/notice';
|
||||||
|
import { useEventSource } from '@vueuse/core';
|
||||||
|
import { watch } from 'vue';
|
||||||
|
|
||||||
// 初始化
|
// 全局单例保存SSE实例,防止多次创建
|
||||||
export const initSSE = (url: any) => {
|
let eventSourceInstance: ReturnType<typeof useEventSource> | null = null;
|
||||||
|
let stopWatchError: (() => void) | null = null;
|
||||||
|
let stopWatchData: (() => void) | null = null;
|
||||||
|
|
||||||
|
// 关闭SSE、清理监听
|
||||||
|
export const closeSSE = () => {
|
||||||
|
if (eventSourceInstance) {
|
||||||
|
eventSourceInstance.close();
|
||||||
|
eventSourceInstance = null;
|
||||||
|
}
|
||||||
|
// 销毁watch
|
||||||
|
stopWatchError?.();
|
||||||
|
stopWatchData?.();
|
||||||
|
stopWatchError = null;
|
||||||
|
stopWatchData = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化SSE
|
||||||
|
export const initSSE = (url: string) => {
|
||||||
if (import.meta.env.VITE_APP_SSE === 'false') {
|
if (import.meta.env.VITE_APP_SSE === 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 关键:新建之前先关闭旧连接!
|
||||||
|
closeSSE();
|
||||||
|
|
||||||
url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID;
|
const token = getToken();
|
||||||
const { data, error } = useEventSource(url, [], {
|
const clientId = import.meta.env.VITE_APP_CLIENT_ID;
|
||||||
|
const sseUrl = url + '?Authorization=Bearer ' + token + '&clientid=' + clientId;
|
||||||
|
|
||||||
|
eventSourceInstance = useEventSource(sseUrl, [], {
|
||||||
autoReconnect: {
|
autoReconnect: {
|
||||||
retries: 5,
|
retries: 5,
|
||||||
delay: 5000,
|
delay: 5000,
|
||||||
@@ -19,24 +44,69 @@ export const initSSE = (url: any) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(error, () => {
|
const { data, error } = eventSourceInstance;
|
||||||
|
|
||||||
|
stopWatchError = watch(error, () => {
|
||||||
console.log('SSE connection error:', error.value);
|
console.log('SSE connection error:', error.value);
|
||||||
error.value = null;
|
// error.value = null; // 不要手动覆盖,会干扰useEventSource内部状态
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(data, () => {
|
stopWatchData = watch(data, () => {
|
||||||
if (!data.value) return;
|
if (!data.value) return;
|
||||||
useNoticeStore().addNotice({
|
const notice = tryParseJson(data.value as string);
|
||||||
message: data.value,
|
if (typeof notice === 'string') {
|
||||||
read: false,
|
useNoticeStore().addNotice({
|
||||||
time: new Date().toLocaleString()
|
message: notice,
|
||||||
});
|
read: false,
|
||||||
ElNotification({
|
time: new Date().toLocaleString()
|
||||||
title: '消息',
|
});
|
||||||
message: data.value,
|
ElNotification({
|
||||||
type: 'success',
|
title: '消息',
|
||||||
duration: 3000
|
message: notice,
|
||||||
});
|
type: 'success',
|
||||||
data.value = null;
|
duration: 3000
|
||||||
|
});
|
||||||
|
data.value = null;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const title = typeof notice.title === 'string' ? notice.title : '消息';
|
||||||
|
const message = typeof notice.message === 'string' ? notice.message : '';
|
||||||
|
const type = typeof notice.type === 'string' ? notice.type : 'info';
|
||||||
|
useNoticeStore().addNotice({
|
||||||
|
message,
|
||||||
|
read: false,
|
||||||
|
time: new Date().toLocaleString()
|
||||||
|
});
|
||||||
|
ElNotification({
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
type: type as 'success' | 'warning' | 'info' | 'error',
|
||||||
|
duration: 3000
|
||||||
|
});
|
||||||
|
data.value = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试解析后端返回的字符串
|
||||||
|
* 如果是合法JSON对象 → 返回 Record<string, unknown>
|
||||||
|
* 否则(数组/null/基础值/非JSON字符串) → 返回原字符串
|
||||||
|
* @param str 后端传过来的字符串
|
||||||
|
*/
|
||||||
|
function tryParseJson(str: string): string | Record<string, unknown> {
|
||||||
|
if (typeof str !== 'string' || str === '') return str;
|
||||||
|
|
||||||
|
const trimStr = str.trim();
|
||||||
|
if (trimStr === '') return str;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(trimStr);
|
||||||
|
// 只有纯对象才返回对象,数组/null/基础值等统一当作字符串处理
|
||||||
|
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||||
|
return parsed as Record<string, unknown>;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
} catch {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,18 +1,37 @@
|
|||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { ElNotification } from 'element-plus';
|
import { ElNotification } from 'element-plus';
|
||||||
import { useNoticeStore } from '@/store/modules/notice';
|
import { useNoticeStore } from '@/store/modules/notice';
|
||||||
|
import { useWebSocket } from '@vueuse/core';
|
||||||
|
|
||||||
|
// 全局保存 ws 实例,单例,防止重复创建
|
||||||
|
let wsInstance: ReturnType<typeof useWebSocket> | null = null;
|
||||||
|
|
||||||
|
// 对外:关闭 websocket
|
||||||
|
export const closeWebSocket = () => {
|
||||||
|
if (wsInstance) {
|
||||||
|
wsInstance.close();
|
||||||
|
wsInstance = null;
|
||||||
|
console.log('websocket 已手动关闭');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 初始化socket
|
// 初始化socket
|
||||||
export const initWebSocket = (url: any) => {
|
export const initWebSocket = (url: string) => {
|
||||||
if (import.meta.env.VITE_APP_WEBSOCKET === 'false') {
|
if (import.meta.env.VITE_APP_WEBSOCKET === 'false') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID;
|
// 已经存在实例,先关闭旧的,避免多连接
|
||||||
useWebSocket(url, {
|
if (wsInstance) {
|
||||||
|
closeWebSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = getToken();
|
||||||
|
const clientId = import.meta.env.VITE_APP_CLIENT_ID;
|
||||||
|
const wsUrl = url + '?Authorization=Bearer ' + token + '&clientid=' + clientId;
|
||||||
|
|
||||||
|
wsInstance = useWebSocket(wsUrl, {
|
||||||
autoReconnect: {
|
autoReconnect: {
|
||||||
// 重连最大次数
|
|
||||||
retries: 3,
|
retries: 3,
|
||||||
// 重连间隔
|
|
||||||
delay: 1000,
|
delay: 1000,
|
||||||
onFailed() {
|
onFailed() {
|
||||||
console.log('websocket重连失败');
|
console.log('websocket重连失败');
|
||||||
@@ -20,9 +39,7 @@ export const initWebSocket = (url: any) => {
|
|||||||
},
|
},
|
||||||
heartbeat: {
|
heartbeat: {
|
||||||
message: JSON.stringify({ type: 'ping' }),
|
message: JSON.stringify({ type: 'ping' }),
|
||||||
// 发送心跳的间隔
|
|
||||||
interval: 10000,
|
interval: 10000,
|
||||||
// 接收到心跳response的超时时间
|
|
||||||
pongTimeout: 2000
|
pongTimeout: 2000
|
||||||
},
|
},
|
||||||
onConnected() {
|
onConnected() {
|
||||||
@@ -32,20 +49,53 @@ export const initWebSocket = (url: any) => {
|
|||||||
console.log('websocket已经断开');
|
console.log('websocket已经断开');
|
||||||
},
|
},
|
||||||
onMessage: (_, e) => {
|
onMessage: (_, e) => {
|
||||||
if (e.data.indexOf('ping') > 0) {
|
// 心跳pong消息直接跳过
|
||||||
|
if (e.data.indexOf('ping') > 0 || e.data.indexOf('pong') > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const msg = tryParseJson(e.data);
|
||||||
|
let messageText = '';
|
||||||
|
let title = '消息';
|
||||||
|
let type: 'success' | 'warning' | 'info' | 'error' = 'success';
|
||||||
|
|
||||||
|
if (typeof msg === 'string') {
|
||||||
|
messageText = msg;
|
||||||
|
} else {
|
||||||
|
title = typeof msg.title === 'string' ? msg.title : '消息';
|
||||||
|
messageText = typeof msg.message === 'string' ? msg.message : '';
|
||||||
|
type = (typeof msg.type === 'string' ? msg.type : 'info') as typeof type;
|
||||||
|
}
|
||||||
|
|
||||||
useNoticeStore().addNotice({
|
useNoticeStore().addNotice({
|
||||||
message: e.data,
|
message: messageText,
|
||||||
read: false,
|
read: false,
|
||||||
time: new Date().toLocaleString()
|
time: new Date().toLocaleString()
|
||||||
});
|
});
|
||||||
ElNotification({
|
ElNotification({
|
||||||
title: '消息',
|
title,
|
||||||
message: e.data,
|
message: messageText,
|
||||||
type: 'success',
|
type,
|
||||||
duration: 3000
|
duration: 3000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 和sse共用的解析函数:
|
||||||
|
* JSON对象返回Record,其他返回原始字符串
|
||||||
|
*/
|
||||||
|
function tryParseJson(str: string): string | Record<string, unknown> {
|
||||||
|
if (typeof str !== 'string' || str === '') return str;
|
||||||
|
const trimStr = str.trim();
|
||||||
|
if (trimStr === '') return str;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(trimStr);
|
||||||
|
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||||
|
return parsed as Record<string, unknown>;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
} catch {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,10 +18,22 @@ export type ColumnConfig = {
|
|||||||
*/
|
*/
|
||||||
export type SpanMethodCallback = (params: { row: any; rowIndex: number; columnIndex: number }) => { rowspan: number; colspan: number };
|
export type SpanMethodCallback = (params: { row: any; rowIndex: number; columnIndex: number }) => { rowspan: number; colspan: number };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行样式回调函数类型
|
||||||
|
* 返回的样式会 merge 到该行所有单元格上
|
||||||
|
*/
|
||||||
|
export type RowStyleCallback = (params: { row: any; rowIndex: number }) => Partial<XLSX.CellStyle> | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前端导出Excel(支持多级表头)
|
* 前端导出Excel(支持多级表头)
|
||||||
*/
|
*/
|
||||||
export function exportToExcel(data: any[], columns: ColumnConfig[], filename: string, spanMethod?: SpanMethodCallback) {
|
export function exportToExcel(
|
||||||
|
data: any[],
|
||||||
|
columns: ColumnConfig[],
|
||||||
|
filename: string,
|
||||||
|
spanMethod?: SpanMethodCallback,
|
||||||
|
rowStyleCallback?: RowStyleCallback
|
||||||
|
) {
|
||||||
if (!data || data.length === 0) {
|
if (!data || data.length === 0) {
|
||||||
ElMessage.warning('没有可导出的数据');
|
ElMessage.warning('没有可导出的数据');
|
||||||
return;
|
return;
|
||||||
@@ -80,27 +92,35 @@ export function exportToExcel(data: any[], columns: ColumnConfig[], filename: st
|
|||||||
worksheet[cellAddress] = { t: 's', v: '' };
|
worksheet[cellAddress] = { t: 's', v: '' };
|
||||||
}
|
}
|
||||||
const isHeader = R < headerRows;
|
const isHeader = R < headerRows;
|
||||||
|
const dataRowIndex = R - headerRows;
|
||||||
|
// 用户自定义的行样式(仅对数据行生效)
|
||||||
|
const customRowStyle =
|
||||||
|
!isHeader && rowStyleCallback && dataRowIndex >= 0 ? rowStyleCallback({ row: data[dataRowIndex], rowIndex: dataRowIndex }) : undefined;
|
||||||
worksheet[cellAddress].s = {
|
worksheet[cellAddress].s = {
|
||||||
fill: isHeader
|
fill:
|
||||||
? {
|
customRowStyle?.fill ??
|
||||||
fgColor: { rgb: 'bec4cb' },
|
(isHeader
|
||||||
patternType: 'solid'
|
? {
|
||||||
}
|
fgColor: { rgb: 'bec4cb' },
|
||||||
: undefined,
|
patternType: 'solid'
|
||||||
font: isHeader
|
}
|
||||||
? {
|
: undefined),
|
||||||
color: { rgb: 'FFFFFF' },
|
font:
|
||||||
bold: true,
|
customRowStyle?.font ??
|
||||||
sz: 11
|
(isHeader
|
||||||
}
|
? {
|
||||||
: undefined,
|
color: { rgb: 'FFFFFF' },
|
||||||
border: {
|
bold: true,
|
||||||
|
sz: 11
|
||||||
|
}
|
||||||
|
: undefined),
|
||||||
|
border: customRowStyle?.border ?? {
|
||||||
top: { style: 'thin', color: { rgb: '000000' } },
|
top: { style: 'thin', color: { rgb: '000000' } },
|
||||||
bottom: { style: 'thin', color: { rgb: '000000' } },
|
bottom: { style: 'thin', color: { rgb: '000000' } },
|
||||||
left: { style: 'thin', color: { rgb: '000000' } },
|
left: { style: 'thin', color: { rgb: '000000' } },
|
||||||
right: { style: 'thin', color: { rgb: '000000' } }
|
right: { style: 'thin', color: { rgb: '000000' } }
|
||||||
},
|
},
|
||||||
alignment: {
|
alignment: customRowStyle?.alignment ?? {
|
||||||
horizontal: 'center',
|
horizontal: 'center',
|
||||||
vertical: 'center'
|
vertical: 'center'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,54 +2,54 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<span>智慧物业后台管理系统</span>
|
<span>智慧物业后台管理系统</span>
|
||||||
<navbar :Showhamburger="false" ref="navbarRef" />
|
<navbar ref="navbarRef" :Showhamburger="false" />
|
||||||
</div>
|
</div>
|
||||||
<div class="container AddBuildingBox">
|
<div class="container AddBuildingBox">
|
||||||
<el-form inline class="formBody" ref="formRef" :model="form" :rules="rules" label-width="100px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" inline label-width="100px">
|
||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form-item label="小区名称" prop="villageName">
|
<el-form-item label="小区名称" prop="villageName">
|
||||||
<el-input maxlength="25" v-model.trim="form.villageName" placeholder="请输入小区名称" />
|
<el-input v-model.trim="form.villageName" maxlength="25" placeholder="请输入小区名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="小区编号" prop="villageCode">
|
<el-form-item label="小区编号" prop="villageCode">
|
||||||
<el-input maxlength="20" v-model.trim="form.villageCode" placeholder="请输入小区编号" />
|
<el-input v-model.trim="form.villageCode" maxlength="20" placeholder="请输入小区编号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="所在城市" prop="city">
|
<el-form-item label="所在城市" prop="city">
|
||||||
<el-cascader :options="pcaTextArrList" v-model="city" @change="cityChange"> </el-cascader>
|
<el-cascader v-model="city" :options="pcaTextArrList" @change="cityChange"> </el-cascader>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="完整详细地址" prop="buildingArea">
|
<el-form-item label="完整详细地址" prop="buildingArea">
|
||||||
<el-input type="textarea" :row="3" maxlength="100" show-word-limit v-model.trim="form.address" placeholder="请输入完整详细地址" />
|
<el-input v-model.trim="form.address" :row="3" maxlength="100" placeholder="请输入完整详细地址" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="建成时间" prop="buildingArea">
|
<el-form-item label="建成时间" prop="buildingArea">
|
||||||
<el-date-picker v-model="builtTime" type="date" placeholder="选择建成时间" value-format="YYYY-MM-DD" @change="changeBuiltTime" />
|
<el-date-picker v-model="builtTime" placeholder="选择建成时间" type="date" value-format="YYYY-MM-DD" @change="changeBuiltTime" />
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="房屋用途" prop="buildingArea">
|
|
||||||
<el-select v-model="form.houseUse" placeholder="请选择房屋用途" style="width: 240px">
|
|
||||||
<el-option v-for="item in houseUserList" :key="item.value" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="房屋用途" prop="houseUse">-->
|
||||||
|
<!-- <el-select v-model="form.houseUse" placeholder="请选择房屋用途" style="width: 240px">-->
|
||||||
|
<!-- <el-option v-for="item in houseUserList" :key="item.id" :label="item.name" :value="item.id" />-->
|
||||||
|
<!-- </el-select>-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
<el-form-item label="小区面积" prop="villageArea">
|
<el-form-item label="小区面积" prop="villageArea">
|
||||||
<el-input maxlength="8" v-model.trim="form.villageArea" placeholder="请输入小区面积"><template #append>㎡</template> </el-input>
|
<el-input v-model.trim="form.villageArea" maxlength="8" placeholder="请输入小区面积"><template #append>㎡</template> </el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item style="width: 100%" label="小区图片">
|
<el-form-item label="小区图片" style="width: 100%">
|
||||||
<el-upload
|
<el-upload
|
||||||
accept=".jpg, .png"
|
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
:action="uploadFileUrl"
|
:action="uploadFileUrl"
|
||||||
:headers="headerToken()"
|
|
||||||
list-type="picture-card"
|
|
||||||
:file-list="villageImg"
|
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
|
:file-list="villageImg"
|
||||||
|
:headers="headerToken()"
|
||||||
:limit="9"
|
:limit="9"
|
||||||
:on-exceed="handleExceed"
|
:on-exceed="handleExceed"
|
||||||
|
accept=".jpg, .png"
|
||||||
|
list-type="picture-card"
|
||||||
@change="handleUploadChange"
|
@change="handleUploadChange"
|
||||||
@before-upload="handleBeforeUpload"
|
@before-upload="handleBeforeUpload"
|
||||||
>
|
>
|
||||||
<el-icon><Plus /></el-icon>
|
<el-icon><Plus /></el-icon>
|
||||||
<template #file="{ file }">
|
<template #file="{ file }">
|
||||||
<div>
|
<div>
|
||||||
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
|
<img :src="file.url" alt="" class="el-upload-list__item-thumbnail" />
|
||||||
<span class="el-upload-list__item-actions">
|
<span class="el-upload-list__item-actions">
|
||||||
<span class="el-upload-list__item-delete" @click="handleRemove(file)">
|
<span class="el-upload-list__item-delete" @click="handleRemove(file)">
|
||||||
<el-icon><Delete /></el-icon>
|
<el-icon><Delete /></el-icon>
|
||||||
@@ -62,8 +62,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item style="width: 100%" label="小区简介">
|
<el-form-item label="小区简介" style="width: 100%">
|
||||||
<el-input maxlength="200" show-word-limit v-model.trim="form.remark" :rows="5" type="textarea" placeholder="小区简介" />
|
<el-input v-model.trim="form.remark" :rows="5" maxlength="200" placeholder="小区简介" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -71,19 +71,19 @@
|
|||||||
<div class="title">负责人信息</div>
|
<div class="title">负责人信息</div>
|
||||||
<div class="addBuildingFormBody addBuildingForm_User_Body">
|
<div class="addBuildingFormBody addBuildingForm_User_Body">
|
||||||
<el-form-item label="姓名">
|
<el-form-item label="姓名">
|
||||||
<el-input maxlength="20" v-model.trim="form.manageName" placeholder="请输入姓名" />
|
<el-input v-model.trim="form.manageName" maxlength="20" placeholder="请输入姓名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="电话" prop="managePhone">
|
<el-form-item label="电话" prop="managePhone">
|
||||||
<el-input v-model.trim="form.managePhone" placeholder="请输入电话" />
|
<el-input v-model.trim="form.managePhone" placeholder="请输入电话" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="微信" prop="manageVx">
|
<el-form-item label="微信" prop="manageVx">
|
||||||
<el-input maxlength="20" v-model.trim="form.manageVx" placeholder="请输入微信"></el-input>
|
<el-input v-model.trim="form.manageVx" maxlength="20" placeholder="请输入微信"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="QQ" prop="manageQq">
|
<el-form-item label="QQ" prop="manageQq">
|
||||||
<el-input maxlength="20" v-model.trim="form.manageQq" placeholder="请输入QQ"> </el-input>
|
<el-input v-model.trim="form.manageQq" maxlength="20" placeholder="请输入QQ"> </el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="邮箱" prop="manageEmail">
|
<el-form-item label="邮箱" prop="manageEmail">
|
||||||
<el-input maxlength="30" v-model.trim="form.manageEmail" placeholder="请输入邮箱"> </el-input>
|
<el-input v-model.trim="form.manageEmail" maxlength="30" placeholder="请输入邮箱"> </el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="pl-100px">
|
<div class="pl-100px">
|
||||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import Navbar from '@/layout/components/Navbar.vue';
|
import Navbar from '@/layout/components/Navbar.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { pcaTextArr } from 'element-china-area-data';
|
import { pcaTextArr } from 'element-china-area-data';
|
||||||
@@ -106,6 +106,7 @@ import { CascaderValue } from 'element-plus';
|
|||||||
import { addVillageAPI, editVillageAPI, getVillageByIdAPI, uploadVillageImageAPI } from '@/api/system/community';
|
import { addVillageAPI, editVillageAPI, getVillageByIdAPI, uploadVillageImageAPI } from '@/api/system/community';
|
||||||
import { communitylist_rows_type } from '@/api/system/community/type';
|
import { communitylist_rows_type } from '@/api/system/community/type';
|
||||||
import { Delete, Plus } from '@element-plus/icons-vue';
|
import { Delete, Plus } from '@element-plus/icons-vue';
|
||||||
|
import { listHouseUseType_add_house } from '@/api/system/houseUse';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -116,24 +117,7 @@ const uploadFileUrl = `${apiPrefix}/village/uploadImages`;
|
|||||||
// 获取省 市 区╬╬╬╬╬╬╬
|
// 获取省 市 区╬╬╬╬╬╬╬
|
||||||
const pcaTextArrList = ref<DataItem[]>(pcaTextArr);
|
const pcaTextArrList = ref<DataItem[]>(pcaTextArr);
|
||||||
// 获取小区用途
|
// 获取小区用途
|
||||||
const houseUserList = ref([
|
const houseUserList = ref([]);
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
label: '住宅'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 1,
|
|
||||||
label: '商住两用'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 2,
|
|
||||||
label: '商业'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 3,
|
|
||||||
label: '办公'
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const uploadRef = ref();
|
const uploadRef = ref();
|
||||||
|
|
||||||
@@ -355,7 +339,6 @@ async function handleUploadChange(file: UploadFile) {
|
|||||||
ElMessage.error(isUpload.type);
|
ElMessage.error(isUpload.type);
|
||||||
return;
|
return;
|
||||||
} else if (typeof isUpload === 'boolean' && isUpload === true) {
|
} else if (typeof isUpload === 'boolean' && isUpload === true) {
|
||||||
console.log(file);
|
|
||||||
villageImg.value.push(file.raw);
|
villageImg.value.push(file.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -421,7 +404,6 @@ const submitForm = () => {
|
|||||||
// 3) 有新文件:先上传新文件,再与已有URL合并
|
// 3) 有新文件:先上传新文件,再与已有URL合并
|
||||||
const formdata = new FormData();
|
const formdata = new FormData();
|
||||||
newFiles.forEach((file) => formdata.append('files', file));
|
newFiles.forEach((file) => formdata.append('files', file));
|
||||||
console.log('newFiles', newFiles);
|
|
||||||
uploadVillageImageAPI(formdata).then((res) => {
|
uploadVillageImageAPI(formdata).then((res) => {
|
||||||
const uploadedUrls = res.data.success.map((x) => x.url).filter(Boolean);
|
const uploadedUrls = res.data.success.map((x) => x.url).filter(Boolean);
|
||||||
// 4) 最终图片 = 已有图片 + 新上传图片(避免覆盖)
|
// 4) 最终图片 = 已有图片 + 新上传图片(避免覆盖)
|
||||||
@@ -474,11 +456,21 @@ function submitFormInfo() {
|
|||||||
const cancelForm = () => {
|
const cancelForm = () => {
|
||||||
router.back();
|
router.back();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取房屋用途
|
||||||
|
const getHouseUserList = () => {
|
||||||
|
listHouseUseType_add_house().then((res) => {
|
||||||
|
houseUserList.value = res.data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
getHouseUserList();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.box {
|
.box {
|
||||||
background: #deedff;
|
background: #deedff;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
:min-scale="0.2"
|
:min-scale="0.2"
|
||||||
:preview-src-list="item.villageImageUrl ? item.villageImageUrl.split(',') : [defaultVilageinfoImage]"
|
:preview-src-list="item.villageImageUrl ? item.villageImageUrl.split(',') : [defaultVilageinfoImage]"
|
||||||
show-progress
|
show-progress
|
||||||
:initial-index="4"
|
:initial-index="0"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
:src="item.villageImageUrl ? item.villageImageUrl.split(',')[0] : defaultVilageinfoImage"
|
:src="item.villageImageUrl ? item.villageImageUrl.split(',')[0] : defaultVilageinfoImage"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ResidentMainBox p-2 w-full">
|
<div class="ResidentMainBox p-2 w-full">
|
||||||
<PageHeader title="活动"></PageHeader>
|
<PageHeader></PageHeader>
|
||||||
<div class="ResidentMainBody">
|
<div class="ResidentMainBody">
|
||||||
<el-card>
|
<el-card>
|
||||||
<template #header>
|
<template #header>
|
||||||
@@ -12,21 +12,24 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="13">
|
<el-col :span="13">
|
||||||
<el-form-item label="活动标题" prop="title">
|
<el-form-item label="活动标题" prop="title">
|
||||||
<el-input maxlength="30" v-model.trim="form.title" placeholder="请输入活动标题" />
|
<el-input v-model.trim="form.title" maxlength="30" placeholder="请输入活动标题" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<!-- <el-col :span="11">-->
|
||||||
|
<!-- <el-form-item label="活动作者" prop="author">-->
|
||||||
|
<!-- <el-input maxlength="20" v-model.trim="form.author" placeholder="请输入活动作者" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="活动作者" prop="author">
|
|
||||||
<el-input maxlength="20" v-model.trim="form.author" placeholder="请输入活动作者" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="13">
|
|
||||||
<el-form-item label="活动时间" prop="startTime">
|
<el-form-item label="活动时间" prop="startTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="activityTime"
|
v-model="activityTime"
|
||||||
|
:disabled-date="disabledDate"
|
||||||
|
end-placeholder="结束活动"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始活动"
|
||||||
|
type="datetimerange"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
@change="
|
@change="
|
||||||
(data: string[] | null) => {
|
(data: string[] | null) => {
|
||||||
@@ -39,27 +42,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
type="datetimerange"
|
|
||||||
range-separator="至"
|
|
||||||
start-placeholder="开始活动"
|
|
||||||
end-placeholder="结束活动"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="11">
|
|
||||||
<el-form-item label="活动地点" prop="address">
|
|
||||||
<el-input maxlength="50" type="textarea" show-word-limit v-model.trim="form.address" placeholder="请输入活动地点" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="13">
|
||||||
<el-form-item label="报名截止日期" prop="applyDeadline">
|
<el-form-item label="报名截止日期" prop="applyDeadline">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
v-model="deadline"
|
v-model="deadline"
|
||||||
:disabled-date="disabledDate"
|
:disabled="!Boolean(form.startTime)"
|
||||||
|
:disabled-date="disabledDateDeadline"
|
||||||
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
placeholder="请选择报名截止日期"
|
||||||
|
style="width: 100%"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(data) => {
|
(data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -69,28 +67,57 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
type="datetime"
|
|
||||||
placeholder="请选择报名截止日期"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-form-item label="活动地点" prop="address">
|
||||||
|
<el-input v-model.trim="form.address" maxlength="50" placeholder="请输入活动地点" show-word-limit type="textarea" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="13">
|
||||||
|
<el-form-item label="签到时间" prop="signinStartTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="SignInTime"
|
||||||
|
:disabled="!Boolean(form.endTime)"
|
||||||
|
:disabled-date="disabledSignInDate"
|
||||||
|
end-placeholder="结束签到"
|
||||||
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始签到"
|
||||||
|
type="datetimerange"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@change="
|
||||||
|
(data: string[] | null) => {
|
||||||
|
if (data) {
|
||||||
|
form.signinStartTime = data[0];
|
||||||
|
form.signinEndTime = data[1];
|
||||||
|
} else {
|
||||||
|
form.signinStartTime = '';
|
||||||
|
form.signinEndTime = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="11">
|
||||||
<el-form-item label="主办方" prop="organizer">
|
<el-form-item label="主办方" prop="organizer">
|
||||||
<el-input maxlength="20" v-model.trim="form.organizer" placeholder="请输入主办方" />
|
<el-input v-model.trim="form.organizer" maxlength="20" placeholder="请输入主办方" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="13">
|
||||||
<el-form-item label="联系人" prop="contactName">
|
<el-form-item label="联系人" prop="contactName">
|
||||||
<el-input maxlength="20" v-model.trim="form.contactName" placeholder="请输入联系人" />
|
<el-input v-model.trim="form.contactName" maxlength="20" placeholder="请输入联系人" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="11">
|
||||||
<el-form-item label="联系方式" prop="contactPhone">
|
<el-form-item label="联系方式" prop="contactPhone">
|
||||||
<el-input maxlength="20" v-model.trim="form.contactPhone" placeholder="请输入联系方式" />
|
<el-input v-model.trim="form.contactPhone" maxlength="11" placeholder="请输入联系方式" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -98,7 +125,7 @@
|
|||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="活动名额" prop="quota">
|
<el-form-item label="活动名额" prop="quota">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<el-input-number v-model.trim.number="form.quota" :min="0" :max="99999" placeholder="0代表无限" />
|
<el-input-number v-model.trim.number="form.quota" :max="99999" :min="0" placeholder="0代表无限" />
|
||||||
<span class="ml-2 text-gray-500 text-sm" style="font-size: 12px">(填 <strong>0</strong> 代表 <u>不限制名额</u> )</span>
|
<span class="ml-2 text-gray-500 text-sm" style="font-size: 12px">(填 <strong>0</strong> 代表 <u>不限制名额</u> )</span>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -109,38 +136,34 @@
|
|||||||
<el-form-item label="活动封面" prop="title">
|
<el-form-item label="活动封面" prop="title">
|
||||||
<el-upload
|
<el-upload
|
||||||
ref="upload"
|
ref="upload"
|
||||||
class="avatar-uploader"
|
|
||||||
:action="uploadUrl"
|
:action="uploadUrl"
|
||||||
:show-file-list="false"
|
|
||||||
:on-success="handleAvatarSuccess"
|
|
||||||
:on-exceed="handleExceed"
|
|
||||||
:before-upload="handleBeforeUpload"
|
:before-upload="handleBeforeUpload"
|
||||||
:on-error="handleError"
|
|
||||||
accept=".png,.jpg,.jpeg,.bmp"
|
|
||||||
:limit="1"
|
:limit="1"
|
||||||
|
:on-error="handleError"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:on-success="handleAvatarSuccess"
|
||||||
|
:show-file-list="false"
|
||||||
|
accept=".png,.jpg,.jpeg,.bmp"
|
||||||
|
class="avatar-uploader"
|
||||||
>
|
>
|
||||||
<img alt="活动封面" v-if="form.coverImage" :src="form.coverImage" class="avatar" />
|
<img v-if="form.coverImage" :src="form.coverImage" alt="活动封面" class="avatar" />
|
||||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
</el-row>
|
||||||
<el-form-item label="招募要求">
|
<el-row>
|
||||||
<el-input
|
<el-col>
|
||||||
maxlength="200"
|
<el-form-item label="招募要求" prop="requirements">
|
||||||
show-word-limit
|
<!-- <editor v-model="form.requirements" :file-size="5" :height="200" :min-height="200" :read-only="false" :type="'url'" /> -->
|
||||||
:row="8"
|
<el-input v-model="form.requirements" :rows="5" maxlength="400" show-word-limit type="textarea"></el-input>
|
||||||
type="textarea"
|
|
||||||
v-model.trim="form.requirements"
|
|
||||||
placeholder="请输入招募要求"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-form-item label="活动详情" prop="content">
|
<el-form-item label="活动详情" prop="content">
|
||||||
<editor v-model="form.content" :height="500" :min-height="300" :read-only="false" :file-size="5" :type="'url'" />
|
<editor v-model="form.content" :file-size="5" :height="300" :min-height="300" :read-only="false" :type="'url'" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -169,7 +192,7 @@
|
|||||||
<el-col :span="13">
|
<el-col :span="13">
|
||||||
<el-form-item label="签到时间" prop="signinStartTime">
|
<el-form-item label="签到时间" prop="signinStartTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="SigninTime"
|
v-model="SignInTime"
|
||||||
type="datetimerange"
|
type="datetimerange"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
@@ -209,7 +232,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row> -->
|
</el-row> -->
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="warning" @click="submitForm('0')">保存为草稿</el-button>
|
<!-- <el-button type="warning" @click="submitForm('0')">保存为草稿</el-button>-->
|
||||||
<el-button type="primary" @click="submitForm('1')">发布</el-button>
|
<el-button type="primary" @click="submitForm('1')">发布</el-button>
|
||||||
<el-button @click="handleBack">返回</el-button>
|
<el-button @click="handleBack">返回</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -220,7 +243,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import editor from '@/components/Editor/index.vue';
|
import editor from '@/components/Editor/index.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
@@ -293,6 +316,8 @@ const rules = {
|
|||||||
applyDeadline: [{ required: true, message: '请输入报名截止日期', trigger: 'blur' }],
|
applyDeadline: [{ required: true, message: '请输入报名截止日期', trigger: 'blur' }],
|
||||||
startTime: [{ required: true, message: '请选择开始日期', trigger: 'blur' }],
|
startTime: [{ required: true, message: '请选择开始日期', trigger: 'blur' }],
|
||||||
endTime: [{ required: true, message: '请选择结束日期', trigger: 'blur' }],
|
endTime: [{ required: true, message: '请选择结束日期', trigger: 'blur' }],
|
||||||
|
signinStartTime: [{ required: true, message: '请选择开始签到时间', trigger: 'blur' }],
|
||||||
|
signinEndTime: [{ required: true, message: '请选择结束签到时间', trigger: 'blur' }],
|
||||||
address: [{ required: true, message: '请输入活动地点', trigger: 'blur' }],
|
address: [{ required: true, message: '请输入活动地点', trigger: 'blur' }],
|
||||||
organizer: [
|
organizer: [
|
||||||
{ required: true, message: '请输入主办方', trigger: 'blur' },
|
{ required: true, message: '请输入主办方', trigger: 'blur' },
|
||||||
@@ -313,8 +338,8 @@ const rules = {
|
|||||||
contactPhone: [
|
contactPhone: [
|
||||||
{ required: true, message: '请输入联系方式', trigger: 'blur' },
|
{ required: true, message: '请输入联系方式', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
validator: (_: any, value: string | number) => validator(value, 'Character'),
|
validator: (_: any, value: string | number) => validator(value, 'phone'),
|
||||||
message: '请输入中文,字母,数字等字符',
|
message: '请输入联系方式',
|
||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -328,12 +353,21 @@ const disabledDate = (time: string) => {
|
|||||||
const selectDate = new Date(time);
|
const selectDate = new Date(time);
|
||||||
return selectDate.getTime() < today.getTime();
|
return selectDate.getTime() < today.getTime();
|
||||||
};
|
};
|
||||||
|
const disabledDateDeadline = (time: string) => {
|
||||||
|
const today = new Date(form.value.endTime);
|
||||||
|
const selectDate = new Date(time);
|
||||||
|
return selectDate.getTime() > today.getTime();
|
||||||
|
};
|
||||||
|
function disabledSignInDate(time: string) {
|
||||||
|
const selectDate = new Date(time);
|
||||||
|
const today = new Date(form.value.endTime);
|
||||||
|
return selectDate.getTime() > today.getTime() || selectDate.getTime() < new Date(new Date().toLocaleDateString()).getTime();
|
||||||
|
}
|
||||||
const userid = ref();
|
const userid = ref();
|
||||||
// 报名截止日期
|
// 报名截止日期
|
||||||
const deadline = ref([]);
|
const deadline = ref([]);
|
||||||
// 有效签到时间
|
// 有效签到时间
|
||||||
const SigninTime = ref([]);
|
const SignInTime = ref([]);
|
||||||
// 活动时间
|
// 活动时间
|
||||||
const activityTime = ref([]);
|
const activityTime = ref([]);
|
||||||
|
|
||||||
@@ -341,7 +375,6 @@ const activityTime = ref([]);
|
|||||||
const upload = ref<UploadInstance>();
|
const upload = ref<UploadInstance>();
|
||||||
// 上传成功
|
// 上传成功
|
||||||
const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
|
const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
|
||||||
console.log(response);
|
|
||||||
if (response.data && response.data.url) {
|
if (response.data && response.data.url) {
|
||||||
form.value.coverImage = response.data.url;
|
form.value.coverImage = response.data.url;
|
||||||
} else {
|
} else {
|
||||||
@@ -396,7 +429,6 @@ async function initSignMap() {
|
|||||||
try {
|
try {
|
||||||
mapReady.value = true;
|
mapReady.value = true;
|
||||||
window._AMapSecurityConfig = { securityJsCode: VITE_GCJ02_JS_CODE_GD };
|
window._AMapSecurityConfig = { securityJsCode: VITE_GCJ02_JS_CODE_GD };
|
||||||
console.log('开始执行 AMapLoader.load');
|
|
||||||
const AMap = await AMapLoader.load({
|
const AMap = await AMapLoader.load({
|
||||||
key: aloaderkey,
|
key: aloaderkey,
|
||||||
version: '2.0',
|
version: '2.0',
|
||||||
@@ -483,8 +515,6 @@ const stopDrawCircle = () => {
|
|||||||
if (circle) {
|
if (circle) {
|
||||||
const center = circle.getCenter();
|
const center = circle.getCenter();
|
||||||
const radius = circle.getRadius();
|
const radius = circle.getRadius();
|
||||||
console.log('中心点:', [center.lng, center.lat]);
|
|
||||||
console.log('半径:', radius, typeof radius);
|
|
||||||
// form.value.SignInfo.lat = center.lat;
|
// form.value.SignInfo.lat = center.lat;
|
||||||
// form.value.SignInfo.lng = center.lng;
|
// form.value.SignInfo.lng = center.lng;
|
||||||
// form.value.SignInfo.radius = center.radius;
|
// form.value.SignInfo.radius = center.radius;
|
||||||
@@ -533,7 +563,7 @@ function init() {
|
|||||||
...res.data
|
...res.data
|
||||||
};
|
};
|
||||||
activityTime.value = [res.data.startTime, res.data.endTime];
|
activityTime.value = [res.data.startTime, res.data.endTime];
|
||||||
SigninTime.value = [res.data.signinStartTime, res.data.signinEndTime];
|
SignInTime.value = [res.data.signinStartTime, res.data.signinEndTime];
|
||||||
deadline.value = [res.data.applyDeadline];
|
deadline.value = [res.data.applyDeadline];
|
||||||
|
|
||||||
// if (res.data?.SignInfo !== null) {
|
// if (res.data?.SignInfo !== null) {
|
||||||
@@ -545,7 +575,7 @@ function init() {
|
|||||||
// 提交
|
// 提交
|
||||||
const submitForm = (status: string) => {
|
const submitForm = (status: string) => {
|
||||||
form.value.status = status;
|
form.value.status = status;
|
||||||
console.log(form.value);
|
|
||||||
// if (!isSignin.value) {
|
// if (!isSignin.value) {
|
||||||
// form.value.SignInfo = null;
|
// form.value.SignInfo = null;
|
||||||
// }
|
// }
|
||||||
@@ -591,7 +621,7 @@ onUnmounted(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.SignMapbox {
|
.SignMapbox {
|
||||||
height: 500px;
|
height: 500px;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="标题" prop="title">
|
<el-form-item label="标题" prop="title">
|
||||||
<el-input v-model="queryParams.title" placeholder="请输入标题" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.title" clearable placeholder="请输入标题" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -19,13 +19,13 @@
|
|||||||
|
|
||||||
<el-card class="flex-1" shadow="never">
|
<el-card class="flex-1" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb10">
|
||||||
<right-toolbar
|
<right-toolbar
|
||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['activity:activity:add'])"
|
:show-add="checkPermi(['activity:activity:add'])"
|
||||||
:show-edit="checkPermi(['activity:activity:edit'])"
|
|
||||||
:show-delete="checkPermi(['activity:activity:remove'])"
|
:show-delete="checkPermi(['activity:activity:remove'])"
|
||||||
|
:show-edit="checkPermi(['activity:activity:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,59 +33,65 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="activityList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="activityList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="封面" align="center">
|
<el-table-column align="center" label="封面" min-width="130px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-image
|
<el-image
|
||||||
preview-teleported
|
|
||||||
lazy
|
|
||||||
:preview-src-list="[scope.row.coverImage]"
|
|
||||||
v-if="scope.row.coverImage"
|
v-if="scope.row.coverImage"
|
||||||
|
:preview-src-list="[scope.row.coverImage]"
|
||||||
:src="scope.row.coverImage"
|
:src="scope.row.coverImage"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
|
lazy
|
||||||
|
preview-teleported
|
||||||
style="width: 100px; height: 100px"
|
style="width: 100px; height: 100px"
|
||||||
></el-image>
|
></el-image>
|
||||||
<span v-else style="color: grey">暂无</span>
|
<span v-else style="color: grey">暂无</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="标题" align="center" prop="title" />
|
<el-table-column align="center" label="标题" prop="title" />
|
||||||
<el-table-column label="主办方" align="center" prop="organizer" />
|
<el-table-column align="center" label="主办方" prop="organizer" />
|
||||||
<el-table-column label="发布状态" width="100" align="center" prop="status">
|
<el-table-column align="center" label="签到时间" prop="signInTime" width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<DictTag :value="scope.row.status" :options="com_publish_status"></DictTag>
|
<span>{{ scope.row.signinStartTime }}-{{ scope.row.signinEndTime }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="活动时间" align="center">
|
<el-table-column align="center" label="发布状态" prop="status" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<DictTag :options="com_publish_status" :value="scope.row.status"></DictTag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="活动时间">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.startTime }}</span>
|
<span>{{ scope.row.startTime }}</span>
|
||||||
<span> -- </span>
|
<span> -- </span>
|
||||||
<span>{{ scope.row.endTime }}</span>
|
<span>{{ scope.row.endTime }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="活动地点" align="center" prop="address" />
|
<el-table-column align="center" label="活动地点" prop="address" />
|
||||||
<el-table-column label="联系人" width="120" align="center" prop="contactName" />
|
<el-table-column align="center" label="联系人" prop="contactName" width="120" />
|
||||||
<el-table-column label="联系电话" width="120" align="center" prop="contactPhone" />
|
<el-table-column align="center" label="联系电话" prop="contactPhone" width="120" />
|
||||||
<el-table-column label="活动名额" width="80" align="center" prop="contactPhone">
|
|
||||||
|
<el-table-column align="center" label="活动名额" prop="contactPhone" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.quota === 0">无限制</span>
|
<span v-if="scope.row.quota === 0">无限制</span>
|
||||||
<span v-else>{{ scope.row.quota }}人</span>
|
<span v-else>{{ scope.row.quota }}人</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" width="200px" fixed="right">
|
<el-table-column align="center" fixed="right" label="操作" width="200px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button v-if="scope.row.status === '0'" link type="primary" @click="handleSend(scope.row)">发布</el-button>
|
<el-button v-if="scope.row.status === '0'" link type="primary" @click="handleSend(scope.row)">发布</el-button>
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['activity:activity:edit']">编辑</el-button>
|
<el-button v-has-permi="['activity:activity:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['activity:activity:remove']">删除</el-button>
|
<el-button v-has-permi="['activity:activity:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<el-form ref="activityFormRef" :model="form" :rules="rules" label-width="120px">
|
<el-form ref="activityFormRef" :model="form" :rules="rules" label-width="120px">
|
||||||
<el-form-item label="发布人姓名" prop="createName">
|
<el-form-item label="发布人姓名" prop="createName">
|
||||||
<el-input maxlength="20" v-model.trim="form.createName" placeholder="请输入发布人姓名" />
|
<el-input v-model.trim="form.createName" maxlength="20" placeholder="请输入发布人姓名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="发布后状态" prop="status">
|
<el-form-item label="发布后状态" prop="status">
|
||||||
<el-radio-group v-model="form.status">
|
<el-radio-group v-model="form.status">
|
||||||
@@ -103,7 +109,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Activity" lang="ts">
|
<script lang="ts" name="Activity" setup>
|
||||||
import { listActivity, delActivity, updateActivity } from '@/api/system/Activity';
|
import { listActivity, delActivity, updateActivity } from '@/api/system/Activity';
|
||||||
import { ActivityVO, ActivityQuery, ActivityForm } from '@/api/system/Activity/type';
|
import { ActivityVO, ActivityQuery, ActivityForm } from '@/api/system/Activity/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<el-input v-model.trim="form.link" placeholder="请输入跳转链接" />
|
<el-input v-model.trim="form.link" placeholder="请输入跳转链接" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="排序号" prop="byOrder">
|
<el-form-item label="排序号" prop="byOrder">
|
||||||
<el-input-number v-model.trim="form.byOrder" placeholder="请输入" />
|
<el-input-number :min="0" :max="9999" v-model.trim="form.byOrder" placeholder="请输入" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item style="margin-top: 30px">
|
<el-form-item style="margin-top: 30px">
|
||||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="名称" prop="name">
|
<el-form-item label="名称" prop="name">
|
||||||
<el-input maxlength="20" v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.name" clearable maxlength="20" placeholder="请输入名称" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['banner:banner:add'])"
|
:show-add="checkPermi(['banner:banner:add'])"
|
||||||
:show-edit="false"
|
:show-delete="checkPermi(['banner:banner:remove'])"
|
||||||
:show-delete="false"
|
:show-edit="checkPermi(['banner:banner:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,49 +33,49 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="bannerList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="bannerList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="Banner缩略图" align="center" prop="id">
|
<el-table-column align="center" label="Banner缩略图" prop="id">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-image
|
<el-image
|
||||||
v-if="scope.row.url && scope.row.url.includes('http')"
|
v-if="scope.row.url && scope.row.url.includes('http')"
|
||||||
:src="scope.row.url"
|
|
||||||
:preview-src-list="[scope.row.url]"
|
:preview-src-list="[scope.row.url]"
|
||||||
style="width: 40px; height: 40px; border-radius: 4px; margin-right: 5px"
|
:src="scope.row.url"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
preview-teleported
|
preview-teleported
|
||||||
|
style="width: 40px; height: 40px; border-radius: 4px; margin-right: 5px"
|
||||||
/>
|
/>
|
||||||
<span v-else>暂时没有</span>
|
<span v-else>暂时没有</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="名称" align="center" prop="name" />
|
<el-table-column align="center" label="名称" prop="name" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<!-- 0启用 1停用 -->
|
<!-- 0启用 1停用 -->
|
||||||
<el-switch
|
<el-switch
|
||||||
@change="(val: string) => handleSwitch(scope.row.id, val)"
|
|
||||||
inactive-value="1"
|
|
||||||
active-value="0"
|
|
||||||
v-model="scope.row.status"
|
v-model="scope.row.status"
|
||||||
|
active-value="0"
|
||||||
|
inactive-value="1"
|
||||||
|
@change="(val: string) => handleSwitch(scope.row.id, val)"
|
||||||
></el-switch>
|
></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="排序" align="center" prop="byOrder" />
|
<el-table-column align="center" label="排序" prop="byOrder" />
|
||||||
<el-table-column label="添加时间" align="center" prop="createTime" />
|
<el-table-column align="center" label="添加时间" prop="createTime" />
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['banner:banner:edit']">修改</el-button>
|
<el-button v-has-permi="['banner:banner:edit']" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['banner:banner:remove']">删除</el-button>
|
<el-button v-has-permi="['banner:banner:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Banner" lang="ts">
|
<script lang="ts" name="Banner" setup>
|
||||||
import { listBanner, delBanner, switchBanner } from '@/api/system/Banner';
|
import { listBanner, delBanner, switchBanner } from '@/api/system/Banner';
|
||||||
import { BannerVO, BannerQuery, BannerForm } from '@/api/system/Banner/type';
|
import { BannerVO, BannerQuery, BannerForm } from '@/api/system/Banner/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|||||||
@@ -52,10 +52,10 @@
|
|||||||
<el-image
|
<el-image
|
||||||
v-for="(item, index) in problemImageUrlList"
|
v-for="(item, index) in problemImageUrlList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:src="item"
|
|
||||||
:preview-teleported="true"
|
|
||||||
:initial-index="index"
|
:initial-index="index"
|
||||||
:preview-src-list="problemImageUrlList"
|
:preview-src-list="problemImageUrlList"
|
||||||
|
:preview-teleported="true"
|
||||||
|
:src="item"
|
||||||
style="width: 120px; height: 120px; margin-right: 10px"
|
style="width: 120px; height: 120px; margin-right: 10px"
|
||||||
></el-image>
|
></el-image>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,27 +73,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="formBox">
|
<div class="formBox">
|
||||||
<el-form ref="formRef" :rules="rules" class="m-auto" :inline="false" label-width="100px" :model="form">
|
<el-form ref="formRef" :inline="false" :model="form" :rules="rules" class="m-auto" label-width="100px">
|
||||||
<el-form-item label="处理状态" prop="status">
|
<el-form-item label="处理状态" prop="status">
|
||||||
<el-radio-group v-model="form.status">
|
<el-radio-group v-model="form.status">
|
||||||
<el-radio value="1">处理完成</el-radio>
|
<el-radio value="1">处理完成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="处理人员" prop="handleId">
|
<el-form-item label="处理人员" prop="handleId">
|
||||||
<repairUser
|
<complainUser
|
||||||
title-name="选择处理人员"
|
|
||||||
:is-multiple="false"
|
:is-multiple="false"
|
||||||
:username="formInfo.handleName"
|
|
||||||
:userid="formInfo.handleId"
|
:userid="formInfo.handleId"
|
||||||
|
:username="formInfo.handleName"
|
||||||
returnvalue="*"
|
returnvalue="*"
|
||||||
|
title-name="选择处理人员"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
></repairUser>
|
></complainUser>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="处理描述" prop="handleContent">
|
<el-form-item label="处理描述" prop="handleContent">
|
||||||
<el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.handleContent"></el-input>
|
<el-input v-model.trim="form.handleContent" :rows="5" maxlength="200" show-word-limit type="textarea"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" v-if="form.status !== '0'" @click="submitForm">提交</el-button>
|
<el-button v-if="formInfo.status !== '1'" type="primary" @click="submitForm">提交</el-button>
|
||||||
<el-button @click="handleBack">返回</el-button>
|
<el-button @click="handleBack">返回</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -103,10 +103,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import repairUser from '@/components/Holder/repairUser.vue';
|
import complainUser from '@/components/Holder/complainUser.vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { getComplaint, updateComplaint } from '@/api/system/Complaint';
|
import { getComplaint, updateComplaint } from '@/api/system/Complaint';
|
||||||
import { listComplaintType } from '@/api/system/ComplainType';
|
import { listComplaintType } from '@/api/system/ComplainType';
|
||||||
@@ -126,7 +126,7 @@ const formInfo = ref({
|
|||||||
'phone': '',
|
'phone': '',
|
||||||
'problemImageUrl': '',
|
'problemImageUrl': '',
|
||||||
/**
|
/**
|
||||||
* 投诉状态 0 待处理 1 已处理╬╬╬╬╬╬
|
* 投诉状态 0 待处理 1 已处理
|
||||||
*/
|
*/
|
||||||
'status': '1',
|
'status': '1',
|
||||||
'handleId': '',
|
'handleId': '',
|
||||||
@@ -143,7 +143,7 @@ const form = ref({
|
|||||||
});
|
});
|
||||||
const rules = {
|
const rules = {
|
||||||
status: [{ required: true, message: '选择投诉处理状态', trigger: 'blur' }],
|
status: [{ required: true, message: '选择投诉处理状态', trigger: 'blur' }],
|
||||||
handleContent: [{ required: true, message: '投诉处理内容不能为空', trigger: 'blur' }],
|
handleContent: [{ required: false, message: '投诉处理内容不能为空', trigger: 'blur' }],
|
||||||
handleId: [{ required: true, message: '投诉处理人员不能为空', trigger: 'blur' }]
|
handleId: [{ required: true, message: '投诉处理人员不能为空', trigger: 'blur' }]
|
||||||
};
|
};
|
||||||
const userid = ref();
|
const userid = ref();
|
||||||
@@ -159,7 +159,8 @@ async function init() {
|
|||||||
};
|
};
|
||||||
form.value = {
|
form.value = {
|
||||||
...form.value,
|
...form.value,
|
||||||
...res.data
|
...res.data,
|
||||||
|
status: '1'
|
||||||
};
|
};
|
||||||
// 处理照片
|
// 处理照片
|
||||||
problemImageUrlList.value = res.data.problemImageUrl ? res.data.problemImageUrl.split(',') : [];
|
problemImageUrlList.value = res.data.problemImageUrl ? res.data.problemImageUrl.split(',') : [];
|
||||||
@@ -209,7 +210,7 @@ function handleBack() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.ResidentMainBox {
|
.ResidentMainBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" label-width="90px" label-position="left" :model="queryParams" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" label-position="left" label-width="90px">
|
||||||
<el-form-item label="投诉类型" prop="typeId">
|
<el-form-item label="投诉状态" prop="status">
|
||||||
<el-select @clear="handleClear" clearable v-model="queryParams.typeId" placeholder="请选择投诉类型" style="width: 240px">
|
<el-select v-model="queryParams.status" clearable placeholder="请选择投诉状态" style="width: 240px" @clear="handleClear">
|
||||||
<el-option :disabled="item.status === '1'" v-for="item in complainTypeList" :key="item.id" :label="item.name" :value="item.id" />
|
<el-option v-for="item in com_complaint_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="投诉人姓名" prop="complaintName">
|
<el-form-item label="投诉人姓名" prop="complaintName">
|
||||||
<el-input v-model="queryParams.complaintName" placeholder="请输入投诉人姓名" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.complaintName" clearable placeholder="请输入投诉人姓名" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -22,31 +22,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<el-card class="flex-1" shadow="never">
|
<el-card class="flex-1" shadow="never">
|
||||||
<el-table v-loading="loading" border :data="complaintList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="complaintList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="投诉类型" align="center" prop="typeName" />
|
<el-table-column align="center" label="投诉类型" prop="typeName" />
|
||||||
<el-table-column label="问题描述" show-overflow-tooltip align="center" prop="problemDes" />
|
<el-table-column align="center" label="问题描述" prop="problemDes" show-overflow-tooltip />
|
||||||
<el-table-column label="投诉人姓名" align="center" prop="complaintName" />
|
<el-table-column align="center" label="投诉人姓名" prop="complaintName" />
|
||||||
<el-table-column label="手机号" align="center" prop="phone" />
|
<el-table-column align="center" label="手机号" prop="phone" />
|
||||||
<el-table-column label="投诉时间" align="center" prop="createTime" />
|
<el-table-column align="center" label="投诉时间" prop="createTime" />
|
||||||
<el-table-column label="投诉状态" align="center" prop="status">
|
<el-table-column align="center" label="投诉状态" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_complaint_status" :value="scope.row.status"></dict-tag>
|
<dict-tag :options="com_complaint_status" :value="scope.row.status"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="处理人" align="center" prop="handleName" />
|
<el-table-column align="center" label="处理人" prop="handleName" />
|
||||||
<el-table-column label="处理描述" show-overflow-tooltip align="center" prop="handleContent" />
|
<el-table-column align="center" label="处理描述" prop="handleContent" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['complaint:complaint:query']">查看详情</el-button>
|
<el-button v-has-permi="['complaint:complaint:query']" link type="primary" @click="handleUpdate(scope.row)">查看详情</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup name="Complaint" lang="ts">
|
<script lang="ts" name="Complaint" setup>
|
||||||
import { listComplaint } from '@/api/system/Complaint';
|
import { listComplaint } from '@/api/system/Complaint';
|
||||||
import { ComplaintVO, ComplaintQuery, ComplaintForm } from '@/api/system/Complaint/type';
|
import { ComplaintVO, ComplaintQuery, ComplaintForm } from '@/api/system/Complaint/type';
|
||||||
import { listComplaintType } from '@/api/system/ComplainType';
|
import { listComplaintType } from '@/api/system/ComplainType';
|
||||||
@@ -120,9 +120,9 @@ const handleQuery = () => {
|
|||||||
getList();
|
getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 清空投诉类型 */
|
/** 清空投诉状态 */
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
queryParams.value.typeId = undefined;
|
queryParams.value.status = undefined;
|
||||||
handleQuery();
|
handleQuery();
|
||||||
};
|
};
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" label-width="100px" :model="queryParams" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" label-width="100px">
|
||||||
<el-form-item label="投诉类型名称" prop="name">
|
<el-form-item label="投诉类型名称" prop="name">
|
||||||
<el-input maxlength="20" v-model.trim="queryParams.name" placeholder="请输入投诉类型名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model.trim="queryParams.name" clearable maxlength="20" placeholder="请输入投诉类型名称" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -17,15 +17,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never" class="flex-1">
|
<el-card class="flex-1" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<right-toolbar
|
<right-toolbar
|
||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['complaintType:complaintType:add'])"
|
:show-add="checkPermi(['complaintType:complaintType:add'])"
|
||||||
:show-edit="false"
|
:show-delete="checkPermi(['complaintType:complaintType:remove'])"
|
||||||
:show-delete="false"
|
:show-edit="checkPermi(['complaintType:complaintType:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,38 +33,43 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="complaintTypeList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="complaintTypeList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="投诉类型名称" align="center" prop="name" />
|
<el-table-column align="center" label="投诉类型名称" prop="name" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch
|
<el-switch
|
||||||
@change="(val: string) => handleChange(val, scope.row)"
|
|
||||||
v-model="scope.row.status"
|
v-model="scope.row.status"
|
||||||
active-value="0"
|
active-value="0"
|
||||||
inactive-value="1"
|
inactive-value="1"
|
||||||
|
@change="(val: string) => handleChange(val, scope.row)"
|
||||||
></el-switch>
|
></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column align="center" label="添加人" prop="createName" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ scope.row.createName }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" label="创建时间" prop="createTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['complaintType:complaintType:edit']">编辑</el-button>
|
<span>{{ scope.row.createTime }}</span>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['complaintType:complaintType:remove']">删除</el-button>
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" class-name="small-padding fixed-width" label="操作">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button v-has-permi="['complaintType:complaintType:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
|
<el-button v-has-permi="['complaintType:complaintType:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="ComplaintType" lang="ts">
|
<script lang="ts" name="ComplaintType" setup>
|
||||||
import { listComplaintType, delComplaintType, updateComplaintType } from '@/api/system/ComplainType';
|
import { listComplaintType, delComplaintType, updateComplaintType } from '@/api/system/ComplainType';
|
||||||
import { ComplaintTypeVO, ComplaintTypeQuery, ComplaintTypeForm } from '@/api/system/ComplainType/type';
|
import { ComplaintTypeVO, ComplaintTypeQuery, ComplaintTypeForm } from '@/api/system/ComplainType/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|||||||
@@ -12,12 +12,12 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="房屋" prop="houseId">
|
<el-form-item label="房屋" prop="houseId">
|
||||||
<el-cascader @change="handleChange" v-model="userHousepath" :options="treedata" />
|
<el-cascader v-model="userHousepath" :options="treedata" @change="handleChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="申请人" prop="applyName">
|
<el-form-item label="申请人" prop="applyName">
|
||||||
<el-input maxlength="20" v-model.trim="form.applyName" placeholder="请输入申请人" />
|
<el-input v-model.trim="form.applyName" maxlength="20" placeholder="请输入申请人" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -25,19 +25,19 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="装修公司" prop="decorationCompany">
|
<el-form-item label="装修公司" prop="decorationCompany">
|
||||||
<el-input maxlength="20" v-model.trim="form.decorationCompany" placeholder="请输入装修公司" />
|
<el-input v-model.trim="form.decorationCompany" maxlength="20" placeholder="请输入装修公司" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="装修内容" prop="decorationContent">
|
<el-form-item label="装修内容" prop="decorationContent">
|
||||||
<el-input maxlength="200" show-word-limit type="textarea" v-model.trim="form.decorationContent" placeholder="请输入装修内容" />
|
<el-input v-model.trim="form.decorationContent" maxlength="200" placeholder="请输入装修内容" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="装修押金(元)" prop="decorationDeposit">
|
<el-form-item label="装修押金(元)" prop="decorationDeposit">
|
||||||
<el-input maxlength="8" placeholder="请输入装修押金,最多保留2位小数" v-model.number.trim="form.decorationDeposit" />
|
<el-input v-model.number.trim="form.decorationDeposit" maxlength="8" placeholder="请输入装修押金,最多保留2位小数" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { addDecoration, getDecoration, updateDecoration } from '@/api/system/Decoration';
|
import { addDecoration, getDecoration, updateDecoration } from '@/api/system/Decoration';
|
||||||
@@ -109,7 +109,6 @@ const rules = {
|
|||||||
return callback(new Error('请输入装修押金'));
|
return callback(new Error('请输入装修押金'));
|
||||||
}
|
}
|
||||||
const num = Number(val);
|
const num = Number(val);
|
||||||
console.log(val);
|
|
||||||
if (Number.isNaN(num)) {
|
if (Number.isNaN(num)) {
|
||||||
return callback(new Error('请输入装修押金'));
|
return callback(new Error('请输入装修押金'));
|
||||||
}
|
}
|
||||||
@@ -148,7 +147,7 @@ function handleChange(val: (string | number)[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! 投诉 ====================================================================================================
|
// ! 投诉 蚱蝉====================================================================================================
|
||||||
function getTree() {
|
function getTree() {
|
||||||
houseStore.getCurrentVilageTreeHouse().then((res) => {
|
houseStore.getCurrentVilageTreeHouse().then((res) => {
|
||||||
treedata.value = res;
|
treedata.value = res;
|
||||||
@@ -195,7 +194,7 @@ function handleBack() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.ResidentMainBox {
|
.ResidentMainBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form label-width="120px" ref="queryFormRef" :rules="rules" :model="queryParams" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" :rules="rules" label-width="120px">
|
||||||
<el-form-item label="申请人姓名" prop="applyName">
|
<el-form-item label="申请人姓名" prop="applyName">
|
||||||
<el-input maxlength="20" v-model.trim="queryParams.applyName" placeholder="请输入申请人姓名" clearable @keyup.enter="handleQuery" />
|
<el-input v-model.trim="queryParams.applyName" clearable maxlength="20" placeholder="请输入申请人姓名" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="装修验收结果">
|
<el-form-item label="装修验收结果">
|
||||||
<el-select clearable @clear="handleClear" v-model="queryParams.inspectionResult" placeholder="请选择装修验收结果" style="width: 240px">
|
<el-select v-model="queryParams.inspectionResult" clearable placeholder="请选择装修验收结果" style="width: 240px" @clear="handleClear">
|
||||||
<el-option v-for="item in com_decoration_status" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in com_decoration_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['decoration:decoration:add'])"
|
:show-add="checkPermi(['decoration:decoration:add'])"
|
||||||
:show-edit="checkPermi(['decoration:decoration:edit'])"
|
|
||||||
:show-delete="checkPermi(['decoration:decoration:remove'])"
|
:show-delete="checkPermi(['decoration:decoration:remove'])"
|
||||||
|
:show-edit="checkPermi(['decoration:decoration:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -38,91 +38,91 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="decorationList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="decorationList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="小区名称" align="center" prop="villageName" />
|
<el-table-column align="center" label="小区名称" prop="villageName" />
|
||||||
<el-table-column label="房屋号" show-overflow-tooltip align="center" prop="houseName" />
|
<el-table-column align="center" label="房屋号" prop="houseName" show-overflow-tooltip />
|
||||||
<el-table-column label="申请人姓名" align="center" prop="applyName" />
|
<el-table-column align="center" label="申请人姓名" prop="applyName" />
|
||||||
<el-table-column label="装修公司" align="center" prop="decorationCompany" />
|
<el-table-column align="center" label="装修公司" prop="decorationCompany" />
|
||||||
<el-table-column label="装修内容" align="center" prop="decorationContent" />
|
<el-table-column align="center" label="装修内容" prop="decorationContent" />
|
||||||
<el-table-column label="装修押金" width="120" align="center" prop="decorationDeposit" />
|
<el-table-column align="center" label="申请时间" prop="createTime" width="170" />
|
||||||
<el-table-column label="验收结果" width="100" align="center" prop="inspectionResult">
|
<el-table-column align="center" label="装修押金(元)" prop="decorationDeposit" width="120" />
|
||||||
|
<el-table-column align="center" label="验收结果" prop="inspectionResult" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_decoration_status" :value="Number(scope.row.inspectionResult)"></dict-tag>
|
<dict-tag :options="com_decoration_status" :value="Number(scope.row.inspectionResult)"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="申请时间" width="170" align="center" prop="createTime" />
|
<el-table-column align="center" label="验收人" prop="inspectionName" />
|
||||||
<el-table-column label="验收人" align="center" prop="inspectionName" />
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" width="170">
|
||||||
<el-table-column label="操作" width="170" align="center" fixed="right" class-name="small-padding fixed-width">
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
|
v-if="scope.row.inspectionResult !== '1'"
|
||||||
|
v-has-permi="['decoration:decoration:edit']"
|
||||||
link
|
link
|
||||||
type="primary"
|
type="primary"
|
||||||
v-if="scope.row.inspectionResult !== '1'"
|
|
||||||
@click="handleInspection(scope.row, EditType.Add, '验收')"
|
@click="handleInspection(scope.row, EditType.Add, '验收')"
|
||||||
v-has-permi="['repair:edit:decoration']"
|
|
||||||
>验收</el-button
|
>验收</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
|
v-else
|
||||||
|
v-has-permi="['decoration:decoration:query']"
|
||||||
link
|
link
|
||||||
type="primary"
|
type="primary"
|
||||||
v-else
|
|
||||||
@click="handleInspection(scope.row, EditType.Detail, '详情')"
|
@click="handleInspection(scope.row, EditType.Detail, '详情')"
|
||||||
v-has-permi="['decoration:decoration:query']"
|
|
||||||
>详情</el-button
|
>详情</el-button
|
||||||
>
|
>
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['decoration:decoration:edit']">编辑</el-button>
|
<el-button v-has-permi="['decoration:decoration:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['decoration:decoration:remove']">删除</el-button>
|
<el-button v-has-permi="['decoration:decoration:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<el-form ref="decorationFormRef" :model="form" :rules="rules" label-width="120px">
|
<el-form ref="decorationFormRef" :model="form" :rules="rules" label-width="120px">
|
||||||
<div v-if="isEditComputed">
|
<div v-if="isEditComputed">
|
||||||
<el-form-item label="小区名称" prop="villageName">
|
<el-form-item label="小区名称" prop="villageName">
|
||||||
<el-input :disabled="isEditComputed" v-model="form.villageName" />
|
<el-input v-model="form.villageName" :disabled="isEditComputed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="房屋号" prop="houseName">
|
<el-form-item label="房屋号" prop="houseName">
|
||||||
<el-input :disabled="isEditComputed" v-model="form.houseName" />
|
<el-input v-model="form.houseName" :disabled="isEditComputed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="申请人" prop="applyName">
|
<el-form-item label="申请人" prop="applyName">
|
||||||
<el-input :disabled="isEditComputed" v-model="form.applyName" />
|
<el-input v-model="form.applyName" :disabled="isEditComputed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="装修公司" prop="decorationCompany">
|
<el-form-item label="装修公司" prop="decorationCompany">
|
||||||
<el-input :disabled="isEditComputed" v-model="form.decorationCompany" />
|
<el-input v-model="form.decorationCompany" :disabled="isEditComputed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="装修内容" prop="decorationContent">
|
<el-form-item label="装修内容" prop="decorationContent">
|
||||||
<el-input :disabled="isEditComputed" v-model="form.decorationContent" />
|
<el-input v-model="form.decorationContent" :disabled="isEditComputed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="装修押金" prop="decorationDeposit">
|
<el-form-item label="装修押金" prop="decorationDeposit">
|
||||||
<el-input :disabled="isEditComputed" v-model="form.decorationDeposit" />
|
<el-input v-model="form.decorationDeposit" :disabled="isEditComputed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item label="验收结果" :prop="isEditComputed ? '' : 'inspectionResult'">
|
<el-form-item :prop="isEditComputed ? '' : 'inspectionResult'" label="验收结果">
|
||||||
<el-select :disabled="isEditComputed" v-model="form.inspectionResult" placeholder="请选择装修验收结果">
|
<el-select v-model="form.inspectionResult" :disabled="isEditComputed" placeholder="请选择装修验收结果">
|
||||||
<el-option v-for="item in com_decoration_status" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in com_decoration_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="验收人" :prop="isEditComputed ? '' : 'inspectionName'">
|
<el-form-item :prop="isEditComputed ? '' : 'inspectionName'" label="验收人">
|
||||||
<el-input :disabled="isEditComputed" placeholder="请输入验收人" v-model.trim="form.inspectionName" />
|
<el-input v-model.trim="form.inspectionName" :disabled="isEditComputed" placeholder="请输入验收人" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input
|
<el-input
|
||||||
:disabled="isEditComputed"
|
|
||||||
v-model="form.remark"
|
v-model="form.remark"
|
||||||
type="textarea"
|
:disabled="isEditComputed"
|
||||||
maxlength="200"
|
|
||||||
show-word-limit
|
|
||||||
:placeholder="isEditComputed ? '' : '请输入'"
|
:placeholder="isEditComputed ? '' : '请输入'"
|
||||||
:rows="5"
|
:rows="5"
|
||||||
|
maxlength="200"
|
||||||
|
show-word-limit
|
||||||
|
type="textarea"
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer v-if="!isEditComputed">
|
<template v-if="!isEditComputed" #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
<el-button @click="cancel">取 消</el-button>
|
<el-button @click="cancel">取 消</el-button>
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Decoration" lang="ts">
|
<script lang="ts" name="Decoration" setup>
|
||||||
import { listDecoration, delDecoration, updateDecoration } from '@/api/system/Decoration';
|
import { listDecoration, delDecoration, updateDecoration } from '@/api/system/Decoration';
|
||||||
import { DecorationVO, DecorationQuery, DecorationForm } from '@/api/system/Decoration/type';
|
import { DecorationVO, DecorationQuery, DecorationForm } from '@/api/system/Decoration/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
<el-col>
|
<el-col>
|
||||||
<el-form-item label="办事内容" prop="content">
|
<el-form-item label="办事内容" prop="content">
|
||||||
<editor
|
<editor
|
||||||
@update:model-value="handleContent"
|
:file-size="5"
|
||||||
:model-value="form.content"
|
|
||||||
:height="500"
|
:height="500"
|
||||||
:min-height="300"
|
:min-height="300"
|
||||||
|
:model-value="form.content"
|
||||||
:read-only="false"
|
:read-only="false"
|
||||||
:file-size="5"
|
@update:model-value="handleContent"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -26,12 +26,12 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="求助人姓名" prop="seekName">
|
<el-form-item label="求助人姓名" prop="seekName">
|
||||||
<el-input maxlength="20" v-model.trim="form.seekName" placeholder="请输入求助人姓名" />
|
<el-input v-model.trim="form.seekName" maxlength="20" placeholder="请输入求助人姓名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="联系方式" prop="phone">
|
<el-form-item label="联系方式" prop="phone">
|
||||||
<el-input maxlength="50" show-word-limit v-model.trim="form.phone" placeholder="请输入联系方式" />
|
<el-input v-model.trim="form.phone" maxlength="50" placeholder="请输入联系方式" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -39,23 +39,23 @@
|
|||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="办事时间" prop="handleTime">
|
<el-form-item label="办事时间" prop="handleTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
format="YYYY-MM-DD HH:mm"
|
|
||||||
value-format="YYYY-MM-DD HH:mm"
|
|
||||||
v-model="form.handleTime"
|
v-model="form.handleTime"
|
||||||
type="datetime"
|
format="YYYY-MM-DD HH:mm"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="办事地点" prop="handlePosition">
|
<el-form-item label="办事地点" prop="handlePosition">
|
||||||
<el-input
|
<el-input
|
||||||
maxlength="200"
|
|
||||||
type="textarea"
|
|
||||||
:rows="3"
|
|
||||||
show-word-limit
|
|
||||||
v-model.trim="form.handlePosition"
|
v-model.trim="form.handlePosition"
|
||||||
|
:rows="3"
|
||||||
|
maxlength="200"
|
||||||
placeholder="请输入办事地点"
|
placeholder="请输入办事地点"
|
||||||
|
show-word-limit
|
||||||
|
type="textarea"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -64,21 +64,21 @@
|
|||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="附属材料">
|
<el-form-item label="附属材料">
|
||||||
<el-upload
|
<el-upload
|
||||||
class="upload-demo"
|
|
||||||
:file-list="fileList"
|
|
||||||
:action="uploadUrl"
|
|
||||||
:multiple="true"
|
|
||||||
:auto-upload="false"
|
|
||||||
:limit="9"
|
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
:show-file-list="true"
|
:action="uploadUrl"
|
||||||
name="files"
|
:auto-upload="false"
|
||||||
:on-exceed="handleExceed"
|
|
||||||
:headers="headerToken()"
|
|
||||||
:on-remove="handleAvatarRemove"
|
|
||||||
:on-change="handleProgress"
|
|
||||||
:before-upload="beforeAvatarUpload"
|
:before-upload="beforeAvatarUpload"
|
||||||
|
:file-list="fileList"
|
||||||
|
:headers="headerToken()"
|
||||||
|
:limit="9"
|
||||||
|
:multiple="true"
|
||||||
|
:on-change="handleProgress"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:on-remove="handleAvatarRemove"
|
||||||
|
:show-file-list="true"
|
||||||
accept=".doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.bmp,.webp,.zip"
|
accept=".doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.bmp,.webp,.zip"
|
||||||
|
class="upload-demo"
|
||||||
|
name="files"
|
||||||
>
|
>
|
||||||
<div class="uploadBtn flex flex-items-center">
|
<div class="uploadBtn flex flex-items-center">
|
||||||
<el-icon><Upload /></el-icon>
|
<el-icon><Upload /></el-icon>
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import editor from '@/components/Editor/index.vue';
|
import editor from '@/components/Editor/index.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
@@ -130,6 +130,8 @@ const form = ref({
|
|||||||
});
|
});
|
||||||
const rules = {
|
const rules = {
|
||||||
content: [{ required: true, message: '请输入办事内容', trigger: 'blur' }],
|
content: [{ required: true, message: '请输入办事内容', trigger: 'blur' }],
|
||||||
|
handleTime: [{ required: true, message: '请输入办事时间', trigger: 'blur' }],
|
||||||
|
handlePosition: [{ required: true, message: '请输入办事地点', trigger: 'blur' }],
|
||||||
seekName: [
|
seekName: [
|
||||||
{ required: true, message: '请选择求助人', trigger: 'blur' },
|
{ required: true, message: '请选择求助人', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
@@ -282,7 +284,6 @@ const beforeAvatarUpload = (rawFile: UploadUserFile) => {
|
|||||||
|
|
||||||
// ! 初始 ====================================================================================================
|
// ! 初始 ====================================================================================================
|
||||||
function init() {
|
function init() {
|
||||||
console.log('init');
|
|
||||||
getHandleLog(userid.value).then((res) => {
|
getHandleLog(userid.value).then((res) => {
|
||||||
form.value = {
|
form.value = {
|
||||||
...form.value,
|
...form.value,
|
||||||
@@ -317,7 +318,6 @@ const submitForm = async () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
const files = [...oldFiles];
|
const files = [...oldFiles];
|
||||||
console.log('oldFiles', files);
|
|
||||||
if (newFiles.length > 0) {
|
if (newFiles.length > 0) {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
newFiles.forEach((item) => {
|
newFiles.forEach((item) => {
|
||||||
@@ -371,7 +371,7 @@ function handleBack() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.ResidentMainBox {
|
.ResidentMainBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="求助人" prop="seekName">
|
<el-form-item label="求助人" prop="seekName">
|
||||||
<el-input maxlength="20" v-model="queryParams.seekName" placeholder="请输入求助人" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.seekName" clearable maxlength="20" placeholder="请输入求助人" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['handleLog:handleLog:add'])"
|
:show-add="checkPermi(['handleLog:handleLog:add'])"
|
||||||
:show-edit="checkPermi(['handleLog:handleLog:edit'])"
|
|
||||||
:show-delete="checkPermi(['handleLog:handleLog:remove'])"
|
:show-delete="checkPermi(['handleLog:handleLog:remove'])"
|
||||||
|
:show-edit="checkPermi(['handleLog:handleLog:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,46 +33,48 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="handleLogList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="handleLogList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="办事内容" align="center" prop="content">
|
<el-table-column align="center" label="办事内容" prop="content">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="color-blue moreRowEllipsis" v-html="scope.row.content"></div>
|
<div class="color-blue moreRowEllipsis">
|
||||||
|
{{ stripHtml(scope.row.content) }}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="求助人" align="center" prop="seekName" width="120" />
|
<el-table-column align="center" label="求助人" prop="seekName" width="120" />
|
||||||
<el-table-column label="联系方式" align="center" prop="phone" width="120" />
|
<el-table-column align="center" label="联系方式" prop="phone" width="120" />
|
||||||
<el-table-column label="办事地点" align="center" prop="handlePosition" />
|
<el-table-column align="center" label="办事时间" prop="handleTime" width="120">
|
||||||
<el-table-column label="办事时间" align="center" prop="handleTime" width="120">
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="附属材料" width="100" align="center" prop="handlePosition">
|
<el-table-column align="center" label="办事地点" prop="handlePosition" />
|
||||||
|
<el-table-column align="center" label="附属材料" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button type="primary" v-if="scope.row.handleLogFileList?.length > 0" @click="openDialog(scope.row)" link>点击查看</el-button>
|
<el-button v-if="scope.row.handleLogFileList?.length > 0" link type="primary" @click="openDialog(scope.row)">点击查看</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="200" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['handleLog:handleLog:edit']">编辑</el-button>
|
<el-button v-has-permi="['handleLog:handleLog:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['handleLog:handleLog:remove']">删除</el-button>
|
<el-button v-has-permi="['handleLog:handleLog:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
<!-- 添加或修改办事记录对话框 -->
|
<!-- 添加或修改办事记录对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<ul class="ulBox" v-if="dialog.files.length > 0">
|
<ul v-if="dialog.files.length > 0" class="ulBox">
|
||||||
<li @click="handleDown(item)" class="files_item" v-for="(item, index) in dialog.files" :key="index">
|
<li v-for="(item, index) in dialog.files" :key="index" class="files_item" @click="handleDown(item)">
|
||||||
<div>
|
<div>
|
||||||
{{ item.fileName }}
|
{{ item.fileName }}
|
||||||
</div>
|
</div>
|
||||||
<span class="clickDown">点击下载</span>
|
<span class="clickDown">点击下载</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="ulBox" v-else>
|
<ul v-else class="ulBox">
|
||||||
<li class="files_item_no">
|
<li class="files_item_no">
|
||||||
<div>暂无数据</div>
|
<div>暂无数据</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -82,10 +84,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="HandleLog" lang="ts">
|
<script lang="ts" name="HandleLog" setup>
|
||||||
import { listHandleLog, delHandleLog } from '@/api/system/HandleLog';
|
import { listHandleLog, delHandleLog } from '@/api/system/HandleLog';
|
||||||
import { HandleLogVO, HandleLogQuery, HandleLogForm, FileVO } from '@/api/system/HandleLog/type';
|
import { HandleLogVO, HandleLogQuery, HandleLogForm, FileVO } from '@/api/system/HandleLog/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
import { stripHtml } from '@/utils/html';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="设施名称" prop="name">
|
<el-form-item label="设施名称" prop="name">
|
||||||
<el-input maxlength="20" v-model.trim="queryParams.name" placeholder="请输入设施名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model.trim="queryParams.name" clearable maxlength="20" placeholder="请输入设施名称" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['houseFacilities:houseFacilities:add'])"
|
:show-add="checkPermi(['houseFacilities:houseFacilities:add'])"
|
||||||
:show-edit="false"
|
:show-delete="checkPermi(['houseFacilities:houseFacilities:remove'])"
|
||||||
:show-delete="false"
|
:show-edit="checkPermi(['houseFacilities:houseFacilities:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,28 +33,28 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="houseFacilitiesList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="houseFacilitiesList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="设施名称" align="center" prop="name" />
|
<el-table-column align="center" label="设施名称" prop="name" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_repair_project_status" :value="scope.row.status"></dict-tag>
|
<dict-tag :options="com_repair_project_status" :value="scope.row.status"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['houseFacilities:houseFacilities:edit']">编辑</el-button>
|
<el-button v-has-permi="['houseFacilities:houseFacilities:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['houseFacilities:houseFacilities:remove']">删除</el-button>
|
<el-button v-has-permi="['houseFacilities:houseFacilities:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="HouseFacilities" lang="ts">
|
<script lang="ts" name="HouseFacilities" setup>
|
||||||
import { listHouseFacilities, delHouseFacilities } from '@/api/system/HouseFacilities';
|
import { listHouseFacilities, delHouseFacilities } from '@/api/system/HouseFacilities';
|
||||||
import { HouseFacilitiesVO, HouseFacilitiesQuery, HouseFacilitiesForm } from '@/api/system/HouseFacilities/type';
|
import { HouseFacilitiesVO, HouseFacilitiesQuery, HouseFacilitiesForm } from '@/api/system/HouseFacilities/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|||||||
@@ -4,17 +4,17 @@
|
|||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" label-position="right" label-width="130px">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="月卡编号" prop="cardCode">
|
<el-form-item label="月卡编号" prop="cardCode">
|
||||||
<el-input maxlength="15" v-model.trim="form.cardCode" placeholder="请输入月卡编号" />
|
<el-input v-model.trim="form.cardCode" maxlength="15" placeholder="请输入月卡编号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="持卡人姓名" prop="cardName">
|
<el-form-item label="持卡人姓名" prop="cardName">
|
||||||
<el-input maxlength="15" v-model.trim="form.cardName" placeholder="请输入持卡人姓名" />
|
<el-input v-model.trim="form.cardName" maxlength="15" placeholder="请输入持卡人姓名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -22,17 +22,18 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="手机号码" prop="phone">
|
<el-form-item label="手机号码" prop="phone">
|
||||||
<el-input maxlength="11" v-model.number="form.phone" placeholder="请输入手机号码" />
|
<el-input v-model.number="form.phone" maxlength="11" placeholder="请输入手机号码" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="绑定车牌号" prop="carNum">
|
<el-form-item label="绑定车牌号" prop="carNum">
|
||||||
<el-input
|
<el-input
|
||||||
maxlength="10"
|
|
||||||
v-model.trim="form.carNum"
|
v-model.trim="form.carNum"
|
||||||
|
maxlength="10"
|
||||||
placeholder="请输入车牌号"
|
placeholder="请输入车牌号"
|
||||||
style="text-transform: uppercase; letter-spacing: 2px"
|
style="text-transform: uppercase; letter-spacing: 2px"
|
||||||
|
@input="handleInputCarNum"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -40,21 +41,23 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="办理人" prop="handleName">
|
<el-form-item label="办理人" prop="handleName">
|
||||||
<el-input maxlength="15" v-model="form.handleName" placeholder="请输入办理人姓名" />
|
<el-input v-model="form.handleName" maxlength="15" placeholder="请输入办理人姓名" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="有效日期" prop="phone">
|
<el-form-item label="有效日期" prop="startTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
|
v-model="checkDate"
|
||||||
|
:disabled-date="disableDate"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
placeholder="选择日期"
|
||||||
range-separator="到"
|
range-separator="到"
|
||||||
start-placeholder="开始日期"
|
start-placeholder="开始日期"
|
||||||
end-placeholder="结束日期"
|
|
||||||
v-model="checkDate"
|
|
||||||
type="daterange"
|
type="daterange"
|
||||||
placeholder="选择日期"
|
|
||||||
@change="handleDate"
|
|
||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
|
@change="handleDate"
|
||||||
|
@clear="handleClear"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -62,7 +65,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="费用" prop="cost">
|
<el-form-item label="费用" prop="cost">
|
||||||
<el-input maxlength="8" v-model.number.trim="form.cost" placeholder="请输入费用">
|
<el-input v-model.number.trim="form.cost" maxlength="8" placeholder="请输入费用">
|
||||||
<template #suffix>元</template>
|
<template #suffix>元</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -70,7 +73,7 @@
|
|||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="支付方式" prop="payMethod">
|
<el-form-item label="支付方式" prop="payMethod">
|
||||||
<el-select v-model="form.payMethod" placeholder="请选择支付方式" clearable>
|
<el-select v-model="form.payMethod" clearable placeholder="请选择支付方式">
|
||||||
<el-option v-for="dict in com_pay_method" :key="dict.value" :label="dict.label" :value="dict.value" />
|
<el-option v-for="dict in com_pay_method" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -79,7 +82,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
<el-input v-model.trim="form.remark" :rows="5" maxlength="200" placeholder="请输入" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -93,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { addMonthCard, getMonthCard, updateMonthCard } from '@/api/system/MonthCard';
|
import { addMonthCard, getMonthCard, updateMonthCard } from '@/api/system/MonthCard';
|
||||||
@@ -120,10 +123,22 @@ const form = ref({
|
|||||||
endTime: '' // 结束日期
|
endTime: '' // 结束日期
|
||||||
});
|
});
|
||||||
const checkDate = ref([]);
|
const checkDate = ref([]);
|
||||||
function handleDate() {
|
// 禁用 过去日期
|
||||||
form.value.startTime = checkDate.value[0];
|
function disableDate(time: Date) {
|
||||||
form.value.endTime = checkDate.value[1];
|
return time.getTime() < new Date(new Date().toLocaleDateString()).getTime();
|
||||||
}
|
}
|
||||||
|
// 处理日期选择
|
||||||
|
function handleDate(data: string[]) {
|
||||||
|
form.value.startTime = data[0] + ' 00:00:00';
|
||||||
|
form.value.endTime = data[1] + ' 23:59:59';
|
||||||
|
}
|
||||||
|
// 清空日期选择
|
||||||
|
function handleClear() {
|
||||||
|
checkDate.value = [];
|
||||||
|
form.value.startTime = '';
|
||||||
|
form.value.endTime = '';
|
||||||
|
}
|
||||||
|
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
cardCode: [
|
cardCode: [
|
||||||
{ required: true, message: '请输入月卡编号', trigger: 'blur' },
|
{ required: true, message: '请输入月卡编号', trigger: 'blur' },
|
||||||
@@ -142,10 +157,17 @@ const rules = ref({
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
handleName: [
|
handleName: [
|
||||||
{ required: true, message: '请输入姓名', trigger: 'blur' },
|
{ required: false, message: '请输入姓名', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
validator: (_: any, value: string | number) => validator(value, 'ChineseName'),
|
validator: (_: any, value: string | number, callback: (error?: Error) => void) => {
|
||||||
message: '请输入正确的中文姓名',
|
if (value === '' || value === null || value === undefined) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
if (!validator(value, 'ChineseName')) {
|
||||||
|
return callback(new Error('请输入正确的中文姓名'));
|
||||||
|
}
|
||||||
|
return callback();
|
||||||
|
},
|
||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -204,6 +226,12 @@ if (route.query.id) {
|
|||||||
checkDate.value = [form.value.startTime, form.value.endTime];
|
checkDate.value = [form.value.startTime, form.value.endTime];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理 车牌号 输入 大写问题
|
||||||
|
function handleInputCarNum(val: string) {
|
||||||
|
form.value.carNum = val.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
// !== 提交 =============================================================================
|
// !== 提交 =============================================================================
|
||||||
// 提交
|
// 提交
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
@@ -233,7 +261,7 @@ const cancelForm = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.AddBuildingBox {
|
.AddBuildingBox {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="月卡编号" prop="cardCode">
|
<el-form-item label="月卡编号" prop="cardCode">
|
||||||
<el-input maxlength="12" v-model="queryParams.cardCode" placeholder="请输入月卡编号" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.cardCode" clearable maxlength="12" placeholder="请输入月卡编号" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['monthCard:monthCard:add'])"
|
:show-add="checkPermi(['monthCard:monthCard:add'])"
|
||||||
:show-edit="checkPermi(['monthCard:monthCard:edit'])"
|
|
||||||
:show-delete="checkPermi(['monthCard:monthCard:remove'])"
|
:show-delete="checkPermi(['monthCard:monthCard:remove'])"
|
||||||
|
:show-edit="checkPermi(['monthCard:monthCard:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,42 +33,42 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="monthCardList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="monthCardList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="月卡编号" align="center" prop="cardCode" v-if="true" />
|
<el-table-column v-if="true" align="center" label="月卡编号" prop="cardCode" />
|
||||||
<el-table-column label="办理时间" align="center" prop="handleTime" width="150">
|
<el-table-column align="center" label="办理时间" prop="handleTime" width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="业主" align="center" prop="cardName" width="150" />
|
<el-table-column align="center" label="业主" prop="cardName" width="150" />
|
||||||
<el-table-column label="绑定车牌号" align="center" prop="carNum" width="150" />
|
<el-table-column align="center" label="绑定车牌号" prop="carNum" width="150" />
|
||||||
<el-table-column label="剩余有效天数" align="center" prop="handleName" width="120">
|
<el-table-column align="center" label="剩余有效天数" prop="handleName" width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ diffDays(scope.row.startTime, scope.row.endTime) }}
|
{{ handleDiffDays(scope.row.startTime, scope.row.endTime) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="支付方式" align="center" prop="payMethod" width="150">
|
<el-table-column align="center" label="支付方式" prop="payMethod" width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_pay_method" :value="scope.row.payMethod" />
|
<dict-tag :options="com_pay_method" :value="scope.row.payMethod" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="备注" show-overflow-tooltip align="center" prop="remark"></el-table-column>
|
<el-table-column align="center" label="备注" prop="remark" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['monthCard:monthCard:edit']">修改</el-button>
|
<el-button v-has-permi="['monthCard:monthCard:edit']" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['monthCard:monthCard:remove']">删除</el-button>
|
<el-button v-has-permi="['monthCard:monthCard:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改月卡管理对话框 -->
|
<!-- 添加或修改月卡管理对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<el-form ref="monthCardFormRef" :model="form" :rules="rules" label-width="80px">
|
<el-form ref="monthCardFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
<el-form-item label="办理时间" prop="handleTime">
|
<el-form-item label="办理时间" prop="handleTime">
|
||||||
<el-date-picker clearable v-model="form.handleTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择办理时间">
|
<el-date-picker v-model="form.handleTime" clearable placeholder="请选择办理时间" type="datetime" value-format="YYYY-MM-DD HH:mm:ss">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="持卡人姓名" prop="cardName">
|
<el-form-item label="持卡人姓名" prop="cardName">
|
||||||
@@ -96,11 +96,11 @@
|
|||||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="开始日期" prop="startTime">
|
<el-form-item label="开始日期" prop="startTime">
|
||||||
<el-date-picker clearable v-model="form.startTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始日期">
|
<el-date-picker v-model="form.startTime" clearable placeholder="请选择开始日期" type="datetime" value-format="YYYY-MM-DD HH:mm:ss">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="结束日期" prop="endTime">
|
<el-form-item label="结束日期" prop="endTime">
|
||||||
<el-date-picker clearable v-model="form.endTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束日期">
|
<el-date-picker v-model="form.endTime" clearable placeholder="请选择结束日期" type="datetime" value-format="YYYY-MM-DD HH:mm:ss">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -114,11 +114,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="MonthCard" lang="ts">
|
<script lang="ts" name="MonthCard" setup>
|
||||||
import { listMonthCard, delMonthCard, addMonthCard, updateMonthCard } from '@/api/system/MonthCard';
|
import { listMonthCard, delMonthCard, addMonthCard, updateMonthCard } from '@/api/system/MonthCard';
|
||||||
import { MonthCardVO, MonthCardQuery, MonthCardForm } from '@/api/system/MonthCard/type';
|
import { MonthCardVO, MonthCardQuery, MonthCardForm } from '@/api/system/MonthCard/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
import { diffDays } from '@/utils/time';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method'));
|
const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method'));
|
||||||
@@ -179,6 +178,32 @@ const data = reactive<PageData<MonthCardForm, MonthCardQuery>>({
|
|||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 一天对应的毫秒数 */
|
||||||
|
const ONE_DAY_MS = 1000 * 60 * 60 * 24;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算月卡剩余有效天数
|
||||||
|
* 规则:
|
||||||
|
* - endTime <= 当前时间 → 已过期,返回 0
|
||||||
|
* - startTime > endTime → 参数非法,返回 0
|
||||||
|
* - 同一天(如 9/2 00:00:00 ~ 9/2 23:59:59)视为 1 天
|
||||||
|
*/
|
||||||
|
function handleDiffDays(startTime: Date | string | number, endTime: Date | string | number): number {
|
||||||
|
const now = Date.now();
|
||||||
|
const start = new Date(startTime).getTime();
|
||||||
|
const end = new Date(endTime).getTime();
|
||||||
|
|
||||||
|
// 非法参数:开始时间晚于结束时间
|
||||||
|
if (start > end) return 0;
|
||||||
|
// 已过期
|
||||||
|
if (end <= now) return 0;
|
||||||
|
|
||||||
|
// 取「开始时间」和「当前时间」中较晚的那个作为计算起点
|
||||||
|
const effectiveStart = Math.max(start, now);
|
||||||
|
const diff = end - effectiveStart;
|
||||||
|
|
||||||
|
return Math.round(diff / ONE_DAY_MS);
|
||||||
|
}
|
||||||
/** 查询月卡管理列表 */
|
/** 查询月卡管理列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|||||||
@@ -12,23 +12,23 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="公告标题" prop="noticeTitle">
|
<el-form-item label="公告标题" prop="noticeTitle">
|
||||||
<el-input maxlength="50" v-model.trim="form.noticeTitle" placeholder="请输入公告标题" />
|
<el-input v-model.trim="form.noticeTitle" maxlength="50" placeholder="请输入公告标题" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="作者" prop="author">
|
||||||
|
<el-input v-model.trim="form.author" placeholder="请输入作者" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- <el-col :span="12">-->
|
|
||||||
<!-- <el-form-item label="作者" prop="author">-->
|
|
||||||
<!-- <el-input v-model.trim="form.author" placeholder="请输入作者" />-->
|
|
||||||
<!-- </el-form-item>-->
|
|
||||||
<!-- </el-col>-->
|
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<!-- <el-col :span="12">-->
|
<el-col :span="12">
|
||||||
<!-- <el-form-item label="公告紧急程度" prop="urgencyLevel">-->
|
<el-form-item label="公告紧急程度" prop="urgencyLevel">
|
||||||
<!-- <el-select v-model="form.urgencyLevel" clearable placeholder="请选择公告紧急程度">-->
|
<el-select v-model="form.urgencyLevel" clearable placeholder="请选择公告紧急程度">
|
||||||
<!-- <el-option v-for="dict in com_noticepc_level" :key="dict.value" :label="dict.label" :value="Number(dict.value)" />-->
|
<el-option v-for="dict in com_noticepc_level" :key="dict.value" :label="dict.label" :value="Number(dict.value)" />
|
||||||
<!-- </el-select>-->
|
</el-select>
|
||||||
<!-- </el-form-item>-->
|
</el-form-item>
|
||||||
<!-- </el-col>-->
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="是否发布" prop="publishStatus">
|
<el-form-item label="是否发布" prop="publishStatus">
|
||||||
<el-radio-group v-model="form.publishStatus">
|
<el-radio-group v-model="form.publishStatus">
|
||||||
@@ -43,13 +43,13 @@
|
|||||||
<el-col>
|
<el-col>
|
||||||
<el-form-item label="公告详情" prop="noticeContent">
|
<el-form-item label="公告详情" prop="noticeContent">
|
||||||
<editor
|
<editor
|
||||||
@update:model-value="handleContent"
|
:file-size="5"
|
||||||
:model-value="form.noticeContent"
|
|
||||||
:height="500"
|
:height="500"
|
||||||
:min-height="300"
|
:min-height="300"
|
||||||
|
:model-value="form.noticeContent"
|
||||||
:read-only="false"
|
:read-only="false"
|
||||||
type="url"
|
type="url"
|
||||||
:file-size="5"
|
@update:model-value="handleContent"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -65,14 +65,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import editor from '@/components/Editor/index.vue';
|
import editor from '@/components/Editor/index.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { addNotice, getNotice } from '@/api/system/NoticePc';
|
import { addNotice, getNotice } from '@/api/system/NoticePc';
|
||||||
import { updateNotice } from '@/api/system/NoticePc';
|
import { updateNotice } from '@/api/system/NoticePc';
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_publish_status } = toRefs<any>(proxy?.useDict('com_publish_status'));
|
const { com_publish_status, com_noticepc_level } = toRefs<any>(proxy?.useDict('com_publish_status', 'com_noticepc_level'));
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -94,7 +94,6 @@ const rules = {
|
|||||||
const userid = ref();
|
const userid = ref();
|
||||||
// ! 富文本 =============================================================================================================
|
// ! 富文本 =============================================================================================================
|
||||||
function handleContent(val: string) {
|
function handleContent(val: string) {
|
||||||
console.log(val);
|
|
||||||
form.value.noticeContent = val.trim();
|
form.value.noticeContent = val.trim();
|
||||||
}
|
}
|
||||||
// ! 富文本 =============================================================================================================
|
// ! 富文本 =============================================================================================================
|
||||||
@@ -139,7 +138,7 @@ function handleBack() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.ResidentMainBox {
|
.ResidentMainBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="公告标题" prop="noticeTitle">
|
<el-form-item label="公告标题" prop="noticeTitle">
|
||||||
<el-input maxlength="30" v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.noticeTitle" clearable maxlength="30" placeholder="请输入公告标题" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -17,15 +17,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card shadow="never" class="flex-1">
|
<el-card class="flex-1" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<right-toolbar
|
<right-toolbar
|
||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['notice:notice:add'])"
|
:show-add="checkPermi(['notice:notice:add'])"
|
||||||
:show-edit="checkPermi(['notice:notice:edit'])"
|
|
||||||
:show-delete="checkPermi(['notice:notice:remove'])"
|
:show-delete="checkPermi(['notice:notice:remove'])"
|
||||||
|
:show-edit="checkPermi(['notice:notice:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,26 +33,26 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="noticeList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="noticeList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="公告标题" align="center" prop="noticeTitle" />
|
<el-table-column align="center" label="公告标题" prop="noticeTitle" />
|
||||||
<!-- <el-table-column label="作者" width="120" align="center" prop="author" />-->
|
<el-table-column align="center" label="作者" prop="author" width="120" />
|
||||||
<!-- <el-table-column label="紧急程度" align="center" prop="urgencyLevel">-->
|
<el-table-column align="center" label="紧急程度" prop="urgencyLevel">
|
||||||
<!-- <template #default="scope">-->
|
<template #default="scope">
|
||||||
<!-- <dict-tag :options="com_noticepc_level" :value="scope.row.urgencyLevel"></dict-tag>-->
|
<dict-tag :options="com_noticepc_level" :value="scope.row.urgencyLevel"></dict-tag>
|
||||||
<!-- </template>-->
|
</template>
|
||||||
<!-- </el-table-column>-->
|
</el-table-column>
|
||||||
<el-table-column label="发布状态" align="center" prop="publishStatus">
|
<el-table-column align="center" label="发布状态" prop="publishStatus">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_publish_status" :value="scope.row.publishStatus"></dict-tag>
|
<dict-tag :options="com_publish_status" :value="scope.row.publishStatus"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="已读" align="center" prop="readNum">
|
<el-table-column align="center" label="已读" prop="readNum">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.readNum ?? '--' }} 人</span>
|
<span>{{ scope.row.readNum ?? '--' }} 人</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="未读" align="center" prop="unReadNum">
|
<el-table-column align="center" label="未读" prop="unReadNum">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.unReadNum ?? '--' }} 人</span>
|
<span>{{ scope.row.unReadNum ?? '--' }} 人</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -63,16 +63,16 @@
|
|||||||
<!-- <span>{{ parseTime(scope.row.publishTime, '{y}-{m}-{d}') }}</span>-->
|
<!-- <span>{{ parseTime(scope.row.publishTime, '{y}-{m}-{d}') }}</span>-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- </el-table-column>-->
|
<!-- </el-table-column>-->
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleMain(scope.row)">详情</el-button>
|
<el-button v-has-permi="['notice:notice:query']" link type="primary" @click="handleMain(scope.row)">详情</el-button>
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['notice:notice:edit']">编辑</el-button>
|
<el-button v-has-permi="['notice:notice:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['notice:notice:remove']">删除</el-button>
|
<el-button v-has-permi="['notice:notice:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog v-model="MainForm.visible" title="公告详情">
|
<el-dialog v-model="MainForm.visible" title="公告详情">
|
||||||
@@ -88,13 +88,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Notice" lang="ts">
|
<script lang="ts" name="Notice" setup>
|
||||||
import { listNotice, delNotice } from '@/api/system/NoticePc';
|
import { listNotice, delNotice } from '@/api/system/NoticePc';
|
||||||
import { NoticeVO, NoticeQuery, NoticeForm } from '@/api/system/NoticePc/type';
|
import { NoticeVO, NoticeQuery, NoticeForm } from '@/api/system/NoticePc/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_publish_status } = toRefs<any>(proxy?.useDict('com_publish_status'));
|
const { com_publish_status, com_noticepc_level } = toRefs<any>(proxy?.useDict('com_publish_status', 'com_noticepc_level'));
|
||||||
|
|
||||||
const noticeList = ref<NoticeVO[]>([]);
|
const noticeList = ref<NoticeVO[]>([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="缴费人" prop="payerName">
|
<el-form-item label="缴费人" prop="payerName">
|
||||||
<el-input maxlength="12" v-model="queryParams.payerName" placeholder="请输入缴费人" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.payerName" clearable maxlength="12" placeholder="请输入缴费人" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="车牌号" prop="carNum">
|
<el-form-item label="车牌号" prop="carNum">
|
||||||
<el-input maxlength="8" v-model="queryParams.carNum" placeholder="请输入车牌号" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.carNum" clearable maxlength="8" placeholder="请输入车牌号" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['parkingCost:parkingCost:add'])"
|
:show-add="checkPermi(['parkingCost:parkingCost:add'])"
|
||||||
:show-edit="checkPermi(['parkingCost:parkingCost:edit'])"
|
|
||||||
:show-delete="checkPermi(['parkingCost:parkingCost:remove'])"
|
:show-delete="checkPermi(['parkingCost:parkingCost:remove'])"
|
||||||
|
:show-edit="checkPermi(['parkingCost:parkingCost:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -36,52 +36,52 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="parkingCostList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="parkingCostList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="车位" align="center" prop="areaId">
|
<el-table-column align="center" label="车位" prop="areaId">
|
||||||
<template #default="scope"> {{ scope.row.name }} </template>
|
<template #default="scope"> {{ scope.row.name }} </template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="收费项目" align="center" prop="chargeItem">
|
<el-table-column align="center" label="收费项目" prop="chargeItem">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_parking_charge" :value="scope.row.chargeItem" />
|
<dict-tag :options="com_parking_charge" :value="scope.row.chargeItem" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="缴纳人" align="center" prop="payerName" />
|
<el-table-column align="center" label="缴纳人" prop="payerName" />
|
||||||
<el-table-column label="车牌号" align="center" prop="carNum" />
|
<el-table-column align="center" label="车牌号" prop="carNum" />
|
||||||
<el-table-column label="停车时长" align="center" width="100">
|
<el-table-column align="center" label="停车时长" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ formatTimeDiff(scope.row.startTime, scope.row.endTime) }}</span>
|
<span>{{ formatTimeDiff(scope.row.startTime, scope.row.endTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="费用" align="center" prop="cost">
|
<el-table-column align="center" label="费用" prop="cost">
|
||||||
<template #default="scope"> {{ Number(scope.row.cost).toFixed(2) }}元 </template>
|
<template #default="scope"> {{ Number(scope.row.cost).toFixed(2) }}元 </template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="缴纳状态" align="center" prop="payerStatus">
|
<el-table-column align="center" label="缴纳状态" prop="payerStatus">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_parking_payer_status" :value="scope.row.payerStatus" />
|
<dict-tag :options="com_parking_payer_status" :value="scope.row.payerStatus" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="支付方式" align="center" prop="payMethod">
|
<!-- <el-table-column label="支付方式" align="center" prop="payMethod">-->
|
||||||
|
<!-- <template #default="scope">-->
|
||||||
|
<!-- <dict-tag v-if="scope.row.payMethod" :options="com_pay_method" :value="scope.row.payMethod" />-->
|
||||||
|
<!-- <span v-else>--</span>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- </el-table-column>-->
|
||||||
|
<el-table-column align="center" label="备注" prop="remark" />
|
||||||
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag v-if="scope.row.payMethod" :options="com_pay_method" :value="scope.row.payMethod" />
|
<el-button v-has-permi="['parkingCost:parkingCost:edit']" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
<span v-else>--</span>
|
<el-button v-has-permi="['parkingCost:parkingCost:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<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-has-permi="['parkingCost:parkingCost:edit']">修改</el-button>
|
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['parkingCost:parkingCost:remove']">删除</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<Pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<Pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="ParkingCost" lang="ts">
|
<script lang="ts" name="ParkingCost" setup>
|
||||||
import Pagination from '@/components/Pagination/index.vue';
|
import Pagination from '@/components/Pagination/index.vue';
|
||||||
import pageHeader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import RightToolbar from '@/components/RightToolbar/index.vue';
|
import RightToolbar from '@/components/RightToolbar/index.vue';
|
||||||
@@ -93,7 +93,6 @@ import { formatTimeDiff } from '@/utils/time';
|
|||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_parking_charge } = toRefs<any>(proxy?.useDict('com_parking_charge'));
|
const { com_parking_charge } = toRefs<any>(proxy?.useDict('com_parking_charge'));
|
||||||
const { com_parking_payer_status } = toRefs<any>(proxy?.useDict('com_parking_payer_status'));
|
const { com_parking_payer_status } = toRefs<any>(proxy?.useDict('com_parking_payer_status'));
|
||||||
const { com_pay_method } = toRefs<any>(proxy?.useDict('com_pay_method'));
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
interface ParkingCostType extends ParkingCostVO {
|
interface ParkingCostType extends ParkingCostVO {
|
||||||
|
|||||||
@@ -1,40 +1,125 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2 h-full flex flex-col">
|
<div class="p-2 h-full flex flex-col">
|
||||||
<div class="container_box flex-1">
|
<PageHeader></PageHeader>
|
||||||
<div class="titlebox flex justify-between items-center">
|
<el-card class="mt-20px" style="min-height: 80px">
|
||||||
<span>问卷内容</span>
|
<div class="flex justify-between">
|
||||||
<el-button link type="primary" @click="router.back()">返回</el-button>
|
<div class="tabs">
|
||||||
|
<div :class="{ 'active': activeTab == 'preview' }" class="tab-item" @click="handleTabClick('preview')">
|
||||||
|
<div class="tab-content">问卷预览</div>
|
||||||
|
</div>
|
||||||
|
<div :class="{ 'active': activeTab == 'detail' }" class="tab-item" @click="handleTabClick('detail')">
|
||||||
|
<div class="tab-content">调查详情</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tabs">
|
||||||
|
<el-button @click="handleBack">返回</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="contentBox h-full" v-loading="viewLoading">
|
</el-card>
|
||||||
|
<div class="flex-1 mt-20px">
|
||||||
|
<el-card v-if="activeTab == 'preview'">
|
||||||
|
<div class="container_box flex-1">
|
||||||
|
<div v-loading="viewLoading" class="contentBox h-full">
|
||||||
|
<div class="detail-header">
|
||||||
|
<h2>{{ viewData.title }}</h2>
|
||||||
|
<p style="color: #666">{{ viewData.description }}</p>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
<div class="detail-content">
|
||||||
|
<div v-for="(q, index) in viewData.content" :key="q.cid" class="question-item">
|
||||||
|
<div class="title">
|
||||||
|
<span style="font-weight: bold">{{ index + 1 }}. {{ q.title }}</span>
|
||||||
|
<span v-if="q.required" style="color: #f56c6c; margin-left: 5px">*</span>
|
||||||
|
</div>
|
||||||
|
<div class="type-tag">
|
||||||
|
<el-tag size="small">{{ getComponentLabel(q.type) }}</el-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 单选题/多选题选项展示 -->
|
||||||
|
<div v-if="q.type === 'radio' || q.type === 'checkbox'" class="options">
|
||||||
|
<div v-for="(opt, idx) in q.options" :key="idx" class="option-item">
|
||||||
|
<span :class="q.type === 'radio' ? 'radio__type' : 'checkbox__type'"></span>
|
||||||
|
<span class="option-label">{{ opt.label }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 填空题/多行文本展示 -->
|
||||||
|
<div v-else-if="q.type === 'input'" class="input-placeholder">
|
||||||
|
<el-input disabled placeholder="用户输入区域" />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="q.type === 'textarea'" class="input-placeholder">
|
||||||
|
<el-input disabled placeholder="用户输入区域" type="textarea" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
<div>
|
||||||
|
<span>备注: {{ viewData.remark ? viewData.remark : '暂无' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card v-else-if="activeTab == 'detail'">
|
||||||
|
<div>
|
||||||
|
<el-table :data="list" style="width: 100%">
|
||||||
|
<el-table-column type="index" />
|
||||||
|
<el-table-column label="答题人" prop="answerName" />
|
||||||
|
<el-table-column label="提交时间" prop="updateTime" />
|
||||||
|
<el-table-column label="操作" prop="options">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="handleGetMain(scope.row.id)">查看详情</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<Pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:total="total"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="680px">
|
||||||
|
<el-form ref="houseRentalFormRef" :model="form.content" label-width="120px">
|
||||||
<div class="detail-header">
|
<div class="detail-header">
|
||||||
<h2>{{ viewData.title }}</h2>
|
<h2>{{ viewData.title }}</h2>
|
||||||
<p style="color: #666">{{ viewData.description }}</p>
|
<p style="color: #666">{{ viewData.description }}</p>
|
||||||
</div>
|
</div>
|
||||||
<el-divider />
|
<el-divider />
|
||||||
<div class="detail-content">
|
<div class="detail-content">
|
||||||
<div v-for="(q, index) in viewData.content" :key="q.cid" class="question-item">
|
<div v-for="(q, index) in form.content" :key="q.cid" class="question-item">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<span style="font-weight: bold">{{ index + 1 }}. {{ q.title }}</span>
|
<span style="font-weight: bold">{{ index + 1 }}. {{ q.title }}</span>
|
||||||
<span style="color: #f56c6c; margin-left: 5px" v-if="q.required">*</span>
|
<span v-if="q.required" style="color: #f56c6c; margin-left: 5px">*</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="type-tag">
|
<div class="type-tag">
|
||||||
<el-tag size="small">{{ getComponentLabel(q.type) }}</el-tag>
|
<el-tag size="small">{{ getComponentLabel(q.type) }}</el-tag>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 单选题/多选题选项展示 -->
|
<!-- 单选题/多选题选项展示 -->
|
||||||
<div v-if="q.type === 'radio' || q.type === 'checkbox'" class="options">
|
<div v-if="q.type === 'radio'" class="options">
|
||||||
<div v-for="(opt, idx) in q.options" :key="idx" class="option-item">
|
<el-radio-group v-model="q.value as string">
|
||||||
<span :class="q.type === 'radio' ? 'radio__type' : 'checkbox__type'"></span>
|
<div>
|
||||||
<span class="option-label">{{ opt.label }}</span>
|
<div v-for="(opt, idx) in q.options" :key="idx">
|
||||||
</div>
|
<el-radio :value="opt.label" disabled>{{ opt.label }}</el-radio>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div v-if="q.type === 'checkbox'" class="options">
|
||||||
|
<el-checkbox-group v-model="q.value as string[]">
|
||||||
|
<div v-for="(opt, idx) in q.options" :key="idx">
|
||||||
|
<el-checkbox :label="opt.label" :value="opt.label" disabled />
|
||||||
|
</div>
|
||||||
|
</el-checkbox-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 填空题/多行文本展示 -->
|
<!-- 填空题/多行文本展示 -->
|
||||||
<div v-else-if="q.type === 'input'" class="input-placeholder">
|
<div v-else-if="q.type === 'input'" class="input-placeholder">
|
||||||
<el-input disabled placeholder="用户输入区域" />
|
<el-input v-model="q.value as string" disabled placeholder="" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="q.type === 'textarea'" class="input-placeholder">
|
<div v-else-if="q.type === 'textarea'" class="input-placeholder">
|
||||||
<el-input disabled type="textarea" placeholder="用户输入区域" />
|
<el-input v-model="q.value as string" disabled placeholder="" type="textarea" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,15 +127,19 @@
|
|||||||
<div>
|
<div>
|
||||||
<span>备注: {{ viewData.remark ? viewData.remark : '暂无' }}</span>
|
<span>备注: {{ viewData.remark ? viewData.remark : '暂无' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</el-form>
|
||||||
</div>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { getQuestionnaire } from '@/api/system/Questionnaire';
|
import { getQuestionnaire, getQuestionnaireAnswer, getQuestionnaireAnswerMain } from '@/api/system/Questionnaire';
|
||||||
import { QuestionComponentItem } from '@/api/system/Questionnaire/type';
|
import { QuestionComponentItem } from '@/api/system/Questionnaire/type';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
|
import QuestionnaireEdit from '@/views/system/Questionnaire/components/QuestionnaireEdit.vue';
|
||||||
|
import Pagination from '@/components/Pagination/index.vue';
|
||||||
|
import { UploadFilled } from '@element-plus/icons-vue';
|
||||||
const viewLoading = ref(false);
|
const viewLoading = ref(false);
|
||||||
const viewData = ref({
|
const viewData = ref({
|
||||||
'id': '',
|
'id': '',
|
||||||
@@ -65,9 +154,21 @@ const viewData = ref({
|
|||||||
'endTime': '2026-04-09 00:00:00',
|
'endTime': '2026-04-09 00:00:00',
|
||||||
'remark': ''
|
'remark': ''
|
||||||
});
|
});
|
||||||
const router = useRouter();
|
const queryParams = ref({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10
|
||||||
|
});
|
||||||
|
const total = ref(0);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
const activeTab = ref<'preview' | 'detail'>('preview');
|
||||||
|
function handleTabClick(tab: 'preview' | 'detail') {
|
||||||
|
activeTab.value = tab;
|
||||||
|
if (activeTab.value === 'detail') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const viewid = ref(null);
|
const viewid = ref(null);
|
||||||
// 组件库定义(用于获取类型名称)
|
// 组件库定义(用于获取类型名称)
|
||||||
const componentList = [
|
const componentList = [
|
||||||
@@ -103,9 +204,75 @@ function init() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
|
const router = useRouter();
|
||||||
|
function handleBack() {
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
type FormQuestionComponentItem = QuestionComponentItem & { value?: string | string[] };
|
||||||
|
const form = ref({
|
||||||
|
id: '',
|
||||||
|
questionnaireId: '',
|
||||||
|
answerContent: [] as FormQuestionComponentItem[],
|
||||||
|
answerId: '',
|
||||||
|
answerName: '',
|
||||||
|
answerStatus: '',
|
||||||
|
content: [] as FormQuestionComponentItem[]
|
||||||
|
});
|
||||||
|
const list = ref([]);
|
||||||
|
function getList() {
|
||||||
|
getQuestionnaireAnswer({
|
||||||
|
pageSize: queryParams.value.pageSize,
|
||||||
|
pageNum: queryParams.value.pageNum,
|
||||||
|
questionnaireId: viewid.value
|
||||||
|
}).then((res) => {
|
||||||
|
list.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function handleGetMain(id: string) {
|
||||||
|
getQuestionnaireAnswerMain(id).then((res) => {
|
||||||
|
form.value = res.data;
|
||||||
|
form.value.answerContent = (JSON.parse(res.data.answerContent) as QuestionComponentItem[]) ?? [];
|
||||||
|
form.value.content = (JSON.parse(res.data.content) as QuestionComponentItem[]) ?? [];
|
||||||
|
form.value.content.forEach((item) => {
|
||||||
|
const find = form.value.answerContent.find((i) => i.cid === item.cid);
|
||||||
|
if (find) {
|
||||||
|
item.value = find.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '问卷调查回答详情';
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: start;
|
||||||
|
.tab-item {
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 10px;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
font-size: 16px;
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
color: #409eff;
|
||||||
|
border-bottom: 4px solid #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.titlebox {
|
.titlebox {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
|
|||||||
@@ -12,31 +12,32 @@
|
|||||||
<el-form-item label="参与范围" prop="cardName">
|
<el-form-item label="参与范围" prop="cardName">
|
||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<el-radio-group v-model="form.scope">
|
<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 v-for="item in com_questionnaire_scope" :key="item.value" :label="item.label" :value="item.value"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<Holder v-if="form.scope === '1'" returnvalue="id" ref="HolderRef" :isMultiple="true" :userid="checkoutUses" @change="handleSelect">
|
<Holder v-if="form.scope === '1'" ref="HolderRef" :isMultiple="true" :userid="checkoutUses" returnvalue="id" @change="handleSelect">
|
||||||
<template #default>
|
<template #default>
|
||||||
<el-button type="primary" link @click="OpenUseTablesFun">选择业主</el-button>
|
<el-button link type="primary" @click="OpenUseTablesFun">选择业主</el-button>
|
||||||
</template>
|
</template>
|
||||||
</Holder>
|
</Holder>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="时间范围" prop="timeData">
|
<el-form-item label="时间范围" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="timeData"
|
v-model="timeData"
|
||||||
style="min-width: 380px"
|
:disabled-date="handleDate"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
end-placeholder="结束日期时间"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
type="datetimerange"
|
placeholder="请选择问卷时间范围"
|
||||||
range-separator="到"
|
range-separator="到"
|
||||||
start-placeholder="开始日期时间"
|
start-placeholder="开始日期时间"
|
||||||
end-placeholder="结束日期时间"
|
style="min-width: 380px"
|
||||||
placeholder="请选择问卷时间范围"
|
type="datetimerange"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@update:model-value="handleModelDate"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input :rows="5" maxlength="200" show-word-limit type="textarea" placeholder="请输入" v-model="form.remark"></el-input>
|
<el-input v-model="form.remark" :rows="5" maxlength="200" placeholder="请输入" show-word-limit type="textarea"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -53,14 +54,14 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<span>问卷题目</span>
|
<span>问卷题目</span>
|
||||||
</template>
|
</template>
|
||||||
<QuestionnaireEdit ref="questionnaireEditRef" :initial-data="editData" @cancel="handleCancel" @save="handleSave" @publish="handlePublish" />
|
<QuestionnaireEdit ref="questionnaireEditRef" :initial-data="editData" @cancel="handleCancel" @publish="handlePublish" @save="handleSave" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import Holder from '@/components/Holder/index.vue';
|
import Holder from '@/components/Holder/index.vue';
|
||||||
import QuestionnaireEdit from './components/QuestionnaireEdit.vue';
|
import QuestionnaireEdit from './components/QuestionnaireEdit.vue';
|
||||||
|
|
||||||
@@ -77,9 +78,19 @@ const route = useRoute();
|
|||||||
const form = ref({
|
const form = ref({
|
||||||
scope: '0',
|
scope: '0',
|
||||||
residents: '',
|
residents: '',
|
||||||
remark: ''
|
remark: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: ''
|
||||||
});
|
});
|
||||||
const timeData = ref([]);
|
const timeData = ref([]);
|
||||||
|
function handleDate(data: string) {
|
||||||
|
const date = new Date(new Date().toLocaleDateString());
|
||||||
|
return date.getTime() > new Date(data).getTime();
|
||||||
|
}
|
||||||
|
function handleModelDate(date: string) {
|
||||||
|
form.value.startTime = date[0];
|
||||||
|
form.value.endTime = date[1];
|
||||||
|
}
|
||||||
// ! 路由参数 --------------------------------------------------------------------------------
|
// ! 路由参数 --------------------------------------------------------------------------------
|
||||||
// 打开
|
// 打开
|
||||||
const HolderRef = ref<InstanceType<typeof Holder>>();
|
const HolderRef = ref<InstanceType<typeof Holder>>();
|
||||||
@@ -126,7 +137,9 @@ function handleEdit(id: string | number) {
|
|||||||
form.value = {
|
form.value = {
|
||||||
scope: res.data.scope,
|
scope: res.data.scope,
|
||||||
residents: res.data.residents,
|
residents: res.data.residents,
|
||||||
remark: res.data.remark
|
remark: res.data.remark,
|
||||||
|
startTime: '',
|
||||||
|
endTime: ''
|
||||||
};
|
};
|
||||||
checkoutUses.value = res.data.residents
|
checkoutUses.value = res.data.residents
|
||||||
.split(',')
|
.split(',')
|
||||||
@@ -138,12 +151,19 @@ function handleEdit(id: string | number) {
|
|||||||
|
|
||||||
// 保存草稿
|
// 保存草稿
|
||||||
async function handleSave(data: QuestionComponentnaireForm) {
|
async function handleSave(data: QuestionComponentnaireForm) {
|
||||||
|
if (timeData.value.length <= 0) {
|
||||||
|
return ElMessage.warning('请选择问卷时间范围');
|
||||||
|
}
|
||||||
|
const list = data.content ?? [];
|
||||||
|
if (list.length <= 0) {
|
||||||
|
return ElMessage.warning('请添加问卷题目');
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// 父组件自己调用接口提交
|
// 父组件自己调用接口提交
|
||||||
if (userid.value !== null) {
|
if (userid.value !== null) {
|
||||||
await updateQuestionnaire({
|
await updateQuestionnaire({
|
||||||
...data,
|
...data,
|
||||||
content: JSON.stringify(data.content),
|
content: JSON.stringify(list),
|
||||||
status: '0', // 草稿状态
|
status: '0', // 草稿状态
|
||||||
startTime: timeData.value[0],
|
startTime: timeData.value[0],
|
||||||
endTime: timeData.value[1],
|
endTime: timeData.value[1],
|
||||||
@@ -152,7 +172,7 @@ async function handleSave(data: QuestionComponentnaireForm) {
|
|||||||
} else {
|
} else {
|
||||||
await addQuestionnaire({
|
await addQuestionnaire({
|
||||||
...data,
|
...data,
|
||||||
content: JSON.stringify(data.content),
|
content: JSON.stringify(list),
|
||||||
status: '0', // 草稿状态
|
status: '0', // 草稿状态
|
||||||
startTime: timeData.value[0],
|
startTime: timeData.value[0],
|
||||||
endTime: timeData.value[1],
|
endTime: timeData.value[1],
|
||||||
@@ -169,11 +189,18 @@ async function handleSave(data: QuestionComponentnaireForm) {
|
|||||||
|
|
||||||
// 发布问卷
|
// 发布问卷
|
||||||
async function handlePublish(data: QuestionComponentnaireForm) {
|
async function handlePublish(data: QuestionComponentnaireForm) {
|
||||||
|
if (timeData.value.length <= 0) {
|
||||||
|
return ElMessage.warning('请选择问卷时间范围');
|
||||||
|
}
|
||||||
|
const list = data.content ?? [];
|
||||||
|
if (list.length <= 0) {
|
||||||
|
return ElMessage.warning('请添加问卷题目');
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (userid.value !== null) {
|
if (userid.value !== null) {
|
||||||
await updateQuestionnaire({
|
await updateQuestionnaire({
|
||||||
...data,
|
...data,
|
||||||
content: JSON.stringify(data.content),
|
content: JSON.stringify(list),
|
||||||
status: '1', // 发布状态
|
status: '1', // 发布状态
|
||||||
startTime: timeData.value[0],
|
startTime: timeData.value[0],
|
||||||
endTime: timeData.value[1],
|
endTime: timeData.value[1],
|
||||||
@@ -182,7 +209,7 @@ async function handlePublish(data: QuestionComponentnaireForm) {
|
|||||||
} else {
|
} else {
|
||||||
await addQuestionnaire({
|
await addQuestionnaire({
|
||||||
...data,
|
...data,
|
||||||
content: JSON.stringify(data.content),
|
content: JSON.stringify(list),
|
||||||
status: '1', // 发布状态
|
status: '1', // 发布状态
|
||||||
endTime: timeData.value[1],
|
endTime: timeData.value[1],
|
||||||
startTime: timeData.value[0],
|
startTime: timeData.value[0],
|
||||||
@@ -202,7 +229,7 @@ function handleCancel() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.AddBuildingBox {
|
.AddBuildingBox {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -3,18 +3,18 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<!-- 左侧:组件库 -->
|
<!-- 左侧:组件库 -->
|
||||||
<el-col :span="4">
|
<el-col :span="4">
|
||||||
<el-card shadow="hover" class="component-panel sticky-card">
|
<el-card class="component-panel sticky-card" shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>组件库</span>
|
<span>组件库</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<draggable
|
<draggable
|
||||||
:list="componentList"
|
|
||||||
:group="{ name: 'components', pull: 'clone', put: false }"
|
|
||||||
:clone="cloneComponent"
|
:clone="cloneComponent"
|
||||||
item-key="type"
|
:group="{ name: 'components', pull: 'clone', put: false }"
|
||||||
|
:list="componentList"
|
||||||
class="component-list"
|
class="component-list"
|
||||||
|
item-key="type"
|
||||||
>
|
>
|
||||||
<template #item="{ element }">
|
<template #item="{ element }">
|
||||||
<div class="component-item">
|
<div class="component-item">
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
<!-- 中间:设计画布 -->
|
<!-- 中间:设计画布 -->
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-card shadow="hover" class="canvas-panel">
|
<el-card class="canvas-panel" shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>设计画布</span>
|
<span>设计画布</span>
|
||||||
@@ -36,24 +36,24 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="question-title-area">
|
<div class="question-title-area">
|
||||||
<el-input maxlength="20" show-word-limit v-model.trim="form.title" placeholder="请输入问卷标题" class="title-input" />
|
<el-input v-model.trim="form.title" class="title-input" maxlength="20" placeholder="请输入问卷标题" show-word-limit />
|
||||||
<el-input maxlength="200" show-word-limit v-model.trim="form.description" type="textarea" placeholder="请输入问卷描述(选填)" />
|
<el-input v-model.trim="form.description" maxlength="200" placeholder="请输入问卷描述(选填)" show-word-limit type="textarea" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<draggable v-model="form.content" group="components" item-key="cid" class="question-list" @add="handleAddQuestion">
|
<draggable v-model="form.content" class="question-list" group="components" item-key="cid" @add="handleAddQuestion">
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<div class="question-item" :class="{ 'is-active': activeIndex === index }" @click="selectQuestion(index)">
|
<div :class="{ 'is-active': activeIndex === index }" class="question-item" @click="selectQuestion(index)">
|
||||||
<div class="question-handle">
|
<div class="question-handle">
|
||||||
<el-icon><Rank /></el-icon>
|
<el-icon><Rank /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="question-content">
|
<div class="question-content">
|
||||||
<el-tag size="small" type="success" class="question-type-tag">
|
<el-tag class="question-type-tag" size="small" type="success">
|
||||||
{{ getComponentLabel(element.type) }}
|
{{ getComponentLabel(element.type) }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<span>Q{{ index + 1 }}. {{ element.title || '未命名题目' }}</span>
|
<span>Q{{ index + 1 }}. {{ element.title || '未命名题目' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="question-actions">
|
<div class="question-actions">
|
||||||
<el-button link type="danger" :icon="Delete" @click.stop="deleteQuestion(index)"> 删除 </el-button>
|
<el-button :icon="Delete" link type="danger" @click.stop="deleteQuestion(index)"> 删除 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -63,16 +63,16 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<!-- 右侧:属性配置 -->
|
<!-- 右侧:属性配置 -->
|
||||||
<el-col style="position: sticky; top: 60px" :span="8">
|
<el-col :span="8" style="position: sticky; top: 60px">
|
||||||
<el-card shadow="hover" class="property-panel sticky-card" v-if="activeQuestion">
|
<el-card v-if="activeQuestion" class="property-panel sticky-card" shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>属性配置</span>
|
<span>属性配置</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-form style="position: sticky; top: 60px" label-width="80px">
|
<el-form :model="activeQuestion" :rules="rules" label-width="80px" style="position: sticky; top: 60px">
|
||||||
<el-form-item label="题目标题">
|
<el-form-item label="题目标题" prop="title">
|
||||||
<el-input maxlength="20" v-model.trim="activeQuestion.title" placeholder="请输入题目标题" />
|
<el-input v-model.trim="activeQuestion.title" maxlength="50" placeholder="请输入题目标题" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="是否必填">
|
<el-form-item label="是否必填">
|
||||||
<el-switch v-model.trim="activeQuestion.required" />
|
<el-switch v-model.trim="activeQuestion.required" />
|
||||||
@@ -82,14 +82,19 @@
|
|||||||
<el-divider content-position="left">选项设置</el-divider>
|
<el-divider content-position="left">选项设置</el-divider>
|
||||||
<div v-for="(opt, idx) in activeQuestion.options" :key="idx" class="option-item">
|
<div v-for="(opt, idx) in activeQuestion.options" :key="idx" class="option-item">
|
||||||
<el-input
|
<el-input
|
||||||
maxlength="20"
|
|
||||||
v-model.trim="opt.label"
|
v-model.trim="opt.label"
|
||||||
|
:class="{ 'is-duplicate': isOptionDuplicate(idx) }"
|
||||||
|
maxlength="20"
|
||||||
placeholder="选项内容"
|
placeholder="选项内容"
|
||||||
style="width: 200px; margin-right: 10px; margin-bottom: 10px"
|
style="width: 200px; margin-right: 10px; margin-bottom: 10px"
|
||||||
|
@blur="handleOptionBlur(idx)"
|
||||||
/>
|
/>
|
||||||
<el-button link type="danger" :icon="Delete" @click="activeQuestion.options.splice(idx, 1)"> 删除 </el-button>
|
<span v-if="isOptionDuplicate(idx)" class="duplicate-tip">选项重复</span>
|
||||||
|
<el-button v-if="activeQuestion.options.length > 2" :icon="Delete" link type="danger" @click="activeQuestion.options.splice(idx, 1)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-button type="primary" @click="activeQuestion.options.push({ label: '新选项' })"> 添加选项 </el-button>
|
<el-button type="primary" @click="addOption">添加选项</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
@@ -106,11 +111,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="QuestionnaireEdit">
|
<script lang="ts" name="QuestionnaireEdit" setup>
|
||||||
import draggable from 'vuedraggable';
|
import draggable from 'vuedraggable';
|
||||||
import { Delete, Rank, Tickets, Document, Edit } from '@element-plus/icons-vue';
|
import { Delete, Rank, Tickets, Document, Edit } from '@element-plus/icons-vue';
|
||||||
import { ComponentItem, QuestionComponentItem, QuestionComponentnaireForm } from '@/api/system/Questionnaire/type';
|
import { ComponentItem, QuestionComponentItem, QuestionComponentnaireForm } from '@/api/system/Questionnaire/type';
|
||||||
import { ElMessage } from 'element-plus'; // 👈 补充引入
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { markRaw } from 'vue';
|
||||||
|
|
||||||
// ==================== Props & Emit ====================
|
// ==================== Props & Emit ====================
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
/** 初始问卷数据(编辑时传入) */
|
/** 初始问卷数据(编辑时传入) */
|
||||||
@@ -125,7 +132,7 @@ const emit = defineEmits<{
|
|||||||
/** 发布问卷 */
|
/** 发布问卷 */
|
||||||
publish: [data: QuestionComponentnaireForm];
|
publish: [data: QuestionComponentnaireForm];
|
||||||
}>();
|
}>();
|
||||||
import { markRaw } from 'vue'; // 👈 引入 markRaw
|
|
||||||
// ==================== 响应式数据 ====================
|
// ==================== 响应式数据 ====================
|
||||||
const componentList = ref<ComponentItem[]>([
|
const componentList = ref<ComponentItem[]>([
|
||||||
{ type: 'radio', label: '单选题', icon: markRaw(Tickets) },
|
{ type: 'radio', label: '单选题', icon: markRaw(Tickets) },
|
||||||
@@ -141,6 +148,10 @@ const form = ref<QuestionComponentnaireForm>({
|
|||||||
content: []
|
content: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rules = ref({
|
||||||
|
title: [{ required: true, message: '请输入问卷标题', trigger: 'blur' }]
|
||||||
|
});
|
||||||
|
|
||||||
const activeIndex = ref<number>(-1);
|
const activeIndex = ref<number>(-1);
|
||||||
|
|
||||||
// ==================== 计算属性 ====================
|
// ==================== 计算属性 ====================
|
||||||
@@ -149,6 +160,46 @@ const activeQuestion = computed<QuestionComponentItem | null>(() => {
|
|||||||
return form.value.content[activeIndex.value];
|
return form.value.content[activeIndex.value];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ==================== 选项重复校验 ====================
|
||||||
|
/** 判断指定选项是否与其他选项内容重复(同一题内,trim 后比对) */
|
||||||
|
function isOptionDuplicate(idx: number): boolean {
|
||||||
|
const options = activeQuestion.value?.options;
|
||||||
|
if (!options) return false;
|
||||||
|
const label = options[idx]?.label?.trim();
|
||||||
|
if (!label) return false;
|
||||||
|
return options.some((opt, i) => i !== idx && opt.label?.trim() === label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 选项失焦时弹提示 */
|
||||||
|
function handleOptionBlur(idx: number): void {
|
||||||
|
if (isOptionDuplicate(idx)) {
|
||||||
|
ElMessage.warning('选项内容不能重复');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加选项:智能生成不冲突的默认名称(避免重名) */
|
||||||
|
function addOption(): void {
|
||||||
|
const options = activeQuestion.value!.options;
|
||||||
|
let nextIndex = options.length + 1;
|
||||||
|
while (options.some((opt) => opt.label === '选项' + nextIndex)) {
|
||||||
|
nextIndex++;
|
||||||
|
}
|
||||||
|
options.push({ label: '选项' + nextIndex });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 遍历所有题目,校验选项是否重复;有重复返回错误信息,否则返回空串 */
|
||||||
|
function validateAllOptions(): string {
|
||||||
|
for (const q of form.value.content) {
|
||||||
|
if (q.type === 'radio' || q.type === 'checkbox') {
|
||||||
|
const labels = q.options.map((o) => o.label?.trim()).filter(Boolean);
|
||||||
|
if (new Set(labels).size !== labels.length) {
|
||||||
|
return `题目「${q.title || '未命名题目'}」存在重复选项`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 辅助方法 ====================
|
// ==================== 辅助方法 ====================
|
||||||
function getComponentLabel(type: string): string {
|
function getComponentLabel(type: string): string {
|
||||||
const item = componentList.value.find((c) => c.type === type);
|
const item = componentList.value.find((c) => c.type === type);
|
||||||
@@ -158,7 +209,7 @@ function getComponentLabel(type: string): string {
|
|||||||
// 克隆组件(用于从左侧拖入中间)
|
// 克隆组件(用于从左侧拖入中间)
|
||||||
function cloneComponent(component: ComponentItem): QuestionComponentItem {
|
function cloneComponent(component: ComponentItem): QuestionComponentItem {
|
||||||
return {
|
return {
|
||||||
cid: Date.now(), // 生成唯一ID
|
cid: Date.now(),
|
||||||
type: component.type,
|
type: component.type,
|
||||||
title: '',
|
title: '',
|
||||||
required: true,
|
required: true,
|
||||||
@@ -173,7 +224,6 @@ function selectQuestion(index: number): void {
|
|||||||
|
|
||||||
// 添加题目后的处理
|
// 添加题目后的处理
|
||||||
function handleAddQuestion(evt: any): void {
|
function handleAddQuestion(evt: any): void {
|
||||||
// 自动选中新添加的题目
|
|
||||||
activeIndex.value = evt.newIndex;
|
activeIndex.value = evt.newIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,6 +244,15 @@ function validateForm(): boolean {
|
|||||||
ElMessage.error('请输入问卷标题');
|
ElMessage.error('请输入问卷标题');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (form.value.content.some((item) => !item.title?.trim())) {
|
||||||
|
ElMessage.error('请填写所有题目标题');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const duplicateMsg = validateAllOptions();
|
||||||
|
if (duplicateMsg) {
|
||||||
|
ElMessage.error(duplicateMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +283,6 @@ function init(data: Partial<QuestionComponentnaireForm>): void {
|
|||||||
...data
|
...data
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理content字符串转对象(如果是从数据库取的)
|
|
||||||
if (typeof form.value.content === 'string') {
|
if (typeof form.value.content === 'string') {
|
||||||
try {
|
try {
|
||||||
form.value.content = JSON.parse(form.value.content);
|
form.value.content = JSON.parse(form.value.content);
|
||||||
@@ -249,7 +307,6 @@ function reset(): void {
|
|||||||
|
|
||||||
// ==================== 生命周期 ====================
|
// ==================== 生命周期 ====================
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 如果传入了初始数据,自动初始化
|
|
||||||
if (props.initialData) {
|
if (props.initialData) {
|
||||||
init(props.initialData);
|
init(props.initialData);
|
||||||
}
|
}
|
||||||
@@ -259,7 +316,7 @@ onMounted(() => {
|
|||||||
defineExpose({ init, reset });
|
defineExpose({ init, reset });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.edit-container {
|
.edit-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@@ -320,8 +377,27 @@ defineExpose({ init, reset });
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.canvas-panel {
|
.canvas-panel {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.option-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.is-duplicate {
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
box-shadow: 0 0 0 1px #f56c6c inset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.duplicate-tip {
|
||||||
|
color: #f56c6c;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.footer-actions {
|
.footer-actions {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="问卷标题" prop="title">
|
<el-form-item label="问卷标题" prop="title">
|
||||||
<el-input maxlength="20" v-model="queryParams.title" placeholder="请输入问卷标题" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.title" clearable maxlength="20" placeholder="请输入问卷标题" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="参与范围" prop="scope">
|
<!-- <el-form-item label="参与范围" prop="scope">
|
||||||
<el-input v-model="queryParams.scope" placeholder="请输入参与范围 0全体业主 1部分业主" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.scope" placeholder="请输入参与范围 0全体业主 1部分业主" clearable @keyup.enter="handleQuery" />
|
||||||
@@ -26,8 +26,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['questionnaire:questionnaire:add'])"
|
:show-add="checkPermi(['questionnaire:questionnaire:add'])"
|
||||||
:show-edit="checkPermi(['questionnaire:questionnaire:edit'])"
|
|
||||||
:show-delete="checkPermi(['questionnaire:questionnaire:remove'])"
|
:show-delete="checkPermi(['questionnaire:questionnaire:remove'])"
|
||||||
|
:show-edit="checkPermi(['questionnaire:questionnaire:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -35,36 +35,50 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="questionnaireList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="questionnaireList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="问卷标题" align="center" prop="title" />
|
<el-table-column align="center" label="小区" prop="villageName" />
|
||||||
<el-table-column label="问卷描述" align="center" prop="description" />
|
<el-table-column align="center" label="问卷标题" prop="title" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column align="center" label="问卷描述" prop="description" />
|
||||||
|
|
||||||
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_questionnaire_status" :value="scope.row.status"></dict-tag>
|
<dict-tag :options="com_questionnaire_status" :value="scope.row.status"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="参与范围" align="center" prop="scope">
|
<el-table-column align="center" label="参与范围" prop="scope">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_questionnaire_scope" :value="scope.row.scope"></dict-tag>
|
<dict-tag :options="com_questionnaire_scope" :value="scope.row.scope"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="备注" align="center" prop="remark" />
|
<el-table-column align="center" label="问题数量" prop="questionCount" />
|
||||||
<el-table-column label="操作" align="center" fixed="right" width="200">
|
<el-table-column align="center" label="发布时间" prop="updateTime" />
|
||||||
|
<el-table-column align="center" label="结束时间" prop="endTime" />
|
||||||
|
<el-table-column align="center" label="已答数量" prop="answeredCount" />
|
||||||
|
<el-table-column align="center" label="未答数量" prop="unansweredCount" />
|
||||||
|
<el-table-column align="center" label="备注" prop="remark" />
|
||||||
|
<el-table-column align="center" fixed="right" label="操作" width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleView(scope.row)" v-has-permi="['questionnaire:questionnaire:query']">查看</el-button>
|
<el-button v-has-permi="['questionnaire:questionnaire:query']" link type="primary" @click="handleView(scope.row)">查看</el-button>
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['questionnaire:questionnaire:edit']">编辑</el-button>
|
<el-button
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['questionnaire:questionnaire:remove']">删除</el-button>
|
v-if="scope.row.status === '0'"
|
||||||
|
v-has-permi="['questionnaire:questionnaire:edit']"
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
>编辑</el-button
|
||||||
|
>
|
||||||
|
<el-button v-has-permi="['questionnaire:questionnaire:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<Pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<Pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Questionnaire" lang="ts">
|
<script lang="ts" name="Questionnaire" setup>
|
||||||
import Pagination from '@/components/Pagination/index.vue';
|
import Pagination from '@/components/Pagination/index.vue';
|
||||||
import pageHeader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import RightToolbar from '@/components/RightToolbar/index.vue';
|
import RightToolbar from '@/components/RightToolbar/index.vue';
|
||||||
@@ -72,13 +86,17 @@ import DictTag from '@/components/DictTag/index.vue';
|
|||||||
import { listQuestionnaire, delQuestionnaire, addQuestionnaire, updateQuestionnaire } from '@/api/system/Questionnaire';
|
import { listQuestionnaire, delQuestionnaire, addQuestionnaire, updateQuestionnaire } from '@/api/system/Questionnaire';
|
||||||
import { QuestionnaireVO, QuestionnaireQuery, QuestionnaireForm } from '@/api/system/Questionnaire/type';
|
import { QuestionnaireVO, QuestionnaireQuery, QuestionnaireForm } from '@/api/system/Questionnaire/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
import type { communitylist_rows_type } from '@/api/system/community/type';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
||||||
const { com_questionnaire_status } = toRefs<any>(proxy?.useDict('com_questionnaire_status'));
|
const { com_questionnaire_status } = toRefs<any>(proxy?.useDict('com_questionnaire_status'));
|
||||||
|
type QuestionVoList = QuestionnaireVO & {
|
||||||
const questionnaireList = ref<QuestionnaireVO[]>([]);
|
contentLength?: number;
|
||||||
|
villageName?: string;
|
||||||
|
};
|
||||||
|
const questionnaireList = ref<QuestionVoList[]>([]);
|
||||||
const buttonLoading = ref(false);
|
const buttonLoading = ref(false);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
@@ -125,9 +143,15 @@ const { queryParams, form, rules } = toRefs(data);
|
|||||||
/** 查询问卷调查列表 */
|
/** 查询问卷调查列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
const villageInfo = localStorage.getItem('villageInfo') as string;
|
||||||
listQuestionnaire(queryParams.value)
|
listQuestionnaire(queryParams.value)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
questionnaireList.value = res.rows;
|
questionnaireList.value = res.rows;
|
||||||
|
questionnaireList.value.forEach((item) => {
|
||||||
|
item.contentLength = JSON.parse(item.content as string).length ?? 0;
|
||||||
|
item.villageName = JSON.parse(villageInfo).villageName;
|
||||||
|
return item;
|
||||||
|
});
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -217,18 +241,25 @@ const handleDelete = async (row?: QuestionnaireVO) => {
|
|||||||
await proxy?.$modal
|
await proxy?.$modal
|
||||||
.confirm('是否确认删除问卷调查?')
|
.confirm('是否确认删除问卷调查?')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
delQuestionnaire(_ids, true).catch(async (res) => {
|
delQuestionnaire(_ids, true)
|
||||||
const content = res.msg.replace(/\n/g, '<br/>');
|
.catch(async (res) => {
|
||||||
await proxy?.$modal
|
const content = res.msg.replace(/\n/g, '<br/>');
|
||||||
.confirm(content)
|
await proxy?.$modal
|
||||||
.then(() => {
|
.confirm(content)
|
||||||
delQuestionnaire(_ids, false).then(() => {
|
.then(() => {
|
||||||
proxy?.$modal.msgSuccess('删除成功');
|
delQuestionnaire(_ids, false).then(() => {
|
||||||
getList();
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
});
|
getList();
|
||||||
})
|
});
|
||||||
.finally(() => (loading.value = false));
|
})
|
||||||
});
|
.finally(() => (loading.value = false));
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.msg === '操作成功') {
|
||||||
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,50 +4,50 @@
|
|||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" label-position="right" label-width="130px">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col v-if="type === 'private'" :span="11">
|
||||||
<el-form-item label="关联房屋" prop="houseId">
|
<el-form-item label="关联房屋" prop="houseId">
|
||||||
<el-cascader v-model="form.houseId" :options="treedata" @change="handleChangeHouse" />
|
<el-cascader v-model="form.houseId" :options="treeData" @change="handleChangeHouse" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2"></el-col>
|
<el-col v-if="type === 'private'" :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="维修项目" prop="maintenanceItemId">
|
<el-form-item label="维修项目" prop="maintenanceItemId">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
|
v-model="form.maintenanceItemId"
|
||||||
|
:options="maintenanceItemTreeData"
|
||||||
:props="{
|
:props="{
|
||||||
label: 'projectName',
|
label: 'projectName',
|
||||||
value: 'id'
|
value: 'id'
|
||||||
}"
|
}"
|
||||||
v-model="form.maintenanceItemId"
|
|
||||||
placeholder="请选择维修项目"
|
placeholder="请选择维修项目"
|
||||||
:options="maintenanceItemTreeData"
|
|
||||||
@change="handleChangeMaintenanceItem"
|
@change="handleChangeMaintenanceItem"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<!-- <el-row>-->
|
||||||
<el-col :span="24">
|
<!-- <el-col :span="24">-->
|
||||||
<el-form-item label="报修标题" prop="item">
|
<!-- <el-form-item label="报修标题" prop="item">-->
|
||||||
<el-input maxlength="30" v-model.trim="form.item" placeholder="请输入报修标题" />
|
<!-- <el-input maxlength="30" v-model.trim="form.item" placeholder="请输入报修标题" />-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
</el-col>
|
<!-- </el-col>-->
|
||||||
</el-row>
|
<!-- </el-row>-->
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="问题描述" prop="problem">
|
<el-form-item label="问题描述" prop="problem">
|
||||||
<el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.problem" placeholder="请输入问题描述" />
|
<el-input v-model.trim="form.problem" :rows="5" maxlength="200" placeholder="请输入问题描述" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="20">
|
<el-col :span="20">
|
||||||
<el-form-item label="报修人" prop="residentId">
|
<el-form-item label="报修人" prop="residentId">
|
||||||
<Holder :isMultiple="false" :userid="form.residentId ?? ''" ref="HolderRef" @change="handleChange">
|
<Holder ref="HolderRef" :isMultiple="false" :userid="form.residentId ?? ''" @change="handleChange">
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="residentBox" @click="choiceResidentFun">
|
<div class="residentBox" @click="choiceResidentFun">
|
||||||
<div class="defaultBox" v-if="form.residentId === '' || form.residentId === null">
|
<div v-if="form.residentId === '' || form.residentId === null" class="defaultBox">
|
||||||
<span>请选择</span>
|
<span>请选择</span>
|
||||||
<el-icon><Search /></el-icon>
|
<el-icon><Search /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,14 +63,20 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="手机号码" prop="phone">
|
<el-form-item label="手机号码" prop="phone">
|
||||||
<el-input v-model.number="form.phone" placeholder="请输入手机号码" />
|
<el-input v-model.number.trim="form.phone" placeholder="请输入手机号码" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="预约日期" prop="orderDate">
|
<el-form-item label="预约日期" prop="orderDate">
|
||||||
<el-date-picker v-model="form.orderDate" type="datetime" placeholder="年/月/日 时:分:秒" value-format="YYYY-MM-DD HH:mm:ss" />
|
<el-date-picker
|
||||||
|
v-model="form.orderDate"
|
||||||
|
:disabled-date="disabledDate"
|
||||||
|
placeholder="年/月/日 时:分:秒"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -81,17 +87,17 @@
|
|||||||
<el-upload
|
<el-upload
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
:action="uploadUrl"
|
:action="uploadUrl"
|
||||||
list-type="picture-card"
|
:before-upload="handleChangeFile"
|
||||||
:limit="9"
|
:limit="9"
|
||||||
:on-exceed="handleExceed"
|
:on-exceed="handleExceed"
|
||||||
:on-preview="handlePictureCardPreview"
|
:on-preview="handlePictureCardPreview"
|
||||||
:on-remove="handleRemove"
|
:on-remove="handleRemove"
|
||||||
:before-upload="handleChangeFile"
|
list-type="picture-card"
|
||||||
>
|
>
|
||||||
<el-icon><Plus /></el-icon>
|
<el-icon><Plus /></el-icon>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<el-dialog v-model="dialogVisible">
|
<el-dialog v-model="dialogVisible">
|
||||||
<img w-full :src="dialogImageUrl" alt="Preview Image" />
|
<img :src="dialogImageUrl" alt="Preview Image" w-full />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -106,7 +112,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { hasFormData } from '@/utils/house';
|
import { hasFormData } from '@/utils/house';
|
||||||
@@ -120,7 +126,7 @@ import { Plus } from '@element-plus/icons-vue';
|
|||||||
import { RepairProjectVO } from '@/api/system/RepairProject/type';
|
import { RepairProjectVO } from '@/api/system/RepairProject/type';
|
||||||
|
|
||||||
const houseStore = useHouseStore();
|
const houseStore = useHouseStore();
|
||||||
const { treedata } = storeToRefs(houseStore);
|
const treeData = ref([]);
|
||||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/repair/uploadImages';
|
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/repair/uploadImages';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -142,8 +148,13 @@ const form = ref({
|
|||||||
repairImageUrl: '', // 维修图片url
|
repairImageUrl: '', // 维修图片url
|
||||||
orderDate: '' // 预约日期
|
orderDate: '' // 预约日期
|
||||||
});
|
});
|
||||||
|
const type = ref('private');
|
||||||
|
onMounted(() => {
|
||||||
|
type.value = (route.query.type as 'public' | 'private') || 'private';
|
||||||
|
init();
|
||||||
|
});
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
houseId: [{ required: true, message: '请选择关联房屋', trigger: 'blur' }],
|
houseId: [{ required: type.value === 'private', message: '请选择关联房屋', trigger: 'blur' }],
|
||||||
maintenanceItemId: [{ required: true, message: '请选择维修项目', trigger: 'blur' }],
|
maintenanceItemId: [{ required: true, message: '请选择维修项目', trigger: 'blur' }],
|
||||||
phone: [
|
phone: [
|
||||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||||
@@ -155,11 +166,20 @@ const rules = ref({
|
|||||||
],
|
],
|
||||||
problem: [{ required: true, message: '请输入问题描述', trigger: 'blur' }]
|
problem: [{ required: true, message: '请输入问题描述', trigger: 'blur' }]
|
||||||
});
|
});
|
||||||
|
|
||||||
const userid = ref(null);
|
const userid = ref(null);
|
||||||
|
|
||||||
// 报修项目 tree 结构
|
// 报修项目 tree 结构
|
||||||
const maintenanceItemTreeData = ref();
|
const maintenanceItemTreeData = ref();
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
gettreelistRepairProject().then((res) => {
|
const obj = {
|
||||||
|
projectType: type.value === 'private' ? '1' : '0'
|
||||||
|
};
|
||||||
|
houseStore.getCurrentVilageTreeHouse().then((res) => {
|
||||||
|
treeData.value = res;
|
||||||
|
});
|
||||||
|
gettreelistRepairProject(obj).then((res) => {
|
||||||
maintenanceItemTreeData.value = handleTreeDisable(res.data);
|
maintenanceItemTreeData.value = handleTreeDisable(res.data);
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
userid.value = route.query.id;
|
userid.value = route.query.id;
|
||||||
@@ -183,7 +203,6 @@ function init() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
init();
|
|
||||||
|
|
||||||
function handleTreeDisable(TreeData: RepairProjectVO[]) {
|
function handleTreeDisable(TreeData: RepairProjectVO[]) {
|
||||||
return TreeData.map((item) => {
|
return TreeData.map((item) => {
|
||||||
@@ -195,15 +214,13 @@ function handleTreeDisable(TreeData: RepairProjectVO[]) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! 上传图片 =--==================================================================
|
// ! 上传图片 ===================================================================
|
||||||
const fileList = ref<UploadUserFile[]>([]);
|
const fileList = ref<UploadUserFile[]>([]);
|
||||||
|
|
||||||
const dialogImageUrl = ref('');
|
const dialogImageUrl = ref('');
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
|
|
||||||
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
|
const handleRemove: UploadProps['onRemove'] = () => {};
|
||||||
console.log(uploadFile, uploadFiles);
|
|
||||||
};
|
|
||||||
const blockedExits = ['.exe', '.bat', '.cmd', '.msi'];
|
const blockedExits = ['.exe', '.bat', '.cmd', '.msi'];
|
||||||
const allUploadExits = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'];
|
const allUploadExits = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'];
|
||||||
const handleChangeFile: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
const handleChangeFile: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||||
@@ -231,7 +248,10 @@ const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
|
|||||||
const holderInfo = ref(null);
|
const holderInfo = ref(null);
|
||||||
const HolderRef = ref<typeof Holder>(null);
|
const HolderRef = ref<typeof Holder>(null);
|
||||||
function choiceResidentFun() {
|
function choiceResidentFun() {
|
||||||
HolderRef.value.open([form.value.residentId]);
|
HolderRef.value.open([form.value.residentId], {
|
||||||
|
ownerRelationship: '0',
|
||||||
|
status: '1'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// 选择住户
|
// 选择住户
|
||||||
function handleChange(pop) {
|
function handleChange(pop) {
|
||||||
@@ -239,9 +259,11 @@ function handleChange(pop) {
|
|||||||
holderInfo.value = pop;
|
holderInfo.value = pop;
|
||||||
form.value.residentId = '';
|
form.value.residentId = '';
|
||||||
form.value.residentName = '';
|
form.value.residentName = '';
|
||||||
|
form.value.phone = null;
|
||||||
if (pop !== null) {
|
if (pop !== null) {
|
||||||
form.value.residentId = holderInfo.value.id;
|
form.value.residentId = holderInfo.value.id;
|
||||||
form.value.residentName = holderInfo.value.name;
|
form.value.residentName = holderInfo.value.name;
|
||||||
|
form.value.phone = holderInfo.value.phone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,6 +323,11 @@ const submitForm = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 禁用日期
|
||||||
|
const disabledDate = (time: Date) => {
|
||||||
|
return time.getTime() <= Date.now();
|
||||||
|
};
|
||||||
|
|
||||||
const sendForm = (str: string) => {
|
const sendForm = (str: string) => {
|
||||||
form.value.problemImageUrl = str;
|
form.value.problemImageUrl = str;
|
||||||
if (userid.value) {
|
if (userid.value) {
|
||||||
@@ -321,7 +348,7 @@ const cancelForm = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.AddBuildingBox {
|
.AddBuildingBox {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -345,7 +372,7 @@ const cancelForm = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.formBody {
|
.formBody {
|
||||||
width: 1050px;
|
width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
&:deep(.el-date-editor.el-input) {
|
&:deep(.el-date-editor.el-input) {
|
||||||
|
|||||||
@@ -4,20 +4,20 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="报修状态" prop="problemStatus">
|
<el-form-item label="报修状态" prop="problemStatus">
|
||||||
<el-select v-model="queryParams.problemStatus" placeholder="请选择" clearable>
|
<el-select v-model="queryParams.problemStatus" clearable placeholder="请选择">
|
||||||
<el-option v-for="dict in com_repair_status" :key="dict.value" :label="dict.label" :value="dict.value" />
|
<el-option v-for="dict in com_repair_status" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="预约日期" prop="maintenanceItemId">
|
<el-form-item label="预约日期" prop="maintenanceItemId">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
clearable
|
|
||||||
v-model="queryParams.orderDate"
|
v-model="queryParams.orderDate"
|
||||||
|
clearable
|
||||||
|
format="YYYY-MM-DD"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
type="date"
|
type="date"
|
||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
format="YYYY-MM-DD"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -36,54 +36,58 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['repair:repair:add'])"
|
:show-add="checkPermi(['repair:repair:add'])"
|
||||||
:show-edit="checkPermi(['repair:repair:edit'])"
|
|
||||||
:show-delete="checkPermi(['repair:repair:remove'])"
|
:show-delete="checkPermi(['repair:repair:remove'])"
|
||||||
|
:show-edit="checkPermi(['repair:repair:edit'])"
|
||||||
|
add-title="个人报修"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
></right-toolbar>
|
>
|
||||||
|
<template #actions>
|
||||||
|
<el-button v-hasPermi="['repair:repair:add']" icon="Plus" type="default" @click="handleAdd('public')">公共报修</el-button>
|
||||||
|
</template>
|
||||||
|
</right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="repairList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="repairList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="报修房屋" align="center" show-overflow-tooltip prop="houseName" />
|
<el-table-column align="center" label="报修房屋" prop="houseName" show-overflow-tooltip />
|
||||||
<el-table-column label="维修项目" align="center" prop="maintenanceItemName" />
|
<el-table-column align="center" label="维修项目" prop="maintenanceItemName" />
|
||||||
<el-table-column label="问题描述" align="center" prop="problem" />
|
<el-table-column align="center" label="问题描述" prop="problem" />
|
||||||
<el-table-column label="报修人" width="100" align="center" prop="residentName" />
|
<el-table-column align="center" label="报修人" prop="residentName" width="100" />
|
||||||
<el-table-column label="联系电话" width="120" align="center" prop="phone" />
|
<el-table-column align="center" label="联系电话" prop="phone" width="120" />
|
||||||
<el-table-column label="维修人员" width="100" align="center" prop="repairName">
|
<el-table-column align="center" label="维修人员" prop="repairName" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.repairName ?? '---' }}</span>
|
<span>{{ scope.row.repairName ?? '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="预约日期" align="center" prop="orderDate" width="150">
|
<el-table-column align="center" label="预约日期" prop="orderDate" width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.orderDate, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.orderDate, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="维修状态" align="center" width="100" prop="problemStatus">
|
<el-table-column align="center" label="维修状态" prop="problemStatus" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_repair_status" :value="scope.row.problemStatus || ''"></dict-tag>
|
<dict-tag :options="com_repair_status" :value="scope.row.problemStatus || ''"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleShare(scope.row)" v-has-permi="['repair:repair:query']">{{
|
<el-button v-has-permi="['repair:repair:query']" link type="primary" @click="handleShare(scope.row)">{{
|
||||||
scope.row.problemStatus === '0' ? '分配' : '详情'
|
scope.row.problemStatus === '0' ? '分配' : '详情'
|
||||||
}}</el-button>
|
}}</el-button>
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['repair:repair:edit']">编辑</el-button>
|
<el-button v-has-permi="['repair:repair:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['repair:repair:remove']">删除</el-button>
|
<el-button v-has-permi="['repair:repair:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Repair" lang="ts">
|
<script lang="ts" name="Repair" setup>
|
||||||
import Pagination from '@/components/Pagination/index.vue';
|
import Pagination from '@/components/Pagination/index.vue';
|
||||||
import pageHeader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import RightToolbar from '@/components/RightToolbar/index.vue';
|
import RightToolbar from '@/components/RightToolbar/index.vue';
|
||||||
@@ -190,19 +194,40 @@ const handleSelectionChange = (selection: RepairVO[]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = (type: 'public' | 'private' = 'private') => {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/repair/addRepair'
|
path: '/repair/addRepair',
|
||||||
|
query: {
|
||||||
|
type
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = (row?: RepairVO) => {
|
const handleUpdate = (row?: RepairVO) => {
|
||||||
const _id = row?.id || ids.value[0];
|
const _id = row?.id || ids.value[0];
|
||||||
|
let type: string;
|
||||||
|
// 如果有行数据,根据houseId判断类型
|
||||||
|
if (row) {
|
||||||
|
if (row.houseId) {
|
||||||
|
type = 'private';
|
||||||
|
} else {
|
||||||
|
type = 'public';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 多选编辑时,根据第一个选中的行判断类型
|
||||||
|
const item = repairList.value.find((item) => item.id === _id);
|
||||||
|
if (item) {
|
||||||
|
type = item.houseId ? 'private' : 'public';
|
||||||
|
} else {
|
||||||
|
type = 'private';
|
||||||
|
}
|
||||||
|
}
|
||||||
router.push({
|
router.push({
|
||||||
path: '/repair/editRepair',
|
path: '/repair/editRepair',
|
||||||
query: {
|
query: {
|
||||||
id: _id
|
id: _id,
|
||||||
|
type
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="ResidentMainBox p-2 w-full">
|
<div class="ResidentMainBox p-2 w-full">
|
||||||
<PageHeader title="报修详情"></PageHeader>
|
<PageHeader title="报修详情"></PageHeader>
|
||||||
<div class="ResidentMainBody">
|
<div class="ResidentMainBody">
|
||||||
<el-row :span="24" :gutter="20">
|
<el-row :gutter="20" :span="24">
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<!-- 车位信息 -->
|
<!-- 车位信息 -->
|
||||||
<div class="mb-10">
|
<div class="mb-10">
|
||||||
@@ -69,20 +69,20 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<div class="carInfo_Item">
|
<div class="carInfo_Item">
|
||||||
<div class="label">附件:</div>
|
<div class="label">附件:</div>
|
||||||
<div class="main fileImagebox" v-if="form.problemImageUrlList.length > 0">
|
<div v-if="form.problemImageUrlList.length > 0" class="main fileImagebox">
|
||||||
<el-image
|
<el-image
|
||||||
:preview-teleported="true"
|
v-for="(item, index) in form.problemImageUrlList"
|
||||||
:zoom-rate="1.2"
|
:key="index"
|
||||||
|
:initial-index="index"
|
||||||
:max-scale="7"
|
:max-scale="7"
|
||||||
:min-scale="0.2"
|
:min-scale="0.2"
|
||||||
:preview-src-list="form.problemImageUrlList"
|
:preview-src-list="form.problemImageUrlList"
|
||||||
show-progress
|
:preview-teleported="true"
|
||||||
v-for="(item, index) in form.problemImageUrlList"
|
|
||||||
:initial-index="index"
|
|
||||||
:key="index"
|
|
||||||
:src="item"
|
:src="item"
|
||||||
lazy
|
:zoom-rate="1.2"
|
||||||
class="carInfoImage"
|
class="carInfoImage"
|
||||||
|
lazy
|
||||||
|
show-progress
|
||||||
></el-image>
|
></el-image>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,10 +100,10 @@
|
|||||||
<div class="repair w-full h-full flex flex-items-start mt-2">
|
<div class="repair w-full h-full flex flex-items-start mt-2">
|
||||||
<div class="title">维修师傅</div>
|
<div class="title">维修师傅</div>
|
||||||
<div class="preivewBodybox flex-1 ml-5">
|
<div class="preivewBodybox flex-1 ml-5">
|
||||||
<repairUser :is-multiple="false" :username="form.repairName" :userid="form.repairUserId" @change="handleChange"> </repairUser>
|
<repairUser :is-multiple="false" :userid="form.repairUserId" :username="form.repairName" @change="handleChange"> </repairUser>
|
||||||
<div class="actions mt-5">
|
<div class="actions mt-5">
|
||||||
<el-button v-if="form.problemStatus === '0'" @click="handleSend" type="primary">确定派单</el-button>
|
<el-button v-if="form.problemStatus === '0'" type="primary" @click="handleSend">确定派单</el-button>
|
||||||
<el-button v-if="form.problemStatus === '1'" @click="handleChangeRepairUser" type="primary">变更人员</el-button>
|
<el-button v-if="form.problemStatus === '1'" type="primary" @click="handleChangeRepairUser">变更人员</el-button>
|
||||||
<el-button @click="backRouter">返回</el-button>
|
<el-button @click="backRouter">返回</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import StepTimeline, { StepItem } from '@/components/StepTimeline/index.vue';
|
import StepTimeline, { StepItem } from '@/components/StepTimeline/index.vue';
|
||||||
import repairUser from '@/components/Holder/repairUser.vue';
|
import repairUser from '@/components/Holder/repairUser.vue';
|
||||||
@@ -222,7 +222,7 @@ async function init() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理审核╬╬
|
// 处理审核
|
||||||
function handleReview() {
|
function handleReview() {
|
||||||
if (reviewInfo.value.submitStatus === '1') {
|
if (reviewInfo.value.submitStatus === '1') {
|
||||||
// 提交完成
|
// 提交完成
|
||||||
@@ -315,7 +315,7 @@ function handleEdit() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.ResidentMainBox {
|
.ResidentMainBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -4,56 +4,47 @@
|
|||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" label-position="right" label-width="130px">
|
||||||
<el-form-item label="项目名称" prop="itemName">
|
<el-form-item label="项目名称" prop="itemName">
|
||||||
<el-input maxlength="20" v-model.trim="form.itemName" placeholder="请输入项目名称" />
|
<el-input v-model.trim="form.itemName" maxlength="20" placeholder="请输入项目名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="收费类型" prop="typeId">
|
<el-form-item label="收费类型" prop="typeId">
|
||||||
<el-select v-model="form.typeId">
|
<el-select v-model="form.typeId">
|
||||||
<el-option
|
<el-option
|
||||||
:disabled="item.status === '1'"
|
|
||||||
v-for="(item, index) in chargeItemList"
|
v-for="(item, index) in chargeItemList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.id"
|
:disabled="item.status === '1'"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="计费方式" prop="billingType">
|
<el-form-item label="计费方式" prop="billingType">
|
||||||
<el-radio-group v-model="form.billingType">
|
<el-radio-group v-model="form.billingType">
|
||||||
<el-radio v-for="(item, index) in com_charge_item_method" :key="index" :value="item.value" :label="item.label"></el-radio>
|
<el-radio v-for="(item, index) in com_charge_item_method" :key="index" :label="item.label" :value="item.value"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="计算公式" prop="formula">
|
<el-form-item label="计算公式" prop="formula">
|
||||||
<el-select
|
<el-select v-model="form.formula">
|
||||||
@change="
|
<el-option v-for="(item, index) in com_charge_item_formula" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
(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-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="计量单位" prop="unit" v-if="form.formula !== '2'">
|
<el-form-item v-if="form.formula !== '2'" label="计量单位" prop="unit">
|
||||||
<el-select v-model="form.unit">
|
<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-option v-for="(item, index) in com_charge_item_unit" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="费用单价">
|
<el-form-item label="费用单价" prop="fixedPrice">
|
||||||
<el-input maxlength="10" v-model.trim.number="form.fixedPrice" :placeholder="placeHolderFun(form.typeId)" />
|
<el-input v-model.trim.number="form.fixedPrice" :placeholder="placeHolderFun(form.typeId)" maxlength="10" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="计算精度" prop="accuracy">
|
<el-form-item label="计算精度" prop="accuracy">
|
||||||
<el-select v-model="form.accuracy">
|
<el-select v-model="form.accuracy">
|
||||||
<el-option v-for="(item, index) in com_charge_item_precision" :key="index" :value="item.value" :label="item.label"></el-option>
|
<el-option v-for="(item, index) in com_charge_item_precision" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="进位方式" prop="carryMethod">
|
<el-form-item label="进位方式" prop="carryMethod">
|
||||||
<el-select v-model="form.carryMethod">
|
<el-select v-model="form.carryMethod">
|
||||||
<el-option v-for="(item, index) in com_charge_item_carry_method" :key="index" :value="item.value" :label="item.label"></el-option>
|
<el-option v-for="(item, index) in com_charge_item_carry_method" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="启用/停用" prop="status">
|
<!-- <el-form-item label="启用/停用" prop="status">
|
||||||
@@ -63,7 +54,7 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
<el-input v-model.trim="form.remark" :rows="5" maxlength="200" placeholder="请输入" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item style="margin-top: 30px">
|
<el-form-item style="margin-top: 30px">
|
||||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||||
@@ -75,7 +66,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { getChargeItem, updateChargeItem, addChargeItem } from '@/api/system/SdbChargeItem';
|
import { getChargeItem, updateChargeItem, addChargeItem } from '@/api/system/SdbChargeItem';
|
||||||
@@ -110,11 +101,16 @@ const rules = ref({
|
|||||||
{ required: true, message: '请输入 项目名称', trigger: 'blur' },
|
{ required: true, message: '请输入 项目名称', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
validator: (_: any, value: string | number, callback: (arg0?: Error) => any) => {
|
validator: (_: any, value: string | number, callback: (arg0?: Error) => any) => {
|
||||||
if (value === '' || value === undefined) {
|
if (value === null || value === undefined || value === '') {
|
||||||
return callback(new Error('请输入项目名称'));
|
return callback(new Error('请输入项目名称'));
|
||||||
}
|
}
|
||||||
return !validator(value, 'fullFilterReg') ? callback() : callback(new Error('请输入正确的项目名称'));
|
const strVal = String(value).trim();
|
||||||
}
|
if (validator(strVal, 'fullFilterReg')) {
|
||||||
|
return callback(new Error('请输入正确的项目名称'));
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change']
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
typeId: [{ required: true, message: '请选择 收费类型', trigger: 'blur' }],
|
typeId: [{ required: true, message: '请选择 收费类型', trigger: 'blur' }],
|
||||||
@@ -160,9 +156,9 @@ if (route.query.id) {
|
|||||||
}
|
}
|
||||||
// !== 提交 =============================================================================
|
// !== 提交 =============================================================================
|
||||||
// 提交
|
// 提交
|
||||||
const submitForm = () => {
|
const submitForm = async () => {
|
||||||
if (form.value.formula === '2') {
|
if (form.value.formula === '2') {
|
||||||
form.value.unit = null;
|
form.value.unit = '';
|
||||||
}
|
}
|
||||||
formRef.value?.validate(async (valid: boolean) => {
|
formRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@@ -188,11 +184,11 @@ const cancelForm = () => {
|
|||||||
// 车位费 物业费
|
// 车位费 物业费
|
||||||
const typeNameList = ref(['2049026520314445826']);
|
const typeNameList = ref(['2049026520314445826']);
|
||||||
function placeHolderFun(typeId: string) {
|
function placeHolderFun(typeId: string) {
|
||||||
return typeNameList.value.includes(typeId) ? '请输入每日费用单价' : '请输入费用单价';
|
return typeNameList.value.includes(typeId) ? '请输入费用单价' : '请输入费用单价';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.AddBuildingBox {
|
.AddBuildingBox {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :rules="rules" :model="queryParams" :inline="true" @submit.prevent="handleQuery">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" :rules="rules" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="项目名称" prop="itemName">
|
<el-form-item label="项目名称" prop="itemName">
|
||||||
<el-input
|
<el-input
|
||||||
maxlength="20"
|
|
||||||
v-model.trim="queryParams.itemName"
|
v-model.trim="queryParams.itemName"
|
||||||
placeholder="请输入项目名称"
|
|
||||||
clearable
|
clearable
|
||||||
|
maxlength="20"
|
||||||
|
placeholder="请输入项目名称"
|
||||||
@keyup.enter.prevent="handleQuery"
|
@keyup.enter.prevent="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -29,9 +29,9 @@
|
|||||||
<right-toolbar
|
<right-toolbar
|
||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-edit="checkPermi(['chargeItem:chargeItem:edit'])"
|
|
||||||
:show-add="checkPermi(['chargeItem:chargeItem:add'])"
|
:show-add="checkPermi(['chargeItem:chargeItem:add'])"
|
||||||
:show-delete="checkPermi(['chargeItem:chargeItem:remove'])"
|
:show-delete="checkPermi(['chargeItem:chargeItem:remove'])"
|
||||||
|
:show-edit="checkPermi(['chargeItem:chargeItem:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -39,65 +39,65 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="chargeItemList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="chargeItemList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="项目名称" align="center" prop="itemName" />
|
<el-table-column align="center" label="项目名称" prop="itemName" />
|
||||||
<el-table-column label="计费方式" width="100" align="center" prop="billingType">
|
<el-table-column align="center" label="计费方式" prop="billingType" width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_charge_item_method" :value="scope.row.billingType"></dict-tag>
|
<dict-tag :options="com_charge_item_method" :value="scope.row.billingType"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="计算公式" width="100" align="center" prop="formula">
|
<el-table-column align="center" label="计算公式" prop="formula" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_charge_item_formula" :value="scope.row.formula"></dict-tag>
|
<dict-tag :options="com_charge_item_formula" :value="scope.row.formula"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="单价" width="100" align="center" prop="fixedPrice">
|
<el-table-column align="center" label="单价" prop="fixedPrice" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.fixedPrice ?? '---' }}
|
{{ scope.row.fixedPrice ?? '---' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="计量单位" width="100" align="center" prop="unit">
|
<el-table-column align="center" label="计量单位" prop="unit" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag v-if="scope.row.unit" :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>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="计算精度" width="120" align="center" prop="accuracy">
|
<el-table-column align="center" label="计算精度" prop="accuracy" width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_charge_item_precision" :value="scope.row.accuracy"></dict-tag>
|
<dict-tag :options="com_charge_item_precision" :value="scope.row.accuracy"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="进位方式" width="100" align="center" prop="carryMethod">
|
<el-table-column align="center" label="进位方式" prop="carryMethod" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_charge_item_carry_method" :value="scope.row.carryMethod"></dict-tag>
|
<dict-tag :options="com_charge_item_carry_method" :value="scope.row.carryMethod"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="状态" width="100" align="center" prop="status">
|
<el-table-column align="center" label="状态" prop="status" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch
|
<el-switch
|
||||||
@change="(val: string) => handleSwitch(val, scope.row)"
|
|
||||||
inactive-value="1"
|
|
||||||
active-value="0"
|
|
||||||
v-model="scope.row.status"
|
v-model="scope.row.status"
|
||||||
|
active-value="0"
|
||||||
|
inactive-value="1"
|
||||||
|
@change="(val: string) => handleSwitch(val, scope.row)"
|
||||||
></el-switch>
|
></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="备注" show-overflow-tooltip align="center" prop="remark" />
|
<el-table-column align="center" label="备注" prop="remark" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['chargeItem:chargeItem:edit']">编辑</el-button>
|
<el-button v-has-permi="['chargeItem:chargeItem:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['chargeItem:chargeItem:remove']">删除</el-button>
|
<el-button v-has-permi="['chargeItem:chargeItem:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="ChargeItem" lang="ts">
|
<script lang="ts" name="ChargeItem" setup>
|
||||||
import pageHeader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import Pagination from '@/components/Pagination/index.vue';
|
import Pagination from '@/components/Pagination/index.vue';
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
@@ -176,7 +176,6 @@ const getList = async () => {
|
|||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryFormRef.value.validate((valid: boolean) => {
|
queryFormRef.value.validate((valid: boolean) => {
|
||||||
console.log(valid);
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
getList();
|
getList();
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" label-width="120" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" label-width="120" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="收费类型名称" prop="name">
|
<el-form-item label="收费类型名称" prop="name">
|
||||||
<el-input maxlength="20" v-model.trim="queryParams.name" placeholder="请输入收费类型名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model.trim="queryParams.name" clearable maxlength="20" placeholder="请输入收费类型名称" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['chargeType:chargeType:add'])"
|
:show-add="checkPermi(['chargeType:chargeType:add'])"
|
||||||
:show-edit="false"
|
:show-delete="checkPermi(['chargeType:chargeType:remove'])"
|
||||||
:show-delete="false"
|
:show-edit="checkPermi(['chargeType:chargeType:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -39,34 +39,34 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="chargeTypeList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="chargeTypeList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="收费类型名称" align="center" prop="name" />
|
<el-table-column align="center" label="收费类型名称" prop="name" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch
|
<el-switch
|
||||||
@change="(val: string) => handleChange(val, scope.row)"
|
|
||||||
v-model="scope.row.status"
|
v-model="scope.row.status"
|
||||||
active-value="0"
|
active-value="0"
|
||||||
inactive-value="1"
|
inactive-value="1"
|
||||||
|
@change="(val: string) => handleChange(val, scope.row)"
|
||||||
></el-switch>
|
></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['chargeType:chargeType:edit']">修改</el-button>
|
<el-button v-has-permi="['chargeType:chargeType:edit']" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['chargeType:chargeType:remove']">删除</el-button>
|
<el-button v-has-permi="['chargeType:chargeType:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改收费类型对话框 -->
|
<!-- 添加或修改收费类型对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<el-form ref="chargeTypeFormRef" :model="form" :rules="rules" label-width="100px">
|
<el-form ref="chargeTypeFormRef" :model="form" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="收费类型名称" prop="name">
|
<el-form-item label="收费类型名称" prop="name">
|
||||||
<el-input maxlength="20" v-model.trim="form.name" placeholder="请输入收费类型名称" />
|
<el-input v-model.trim="form.name" maxlength="20" placeholder="请输入收费类型名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -76,36 +76,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<el-dialog :title="dialog2.title" v-model="dialog2.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog2.visible" :title="dialog2.title" append-to-body width="500px">
|
||||||
<el-form ref="chargeTypeForm2Ref" :model="form2" :rules="rules2" label-width="100px">
|
<el-form ref="chargeTypeForm2Ref" :model="form2" :rules="rules2" label-width="100px">
|
||||||
<el-form-item label="主收费类型">
|
<el-form-item label="主收费类型">
|
||||||
<el-select
|
<el-select
|
||||||
@change="handleChangeMasterType"
|
|
||||||
style="width: 220px; margin-right: 10px"
|
|
||||||
v-model="form2.masterTypeId"
|
v-model="form2.masterTypeId"
|
||||||
placeholder="请选择收费类型"
|
placeholder="请选择收费类型"
|
||||||
|
style="width: 220px; margin-right: 10px"
|
||||||
|
@change="handleChangeMasterType"
|
||||||
>
|
>
|
||||||
<el-option v-for="item in TypeList" :key="item.id" :label="item.name" :value="item.id" />
|
<el-option v-for="item in TypeList" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="次收费类型" v-for="(_, index) in slaveTypeIdsList" :key="index">
|
<el-form-item v-for="(_, index) in slaveTypeIdsList" :key="index" label="次收费类型">
|
||||||
<div class="flex flex-items-center">
|
<div class="flex flex-items-center">
|
||||||
<el-select
|
<el-select
|
||||||
@change="handleChangeMasterType"
|
|
||||||
style="width: 220px; margin-right: 10px"
|
|
||||||
v-model="slaveTypeIdsList[index]"
|
v-model="slaveTypeIdsList[index]"
|
||||||
placeholder="请选择收费类型"
|
placeholder="请选择收费类型"
|
||||||
|
style="width: 220px; margin-right: 10px"
|
||||||
|
@change="handleChangeMasterType"
|
||||||
>
|
>
|
||||||
<el-option :disabled="item.disabled" v-for="item in TypeList" :key="item.id" :label="item.name" :value="item.id" />
|
<el-option v-for="item in TypeList" :key="item.id" :disabled="item.disabled" :label="item.name" :value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
<div class="addBox" @click="handleAddType" v-if="index === 0 && slaveTypeIdsList.length < TypeList.length - 1">
|
<div v-if="index === 0 && slaveTypeIdsList.length < TypeList.length - 1" class="addBox" @click="handleAddType">
|
||||||
<el-icon size="23" color="#ffffff"><Plus /></el-icon>
|
<el-icon color="#ffffff" size="23"><Plus /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
<el-icon @click="deleteType(index)" v-else-if="slaveTypeIdsList.length > 1" size="24" color="red"><Delete /></el-icon>
|
<el-icon v-else-if="slaveTypeIdsList.length > 1" color="red" size="24" @click="deleteType(index)"><Delete /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="是否启用关联">
|
<el-form-item label="是否启用关联">
|
||||||
<el-switch v-model="form2.status" active-value="0" inactive-value="1" active-text="启用" inactive-text="禁用" />
|
<el-switch v-model="form2.status" active-text="启用" active-value="0" inactive-text="禁用" inactive-value="1" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="ChargeType" lang="ts">
|
<script lang="ts" name="ChargeType" setup>
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import {
|
import {
|
||||||
@@ -347,7 +347,7 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.el-table {
|
.el-table {
|
||||||
height: calc(100% - 80px);
|
height: calc(100% - 80px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,28 +3,28 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="用户ID" prop="deviceCode">
|
<el-form-item label="用户ID" prop="deviceCode">
|
||||||
<el-input v-model="queryParams.deviceCode" placeholder="请输入用户ID" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.deviceCode" clearable placeholder="请输入用户ID" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="总用电量" prop="totalEnergy">
|
<el-form-item label="总用电量" prop="totalEnergy">
|
||||||
<el-input v-model="queryParams.totalEnergy" placeholder="请输入总用电量" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.totalEnergy" clearable placeholder="请输入总用电量" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="抄表时间" prop="readTime">
|
<el-form-item label="抄表时间" prop="readTime">
|
||||||
<el-date-picker clearable v-model="queryParams.readTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择抄表时间" />
|
<el-date-picker v-model="queryParams.readTime" clearable placeholder="请选择抄表时间" type="date" value-format="YYYY-MM-DD" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="当前余额" prop="balance">
|
<el-form-item label="当前余额" prop="balance">
|
||||||
<el-input v-model="queryParams.balance" placeholder="请输入当前余额" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.balance" clearable placeholder="请输入当前余额" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="" prop="event">
|
|
||||||
<el-input v-model="queryParams.event" placeholder="请输入" clearable @keyup.enter="handleQuery" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="" prop="rangeTime">
|
|
||||||
<el-input v-model="queryParams.rangeTime" placeholder="请输入" clearable @keyup.enter="handleQuery" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="" prop="rangeFee">
|
|
||||||
<el-input v-model="queryParams.rangeFee" placeholder="请输入" clearable @keyup.enter="handleQuery" />
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="" prop="event">-->
|
||||||
|
<!-- <el-input v-model="queryParams.event" placeholder="请输入" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="" prop="rangeTime">-->
|
||||||
|
<!-- <el-input v-model="queryParams.rangeTime" placeholder="请输入" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="" prop="rangeFee">-->
|
||||||
|
<!-- <el-input v-model="queryParams.rangeFee" placeholder="请输入" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
@@ -38,32 +38,32 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-has-permi="['electricityRecord:electricityRecord:add']">新增</el-button>
|
<el-button v-has-permi="['electricityRecord:electricityRecord:add']" icon="Plus" plain type="primary" @click="handleAdd">新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="success"
|
|
||||||
plain
|
|
||||||
icon="Edit"
|
|
||||||
:disabled="single"
|
|
||||||
@click="handleUpdate()"
|
|
||||||
v-has-permi="['electricityRecord:electricityRecord:edit']"
|
v-has-permi="['electricityRecord:electricityRecord:edit']"
|
||||||
|
:disabled="single"
|
||||||
|
icon="Edit"
|
||||||
|
plain
|
||||||
|
type="success"
|
||||||
|
@click="handleUpdate()"
|
||||||
>修改</el-button
|
>修改</el-button
|
||||||
>
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
|
||||||
plain
|
|
||||||
icon="Delete"
|
|
||||||
:disabled="multiple"
|
|
||||||
@click="handleDelete()"
|
|
||||||
v-has-permi="['electricityRecord:electricityRecord:remove']"
|
v-has-permi="['electricityRecord:electricityRecord:remove']"
|
||||||
|
:disabled="multiple"
|
||||||
|
icon="Delete"
|
||||||
|
plain
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete()"
|
||||||
>删除</el-button
|
>删除</el-button
|
||||||
>
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-has-permi="['electricityRecord:electricityRecord:export']"
|
<el-button v-has-permi="['electricityRecord:electricityRecord:export']" icon="Download" plain type="warning" @click="handleExport"
|
||||||
>导出</el-button
|
>导出</el-button
|
||||||
>
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -71,49 +71,49 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="electricityRecordList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="electricityRecordList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="抄表记录ID" align="center" prop="id" v-if="true" />
|
<el-table-column v-if="true" align="center" label="抄表记录ID" prop="id" />
|
||||||
<el-table-column label="用户ID" align="center" prop="deviceCode" />
|
<el-table-column align="center" label="用户ID" prop="deviceCode" />
|
||||||
<el-table-column label="总用电量" align="center" prop="totalEnergy" />
|
<el-table-column align="center" label="总用电量" prop="totalEnergy" />
|
||||||
<el-table-column label="抄表时间" align="center" prop="readTime" width="180">
|
<el-table-column align="center" label="抄表时间" prop="readTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.readTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.readTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="当前余额" align="center" prop="balance" />
|
<el-table-column align="center" label="当前余额" prop="balance" />
|
||||||
<el-table-column label="状态" align="center" prop="status" />
|
<el-table-column align="center" label="状态" prop="status" />
|
||||||
<el-table-column label="" align="center" prop="event" />
|
<el-table-column align="center" label="" prop="event" />
|
||||||
<el-table-column label="" align="center" prop="rangeTime" />
|
<el-table-column align="center" label="" prop="rangeTime" />
|
||||||
<el-table-column label="" align="center" prop="rangeFee" />
|
<el-table-column align="center" label="" prop="rangeFee" />
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tooltip content="修改" placement="top">
|
<el-tooltip content="修改" placement="top">
|
||||||
<el-button
|
<el-button
|
||||||
|
v-has-permi="['electricityRecord:electricityRecord:edit']"
|
||||||
|
icon="Edit"
|
||||||
link
|
link
|
||||||
type="primary"
|
type="primary"
|
||||||
icon="Edit"
|
|
||||||
@click="handleUpdate(scope.row)"
|
@click="handleUpdate(scope.row)"
|
||||||
v-has-permi="['electricityRecord:electricityRecord:edit']"
|
|
||||||
></el-button>
|
></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="删除" placement="top">
|
<el-tooltip content="删除" placement="top">
|
||||||
<el-button
|
<el-button
|
||||||
|
v-has-permi="['electricityRecord:electricityRecord:remove']"
|
||||||
|
icon="Delete"
|
||||||
link
|
link
|
||||||
type="primary"
|
type="primary"
|
||||||
icon="Delete"
|
|
||||||
@click="handleDelete(scope.row)"
|
@click="handleDelete(scope.row)"
|
||||||
v-has-permi="['electricityRecord:electricityRecord:remove']"
|
|
||||||
></el-button>
|
></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改电抄记录对话框 -->
|
<!-- 添加或修改电抄记录对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<el-form ref="electricityRecordFormRef" :model="form" :rules="rules" label-width="80px">
|
<el-form ref="electricityRecordFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
<el-form-item label="用户ID" prop="deviceCode">
|
<el-form-item label="用户ID" prop="deviceCode">
|
||||||
<el-input v-model="form.deviceCode" placeholder="请输入用户ID" />
|
<el-input v-model="form.deviceCode" placeholder="请输入用户ID" />
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
<el-input v-model="form.totalEnergy" placeholder="请输入总用电量" />
|
<el-input v-model="form.totalEnergy" placeholder="请输入总用电量" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="抄表时间" prop="readTime">
|
<el-form-item label="抄表时间" prop="readTime">
|
||||||
<el-date-picker clearable v-model="form.readTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择抄表时间">
|
<el-date-picker v-model="form.readTime" clearable placeholder="请选择抄表时间" type="datetime" value-format="YYYY-MM-DD HH:mm:ss">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="当前余额" prop="balance">
|
<el-form-item label="当前余额" prop="balance">
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="ElectricityRecord" lang="ts">
|
<script lang="ts" name="ElectricityRecord" setup>
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import {
|
import {
|
||||||
listElectricityRecord,
|
listElectricityRecord,
|
||||||
|
|||||||
@@ -4,9 +4,23 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="仪表名称" prop="houseId">
|
<el-form-item label="抄表周期" prop="recordMonth">
|
||||||
<el-input maxlength="20" v-model="queryParams.houseId" placeholder="请输入仪表名称" clearable @keyup.enter="handleQuery" />
|
<el-date-picker v-model="queryParams.recordMonth" format="YYYY-MM" placeholder="抄表月份" type="month" value-format="YYYY-MM" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="起止日期" prop="dateRange">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="StartEndDate"
|
||||||
|
clearable
|
||||||
|
end-placeholder="结束"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
range-separator="到"
|
||||||
|
start-placeholder="开始"
|
||||||
|
type="daterange"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
@clear="hanleClear"
|
||||||
|
@update:model-value="handleDate"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -22,56 +36,56 @@
|
|||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<right-toolbar
|
<right-toolbar
|
||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
|
:show-add="checkPermi(['payRecord:payRecord:add'])"
|
||||||
|
:show-delete="checkPermi(['payRecord:payRecord:remove'])"
|
||||||
:show-edit="false"
|
:show-edit="false"
|
||||||
:show-add="checkPermi(['payRecordList:payRecordList:add'])"
|
|
||||||
:show-delete="checkPermi(['payRecordList:payRecordList:remove'])"
|
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
></right-toolbar>
|
></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="payRecordList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="payRecordList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="收费设备类型" align="center" prop="deviceType">
|
<el-table-column align="center" label="收费设备类型" prop="deviceType">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_waterelectricity_topup_type" :value="scope.row.deviceType"></dict-tag>
|
<dict-tag :options="com_waterelectricity_topup_type" :value="scope.row.deviceType"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="收费项目" align="center" prop="payType">
|
<el-table-column align="center" label="收费项目" prop="payType">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_payrecord_pay_type" :value="scope.row.payType"></dict-tag>
|
<dict-tag :options="com_payrecord_pay_type" :value="scope.row.payType"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="抄表周期" align="center" prop="recordMonth" width="180">
|
<el-table-column align="center" label="抄表周期" prop="recordMonth" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.recordMonth, '{y}-{m}') }}</span>
|
<span>{{ parseTime(scope.row.recordMonth, '{y}-{m}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="起止日期" width="250" align="center">
|
<el-table-column align="center" label="起止日期" width="250">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.startTime, '{y}/{m}/{d}') }}</span>
|
<span>{{ parseTime(scope.row.startTime, '{y}/{m}/{d}') }}</span>
|
||||||
<span> - </span>
|
<span> - </span>
|
||||||
<span>{{ parseTime(scope.row.endTime, '{y}/{m}/{d}') }}</span>
|
<span>{{ parseTime(scope.row.endTime, '{y}/{m}/{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="recordMonth" width="180">
|
<el-table-column align="center" label="创建时间" prop="recordMonth" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.recordMonth, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.recordMonth, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleMain(scope.row)" v-has-permi="['sdb:main:payrecord']">明细</el-button>
|
<el-button v-has-permi="['payRecord:payRecord:query']" link type="primary" @click="handleMain(scope.row)">明细</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['payRecord:payRecord:remove']">删除</el-button>
|
<el-button v-has-permi="['payRecord:payRecord:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改抄表周期明细对话框 -->
|
<!-- 添加或修改抄表周期明细对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="800px">
|
||||||
<el-form ref="payRecordListFormRef" :model="form" label-position="left">
|
<el-form ref="payRecordListFormRef" :model="form" label-position="left">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@@ -148,7 +162,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="PayRecord" lang="ts">
|
<script lang="ts" name="PayRecord" setup>
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
@@ -162,7 +176,6 @@ const { com_waterelectricity_topup_type } = toRefs<any>(proxy?.useDict('com_wate
|
|||||||
const { com_payrecord_pay_type } = toRefs<any>(proxy?.useDict('com_payrecord_pay_type'));
|
const { com_payrecord_pay_type } = toRefs<any>(proxy?.useDict('com_payrecord_pay_type'));
|
||||||
|
|
||||||
const payRecordList = ref<PayRecordVO[]>([]);
|
const payRecordList = ref<PayRecordVO[]>([]);
|
||||||
const buttonLoading = ref(false);
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
const ids = ref<Array<string | number>>([]);
|
const ids = ref<Array<string | number>>([]);
|
||||||
@@ -171,13 +184,20 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const payRecordFormRef = ref<ElFormInstance>();
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: ''
|
title: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const StartEndDate = ref([]);
|
||||||
|
function handleDate(data: string[]) {
|
||||||
|
if (data !== null) {
|
||||||
|
queryParams.value.startTime = data[0];
|
||||||
|
queryParams.value.endTime = data[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const initFormData: PayRecordListForm = {
|
const initFormData: PayRecordListForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
recordId: undefined,
|
recordId: undefined,
|
||||||
@@ -205,13 +225,9 @@ const data = reactive<PageData<PayRecordListForm, PayRecordQuery>>({
|
|||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
deviceType: undefined,
|
|
||||||
houseId: undefined,
|
|
||||||
payType: undefined,
|
|
||||||
recordMonth: undefined,
|
recordMonth: undefined,
|
||||||
startTime: undefined,
|
startTime: undefined,
|
||||||
endTime: undefined,
|
endTime: undefined
|
||||||
params: {}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -232,8 +248,18 @@ const handleQuery = () => {
|
|||||||
getList();
|
getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function hanleClear() {
|
||||||
|
queryParams.value.startTime = undefined;
|
||||||
|
queryParams.value.endTime = undefined;
|
||||||
|
StartEndDate.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
|
queryParams.value.recordMonth = undefined;
|
||||||
|
queryParams.value.startTime = undefined;
|
||||||
|
queryParams.value.endTime = undefined;
|
||||||
|
StartEndDate.value = [];
|
||||||
queryFormRef.value?.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
};
|
};
|
||||||
@@ -254,7 +280,7 @@ const handleAdd = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 详情按钮操作 */
|
/** 详情按钮操作 */
|
||||||
const handleMain = async (row?: PayRecordVO) => {
|
const handleMain = (row?: PayRecordVO) => {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/sdb/PayRecordMain',
|
path: '/sdb/PayRecordMain',
|
||||||
query: {
|
query: {
|
||||||
@@ -263,13 +289,6 @@ const handleMain = async (row?: PayRecordVO) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
|
||||||
const handleUpdate = async (id: string) => {
|
|
||||||
// const res = await getPayRecordList(id);
|
|
||||||
// Object.assign(form.value, res.data);
|
|
||||||
dialog.visible = true;
|
|
||||||
dialog.title = '最新抄表详细';
|
|
||||||
};
|
|
||||||
/** 取消按钮 */
|
/** 取消按钮 */
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
reset();
|
reset();
|
||||||
@@ -297,7 +316,7 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.el-table {
|
.el-table {
|
||||||
height: calc(100% - 80px);
|
height: calc(100% - 80px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<div class="flex flex-items-center justify-between">
|
<div class="flex flex-items-center justify-between">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="精准查询">
|
<el-form-item label="精准查询">
|
||||||
<el-select v-model="queryParamsType" style="width: 160px; margin-right: 20px">
|
<el-select v-model="queryParamsType" style="width: 160px; margin-right: 20px">
|
||||||
<el-option v-for="item in deviceCodeList" :key="item.value" :label="item.name" :value="item.value"></el-option>
|
<el-option v-for="item in deviceCodeList" :key="item.value" :label="item.name" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-input v-model="queryParamsValue" placeholder="请输入" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParamsValue" clearable placeholder="请输入" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -24,48 +24,45 @@
|
|||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<el-card class="flex-1" shadow="never">
|
<el-card class="flex-1" shadow="never">
|
||||||
<el-table v-loading="loading" border :data="payRecordListList">
|
<el-table v-loading="loading" :data="payRecordListList" border>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="仪表名称" align="center" prop="deviceType">
|
<el-table-column align="center" label="仪表名称" prop="deviceType">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_waterelectricity_topup_type" :value="scope.row.deviceType"></dict-tag>
|
<dict-tag :options="com_waterelectricity_topup_type" :value="scope.row.deviceType"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="设备编号" align="center" prop="deviceCode" />
|
<el-table-column align="center" label="设备编号" prop="deviceCode" width="160" />
|
||||||
<el-table-column label="房间号" align="center" prop="houseName" />
|
<el-table-column align="center" label="房间号" prop="houseName" />
|
||||||
<el-table-column label="收费项目" align="center" prop="payType" width="160">
|
<el-table-column align="center" label="收费项目" prop="payType" width="160">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_payrecord_pay_type" :value="scope.row.payType"></dict-tag>
|
<dict-tag :options="com_payrecord_pay_type" :value="scope.row.payType"></dict-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="抄表月份" align="center" prop="recordMonth" width="100">
|
<el-table-column align="center" label="抄表月份" prop="recordMonth" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.recordMonth, '{y}-{m}') }}</span>
|
<span>{{ parseTime(scope.row.recordMonth, '{y}-{m}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="开始时间" align="center" prop="startTime" width="160">
|
<el-table-column align="center" label="收费起止日期" prop="endTime" width="250">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
<span style="margin: 0 10px">-</span>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="结束时间" align="center" prop="endTime" width="160">
|
|
||||||
<template #default="scope">
|
|
||||||
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="本期用度" align="center" prop="currentCost" width="160" />
|
<el-table-column align="center" label="本期用度" prop="currentCost" width="100" />
|
||||||
<el-table-column label="费用合计(元)" align="center" prop="totalCost" width="120" />
|
<el-table-column align="center" label="费用合计(元)" prop="totalCost" width="120" />
|
||||||
<el-table-column label="操作" align="center" width="160" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" width="160">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)">详情</el-button>
|
<el-button link type="primary" @click="handleUpdate(scope.row)">详情</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改抄表周期明细对话框 -->
|
<!-- 添加或修改抄表周期明细对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="800px">
|
||||||
<el-form ref="payRecordListFormRef" :model="form" label-position="left">
|
<el-form ref="payRecordListFormRef" :model="form" label-position="left">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@@ -141,7 +138,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="PayRecordList" lang="ts">
|
<script lang="ts" name="PayRecordList" setup>
|
||||||
import { listPayRecordList, getPayRecordList, addPayRecordList, updatePayRecordList } from '@/api/system/SdbPayRecordMain';
|
import { listPayRecordList, getPayRecordList, addPayRecordList, updatePayRecordList } from '@/api/system/SdbPayRecordMain';
|
||||||
import { PayRecordListVO, PayRecordListQuery, PayRecordListForm } from '@/api/system/SdbPayRecordMain/type';
|
import { PayRecordListVO, PayRecordListQuery, PayRecordListForm } from '@/api/system/SdbPayRecordMain/type';
|
||||||
|
|
||||||
@@ -205,15 +202,15 @@ const deviceCodeList = [
|
|||||||
{
|
{
|
||||||
name: '房屋号',
|
name: '房屋号',
|
||||||
value: 'houseName'
|
value: 'houseName'
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '住户姓名',
|
|
||||||
value: 'residentName'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '仪表名称',
|
|
||||||
value: 'paycordName'
|
|
||||||
}
|
}
|
||||||
|
// {
|
||||||
|
// name: '住户姓名',
|
||||||
|
// value: 'residentName'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '仪表名称',
|
||||||
|
// value: 'paycordName'
|
||||||
|
// }
|
||||||
];
|
];
|
||||||
const { queryParams, form } = toRefs(data);
|
const { queryParams, form } = toRefs(data);
|
||||||
|
|
||||||
|
|||||||
@@ -4,91 +4,94 @@
|
|||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" label-position="right" label-width="130px">
|
||||||
<el-form-item label="账单名称" prop="billName">
|
<el-form-item label="账单名称" prop="billName">
|
||||||
<el-input maxlength="30" v-model.trim="form.billName" placeholder="请输入账单名称" />
|
<el-input v-model.trim="form.billName" maxlength="30" placeholder="请输入账单名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="收费项目" prop="chargeItemId">
|
<el-form-item label="收费项目" prop="chargeItemId">
|
||||||
<el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)">
|
<el-select v-model="form.chargeItemId" @change="(val: string) => handleChange(val, true)">
|
||||||
<el-option
|
<el-option v-for="(item, index) in chargeItemList" :key="index" :disabled="item.status === '1'" :label="item.itemName" :value="item.id">
|
||||||
:disabled="item.status === '1'"
|
<div class="flex flex-row justify-between" style="font-size: 13px">
|
||||||
v-for="(item, index) in chargeItemList"
|
<span>{{ item.itemName }}</span>
|
||||||
:key="index"
|
<div class="flex flex-items-baseline" style="color: var(--el-text-color-secondary)">
|
||||||
:value="item.id"
|
<span>{{ item.fixedPrice }} ¥ </span>
|
||||||
:label="item.itemName"
|
<span v-if="item.unit" style="margin: 0 5px">/</span>
|
||||||
></el-option>
|
<dict-tag v-if="item.unit" :options="com_charge_item_unit" :value="item.unit"></dict-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 水费,电费, 收费范围为 房屋 -->
|
<!-- 水费,电费, 收费范围为 房屋 -->
|
||||||
<el-form-item label="收费范围" prop="chargeScope" v-if="typeNameList.includes(typeName)">
|
<el-form-item v-if="typeNameList.includes(typeName)" label="收费范围" prop="chargeScope">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex flex-row flex-items-end">
|
<div class="flex flex-row flex-items-end">
|
||||||
<el-radio-group v-model="form.chargeScope">
|
<el-radio-group v-model="form.chargeScope">
|
||||||
<div class="flex flex-col flex-items-end">
|
<div class="flex flex-col flex-items-end">
|
||||||
<el-radio
|
<el-radio
|
||||||
:disabled="!form.chargeItemId"
|
|
||||||
style="margin-right: 0"
|
|
||||||
v-for="(item, index) in com_bill_charge_scope_house"
|
v-for="(item, index) in com_bill_charge_scope_house"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.value"
|
:disabled="!form.chargeItemId"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
style="margin-right: 0"
|
||||||
></el-radio>
|
></el-radio>
|
||||||
</div>
|
</div>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<div style="height: 32px">
|
<div style="height: 32px">
|
||||||
<el-button @click="OpenUseTablesFun('house')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
|
<el-button v-if="form.chargeScope === '1'" class="ml-10px" link type="primary" @click="OpenUseTablesFun('house')">请选择</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 其他费用, 收费范围为 业主 -->
|
<!-- 其他费用, 收费范围为 业主 -->
|
||||||
<el-form-item label="收费范围" prop="chargeScope" v-else>
|
<el-form-item v-else label="收费范围" prop="chargeScope">
|
||||||
<div class="flex flex-row flex-items-end">
|
<div class="flex flex-row flex-items-end">
|
||||||
<el-radio-group v-model="form.chargeScope">
|
<el-radio-group v-model="form.chargeScope">
|
||||||
<div class="flex flex-col flex-items-end">
|
<div class="flex flex-col flex-items-end">
|
||||||
<el-radio
|
<el-radio
|
||||||
style="margin-right: 0"
|
|
||||||
:disabled="!form.chargeItemId"
|
|
||||||
v-for="(item, index) in com_questionnaire_scope"
|
v-for="(item, index) in com_questionnaire_scope"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.value"
|
:disabled="!form.chargeItemId"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
style="margin-right: 0"
|
||||||
></el-radio>
|
></el-radio>
|
||||||
</div>
|
</div>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<div style="height: 32px">
|
<div style="height: 32px">
|
||||||
<el-button @click="OpenUseTablesFun('user')" link type="primary" v-if="form.chargeScope === '1'" class="ml-10px">请选择</el-button>
|
<el-button v-if="form.chargeScope === '1'" class="ml-10px" link type="primary" @click="OpenUseTablesFun('user')">请选择</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 房屋选择 -->
|
<!-- 房屋选择 -->
|
||||||
<el-form-item v-if="form.chargeScope === '1' && typeNameList.includes(typeName)">
|
<el-form-item v-if="form.chargeScope === '1' && typeNameList.includes(typeName)">
|
||||||
<div class="residentBox">
|
<div class="residentBox">
|
||||||
<House returnvalue="houseId" ref="HolderRef" :isMultiple="true" @change="handleSelect"> </House>
|
<House ref="HolderRef" :isMultiple="true" returnvalue="houseId" @change="handleSelect"> </House>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 业主选择 -->
|
<!-- 业主选择 -->
|
||||||
<el-form-item v-if="form.chargeScope === '1' && !typeNameList.includes(typeName)">
|
<el-form-item v-if="form.chargeScope === '1' && !typeNameList.includes(typeName)">
|
||||||
<!-- 业主选择 车位费用 -->
|
<!-- 业主选择 车位费用 -->
|
||||||
<div class="residentBox" v-if="typeName === HandleTypeId.Resident.Parking">
|
<div v-if="typeName === HandleTypeId.Resident.Parking" class="residentBox">
|
||||||
<CarUser returnvalue="parkingId" ref="ParkingUserRef" :isMultiple="true" @change="handleCheckParking"></CarUser>
|
<CarUser ref="ParkingUserRef" :isMultiple="true" returnvalue="parkingId" @change="handleCheckParking"></CarUser>
|
||||||
</div>
|
</div>
|
||||||
<div class="residentBox" v-else>
|
<div v-else class="residentBox">
|
||||||
<UserHolder returnvalue="residentId" ref="userRef" :isMultiple="true" @change="handleCheckUser"></UserHolder>
|
<UserHolder ref="userRef" :isMultiple="true" returnvalue="residentId" @change="handleCheckUser"></UserHolder>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="费用周期" prop="chargePeriod">
|
<el-form-item label="费用周期" prop="chargePeriod">
|
||||||
<el-select @change="handleChangePeriod" v-model="form.chargePeriod">
|
<el-select v-model="form.chargePeriod" @change="handleChangePeriod">
|
||||||
<el-option v-for="(item, index) in com_bill_charge_period" :key="index" :value="item.value" :label="item.label"></el-option>
|
<el-option v-for="(item, index) in com_bill_charge_period" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="form.chargePeriod !== '2'" label="周期计算维度" prop="periodCalcType">
|
<el-form-item v-if="form.chargePeriod !== '2'" label="周期计算维度" prop="periodCalcType">
|
||||||
<div class="w-full flex flex-row flex-items-center">
|
<div class="w-full flex flex-row flex-items-center">
|
||||||
<el-select v-model="form.periodCalcType">
|
<el-select v-model="form.periodCalcType" @change="handleChangePeriodCalcType">
|
||||||
<el-option v-for="(item, index) in PeriodicCalculationDimensionList" :key="index" :value="item.value" :label="item.label"></el-option>
|
<el-option v-for="(item, index) in PeriodicCalculationDimensionList" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-tooltip class="box-item" effect="light" placement="top">
|
<el-tooltip class="box-item" effect="light" placement="top">
|
||||||
<el-icon style="margin-left: 10px" color="#909399"><QuestionFilled /></el-icon>
|
<el-icon color="#909399" style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="items">
|
<div class="items">
|
||||||
<div class="label">自然年:</div>
|
<div class="label">自然年:</div>
|
||||||
@@ -121,20 +124,20 @@
|
|||||||
<el-form-item label="起止日期" prop="startDate">
|
<el-form-item label="起止日期" prop="startDate">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="StartEndDate"
|
v-model="StartEndDate"
|
||||||
unlink-panels
|
|
||||||
@update:model-value="handleDate"
|
|
||||||
@clear="handleClear"
|
|
||||||
:value-format="datepicker[2].format"
|
|
||||||
:disabled-date="handleDisableDate"
|
:disabled-date="handleDisableDate"
|
||||||
:format="datepicker[2].format"
|
:format="eldatepick.format"
|
||||||
:type="datepicker[2].type"
|
:type="eldatepick.type"
|
||||||
|
:value-format="eldatepick.valueformat"
|
||||||
|
end-placeholder="结束"
|
||||||
range-separator="到"
|
range-separator="到"
|
||||||
start-placeholder="开始"
|
start-placeholder="开始"
|
||||||
end-placeholder="结束"
|
unlink-panels
|
||||||
|
@clear="handleClear"
|
||||||
|
@update:model-value="handleDate"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
<el-input v-model.trim="form.remark" :rows="5" maxlength="200" placeholder="请输入" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item style="margin-top: 30px">
|
<el-form-item style="margin-top: 30px">
|
||||||
@@ -147,7 +150,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import House from '@/components/Holder/house.vue';
|
import House from '@/components/Holder/house.vue';
|
||||||
@@ -158,23 +161,18 @@ import PageHeader from '@/components/Pageheader/index.vue';
|
|||||||
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||||||
import { getBill, updateBill, addBill } from '@/api/system/SdbBill';
|
import { getBill, updateBill, addBill } from '@/api/system/SdbBill';
|
||||||
import type { DatePickerType } from 'element-plus';
|
import type { DatePickerType } from 'element-plus';
|
||||||
import { formatDate2 } from '@/utils';
|
|
||||||
import { QuestionFilled } from '@element-plus/icons-vue';
|
import { QuestionFilled } from '@element-plus/icons-vue';
|
||||||
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_bill_charge_scope_house, com_questionnaire_scope, com_bill_charge_period } = toRefs<any>(
|
const { com_bill_charge_scope_house, com_questionnaire_scope, com_bill_charge_period, com_charge_item_unit } = toRefs<any>(
|
||||||
proxy?.useDict('com_bill_charge_scope_house', 'com_questionnaire_scope', 'com_bill_charge_period')
|
proxy?.useDict('com_bill_charge_scope_house', 'com_questionnaire_scope', 'com_bill_charge_period', 'com_charge_item_unit')
|
||||||
);
|
);
|
||||||
|
const eldatepick = ref({
|
||||||
type PickerConfig = {
|
type: 'daterange' as DatePickerType,
|
||||||
type: DatePickerType;
|
format: 'YYYY-MM-DD',
|
||||||
format: string;
|
valueformat: 'YYYY-MM-DD'
|
||||||
};
|
});
|
||||||
const datepicker: Record<string, PickerConfig> = {
|
|
||||||
'0': { type: 'yearrange', format: 'YYYY' },
|
|
||||||
'1': { type: 'monthrange', format: 'YYYY-MM' },
|
|
||||||
'2': { type: 'daterange', format: 'YYYY-MM-DD' }
|
|
||||||
};
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -184,12 +182,14 @@ const form = ref({
|
|||||||
'billName': '',
|
'billName': '',
|
||||||
'chargeItemId': '', // 收费项目
|
'chargeItemId': '', // 收费项目
|
||||||
'chargeScope': '0', // 业主范围
|
'chargeScope': '0', // 业主范围
|
||||||
|
/** 2 day 0 year 1 month 3 季度 */
|
||||||
'chargePeriod': '2', // 费用周期
|
'chargePeriod': '2', // 费用周期
|
||||||
houseIds: [], // 部分房屋
|
houseIds: [], // 部分房屋
|
||||||
residentIds: [], // 部分业主
|
residentIds: [], // 部分业主
|
||||||
parkingIds: [],
|
parkingIds: [],
|
||||||
chargeTypeId: '', // typeid
|
chargeTypeId: '', // 收费类型
|
||||||
periodCalcType: '0', // 周期计算维度
|
/** 周期计算维度 // 0 自然 1 滚动 */
|
||||||
|
periodCalcType: '0', // 周期计算维度 // 0 自然 1 滚动
|
||||||
'startDate': '', // 开始
|
'startDate': '', // 开始
|
||||||
'endDate': '', // 结束
|
'endDate': '', // 结束
|
||||||
'remark': ''
|
'remark': ''
|
||||||
@@ -206,51 +206,58 @@ const userid = ref(null);
|
|||||||
|
|
||||||
// 开始结束日期
|
// 开始结束日期
|
||||||
const StartEndDate = ref([]);
|
const StartEndDate = ref([]);
|
||||||
|
// 禁止
|
||||||
function handleDisableDate(date: Date) {
|
function handleDisableDate(date: Date) {
|
||||||
// 月 - 自然月/滚动月
|
// 月 - 自然月/滚动月
|
||||||
if (form.value.periodCalcType === '0') {
|
if (form.value.chargePeriod === '1') {
|
||||||
// 自然月
|
// 自然月
|
||||||
const year = date.getFullYear();
|
if (form.value.periodCalcType === '0') {
|
||||||
const month = date.getMonth() + 1;
|
const year = date.getFullYear();
|
||||||
const firstDay = new Date(year, month - 1, 1);
|
const month = date.getMonth();
|
||||||
const lastDay = new Date(year, month, 0);
|
const day = date.getDate();
|
||||||
if (date.getTime() == lastDay.getTime() || date.getTime() == firstDay.getTime()) {
|
const lastDay = new Date(year, month + 1, 0).getDate();
|
||||||
|
// 不是1号,也不是月末 → 禁用
|
||||||
|
return day !== 1 && day !== lastDay;
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
} else if (form.value.chargePeriod === '0' && form.value.periodCalcType === '0') {
|
||||||
} else if (form.value.periodCalcType === '1') {
|
const month = date.getMonth(); // 0=1月,11=12月
|
||||||
// 滚动月
|
const day = date.getDate();
|
||||||
|
|
||||||
|
// 允许:1月1日 (month=0, day=1) 、12月31日 (month=11, day=31)
|
||||||
|
const isJan1 = month === 0 && day === 1;
|
||||||
|
const isDec31 = month === 11 && day === 31;
|
||||||
|
|
||||||
|
// 不是这两天 → 禁用
|
||||||
|
return !isJan1 && !isDec31;
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleDate(val: string[]) {
|
function handleDate(val: string[]) {
|
||||||
if (val === null || val.length === 0) {
|
if (val === null || val.length === 0) {
|
||||||
form.value.startDate = '';
|
handleClear();
|
||||||
form.value.endDate = '';
|
|
||||||
} else {
|
} else {
|
||||||
form.value.startDate = val[0] + ' 00:00:00';
|
form.value.startDate = val[0] + ' 00:00:00';
|
||||||
form.value.endDate = val[1] + ' 23:59:59';
|
form.value.endDate = val[1] + ' 23:59:59';
|
||||||
|
if (form.value.chargePeriod === '0' && form.value.periodCalcType === '0') {
|
||||||
|
form.value.startDate = val[0] + ' 00:00:00';
|
||||||
|
form.value.endDate = val[1] + ' 23:59:59';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleClear() {
|
function handleClear() {
|
||||||
form.value.startDate = '';
|
form.value.startDate = '';
|
||||||
|
StartEndDate.value = [];
|
||||||
form.value.endDate = '';
|
form.value.endDate = '';
|
||||||
}
|
}
|
||||||
// 收费类型
|
// 收费类型
|
||||||
const chargeItemList = ref([]);
|
const chargeItemList = ref([]);
|
||||||
|
|
||||||
// // 房屋列表
|
|
||||||
// const houselist = ref([]);
|
|
||||||
// // 住户列表
|
|
||||||
// const userlist = ref([]);
|
|
||||||
async function init() {
|
async function init() {
|
||||||
listChargeItem({}).then((res) => {
|
listChargeItem({}).then((res) => {
|
||||||
chargeItemList.value = res.rows;
|
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) {
|
if (route.query.id) {
|
||||||
userid.value = route.query.id;
|
userid.value = route.query.id;
|
||||||
getBill(userid.value).then((res) => {
|
getBill(userid.value).then((res) => {
|
||||||
@@ -262,9 +269,6 @@ async function init() {
|
|||||||
form.value.houseIds = res.data.houseIds || [];
|
form.value.houseIds = res.data.houseIds || [];
|
||||||
form.value.residentIds = res.data.residentIds || [];
|
form.value.residentIds = res.data.residentIds || [];
|
||||||
form.value.parkingIds = res.data.parkingIds || [];
|
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];
|
|
||||||
checkoutHouses.value = [];
|
checkoutHouses.value = [];
|
||||||
checkoutUser.value = [];
|
checkoutUser.value = [];
|
||||||
checkoutParking.value = [];
|
checkoutParking.value = [];
|
||||||
@@ -273,6 +277,10 @@ async function init() {
|
|||||||
checkoutParking.value = form.value.parkingIds.filter((item) => item);
|
checkoutParking.value = form.value.parkingIds.filter((item) => item);
|
||||||
handleChange(form.value.chargeItemId);
|
handleChange(form.value.chargeItemId);
|
||||||
handleChangePeriod(form.value.chargePeriod);
|
handleChangePeriod(form.value.chargePeriod);
|
||||||
|
handleChangePeriodCalcType();
|
||||||
|
form.value.startDate = res.data.startDate;
|
||||||
|
form.value.endDate = res.data.endDate;
|
||||||
|
StartEndDate.value = [form.value.startDate, form.value.endDate];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -302,7 +310,6 @@ function handleChange(val: string, callback: boolean = false) {
|
|||||||
if (find) {
|
if (find) {
|
||||||
form.value.chargeTypeId = find.typeId;
|
form.value.chargeTypeId = find.typeId;
|
||||||
typeName.value = find.typeId;
|
typeName.value = find.typeId;
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
handleClearCheckout();
|
handleClearCheckout();
|
||||||
}
|
}
|
||||||
@@ -327,7 +334,6 @@ const checkoutParking = ref([]);
|
|||||||
/** 添加 车位业主 */
|
/** 添加 车位业主 */
|
||||||
function handleCheckParking(val: string[]) {
|
function handleCheckParking(val: string[]) {
|
||||||
checkoutParking.value = val;
|
checkoutParking.value = val;
|
||||||
console.log(val);
|
|
||||||
form.value.parkingIds = val;
|
form.value.parkingIds = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,10 +380,62 @@ function handleChangePeriod(val: string) {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
// eldatepick.value.format = 'YYYY-MM-DD';
|
||||||
|
// eldatepick.value.valueformat = 'YYYY-MM-DD';
|
||||||
|
// // 0 年
|
||||||
|
// if (val === '0') {
|
||||||
|
// eldatepick.value.type = 'yearrange';
|
||||||
|
// eldatepick.value.format = 'YYYY';
|
||||||
|
// eldatepick.value.valueformat = 'YYYY';
|
||||||
|
// // 1 月
|
||||||
|
// } else if (val === '1') {
|
||||||
|
// eldatepick.value.type = 'daterange';
|
||||||
|
// // 2 日
|
||||||
|
// } else if (val === '2') {
|
||||||
|
// eldatepick.value.type = 'daterange';
|
||||||
|
// }
|
||||||
|
handleClear();
|
||||||
|
}
|
||||||
|
// 计算维度周期 变化
|
||||||
|
function handleChangePeriodCalcType() {
|
||||||
|
handleClear();
|
||||||
|
// if (form.value.chargePeriod === '0') {
|
||||||
|
// if (val === '0') {
|
||||||
|
// eldatepick.value.type = 'yearrange';
|
||||||
|
// eldatepick.value.format = 'YYYY';
|
||||||
|
// eldatepick.value.valueformat = 'YYYY';
|
||||||
|
// } else if (val === '1') {
|
||||||
|
// eldatepick.value.type = 'daterange';
|
||||||
|
// eldatepick.value.format = 'YYYY-MM-DD';
|
||||||
|
// eldatepick.value.valueformat = 'YYYY-MM-DD';
|
||||||
|
// }
|
||||||
|
// } else if (form.value.chargePeriod === '1') {
|
||||||
|
// if (val === '0') {
|
||||||
|
// eldatepick.value.type = 'daterange';
|
||||||
|
// eldatepick.value.format = 'YYYY-MM-DD';
|
||||||
|
// eldatepick.value.valueformat = 'YYYY-MM-DD';
|
||||||
|
// } else if (val === '1') {
|
||||||
|
// eldatepick.value.type = 'daterange';
|
||||||
|
// eldatepick.value.format = 'YYYY-MM-DD';
|
||||||
|
// eldatepick.value.valueformat = 'YYYY-MM-DD';
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// !== 提交 =============================================================================
|
// !== 提交 =============================================================================
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
|
if (form.value.chargePeriod === '0') {
|
||||||
|
if (form.value.periodCalcType === '0') {
|
||||||
|
const startData = new Date(form.value.startDate);
|
||||||
|
const endData = new Date(form.value.endDate);
|
||||||
|
|
||||||
|
const diff = endData.getTime() - startData.getTime();
|
||||||
|
if (diff <= 60 * 60 * 24 * 1000 * 2) {
|
||||||
|
ElMessage.warning('起止日期不足1年');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
formRef.value?.validate(async (valid: boolean) => {
|
formRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (userid.value) {
|
if (userid.value) {
|
||||||
@@ -400,7 +458,7 @@ const cancelForm = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.items {
|
.items {
|
||||||
.label {
|
.label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|||||||
@@ -4,12 +4,15 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="收费项目" prop="chargeItemId">
|
<el-form-item label="收费项目" prop="chargeItemId">
|
||||||
<el-select v-model="queryParams.chargeItemId" placeholder="请选择收费项目">
|
<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-option v-for="(item, index) in chargeItems" :key="index" :label="item.itemName" :value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="账单编号" prop="billCode">
|
||||||
|
<el-input v-model="queryParams.billCode" placeholder="请输入账单编号"></el-input>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
@@ -21,15 +24,15 @@
|
|||||||
<el-card class="flex-1" shadow="never">
|
<el-card class="flex-1" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<right-toolbar :show-add="checkPermi(['bill:bill:add'])" :show-edit="false" :show-delete="false" @update:add="handleAdd"></right-toolbar>
|
<right-toolbar :show-add="checkPermi(['bill:bill:add'])" :show-delete="false" :show-edit="false" @update:add="handleAdd"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="billList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="billList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="账单编号" align="center" prop="billCode" />
|
<el-table-column align="center" label="账单编号" prop="billCode" />
|
||||||
<el-table-column label="账单名称" align="center" prop="billName" />
|
<el-table-column align="center" label="账单名称" prop="billName" />
|
||||||
<el-table-column label="收费范围" align="center" prop="chargeScope" width="100">
|
<el-table-column align="center" label="收费范围" prop="chargeScope" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="ShowHouseList.includes(scope.row.chargeTypeId)">
|
<template v-if="ShowHouseList.includes(scope.row.chargeTypeId)">
|
||||||
<DictTag :options="com_bill_charge_scope_house" :value="scope.row.chargeScope"></DictTag>
|
<DictTag :options="com_bill_charge_scope_house" :value="scope.row.chargeScope"></DictTag>
|
||||||
@@ -39,66 +42,79 @@
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="收费项目" align="center" prop="chargeItemName" />
|
<el-table-column align="center" label="收费项目" prop="chargeItemName" />
|
||||||
<el-table-column label="起止时间" align="center">
|
<el-table-column align="center" label="起止时间">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.startDate, '{y}/{m}/{d}') }}</span> -
|
<span>{{ parseTime(scope.row.startDate, '{y}/{m}/{d}') }}</span> -
|
||||||
<span>{{ parseTime(scope.row.endDate, '{y}/{m}/{d}') }}</span>
|
<span>{{ parseTime(scope.row.endDate, '{y}/{m}/{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="单价" align="center" width="180">
|
<el-table-column align="center" label="单价" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="flex justify-center" v-if="scope.row.unit">
|
<div v-if="scope.row.unit" class="flex justify-center">
|
||||||
<span>{{ scope.row.fixedPrice }}</span> /
|
<span>{{ scope.row.fixedPrice }}</span> /
|
||||||
<DictTag :options="com_charge_item_unit" :value="scope.row.unit"></DictTag>
|
<DictTag :options="com_charge_item_unit" :value="scope.row.unit"></DictTag>
|
||||||
</div>
|
</div>
|
||||||
|
<span v-else-if="scope.row.fixedPrice">{{ scope.row.fixedPrice }}{{ handleChargePeriod(scope.row.chargePeriod) }}</span>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="200" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" label="备注" prop="remark" show-overflow-tooltip />
|
||||||
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleChange(scope.row)">生成账单</el-button>
|
<el-button link type="primary" @click="handleChange(scope.row)">生成账单</el-button>
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['bill:bill:edit']">编辑</el-button>
|
<el-button v-has-permi="['bill:bill:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleMain(scope.row)" v-has-permi="['bill:bill:query']">详情</el-button>
|
<el-button v-has-permi="['bill:bill:query']" link type="primary" @click="handleMain(scope.row)">详情</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-dialog v-model="BillVisible" :title="BillForm.title" width="500">
|
<el-dialog v-model="BillVisible" :title="BillForm.title" width="500">
|
||||||
<el-form :model="BillForm" label-width="auto" style="max-width: 600px">
|
<el-form v-loading="UploadLoading" :model="BillForm" label-width="auto" style="max-width: 600px">
|
||||||
<el-form-item label="账单生成时间">
|
<el-form-item label="账单生成时间">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-if="BillForm.chargePeriod === '0'"
|
v-if="BillForm.chargePeriod === '0'"
|
||||||
v-model="BillForm.year"
|
v-model="BillForm.years"
|
||||||
type="years"
|
|
||||||
format="YYYY"
|
format="YYYY"
|
||||||
value-format="YYYY"
|
|
||||||
placeholder="选择账单生成年份"
|
placeholder="选择账单生成年份"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
type="years"
|
||||||
|
value-format="YYYY"
|
||||||
/>
|
/>
|
||||||
<!-- 滚动月份 -->
|
<!-- 滚动月份 -->
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
format="YYYY-MM"
|
|
||||||
value-format="YYYY-MM"
|
|
||||||
v-else-if="BillForm.chargePeriod === '1'"
|
v-else-if="BillForm.chargePeriod === '1'"
|
||||||
v-model="BillForm.yearMonths"
|
v-model="BillForm.yearMonths"
|
||||||
:disabled-date="handleDisableMonth"
|
:disabled-date="handleDisableMonth"
|
||||||
type="months"
|
format="YYYY-MM"
|
||||||
placeholder="选择账单生成月份"
|
placeholder="选择账单生成月份"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
type="months"
|
||||||
|
value-format="YYYY-MM"
|
||||||
/>
|
/>
|
||||||
<!-- 滚动季度 -->
|
<!-- 滚动季度 -->
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
format="YYYY-MM"
|
|
||||||
value-format="YYYY-MM"
|
|
||||||
v-else-if="BillForm.chargePeriod === '3'"
|
v-else-if="BillForm.chargePeriod === '3'"
|
||||||
v-model="BillForm.yearQuarters"
|
v-model="BillForm.yearQuarters"
|
||||||
type="months"
|
|
||||||
placeholder="选择账单生成季度"
|
|
||||||
:disabled-date="handleDisableMonth"
|
:disabled-date="handleDisableMonth"
|
||||||
|
format="YYYY-MM"
|
||||||
|
placeholder="选择账单生成季度"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
type="months"
|
||||||
|
value-format="YYYY-MM"
|
||||||
/>
|
/>
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="BillForm.chargePeriod === '2'"
|
||||||
|
v-model="BillForm.days"
|
||||||
|
:disabled-date="handleDisableMonth"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
placeholder="选择日期生成每日账单"
|
||||||
|
style="width: 100%"
|
||||||
|
type="dates"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 季度账单-滚动季度 -->
|
<!-- 季度账单-滚动季度 -->
|
||||||
<!-- <QuarterSelect v-if="BillForm.chargePeriod === '3' && BillForm.periodCalcType === '1'" v-model="myQuarter" @change="onQuarterChange" />-->
|
<!-- <QuarterSelect v-if="BillForm.chargePeriod === '3' && BillForm.periodCalcType === '1'" v-model="myQuarter" @change="onQuarterChange" />-->
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -123,14 +139,14 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="BillVisible = false">关闭</el-button>
|
<el-button @click="BillVisible = false">关闭</el-button>
|
||||||
<el-button type="primary" @click="handleChangeApi"> 生成 </el-button>
|
<el-button :loading="UploadLoading" type="primary" @click="handleChangeApi"> 生成 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Bill" lang="ts">
|
<script lang="ts" name="Bill" setup>
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
@@ -138,10 +154,7 @@ import { listBill, manualGenerateApi } from '@/api/system/SdbBill';
|
|||||||
import { BillVO, BillQuery, BillForm } from '@/api/system/SdbBill/type';
|
import { BillVO, BillQuery, BillForm } from '@/api/system/SdbBill/type';
|
||||||
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
// import House from '@/components/Holder/house.vue';
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
// import UserHolder from '@/components/Holder/user.vue';
|
|
||||||
// import CarUser from '@/components/Holder/CarUser.vue';
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
||||||
@@ -176,7 +189,7 @@ const data = reactive<PageData<BillForm, BillQuery>>({
|
|||||||
form: { ...initFormData },
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 10,
|
||||||
chargeItemId: '',
|
chargeItemId: '',
|
||||||
billCode: ''
|
billCode: ''
|
||||||
}
|
}
|
||||||
@@ -213,6 +226,10 @@ const handleQuery = () => {
|
|||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
|
queryParams.value.billCode = '';
|
||||||
|
queryParams.value.chargeItemId = '';
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
queryParams.value.pageSize = 10;
|
||||||
queryFormRef.value?.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
handleQuery();
|
handleQuery();
|
||||||
};
|
};
|
||||||
@@ -241,7 +258,7 @@ const handleUpdate = (row?: BillVO) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
// 详情
|
||||||
function handleMain(row: BillVO) {
|
function handleMain(row: BillVO) {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/sdb/sdbbillMain',
|
path: '/sdb/sdbbillMain',
|
||||||
@@ -250,20 +267,28 @@ function handleMain(row: BillVO) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 删除
|
||||||
|
// function handleDelete(row: BillVO) {
|
||||||
|
// delBill(row.id).then((res) => {
|
||||||
|
// ElMessage.success(res.msg);
|
||||||
|
// getList();
|
||||||
|
// })
|
||||||
|
// }
|
||||||
const BillVisible = ref(false);
|
const BillVisible = ref(false);
|
||||||
const BillForm = ref<{
|
const BillForm = ref<{
|
||||||
title: string;
|
title: string;
|
||||||
billId: string;
|
billId: string;
|
||||||
/**
|
/**
|
||||||
* 收费周期 0年 1月 2日 3 季度 4永久;为空时取账单配置
|
* 收费周期 0年 1月 2日 3 季度 ;为空时取账单配置
|
||||||
*/
|
*/
|
||||||
chargePeriod: string;
|
chargePeriod: string;
|
||||||
chargeScope: string;
|
chargeScope: string;
|
||||||
yearMonths?: string[];
|
yearMonths?: string[];
|
||||||
|
days?: string[];
|
||||||
periodCalcType: string;
|
periodCalcType: string;
|
||||||
houseId: string[];
|
houseId: string[];
|
||||||
yearQuarters?: string[];
|
yearQuarters?: string[];
|
||||||
year?: string[];
|
years?: string[];
|
||||||
startDate?: string;
|
startDate?: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
}>({
|
}>({
|
||||||
@@ -274,6 +299,19 @@ const BillForm = ref<{
|
|||||||
periodCalcType: '0',
|
periodCalcType: '0',
|
||||||
houseId: []
|
houseId: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleChargePeriod(chargePeriod: string) {
|
||||||
|
if (chargePeriod === '0') {
|
||||||
|
return '/年';
|
||||||
|
} else if (chargePeriod === '1') {
|
||||||
|
return '/月';
|
||||||
|
} else if (chargePeriod === '2') {
|
||||||
|
return '/日';
|
||||||
|
} else if (chargePeriod === '3') {
|
||||||
|
return '/季度';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// const HolderRef = ref<InstanceType<typeof House>>();
|
// const HolderRef = ref<InstanceType<typeof House>>();
|
||||||
// // 打开模态框
|
// // 打开模态框
|
||||||
// function OpenUseTablesFun() {
|
// function OpenUseTablesFun() {
|
||||||
@@ -283,6 +321,7 @@ const BillForm = ref<{
|
|||||||
// function handleSelect(val: string[]) {
|
// function handleSelect(val: string[]) {
|
||||||
// BillForm.value.houseId = val;
|
// BillForm.value.houseId = val;
|
||||||
// }
|
// }
|
||||||
|
// 生成账单
|
||||||
function handleChange(row: BillVO) {
|
function handleChange(row: BillVO) {
|
||||||
clearChangeBillForm();
|
clearChangeBillForm();
|
||||||
BillVisible.value = true;
|
BillVisible.value = true;
|
||||||
@@ -300,13 +339,22 @@ function handleChange(row: BillVO) {
|
|||||||
BillForm.value['year'] = [];
|
BillForm.value['year'] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UploadLoading = ref(false);
|
||||||
|
// 生成账单
|
||||||
function handleChangeApi() {
|
function handleChangeApi() {
|
||||||
manualGenerateApi(BillForm.value).then((res) => {
|
UploadLoading.value = true;
|
||||||
ElMessage.success(res.msg);
|
manualGenerateApi(BillForm.value)
|
||||||
clearChangeBillForm();
|
.then((res) => {
|
||||||
BillVisible.value = false;
|
ElMessage.success(res.msg);
|
||||||
});
|
clearChangeBillForm();
|
||||||
|
BillVisible.value = false;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
UploadLoading.value = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
// 清空表单
|
||||||
function clearChangeBillForm() {
|
function clearChangeBillForm() {
|
||||||
BillForm.value = {
|
BillForm.value = {
|
||||||
periodCalcType: undefined,
|
periodCalcType: undefined,
|
||||||
@@ -317,16 +365,10 @@ function clearChangeBillForm() {
|
|||||||
houseId: []
|
houseId: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// 禁用月份
|
||||||
function handleDisableMonth(date: Date) {
|
function handleDisableMonth(date: Date) {
|
||||||
if (!BillForm.value.startDate || !BillForm.value.endDate) return false;
|
if (!BillForm.value.startDate || !BillForm.value.endDate) return false;
|
||||||
return date.getTime() < new Date(BillForm.value.startDate).getTime() || date.getTime() > new Date(BillForm.value.endDate).getTime();
|
return date.getTime() > new Date(BillForm.value.endDate).getTime();
|
||||||
}
|
|
||||||
|
|
||||||
const myQuarter = ref('2026-2');
|
|
||||||
|
|
||||||
function onQuarterChange(val: string) {
|
|
||||||
console.log(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -4,48 +4,56 @@
|
|||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form class="formBody" label-position="right" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" label-position="right" label-width="130px">
|
||||||
<el-form-item label="账单名称" prop="billName">
|
<el-form-item label="账单名称" prop="billName">
|
||||||
<el-input disabled v-model.trim="form.billName" placeholder="请输入账单名称" />
|
<el-input v-model.trim="form.billName" disabled placeholder="请输入账单名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账单编号" prop="billCode">
|
||||||
|
<el-input v-model.trim="form.billCode" disabled placeholder="请输入账单编号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="收费项目" prop="chargeItemId">
|
<el-form-item label="收费项目" prop="chargeItemId">
|
||||||
<el-select disabled v-model="form.chargeItemId" @change="handleChange">
|
<el-select v-model="form.chargeItemId" disabled @change="handleChange">
|
||||||
<el-option v-for="(item, index) in chargeItemList" :key="index" :value="item.id" :label="item.itemName"></el-option>
|
<el-option v-for="(item, index) in chargeItemList" :key="index" :label="item.itemName" :value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="费用单价" prop="price">
|
||||||
<el-form-item label="收费范围" prop="chargeScope" v-if="itemTypeIncludes">
|
<el-input v-model.trim="form.price" disabled placeholder="请输入账单编号" />
|
||||||
<el-radio-group disabled v-model="form.chargeScope">
|
</el-form-item>
|
||||||
<el-radio v-for="(item, index) in com_questionnaire_scope" :key="index" :value="item.value" :label="item.label"></el-radio>
|
<el-form-item label="收费周期" prop="date">
|
||||||
|
<el-input v-model.trim="form.date" disabled placeholder="请输入账单编号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="itemTypeIncludes" label="收费范围" prop="chargeScope">
|
||||||
|
<el-radio-group v-model="form.chargeScope" disabled>
|
||||||
|
<el-radio v-for="(item, index) in com_questionnaire_scope" :key="index" :label="item.label" :value="item.value"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="收费范围" prop="chargeScope" v-else>
|
<el-form-item v-else label="收费范围" prop="chargeScope">
|
||||||
<el-radio-group disabled v-model="form.chargeScope">
|
<el-radio-group v-model="form.chargeScope" disabled>
|
||||||
<el-radio v-for="(item, index) in com_bill_charge_scope_house" :key="index" :value="item.value" :label="item.label"></el-radio>
|
<el-radio v-for="(item, index) in com_bill_charge_scope_house" :key="index" :label="item.label" :value="item.value"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="费用周期" prop="chargePeriod">
|
<el-form-item label="费用周期" prop="chargePeriod">
|
||||||
<el-select disabled v-model="form.chargePeriod">
|
<el-select v-model="form.chargePeriod" disabled>
|
||||||
<el-option v-for="(item, index) in com_bill_charge_period" :key="index" :value="item.value" :label="item.label"></el-option>
|
<el-option v-for="(item, index) in com_bill_charge_period" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="起止日期" prop="price">
|
<el-form-item label="起止日期" prop="price">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
disabled
|
|
||||||
v-model="StartEndDate"
|
v-model="StartEndDate"
|
||||||
@update:model-value="handleDate"
|
|
||||||
:value-format="datepicker[form.chargePeriod].format"
|
|
||||||
:format="datepicker[form.chargePeriod].format"
|
:format="datepicker[form.chargePeriod].format"
|
||||||
:type="datepicker[form.chargePeriod].type"
|
:type="datepicker[form.chargePeriod].type"
|
||||||
|
:value-format="datepicker[form.chargePeriod].format"
|
||||||
|
disabled
|
||||||
|
end-placeholder="结束"
|
||||||
range-separator="到"
|
range-separator="到"
|
||||||
start-placeholder="开始"
|
start-placeholder="开始"
|
||||||
end-placeholder="结束"
|
@update:model-value="handleDate"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input disabled type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
<el-input v-model.trim="form.remark" :rows="5" disabled placeholder="请输入" type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item style="margin-top: 30px">
|
<el-form-item style="margin-top: 30px">
|
||||||
@@ -57,7 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||||||
@@ -69,6 +77,7 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|||||||
const { com_questionnaire_scope } = toRefs<any>(proxy?.useDict('com_questionnaire_scope'));
|
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_scope_house } = toRefs<any>(proxy?.useDict('com_bill_charge_scope_house'));
|
||||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
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 PickerConfig = {
|
type PickerConfig = {
|
||||||
type: DatePickerType;
|
type: DatePickerType;
|
||||||
@@ -85,18 +94,26 @@ const route = useRoute();
|
|||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const form = ref({
|
const form = ref({
|
||||||
'id': null,
|
'id': null,
|
||||||
|
billCode: '',
|
||||||
'billName': '',
|
'billName': '',
|
||||||
'chargeItemId': '', // 收费项目
|
'chargeItemId': '', // 收费项目
|
||||||
'chargeScope': '0', // 业主范围
|
'chargeScope': '0', // 业主范围
|
||||||
'chargePeriod': '2', // 费用周期
|
'chargePeriod': '2', // 费用周期
|
||||||
houseIds: [], // 部分业主
|
houseIds: [], // 部分业主
|
||||||
charegeTypeId: '', // typeid
|
charegeTypeId: '', // typeid
|
||||||
|
fixedPrice: '',
|
||||||
|
unit: '',
|
||||||
|
price: '',
|
||||||
|
date: '',
|
||||||
'startDate': '', // 开始
|
'startDate': '', // 开始
|
||||||
'endDate': '', // 结束
|
'endDate': '', // 结束
|
||||||
'remark': ''
|
'remark': ''
|
||||||
});
|
});
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
billName: [{ required: true, message: '请输入 项目名称', trigger: 'blur' }],
|
billName: [{ required: true, message: '请输入 项目名称', trigger: 'blur' }],
|
||||||
|
date: [{ required: true, message: '请输入 收费周期', trigger: 'blur' }],
|
||||||
|
billCode: [{ required: true, message: '请输入 账单编号', trigger: 'blur' }],
|
||||||
|
price: [{ required: true, message: '请输入 费用单价', trigger: 'blur' }],
|
||||||
chargeItemId: [{ required: true, message: '请选择 收费项目', trigger: 'blur' }],
|
chargeItemId: [{ required: true, message: '请选择 收费项目', trigger: 'blur' }],
|
||||||
chargePeriod: [{ required: true, message: '请选择 费用周期', trigger: 'blur' }],
|
chargePeriod: [{ required: true, message: '请选择 费用周期', trigger: 'blur' }],
|
||||||
startDate: [{ required: true, message: '请选择 起止日期', trigger: 'blur' }],
|
startDate: [{ required: true, message: '请选择 起止日期', trigger: 'blur' }],
|
||||||
@@ -117,14 +134,7 @@ const typeNameList = ref(['2049026484272791553', '2049026503017136129']);
|
|||||||
const itemTypeIncludes = computed(() => {
|
const itemTypeIncludes = computed(() => {
|
||||||
return typeNameList.value.includes(form.value.chargeItemId);
|
return typeNameList.value.includes(form.value.chargeItemId);
|
||||||
});
|
});
|
||||||
|
|
||||||
const houseList = ref([]);
|
|
||||||
|
|
||||||
const checkoutUses = ref([]);
|
|
||||||
async function init() {
|
async function init() {
|
||||||
const res1 = await listBillHouse({ pageNum: 1, pageSize: 999999 });
|
|
||||||
houseList.value = res1.rows;
|
|
||||||
|
|
||||||
listChargeItem().then(async (res) => {
|
listChargeItem().then(async (res) => {
|
||||||
chargeItemList.value = res.rows;
|
chargeItemList.value = res.rows;
|
||||||
|
|
||||||
@@ -135,20 +145,13 @@ async function init() {
|
|||||||
...form.value,
|
...form.value,
|
||||||
...res1.data
|
...res1.data
|
||||||
};
|
};
|
||||||
|
const find = com_charge_item_unit.value.find((item) => item.value === form.value.unit);
|
||||||
|
if (find) {
|
||||||
|
form.value.price = `${form.value.fixedPrice}元/${find.label}`;
|
||||||
|
}
|
||||||
|
form.value.date = form.value.startDate.split(' ')[0] + ' - ' + form.value.endDate.split(' ')[0];
|
||||||
form.value.houseIds = res1.data.houseIds || [];
|
form.value.houseIds = res1.data.houseIds || [];
|
||||||
StartEndDate.value = [formatDate(res1.data.startDate), formatDate(res1.data.endDate)];
|
StartEndDate.value = [res1.data.startDate, 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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -169,7 +172,7 @@ const cancelForm = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.AddBuildingBox {
|
.AddBuildingBox {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-card style="margin-top: 20px; height: 100%">
|
<el-card style="margin-top: 20px; height: 100%">
|
||||||
<div class="p-2 flex flex-col cashierbox h-full">
|
<div class="p-2 flex flex-col cashierBox h-full">
|
||||||
<div class="tablebox">
|
<div class="tableBox">
|
||||||
<div style="margin-bottom: 20px">
|
<div style="margin-bottom: 20px">
|
||||||
<el-button @click="printPiaoju" type="primary">打印票据</el-button>
|
<el-button type="primary" @click="printPiaoju">打印票据</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="tabledata" @selection-change="handleSelectionChange">
|
<el-table :data="tableData" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column align="center" label="收费名称">
|
<el-table-column align="center" label="收费名称">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div>{{ scope.row.detailsName }}</div>
|
<div>{{ scope.row.detailsName }}</div>
|
||||||
@@ -42,27 +42,27 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-dialog :title="dialog_print.title" v-model="dialog_print.visible" width="1200px" append-to-body>
|
<el-dialog v-model="dialog_print.visible" :title="dialog_print.title" append-to-body width="1200px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex" style="justify-content: space-between; padding: 0 20px">
|
<div class="flex" style="justify-content: space-between; padding: 0 20px">
|
||||||
<div class="title">票据打印</div>
|
<div class="title">票据打印</div>
|
||||||
<el-button type="primary" :loading="isLoading" @click="confimPrint">打印</el-button>
|
<el-button :loading="isLoading" type="primary" @click="completePrint">打印</el-button>
|
||||||
<!-- <el-button type="primary" v-print="printOption">打印</el-button> -->
|
<!-- <el-button type="primary" v-print="printOption">打印</el-button> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="printBox" id="printBox-Bill">
|
<div id="printBox-Bill" class="printBox">
|
||||||
<div class="title">{{ print_form.title }}</div>
|
<div class="title">{{ print_form.title }}</div>
|
||||||
<div class="nav gridbox">
|
<div class="nav gridBox">
|
||||||
<div>单据日期:{{ print_form.printDate }}</div>
|
<div>单据日期:{{ print_form.printDate }}</div>
|
||||||
<div>房号:{{ print_form.HouseName }}</div>
|
<div>房号:{{ print_form.HouseName }}</div>
|
||||||
<div>产权人:{{ print_form.residentName }}</div>
|
<div>产权人:{{ print_form.residentName }}</div>
|
||||||
<div>No.</div>
|
<div>No.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tablebox">
|
<div class="tableBox">
|
||||||
<table border class="printTable">
|
<table border class="printTable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -103,8 +103,8 @@
|
|||||||
<div class="flex-1">交款人:</div>
|
<div class="flex-1">交款人:</div>
|
||||||
<div class="flex-1 flex flex-items-center">
|
<div class="flex-1 flex flex-items-center">
|
||||||
<span style="white-space: nowrap">收款人: </span>
|
<span style="white-space: nowrap">收款人: </span>
|
||||||
<el-input v-model="inHomelyUse" v-if="!isPrint" placeholder="请输入收款人姓名" style="width: 150px"></el-input>
|
<el-input v-if="!isPrint" v-model="inHomelyUse" placeholder="请输入收款人姓名" style="width: 150px"></el-input>
|
||||||
<span style="white-space: nowrap" v-else> {{ inHomelyUse }}</span>
|
<span v-else style="white-space: nowrap"> {{ inHomelyUse }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
@@ -125,7 +125,7 @@ const { com_pay_status } = toRefs<any>(proxy?.useDict('com_pay_status'));
|
|||||||
const { com_bill_charge_period } = toRefs<any>(proxy?.useDict('com_bill_charge_period'));
|
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_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_unit'));
|
||||||
|
|
||||||
type querytype = {
|
type queryType = {
|
||||||
residentId: string;
|
residentId: string;
|
||||||
residentName: string;
|
residentName: string;
|
||||||
houseName: string;
|
houseName: string;
|
||||||
@@ -133,7 +133,7 @@ type querytype = {
|
|||||||
};
|
};
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
query: {
|
query: {
|
||||||
type: Object as PropType<querytype>,
|
type: Object as PropType<queryType>,
|
||||||
default: () => {
|
default: () => {
|
||||||
return {
|
return {
|
||||||
'residentId': '',
|
'residentId': '',
|
||||||
@@ -152,14 +152,14 @@ const queryParams = ref({
|
|||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10
|
pageSize: 10
|
||||||
});
|
});
|
||||||
const tabledata = ref<billlistType[]>([]);
|
const tableData = ref<billlistType[]>([]);
|
||||||
// 支付状态 0未缴纳 1已缴纳 2缴纳失败
|
// 支付状态 0未缴纳 1已缴纳 2缴纳失败
|
||||||
const getList = () => {
|
const getList = () => {
|
||||||
billQuery({
|
billQuery({
|
||||||
residentId: props.query.residentId,
|
residentId: props.query.residentId,
|
||||||
'payStatus': '1'
|
'payStatus': '1'
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
tabledata.value = res.rows;
|
tableData.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -210,7 +210,7 @@ function printPiaoju() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
function confimPrint() {
|
function completePrint() {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
isPrint.value = true;
|
isPrint.value = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -222,7 +222,7 @@ function confimPrint() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.printBox {
|
.printBox {
|
||||||
color: rgba(0, 0, 0, 1);
|
color: rgba(0, 0, 0, 1);
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
@@ -234,7 +234,7 @@ function confimPrint() {
|
|||||||
}
|
}
|
||||||
.nav {
|
.nav {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
&.gridbox {
|
&.gridBox {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
@@ -246,7 +246,7 @@ function confimPrint() {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tablebox {
|
.tableBox {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
.printTable {
|
.printTable {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
@@ -261,7 +261,7 @@ function confimPrint() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cashierbox {
|
.cashierBox {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
.el-button {
|
.el-button {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
@@ -269,10 +269,10 @@ function confimPrint() {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionsbox {
|
.actionsBox {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
.tablebox {
|
.tableBox {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
.el-table {
|
.el-table {
|
||||||
@@ -280,7 +280,7 @@ function confimPrint() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.payinfo {
|
.payInfo {
|
||||||
color: rgba(0, 0, 0, 1);
|
color: rgba(0, 0, 0, 1);
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
|||||||
@@ -3,25 +3,31 @@
|
|||||||
<PageHeader></PageHeader>
|
<PageHeader></PageHeader>
|
||||||
<div class="mb-[10px]">
|
<div class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<div>
|
<div>
|
||||||
<el-form-item label="小区" prop="villageId">
|
<el-form-item label="小区" prop="villageId">
|
||||||
<el-select @change="handleChangeVillage" v-model="queryParams.villageId" placeholder="请选择小区">
|
<el-select v-model="queryParams.villageId" placeholder="请选择小区" @change="handleChangeVillage">
|
||||||
<el-option v-for="(item, index) in villageList" :key="index" :value="item.villageId" :label="item.villageName"></el-option>
|
<el-option v-for="(item, index) in villageList" :key="index" :label="item.villageName" :value="item.villageId"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="楼栋" prop="buildingId">
|
<el-form-item label="楼栋" prop="buildingId">
|
||||||
<el-select @change="handleChangeBuilding" v-model="queryParams.buildingId" placeholder="请选择楼栋">
|
<el-select
|
||||||
<el-option v-for="(item, index) in buildingList" :key="index" :value="item.id" :label="item.buildingName"></el-option>
|
v-model="queryParams.buildingId"
|
||||||
|
clearable
|
||||||
|
placeholder="请选择楼栋"
|
||||||
|
@change="handleChangeBuilding"
|
||||||
|
@clear="handleClearBuildingId"
|
||||||
|
>
|
||||||
|
<el-option v-for="(item, index) in buildingList" :key="index" :label="item.buildingName" :value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="单元" prop="unitNoId">
|
<el-form-item label="单元" prop="unitNoId">
|
||||||
<el-select @change="handleChangeUnit" v-model="queryParams.unitNoId" placeholder="请选择单元">
|
<el-select v-model="queryParams.unitNoId" clearable placeholder="请选择单元" @change="handleChangeUnit" @clear="handleClearUnit">
|
||||||
<el-option v-for="(item, index) in unitList" :key="index" :value="item.unitNoId" :label="item.unitNoName"></el-option>
|
<el-option v-for="(item, index) in unitList" :key="index" :label="item.unitNoName" :value="item.unitNoId"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item @change="handleChangeHouseNo" label="房号" prop="houseId">
|
<el-form-item label="房号" prop="houseId">
|
||||||
<el-select v-model="queryParams.houseId" placeholder="请选择房号">
|
<el-select v-model="queryParams.houseId" clearable placeholder="请选择房号" @clear="handleClear('houseId')">
|
||||||
<el-option-group v-for="group in houseList" :key="group.floorNo" :label="String(group.floorNo) + ' 楼'">
|
<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 v-for="item in group.houses" :key="item.houseId" :label="item.houseNo" :value="item.houseId" />
|
||||||
</el-option-group>
|
</el-option-group>
|
||||||
@@ -30,61 +36,70 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-form-item label="收费项目" prop="itemId">
|
<el-form-item label="收费项目" prop="itemId">
|
||||||
<el-select multiple v-model="queryParams.chargeItemId" placeholder="请选择收费项目">
|
<el-select v-model="queryParams.chargeItemId" clearable multiple placeholder="请选择收费项目" @clear="handleClear('chargeItemId')">
|
||||||
<el-option
|
<el-option
|
||||||
:disabled="item.status === '1'"
|
|
||||||
v-for="(item, index) in chargeItems"
|
v-for="(item, index) in chargeItems"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.id"
|
:disabled="item.status === '1'"
|
||||||
:label="item.itemName"
|
:label="item.itemName"
|
||||||
|
:value="item.id"
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="缴费周期">
|
<el-form-item label="缴费周期">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="queryParams.startDate"
|
v-model="queryParams.startDate"
|
||||||
type="date"
|
clearable
|
||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
|
placeholder="请选择开始缴费日期"
|
||||||
|
type="date"
|
||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
@clear="handleClearChargePeriod('start')"
|
@clear="handleClearChargePeriod('start')"
|
||||||
placeholder="请选择开始缴费日期"
|
|
||||||
/>
|
/>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="queryParams.endDate"
|
v-model="queryParams.endDate"
|
||||||
type="date"
|
|
||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
|
placeholder="请选择结束缴费日期"
|
||||||
|
style="margin-left: 10px"
|
||||||
|
type="date"
|
||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
@clear="handleClearChargePeriod('end')"
|
@clear="handleClearChargePeriod('end')"
|
||||||
style="margin-left: 10px"
|
|
||||||
placeholder="请选择结束缴费日期"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="房屋分类" prop="houseUseTypeId">
|
<el-form-item label="房屋分类" prop="houseUseTypeId">
|
||||||
<el-select v-model="queryParams.houseUseTypeId">
|
<el-select v-model="queryParams.houseUseTypeId" clearable @clear="handleClear('houseUseTypeId')">
|
||||||
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
|
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="缴费时间">
|
<el-form-item label="缴费时间">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="queryParams.payTimeBegin"
|
v-model="queryParams.payTimeBegin"
|
||||||
type="datetime"
|
clearable
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
@clear="handleClearPayTime('payTimeBegin')"
|
|
||||||
placeholder="请选择开始缴费时间"
|
placeholder="请选择开始缴费时间"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@clear="handleClear('payTimeBegin')"
|
||||||
/>
|
/>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="queryParams.payTimeEnd"
|
v-model="queryParams.payTimeEnd"
|
||||||
type="datetime"
|
clearable
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
@clear="handleClearPayTime('payTimeEnd')"
|
|
||||||
style="margin-left: 10px"
|
|
||||||
placeholder="请选择结束缴费时间"
|
placeholder="请选择结束缴费时间"
|
||||||
|
style="margin-left: 10px"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@clear="handleClear('payTimeEnd')"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="业主姓名" prop="residentName">
|
<el-form-item label="业主姓名" prop="residentName">
|
||||||
<el-input maxlength="30" v-model.trim="queryParams.residentName" placeholder="请选择业主姓名"></el-input>
|
<el-input
|
||||||
|
v-model.trim="queryParams.residentName"
|
||||||
|
clearable
|
||||||
|
maxlength="30"
|
||||||
|
placeholder="请选择业主姓名"
|
||||||
|
@clear="handleClear('residentName')"
|
||||||
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div style="text-align: right">
|
<div style="text-align: right">
|
||||||
@@ -99,43 +114,43 @@
|
|||||||
<div class="actionsBox">
|
<div class="actionsBox">
|
||||||
<div class="tabs-box">
|
<div class="tabs-box">
|
||||||
<div
|
<div
|
||||||
class="tabs-items"
|
|
||||||
v-for="(item, index) in tabs"
|
v-for="(item, index) in tabs"
|
||||||
:key="index"
|
:key="index"
|
||||||
:class="{
|
:class="{
|
||||||
active: activeTabs === item.value
|
active: activeTabs === item.value
|
||||||
}"
|
}"
|
||||||
|
class="tabs-items"
|
||||||
@click="changeTabs(item.value)"
|
@click="changeTabs(item.value)"
|
||||||
>
|
>
|
||||||
{{ item.type }}
|
{{ item.type }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<el-button @click="handleIncome(false)" :disabled="!single">收费</el-button>
|
<el-button :disabled="!single" @click="handleIncome(false)">收费</el-button>
|
||||||
<el-button @click="printPIaoJuByOnly(false)" :disabled="!printSingle">打印票据</el-button>
|
<el-button :disabled="!printSingle" @click="printPIaoJuByOnly(false)">打印票据</el-button>
|
||||||
<el-button @click="handleDelete(false)">批量删除</el-button>
|
<el-button @click="handleDelete(false)">批量删除</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-card class="flex-1" shadow="never">
|
<el-card class="flex-1" shadow="never">
|
||||||
<el-table v-loading="loading" border :data="tableData" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="tableData" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" fixed="left" width="55" align="center" />
|
<el-table-column align="center" fixed="left" type="selection" width="55" />
|
||||||
<el-table-column label="房屋/车位/车辆" fixed="left" align="center" prop="unitNo" width="120">
|
<el-table-column align="center" fixed="left" label="房屋/车位/车辆" prop="unitNo" width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.unitNo }}
|
<el-button link type="primary" @click="handleRoute(scope.row)">{{ scope.row.unitNo }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="收费项目" fixed="left" align="center" prop="billCode" width="120">
|
<el-table-column align="center" fixed="left" label="收费项目" prop="billCode" width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.chargeItemName }}
|
{{ scope.row.chargeItemName }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="收费周期" align="center" prop="periodDisplay" width="280">
|
<el-table-column align="center" label="收费周期" prop="periodDisplay" width="280">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.periodDisplay }}</span>
|
<span>{{ scope.row.periodDisplay }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="单价" width="100" align="center" prop="fixedPrice">
|
<el-table-column align="center" label="单价" prop="fixedPrice" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<span>
|
<span>
|
||||||
@@ -146,30 +161,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="数量" width="85" align="center" prop="quantity">
|
<el-table-column align="center" label="数量" prop="quantity" width="85">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.quantity }}</span>
|
<span>{{ scope.row.quantity }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="应收金额" width="100" align="center" prop="amount" />
|
<el-table-column align="center" label="应收金额" prop="amount" width="100" />
|
||||||
<el-table-column label="缴费状态" width="100" align="center" prop="payStatus">
|
<el-table-column align="center" label="缴费状态" prop="payStatus" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.payStatus === '0'">未缴纳</span>
|
<span v-if="scope.row.payStatus === PayStatus.PENDING">未缴纳</span>
|
||||||
<span v-else-if="scope.row.payStatus === '1'">已缴纳</span>
|
<span v-else-if="scope.row.payStatus === PayStatus.PAID">已缴纳</span>
|
||||||
<span v-else-if="scope.row.payStatus === '2'">缴纳失败</span>
|
<span v-else-if="scope.row.payStatus === PayStatus.FAILED">缴纳失败</span>
|
||||||
<span v-else>部分缴纳</span>
|
<span v-else-if="scope.row.payStatus === PayStatus.PARTIAL">部分缴纳</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="应缴金额" width="100" align="center" prop="amount" />
|
<el-table-column align="center" label="剩余应缴金额" prop="needPayAmount" width="140" />
|
||||||
<el-table-column label="优惠金额" width="100" align="center" prop="singleDiscountAmount" />
|
<el-table-column align="center" label="优惠金额" prop="singleDiscountAmount" width="100" />
|
||||||
<el-table-column label="实缴金额" width="100" align="center" prop="actualAccount" />
|
<el-table-column align="center" label="实缴金额" prop="actualAccount" width="100" />
|
||||||
<el-table-column label="缴费人" width="120" align="center" prop="residentName" />
|
<el-table-column align="center" label="缴费人" prop="residentName" width="120" />
|
||||||
<el-table-column label="缴费时间" align="center" prop="payTime" />
|
<el-table-column align="center" label="缴费时间" prop="payTime" />
|
||||||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
<el-table-column align="center" label="备注" prop="remark" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" width="150" align="center" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" label="操作" width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" v-if="scope.row.payStatus !== '1'" @click="handleIncome(scope.row)">收款</el-button>
|
<el-button v-if="scope.row.payStatus !== PayStatus.PAID" link type="primary" @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 v-if="scope.row.payStatus === PayStatus.PAID" link type="success" @click="printPIaoJuByOnly(scope.row)">打印票据</el-button>
|
||||||
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -177,15 +192,21 @@
|
|||||||
<div class="footerBox">
|
<div class="footerBox">
|
||||||
<div class="totalBox">
|
<div class="totalBox">
|
||||||
<span>合计:</span>
|
<span>合计:</span>
|
||||||
<span style="padding: 0 10px">应收:{{ totalAll.totalAccount }}元</span>
|
<span>应收:{{ totalAll.totalAccount }}元(原金额:{{ totalAll.originalAmount }}元, 优惠:{{ totalAll.totalDiscountAmount }}元)</span>
|
||||||
<span style="padding: 0 10px">实收:{{ totalAll.TotalPaymentAmount }}元</span>
|
<span style="padding: 0 5px">已收:{{ totalAll.TotalPaymentAmount }}元</span>
|
||||||
<span style="padding: 0 10px">优惠:{{ totalAll.totalDiscountAmount }}元</span>
|
<span style="padding: 0 5px">未收:{{ totalAll.TotalUnPaymentAmount }}元</span>
|
||||||
<span style="padding: 0 10px">未收:{{ totalAll.TotalUnPaymentAmount }}元</span>
|
|
||||||
</div>
|
</div>
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:pageSizes="[10, 20, 30, 50, 100, 200, 300]"
|
||||||
|
:total="total"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="650px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="650px">
|
||||||
<div class="payInfo">
|
<div class="payInfo">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex flex-items-center justify-between">
|
<div class="flex flex-items-center justify-between">
|
||||||
@@ -206,19 +227,19 @@
|
|||||||
<div style="text-decoration: underline; padding-right: 5px; text-align: center">
|
<div style="text-decoration: underline; padding-right: 5px; text-align: center">
|
||||||
{{ item.detailsName }} (应缴:¥{{ item.needPayAmount }})
|
{{ item.detailsName }} (应缴:¥{{ item.needPayAmount }})
|
||||||
</div>
|
</div>
|
||||||
<el-tooltip class="box-item" effect="light" placement="top" v-if="item.payStatus === '3'">
|
<el-tooltip v-if="item.payStatus === PayStatus.PENDING" class="box-item" effect="light" placement="top">
|
||||||
<el-icon color="#909399"><QuestionFilled /></el-icon>
|
<el-icon color="#909399"><QuestionFilled /></el-icon>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div style="line-height: 1.8; font-size: 13px; width: 180px">
|
<div style="line-height: 1.8; font-size: 13px; width: 180px">
|
||||||
<div style="text-align: right" class="flex justify-between">
|
<div class="flex justify-between" style="text-align: right">
|
||||||
<span>总金额</span>
|
<span>总金额</span>
|
||||||
<span>{{ item.amount }}¥</span>
|
<span>{{ item.amount }}¥</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: right" class="flex justify-between">
|
<div class="flex justify-between" style="text-align: right">
|
||||||
<span>累计优惠金额</span>
|
<span>累计优惠金额</span>
|
||||||
<span>− {{ item.singleDiscountAmount }}¥</span>
|
<span>− {{ item.singleDiscountAmount }}¥</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: right" class="flex justify-between">
|
<div class="flex justify-between" style="text-align: right">
|
||||||
<span>累计已交金额</span>
|
<span>累计已交金额</span>
|
||||||
<span>− {{ item.paidAmount }}¥</span>
|
<span>− {{ item.paidAmount }}¥</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -233,7 +254,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="item.payStatus === '1'">(已缴费,不计入金额)</span>
|
<span v-if="item.payStatus === PayStatus.PAID">(已缴费,不计入金额)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -275,33 +296,33 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="缴纳状态" prop="payStatus">
|
<el-form-item label="缴纳状态" prop="payStatus">
|
||||||
<el-radio-group v-model="inComeFrom.payStatus">
|
<el-radio-group v-model="inComeFrom.payStatus">
|
||||||
<el-radio value="1" label="已缴纳"></el-radio>
|
<el-radio label="已缴纳" value="1"></el-radio>
|
||||||
<el-radio value="2" label="部分缴纳"></el-radio>
|
<el-radio label="部分缴纳" value="3"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="优惠方式" prop="discountMethod" v-if="inComeFrom.payStatus !== '0'">
|
<el-form-item v-if="inComeFrom.payStatus !== PayStatus.PENDING" label="优惠方式" prop="discountMethod">
|
||||||
<el-select style="width: 400px" @change="handleChangeDisCountMethod" v-model="inComeFrom.discountMethod" placeholder="请选择">
|
<el-select v-model="inComeFrom.discountMethod" placeholder="请选择" style="width: 400px" @change="handleChangeDisCountMethod">
|
||||||
<el-option label="不优惠" :value="0"></el-option>
|
<el-option :value="0" label="不优惠"></el-option>
|
||||||
<el-option label="金额" :value="2"></el-option>
|
<el-option :value="2" label="金额"></el-option>
|
||||||
<el-option label="比例" :value="1"></el-option>
|
<el-option :value="1" label="比例"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-if="inComeFrom.discountMethod !== 0">
|
<div v-if="inComeFrom.discountMethod !== 0">
|
||||||
<div v-if="inComeFrom.discountMethod === 2">
|
<div v-if="inComeFrom.discountMethod === 2">
|
||||||
<el-form-item label="单笔优惠金额" prop="discount">
|
<el-form-item label="单笔优惠金额" prop="discount">
|
||||||
<el-input style="width: 400px" v-model.trim.number="inComeFrom.discount" @input="debouncedHandleDiscountMoney">
|
<el-input v-model.trim.number="inComeFrom.discount" style="width: 400px" @input="debouncedHandleDiscountMoney">
|
||||||
<template #append>
|
<template #append>
|
||||||
<span>¥</span>
|
<span>¥</span>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item label="优惠比例" prop="discountRate" v-else>
|
<el-form-item v-else label="优惠比例" prop="discountRate">
|
||||||
<el-input
|
<el-input
|
||||||
style="width: 400px"
|
|
||||||
v-model.trim.number="inComeFrom.discountRate"
|
v-model.trim.number="inComeFrom.discountRate"
|
||||||
placeholder="0~100:0=无优惠,80=优惠80%,100=全免"
|
placeholder="0~100:0=无优惠,80=优惠80%,100=全免"
|
||||||
|
style="width: 400px"
|
||||||
@input="debounceDiscountRate"
|
@input="debounceDiscountRate"
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
@@ -310,61 +331,61 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="总优惠金额" prop="totalDiscountAmount">
|
<el-form-item label="总优惠金额" prop="totalDiscountAmount">
|
||||||
<el-input style="width: 400px" disabled v-model="totalDiscountAmount">
|
<el-input v-model="totalDiscountAmount" disabled style="width: 400px">
|
||||||
<template #append>
|
<template #append>
|
||||||
<span>¥</span>
|
<span>¥</span>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item label="支付方式" prop="payType" v-if="inComeFrom.payStatus !== '0'">
|
<el-form-item v-if="inComeFrom.payStatus !== PayStatus.PENDING" label="支付方式" prop="payType">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<div class="flex flex-items-center" v-for="(item, index) in payList" :key="index">
|
<div v-for="(item, index) in payList" :key="index" class="flex flex-items-center">
|
||||||
<div class="flex-1 flex">
|
<div class="flex-1 flex">
|
||||||
<el-select @change="handleChangePayTypeId($event, index)" v-model="item.payType" placeholder="请选择">
|
<el-select v-model="item.payType" placeholder="请选择" @change="handleChangePayTypeId($event, index)">
|
||||||
<el-option
|
<el-option
|
||||||
:disabled="isOptionDisabled(dict.value, item.payType)"
|
|
||||||
v-for="dict in com_pay_method"
|
v-for="dict in com_pay_method"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
|
:disabled="isOptionDisabled(dict.value, item.payType)"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
:value="dict.value"
|
:value="dict.value"
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-input @change="(val: string) => handleChangePay(val, index)" v-model.number.trim="item.payAmount" style="margin: 0 10px">
|
<el-input v-model.number.trim="item.payAmount" style="margin: 0 10px" @change="(val: string) => handleChangePay(val, index)">
|
||||||
<template #append>¥</template>
|
<template #append>¥</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
<div style="width: 80px; text-align: left">
|
<div style="width: 80px; text-align: left">
|
||||||
<el-icon
|
<el-icon
|
||||||
|
v-if="index === payList.length - 1 && payList.length < com_pay_method.length"
|
||||||
color="blue"
|
color="blue"
|
||||||
size="24"
|
size="24"
|
||||||
v-if="index === payList.length - 1 && payList.length < com_pay_method.length"
|
|
||||||
@click="addPayList"
|
|
||||||
style="margin-right: 10px; cursor: pointer"
|
style="margin-right: 10px; cursor: pointer"
|
||||||
|
@click="addPayList"
|
||||||
><CirclePlus
|
><CirclePlus
|
||||||
/></el-icon>
|
/></el-icon>
|
||||||
<el-icon color="red" style="cursor: pointer" size="24" v-if="payList.length > 1" @click="removePayList(index)"><Delete /></el-icon>
|
<el-icon v-if="payList.length > 1" color="red" size="24" style="cursor: pointer" @click="removePayList(index)"><Delete /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input style="width: 400px" type="textarea" show-word-limit maxlength="100" :rows="5" v-model="inComeFrom.remark"></el-input>
|
<el-input v-model="inComeFrom.remark" :rows="5" maxlength="100" show-word-limit style="width: 400px" type="textarea"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<el-button @click="closer">取消</el-button>
|
<el-button @click="closer">取消</el-button>
|
||||||
<el-button @click="submitForm" :loading="buttonLoading" type="primary">提交</el-button>
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<el-dialog :title="dialog_print.title" v-model="dialog_print.visible" width="1200px" append-to-body>
|
<el-dialog v-model="dialog_print.visible" :title="dialog_print.title" append-to-body width="1200px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex" style="justify-content: space-between; padding: 0 20px">
|
<div class="flex" style="justify-content: space-between; padding: 0 20px">
|
||||||
<div class="title">票据打印</div>
|
<div class="title">票据打印</div>
|
||||||
<el-button type="primary" v-print="printOption" :loading="isLoading" @click="conFimPrint">打印</el-button>
|
<el-button v-print="printOption" :loading="isLoading" type="primary" @click="conFimPrint">打印</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="printBox" id="printBox-Bill" style="margin: 0; color: rgba(0, 0, 0, 1); padding: 5px">
|
<div id="printBox-Bill" class="printBox" style="margin: 0; color: rgba(0, 0, 0, 1); padding: 5px">
|
||||||
<div class="title" style="font-size: 1.2rem; margin-bottom: 10px; text-indent: 5em">{{ print_form.title }}</div>
|
<div class="title" style="font-size: 1.2rem; margin-bottom: 10px; text-indent: 5em">{{ print_form.title }}</div>
|
||||||
<div style="font-size: 12px; display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 10px; grid-template-rows: 1fr">
|
<div style="font-size: 12px; display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 10px; grid-template-rows: 1fr">
|
||||||
<div>单据日期:{{ print_form.printDate }}</div>
|
<div>单据日期:{{ print_form.printDate }}</div>
|
||||||
@@ -425,8 +446,8 @@
|
|||||||
<div style="flex: 1">交款人:</div>
|
<div style="flex: 1">交款人:</div>
|
||||||
<div style="flex: 1; display: flex; align-items: center">
|
<div style="flex: 1; display: flex; align-items: center">
|
||||||
<span style="white-space: nowrap">收款人: </span>
|
<span style="white-space: nowrap">收款人: </span>
|
||||||
<el-input v-model="inHomelyUse" v-if="!isPrint" placeholder="请输入收款人姓名" style="width: 150px"></el-input>
|
<el-input v-if="!isPrint" v-model="inHomelyUse" placeholder="请输入收款人姓名" style="width: 150px"></el-input>
|
||||||
<span style="white-space: nowrap" v-else> {{ inHomelyUse }}</span>
|
<span v-else style="white-space: nowrap"> {{ inHomelyUse }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -435,7 +456,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
@@ -444,7 +465,7 @@ import { getCommunitylistAPI } from '@/api/system/community';
|
|||||||
import { billDelete, billEdit, billlistType, billPrint, BillPrintType, billQuery, getAllAccount } from '@/api/system/SdbCashier';
|
import { billDelete, billEdit, billlistType, billPrint, BillPrintType, billQuery, getAllAccount } from '@/api/system/SdbCashier';
|
||||||
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { add, div, eq, eqMoney, gtMoney, ltMoney, minMoney, moneyAdd, mul, sub, sum, toBig } from '@/utils/money';
|
import { add, div, eq, eqMoney, gtMoney, minMoney, moneyAdd, mul, sub, sum, toBig } from '@/utils/money';
|
||||||
import { BuildingUnitlist, BuildingVo, FloorsType } from '@/api/system/house/type';
|
import { BuildingUnitlist, BuildingVo, FloorsType } from '@/api/system/house/type';
|
||||||
import { ChargeItemVO } from '@/api/system/SdbChargeItem/type';
|
import { ChargeItemVO } from '@/api/system/SdbChargeItem/type';
|
||||||
import { communitylist_rows_type } from '@/api/system/community/type';
|
import { communitylist_rows_type } from '@/api/system/community/type';
|
||||||
@@ -456,6 +477,18 @@ import { useUserStore } from '@/store/modules/user';
|
|||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_pay_method, com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_pay_method', 'com_charge_item_unit'));
|
const { com_pay_method, com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_pay_method', 'com_charge_item_unit'));
|
||||||
|
|
||||||
|
/** 支付状态 */
|
||||||
|
const PayStatus = {
|
||||||
|
/** 待缴纳 */
|
||||||
|
PENDING: '0',
|
||||||
|
/** 已缴纳 */
|
||||||
|
PAID: '1',
|
||||||
|
/** 缴纳失败 */
|
||||||
|
FAILED: '2',
|
||||||
|
/** 部分缴纳 */
|
||||||
|
PARTIAL: '3'
|
||||||
|
} as const;
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const ids = ref<Array<billlistType>>([]);
|
const ids = ref<Array<billlistType>>([]);
|
||||||
@@ -468,15 +501,15 @@ const tabs = [
|
|||||||
type: '全部'
|
type: '全部'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 0,
|
value: PayStatus.PENDING,
|
||||||
type: '待缴纳'
|
type: '待缴纳'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 1,
|
value: PayStatus.PAID,
|
||||||
type: '已缴纳'
|
type: '已缴纳'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 3,
|
value: PayStatus.PARTIAL,
|
||||||
type: '部分缴纳'
|
type: '部分缴纳'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -512,6 +545,8 @@ const queryParams = ref({
|
|||||||
// 结束时间
|
// 结束时间
|
||||||
endDate: undefined
|
endDate: undefined
|
||||||
});
|
});
|
||||||
|
// ts工具 排除参数
|
||||||
|
type ExcludeType = keyof Omit<typeof queryParams.value, 'villageId' | 'pageSize' | 'pageNum'>;
|
||||||
|
|
||||||
const villageList = ref<communitylist_rows_type[]>([]); // 小区列表
|
const villageList = ref<communitylist_rows_type[]>([]); // 小区列表
|
||||||
const buildingList = ref<BuildingVo[]>([]); // 楼栋列表
|
const buildingList = ref<BuildingVo[]>([]); // 楼栋列表
|
||||||
@@ -530,7 +565,7 @@ function getHouseTypeList() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 切换 账单类型
|
// 切换 账单类型
|
||||||
function changeTabs(value: number) {
|
function changeTabs(value: string) {
|
||||||
activeTabs.value = value;
|
activeTabs.value = value;
|
||||||
queryParams.value.payStatus = value;
|
queryParams.value.payStatus = value;
|
||||||
getList();
|
getList();
|
||||||
@@ -567,12 +602,17 @@ function handleChangeBuilding(val: string): void {
|
|||||||
queryParams.value.unitNoId = undefined;
|
queryParams.value.unitNoId = undefined;
|
||||||
queryParams.value.houseId = undefined;
|
queryParams.value.houseId = undefined;
|
||||||
unitList.value = [];
|
unitList.value = [];
|
||||||
getHouselistAPI(val).then((res) => {
|
if (val !== undefined) {
|
||||||
unitList.value = res.data.units;
|
getHouselistAPI(val).then((res) => {
|
||||||
});
|
unitList.value = res.data.units;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 选择 单元
|
// 选择 单元
|
||||||
function handleChangeUnit(val: string) {
|
function handleChangeUnit(val: string) {
|
||||||
|
if (val === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const find = unitList.value.find((item) => item.unitNoId === val);
|
const find = unitList.value.find((item) => item.unitNoId === val);
|
||||||
queryParams.value.houseId = undefined;
|
queryParams.value.houseId = undefined;
|
||||||
houseList.value = [];
|
houseList.value = [];
|
||||||
@@ -580,13 +620,7 @@ function handleChangeUnit(val: string) {
|
|||||||
houseList.value = find.floors;
|
houseList.value = find.floors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 选择房屋
|
|
||||||
function handleChangeHouseNo() {}
|
|
||||||
|
|
||||||
// 清空缴费时间
|
|
||||||
function handleClearPayTime(type: 'payTimeBegin' | 'payTimeEnd') {
|
|
||||||
queryParams.value[type] = undefined;
|
|
||||||
}
|
|
||||||
// 清空缴费周期
|
// 清空缴费周期
|
||||||
function handleClearChargePeriod(type: 'start' | 'end' = 'start') {
|
function handleClearChargePeriod(type: 'start' | 'end' = 'start') {
|
||||||
if (type === 'start') {
|
if (type === 'start') {
|
||||||
@@ -602,7 +636,6 @@ function getList() {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
tableData.value = res.rows;
|
tableData.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
handleSelectBill(res.rows);
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
@@ -612,11 +645,11 @@ function getList() {
|
|||||||
|
|
||||||
function getAllBillAmount() {
|
function getAllBillAmount() {
|
||||||
getAllAccount(queryParams.value).then((res) => {
|
getAllAccount(queryParams.value).then((res) => {
|
||||||
console.log(res);
|
|
||||||
totalAll.value = {
|
totalAll.value = {
|
||||||
totalDiscountAmount: res.data.discountAmount, // 总优惠金额
|
totalDiscountAmount: res.data.discountAmount, // 总优惠金额
|
||||||
TotalPaymentAmount: res.data.receivedAmount, // 总实收金额
|
TotalPaymentAmount: res.data.receivedAmount, // 总实收金额
|
||||||
totalAccount: res.data.receivableAmount, // 总金额
|
totalAccount: res.data.receivableAmount, // 总 应收金额
|
||||||
|
originalAmount: res.data.originalAmount, // 原始金额之和(应收+优惠)
|
||||||
TotalUnPaymentAmount: res.data.unpaidAmount // 未收金额
|
TotalUnPaymentAmount: res.data.unpaidAmount // 未收金额
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -628,30 +661,51 @@ const handleQuery = () => {
|
|||||||
getList();
|
getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 优化后
|
||||||
|
const defaultQueryParams = () => ({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
payStatus: null as number | null,
|
||||||
|
villageId: villageId as string | undefined,
|
||||||
|
buildingId: undefined,
|
||||||
|
unitNoId: undefined,
|
||||||
|
houseId: undefined,
|
||||||
|
houseUseTypeId: undefined,
|
||||||
|
payTime: undefined,
|
||||||
|
residentName: undefined,
|
||||||
|
chargeItemId: undefined,
|
||||||
|
period: undefined,
|
||||||
|
payTimeBegin: undefined,
|
||||||
|
payTimeEnd: undefined,
|
||||||
|
startDate: undefined,
|
||||||
|
endDate: undefined
|
||||||
|
});
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value?.resetFields();
|
queryFormRef.value?.resetFields();
|
||||||
queryParams.value = {
|
queryParams.value = {
|
||||||
startDate: undefined,
|
...defaultQueryParams(),
|
||||||
payTime: undefined,
|
payStatus: queryParams.value.payStatus // 保留当前 tab
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 20,
|
|
||||||
payStatus: null,
|
|
||||||
villageId: undefined,
|
|
||||||
buildingId: undefined,
|
|
||||||
unitNoId: undefined,
|
|
||||||
houseId: undefined,
|
|
||||||
chargeItemId: undefined,
|
|
||||||
period: undefined,
|
|
||||||
houseUseTypeId: undefined,
|
|
||||||
residentName: undefined,
|
|
||||||
payTimeBegin: undefined,
|
|
||||||
payTimeEnd: undefined,
|
|
||||||
endDate: undefined
|
|
||||||
};
|
};
|
||||||
queryParams.value.villageId = villageId;
|
|
||||||
handleQuery();
|
handleQuery();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 清空楼栋
|
||||||
|
function handleClearBuildingId() {
|
||||||
|
queryParams.value.buildingId = undefined;
|
||||||
|
queryParams.value.unitNoId = undefined;
|
||||||
|
queryParams.value.houseId = undefined;
|
||||||
|
}
|
||||||
|
// 清空单元
|
||||||
|
function handleClearUnit() {
|
||||||
|
queryParams.value.unitNoId = undefined;
|
||||||
|
queryParams.value.houseId = undefined;
|
||||||
|
}
|
||||||
|
// 清空其他参数
|
||||||
|
function handleClear(type: ExcludeType) {
|
||||||
|
queryParams.value[type] = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
// 控制收费 按钮 不能有已缴纳的(后端会校验)
|
// 控制收费 按钮 不能有已缴纳的(后端会校验)
|
||||||
const single = ref(true);
|
const single = ref(true);
|
||||||
// 控制打印票据的 按钮 不能有收费的
|
// 控制打印票据的 按钮 不能有收费的
|
||||||
@@ -660,9 +714,9 @@ const printSingle = ref(true);
|
|||||||
const handleSelectionChange = (selection: billlistType[]) => {
|
const handleSelectionChange = (selection: billlistType[]) => {
|
||||||
ids.value = selection.map((item) => item);
|
ids.value = selection.map((item) => item);
|
||||||
// 不能全部都是已缴纳的 0待缴纳 1已缴纳 2缴纳失败 3混合缴纳
|
// 不能全部都是已缴纳的 0待缴纳 1已缴纳 2缴纳失败 3混合缴纳
|
||||||
single.value = ids.value.every((item) => item.payStatus === '0' || item.payStatus === '3');
|
single.value = ids.value.every((item) => item.payStatus === PayStatus.PENDING || item.payStatus === PayStatus.PARTIAL);
|
||||||
// 必须都要缴费后打印
|
// 必须都要缴费后打印
|
||||||
printSingle.value = ids.value.every((item) => item.payStatus === '1');
|
printSingle.value = ids.value.every((item) => item.payStatus === PayStatus.PAID);
|
||||||
};
|
};
|
||||||
const buttonLoading = ref(false);
|
const buttonLoading = ref(false);
|
||||||
// 是否多选
|
// 是否多选
|
||||||
@@ -695,7 +749,7 @@ function initInComeFrom() {
|
|||||||
allCost: 0, // 总金额
|
allCost: 0, // 总金额
|
||||||
billResidentId: [], // 账单id
|
billResidentId: [], // 账单id
|
||||||
payStatus: '1', // 0:未缴 1:已缴 2: 缴纳失败 3: 部分缴纳
|
payStatus: '1', // 0:未缴 1:已缴 2: 缴纳失败 3: 部分缴纳
|
||||||
payType: '2', // 0:微信 1:支付宝 2 线下
|
payType: '2', // 0:微信 1:支付宝
|
||||||
remark: '',
|
remark: '',
|
||||||
discountMethod: 0, // 优惠方式 0 不优惠 1 比例 2 金额
|
discountMethod: 0, // 优惠方式 0 不优惠 1 比例 2 金额
|
||||||
discountRate: '0', // 优惠比例 10 === 10%
|
discountRate: '0', // 优惠比例 10 === 10%
|
||||||
@@ -754,7 +808,7 @@ function handleChangeDiscountMoney(val: string) {
|
|||||||
if (isMore) {
|
if (isMore) {
|
||||||
// 过滤:只保留未支付账单,已支付直接丢弃
|
// 过滤:只保留未支付账单,已支付直接丢弃
|
||||||
const unPaidList = ids.value.filter((item) => {
|
const unPaidList = ids.value.filter((item) => {
|
||||||
return item.payStatus !== '1';
|
return item.payStatus !== PayStatus.PAID;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算优惠总额
|
// 计算优惠总额
|
||||||
@@ -813,7 +867,7 @@ function handleChangeDiscountRate(val: string) {
|
|||||||
// 批量多选模式
|
// 批量多选模式
|
||||||
if (isMore) {
|
if (isMore) {
|
||||||
const unPaidList = ids.value.filter((item) => {
|
const unPaidList = ids.value.filter((item) => {
|
||||||
return item.payStatus !== '1';
|
return item.payStatus !== PayStatus.PAID;
|
||||||
});
|
});
|
||||||
// 总价格
|
// 总价格
|
||||||
const sourceTotal = sum(unPaidList.map((item) => item.needPayAmount ?? 0));
|
const sourceTotal = sum(unPaidList.map((item) => item.needPayAmount ?? 0));
|
||||||
@@ -858,7 +912,7 @@ function handleIncome(row: billlistType | false) {
|
|||||||
ids.value.forEach((item) => {
|
ids.value.forEach((item) => {
|
||||||
set.add(item.residentId);
|
set.add(item.residentId);
|
||||||
});
|
});
|
||||||
if (ids.value.some((item) => item.payStatus === '1')) {
|
if (ids.value.some((item) => item.payStatus === PayStatus.PAID)) {
|
||||||
return ElMessage.warning('存在已支付账单,请重新选择');
|
return ElMessage.warning('存在已支付账单,请重新选择');
|
||||||
}
|
}
|
||||||
if (set.size > 1) {
|
if (set.size > 1) {
|
||||||
@@ -869,7 +923,7 @@ function handleIncome(row: billlistType | false) {
|
|||||||
inComeFrom.value.residentName = ids.value[0].residentName;
|
inComeFrom.value.residentName = ids.value[0].residentName;
|
||||||
ids.value.forEach((item) => {
|
ids.value.forEach((item) => {
|
||||||
inComeFrom.value.billResidentId.push(item);
|
inComeFrom.value.billResidentId.push(item);
|
||||||
if (item.payStatus === '0' || item.payStatus === '3') {
|
if (item.payStatus === PayStatus.PENDING || item.payStatus === PayStatus.PARTIAL) {
|
||||||
inComeFrom.value.allCost = moneyAdd(inComeFrom.value.allCost || 0, item.needPayAmount);
|
inComeFrom.value.allCost = moneyAdd(inComeFrom.value.allCost || 0, item.needPayAmount);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -892,12 +946,18 @@ const submitForm = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
// 部分缴纳时 不管
|
// 部分缴纳时 判断 支付金额 和 预计支付金额 是否相等 ,相等 则 可选择 部分缴纳 方式
|
||||||
|
if (inComeFrom.value.payStatus === PayStatus.PARTIAL) {
|
||||||
|
if (eqMoney(totalPayAmount.value, payListAllAmount.value)) {
|
||||||
|
buttonLoading.value = false;
|
||||||
|
return ElMessage.warning('实缴金额等于应收金额时,请选择 【已缴纳】 状态');
|
||||||
|
}
|
||||||
|
}
|
||||||
// 已缴纳时 判断 支付金额 和 预计支付金额 是否相等
|
// 已缴纳时 判断 支付金额 和 预计支付金额 是否相等
|
||||||
if (inComeFrom.value.payStatus === '1') {
|
if (inComeFrom.value.payStatus === PayStatus.PAID) {
|
||||||
if (!eqMoney(totalPayAmount.value, payListAllAmount.value)) {
|
if (!eqMoney(totalPayAmount.value, payListAllAmount.value)) {
|
||||||
buttonLoading.value = false;
|
buttonLoading.value = false;
|
||||||
return ElMessage.warning('支付金额不足,可选择 部分缴纳 方式');
|
return ElMessage.warning('支付金额不足,可以选择 【部分缴纳】 状态');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const obj = {
|
const obj = {
|
||||||
@@ -920,6 +980,37 @@ const submitForm = () => {
|
|||||||
buttonLoading.value = false;
|
buttonLoading.value = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
function handleRoute(row: billlistType) {
|
||||||
|
const villageId = localStorage.getItem('villageid');
|
||||||
|
if (row.villageId !== villageId) {
|
||||||
|
ElMessage.warning('非本小区房屋/车位/车辆');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (row.detailsType) {
|
||||||
|
case '0':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
router.push({
|
||||||
|
path: '/house/HouseDetails',
|
||||||
|
query: {
|
||||||
|
id: row.unitNoId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
router.push({
|
||||||
|
path: '/carArea/parkMain',
|
||||||
|
query: {
|
||||||
|
id: row.unitNoId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 打印票据--------------------------------------------------------------
|
// 打印票据--------------------------------------------------------------
|
||||||
const isPrint = ref(false);
|
const isPrint = ref(false);
|
||||||
@@ -1054,22 +1145,14 @@ function conFimPrint() {
|
|||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
async function handleDelete(row: billlistType | false) {
|
async function handleDelete(row: billlistType | false) {
|
||||||
if (row) {
|
const targetIds = row ? [row.detailsId] : ids.value.map((item) => item.detailsId);
|
||||||
await proxy?.$modal.confirm('该信息删除后无法恢复,确定要删除吗?');
|
if (targetIds.length === 0) {
|
||||||
billDelete(row.detailsId).then(() => {
|
return ElMessage.warning('请选择账单!');
|
||||||
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();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
await proxy?.$modal.confirm('该信息删除后无法恢复,确定要删除吗?');
|
||||||
|
await billDelete(targetIds);
|
||||||
|
ElMessage.success('删除成功');
|
||||||
|
getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -1086,18 +1169,17 @@ onMounted(() => {
|
|||||||
// 总 表单
|
// 总 表单
|
||||||
const totalAll = ref({
|
const totalAll = ref({
|
||||||
totalDiscountAmount: '0', // 总优惠金额
|
totalDiscountAmount: '0', // 总优惠金额
|
||||||
TotalPaymentAmount: '0', // 总实收金额
|
TotalPaymentAmount: '0', // 总已收金额
|
||||||
totalAccount: '0', // 总金额
|
totalAccount: '0', // 总 应收金额
|
||||||
|
originalAmount: '0', // 原始金额之和(应收+优惠)
|
||||||
TotalUnPaymentAmount: '0' // 未收金额
|
TotalUnPaymentAmount: '0' // 未收金额
|
||||||
});
|
});
|
||||||
// 多选时 统计总金额,优惠总金额,实付总金额
|
|
||||||
function handleSelectBill() {}
|
|
||||||
|
|
||||||
function handleChangePayTypeId(val: string, index: number) {
|
function handleChangePayTypeId(val: string, index: number) {
|
||||||
// 【可选兜底校验】防止异常数据出现重复
|
// 【可选兜底校验】防止异常数据出现重复
|
||||||
const repeatCount = usedPayValues.value.filter((v) => v === val).length;
|
const repeatCount = usedPayValues.value.filter((v) => v === val).length;
|
||||||
if (repeatCount > 1) {
|
if (repeatCount > 1) {
|
||||||
payList.value[index].payType = null;
|
payList.value[index].payType = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const usedPayValues = computed(() => {
|
const usedPayValues = computed(() => {
|
||||||
@@ -1109,15 +1191,20 @@ const isOptionDisabled = (optVal: string, currentVal: any) => {
|
|||||||
return usedPayValues.value.includes(optVal);
|
return usedPayValues.value.includes(optVal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 支付列表项类型 */
|
||||||
|
interface PayListItem {
|
||||||
|
payType: string;
|
||||||
|
payAmount: number | null;
|
||||||
|
}
|
||||||
// 混合支付 列表
|
// 混合支付 列表
|
||||||
const payList = ref([
|
const payList = ref<PayListItem[]>([
|
||||||
{
|
{
|
||||||
payType: '',
|
payType: '',
|
||||||
payAmount: null
|
payAmount: null
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
// 混合支付 总金额
|
// 混合支付 总金额
|
||||||
const payListAllAmount = computed(() => {
|
const payListAllAmount = computed<number>(() => {
|
||||||
return sum(payList.value.map((item) => item.payAmount ?? 0));
|
return sum(payList.value.map((item) => item.payAmount ?? 0));
|
||||||
});
|
});
|
||||||
// 添加支付方式
|
// 添加支付方式
|
||||||
@@ -1131,27 +1218,32 @@ function addPayList() {
|
|||||||
function removePayList(index: number) {
|
function removePayList(index: number) {
|
||||||
payList.value.splice(index, 1);
|
payList.value.splice(index, 1);
|
||||||
}
|
}
|
||||||
// 数据框改变时 检测数据是否大于 总金额
|
// 数据框改变时 检测数据是否大于 总金额, 如果大于则自动回填剩余金额
|
||||||
function handleChangePay(val: string, index: number = -1) {
|
function handleChangePay(val: string, index: number = -1) {
|
||||||
if (!checkMoney(val)) {
|
if (!checkMoney(val)) {
|
||||||
ElMessage.warning('金额格式错误');
|
ElMessage.warning('金额格式错误');
|
||||||
payList.value[index].payAmount = null;
|
payList.value[index].payAmount = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 如果 当前行输入的金额 大于 总实缴金额
|
||||||
|
// 则在当前行,自动回填正确剩余金额
|
||||||
if (gtMoney(payListAllAmount.value, totalPayAmount.value)) {
|
if (gtMoney(payListAllAmount.value, totalPayAmount.value)) {
|
||||||
ElMessage.warning('输入金额 总和 不能大于 总实缴金额');
|
ElMessage.warning('输入金额 总和 不能大于 总实缴金额');
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
payList.value[index].payAmount = 0;
|
|
||||||
// 自动回填
|
// 自动回填
|
||||||
payList.value[index].payAmount = sub(totalPayAmount.value, payListAllAmount.value);
|
// BUG: payAmount=0,让 payListAllAmount’s computed 只算其他行,然后 补 回来
|
||||||
}
|
// payList.value[index].payAmount = 0;
|
||||||
}
|
// payList.value[index].payAmount = sub(totalPayAmount.value, payListAllAmount.value);
|
||||||
// 已缴纳状态时,输入金额 总和 不能小于 总实缴金额
|
// 总实缴 - (全部总和 - 当前行刚输入的值) = 总实缴 - 其他行总和 = 当前行剩余应缴金额
|
||||||
if (inComeFrom.value.payStatus === '1') {
|
payList.value[index].payAmount = sub(totalPayAmount.value, sub(payListAllAmount.value, val));
|
||||||
if (ltMoney(payListAllAmount.value, totalPayAmount.value)) {
|
|
||||||
ElMessage.warning('输入金额 总和 不能小于 总实缴金额');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// // 已缴纳状态时,输入金额 总和 不能小于 总实缴金额
|
||||||
|
// if (inComeFrom.value.payStatus === PayStatus.PAID) {
|
||||||
|
// if (ltMoney(payListAllAmount.value, totalPayAmount.value)) {
|
||||||
|
// ElMessage.warning('输入金额 总和 不能小于 总实缴金额');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePayListIsEmpty() {
|
function handlePayListIsEmpty() {
|
||||||
@@ -1160,13 +1252,7 @@ function handlePayListIsEmpty() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const invalidIndex = payList.value.findIndex(
|
const invalidIndex = payList.value.findIndex(
|
||||||
(item) =>
|
(item) => item.payType === null || item.payType === undefined || item.payType === '' || item.payAmount === null || item.payAmount === undefined
|
||||||
item.payType === null ||
|
|
||||||
item.payType === undefined ||
|
|
||||||
item.payType === '' ||
|
|
||||||
item.payAmount === null ||
|
|
||||||
item.payAmount === undefined ||
|
|
||||||
item.payAmount === ''
|
|
||||||
);
|
);
|
||||||
return invalidIndex === -1;
|
return invalidIndex === -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
<div>基本信息</div>
|
<div>基本信息</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bodybox">
|
<div class="bodyBox">
|
||||||
<el-form label-width="100px" label-position="right">
|
<el-form label-position="right" label-width="100px">
|
||||||
<el-form-item label="设备编码" prop="deviceCode">
|
<el-form-item label="设备编码" prop="deviceCode">
|
||||||
<el-input v-model="form.deviceCode" placeholder="请输入"></el-input>
|
<el-input v-model="form.deviceCode" placeholder="请输入"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -15,12 +15,12 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="分合状态">
|
<el-form-item label="分合状态">
|
||||||
<el-radio-group v-model="form.electricityRecord.status">
|
<el-radio-group v-model="form.electricityRecord.status">
|
||||||
<el-radio v-for="(item, index) in com_electricity_readrecord_status" :key="index" :value="item.value" :label="item.label"></el-radio>
|
<el-radio v-for="(item, index) in com_electricity_readrecord_status" :key="index" :label="item.label" :value="item.value"></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary">提交</el-button>
|
<el-button type="primary">提交</el-button>
|
||||||
<el-button @click="routeback">返回</el-button>
|
<el-button @click="routeBack">返回</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { getElectricityDevice } from '@/api/system/SdbElectricityDevice';
|
import { getElectricityDevice } from '@/api/system/SdbElectricityDevice';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
@@ -49,11 +49,11 @@ const form = ref({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const editid = ref(null);
|
const editId = ref(null);
|
||||||
function init() {
|
function init() {
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
editid.value = route.query.id;
|
editId.value = route.query.id;
|
||||||
getElectricityDevice(editid.value).then((res) => {
|
getElectricityDevice(editId.value).then((res) => {
|
||||||
form.value = {
|
form.value = {
|
||||||
...form.value,
|
...form.value,
|
||||||
...res.data
|
...res.data
|
||||||
@@ -64,17 +64,17 @@ function init() {
|
|||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
function routeback() {
|
function routeBack() {
|
||||||
router.back();
|
router.back();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.EditBody {
|
.EditBody {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
.bodybox {
|
.bodyBox {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
margin: 20px auto 0;
|
margin: 20px auto 0;
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ function routeback() {
|
|||||||
color: #000;
|
color: #000;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.iconbox {
|
.iconBox {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" label-width="100px" @submit.prevent="handleQuery" :model="queryParams" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" label-width="100px" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="设备编号" prop="deviceCode">
|
<el-form-item label="设备编号" prop="deviceCode">
|
||||||
<el-input maxlength="25" v-model="queryParams.deviceCode" placeholder="请输入" clearable />
|
<el-input v-model="queryParams.deviceCode" clearable maxlength="25" placeholder="请输入" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="房屋号" prop="houseName">
|
<el-form-item label="房屋号" prop="houseName">
|
||||||
<el-input maxlength="20" v-model="queryParams.houseName" placeholder="请输入" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.houseName" clearable maxlength="20" placeholder="请输入" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -26,15 +26,19 @@
|
|||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<div style="font-size: 0.8rem">电表列表</div>
|
<div style="font-size: 0.8rem">电表列表</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :show-add="false" :show-edit="false" :show-delete="false">
|
<right-toolbar :show-add="false" :show-delete="false" :show-edit="false">
|
||||||
|
<template #actions>
|
||||||
|
<el-button icon="Upload" plain type="success" @click="handleOpenDialog('UploadDevices')">导入设备</el-button>
|
||||||
|
<el-button icon="Download" plain type="warning" @click="handleExport">获取导入模板</el-button>
|
||||||
|
</template>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-item @click="handleMarkQRCode" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
<el-dropdown-item @click="handleMarkQRCode">
|
||||||
<span>批量生成条形码</span>
|
<span>批量生成条形码</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item @click="handleMarkQrcodeZip" v-if="checkPermi(['equipment:addqrcode:electricitydevice'])">
|
<el-dropdown-item @click="handleMarkQrcodeZip">
|
||||||
<span>批量下载条形码</span>
|
<span>批量下载条形码</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<!-- <el-dropdown-item v-has-permi="['equipment:addqrcode:electricitydevice']">
|
<!-- <el-dropdown-item >
|
||||||
<div @click="handleMarkQRCode">批量更新固件</div>
|
<div @click="handleMarkQRCode">批量更新固件</div>
|
||||||
</el-dropdown-item> -->
|
</el-dropdown-item> -->
|
||||||
</template>
|
</template>
|
||||||
@@ -42,41 +46,42 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="ElectricityDeviceList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="ElectricityDeviceList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="设备编码" width="250" align="center" prop="deviceCode" />
|
<el-table-column align="center" label="设备编码" prop="deviceCode" width="250" />
|
||||||
<el-table-column label="设备状态" width="100" align="center" prop="status">
|
<el-table-column align="center" label="设备状态" prop="status" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="readRecord" v-if="scope.row.status !== null">
|
<div v-if="scope.row.status !== null" class="readRecord">
|
||||||
<DictTag :options="com_waterdevice_on_status" :value="scope.row.status"></DictTag>
|
<DictTag :options="com_waterdevice_on_status" :value="scope.row.status"></DictTag>
|
||||||
</div>
|
</div>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="分合状态" width="100" align="center">
|
<el-table-column align="center" label="分合状态" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="readRecord" v-if="scope.row.electricityRecord">
|
<div v-if="scope.row.electricityRecord" class="readRecord">
|
||||||
<DictTag :options="com_electricity_readrecord_status" :value="scope.row.electricityRecord.status"></DictTag>
|
<DictTag :options="com_electricity_readrecord_status" :value="scope.row.electricityRecord.status"></DictTag>
|
||||||
</div>
|
</div>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="房屋号" align="center" prop="houseName" />
|
<el-table-column align="center" label="房屋号" prop="houseName" />
|
||||||
<el-table-column label="余额" width="100" align="center">
|
<el-table-column align="center" label="余额" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.electricityRecord">{{ scope.row.electricityRecord.balance }}</span>
|
<span v-if="scope.row.electricityRecord">{{ scope.row.electricityRecord.balance }}</span>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="条码" width="250" align="center" prop="deleted">
|
<el-table-column align="center" label="条码" prop="deleted" width="250">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-image
|
<el-image
|
||||||
v-if="scope.row.url && scope.row.url.includes('http')"
|
v-if="scope.row.url && scope.row.url.includes('http')"
|
||||||
:src="scope.row.url"
|
|
||||||
:preview-src-list="[scope.row.url]"
|
:preview-src-list="[scope.row.url]"
|
||||||
style="width: 90%; height: 100%"
|
:src="scope.row.url"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
|
lazy
|
||||||
preview-teleported
|
preview-teleported
|
||||||
|
style="width: 90%; height: 100%; max-width: 150px"
|
||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-icon @click="download(scope.row.url)"><Download /></el-icon>
|
<el-icon @click="download(scope.row.url)"><Download /></el-icon>
|
||||||
@@ -85,100 +90,72 @@
|
|||||||
<span v-else>暂未生成</span>
|
<span v-else>暂未生成</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="抄表时间" align="center">
|
<el-table-column align="center" label="抄表时间">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.electricityRecord ? scope.row.electricityRecord.readTime : '--' }}</span>
|
<span>{{ scope.row.electricityRecord ? scope.row.electricityRecord.readTime : '--' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- <el-table-column width="150" label="启停" align="center" prop="deleted" v-has-permi="['equipment:isUse:electricitydevice']">
|
<el-table-column align="center" label="启停" prop="deleted" width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch
|
<el-switch
|
||||||
@change="(val: string) => handleChangeWater(val, scope.row)"
|
v-if="scope.row.electricityRecord"
|
||||||
v-model="scope.row.deleted"
|
:active-value="true"
|
||||||
active-text="启用"
|
:before-change="
|
||||||
inactive-text="停止"
|
() => {
|
||||||
active-value="0"
|
// 0 合闸 1 2 拉闸
|
||||||
inactive-value="1"
|
// 0 合闸 传入 1 拉闸 传入 0
|
||||||
|
const status = scope.row.electricityRecord.status === 0 ? 1 : 0;
|
||||||
|
return handleChangeWater(status, scope.row);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:inactive-value="false"
|
||||||
|
:model-value="scope.row.electricityRecord.status === 0"
|
||||||
|
active-text="合闸"
|
||||||
|
inactive-text="拉闸"
|
||||||
></el-switch>
|
></el-switch>
|
||||||
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column> -->
|
</el-table-column>
|
||||||
<el-table-column min-width="120" label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" min-width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<el-button link type="primary" @click="handleRecode(scope.row)" v-has-permi="['equipment:view:electricitydevice']">充值记录</el-button>
|
<el-button link type="primary" @click="handleRecode(scope.row)">充值记录</el-button>
|
||||||
<el-button link type="primary" @click="handleQrCode(scope.row)" v-has-permi="['equipment:addqrcode:electricitydevice']"
|
<el-button link type="primary" @click="handleQrCode(scope.row)">生成条码</el-button>
|
||||||
>生成条码</el-button
|
<el-button link type="primary" @click="handleOpenDialog('usedWater', scope.row)">用电量</el-button>
|
||||||
>
|
<el-button link type="primary" @click="handleOpenDialog('recharge', scope.row)">充值</el-button>
|
||||||
<el-button link type="primary" @click="handleOpenDialog('usedWater', scope.row)" v-has-permi="['equipment:useWater:electricitydevice']"
|
<!-- <el-button link type="primary" @click="handleOpenDialog('price', scope.row)">设置价格</el-button>-->
|
||||||
>用电量</el-button
|
<el-button v-if="!scope.row.houseName" link type="primary" @click="handleOpenDialog('UpdateHouse', scope.row)">绑定房屋</el-button>
|
||||||
>
|
<el-button v-else link type="primary" @click="handleUnbind(scope.row)">解绑房屋</el-button>
|
||||||
<!-- <el-button
|
<el-button link type="primary" @click="handleUpload(scope.row)">更新数据</el-button>
|
||||||
link
|
|
||||||
type="primary"
|
|
||||||
@click="handleOpenDialog('Upload', scope.row)"
|
|
||||||
v-has-permi="['equipment:updatehardware:electricitydevice']"
|
|
||||||
>更新固件</el-button
|
|
||||||
> -->
|
|
||||||
<el-button
|
|
||||||
link
|
|
||||||
v-if="!scope.row.houseName"
|
|
||||||
type="primary"
|
|
||||||
@click="handleOpenDialog('UpdateHouse', scope.row)"
|
|
||||||
v-has-permi="['equipment:edithouse:electricitydevice']"
|
|
||||||
>绑定房屋</el-button
|
|
||||||
>
|
|
||||||
<el-button v-else link type="primary" @click="handleUnbind(scope.row)" v-has-permi="['equipment:edithouse:electricitydevice']"
|
|
||||||
>解绑房屋</el-button
|
|
||||||
>
|
|
||||||
<!-- <el-dropdown style="vertical-align: text-top">
|
|
||||||
<el-button link type="primary">
|
|
||||||
<div>
|
|
||||||
更多<el-icon><arrow-down /></el-icon>
|
|
||||||
</div>
|
|
||||||
</el-button>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item>
|
|
||||||
<div @click="handleOpenDialog('usedWater', scope.row)" v-has-permi="['equipment:used:electricitydevice']">用电量</div>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item>
|
|
||||||
<div @click="handleOpenDialog('Upload', scope.row)" v-has-permi="['equipment:updatehardware:electricitydevice']">更新固件</div>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item>
|
|
||||||
<div @click="handleOpenDialog('UpdateHouse', scope.row)" v-has-permi="['equipment:edithouse:electricitydevice']">修改</div>
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown> -->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改电 设备对话框 -->
|
<!-- 添加或修改电 设备对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<el-form v-if="dialogType === 'usedWater'" :rules="rules" ref="UsedWaterFormRef" :model="UsedWaterform" label-width="100px">
|
<el-form v-if="dialogType === 'usedWater'" ref="UsedWaterFormRef" :model="UsedWaterForm" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="设备编号" prop="deviceCode"> {{ UsedWaterform.deviceCode }} </el-form-item>
|
<el-form-item label="设备编号" prop="deviceCode"> {{ UsedWaterForm.deviceCode }} </el-form-item>
|
||||||
<el-form-item label="开始时间" prop="startTime">
|
<el-form-item label="开始时间" prop="startTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
|
v-model="UsedWaterForm.startTime"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
v-model="UsedWaterform.startTime"
|
|
||||||
type="datetime"
|
|
||||||
@update:model-value="handleStarTime"
|
|
||||||
placeholder="开始时间"
|
placeholder="开始时间"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@update:model-value="handleStarTime"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="结束时间" prop="endTime">
|
<el-form-item label="结束时间" prop="endTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
|
v-model="UsedWaterForm.endTime"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
v-model="UsedWaterform.endTime"
|
|
||||||
type="datetime"
|
|
||||||
@update:model-value="handleEndTime"
|
|
||||||
placeholder="结束时间"
|
placeholder="结束时间"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@update:model-value="handleEndTime"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -190,14 +167,14 @@
|
|||||||
<el-form-item label="上传更新文件" prop="file">
|
<el-form-item label="上传更新文件" prop="file">
|
||||||
<el-upload
|
<el-upload
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
accept=".bin"
|
|
||||||
:action="uploadUrl"
|
:action="uploadUrl"
|
||||||
name="file"
|
|
||||||
:headers="headerToken()"
|
|
||||||
:show-file-list="true"
|
|
||||||
class="upload-demo"
|
|
||||||
:on-success="handleAvatarSuccess"
|
|
||||||
:before-upload="beforeAvatarUpload"
|
:before-upload="beforeAvatarUpload"
|
||||||
|
:headers="headerToken()"
|
||||||
|
:on-success="handleAvatarSuccess"
|
||||||
|
:show-file-list="true"
|
||||||
|
accept=".bin"
|
||||||
|
class="upload-demo"
|
||||||
|
name="file"
|
||||||
>
|
>
|
||||||
<div class="uploadFileBox flex flex-items-center">
|
<div class="uploadFileBox flex flex-items-center">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@@ -224,40 +201,112 @@
|
|||||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">更新到设备</el-button>
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">更新到设备</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
<el-form v-else-if="dialogType === 'recharge'" ref="rechargeFormRef" :model="reChargeForm" label-width="100px">
|
||||||
|
<el-form-item label="充值金额" prop="amount">
|
||||||
|
<el-input-number v-model.trim.number="reChargeForm.amount" :max="99999" :min="0" :step="0.1"> </el-input-number
|
||||||
|
><span style="padding-left: 10px">¥</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="支付方式" prop="payType">
|
||||||
|
<el-select v-model="reChargeForm.payType" placeholder="请选择支付方式">
|
||||||
|
<el-option v-for="(item, index) in com_pay_method" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="unSubmit">取消</el-button>
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">充值</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form v-else-if="dialogType === 'price'" ref="priceFormRef" :model="priceForm" label-width="100px">
|
||||||
|
<el-form-item label="电表价格" prop="price">
|
||||||
|
<el-input-number v-model.trim.number="priceForm.price" :max="99999" :min="0" :step="0.1"> </el-input-number
|
||||||
|
><span style="padding-left: 10px">(元/kw·h)</span>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="欠费阈值" prop="arrearsThreshold">-->
|
||||||
|
<!-- <el-input-number v-model.trim.number="priceForm.arrearsThreshold" :max="99999" :min="0" :step="0.1"> </el-input-number-->
|
||||||
|
<!-- ><span style="padding-left: 10px">元</span>-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="unSubmit">取消</el-button>
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">设置价格</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form
|
||||||
|
v-else-if="dialogType === 'UploadDevices'"
|
||||||
|
ref="UploadDevicesFormRef"
|
||||||
|
:model="UploadDevicesFiles"
|
||||||
|
:rule="UploadDevicesFilesRules"
|
||||||
|
label-width="120px"
|
||||||
|
>
|
||||||
|
<el-form-item label="上传设备文件" prop="file">
|
||||||
|
<el-upload
|
||||||
|
ref="UploadDevicesRef"
|
||||||
|
v-model:file-list="UploadDevicesFiles.file"
|
||||||
|
:action="uploadDevicesUrl"
|
||||||
|
:auto-upload="false"
|
||||||
|
:headers="headerToken()"
|
||||||
|
:limit="1"
|
||||||
|
:on-change="handleChangeUploadDevices"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:show-file-list="true"
|
||||||
|
accept=".xls, .xlsx"
|
||||||
|
class="upload-demo"
|
||||||
|
name="file"
|
||||||
|
>
|
||||||
|
<div class="uploadFileBox flex flex-items-center">
|
||||||
|
<el-icon>
|
||||||
|
<upload></upload>
|
||||||
|
</el-icon>
|
||||||
|
<div style="margin-left: 10px">上传文件</div>
|
||||||
|
</div>
|
||||||
|
<template #tip>
|
||||||
|
<div class="el-upload__tip">文件必须是 <strong>excel</strong> 文件</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="unSubmit">取消</el-button>
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> 上传 </el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
<div v-show="!usedWaterInfo" class="usedWaterbox">
|
<div v-show="!usedWaterInfo" class="usedWaterBox">
|
||||||
<div class="useditem">查询用电量开始时间</div>
|
<div class="usedItem">查询用电量开始时间</div>
|
||||||
<div class="useditem value">{{ UsedWaterInfo.startTime }}</div>
|
<div class="usedItem value">{{ UsedWaterInfo.startTime }}</div>
|
||||||
<div class="useditem">查询用电量结束时间</div>
|
<div class="usedItem">查询用电量结束时间</div>
|
||||||
<div class="useditem value">{{ UsedWaterInfo.endTime }}</div>
|
<div class="usedItem value">{{ UsedWaterInfo.endTime }}</div>
|
||||||
<div class="useditem">用电量</div>
|
<div class="usedItem">用电量</div>
|
||||||
<div class="useditem value">{{ UsedWaterInfo.count }}</div>
|
<div class="usedItem value">{{ UsedWaterInfo.count }}</div>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="WaterDevice" lang="ts">
|
<script lang="ts" name="WaterDevice" setup>
|
||||||
import {
|
import {
|
||||||
ElectricityDeviceMakerQrcode,
|
ElectricityDeviceMakerQrcode,
|
||||||
|
ElectricityDeviceRecharge,
|
||||||
ElectricityDeviceUnbind,
|
ElectricityDeviceUnbind,
|
||||||
getElectricityDeviceTimeRangeUsedWater,
|
getElectricityDeviceTimeRangeUsedWater,
|
||||||
listElectricityDevice,
|
listElectricityDevice,
|
||||||
updateElectricityDevice
|
setElectricityDevicePrice,
|
||||||
|
setElectricityDeviceSwitchStatus,
|
||||||
|
updateElectricityDevice,
|
||||||
|
updateElectricityDeviceData,
|
||||||
|
uploadElectricityDevices
|
||||||
} from '@/api/system/SdbElectricityDevice';
|
} from '@/api/system/SdbElectricityDevice';
|
||||||
import { ElectricityDeviceVO } from '@/api/system/SdbElectricityDevice/type';
|
import { ElectricityDeviceVO } from '@/api/system/SdbElectricityDevice/type';
|
||||||
import { useHouseStore } from '@/store/modules/house';
|
import { useHouseStore } from '@/store/modules/house';
|
||||||
import { useUserStore } from '@/store/modules/user';
|
import { useUserStore } from '@/store/modules/user';
|
||||||
import { checkPermi } from '@/utils/permission';
|
|
||||||
import { Upload } from '@element-plus/icons-vue';
|
import { Upload } from '@element-plus/icons-vue';
|
||||||
import { CascaderValue, UploadProps, UploadRawFile } from 'element-plus';
|
import { CascaderValue, genFileId, UploadProps, UploadRawFile } from 'element-plus';
|
||||||
import { exportImagesToZip } from '@/utils/exportZip';
|
import { exportImagesToZip } from '@/utils/exportZip';
|
||||||
|
|
||||||
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/electricityDevice/upload';
|
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/electricityDevice/upload';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_waterdevice_on_status } = toRefs<any>(proxy?.useDict('com_waterdevice_on_status'));
|
const { com_waterdevice_on_status, com_electricity_readrecord_status, com_pay_method } = toRefs<any>(
|
||||||
const { com_electricity_readrecord_status } = toRefs<any>(proxy?.useDict('com_electricity_readrecord_status'));
|
proxy?.useDict('com_waterdevice_on_status', 'com_electricity_readrecord_status', 'com_pay_method')
|
||||||
|
);
|
||||||
|
|
||||||
const ElectricityDeviceList = ref<ElectricityDeviceVO[]>([]);
|
const ElectricityDeviceList = ref<ElectricityDeviceVO[]>([]);
|
||||||
const buttonLoading = ref(false);
|
const buttonLoading = ref(false);
|
||||||
@@ -298,7 +347,7 @@ const getList = async () => {
|
|||||||
// ! 用电量 =============================================================================
|
// ! 用电量 =============================================================================
|
||||||
const usedWaterInfo = ref(true);
|
const usedWaterInfo = ref(true);
|
||||||
const UsedWaterFormRef = ref(null);
|
const UsedWaterFormRef = ref(null);
|
||||||
const UsedWaterform = ref({
|
const UsedWaterForm = ref({
|
||||||
deviceCode: '',
|
deviceCode: '',
|
||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: ''
|
endTime: ''
|
||||||
@@ -315,9 +364,9 @@ const rules = {
|
|||||||
function handleStarTime(val: string) {
|
function handleStarTime(val: string) {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
const current = new Date(val).getTime();
|
const current = new Date(val).getTime();
|
||||||
if (UsedWaterform.value.endTime && UsedWaterform.value.startTime) {
|
if (UsedWaterForm.value.endTime && UsedWaterForm.value.startTime) {
|
||||||
if (current > new Date(UsedWaterform.value.endTime).getTime()) {
|
if (current > new Date(UsedWaterForm.value.endTime).getTime()) {
|
||||||
UsedWaterform.value.endTime = '';
|
UsedWaterForm.value.endTime = '';
|
||||||
ElMessage.warning('开始时间不能大于结束时间');
|
ElMessage.warning('开始时间不能大于结束时间');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,9 +374,9 @@ function handleStarTime(val: string) {
|
|||||||
function handleEndTime(val: string) {
|
function handleEndTime(val: string) {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
const current = new Date(val).getTime();
|
const current = new Date(val).getTime();
|
||||||
if (UsedWaterform.value.startTime && UsedWaterform.value.endTime) {
|
if (UsedWaterForm.value.startTime && UsedWaterForm.value.endTime) {
|
||||||
if (current < new Date(UsedWaterform.value.startTime).getTime()) {
|
if (current < new Date(UsedWaterForm.value.startTime).getTime()) {
|
||||||
UsedWaterform.value.startTime = '';
|
UsedWaterForm.value.startTime = '';
|
||||||
ElMessage.warning('结束时间不能小于开始时间');
|
ElMessage.warning('结束时间不能小于开始时间');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,28 +507,108 @@ function handleChange(val: CascaderValue) {
|
|||||||
EditHouseForm.value.houseId = val[2];
|
EditHouseForm.value.houseId = val[2];
|
||||||
}
|
}
|
||||||
// * house
|
// * house
|
||||||
const dialogType = ref<'usedWater' | 'Upload' | 'UpdateHouse'>('usedWater');
|
|
||||||
|
// recharge
|
||||||
|
const reChargeForm = ref({
|
||||||
|
deviceCode: '',
|
||||||
|
amount: 0,
|
||||||
|
payType: ''
|
||||||
|
});
|
||||||
|
// recharge
|
||||||
|
|
||||||
|
const priceFormRef = ref(null);
|
||||||
|
const priceForm = ref({
|
||||||
|
deviceCode: '',
|
||||||
|
// 电价
|
||||||
|
price: 0,
|
||||||
|
// 欠费阈值
|
||||||
|
arrearsThreshold: 0
|
||||||
|
});
|
||||||
|
// devices
|
||||||
|
const UploadDevicesFormRef = ref(null);
|
||||||
|
const UploadDevicesRef = ref(null);
|
||||||
|
const UploadDevicesLoading = ref(false);
|
||||||
|
const UploadDevicesFiles = ref({
|
||||||
|
file: []
|
||||||
|
});
|
||||||
|
const UploadDevicesFilesRules = ref({
|
||||||
|
file: [{ required: true, message: '设备文件不能为空', trigger: 'blur' }],
|
||||||
|
manufacturer: [{ required: true, message: '厂商标识不能为空', trigger: 'blur' }]
|
||||||
|
});
|
||||||
|
const uploadDevicesUrl = import.meta.env.VITE_APP_BASE_API + '/electricityDevice/importData';
|
||||||
|
const beforeAvatarUploadDevices: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||||
|
// 1. 校验后缀
|
||||||
|
if (!rawFile.name.endsWith('.xls') && !rawFile.name.endsWith('.xlsx')) {
|
||||||
|
ElMessage.warning('请上传 .xls, .xlsx 后缀的文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const typeList = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/octet-stream'];
|
||||||
|
// 2. 校验文件类型(bin 文件类型)
|
||||||
|
if (!typeList.includes(rawFile.type) && rawFile.type !== '') {
|
||||||
|
ElMessage.warning('文件类型不正确,请上传标准 excel 文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 校验文件大小(不能空)
|
||||||
|
// 小于5m 1024 * 1024 * 5
|
||||||
|
if (rawFile.size <= 0) {
|
||||||
|
ElMessage.warning('上传 excel 文件不能为空');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rawFile.size >= 1024 * 1024 * 5) {
|
||||||
|
ElMessage.warning('上传 excel 文件不能超过5M');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
const handleExceed: UploadProps['onExceed'] = (files) => {
|
||||||
|
UploadDevicesRef.value!.clearFiles();
|
||||||
|
const file = files[0] as UploadRawFile;
|
||||||
|
file.uid = genFileId();
|
||||||
|
UploadDevicesRef.value!.handleStart(file);
|
||||||
|
};
|
||||||
|
const handleChangeUploadDevices: UploadProps['onChange'] = (uploadFile: UploadFile) => {
|
||||||
|
if (!beforeAvatarUploadDevices(uploadFile.raw)) {
|
||||||
|
UploadDevicesRef.value!.clearFiles();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
type dialogTypeList = 'usedWater' | 'Upload' | 'UpdateHouse' | 'UploadDevices' | 'recharge' | 'price';
|
||||||
|
|
||||||
|
const dialogType = ref<dialogTypeList>('usedWater');
|
||||||
/** 用电量 更新固件 */
|
/** 用电量 更新固件 */
|
||||||
const handleOpenDialog = (type: 'usedWater' | 'Upload' | 'UpdateHouse', row: ElectricityDeviceVO) => {
|
const handleOpenDialog = (type: dialogTypeList, row?: ElectricityDeviceVO) => {
|
||||||
reset();
|
reset();
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialogType.value = type;
|
dialogType.value = type;
|
||||||
dialog.title = type === 'usedWater' ? '用电量' : type === 'UpdateHouse' ? '编辑户号' : '更新固件';
|
|
||||||
|
|
||||||
if (type === 'usedWater') {
|
if (type === 'usedWater') {
|
||||||
UsedWaterform.value.deviceCode = row.deviceCode;
|
dialog.title = '用电量';
|
||||||
UsedWaterform.value.startTime = '';
|
UsedWaterForm.value.deviceCode = row.deviceCode;
|
||||||
UsedWaterform.value.endTime = '';
|
UsedWaterForm.value.startTime = '';
|
||||||
|
UsedWaterForm.value.endTime = '';
|
||||||
usedWaterInfo.value = true;
|
usedWaterInfo.value = true;
|
||||||
} else if (type === 'Upload') {
|
} else if (type === 'Upload') {
|
||||||
|
dialog.title = '更新固件';
|
||||||
UploadFileForm.value.file = '';
|
UploadFileForm.value.file = '';
|
||||||
UploadFileForm.value.deviceCode = row.deviceCode;
|
UploadFileForm.value.deviceCode = row.deviceCode;
|
||||||
UploadFileForm.value.id = row.id;
|
UploadFileForm.value.id = row.id;
|
||||||
|
} else if (type === 'recharge') {
|
||||||
|
// 充值
|
||||||
|
dialog.title = '充值';
|
||||||
|
reChargeForm.value.deviceCode = row.deviceCode;
|
||||||
|
reChargeForm.value.amount = 0;
|
||||||
|
} else if (type === 'price') {
|
||||||
|
dialog.title = '设置电价';
|
||||||
|
priceForm.value.deviceCode = row.deviceCode;
|
||||||
|
priceForm.value.price = row.price ? Number(row.price) : 0;
|
||||||
} else if (type === 'UpdateHouse') {
|
} else if (type === 'UpdateHouse') {
|
||||||
|
dialog.title = '编辑户号';
|
||||||
EditHouseForm.value.id = row.id;
|
EditHouseForm.value.id = row.id;
|
||||||
EditHouseForm.value.deviceCode = row.deviceCode;
|
EditHouseForm.value.deviceCode = row.deviceCode;
|
||||||
EditHouseForm.value.houseId = '';
|
EditHouseForm.value.houseId = '';
|
||||||
getTree();
|
getTree();
|
||||||
|
} else if (dialogType.value === 'UploadDevices') {
|
||||||
|
dialog.title = '上传设备文件';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -502,20 +631,40 @@ function getTree() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 数据上传
|
||||||
|
function handleUpload(row: ElectricityDeviceVO) {
|
||||||
|
updateElectricityDeviceData({
|
||||||
|
deviceCode: row.deviceCode
|
||||||
|
}).then(() => {
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
/** 电表 启停*/
|
/** 电表 启停*/
|
||||||
// TODO 修改电表 启停
|
const handleChangeWater = (val: number, row: ElectricityDeviceVO): Promise<boolean> => {
|
||||||
// const handleChangeWater = (val: string, row: ElectricityDeviceVO) => {};
|
return new Promise((resolve, reject) => {
|
||||||
|
setElectricityDeviceSwitchStatus({
|
||||||
|
deviceCode: row.deviceCode,
|
||||||
|
status: val
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
.catch(() => reject(false));
|
||||||
|
});
|
||||||
|
};
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
if (dialogType.value === 'usedWater') {
|
if (dialogType.value === 'usedWater') {
|
||||||
if (UsedWaterform.value.startTime === '' || UsedWaterform.value.endTime === '') {
|
if (UsedWaterForm.value.startTime === '' || UsedWaterForm.value.endTime === '') {
|
||||||
ElMessage.warning('请选择时间');
|
ElMessage.warning('请选择时间');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UsedWaterFormRef.value?.validate(async (valid: boolean) => {
|
UsedWaterFormRef.value?.validate(async (valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
buttonLoading.value = true;
|
buttonLoading.value = true;
|
||||||
await getElectricityDeviceTimeRangeUsedWater(UsedWaterform.value)
|
await getElectricityDeviceTimeRangeUsedWater(UsedWaterForm.value)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
UsedWaterInfo.value.endTime = res.data.endTime;
|
UsedWaterInfo.value.endTime = res.data.endTime;
|
||||||
UsedWaterInfo.value.startTime = res.data.startTime;
|
UsedWaterInfo.value.startTime = res.data.startTime;
|
||||||
@@ -536,18 +685,58 @@ const submitForm = () => {
|
|||||||
unSubmit();
|
unSubmit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else if (dialogType.value === 'UploadDevices') {
|
||||||
|
UploadDevicesFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
if (UploadDevicesFiles.value.file.length <= 0) {
|
||||||
|
return ElMessage.warning('上传文件不能为空');
|
||||||
|
}
|
||||||
|
UploadDevicesLoading.value = true;
|
||||||
|
buttonLoading.value = true;
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', UploadDevicesFiles.value.file[0].raw);
|
||||||
|
uploadElectricityDevices(formData)
|
||||||
|
.then(() => {
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
getList();
|
||||||
|
unSubmit();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
buttonLoading.value = false;
|
||||||
|
UploadDevicesLoading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (dialogType.value === 'recharge') {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
ElectricityDeviceRecharge(reChargeForm.value)
|
||||||
|
.then(() => {
|
||||||
|
getList();
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
unSubmit();
|
||||||
|
})
|
||||||
|
.finally(() => (buttonLoading.value = false));
|
||||||
|
} else if (dialogType.value === 'price') {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
setElectricityDevicePrice(priceForm.value)
|
||||||
|
.then(() => {
|
||||||
|
getList();
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
unSubmit();
|
||||||
|
})
|
||||||
|
.finally(() => (buttonLoading.value = false));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const unSubmit = () => {
|
const unSubmit = () => {
|
||||||
reset();
|
reset();
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
dialog.title = '';
|
dialog.title = '';
|
||||||
uploadRef?.value.clearFiles();
|
uploadRef.value && uploadRef?.value.clearFiles();
|
||||||
};
|
};
|
||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
usedWaterInfo.value = true;
|
usedWaterInfo.value = true;
|
||||||
UsedWaterform.value = {
|
UsedWaterForm.value = {
|
||||||
deviceCode: '',
|
deviceCode: '',
|
||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: ''
|
endTime: ''
|
||||||
@@ -562,13 +751,20 @@ const reset = () => {
|
|||||||
deviceCode: '',
|
deviceCode: '',
|
||||||
id: ''
|
id: ''
|
||||||
};
|
};
|
||||||
|
UploadDevicesFiles.value = {
|
||||||
|
file: []
|
||||||
|
};
|
||||||
UploadFileForm.value.file = '';
|
UploadFileForm.value.file = '';
|
||||||
// 上传 清空
|
// 上传 清空
|
||||||
UploadFileFormRef.value?.resetFields();
|
UploadFileFormRef.value?.resetFields();
|
||||||
// 使用电量 清空
|
// 绑定房屋 清空
|
||||||
EditHouseFormRef.value?.resetFields();
|
EditHouseFormRef.value?.resetFields();
|
||||||
// 使用电量 清空
|
// 使用电量 清空
|
||||||
UsedWaterFormRef.value?.resetFields();
|
UsedWaterFormRef.value?.resetFields();
|
||||||
|
|
||||||
|
UploadDevicesFormRef.value?.resetFields();
|
||||||
|
UploadDevicesRef.value && UploadDevicesRef.value?.clearFiles();
|
||||||
|
UploadDevicesLoading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
@@ -587,11 +783,11 @@ const router = useRouter();
|
|||||||
|
|
||||||
/** 充值记录 */
|
/** 充值记录 */
|
||||||
const handleRecode = (row: ElectricityDeviceVO) => {
|
const handleRecode = (row: ElectricityDeviceVO) => {
|
||||||
// 1.电表 2.电表
|
// 1.电表 2.水表
|
||||||
router.push({
|
router.push({
|
||||||
path: '/equipment/electricityTopupRecord',
|
path: '/equipment/electricityTopupRecord',
|
||||||
query: {
|
query: {
|
||||||
type: '2',
|
type: '1',
|
||||||
houseName: row.houseName,
|
houseName: row.houseName,
|
||||||
deviceCode: row.deviceCode,
|
deviceCode: row.deviceCode,
|
||||||
id: row.id
|
id: row.id
|
||||||
@@ -614,6 +810,12 @@ const download = (url: string) => {
|
|||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download('/electricityDevice/importTemplate', {}, `电表导入设备模板_${new Date().getTime()}.xlsx`);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -645,10 +847,10 @@ const download = (url: string) => {
|
|||||||
height: calc(100% - 80px);
|
height: calc(100% - 80px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.usedWaterbox {
|
.usedWaterBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid #eef0ff;
|
border: 1px solid #eef0ff;
|
||||||
.useditem {
|
.usedItem {
|
||||||
height: 42px;
|
height: 42px;
|
||||||
line-height: 42px;
|
line-height: 42px;
|
||||||
background-color: rgba(26, 117, 255, 0.1);
|
background-color: rgba(26, 117, 255, 0.1);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" label-width="70px" @submit.prevent="handleQuery" :model="queryParams" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" label-width="70px" @submit.prevent="handleQuery">
|
||||||
<!-- <el-form-item label="设备状态" prop="eleStatus">
|
<!-- <el-form-item label="设备状态" prop="eleStatus">
|
||||||
<el-select v-model="queryParams.eleStatus">
|
<el-select v-model="queryParams.eleStatus">
|
||||||
<el-option v-for="(item, index) in com_waterdevice_on_status" :key="index" :label="item.label" :value="item.value"></el-option>
|
<el-option v-for="(item, index) in com_waterdevice_on_status" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<el-form-item label="设备编号" prop="deviceCode">
|
<el-form-item label="设备编号" prop="deviceCode">
|
||||||
<el-input maxlength="25" v-model="queryParams.deviceCode" placeholder="请输入" clearable />
|
<el-input v-model="queryParams.deviceCode" clearable maxlength="25" placeholder="请输入" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="房屋" prop="houseName">
|
<el-form-item label="房屋" prop="houseName">
|
||||||
<el-input maxlength="20" clearable v-model="queryParams.houseName" placeholder="请输入" />
|
<el-input v-model="queryParams.houseName" clearable maxlength="20" placeholder="请输入" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -36,9 +36,9 @@
|
|||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<div style="font-size: 0.8rem">水表列表</div>
|
<div style="font-size: 0.8rem">水表列表</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :show-add="false" :show-edit="false" :show-delete="false">
|
<right-toolbar :show-add="false" :show-delete="false" :show-edit="false">
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-item @click="handleMarkqrcode" v-if="checkPermi(['equipment:addqrcode:waterdevice'])">
|
<el-dropdown-item @click="handleMarkqrcode">
|
||||||
<span>批量生成条形码</span>
|
<span>批量生成条形码</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item @click="handleMarkQrcodeZip">
|
<el-dropdown-item @click="handleMarkQrcodeZip">
|
||||||
@@ -52,38 +52,38 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="waterDeviceList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="waterDeviceList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="设备编码" width="250" align="center" prop="deviceCode" />
|
<el-table-column align="center" label="设备编码" prop="deviceCode" width="250" />
|
||||||
<el-table-column label="设备状态" width="100" align="center" prop="eleStatus">
|
<el-table-column align="center" label="设备状态" prop="eleStatus" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<!-- 1 离线 0在线 -->
|
<!-- 1 离线 0在线 -->
|
||||||
<dict-tag v-if="scope.row.waterRecord" :options="com_waterdevice_on_status" :value="Number(scope.row.status)"></dict-tag>
|
<dict-tag v-if="scope.row.waterRecord" :options="com_waterdevice_on_status" :value="Number(scope.row.status)"></dict-tag>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="分合状态" width="100" align="center">
|
<el-table-column align="center" label="分合状态" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag v-if="scope.row.status !== null" :options="com_water_readrecord_status" :value="scope.row.waterRecord.status"></dict-tag>
|
<dict-tag v-if="scope.row.status !== null" :options="com_water_readrecord_status" :value="scope.row.waterRecord.status"></dict-tag>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="房屋" align="center" prop="houseName" />
|
<el-table-column align="center" label="房屋" prop="houseName" />
|
||||||
<el-table-column label="余额" width="120" align="center" prop="deviceCode">
|
<el-table-column align="center" label="余额" prop="deviceCode" width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.waterRecord">{{ scope.row.waterRecord.balance }}</span>
|
<span v-if="scope.row.waterRecord">{{ scope.row.waterRecord.balance }}</span>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="条码" width="250" align="center">
|
<el-table-column align="center" label="条码" width="250">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-image
|
<el-image
|
||||||
v-if="scope.row.url && scope.row.url.includes('http')"
|
v-if="scope.row.url && scope.row.url.includes('http')"
|
||||||
:src="scope.row.url"
|
|
||||||
:preview-src-list="[scope.row.url]"
|
:preview-src-list="[scope.row.url]"
|
||||||
style="width: 100%; height: 100%; border-radius: 4px"
|
:src="scope.row.url"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
preview-teleported
|
preview-teleported
|
||||||
|
style="width: 100%; height: 100%; border-radius: 4px"
|
||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-icon @click="download(scope.row.url)"><Download /></el-icon>
|
<el-icon @click="download(scope.row.url)"><Download /></el-icon>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
<span v-else>暂未生成</span>
|
<span v-else>暂未生成</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="抄表时间" align="center">
|
<el-table-column align="center" label="抄表时间">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.waterRecord ? scope.row.waterRecord.readTime : '---' }}</span>
|
<span>{{ scope.row.waterRecord ? scope.row.waterRecord.readTime : '---' }}</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -109,37 +109,24 @@
|
|||||||
></el-switch>
|
></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
<el-table-column label="操作" min-width="150" align="center" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" min-width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<el-button link type="primary" @click="handleRecode(scope.row)" v-has-permi="['equipment:view:waterdevice']">充值记录</el-button>
|
<el-button link type="primary" @click="handleRecode(scope.row)">充值记录</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
|
v-has-permi="['equipment:addqrcode:waterdevice']"
|
||||||
|
:loading="loadingQRCode.includes(scope.row.id)"
|
||||||
link
|
link
|
||||||
type="primary"
|
type="primary"
|
||||||
:loading="loadingQRCode.includes(scope.row.id)"
|
|
||||||
@click="handleQrCode(scope.row)"
|
@click="handleQrCode(scope.row)"
|
||||||
v-has-permi="['equipment:addqrcode:waterdevice']"
|
|
||||||
>生成条码</el-button
|
>生成条码</el-button
|
||||||
>
|
>
|
||||||
<el-button link type="primary" @click="handleOpenDialog('usedWater', scope.row)" v-has-permi="['equipment:useWater:waterdevice']"
|
<el-button link type="primary" @click="handleOpenDialog('usedWater', scope.row)">用水量</el-button>
|
||||||
>用水量</el-button
|
<el-button link type="primary" @click="handleOpenDialog('Upload', scope.row)">更新固件</el-button>
|
||||||
>
|
|
||||||
<el-button link type="primary" @click="handleOpenDialog('Upload', scope.row)" v-has-permi="['equipment:updatehardware:waterdevice']"
|
|
||||||
>更新固件</el-button
|
|
||||||
>
|
|
||||||
<!-- <el-button link type="primary" @click="handleUpdate(scope.row.deviceCode)">最新抄表记录</el-button> -->
|
<!-- <el-button link type="primary" @click="handleUpdate(scope.row.deviceCode)">最新抄表记录</el-button> -->
|
||||||
|
|
||||||
<el-button
|
<el-button v-if="!scope.row.houseName" link type="primary" @click="handleOpenDialog('UpdateHouse', scope.row)">绑定房屋</el-button>
|
||||||
v-if="!scope.row.houseName"
|
<el-button v-else link type="primary" @click="handleUnbind(scope.row)">解绑房屋</el-button>
|
||||||
link
|
|
||||||
type="primary"
|
|
||||||
@click="handleOpenDialog('UpdateHouse', scope.row)"
|
|
||||||
v-has-permi="['equipment:edithouse:waterdevice']"
|
|
||||||
>绑定房屋</el-button
|
|
||||||
>
|
|
||||||
<el-button v-else link type="primary" @click="handleUnbind(scope.row)" v-has-permi="['equipment:edithouse:waterdevice']"
|
|
||||||
>解绑房屋</el-button
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- <el-dropdown style="vertical-align: text-top">
|
<!-- <el-dropdown style="vertical-align: text-top">
|
||||||
<el-button link type="primary">
|
<el-button link type="primary">
|
||||||
@@ -167,37 +154,37 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination
|
<pagination
|
||||||
:pageSizes="[10, 30, 50, 100]"
|
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNum"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
:pageSizes="[10, 30, 50, 100]"
|
||||||
|
:total="total"
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 添加或修改水 设备对话框 -->
|
<!-- 添加或修改水 设备对话框 -->
|
||||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
<el-dialog v-model="dialog.visible" :title="dialog.title" append-to-body width="500px">
|
||||||
<!-- water -->
|
<!-- water -->
|
||||||
<el-form v-if="dialogType === 'usedWater'" :rules="rules" ref="UsedWaterformRef" :model="UsedWaterform" label-width="100px">
|
<el-form v-if="dialogType === 'usedWater'" ref="UsedWaterformRef" :model="UsedWaterform" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="设备编号" prop="deviceCode"> {{ UsedWaterform.deviceCode }} </el-form-item>
|
<el-form-item label="设备编号" prop="deviceCode"> {{ UsedWaterform.deviceCode }} </el-form-item>
|
||||||
<el-form-item label="开始时间" prop="startTime">
|
<el-form-item label="开始时间" prop="startTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
v-model="UsedWaterform.startTime"
|
v-model="UsedWaterform.startTime"
|
||||||
type="datetime"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
@update:model-value="handleStarTime"
|
|
||||||
placeholder="开始时间"
|
placeholder="开始时间"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@update:model-value="handleStarTime"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="结束时间" prop="endTime">
|
<el-form-item label="结束时间" prop="endTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
v-model="UsedWaterform.endTime"
|
v-model="UsedWaterform.endTime"
|
||||||
type="datetime"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
@update:model-value="handleEndTime"
|
|
||||||
placeholder="结束时间"
|
placeholder="结束时间"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
@update:model-value="handleEndTime"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -207,24 +194,24 @@
|
|||||||
<!-- upload file -->
|
<!-- upload file -->
|
||||||
<el-form v-else-if="dialogType === 'Upload'" ref="UploadFileformRef" :model="UploadFileform" :rules="UploadFileformRules" label-width="140px">
|
<el-form v-else-if="dialogType === 'Upload'" ref="UploadFileformRef" :model="UploadFileform" :rules="UploadFileformRules" label-width="140px">
|
||||||
<el-form-item label="LEN_A" prop="lenA">
|
<el-form-item label="LEN_A" prop="lenA">
|
||||||
<el-input maxlength="40" v-model="UploadFileform.lenA"></el-input>
|
<el-input v-model="UploadFileform.lenA" maxlength="40"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="CRC32_HEX_A" prop="crcA">
|
<el-form-item label="CRC32_HEX_A" prop="crcA">
|
||||||
<el-input maxlength="40" v-model="UploadFileform.crcA"></el-input>
|
<el-input v-model="UploadFileform.crcA" maxlength="40"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="上传 A槽更新 文件" prop="urlA">
|
<el-form-item label="上传 A槽更新 文件" prop="urlA">
|
||||||
<el-upload
|
<el-upload
|
||||||
ref="uploadARef"
|
ref="uploadARef"
|
||||||
accept=".bin"
|
|
||||||
:action="uploadAUrl"
|
:action="uploadAUrl"
|
||||||
name="file"
|
:before-upload="beforeAvatarUpload"
|
||||||
:headers="headerToken()"
|
:headers="headerToken()"
|
||||||
:limit="1"
|
:limit="1"
|
||||||
:show-file-list="true"
|
|
||||||
class="upload-demo"
|
|
||||||
:on-exceed="handleExceedA"
|
:on-exceed="handleExceedA"
|
||||||
:on-success="handleAvatarSuccessA"
|
:on-success="handleAvatarSuccessA"
|
||||||
:before-upload="beforeAvatarUpload"
|
:show-file-list="true"
|
||||||
|
accept=".bin"
|
||||||
|
class="upload-demo"
|
||||||
|
name="file"
|
||||||
>
|
>
|
||||||
<div class="uploadFileBox flex flex-items-center">
|
<div class="uploadFileBox flex flex-items-center">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@@ -239,24 +226,24 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="LEN_B" prop="lenB">
|
<el-form-item label="LEN_B" prop="lenB">
|
||||||
<el-input maxlength="40" v-model="UploadFileform.lenB"></el-input>
|
<el-input v-model="UploadFileform.lenB" maxlength="40"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="CRC32_HEX_B" prop="crcB">
|
<el-form-item label="CRC32_HEX_B" prop="crcB">
|
||||||
<el-input maxlength="40" v-model="UploadFileform.crcB"></el-input>
|
<el-input v-model="UploadFileform.crcB" maxlength="40"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="上传 B槽更新 文件" prop="urlB">
|
<el-form-item label="上传 B槽更新 文件" prop="urlB">
|
||||||
<el-upload
|
<el-upload
|
||||||
ref="uploadBRef"
|
ref="uploadBRef"
|
||||||
accept=".bin"
|
|
||||||
:action="uploadBUrl"
|
:action="uploadBUrl"
|
||||||
name="file"
|
:before-upload="beforeAvatarUpload"
|
||||||
:limit="1"
|
|
||||||
:headers="headerToken()"
|
:headers="headerToken()"
|
||||||
:show-file-list="true"
|
:limit="1"
|
||||||
class="upload-demo"
|
|
||||||
:on-exceed="handleExceedB"
|
:on-exceed="handleExceedB"
|
||||||
:on-success="handleAvatarSuccessB"
|
:on-success="handleAvatarSuccessB"
|
||||||
:before-upload="beforeAvatarUpload"
|
:show-file-list="true"
|
||||||
|
accept=".bin"
|
||||||
|
class="upload-demo"
|
||||||
|
name="file"
|
||||||
>
|
>
|
||||||
<div class="uploadFileBox flex flex-items-center">
|
<div class="uploadFileBox flex flex-items-center">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@@ -310,7 +297,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="WaterDevice" lang="ts">
|
<script lang="ts" name="WaterDevice" setup>
|
||||||
import 'element-plus/theme-chalk/display.css';
|
import 'element-plus/theme-chalk/display.css';
|
||||||
import {
|
import {
|
||||||
listWaterDevice,
|
listWaterDevice,
|
||||||
@@ -629,7 +616,6 @@ const handleChangeWater = (val: string, row: WaterDeviceVO) => {};
|
|||||||
|
|
||||||
function handleUpdate(id: string) {
|
function handleUpdate(id: string) {
|
||||||
latestRecord(id).then((res) => {
|
latestRecord(id).then((res) => {
|
||||||
console.log('设备最新抄表记录', res);
|
|
||||||
deviceLastRecordform.value = {
|
deviceLastRecordform.value = {
|
||||||
id: '',
|
id: '',
|
||||||
deviceCode: '',
|
deviceCode: '',
|
||||||
|
|||||||
@@ -4,11 +4,17 @@
|
|||||||
<el-card class="flex-1 mt-10px" shadow="never">
|
<el-card class="flex-1 mt-10px" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<el-form class="demo-form-inline" :inline="true">
|
<el-form :inline="true" class="demo-form-inline">
|
||||||
<el-form-item label="查询日期">
|
<el-form-item label="查询日期">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
clearable
|
|
||||||
v-model="SearchTime"
|
v-model="SearchTime"
|
||||||
|
clearable
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
range-separator="到"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
type="daterange"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
@change="
|
@change="
|
||||||
(val) => {
|
(val) => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
@@ -22,47 +28,41 @@
|
|||||||
queryParams.endDate = end + ' 23:59:59';
|
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>
|
||||||
<el-form-item label="" v-has-permi="['electricity:topupRecord:list']">
|
<el-form-item v-has-permi="['electricity:topupRecord:list']" label="">
|
||||||
<el-button type="primary" @click="getList">查询</el-button>
|
<el-button type="primary" @click="getList">查询</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-button @click="handleExport" v-has-permi="['electricity:topupRecord:export']" type="warning">导出统计</el-button>
|
<el-button v-has-permi="['electricity:topupRecord:export']" type="warning" @click="handleExport">导出统计</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-table v-loading="loading" border :data="topupRecordList">
|
<el-table v-loading="loading" :data="topupRecordList" :span-method="handleSpanMethod" border>
|
||||||
<el-table-column label="充值时间" align="center" prop="rechargeTime">
|
<el-table-column align="center" label="充值时间" prop="rechargeTime">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.rechargeTime">{{ scope.row.rechargeTime }}</span>
|
<span v-if="scope.row.rechargeTime">{{ scope.row.rechargeTime }}</span>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="小区名称" align="center" prop="villageName">
|
<el-table-column align="center" label="小区名称" prop="villageName">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.villageName">{{ scope.row.villageName }}</span>
|
<span v-if="scope.row.villageName">{{ scope.row.villageName }}</span>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="户主" align="center" prop="residentName">
|
<el-table-column align="center" label="户主" prop="residentName">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.residentName">{{ scope.row.residentName }}</span>
|
<span v-if="scope.row.residentName">{{ scope.row.residentName }}</span>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="房号" align="center" prop="houseName">
|
<el-table-column align="center" label="房号" prop="houseName">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.houseName">{{ scope.row.houseName }}</span>
|
<span v-if="scope.row.houseName">{{ scope.row.houseName }}</span>
|
||||||
<span v-else>---</span>
|
<span v-else>---</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="单价" align="center" prop="fixedPrice">
|
<el-table-column align="center" label="单价" prop="fixedPrice">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div v-if="scope.row.fixedPrice && scope.row.unit">
|
<div v-if="scope.row.fixedPrice && scope.row.unit">
|
||||||
<span>{{ scope.row.fixedPrice }}</span>
|
<span>{{ scope.row.fixedPrice }}</span>
|
||||||
@@ -74,17 +74,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="设备编号" align="center" prop="deviceCode" />
|
<el-table-column align="center" label="设备编号" prop="deviceCode" />
|
||||||
<el-table-column label="订单号" align="center" prop="orderId" />
|
<el-table-column align="center" label="订单号" prop="orderId" />
|
||||||
<el-table-column label="充值金额" align="center" prop="rechargeAmount" />
|
<el-table-column align="center" label="充值金额" prop="rechargeAmount" />
|
||||||
<el-table-column label="缴费方式" align="center" prop="topUpType" />
|
<el-table-column align="center" label="缴费方式" prop="topUpType" />
|
||||||
</el-table>
|
</el-table>
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import pageHeader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import { getElectricityTopupRecordByDate, type TopupRecordList } from '@/api/system/SdbTopupRecord';
|
import { getElectricityTopupRecordByDate, type TopupRecordList } from '@/api/system/SdbTopupRecord';
|
||||||
@@ -112,6 +112,7 @@ const getList = async () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await getElectricityTopupRecordByDate(queryParams.value);
|
const res = await getElectricityTopupRecordByDate(queryParams.value);
|
||||||
topupRecordList.value = res.rows;
|
topupRecordList.value = res.rows;
|
||||||
|
topupRecordList.value[topupRecordList.value.length - 1].rechargeTime = '合计';
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
@@ -119,7 +120,24 @@ const getList = async () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
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 handleExport = () => {
|
const handleExport = () => {
|
||||||
proxy?.download(
|
proxy?.download(
|
||||||
|
|||||||
@@ -4,24 +4,24 @@
|
|||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form label-position="right" class="formBody" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" label-position="right" label-width="130px">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="区域名称" prop="areaName">
|
<el-form-item label="区域名称" prop="areaName">
|
||||||
<el-input maxlength="8" show-word-limit v-model.trim="form.areaName" placeholder="请输入区域名称" />
|
<el-input v-model.trim="form.areaName" maxlength="8" placeholder="请输入区域名称" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="区域编号" prop="areaCode">
|
<el-form-item label="区域编号" prop="areaCode">
|
||||||
<el-input maxlength="8" v-model.trim="form.areaCode" placeholder="请输入区域编号" />
|
<el-input v-model.trim="form.areaCode" maxlength="8" placeholder="请输入区域编号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="区域面积" prop="area">
|
<el-form-item label="区域面积" prop="area">
|
||||||
<el-input maxlength="8" v-model.number.trim="form.area" placeholder="请输入区域面积">
|
<el-input v-model.number.trim="form.area" maxlength="8" placeholder="请输入区域面积">
|
||||||
<template #suffix>㎡</template>
|
<template #suffix>㎡</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -29,14 +29,14 @@
|
|||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="车位数量" prop="parkingCount">
|
<el-form-item label="车位数量" prop="parkingCount">
|
||||||
<el-input maxlength="5" v-model.number.trim="form.parkingCount" placeholder="请输入车位数量" />
|
<el-input v-model.number.trim="form.parkingCount" maxlength="5" placeholder="请输入车位数量" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input type="textarea" maxlength="200" show-word-limit :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
<el-input v-model.trim="form.remark" :rows="5" maxlength="200" placeholder="请输入" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { addArea, getArea, updateArea } from '@/api/system/carArea';
|
import { addArea, getArea, updateArea } from '@/api/system/carArea';
|
||||||
@@ -110,11 +110,11 @@ const rules = ref({
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
area: [
|
area: [
|
||||||
{ required: true, message: '请输入区域面积', trigger: 'blur' },
|
{ required: false, message: '请输入区域面积', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
|
validator: (_: any, value: string | number, callback: (arg0?: Error) => void) => {
|
||||||
if (value === '' || value === null) {
|
if (value === '' || value === null) {
|
||||||
return callback(new Error('请输入区域面积'));
|
return callback();
|
||||||
}
|
}
|
||||||
const val = Number(value);
|
const val = Number(value);
|
||||||
if (Number.isNaN(val)) {
|
if (Number.isNaN(val)) {
|
||||||
@@ -165,7 +165,7 @@ const cancelForm = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.AddBuildingBox {
|
.AddBuildingBox {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column label="区域名称" align="center" prop="areaName" />
|
<el-table-column label="区域名称" align="center" prop="areaName" />
|
||||||
<el-table-column label="区域编号" align="center" prop="areaCode" />
|
<el-table-column label="区域编号" align="center" prop="areaCode" />
|
||||||
<el-table-column label="面积" align="center" prop="area" >
|
<el-table-column label="面积" align="center" prop="area">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.area">{{ scope.row.area + ' m²' }}</span>
|
<span v-if="scope.row.area">{{ scope.row.area + ' m²' }}</span>
|
||||||
<span v-else> --- </span>
|
<span v-else> --- </span>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
<div class="AddBuildingBody">
|
<div class="AddBuildingBody">
|
||||||
<div class="title">基本信息</div>
|
<div class="title">基本信息</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-form class="formBody" label-position="left" ref="formRef" :model="form" :rules="rules" label-width="130px">
|
<el-form ref="formRef" :model="form" :rules="rules" class="formBody" label-position="left" label-width="130px">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="车牌号" prop="carNum" :validate-event="false">
|
<el-form-item :validate-event="false" label="车牌号" prop="carNum">
|
||||||
<el-input
|
<el-input
|
||||||
maxlength="10"
|
|
||||||
v-model.trim="form.carNum"
|
v-model.trim="form.carNum"
|
||||||
|
maxlength="10"
|
||||||
placeholder="请输入车牌号"
|
placeholder="请输入车牌号"
|
||||||
style="text-transform: uppercase; letter-spacing: 2px"
|
style="text-transform: uppercase; letter-spacing: 2px"
|
||||||
/>
|
/>
|
||||||
@@ -19,20 +19,20 @@
|
|||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="车辆品牌" prop="carBrand">
|
<el-form-item label="车辆品牌" prop="carBrand">
|
||||||
<el-input maxlength="12" v-model.trim="form.carBrand" placeholder="请输入车辆品牌" />
|
<el-input v-model.trim="form.carBrand" maxlength="12" placeholder="请输入车辆品牌" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="车辆型号" prop="carModel">
|
<el-form-item label="车辆型号" prop="carModel">
|
||||||
<el-input maxlength="12" v-model.trim="form.carModel" placeholder="请输入补充车辆型号" />
|
<el-input v-model.trim="form.carModel" maxlength="12" placeholder="请输入补充车辆型号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2"></el-col>
|
<el-col :span="2"></el-col>
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="车身颜色" prop="carColor">
|
<el-form-item label="车身颜色" prop="carColor">
|
||||||
<el-input maxlength="12" v-model.trim="form.carColor" placeholder="请输入车身颜色" />
|
<el-input v-model.trim="form.carColor" maxlength="12" placeholder="请输入车身颜色" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -40,18 +40,18 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="车辆照片">
|
<el-form-item label="车辆照片">
|
||||||
<el-upload
|
<el-upload
|
||||||
class="avatar-uploader"
|
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
accept=".png, .jpg"
|
|
||||||
:action="uploadUrl"
|
:action="uploadUrl"
|
||||||
name="file"
|
:before-upload="beforeAvatarUpload"
|
||||||
:headers="headerToken()"
|
:headers="headerToken()"
|
||||||
:show-file-list="false"
|
|
||||||
:limit="1"
|
:limit="1"
|
||||||
:on-success="handleAvatarSuccess"
|
:on-success="handleAvatarSuccess"
|
||||||
:before-upload="beforeAvatarUpload"
|
:show-file-list="false"
|
||||||
|
accept=".png, .jpg"
|
||||||
|
class="avatar-uploader"
|
||||||
|
name="file"
|
||||||
>
|
>
|
||||||
<img alt="车辆照片" v-if="form.carImageUrl" :src="form.carImageUrl" class="avatar" />
|
<img v-if="form.carImageUrl" :src="form.carImageUrl" alt="车辆照片" class="avatar" />
|
||||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||||
<template #tip>
|
<template #tip>
|
||||||
<div style="color: gray; font-size: small">支持jpg, png等格式文件上传</div>
|
<div style="color: gray; font-size: small">支持jpg, png等格式文件上传</div>
|
||||||
@@ -64,10 +64,10 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="持有人">
|
<el-form-item label="持有人">
|
||||||
<AppUser returnable="*" :isMultiple="false" ref="HolderRef" @change="handleChange">
|
<AppUser ref="HolderRef" :isMultiple="false" returnable="*" @change="handleChange">
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="residentBox" @click="choiceResidentFun">
|
<div class="residentBox" @click="choiceResidentFun">
|
||||||
<div class="defaultBox" v-if="form.userId === ''">
|
<div v-if="form.userId === ''" class="defaultBox">
|
||||||
<span>请选择</span>
|
<span>请选择</span>
|
||||||
<el-icon><Search /></el-icon>
|
<el-icon><Search /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input maxlength="200" show-word-limit type="textarea" :rows="5" v-model.trim="form.remark" placeholder="请输入" />
|
<el-input v-model.trim="form.remark" :rows="5" maxlength="200" placeholder="请输入" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -98,9 +98,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import Holder from '@/components/Holder/index.vue';
|
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { listArea } from '@/api/system/carArea';
|
import { listArea } from '@/api/system/carArea';
|
||||||
import { listParking } from '@/api/system/parking';
|
import { listParking } from '@/api/system/parking';
|
||||||
@@ -242,7 +241,7 @@ const cancelForm = () => {
|
|||||||
router.back();
|
router.back();
|
||||||
};
|
};
|
||||||
const holderInfo = ref(null);
|
const holderInfo = ref(null);
|
||||||
const HolderRef = ref<typeof Holder>(null);
|
const HolderRef = ref<typeof AppUser>(null);
|
||||||
function choiceResidentFun() {
|
function choiceResidentFun() {
|
||||||
if (form.value.userId && form.value.userId.trim() !== '') {
|
if (form.value.userId && form.value.userId.trim() !== '') {
|
||||||
HolderRef.value.open([form.value.userId]);
|
HolderRef.value.open([form.value.userId]);
|
||||||
@@ -262,7 +261,7 @@ function handleChange(pop) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 178px;
|
width: 178px;
|
||||||
height: 178px;
|
height: 178px;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col h-full p-2">
|
<div class="flex flex-col h-full p-2">
|
||||||
<Pageheader title="车辆管理"></Pageheader>
|
<pageHeader title="车辆管理"></pageHeader>
|
||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" @submit.prevent="handleQuery">
|
||||||
<el-form-item label="车牌号" prop="carNum">
|
<el-form-item label="车牌号" prop="carNum">
|
||||||
<el-input maxlength="12" v-model.trim="queryParams.carNum" placeholder="请输入车牌号" clearable @keyup.enter="handleQuery" />
|
<el-input v-model.trim="queryParams.carNum" clearable maxlength="12" placeholder="请输入车牌号" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="车辆品牌" prop="carBrand">
|
<el-form-item label="车辆品牌" prop="carBrand">
|
||||||
<el-input maxlength="12" v-model.trim="queryParams.carBrand" placeholder="请输入车辆品牌" clearable @keyup.enter="handleQuery" />
|
<el-input v-model.trim="queryParams.carBrand" clearable maxlength="12" placeholder="请输入车辆品牌" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="车身颜色" prop="carColor">
|
<el-form-item label="车身颜色" prop="carColor">
|
||||||
<el-input maxlength="12" v-model.trim="queryParams.carColor" placeholder="请输入车身颜色" clearable @keyup.enter="handleQuery" />
|
<el-input v-model.trim="queryParams.carColor" clearable maxlength="12" placeholder="请输入车身颜色" @keyup.enter="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
:disable-delete="multiple"
|
:disable-delete="multiple"
|
||||||
:disable-edit="single"
|
:disable-edit="single"
|
||||||
:show-add="checkPermi(['car:car:add'])"
|
:show-add="checkPermi(['car:car:add'])"
|
||||||
:show-edit="checkPermi(['car:car:edit'])"
|
|
||||||
:show-delete="checkPermi(['car:car:remove'])"
|
:show-delete="checkPermi(['car:car:remove'])"
|
||||||
|
:show-edit="checkPermi(['car:car:edit'])"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -39,34 +39,33 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="carList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="carList" border @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<el-table-column label="车牌号" align="center" prop="carNum" />
|
<el-table-column align="center" label="车牌号" prop="carNum" />
|
||||||
<el-table-column label="车辆品牌" align="center" prop="carBrand" />
|
<el-table-column align="center" label="车辆品牌" prop="carBrand" />
|
||||||
<el-table-column label="车辆型号" align="center" prop="carModel" />
|
<el-table-column align="center" label="车辆型号" prop="carModel" />
|
||||||
<el-table-column label="车身颜色" align="center" prop="carColor" />
|
<el-table-column align="center" label="车身颜色" prop="carColor" />
|
||||||
<el-table-column label="持有人" align="center" prop="userName">
|
<el-table-column align="center" label="持有人" prop="userName">
|
||||||
<template #default="scope"> {{ scope.row.userName }} </template>
|
<template #default="scope"> {{ scope.row.userName }} </template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
<el-table-column align="center" label="备注" prop="remark" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" align="center">
|
<el-table-column align="center" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-has-permi="['car:car:edit']">修改</el-button>
|
<el-button v-has-permi="['car:car:edit']" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['car:car:remove']">删除</el-button>
|
<el-button v-has-permi="['car:car:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Car" lang="ts">
|
<script lang="ts" name="Car" setup>
|
||||||
import Pageheader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { listCar, delCar } from '@/api/system/cars/index';
|
import { listCar, delCar } from '@/api/system/cars';
|
||||||
import { CarVO, CarQuery, CarForm } from '@/api/system/cars/type';
|
import { CarVO, CarQuery, CarForm } from '@/api/system/cars/type';
|
||||||
import { listResident } from '@/api/system/residentReviewProcess/resident';
|
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
@@ -74,7 +73,6 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const carList = ref<CarVO[]>([]);
|
const carList = ref<CarVO[]>([]);
|
||||||
const buttonLoading = ref(false);
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
const ids = ref<Array<string | number>>([]);
|
const ids = ref<Array<string | number>>([]);
|
||||||
@@ -83,7 +81,6 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const carFormRef = ref<ElFormInstance>();
|
|
||||||
|
|
||||||
const initFormData: CarForm = {
|
const initFormData: CarForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@@ -162,7 +159,7 @@ const handleAdd = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = async (row?: CarVO) => {
|
const handleUpdate = (row?: CarVO) => {
|
||||||
const id = row?.id || ids.value[0];
|
const id = row?.id || ids.value[0];
|
||||||
router.push({
|
router.push({
|
||||||
path: '/carArea/editCars',
|
path: '/carArea/editCars',
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user