9/20
This commit is contained in:
@@ -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.1.222:8080'
|
||||||
# 开发环境 接口代理地址
|
# 开发环境 接口代理地址
|
||||||
#VITE_APP_PROXY_API='http://192.168.1.6:8080'
|
VITE_APP_PROXY_API='http://192.168.1.6: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'
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export const cashQuery = (data: { residentName?: string; queryType: number }): A
|
|||||||
|
|
||||||
export type billlistType = {
|
export type billlistType = {
|
||||||
/**
|
/**
|
||||||
* 类型 0物业费 1车位管理费 2垃圾处理费 3租金 4押金
|
* 类型 0 物业费 1 车位管理费 2 垃圾处理费 3 租金 4 押金
|
||||||
*/
|
*/
|
||||||
detailsType: string;
|
detailsType: string;
|
||||||
unitNoId: string;
|
unitNoId: string;
|
||||||
@@ -57,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',
|
||||||
@@ -113,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;
|
||||||
}[];
|
}[];
|
||||||
@@ -130,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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export interface ElectricityDeviceVO {
|
|||||||
'totalEnergy': string;
|
'totalEnergy': string;
|
||||||
'readTime': string;
|
'readTime': string;
|
||||||
'balance': string;
|
'balance': string;
|
||||||
'status': number;
|
'status': string;
|
||||||
'event': string;
|
'event': string;
|
||||||
'rangeTime': string;
|
'rangeTime': string;
|
||||||
'rangeFee': number;
|
'rangeFee': number;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
userType: {
|
userType: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'complainUser'
|
default: ''
|
||||||
},
|
},
|
||||||
isMultiple: {
|
isMultiple: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|||||||
@@ -19,20 +19,21 @@
|
|||||||
<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>
|
||||||
ref="multipleTableRef"
|
<el-table-column align="center" width="55">
|
||||||
:data="tableData"
|
<template #header>
|
||||||
border
|
<el-checkbox v-model="isSelectAll" :disabled="!isMultiple" :indeterminate="isIndeterminate" @change="handleSelectAllChange" />
|
||||||
@select-all="handleSelectionChange"
|
</template>
|
||||||
@row-click="handleRowClick"
|
<template #default="scope">
|
||||||
@selection-change="handleSelectionChange"
|
<el-checkbox :model-value="isRowSelected(scope.row)" @change="(val: boolean) => handleRowCheckChange(scope.row, val)" />
|
||||||
>
|
</template>
|
||||||
<el-table-column align="center" type="selection" width="55" />
|
</el-table-column>
|
||||||
<el-table-column align="center" label="物料名称" prop="materialName" />
|
<el-table-column align="center" label="物料名称" prop="materialName" />
|
||||||
<el-table-column align="center" label="品牌" prop="brand" />
|
<el-table-column align="center" label="品牌" prop="brand" />
|
||||||
<el-table-column align="center" label="规格型号" prop="model" />
|
<el-table-column align="center" label="规格型号" prop="model" />
|
||||||
<el-table-column align="center" label="单位" prop="unit" />
|
<el-table-column align="center" label="单位" prop="unit" />
|
||||||
<el-table-column v-if="!isHidden" align="center" label="数量" prop="stockNum" />
|
<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-column align="center" label="备注" prop="remark" />
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@
|
|||||||
/>
|
/>
|
||||||
<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>
|
||||||
@@ -58,7 +59,7 @@
|
|||||||
<script lang="ts" setup>
|
<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;
|
||||||
|
|
||||||
@@ -109,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;
|
||||||
@@ -151,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 = {
|
||||||
@@ -199,6 +216,7 @@ function resetQuery() {
|
|||||||
brand: '',
|
brand: '',
|
||||||
materialName: ''
|
materialName: ''
|
||||||
};
|
};
|
||||||
|
resetSelection();
|
||||||
getlist();
|
getlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,44 +226,90 @@ 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>
|
||||||
|
|||||||
@@ -1,71 +1,71 @@
|
|||||||
<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 v-if="multipleSelection.length === 0 && props.username === null" class="defaultBox">
|
<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 v-model="dialog.dialogVisible" :title="dialog.dialogTitle" append-to-body 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 v-model="queryParams.nickName" clearable placeholder="请输入员工姓名" style="width: 170px" />
|
|
||||||
</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 v-model="queryParams.phonenumber" clearable placeholder="请输入手机号" style="width: 170px" />
|
</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 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>
|
<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 lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ 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 multipleSelection = ref<BillUserlist[]>([]);
|
const multipleSelection = ref<BillUserlist[]>([]);
|
||||||
/** 是否已跨页全选(标记模式,不实际持有全部数据) */
|
/** 是否已跨页全选(标记模式,不实际持有全部数据) */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<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">
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<el-button
|
<el-button
|
||||||
v-for="q in 4"
|
v-for="q in 4"
|
||||||
:key="q"
|
:key="q"
|
||||||
:disabled="isDisabledQuarter(currentYear, q)"
|
:disabled="isDisabledQuarter()"
|
||||||
:type="isSelected(currentYear, q) ? 'primary' : ''"
|
:type="isSelected(currentYear, q) ? 'primary' : ''"
|
||||||
style="margin: 0"
|
style="margin: 0"
|
||||||
@click="handleSelect(currentYear, q)"
|
@click="handleSelect(currentYear, q)"
|
||||||
@@ -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 };
|
||||||
@@ -72,7 +72,7 @@ const displayText = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 是否选中该季度
|
// 是否选中该季度
|
||||||
const isSelected = (y, q) => {
|
const isSelected = (y: any, q: any) => {
|
||||||
return props.modelValue === `${y}-${q}`;
|
return props.modelValue === `${y}-${q}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,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);
|
||||||
|
|||||||
@@ -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,15 @@
|
|||||||
<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" />
|
<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" v-has-permi="['system:user:profile']">
|
<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 +51,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 +61,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 +94,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: {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
});
|
||||||
|
|||||||
@@ -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>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -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,14 +44,16 @@ 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;
|
||||||
const notice = tryParseJson(data.value);
|
const notice = tryParseJson(data.value as string);
|
||||||
if (typeof notice === 'string') {
|
if (typeof notice === 'string') {
|
||||||
useNoticeStore().addNotice({
|
useNoticeStore().addNotice({
|
||||||
message: notice,
|
message: notice,
|
||||||
@@ -42,7 +69,6 @@ export const initSSE = (url: any) => {
|
|||||||
data.value = null;
|
data.value = null;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// 此处 notice 类型为 Record<string, unknown>,安全取出属性
|
|
||||||
const title = typeof notice.title === 'string' ? notice.title : '消息';
|
const title = typeof notice.title === 'string' ? notice.title : '消息';
|
||||||
const message = typeof notice.message === 'string' ? notice.message : '';
|
const message = typeof notice.message === 'string' ? notice.message : '';
|
||||||
const type = typeof notice.type === 'string' ? notice.type : 'info';
|
const type = typeof notice.type === 'string' ? notice.type : 'info';
|
||||||
@@ -75,7 +101,7 @@ function tryParseJson(str: string): string | Record<string, unknown> {
|
|||||||
if (trimStr === '') return str;
|
if (trimStr === '') return str;
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(trimStr);
|
const parsed = JSON.parse(trimStr);
|
||||||
// 只有"纯对象"才返回对象,数组/null/基础值等统一当作字符串处理
|
// 只有纯对象才返回对象,数组/null/基础值等统一当作字符串处理
|
||||||
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||||
return parsed as Record<string, unknown>;
|
return parsed as Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
<span>{{ scope.row.createTime }}</span>
|
<span>{{ scope.row.createTime }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作">
|
<el-table-column align="center" class-name="small-padding fixed-width" label="操作">
|
||||||
<template #default="scope">
|
<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: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>
|
<el-button v-has-permi="['complaintType:complaintType:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
|||||||
@@ -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,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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -79,8 +79,9 @@
|
|||||||
:preview-src-list="[scope.row.url]"
|
:preview-src-list="[scope.row.url]"
|
||||||
:src="scope.row.url"
|
:src="scope.row.url"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
|
lazy
|
||||||
preview-teleported
|
preview-teleported
|
||||||
style="width: 90%; height: 100%"
|
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>
|
||||||
@@ -98,15 +99,17 @@
|
|||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch
|
<el-switch
|
||||||
v-if="scope.row.electricityRecord"
|
v-if="scope.row.electricityRecord"
|
||||||
v-model="scope.row.electricityRecord.status"
|
:active-value="true"
|
||||||
:active-value="0"
|
|
||||||
:before-change="
|
:before-change="
|
||||||
() => {
|
() => {
|
||||||
const status = scope.row.status === 1 ? 0 : 1;
|
// 0 合闸 1 2 拉闸
|
||||||
|
// 0 合闸 传入 1 拉闸 传入 0
|
||||||
|
const status = scope.row.electricityRecord.status === 0 ? 1 : 0;
|
||||||
return handleChangeWater(status, scope.row);
|
return handleChangeWater(status, scope.row);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:inactive-value="1"
|
:inactive-value="false"
|
||||||
|
:model-value="scope.row.electricityRecord.status === 0"
|
||||||
active-text="合闸"
|
active-text="合闸"
|
||||||
inactive-text="拉闸"
|
inactive-text="拉闸"
|
||||||
></el-switch>
|
></el-switch>
|
||||||
|
|||||||
@@ -39,11 +39,14 @@
|
|||||||
<div class="label">维护人员:</div>
|
<div class="label">维护人员:</div>
|
||||||
<span class="value">{{ form.maintainUserListName }}</span>
|
<span class="value">{{ form.maintainUserListName }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="info_item">
|
||||||
|
<div class="label">设备保质期:</div>
|
||||||
|
<span class="value">{{ form.shelfLife }}</span>
|
||||||
|
</div>
|
||||||
<div class="info_item">
|
<div class="info_item">
|
||||||
<div class="label">添加时间:</div>
|
<div class="label">添加时间:</div>
|
||||||
<span class="value">{{ form.createTime }}</span>
|
<span class="value">{{ form.createTime }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div></div>
|
|
||||||
<div class="info_item">
|
<div class="info_item">
|
||||||
<div class="label">备注:</div>
|
<div class="label">备注:</div>
|
||||||
<span class="value">{{ form.remark }}</span>
|
<span class="value">{{ form.remark }}</span>
|
||||||
@@ -55,17 +58,17 @@
|
|||||||
<div class="title">维修记录</div>
|
<div class="title">维修记录</div>
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<el-table v-loading="loading" :data="deviceRepairList">
|
<el-table v-loading="loading" :data="deviceRepairList">
|
||||||
<el-table-column type="index" align="center" />
|
<el-table-column align="center" type="index" />
|
||||||
<el-table-column label="设备名称" align="center" prop="deviceName" />
|
<el-table-column align="center" label="设备名称" prop="deviceName" />
|
||||||
<el-table-column label="设备编号" align="center" prop="deviceCode" />
|
<el-table-column align="center" label="设备编号" prop="deviceCode" />
|
||||||
<el-table-column label="维修人员" align="center" prop="maintainUserNames" />
|
<el-table-column align="center" label="维修人员" prop="maintainUserNames" />
|
||||||
<el-table-column label="故障描述" align="center" prop="faultDesc" />
|
<el-table-column align="center" label="故障描述" prop="faultDesc" />
|
||||||
<el-table-column label="维修结果" align="center" prop="repairResult">
|
<el-table-column align="center" label="维修结果" prop="repairResult">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="com_equipment_repair_status" :value="scope.row.repairResult"></dict-tag>
|
<dict-tag :options="com_equipment_repair_status" :value="scope.row.repairResult"></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="handleMain(scope.row)">详情</el-button>
|
<el-button link type="primary" @click="handleMain(scope.row)">详情</el-button>
|
||||||
<el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
|
<el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
|
||||||
@@ -73,13 +76,13 @@
|
|||||||
</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>
|
||||||
</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 { getDevice } from '@/api/system/equipment/archive';
|
import { getDevice } from '@/api/system/equipment/archive';
|
||||||
@@ -100,6 +103,7 @@ const form = ref({
|
|||||||
deviceModel: '', // 型号
|
deviceModel: '', // 型号
|
||||||
area: '', // 区域
|
area: '', // 区域
|
||||||
status: '0', // 区域
|
status: '0', // 区域
|
||||||
|
shelfLife: '', // 设备保质期
|
||||||
maintainUserIds: '', // 设备维护人员
|
maintainUserIds: '', // 设备维护人员
|
||||||
maintainUserListName: '', // 设备维护人员
|
maintainUserListName: '', // 设备维护人员
|
||||||
createTime: '', // 设备维护人员
|
createTime: '', // 设备维护人员
|
||||||
@@ -109,7 +113,10 @@ const form = ref({
|
|||||||
const userid = ref(null);
|
const userid = ref(null);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const deviceRepairList = ref([]);
|
type DeviceRepairVOList = DeviceRepairVO & {
|
||||||
|
maintainUserNames?: string;
|
||||||
|
};
|
||||||
|
const deviceRepairList = ref<DeviceRepairVOList[]>([]);
|
||||||
|
|
||||||
const queryParams = ref({
|
const queryParams = ref({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@@ -124,6 +131,7 @@ function init() {
|
|||||||
id: res.data.id,
|
id: res.data.id,
|
||||||
categoryName: res.data.categoryName,
|
categoryName: res.data.categoryName,
|
||||||
deviceName: res.data.deviceName,
|
deviceName: res.data.deviceName,
|
||||||
|
shelfLife: res.data.shelfLife,
|
||||||
deviceCode: res.data.deviceCode,
|
deviceCode: res.data.deviceCode,
|
||||||
deviceModel: res.data.deviceModel,
|
deviceModel: res.data.deviceModel,
|
||||||
area: res.data.area,
|
area: res.data.area,
|
||||||
@@ -139,15 +147,19 @@ function init() {
|
|||||||
.filter((it) => it !== null)
|
.filter((it) => it !== null)
|
||||||
.join(',');
|
.join(',');
|
||||||
}
|
}
|
||||||
getlist();
|
getList();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
|
|
||||||
async function getlist() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
listDeviceRepair()
|
listDeviceRepair({
|
||||||
|
deviceId: form.value.id,
|
||||||
|
pageNum: queryParams.value.pageNum,
|
||||||
|
pageSize: queryParams.value.pageSize
|
||||||
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
deviceRepairList.value = rows.rows;
|
deviceRepairList.value = rows.rows;
|
||||||
deviceRepairList.value.forEach((item) => {
|
deviceRepairList.value.forEach((item) => {
|
||||||
@@ -177,10 +189,10 @@ const handleDelete = async (row?: DeviceRepairVO) => {
|
|||||||
await proxy?.$modal.confirm('是否确认删除维修工单?');
|
await proxy?.$modal.confirm('是否确认删除维修工单?');
|
||||||
await delDeviceRepair(_ids);
|
await delDeviceRepair(_ids);
|
||||||
proxy?.$modal.msgSuccess('删除成功');
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
getlist();
|
getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMain = (row) => {
|
const handleMain = (row: DeviceRepairVO) => {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/equipment/equipmentRepairMain',
|
path: '/equipment/equipmentRepairMain',
|
||||||
query: {
|
query: {
|
||||||
@@ -188,7 +200,7 @@ const handleMain = (row) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const handleEdit = (row) => {
|
const handleEdit = (row: DeviceRepairVO) => {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/equipment/editEquipmentRepair',
|
path: '/equipment/editEquipmentRepair',
|
||||||
query: {
|
query: {
|
||||||
@@ -202,7 +214,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" label-width="100" :model="queryParams" :inline="true">
|
<el-form ref="queryFormRef" :inline="true" :model="queryParams" label-width="100">
|
||||||
<el-form-item label="设备分类名称" prop="categoryName">
|
<el-form-item label="设备分类名称" prop="categoryName">
|
||||||
<el-input maxlength="20" v-model="queryParams.categoryName" placeholder="请输入设备分类名称" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.categoryName" 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(['warehouse:deviceCategory:add'])"
|
:show-add="checkPermi(['warehouse:deviceCategory:add'])"
|
||||||
:show-edit="false"
|
|
||||||
:show-delete="checkPermi(['warehouse:deviceCategory:remove'])"
|
:show-delete="checkPermi(['warehouse:deviceCategory:remove'])"
|
||||||
|
:show-edit="false"
|
||||||
@update:add="handleAdd"
|
@update:add="handleAdd"
|
||||||
@update:edit="handleUpdate()"
|
@update:edit="handleUpdate()"
|
||||||
@update:delete="handleDelete()"
|
@update:delete="handleDelete()"
|
||||||
@@ -33,39 +33,36 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table v-loading="loading" border :data="deviceCategoryList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="deviceCategoryList" 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="categoryName" />
|
<el-table-column align="center" label="设备分类名称" prop="categoryName" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column align="center" label="状态" prop="status">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch :inactive-value="1" :active-value="0" v-model="scope.row.status"></el-switch>
|
<el-switch
|
||||||
|
v-model="scope.row.status"
|
||||||
|
:active-value="0"
|
||||||
|
:before-change="() => updateDeviceSwitch(scope.row)"
|
||||||
|
:inactive-value="1"
|
||||||
|
></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<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="['warehouse:deviceCategory:edit']">编辑</el-button>
|
<el-button v-has-permi="['warehouse:deviceCategory:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-has-permi="['warehouse:deviceCategory:remove']">删除</el-button>
|
<el-button v-has-permi="['warehouse:deviceCategory: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="deviceCategoryFormRef" :model="form" :rules="rules" label-width="120px">
|
<el-form ref="deviceCategoryFormRef" :model="form" :rules="rules" label-width="120px">
|
||||||
<el-form-item label="设备分类名称" prop="categoryName">
|
<el-form-item label="设备分类名称" prop="categoryName">
|
||||||
<el-input maxlength="20" show-word-limit v-model="form.categoryName" placeholder="请输入设备分类名称" />
|
<el-input v-model="form.categoryName" maxlength="20" placeholder="请输入设备分类名称" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备分类状态" prop="status">
|
|
||||||
<el-radio-group v-model="form.status">
|
|
||||||
<el-radio v-for="(item, index) in com_equipment_device_category" :key="index" :value="Number(item.value)" :label="item.label"></el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- <el-form-item label="备注" prop="remark">
|
|
||||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
|
||||||
</el-form-item> -->
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
@@ -77,13 +74,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="DeviceCategory" lang="ts">
|
<script lang="ts" name="DeviceCategory" setup>
|
||||||
import { listDeviceCategory, delDeviceCategory, addDeviceCategory, updateDeviceCategory } from '@/api/system/equipment/Category';
|
import { listDeviceCategory, delDeviceCategory, addDeviceCategory, updateDeviceCategory } from '@/api/system/equipment/Category';
|
||||||
import { DeviceCategoryVO, DeviceCategoryQuery, DeviceCategoryForm } from '@/api/system/equipment/Category/type';
|
import { DeviceCategoryVO, DeviceCategoryQuery, DeviceCategoryForm } from '@/api/system/equipment/Category/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_equipment_device_category } = toRefs<any>(proxy?.useDict('com_equipment_device_category'));
|
|
||||||
|
|
||||||
const deviceCategoryList = ref<DeviceCategoryVO[]>([]);
|
const deviceCategoryList = ref<DeviceCategoryVO[]>([]);
|
||||||
const buttonLoading = ref(false);
|
const buttonLoading = ref(false);
|
||||||
@@ -135,6 +131,22 @@ const getList = async () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function updateDeviceSwitch(row: DeviceCategoryVO): Promise<boolean> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const obj = {
|
||||||
|
id: row.id,
|
||||||
|
status: row.status === 1 ? 0 : 1
|
||||||
|
};
|
||||||
|
updateDeviceCategory(obj)
|
||||||
|
.then(() => {
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
reject(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** 取消按钮 */
|
/** 取消按钮 */
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
reset();
|
reset();
|
||||||
|
|||||||
@@ -4,43 +4,44 @@
|
|||||||
<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="deviceId">
|
<el-form-item label="设备分类" prop="categoryId">
|
||||||
<el-select v-model="form.deviceId">
|
<el-select v-model="form.categoryId" @change="handleCategoryIdChange">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item, index) in deviceCategorylist"
|
v-for="(item, index) in deviceCategoryList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:disabled="item.status === 1"
|
:disabled="item.status === 1"
|
||||||
:value="item.id"
|
|
||||||
:label="item.categoryName"
|
:label="item.categoryName"
|
||||||
|
:value="item.id"
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备名称" prop="deviceName">
|
<el-form-item label="设备名称" prop="deviceId">
|
||||||
<el-input maxlength="20" v-model.trim="form.deviceName" placeholder="请输入设备名称" />
|
<el-select v-model="form.deviceId" filterable @change="handleDeviceChange">
|
||||||
|
<el-option v-for="(item, index) in deviceList" :key="index" :label="item.deviceName" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备编号" prop="deviceCode">
|
<el-form-item label="设备编号" prop="deviceCode">
|
||||||
<el-input maxlength="20" v-model.trim="form.deviceCode" placeholder="请输入设备编号" />
|
<el-input v-model.trim="form.deviceCode" disabled maxlength="20" placeholder="请输入设备编号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备型号" prop="deviceModel">
|
<el-form-item label="设备型号" prop="deviceModel">
|
||||||
<el-input maxlength="20" v-model.trim="form.deviceModel" placeholder="请输入设备型号" />
|
<el-input v-model.trim="form.deviceModel" disabled maxlength="20" placeholder="请输入设备型号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="位置区域" prop="area">
|
<el-form-item label="位置区域" prop="area">
|
||||||
<el-input maxlength="100" show-word-limit type="textarea" :rows="2" v-model.trim="form.area" placeholder="请输入位置区域" />
|
<el-input v-model.trim="form.area" :rows="2" maxlength="100" placeholder="请输入位置区域" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="维护人员" prop="maintainUserIds">
|
<el-form-item label="维护人员" prop="maintainUserIds">
|
||||||
<repairUser
|
<repairUser
|
||||||
userType="repair"
|
|
||||||
EquipmentMaintenance
|
|
||||||
:userid="checkoutuseid"
|
|
||||||
ref="repairUserRef"
|
ref="repairUserRef"
|
||||||
returnvalue="*"
|
|
||||||
:is-multiple="true"
|
:is-multiple="true"
|
||||||
|
:userid="checkoutUseId"
|
||||||
|
returnvalue="*"
|
||||||
title-name="维护人员"
|
title-name="维护人员"
|
||||||
|
userType="repair"
|
||||||
@change="handleCheckoutUser"
|
@change="handleCheckoutUser"
|
||||||
>
|
>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="checkoutuserbox flex flex-items-center justify-around" v-for="(item, index) in checkoutuser" :key="index">
|
<div v-for="(item, index) in checkoutUser" :key="index" class="checkoutUserBox flex flex-items-center justify-around">
|
||||||
<span>{{ item.nickName }}</span>
|
<span>{{ item.nickName }}</span>
|
||||||
<div @click="handleDelete(item.id)">
|
<div @click="handleDelete(item.id)">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@@ -48,7 +49,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkoutuserbox add flex flex-items-center justify-center" @click="() => repairUserRef.open()">
|
<div class="checkoutUserBox add flex flex-items-center justify-center" @click="() => repairUserRef.open()">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Plus></Plus>
|
<Plus></Plus>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
@@ -58,15 +59,15 @@
|
|||||||
</repairUser>
|
</repairUser>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="故障描述" prop="faultDesc">
|
<el-form-item label="故障描述" prop="faultDesc">
|
||||||
<el-input maxlength="100" show-word-limit type="textarea" :rows="2" v-model.trim="form.faultDesc" placeholder="请输入" />
|
<el-input v-model.trim="form.faultDesc" :rows="2" maxlength="100" placeholder="请输入" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="维修结果" prop="repairResult">
|
<el-form-item label="维修结果" prop="repairResult">
|
||||||
<el-radio-group v-model.trim="form.repairResult">
|
<el-radio-group v-model.trim="form.repairResult">
|
||||||
<el-radio v-for="(item, index) in com_equipment_repair_status" :value="item.value" :label="item.label" :key="index"></el-radio>
|
<el-radio v-for="(item, index) in com_equipment_repair_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 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-form-item style="margin-top: 30px">
|
<el-form-item style="margin-top: 30px">
|
||||||
@@ -78,13 +79,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import repairUser from '@/components/Holder/repairUser.vue';
|
import repairUser from '@/components/Holder/repairUser.vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { listDeviceCategory } from '@/api/system/equipment/Category';
|
import { listDeviceCategory } from '@/api/system/equipment/Category';
|
||||||
import { Delete, Plus } from '@element-plus/icons-vue';
|
import { Delete, Plus } from '@element-plus/icons-vue';
|
||||||
import { addDeviceRepair, getDeviceRepair, updateDeviceRepair } from '@/api/system/equipment/Repair';
|
import { addDeviceRepair, getDeviceRepair, updateDeviceRepair } from '@/api/system/equipment/Repair';
|
||||||
|
import { listDevice } from '@/api/system/equipment/archive';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_equipment_repair_status } = toRefs<any>(proxy?.useDict('com_equipment_repair_status'));
|
const { com_equipment_repair_status } = toRefs<any>(proxy?.useDict('com_equipment_repair_status'));
|
||||||
@@ -96,7 +98,8 @@ const formRef = ref();
|
|||||||
const repairUserRef = ref();
|
const repairUserRef = ref();
|
||||||
const form = ref({
|
const form = ref({
|
||||||
id: null,
|
id: null,
|
||||||
deviceId: '', // 分类id、
|
categoryId: '', // 分类id、
|
||||||
|
deviceId: '', // 设备id
|
||||||
deviceName: '', // 设备名称
|
deviceName: '', // 设备名称
|
||||||
deviceCode: '', // 编号
|
deviceCode: '', // 编号
|
||||||
deviceModel: '', // 型号
|
deviceModel: '', // 型号
|
||||||
@@ -107,22 +110,40 @@ const form = ref({
|
|||||||
remark: '' // 备注
|
remark: '' // 备注
|
||||||
});
|
});
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
deviceId: [{ required: true, message: '请选择 设备类型', trigger: 'blur' }],
|
categoryId: [{ required: true, message: '请选择 设备分类', trigger: 'blur' }],
|
||||||
|
deviceId: [{ required: true, message: '请选择 设备', trigger: 'blur' }],
|
||||||
deviceName: [{ required: true, message: '请输入 设备名称', trigger: 'blur' }],
|
deviceName: [{ required: true, message: '请输入 设备名称', trigger: 'blur' }],
|
||||||
faultDesc: [{ required: true, message: '请输入 故障描述', trigger: 'blur' }],
|
faultDesc: [{ required: true, message: '请输入 故障描述', trigger: 'blur' }],
|
||||||
maintainUserIds: [{ required: true, message: '请选择 维修人员', trigger: 'blur' }]
|
maintainUserIds: [{ required: true, message: '请选择 维修人员', trigger: 'blur' }]
|
||||||
});
|
});
|
||||||
const userid = ref(null);
|
const userid = ref(null);
|
||||||
|
|
||||||
const deviceCategorylist = ref([]);
|
// 设备列表
|
||||||
|
const deviceList = ref([]);
|
||||||
|
// 分类列表
|
||||||
|
const deviceCategoryList = ref([]);
|
||||||
|
function handleCategoryIdChange(val: string) {
|
||||||
|
listDevice({ categoryId: val, pageNum: 1, pageSize: undefined }).then((res) => {
|
||||||
|
deviceList.value = res.rows;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function handleDeviceChange(val: string) {
|
||||||
|
const find = deviceList.value.find((item) => item.id === val);
|
||||||
|
if (find) {
|
||||||
|
form.value.deviceName = find.deviceName;
|
||||||
|
form.value.deviceCode = find.deviceCode;
|
||||||
|
form.value.deviceModel = find.deviceModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
function init() {
|
function init() {
|
||||||
listDeviceCategory().then((res) => {
|
listDeviceCategory().then((res) => {
|
||||||
deviceCategorylist.value = res.rows;
|
deviceCategoryList.value = res.rows;
|
||||||
});
|
});
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
userid.value = route.query.id;
|
userid.value = route.query.id;
|
||||||
getDeviceRepair(userid.value).then((res) => {
|
getDeviceRepair(userid.value).then((res) => {
|
||||||
form.value = {
|
form.value = {
|
||||||
|
categoryId: res.data.categoryId,
|
||||||
id: res.data.id,
|
id: res.data.id,
|
||||||
deviceName: res.data.deviceName,
|
deviceName: res.data.deviceName,
|
||||||
deviceCode: res.data.deviceCode,
|
deviceCode: res.data.deviceCode,
|
||||||
@@ -131,38 +152,38 @@ function init() {
|
|||||||
maintainUserIds: res.data.maintainUserIds,
|
maintainUserIds: res.data.maintainUserIds,
|
||||||
area: res.data.area,
|
area: res.data.area,
|
||||||
faultDesc: res.data.faultDesc,
|
faultDesc: res.data.faultDesc,
|
||||||
|
|
||||||
repairResult: res.data.repairResult,
|
repairResult: res.data.repairResult,
|
||||||
remark: res.data.remark
|
remark: res.data.remark
|
||||||
};
|
};
|
||||||
|
// 根据 分类id 回显设备
|
||||||
checkoutuser.value = [];
|
handleCategoryIdChange(res.data.categoryId);
|
||||||
checkoutuser.value = res.data.maintainUserList ?? [];
|
checkoutUser.value = [];
|
||||||
|
checkoutUser.value = res.data.maintainUserList ?? [];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
|
// 用于回显维修人员
|
||||||
const checkoutuseid = computed(() => {
|
const checkoutUseId = computed(() => {
|
||||||
return checkoutuser.value
|
return checkoutUser.value
|
||||||
.map((item) => item.userId)
|
.map((item) => item.userId)
|
||||||
.filter((item) => item)
|
.filter((item) => item)
|
||||||
.join(',');
|
.join(',');
|
||||||
});
|
});
|
||||||
const checkoutuser = ref([]);
|
// 选择维修人员
|
||||||
function handleCheckoutUser(row) {
|
const checkoutUser = ref([]);
|
||||||
checkoutuser.value = row;
|
function handleCheckoutUser(row: any[]) {
|
||||||
|
checkoutUser.value = row;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDelete(id: string) {
|
function handleDelete(id: string) {
|
||||||
checkoutuser.value = checkoutuser.value.filter((item) => item.id !== id);
|
checkoutUser.value = checkoutUser.value.filter((item) => item.id !== id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// !== 提交 =============================================================================
|
// !== 提交 =============================================================================
|
||||||
// 提交
|
// 提交
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
form.value.maintainUserIds = checkoutuser.value
|
form.value.maintainUserIds = checkoutUser.value
|
||||||
.map((itme) => itme.userId)
|
.map((item) => item.userId)
|
||||||
.filter((item) => item)
|
.filter((item) => item)
|
||||||
.join(',');
|
.join(',');
|
||||||
formRef.value?.validate(async (valid: boolean) => {
|
formRef.value?.validate(async (valid: boolean) => {
|
||||||
@@ -187,7 +208,7 @@ const cancelForm = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.AddBuildingBox {
|
.AddBuildingBox {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -214,7 +235,7 @@ const cancelForm = () => {
|
|||||||
width: 650px;
|
width: 650px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
.checkoutuserbox {
|
.checkoutUserBox {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" label="备注" prop="remark" />
|
<el-table-column align="center" label="备注" prop="remark" />
|
||||||
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" width="160">
|
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" min-width="160">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button v-has-permi="['warehouse:deviceRepair:query']" link type="primary" @click="handleMain(scope.row)">查看详情</el-button>
|
<el-button v-has-permi="['warehouse:deviceRepair:query']" link type="primary" @click="handleMain(scope.row)">查看详情</el-button>
|
||||||
<el-button v-has-permi="['warehouse:deviceRepair:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
<el-button v-has-permi="['warehouse:deviceRepair:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
|
|||||||
@@ -7,39 +7,39 @@
|
|||||||
<el-button v-if="HouseInfo.house" v-has-permi="['system:house:edit']" text type="primary" @click="editHouse">编辑</el-button>
|
<el-button v-if="HouseInfo.house" v-has-permi="['system:house:edit']" text type="primary" @click="editHouse">编辑</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="HouseInfo.house" class="addBuildingFormBody">
|
<div v-if="HouseInfo.house" class="addBuildingFormBody">
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">房号:</div>
|
<div class="label">房号:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.buildingName }}-{{ HouseInfo.house?.unitNoName }}-{{ HouseInfo.house?.houseNo ?? '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.buildingName }}-{{ HouseInfo.house?.unitNoName }}-{{ HouseInfo.house?.houseNo ?? '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">所属小区:</div>
|
<div class="label">所属小区:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.villageName ?? '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.villageName ?? '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">楼栋:</div>
|
<div class="label">楼栋:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.buildingName ?? '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.buildingName ?? '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">单元:</div>
|
<div class="label">单元:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.unitNoName ?? '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.unitNoName ?? '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">楼层:</div>
|
<div class="label">楼层:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.floorNo ? HouseInfo.house?.floorNo + ' 层' : '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.floorNo ? HouseInfo.house?.floorNo + ' 层' : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">建筑面积:</div>
|
<div class="label">建筑面积:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.houseArea ? `${HouseInfo.house?.houseArea} ㎡` : '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.houseArea ? `${HouseInfo.house?.houseArea} ㎡` : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">套内面积:</div>
|
<div class="label">套内面积:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.internalArea ? `${HouseInfo.house?.internalArea} ㎡` : '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.internalArea ? `${HouseInfo.house?.internalArea} ㎡` : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">公摊面积:</div>
|
<div class="label">公摊面积:</div>
|
||||||
<div class="value">{{ HouseInfo.house?.shareArea ? `${HouseInfo.house?.shareArea} ㎡` : '--' }}</div>
|
<div class="value">{{ HouseInfo.house?.shareArea ? `${HouseInfo.house?.shareArea} ㎡` : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">户型:</div>
|
<div class="label">户型:</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
{{ HouseInfo.house?.houseType ? HouseInfo.house?.houseType.split('')[0] : '--' }}室
|
{{ HouseInfo.house?.houseType ? HouseInfo.house?.houseType.split('')[0] : '--' }}室
|
||||||
@@ -60,31 +60,31 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="HouseInfo.storeroom" class="">
|
<div v-if="HouseInfo.storeroom" class="">
|
||||||
<div class="addBuildingFormBody">
|
<div class="addBuildingFormBody">
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">楼栋:</div>
|
<div class="label">楼栋:</div>
|
||||||
<div class="value">{{ HouseInfo.storeroom?.buildingName ?? '--' }}</div>
|
<div class="value">{{ HouseInfo.storeroom?.buildingName ?? '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">单元:</div>
|
<div class="label">单元:</div>
|
||||||
<div class="value">{{ HouseInfo.storeroom?.unitNoName ? `${HouseInfo.storeroom?.unitNoName} 单元` : '--' }}</div>
|
<div class="value">{{ HouseInfo.storeroom?.unitNoName ? `${HouseInfo.storeroom?.unitNoName} 单元` : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">储藏室号:</div>
|
<div class="label">储藏室号:</div>
|
||||||
<div class="value">{{ HouseInfo.storeroom?.storeroomNo ? `${HouseInfo.storeroom?.storeroomNo}` : '--' }}</div>
|
<div class="value">{{ HouseInfo.storeroom?.storeroomNo ? `${HouseInfo.storeroom?.storeroomNo}` : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">建筑面积:</div>
|
<div class="label">建筑面积:</div>
|
||||||
<div class="value">{{ HouseInfo.storeroom?.houseArea ? HouseInfo.storeroom?.houseArea + ' ㎡' : '--' }}</div>
|
<div class="value">{{ HouseInfo.storeroom?.houseArea ? HouseInfo.storeroom?.houseArea + ' ㎡' : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">公摊面积:</div>
|
<div class="label">公摊面积:</div>
|
||||||
<div class="value">{{ HouseInfo.storeroom?.shareArea ? HouseInfo.storeroom?.shareArea + ' ㎡' : '--' }}</div>
|
<div class="value">{{ HouseInfo.storeroom?.shareArea ? HouseInfo.storeroom?.shareArea + ' ㎡' : '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox">
|
<div class="descriptionsBox">
|
||||||
<div class="label">实用面积:</div>
|
<div class="label">实用面积:</div>
|
||||||
<div class="value">{{ HouseInfo.storeroom?.internalArea ? HouseInfo.storeroom?.internalArea + ' ㎡' : '--' }}㎡</div>
|
<div class="value">{{ HouseInfo.storeroom?.internalArea ? HouseInfo.storeroom?.internalArea + ' ㎡' : '--' }}㎡</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptionsbox" style="grid-column-start: 1; grid-column-end: 4">
|
<div class="descriptionsBox" style="grid-column-start: 1; grid-column-end: 4">
|
||||||
<div class="label">备注:</div>
|
<div class="label">备注:</div>
|
||||||
<div class="value">{{ HouseInfo.storeroom?.remark ?? '--' }}</div>
|
<div class="value">{{ HouseInfo.storeroom?.remark ?? '--' }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,12 +141,12 @@
|
|||||||
<el-table-column label="收费项目" prop="itemName" />
|
<el-table-column label="收费项目" prop="itemName" />
|
||||||
<el-table-column label="收费标准" prop="name">
|
<el-table-column label="收费标准" prop="name">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="flex">
|
<div v-if="scope.row.fixedPrice" class="flex">
|
||||||
<span>{{ scope.row.fixedPrice }}</span>
|
<span>{{ scope.row.fixedPrice }}</span>
|
||||||
<span v-if="scope.row.fixedPrice && scope.row.unit">/</span>
|
<span v-if="scope.row.unit">/</span>
|
||||||
<span v-else>---</span>
|
<dict-tag v-if="scope.row.unit" :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
||||||
<dict-tag :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span v-else> --- </span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="开始时间" prop="createTime" />
|
<el-table-column label="开始时间" prop="createTime" />
|
||||||
@@ -178,7 +178,7 @@
|
|||||||
<DictTag :options="com_resident_relationship" :value="scope.row.ownerRelationship"></DictTag>
|
<DictTag :options="com_resident_relationship" :value="scope.row.ownerRelationship"></DictTag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="备注" prop="name" />
|
<el-table-column label="备注" prop="remark" show-overflow-tooltip />
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -188,19 +188,16 @@
|
|||||||
<span>缴费账单</span>
|
<span>缴费账单</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-table :data="HouseInfo.billResidentList" style="width: 100%">
|
<el-table :data="billList" style="width: 100%">
|
||||||
<el-table-column label="账单编号" prop="billCode" />
|
<el-table-column label="账单名称" prop="detailsName" />
|
||||||
<el-table-column label="账单名称" prop="billName" />
|
<el-table-column label="账单项目" prop="chargeItemName" />
|
||||||
<el-table-column label="账单项目" prop="chargeTypeName" />
|
|
||||||
<el-table-column label="金额" prop="money">
|
<el-table-column label="金额" prop="money">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.chargeTypeName === '水费' || scope.row.chargeTypeName === '电费'">--</span>
|
<span>{{ scope.row.amount }}</span>
|
||||||
<span v-else>{{ scope.row.money }}</span>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="支付状态" prop="payStatus">
|
<el-table-column label="支付状态" prop="payStatus">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.chargeTypeName === '水费' || scope.row.chargeTypeName === '电费'">--</span>
|
|
||||||
<DictTag :options="com_pay_status" :value="scope.row.payStatus ?? 0"></DictTag>
|
<DictTag :options="com_pay_status" :value="scope.row.payStatus ?? 0"></DictTag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -214,7 +211,8 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import DictTag from '@/components/DictTag/index.vue';
|
import DictTag from '@/components/DictTag/index.vue';
|
||||||
import PageHeader from '@/components/Pageheader/index.vue';
|
import PageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { Data, getHouseMain } from '@/api/system/house';
|
import { Data, getHouseMain, House } from '@/api/system/house';
|
||||||
|
import { billlistType, billQuery } from '@/api/system/SdbCashier';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { com_resident_relationship } = toRefs<any>(proxy?.useDict('com_resident_relationship'));
|
const { com_resident_relationship } = toRefs<any>(proxy?.useDict('com_resident_relationship'));
|
||||||
@@ -226,7 +224,7 @@ const { com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_charge_item_uni
|
|||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const routeid = ref('');
|
let routeId = '';
|
||||||
const HouseInfo = ref<Data>({
|
const HouseInfo = ref<Data>({
|
||||||
billResidentList: [],
|
billResidentList: [],
|
||||||
chargeItemList: [],
|
chargeItemList: [],
|
||||||
@@ -263,13 +261,35 @@ function handleEditUser(id: string) {
|
|||||||
}
|
}
|
||||||
function init() {
|
function init() {
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
routeid.value = route.query.id as string;
|
routeId = route.query.id as string;
|
||||||
getHouseMain(routeid.value).then((res) => {
|
getHouseMain(routeId).then((res) => {
|
||||||
HouseInfo.value = res.data;
|
HouseInfo.value = res.data;
|
||||||
|
getBillByHouse(res.data.house);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
|
const billList = ref<billlistType[]>([]);
|
||||||
|
const queryParams = ref({
|
||||||
|
pageSize: 10,
|
||||||
|
pageNum: 1
|
||||||
|
});
|
||||||
|
const total = ref(0);
|
||||||
|
function getBillByHouse(info: House) {
|
||||||
|
const obj = {
|
||||||
|
buildingId: info.buildingId,
|
||||||
|
houseId: info.houseId,
|
||||||
|
pageNum: queryParams.value.pageNum,
|
||||||
|
pageSize: queryParams.value.pageSize,
|
||||||
|
unitNoId: info.unitNoId,
|
||||||
|
payStatus: null,
|
||||||
|
villageId: info.villageId
|
||||||
|
};
|
||||||
|
billQuery(obj).then((res) => {
|
||||||
|
billList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -300,10 +320,10 @@ init();
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
grid-template-rows: repeat(3, 1fr);
|
grid-template-rows: repeat(3, 1fr);
|
||||||
&.remarkbuildingformbody {
|
&.remarkBuildingFormBody {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.descriptionsbox {
|
.descriptionsBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
|
|||||||
@@ -47,9 +47,9 @@
|
|||||||
></el-switch>
|
></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" label="添加人" prop="createByName" width="120" />
|
<el-table-column align="center" label="添加人" prop="createByName" width="150" />
|
||||||
<el-table-column align="center" label="添加时间" prop="createTime" width="120" />
|
<el-table-column align="center" label="添加时间" prop="createTime" width="180" />
|
||||||
<el-table-column align="center" class-name="small-padding fixed-width" fixed="right" label="操作" width="300">
|
<el-table-column align="center" class-name="small-padding fixed-width" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button v-has-permi="['inspection:item:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
<el-button v-has-permi="['inspection:item:edit']" link type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
<el-button v-has-permi="['inspection:item:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
<el-button v-has-permi="['inspection:item:remove']" link type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
@@ -63,14 +63,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" name="Item" setup>
|
<script lang="ts" name="Item" setup>
|
||||||
import { listItem, delItem, addItem, updateItem, updateItemStatus } from '@/api/system/InspectionItem/index';
|
import { listItem, delItem, updateItemStatus } from '@/api/system/InspectionItem';
|
||||||
import { ItemVO, ItemQuery, ItemForm } from '@/api/system/InspectionItem/type';
|
import { ItemVO, ItemQuery, ItemForm } from '@/api/system/InspectionItem/type';
|
||||||
import { checkPermi } from '@/utils/permission';
|
import { checkPermi } from '@/utils/permission';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
const itemList = ref<ItemVO[]>([]);
|
const itemList = ref<ItemVO[]>([]);
|
||||||
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>>([]);
|
||||||
@@ -79,12 +78,6 @@ const multiple = ref(true);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const itemFormRef = ref<ElFormInstance>();
|
|
||||||
|
|
||||||
const dialog = reactive<DialogOption>({
|
|
||||||
visible: false,
|
|
||||||
title: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const initFormData: ItemForm = {
|
const initFormData: ItemForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@@ -123,7 +116,7 @@ const data = reactive<PageData<ItemForm, ItemQuery>>({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams } = toRefs(data);
|
||||||
|
|
||||||
/** 查询巡检项目列表 */
|
/** 查询巡检项目列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
@@ -138,18 +131,6 @@ const getList = async () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 取消按钮 */
|
|
||||||
const cancel = () => {
|
|
||||||
reset();
|
|
||||||
dialog.visible = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 表单重置 */
|
|
||||||
const reset = () => {
|
|
||||||
form.value = { ...initFormData };
|
|
||||||
itemFormRef.value?.resetFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
@@ -179,7 +160,7 @@ const handleAdd = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
const handleUpdate = async (row?: ItemVO) => {
|
const handleUpdate = (row?: ItemVO) => {
|
||||||
const _ids = row?.id || ids.value[0];
|
const _ids = row?.id || ids.value[0];
|
||||||
router.push({
|
router.push({
|
||||||
path: '/inspection/editItem',
|
path: '/inspection/editItem',
|
||||||
@@ -204,23 +185,6 @@ const handleChange = (value: string, id: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 提交按钮 */
|
|
||||||
const submitForm = () => {
|
|
||||||
itemFormRef.value?.validate(async (valid: boolean) => {
|
|
||||||
if (valid) {
|
|
||||||
buttonLoading.value = true;
|
|
||||||
if (form.value.id) {
|
|
||||||
await updateItem(form.value).finally(() => (buttonLoading.value = false));
|
|
||||||
} else {
|
|
||||||
await addItem(form.value).finally(() => (buttonLoading.value = false));
|
|
||||||
}
|
|
||||||
proxy?.$modal.msgSuccess('操作成功');
|
|
||||||
dialog.visible = false;
|
|
||||||
await getList();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
const handleDelete = async (row?: ItemVO) => {
|
const handleDelete = async (row?: ItemVO) => {
|
||||||
const _ids = row?.id || ids.value;
|
const _ids = row?.id || ids.value;
|
||||||
@@ -230,17 +194,6 @@ const handleDelete = async (row?: ItemVO) => {
|
|||||||
await getList();
|
await getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 导出按钮操作 */
|
|
||||||
const handleExport = () => {
|
|
||||||
proxy?.download(
|
|
||||||
'system/item/export',
|
|
||||||
{
|
|
||||||
...queryParams.value
|
|
||||||
},
|
|
||||||
`item_${new Date().getTime()}.xlsx`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ const data = reactive<PageData<NoticeForm, NoticeQuery>>({
|
|||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
/** 查询公告列表╬╬╬╬╬ */
|
/** 查询公告列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
listNotice(queryParams.value)
|
listNotice(queryParams.value)
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ const rules = ref({
|
|||||||
//不能输入0
|
//不能输入0
|
||||||
return callback(new Error('请输入不等于0的数字'));
|
return callback(new Error('请输入不等于0的数字'));
|
||||||
}
|
}
|
||||||
|
if (val % 1 !== 0) {
|
||||||
|
return callback(new Error('请输入整数'));
|
||||||
|
}
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,12 +230,13 @@ if (route.query.id) {
|
|||||||
}
|
}
|
||||||
// ! 获取区域==================================================================================
|
// ! 获取区域==================================================================================
|
||||||
const areaList = ref([]);
|
const areaList = ref([]);
|
||||||
const getAreaList = async () => {
|
const getAreaList = () => {
|
||||||
const res = await listArea({
|
listArea({
|
||||||
pageSize: 99999,
|
pageSize: 99999,
|
||||||
pageNum: 1
|
pageNum: 1
|
||||||
|
}).then((res) => {
|
||||||
|
areaList.value = res.rows;
|
||||||
});
|
});
|
||||||
areaList.value = res.rows;
|
|
||||||
};
|
};
|
||||||
getAreaList();
|
getAreaList();
|
||||||
|
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ getInfo();
|
|||||||
.label {
|
.label {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
|
min-width: 120px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ const handleExport = () => {
|
|||||||
{ label: '截至应收账期', prop: 'cutoffPeriod' },
|
{ label: '截至应收账期', prop: 'cutoffPeriod' },
|
||||||
{ label: '小区项目', prop: 'villageName' },
|
{ label: '小区项目', prop: 'villageName' },
|
||||||
{ label: '楼栋', prop: 'buildingName' },
|
{ label: '楼栋', prop: 'buildingName' },
|
||||||
{ label: '客户名称', prop: 'buildingName' },
|
{ label: '客户名称', prop: 'customerName' },
|
||||||
{ label: '房号编号', prop: 'roomNo' },
|
{ label: '房号编号', prop: 'roomNo' },
|
||||||
{ label: '欠费月数', prop: 'arrearsMonthsLabel' },
|
{ label: '欠费月数', prop: 'arrearsMonthsLabel' },
|
||||||
{ label: '≤6个月', prop: 'amountLe6' },
|
{ label: '≤6个月', prop: 'amountLe6' },
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-table v-loading="loading" :data="AgingList" border>
|
<el-table v-loading="loading" :data="AgingList" border>
|
||||||
<el-table-column v-if="activeName === 'first'" align="center" label="小区名称" prop="villageName" />
|
<el-table-column v-if="activeName === 'first'" align="center" label="项目" prop="villageName" />
|
||||||
<el-table-column v-else align="center" label="收费项目" prop="chargeItemName" />
|
<el-table-column v-else align="center" label="收费项目" prop="chargeItemName" />
|
||||||
<el-table-column v-for="(item, index) in rows" :key="index" :label="item.payTypeName" align="center">
|
<el-table-column v-for="(item, index) in rows" :key="index" :label="item.payTypeName" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
|||||||
@@ -225,7 +225,8 @@ const handleExport = () => {
|
|||||||
children: [
|
children: [
|
||||||
...dynamicColumns.value.map((item) => {
|
...dynamicColumns.value.map((item) => {
|
||||||
return { label: item, prop: `chargeItemAmounts.${item}` };
|
return { label: item, prop: `chargeItemAmounts.${item}` };
|
||||||
})
|
}),
|
||||||
|
{ label: '金额合计', prop: 'totalAmount' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -13,26 +13,26 @@
|
|||||||
<table border>
|
<table border>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width: 60px">序号</td>
|
<td style="width: 85px">序号</td>
|
||||||
<td>物资名称</td>
|
<td style="min-width: 75px">物资名称</td>
|
||||||
<td>品牌</td>
|
<td style="width: 75px">品牌</td>
|
||||||
<td>规格型号</td>
|
<td style="width: 85px">规格型号</td>
|
||||||
<td style="width: 80px">单位</td>
|
<td style="width: 65px">单位</td>
|
||||||
<td>供应商</td>
|
<td style="min-width: 100px">供应商</td>
|
||||||
<td style="width: 100px">数量</td>
|
<td style="width: 65px">数量</td>
|
||||||
<td style="width: 150px">单价</td>
|
<td style="width: 65px">单价</td>
|
||||||
<td>合计</td>
|
<td style="width: 65px">合计</td>
|
||||||
<td>备注</td>
|
<td style="min-width: 200px; line-height: normal">备注</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-for="(item, index) in form.items" :key="index">
|
<tr v-for="(item, index) in form.items" :key="index">
|
||||||
<td style="width: 60px">{{ index + 1 }}</td>
|
<td>{{ index + 1 }}</td>
|
||||||
<td>{{ item.materialName }}</td>
|
<td>{{ item.materialName }}</td>
|
||||||
<td>{{ item.brand }}</td>
|
<td>{{ item.brand }}</td>
|
||||||
<td>{{ item.model }}</td>
|
<td>{{ item.model }}</td>
|
||||||
<td style="width: 80px">{{ item.unit }}</td>
|
<td>{{ item.unit }}</td>
|
||||||
<td>{{ form.supplierName }}</td>
|
<td>{{ form.supplierName }}</td>
|
||||||
<td style="width: 100px">{{ item.outNum }}</td>
|
<td>{{ item.outNum }}</td>
|
||||||
<td style="width: 150px">{{ item.outPrice }}</td>
|
<td>{{ item.outPrice }}</td>
|
||||||
<td>{{ item.totalPrice }}</td>
|
<td>{{ item.totalPrice }}</td>
|
||||||
<td>{{ item.remark }}</td>
|
<td>{{ item.remark }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -122,6 +122,7 @@ const cancelForm = () => {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.formBody {
|
.formBody {
|
||||||
|
font-size: 15px;
|
||||||
.navtitle {
|
.navtitle {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 41px;
|
height: 41px;
|
||||||
@@ -146,15 +147,15 @@ const cancelForm = () => {
|
|||||||
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);
|
||||||
font-size: 1rem;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 450;
|
font-weight: 450;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.footertr td {
|
&.footertr td {
|
||||||
height: 90px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,8 +163,13 @@ const cancelForm = () => {
|
|||||||
.foorter {
|
.foorter {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
width: 100%;
|
||||||
gap: 30px;
|
gap: 30px;
|
||||||
margin: 30px auto 0;
|
margin: 20px auto 0;
|
||||||
|
}
|
||||||
|
.formark {
|
||||||
|
font-size: smaller;
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,12 +23,28 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="供应商" prop="supplierId">
|
<el-form-item label="供应商" prop="supplierId">
|
||||||
<el-select v-model="form.supplierId" placeholder="请选择供应商">
|
<el-select v-model="form.supplierId" placeholder="请选择供应商">
|
||||||
<el-option v-for="(item, index) in supplierlist" :key="index" :label="item.supplierName" :value="item.id" />
|
<el-option v-for="(item, index) in supplierlist" :key="index" :label="item.supplierName" :value="item.id">
|
||||||
|
<span style="float: left">{{ item.supplierName }}</span>
|
||||||
|
<span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">
|
||||||
|
{{ item.villageName }}
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="出库仓库" prop="warehouseId">
|
<el-form-item label="出库仓库" prop="warehouseId">
|
||||||
<el-select v-model="form.warehouseId" placeholder="请选择出库仓库">
|
<el-select v-model="form.warehouseId" placeholder="请选择出库仓库">
|
||||||
<el-option v-for="(item, index) in warehouselist" :key="index" :label="item.warehouseName" :value="item.id" />
|
<el-option
|
||||||
|
v-for="(item, index) in warehouselist"
|
||||||
|
:key="index"
|
||||||
|
:disabled="item.status === '1'"
|
||||||
|
:label="item.warehouseName"
|
||||||
|
:value="item.id"
|
||||||
|
>
|
||||||
|
<span style="float: left">{{ item.warehouseName }}</span>
|
||||||
|
<span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">
|
||||||
|
{{ item.villageName }}
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="出库状态" prop="operateStatus">-->
|
<!-- <el-form-item label="出库状态" prop="operateStatus">-->
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<el-input v-model.trim="form.unit" maxlength="20" placeholder="请输入计量单位" />
|
<el-input v-model.trim="form.unit" maxlength="20" placeholder="请输入计量单位" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input v-model.trim="form.remark" :rows="5" maxlength="200" placeholder="请输入备注" show-word-limit type="textarea" />
|
<el-input v-model.trim="form.remark" :rows="5" maxlength="30" 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>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="h-full flex flex-col p-2">
|
<div class="h-full flex flex-col p-2">
|
||||||
<pageHeader></pageHeader>
|
<pageHeader></pageHeader>
|
||||||
<div class="mainbody">
|
<div class="mainbody">
|
||||||
<div class="actionsbox">
|
<div class="actionsBox">
|
||||||
<el-button icon="Printer" type="primary" @click="handlePrint">打印</el-button>
|
<el-button icon="Printer" type="primary" @click="handlePrint">打印</el-button>
|
||||||
<el-button @click="cancelForm">返回</el-button>
|
<el-button @click="cancelForm">返回</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -13,16 +13,16 @@
|
|||||||
<table border>
|
<table border>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width: 90px">序号</td>
|
<td style="width: 85px">序号</td>
|
||||||
<td>物资名称</td>
|
<td style="min-width: 75px">物资名称</td>
|
||||||
<td>品牌</td>
|
<td style="width: 75px">品牌</td>
|
||||||
<td>规格型号</td>
|
<td style="width: 85px">规格型号</td>
|
||||||
<td style="width: 80px">单位</td>
|
<td style="width: 65px">单位</td>
|
||||||
<td>供应商</td>
|
<td style="min-width: 100px">供应商</td>
|
||||||
<td style="width: 80px">数量</td>
|
<td style="width: 65px">数量</td>
|
||||||
<td style="width: 80px">单价</td>
|
<td style="width: 65px">单价</td>
|
||||||
<td>合计</td>
|
<td style="width: 65px">合计</td>
|
||||||
<td>备注</td>
|
<td style="min-width: 200px; line-height: normal">备注</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-for="(item, index) in form.items" :key="index">
|
<tr v-for="(item, index) in form.items" :key="index">
|
||||||
<td>{{ index + 1 }}</td>
|
<td>{{ index + 1 }}</td>
|
||||||
@@ -30,7 +30,9 @@
|
|||||||
<td>{{ item.brand }}</td>
|
<td>{{ item.brand }}</td>
|
||||||
<td>{{ item.model }}</td>
|
<td>{{ item.model }}</td>
|
||||||
<td>{{ item.unit }}</td>
|
<td>{{ item.unit }}</td>
|
||||||
<td>{{ form.supplierName }}</td>
|
<td>
|
||||||
|
{{ form.supplierName }}
|
||||||
|
</td>
|
||||||
<td>{{ item.inNum }}</td>
|
<td>{{ item.inNum }}</td>
|
||||||
<td>{{ item.costPrice }}</td>
|
<td>{{ item.costPrice }}</td>
|
||||||
<td>{{ item.totalPrice }}</td>
|
<td>{{ item.totalPrice }}</td>
|
||||||
@@ -117,11 +119,12 @@ const cancelForm = () => {
|
|||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
.actionsbox {
|
.actionsBox {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.formBody {
|
.formBody {
|
||||||
|
font-size: 15px;
|
||||||
.navtitle {
|
.navtitle {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 41px;
|
height: 41px;
|
||||||
@@ -146,15 +149,15 @@ const cancelForm = () => {
|
|||||||
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);
|
||||||
font-size: 1rem;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 450;
|
font-weight: 450;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.footertr td {
|
&.footertr td {
|
||||||
height: 90px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,7 +167,7 @@ const cancelForm = () => {
|
|||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
gap: 30px;
|
gap: 30px;
|
||||||
margin: 30px auto 0;
|
margin: 20px auto 0;
|
||||||
}
|
}
|
||||||
.formark {
|
.formark {
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
|
|||||||
@@ -23,7 +23,12 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="供应商" prop="supplierId">
|
<el-form-item label="供应商" prop="supplierId">
|
||||||
<el-select v-model="form.supplierId" placeholder="请选择供应商">
|
<el-select v-model="form.supplierId" placeholder="请选择供应商">
|
||||||
<el-option v-for="(item, index) in supplierlist" :key="index" :label="item.supplierName" :value="item.id" />
|
<el-option v-for="(item, index) in supplierlist" :key="index" :label="item.supplierName" :value="item.id">
|
||||||
|
<span style="float: left">{{ item.supplierName }}</span>
|
||||||
|
<span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">
|
||||||
|
{{ item.villageName }}
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="入库仓库" prop="warehouseId">
|
<el-form-item label="入库仓库" prop="warehouseId">
|
||||||
@@ -34,7 +39,12 @@
|
|||||||
:disabled="item.status === '1'"
|
:disabled="item.status === '1'"
|
||||||
:label="item.warehouseName"
|
:label="item.warehouseName"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
/>
|
>
|
||||||
|
<span style="float: left">{{ item.warehouseName }}</span>
|
||||||
|
<span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">
|
||||||
|
{{ item.villageName }}
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="入库状态" prop="operateStatus">-->
|
<!-- <el-form-item label="入库状态" prop="operateStatus">-->
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
<div class="flex flex-items-center justify-center">
|
<div class="flex flex-items-center justify-center">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="time"
|
v-model="time"
|
||||||
type="daterange"
|
|
||||||
range-separator="至"
|
|
||||||
format="YYYY-MM-DD"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
@update:model-value="handleChangeDate"
|
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
type="daterange"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
@update:model-value="handleChangeDate"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -174,7 +174,7 @@ function updateOptions(value: string) {
|
|||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, #ffffff 70%);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 19px 23px;
|
padding: 19px 23px;
|
||||||
box-shadow: 0px 2px 6px 0px rgba(26, 117, 255, 0.15);
|
box-shadow: 0 2px 6px 0 rgba(26, 117, 255, 0.15);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
.echartsBody {
|
.echartsBody {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
|
|||||||
@@ -109,7 +109,19 @@ function handleRoutesToShowList(routes: any[]) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
quicklyList.value = routes.map((ele) => _handle(null, ele, 1)).filter((item) => item);
|
quicklyList.value = routes.map((ele) => _handle(null, ele, 1)).filter((item) => item);
|
||||||
|
console.log(quicklyList.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 隐藏快捷入口路径
|
||||||
|
const hiddenPaths = [
|
||||||
|
'/house/houseDetails', // 房屋详情
|
||||||
|
'/equipment/electricityTopupRecord', // 电表充值记录
|
||||||
|
'/equipment/waterTopupRecord', // 水表充值记录
|
||||||
|
|
||||||
|
'/system/role-auth/user/:roleId', // 分配用户
|
||||||
|
'/system/user-auth/role/:userId' // 分配角色
|
||||||
|
];
|
||||||
|
|
||||||
function _handle(
|
function _handle(
|
||||||
parentRoute: { name?: any; icon?: any; path: any; level?: any; children?: any[] },
|
parentRoute: { name?: any; icon?: any; path: any; level?: any; children?: any[] },
|
||||||
currentRoute: { hidden: any; path: string; meta: { title: any; icon: any }; children: any[] },
|
currentRoute: { hidden: any; path: string; meta: { title: any; icon: any }; children: any[] },
|
||||||
@@ -125,6 +137,11 @@ function _handle(
|
|||||||
if (excludeKeywords.test(currentRoute.path)) {
|
if (excludeKeywords.test(currentRoute.path)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
console.log(parentRoute);
|
||||||
|
console.log(parentRoute ? parentRoute.path : '', currentRoute.path);
|
||||||
|
if (hiddenPaths.includes(`${parentRoute ? parentRoute.path : ''}/${currentRoute.path}`)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!currentRoute.meta) {
|
if (!currentRoute.meta) {
|
||||||
if (currentRoute.children && currentRoute.children.length > 0) {
|
if (currentRoute.children && currentRoute.children.length > 0) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user