新增标准节租金等功能

This commit is contained in:
gxwebsoft
2024-02-05 15:54:26 +08:00
parent 494e3ee248
commit aac8dc687d
16 changed files with 2467 additions and 1582 deletions

View File

@@ -6,9 +6,7 @@ import type { Project, ProjectParam } from '@/api/tower/project/model';
* 项目数据
*/
export async function towerProjectData() {
const res = await request.get(
'/tower/tower-project/data'
);
const res = await request.get('/tower/tower-project/data');
if (res.data.code === 0) {
return res.data.data;
}

View File

@@ -56,6 +56,7 @@ export interface Project {
export interface ProjectParam extends PageParam {
projectId?: number;
projectName?: string;
projectStatus?: any;
status?: number;
keywords?: string;
}

107
src/api/tower/rent/index.ts Normal file
View File

@@ -0,0 +1,107 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { TowerRent, TowerRentParam } from './model';
// const merchantCode = String(localStorage.getItem('merchantCode'));
/**
* 分页查询标准节租金
*/
export async function pageTowerRent(params: TowerRentParam) {
const res = await request.get<ApiResult<PageResult<TowerRent>>>(
'/tower/tower-rent/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询标准节租金列表
*/
export async function listTowerRent(params?: TowerRentParam) {
const res = await request.get<ApiResult<TowerRent[]>>('/tower/tower-rent', {
params
});
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加标准节租金
*/
export async function addTowerRent(data: TowerRent) {
const res = await request.post<ApiResult<unknown>>(
'/tower/tower-rent',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改标准节租金
*/
export async function updateTowerRent(data: TowerRent) {
const res = await request.put<ApiResult<unknown>>('/tower/tower-rent', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除标准节租金
*/
export async function removeTowerRent(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
'/tower/tower-rent/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除标准节租金
*/
export async function removeBatchTowerRent(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
'/tower/tower-rent/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 检查IP是否存在
*/
export async function checkExistence(
field: string,
value: string,
id?: number
) {
const res = await request.get<ApiResult<unknown>>(
'/tower/tower-rent/existence',
{
params: { field, value, id }
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}

View File

@@ -0,0 +1,57 @@
import type { PageParam } from '@/api';
/**
* 标准节租金
*/
export interface TowerRent {
rentId?: number;
name?: string;
rent?: number;
month?: number;
num?: number;
totalRent?: string;
companyId?: number;
companyName?: string;
// 型号分类图片
image?: string;
// 使用年限
yearLife?: number;
// 上级分类
parentId?: number;
// 是否隐藏
hide?: number;
// 封面图
avatar?: string;
// 用户ID
userId?: string;
// 所属门店ID
shopId?: string;
// 排序
sortNumber?: number;
// 备注
comments?: string;
// 状态
status?: number;
// 创建时间
createTime?: string;
// 更新时间
updateTime?: string;
//
key?: number;
//
merchantCode?: string;
value?: number;
index?: number;
}
/**
* 搜索条件
*/
export interface TowerRentParam extends PageParam {
rentId?: number;
title?: string;
categoryId?: string;
yearLife?: number;
// 商户编号
merchantCode?: string;
}

View File

@@ -113,7 +113,7 @@
import type { EleProTable } from 'ele-admin-pro/es';
import CategoryEdit from './components/category-edit.vue';
import type { Category, CategoryParam } from '@/api/goods/category/model';
import { listCategory } from '@/api/goods/category';
import { listCategory, removeCategory } from "@/api/goods/category";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);

View File

@@ -221,11 +221,12 @@
/* 删除单个 */
const remove = (row: Category) => {
console.log(row);
if (row.children?.length) {
message.error('请先删除子节点');
return;
}
const hide = messageLoading('请求中..', 0);
const hide = messageLoading('请求中..' + row.categoryId, 0);
removeCategory(row.categoryId)
.then((msg) => {
hide();

View File

@@ -1,237 +1,245 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加设备</span>
</a-button>
<a-button
danger
type="primary"
class="ele-btn-icon"
:disabled="selection.length === 0"
@click="removeBatch"
>
<template #icon>
<DeleteOutlined />
</template>
<span>批量删除</span>
</a-button>
<a-button class="ele-btn-icon" @click="openImport">
<template #icon>
<UploadOutlined />
</template>
<span>导入设备</span>
</a-button>
<a-button class="ele-btn-icon" @click="handleExport">
<template #icon>
<DownloadOutlined />
</template>
<span>导出设备</span>
</a-button>
<a-radio-group v-model:value="status" @change="handleStatus" :disabled="selection.length === 0">
<a-radio-button :value="0">闲置</a-radio-button>
<a-radio-button :value="1">报废</a-radio-button>
<a-radio-button :value="2">注销</a-radio-button>
<a-radio-button :value="3">转卖</a-radio-button>
<a-radio-button :value="4">在用</a-radio-button>
<a-radio-button :value="5">停工</a-radio-button>
</a-radio-group>
<a-select placeholder="设备状态筛选" style="width: 250px" @change="search"
@clear="search"
v-model:value="statusFilter" allow-clear>
<a-select-option :value="null">全部</a-select-option>
<a-select-option :value="0">闲置</a-select-option>
<a-select-option :value="1">报废</a-select-option>
<a-select-option :value="2">注销</a-select-option>
<a-select-option :value="3">转卖</a-select-option>
<a-select-option :value="4">在用</a-select-option>
<a-select-option :value="5">停工</a-select-option>
</a-select>
<a-input-search
allow-clear
placeholder="请输入关键词"
v-model:value="searchText"
@pressEnter="search"
@search="search"
/>
<a-input-search
:min="0"
type="number"
allow-clear
placeholder="剩余可用年份筛选"
v-model:value="yearFilter"
@pressEnter="search"
@search="search"
/>
<!-- 导入弹窗 -->
<Import v-model:visible="showImport" @done="search" />
</a-space>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加设备</span>
</a-button>
<a-button
danger
type="primary"
class="ele-btn-icon"
:disabled="selection.length === 0"
@click="removeBatch"
>
<template #icon>
<DeleteOutlined />
</template>
<span>批量删除</span>
</a-button>
<a-button class="ele-btn-icon" @click="openImport">
<template #icon>
<UploadOutlined />
</template>
<span>导入设备</span>
</a-button>
<a-button class="ele-btn-icon" @click="handleExport">
<template #icon>
<DownloadOutlined />
</template>
<span>导出设备</span>
</a-button>
<!-- <a-radio-group-->
<!-- v-model:value="status"-->
<!-- @change="handleStatus"-->
<!-- :disabled="selection.length === 0"-->
<!-- >-->
<!-- <a-radio-button :value="0">闲置</a-radio-button>-->
<!-- <a-radio-button :value="1">报废</a-radio-button>-->
<!-- <a-radio-button :value="2">注销</a-radio-button>-->
<!-- <a-radio-button :value="3">转卖</a-radio-button>-->
<!-- <a-radio-button :value="4">在用</a-radio-button>-->
<!-- <a-radio-button :value="5">停工</a-radio-button>-->
<!-- </a-radio-group>-->
<!-- <a-select-->
<!-- placeholder="设备状态筛选"-->
<!-- style="width: 250px"-->
<!-- @change="search"-->
<!-- @clear="search"-->
<!-- v-model:value="statusFilter"-->
<!-- allow-clear-->
<!-- >-->
<!-- <a-select-option :value="null">全部</a-select-option>-->
<!-- <a-select-option :value="0">闲置</a-select-option>-->
<!-- <a-select-option :value="1">报废</a-select-option>-->
<!-- <a-select-option :value="2">注销</a-select-option>-->
<!-- <a-select-option :value="3">转卖</a-select-option>-->
<!-- <a-select-option :value="4">在用</a-select-option>-->
<!-- <a-select-option :value="5">停工</a-select-option>-->
<!-- </a-select>-->
<a-input-search
allow-clear
placeholder="请输入关键词"
v-model:value="searchText"
@pressEnter="search"
@search="search"
/>
<a-input-search
:min="0"
type="number"
allow-clear
placeholder="剩余可用年份筛选"
v-model:value="yearFilter"
@pressEnter="search"
@search="search"
/>
<!-- 导入弹窗 -->
<Import v-model:visible="showImport" @done="search" />
</a-space>
</template>
<script lang="ts" setup>
import {
import {
PlusOutlined,
UploadOutlined,
DownloadOutlined,
DeleteOutlined
} from "@ant-design/icons-vue";
import useSearch from "@/utils/use-search";
import { ref, watch } from "vue";
import { utils, writeFile } from "xlsx";
import { TowerEquipment } from "@/api/tower/equipment/model";
import { TowerEquipmentParam } from "@/api/tower/equipment/model";
import Import from "./import.vue";
import { message } from "ant-design-vue";
import { ContractSettleMethod } from "@/api/tower/contract/model";
} from '@ant-design/icons-vue';
import useSearch from '@/utils/use-search';
import { ref, watch } from 'vue';
import { utils, writeFile } from 'xlsx';
import { TowerEquipment } from '@/api/tower/equipment/model';
import { TowerEquipmentParam } from '@/api/tower/equipment/model';
import Import from './import.vue';
import { message } from 'ant-design-vue';
import { ContractSettleMethod } from '@/api/tower/contract/model';
const props = withDefaults(
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
// 选中的角色
selection?: [];
}>(),
{}
);
);
const emit = defineEmits<{
(e: "search", where?: TowerEquipmentParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "update", status?: number): void;
(e: "import"): void;
}>();
const emit = defineEmits<{
(e: 'search', where?: TowerEquipmentParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'update', status?: number): void;
(e: 'import'): void;
}>();
// 表单数据
const { where, resetFields } = useSearch<TowerEquipmentParam>({
// 表单数据
const { where, resetFields } = useSearch<TowerEquipmentParam>({
equipmentId: undefined,
name: undefined,
keywords: "",
keywords: '',
status: undefined,
yearFilter: undefined,
});
// 下来选项
const type = ref("keywords");
// 搜索内容
const searchText = ref("");
const yearFilter = ref<number>();
const statusFilter = ref(undefined);
// 状态
const status = ref<number>();
// 是否显示导入弹窗
const showImport = ref(false);
yearFilter: undefined
});
// 下来选项
const type = ref('keywords');
// 搜索内容
const searchText = ref('');
const yearFilter = ref<number>();
const statusFilter = ref(undefined);
// 状态
const status = ref<number>();
// 是否显示导入弹窗
const showImport = ref(false);
/* 搜索 */
const search = () => {
/* 搜索 */
const search = () => {
resetFields();
if (type.value == "keywords") {
where.keywords = searchText.value;
if (type.value == 'keywords') {
where.keywords = searchText.value;
}
if (statusFilter.value !== undefined) {
where.status = statusFilter.value;
where.status = statusFilter.value;
}
if (yearFilter.value !== undefined) {
where.yearFilter = yearFilter.value;
where.yearFilter = yearFilter.value;
}
emit("search", {
...where
emit('search', {
...where
});
};
};
// 导出
const handleExport = () => {
// 导出
const handleExport = () => {
if (!props.selection?.length) {
message.error("请至少选择一条数据");
return;
message.error('请至少选择一条数据');
return;
}
const array: (string | number)[][] = [
[
"设备状态",
"设备名称",
"出厂编号",
"设备型号",
"制造厂商",
"采购日期",
"备案编号",
"出厂日期",
"产权单位",
"设备来源",
"所属仓库",
"所属人员",
"自编号",
"额定载重",
"最大起升高度(m)",
"臂长",
"当前位置",
"楼号"
]
[
'设备状态',
'设备名称',
'出厂编号',
'设备型号',
'制造厂商',
'采购日期',
'备案编号',
'出厂日期',
'产权单位',
'设备来源',
'所属仓库',
'所属人员',
'自编号',
'额定载重',
'最大起升高度(m)',
'臂长',
'当前位置',
'楼号'
]
];
props.selection?.forEach((d: TowerEquipment) => {
array.push([
`${["闲置", "报废", "注销", "转卖", "在用", "停工"][Number(d.status)]}`,
`${d.name}`,
`${d.factoryNo}`,
`${d.model}`,
`${d.manufactor}`,
`${d.buyDate ? d.buyDate : ""}`,
`${d.filingNo}`,
`${d.factoryDate ? d.factoryDate : ""}`,
`${d.company}`,
`${d.source}`,
`${d.warehouse}`,
`${d.users}`,
`${d.equipmentNo}`,
`${d.ratedLoad}`,
`${d.maxLiftingHeight}`,
`${d.armLength}`,
`${d.currentLocation}`,
`${d.machineNo}`
]);
array.push([
`${['闲置', '报废', '注销', '转卖', '在用', '停工'][Number(d.status)]}`,
`${d.name}`,
`${d.factoryNo}`,
`${d.model}`,
`${d.manufactor}`,
`${d.buyDate ? d.buyDate : ''}`,
`${d.filingNo}`,
`${d.factoryDate ? d.factoryDate : ''}`,
`${d.company}`,
`${d.source}`,
`${d.warehouse}`,
`${d.users}`,
`${d.equipmentNo}`,
`${d.ratedLoad}`,
`${d.maxLiftingHeight}`,
`${d.armLength}`,
`${d.currentLocation}`,
`${d.machineNo}`
]);
});
const sheetName = "设备导出列表";
const sheetName = '设备导出列表';
const workbook = {
SheetNames: [sheetName],
Sheets: {}
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet["!cols"] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
sheet['!cols'] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
];
writeFile(workbook, "导出设备管理表.xlsx");
};
writeFile(workbook, '导出设备管理表.xlsx');
};
// 发布设备
const add = () => {
emit("add");
};
// 发布设备
const add = () => {
emit('add');
};
// 导入
const openImport = () => {
// 导入
const openImport = () => {
showImport.value = true;
};
};
const handleStatus = () => {
emit("update", status.value);
};
const handleStatus = () => {
emit('update', status.value);
};
// 批量删除
const removeBatch = () => {
emit("remove");
};
// 批量删除
const removeBatch = () => {
emit('remove');
};
watch(
watch(
() => props.selection,
() => {
}
);
() => {}
);
</script>

View File

@@ -1,17 +1,64 @@
<template>
<div>
<a-card title="设备数据">
<a-row :gutter="10">
<a-col :span="4">
<span>设备总数:{{ equipmentData.totalNum }}</span>
</a-col>
<a-col :span="4">
<span>闲置设备总数:{{ equipmentData.idleNum }}</span>
</a-col>
<a-col :span="4">
<span>已达报废年限设备总数:{{ equipmentData.scrapNum }}</span>
</a-col>
</a-row>
<div class="count">
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab(undefined)"
:class="active == undefined ? 'active' : ''"
>
{{ `全部设备(${equipmentData.totalNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(0)" :class="active == 0 ? 'active' : ''">
{{ `闲置(${equipmentData.idleNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(1)" :class="active == 1 ? 'active' : ''">
{{ `已达报废年限(${equipmentData.scrapNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(2)" :class="active == 2 ? 'active' : ''">
{{ `已注销(${equipmentData.totalNum2})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(3)" :class="active == 3 ? 'active' : ''">
{{ `已转卖(${equipmentData.totalNum3})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(4)" :class="active == 4 ? 'active' : ''">
{{ `在用(${equipmentData.totalNum4})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(5)" :class="active == 5 ? 'active' : ''">
{{ `已停工(${equipmentData.totalNum5})` }}
</div>
</div>
</div>
<!-- <a-row :gutter="10">-->
<!-- <a-col :span="4">-->
<!-- <span>设备总数:{{ equipmentData.totalNum }}</span>-->
<!-- </a-col>-->
<!-- <a-col :span="4">-->
<!-- <span>闲置设备总数:{{ equipmentData.idleNum }}</span>-->
<!-- </a-col>-->
<!-- <a-col :span="4">-->
<!-- <span>已达报废年限设备总数:{{ equipmentData.scrapNum }}</span>-->
<!-- </a-col>-->
<!-- </a-row>-->
</a-card>
<div class="page">
<div class="ele-body">
@@ -40,17 +87,27 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'useYear'">
<span v-if="record.factoryDate">{{ dayjs().diff(dayjs(record.factoryDate), "year") }}</span>
<span v-if="record.factoryDate"
>{{ dayjs().diff(dayjs(record.factoryDate), 'year') }}</span
>
</template>
<template v-if="column.key === 'canUseYear'">
<span v-if="record.scrapDate">{{ dayjs(record.scrapDate).diff(dayjs(), "year") + 1 }}</span>
<span v-if="record.scrapDate"
>{{
dayjs(record.scrapDate).diff(dayjs(), 'year') + 1
}}</span
>
</template>
<template v-if="column.key === 'createTime'">
{{ record.createTime }}
</template>
<template v-if="column.key === 'inProject'">
<div>
<p v-for="(item, index) in record.projectList" :key="index" style="line-height: 1.5">
<p
v-for="(item, index) in record.projectList"
:key="index"
style="line-height: 1.5"
>
{{ item.projectName }}
</p>
</div>
@@ -75,274 +132,313 @@
</a-card>
</div>
<!-- 编辑弹窗 -->
<EquipmentEdit v-model:visible="showEdit" :data="current" @done="reload" />
<EquipmentEdit
v-model:visible="showEdit"
:data="current"
@done="reload"
/>
<ProjectList v-model:visible="showProject" :data="current" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, reactive, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import { toDateString } from "ele-admin-pro";
import Search from "./components/search.vue";
import EquipmentEdit from "./components/equipment-edit.vue";
import {
pageTowerEquipment,
removeBatchTowerEquipment, towerEquipmentData, towerEquipmentQr,
updateBatchTowerEquipment
} from "@/api/tower/equipment";
import {
TowerEquipment,
TowerEquipmentParam
} from "@/api/tower/equipment/model";
import { ApiResult, PageResult } from "@/api";
import dayjs from "dayjs";
import ProjectList from "@/views/tower/equipment/components/project-list.vue";
import { createVNode, reactive, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import EquipmentEdit from './components/equipment-edit.vue';
import {
pageTowerEquipment,
removeBatchTowerEquipment,
towerEquipmentData,
towerEquipmentQr,
updateBatchTowerEquipment
} from '@/api/tower/equipment';
import {
TowerEquipment,
TowerEquipmentParam
} from '@/api/tower/equipment/model';
import dayjs from 'dayjs';
import ProjectList from '@/views/tower/equipment/components/project-list.vue';
defineProps<{
activeKey?: boolean;
data?: any;
}>();
defineProps<{
activeKey?: boolean;
data?: any;
}>();
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格列配置
const columns = ref<ColumnItem[]>([
{
key: "index",
width: 48,
align: "center",
fixed: "left",
hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
},
{
title: "设备状态",
dataIndex: "status",
key: "status",
customRender: ({ text }) => ["闲置", "报废", "注销", "转卖", "在用", "停工"][text]
},
{
title: "设备名称",
dataIndex: "name",
key: "name"
},
{
title: "出厂编号",
dataIndex: "factoryNo"
},
{
title: "设备型号",
dataIndex: "model",
key: "model"
},
{
title: "备案编号",
dataIndex: "filingNo"
},
{
title: "制造厂商",
dataIndex: "manufactor",
key: "manufactor"
},
{
title: "所在项目",
key: "inProject"
},
{
title: "产权单位(个人)",
dataIndex: "company",
key: "company"
},
{
title: "购买日期",
dataIndex: "buyDate"
},
{
title: "已使用年份",
key: "useYear"
},
{
title: "剩余可使用年份",
key: "canUseYear"
},
{
title: "操作",
key: "action",
width: 200,
align: "center",
hideInSetting: true
}
]);
let equipmentData = reactive({
totalNum: 0,
idleNum: 0,
scrapNum: 0
});
const getData = async () => {
const res = await towerEquipmentData();
for (let key in equipmentData) equipmentData[key] = res[key];
};
// 表格选中数据
const selection = ref<TowerEquipment[]>([]);
// 当前编辑数据
const current = ref<TowerEquipment | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
// 搜索条件
if (filters.payMethod) {
where.payMethod = filters.payMethod;
}
if (filters.deliveryType) {
where.deliveryType = filters.deliveryType;
}
if (filters.payStatus) {
where.payStatus = filters.payStatus;
}
if (filters.orderSource) {
where.orderSource = filters.orderSource;
}
where.tenantId = localStorage.getItem("tenantId");
where.payStatus = 20;
return pageTowerEquipment({
...where,
...orders,
page,
limit
});
};
/* 搜索 */
const reload = (where?: TowerEquipmentParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
getData();
};
/* 打开编辑弹窗 */
const openEdit = (row?: TowerEquipment) => {
current.value = row ?? null;
showEdit.value = true;
};
const showQr = async (row?: TowerEquipment) => {
const res = towerEquipmentQr({ equipmentId: row?.equipmentId })
console.log(res)
};
const showProject = ref<Boolean>(false)
const showProjectList = async (row?: TowerEquipment) => {
current.value = row ?? null;
showProject.value = true;
};
/* 批量修改 */
const handleStatus = (status) => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
const data = selection.value.map((d) => {
return {
equipmentId: d.equipmentId,
status
};
});
updateBatchTowerEquipment(data).then((msg) => {
message.success(msg);
reload();
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchTowerEquipment(selection.value.map((d) => d.equipmentId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 自定义行属性 */
const customRow = (record: TowerEquipment) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
// 表格列配置
const columns = ref<ColumnItem[]>([
{
key: 'index',
width: 48,
align: 'center',
fixed: 'left',
hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
},
// 行双击事件
onDblclick: () => {
openEdit(record);
{
title: '设备状态',
dataIndex: 'status',
key: 'status',
customRender: ({ text }) =>
['闲置', '报废', '注销', '转卖', '在用', '停工'][text]
},
{
title: '设备名称',
dataIndex: 'name',
key: 'name'
},
{
title: '出厂编号',
dataIndex: 'factoryNo'
},
{
title: '设备型号',
dataIndex: 'model',
key: 'model'
},
{
title: '备案编号',
dataIndex: 'filingNo'
},
{
title: '制造厂商',
dataIndex: 'manufactor',
key: 'manufactor'
},
{
title: '所在项目',
key: 'inProject'
},
{
title: '产权单位(个人)',
dataIndex: 'company',
key: 'company'
},
{
title: '购买日期',
dataIndex: 'buyDate'
},
{
title: '已使用年份',
key: 'useYear'
},
{
title: '剩余可使用年份',
key: 'canUseYear'
},
{
title: '操作',
key: 'action',
width: 200,
align: 'center',
hideInSetting: true
}
};
};
]);
reload();
let equipmentData = reactive({
totalNum: 0,
idleNum: 0,
scrapNum: 0,
totalNum2: 0,
totalNum3: 0,
totalNum4: 0,
totalNum5: 0
});
const getData = async () => {
const res = await towerEquipmentData();
for (let key in equipmentData) equipmentData[key] = res[key];
};
// 表格选中数据
const selection = ref<TowerEquipment[]>([]);
// 当前编辑数据
const current = ref<TowerEquipment | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
const active = ref<any>(undefined);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
// 搜索条件
if (filters.payMethod) {
where.payMethod = filters.payMethod;
}
if (filters.deliveryType) {
where.deliveryType = filters.deliveryType;
}
if (filters.payStatus) {
where.payStatus = filters.payStatus;
}
if (filters.orderSource) {
where.orderSource = filters.orderSource;
}
where.tenantId = localStorage.getItem('tenantId');
where.payStatus = 20;
return pageTowerEquipment({
...where,
...orders,
page,
limit
});
};
const onTab = (type: any) => {
active.value = type;
reload({ status: active.value });
};
/* 搜索 */
const reload = (where?: TowerEquipmentParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
getData();
};
/* 打开编辑弹窗 */
const openEdit = (row?: TowerEquipment) => {
current.value = row ?? null;
showEdit.value = true;
};
const showQr = async (row?: TowerEquipment) => {
const res = towerEquipmentQr({ equipmentId: row?.equipmentId });
console.log(res);
};
const showProject = ref<Boolean>(false);
const showProjectList = async (row?: TowerEquipment) => {
current.value = row ?? null;
showProject.value = true;
};
/* 批量修改 */
const handleStatus = (status) => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
const data = selection.value.map((d) => {
return {
equipmentId: d.equipmentId,
status
};
});
updateBatchTowerEquipment(data).then((msg) => {
message.success(msg);
reload();
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchTowerEquipment(selection.value.map((d) => d.equipmentId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 自定义行属性 */
const customRow = (record: TowerEquipment) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
reload();
</script>
<script lang="ts">
export default {
name: "TowerEquipmentIndex"
};
export default {
name: 'TowerEquipmentIndex'
};
</script>
<style lang="less" scoped>
p {
line-height: 0.8;
}
p {
line-height: 0.8;
}
.sys-org-table :deep(.ant-table-body) {
overflow: auto !important;
overflow: overlay !important;
}
.sys-org-table :deep(.ant-table-body) {
overflow: auto !important;
overflow: overlay !important;
}
.sys-org-table :deep(.ant-table-pagination.ant-pagination) {
padding: 0 4px;
margin-bottom: 0;
}
.sys-org-table :deep(.ant-table-pagination.ant-pagination) {
padding: 0 4px;
margin-bottom: 0;
}
.price-edit {
padding-right: 5px;
}
.price-edit {
padding-right: 5px;
}
.comments {
max-width: 200px;
}
.comments {
max-width: 200px;
}
.count {
display: flex;
.btn {
margin: 0 12px;
padding: 6px 18px;
background-color: #f3f3f3;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
font-size: 16px;
.divider {
width: 4px;
height: 15px;
border-radius: 8px;
margin-right: 8px;
background-color: #16a90b;
}
.active {
color: #16a90b;
}
}
}
</style>

View File

@@ -1,35 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon">
<a-button class="ele-btn-icon">
<template #icon>
<QrcodeOutlined />
</template>
<span>批量生产二维码</span>
</a-button>
<a-alert type="success" style="margin-left: 105px">
<template #icon><smile-outlined /></template>
<template #message>
<a-space>
<span>设备总数4</span>
<span>在用数1</span>
<span>闲置数1</span>
<span>报废数1</span>
<span>转卖数1</span>
<span>注销数0</span>
<span>自有设备3</span>
<span>租赁设备1</span>
</a-space>
</template>
</a-alert>
<!-- <a-space>-->
<!-- <a-button @click="onTab(undefined)"-->
<!-- >设备总数:{{ equipmentData.totalNum }}</a-button-->
<!-- >-->
<!-- <a-button @click="onTab(0)">闲置{{ equipmentData.idleNum }}</a-button>-->
<!-- <a-button @click="onTab(1)"-->
<!-- >已达报废年限:{{ equipmentData.scrapNum }}</a-button-->
<!-- >-->
<!-- <a-button @click="onTab(2)"-->
<!-- >已注销:{{ equipmentData.totalNum2 }}</a-button-->
<!-- >-->
<!-- <a-button @click="onTab(3)"-->
<!-- >已转卖:{{ equipmentData.totalNum3 }}</a-button-->
<!-- >-->
<!-- <a-button @click="onTab(4)">在用{{ equipmentData.totalNum4 }}</a-button>-->
<!-- <a-button @click="onTab(5)"-->
<!-- >已停工:{{ equipmentData.totalNum5 }}</a-button-->
<!-- >-->
<!-- <span>自有设备3</span>-->
<!-- <span>租赁设备1</span>-->
<!-- </a-space>-->
</a-space>
</template>
<script lang="ts" setup>
import { QrcodeOutlined } from '@ant-design/icons-vue';
import useSearch from '@/utils/use-search';
import { ref, watch } from 'vue';
import { reactive, ref, watch } from 'vue';
import { TowerEquipmentParam } from '@/api/tower/equipment/model';
import { towerEquipmentData } from '@/api/tower/equipment';
const props = withDefaults(
defineProps<{
@@ -62,6 +69,31 @@
// 状态
const status = ref<number>();
const active = ref<any>(undefined);
let equipmentData = reactive({
totalNum: 0,
idleNum: 0,
scrapNum: 0,
totalNum2: 0,
totalNum3: 0,
totalNum4: 0,
totalNum5: 0
});
const getData = async () => {
const res = await towerEquipmentData();
for (let key in equipmentData) equipmentData[key] = res[key];
};
const onTab = (type: any) => {
active.value = type;
where.status = active.value;
emit('search', {
...where
});
};
/* 搜索 */
const search = () => {
resetFields();
@@ -88,8 +120,36 @@
emit('remove');
};
getData();
watch(
() => props.selection,
() => {}
);
</script>
<style lang="less" scoped>
.count {
display: flex;
.btn {
margin: 0 12px;
padding: 6px 18px;
background-color: #f3f3f3;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
font-size: 16px;
.divider {
width: 4px;
height: 15px;
border-radius: 8px;
margin-right: 8px;
background-color: #16a90b;
}
.active {
color: #16a90b;
}
}
}
</style>

View File

@@ -1,5 +1,54 @@
<template>
<div class="page">
<a-card title="设备数据">
<div class="count">
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab(undefined)"
:class="active == undefined ? 'active' : ''"
>
{{ `全部设备(${equipmentData.totalNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(0)" :class="active == 0 ? 'active' : ''">
{{ `闲置(${equipmentData.idleNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(1)" :class="active == 1 ? 'active' : ''">
{{ `已达报废年限(${equipmentData.scrapNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(2)" :class="active == 2 ? 'active' : ''">
{{ `已注销(${equipmentData.totalNum2})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(3)" :class="active == 3 ? 'active' : ''">
{{ `已转卖(${equipmentData.totalNum3})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(4)" :class="active == 4 ? 'active' : ''">
{{ `在用(${equipmentData.totalNum4})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div @click="onTab(5)" :class="active == 5 ? 'active' : ''">
{{ `已停工(${equipmentData.totalNum5})` }}
</div>
</div>
</div>
</a-card>
<div class="ele-body">
<a-card :bordered="false">
<!-- 表格 -->
@@ -52,7 +101,7 @@
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { createVNode, reactive, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
@@ -66,9 +115,11 @@
import {
pageTowerEquipment,
removeBatchTowerEquipment,
statusBatchTowerEquipment, updateBatchTowerEquipment,
towerEquipmentData,
// statusBatchTowerEquipment,
updateBatchTowerEquipment,
updateTowerEquipment
} from "@/api/tower/equipment";
} from '@/api/tower/equipment';
import {
TowerEquipment,
TowerEquipmentParam
@@ -96,7 +147,8 @@
title: '设备状态',
dataIndex: 'status',
key: 'status',
customRender: ({ text }) => ['闲置', '报废', '注销', '转卖', '在用', '场地'][text]
customRender: ({ text }) =>
['闲置', '报废', '注销', '转卖', '在用', '场地'][text]
},
{
title: '设备名称',
@@ -147,6 +199,28 @@
// 是否显示编辑弹窗
const showEdit = ref(false);
const active = ref<any>(undefined);
let equipmentData = reactive({
totalNum: 0,
idleNum: 0,
scrapNum: 0,
totalNum2: 0,
totalNum3: 0,
totalNum4: 0,
totalNum5: 0
});
const getData = async () => {
const res = await towerEquipmentData();
for (let key in equipmentData) equipmentData[key] = res[key];
};
const onTab = (type: any) => {
active.value = type;
reload({ status: active.value });
};
// 表格数据源
const datasource: DatasourceFunction = ({
page,
@@ -249,7 +323,7 @@
}
};
};
getData();
reload();
</script>
@@ -278,4 +352,27 @@
.comments {
max-width: 200px;
}
.count {
display: flex;
.btn {
margin: 0 12px;
padding: 6px 18px;
background-color: #f3f3f3;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
font-size: 16px;
.divider {
width: 4px;
height: 15px;
border-radius: 8px;
margin-right: 8px;
background-color: #16a90b;
}
.active {
color: #16a90b;
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,120 +1,185 @@
<template>
<div>
<a-card title="项目数据">
<a-row :gutter="10">
<a-col :span="4">
<span>项目总数:{{ projectData.totalNum }}</span>
</a-col>
<a-col :span="4">
<span>已开工总数:{{ projectData.startedNum }}</span>
</a-col>
<a-col :span="4">
<span>未开工:{{ projectData.notStartNum }}</span>
</a-col>
</a-row>
</a-card>
<div class="page">
<div class="ele-body">
<a-card :bordered="false">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="projectId"
:columns="columns"
:datasource="datasource"
v-model:selection="selection"
:customRow="customRow"
:height="tableHeight"
:full-height="fixedHeight ? 'calc(100vh - 100px)' : void 0"
tool-class="ele-toolbar-form"
:scroll="{ x: 1200 }"
class="sys-org-table"
:striped="true"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'nickname'">
{{ record.nickname }}
</template>
<template v-if="column.key === 'orders'">
{{ record.orders.length > 0 ? record.orders[0].comments : "" }}
</template>
<template v-if="column.key === 'createTime'">
{{ record.createTime }}
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a @click="openEdit(record)">库存查看</a>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
</div>
<!-- 编辑弹窗 -->
<ProjectEdit v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 订单详情 -->
<order-info v-model:visible="showInfo" :data="current" @done="reload" />
<div>
<a-card title="项目数据">
<div class="count">
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab(undefined)"
:class="active == undefined ? 'active' : ''"
>
{{ `全部项目(${projectData.totalNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab('建设中')"
:class="active == '建设中' ? 'active' : ''"
>
{{ `建设中(${projectData.startedNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab('未开工')"
:class="active == '未开工' ? 'active' : ''"
>
{{ `未开工(${projectData.notStartNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab('已完成')"
:class="active == '已完成' ? 'active' : ''"
>
{{ `已完成(${projectData.okNum})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab('停工中')"
:class="active == '停工中' ? 'active' : ''"
>
{{ `停工中(${projectData.notStartNum2})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab('停工已拆机')"
:class="active == '停工已拆机' ? 'active' : ''"
>
{{ `停工已拆机(${projectData.notStartNum3})` }}
</div>
</div>
<div class="btn">
<a-divider type="vertical" class="divider" />
<div
@click="onTab('完工未拆机')"
:class="active == '完工未拆机' ? 'active' : ''"
>
{{ `完工未拆机(${projectData.notStartNum4})` }}
</div>
</div>
</div>
<!-- <a-row :gutter="10">-->
<!-- <a-col :span="4">-->
<!-- <span></span>-->
<!-- </a-col>-->
<!-- <a-col :span="4">-->
<!-- <span>已开工总数:{{ projectData.startedNum }}</span>-->
<!-- </a-col>-->
<!-- <a-col :span="4">-->
<!-- <span>未开工:{{ projectData.notStartNum }}</span>-->
<!-- </a-col>-->
<!-- </a-row>-->
</a-card>
<div class="page">
<div class="ele-body">
<a-card :bordered="false">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="projectId"
:columns="columns"
:datasource="datasource"
v-model:selection="selection"
:customRow="customRow"
:height="tableHeight"
:full-height="fixedHeight ? 'calc(100vh - 100px)' : void 0"
tool-class="ele-toolbar-form"
:scroll="{ x: 1200 }"
class="sys-org-table"
:striped="true"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'nickname'">
{{ record.nickname }}
</template>
<template v-if="column.key === 'orders'">
{{ record.orders.length > 0 ? record.orders[0].comments : '' }}
</template>
<template v-if="column.key === 'createTime'">
{{ record.createTime }}
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a @click="openEdit(record)">库存查看</a>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
</div>
<!-- 编辑弹窗 -->
<ProjectEdit v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 订单详情 -->
<order-info v-model:visible="showInfo" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, computed, ref, reactive } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import type {
import { createVNode, computed, ref, reactive } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ProjectEdit from "./components/project-edit.vue";
import OrderInfo from "./components/order-info.vue";
import {
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ProjectEdit from './components/project-edit.vue';
import OrderInfo from './components/order-info.vue';
import {
pageProject,
removeBatchProject,
removeProject, towerProjectData
} from "@/api/tower/project";
import { Project, ProjectParam } from "@/api/tower/project/model";
import { towerEquipmentData } from "@/api/tower/equipment";
removeProject,
towerProjectData
} from '@/api/tower/project';
import { Project, ProjectParam } from '@/api/tower/project/model';
defineProps<{
defineProps<{
activeKey?: boolean;
data?: any;
}>();
}>();
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格列配置
const columns = ref<ColumnItem[]>([
// 表格列配置
const columns = ref<ColumnItem[]>([
{
key: "index",
width: 48,
align: "center",
fixed: "left",
hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
key: 'index',
width: 48,
align: 'center',
fixed: 'left',
hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
},
{
title: "项目状态",
dataIndex: "projectStatus",
key: "projectStatus"
title: '项目状态',
dataIndex: 'projectStatus',
key: 'projectStatus'
},
{
title: "项目名称",
dataIndex: "projectName",
key: "projectName"
title: '项目名称',
dataIndex: 'projectName',
key: 'projectName'
},
// {
// title: '具体标地',
@@ -122,21 +187,21 @@ const columns = ref<ColumnItem[]>([
// key: 'orders'
// },
{
title: "承租单位",
dataIndex: "customerName",
key: "customerName"
title: '承租单位',
dataIndex: 'customerName',
key: 'customerName'
},
{
title: "项目所属主管部门",
dataIndex: "competentDepartment"
title: '项目所属主管部门',
dataIndex: 'competentDepartment'
},
{
title: "关联设备数",
dataIndex: "equipmentNum"
title: '关联设备数',
dataIndex: 'equipmentNum'
},
{
title: "项目管理员",
dataIndex: "director"
title: '项目管理员',
dataIndex: 'director'
},
// {
// title: '检查次数',
@@ -149,180 +214,212 @@ const columns = ref<ColumnItem[]>([
// key: 'companyId'
// },
{
title: "创建时间",
dataIndex: "createTime"
title: '创建时间',
dataIndex: 'createTime'
},
{
title: "操作",
key: "action",
width: 150,
align: "center",
hideInSetting: true
title: '操作',
key: 'action',
width: 150,
align: 'center',
hideInSetting: true
}
]);
]);
// 表格选中数据
const selection = ref<Project[]>([]);
// 当前编辑数据
const current = ref<Project | null>(null);
// 是否显示资产详情
const showInfo = ref(false);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 表格固定高度
const fixedHeight = ref(true);
// 表格高度
const tableHeight = computed(() => {
return fixedHeight.value ? "calc(100vh - 308px)" : void 0;
});
// 表格选中数据
const selection = ref<Project[]>([]);
// 当前编辑数据
const current = ref<Project | null>(null);
// 是否显示资产详情
const showInfo = ref(false);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 表格固定高度
const fixedHeight = ref(true);
const active = ref<any>(undefined);
// 表格高度
const tableHeight = computed(() => {
return fixedHeight.value ? 'calc(100vh - 308px)' : void 0;
});
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
// 搜索条件
if (filters.payMethod) {
where.payMethod = filters.payMethod;
where.payMethod = filters.payMethod;
}
if (filters.deliveryType) {
where.deliveryType = filters.deliveryType;
where.deliveryType = filters.deliveryType;
}
if (filters.payStatus) {
where.payStatus = filters.payStatus;
where.payStatus = filters.payStatus;
}
if (filters.orderSource) {
where.orderSource = filters.orderSource;
where.orderSource = filters.orderSource;
}
where.tenantId = localStorage.getItem("tenantId");
where.tenantId = localStorage.getItem('tenantId');
where.payStatus = 20;
return pageProject({
...where,
...orders,
page,
limit
...where,
...orders,
page,
limit
});
};
};
/* 搜索 */
const reload = (where?: ProjectParam) => {
/* 搜索 */
const reload = (where?: ProjectParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
getData();
};
};
/* 打开编辑弹窗 */
const openEdit = (row?: Project) => {
/* 打开编辑弹窗 */
const openEdit = (row?: Project) => {
current.value = row ?? null;
showEdit.value = true;
};
};
/* 打开用户详情弹窗 */
const openInfo = (row?: Project) => {
/* 打开用户详情弹窗 */
const openInfo = (row?: Project) => {
current.value = row ?? null;
showInfo.value = true;
};
};
let projectData = reactive({
let projectData = reactive({
totalNum: 0,
startedNum: 0,
notStartNum: 0
});
const getData = async () => {
notStartNum: 0,
okNum: 0,
notStartNum2: 0,
notStartNum3: 0,
notStartNum4: 0
});
const getData = async () => {
const res = await towerProjectData();
for (let key in projectData) projectData[key] = res[key];
};
};
/* 删除单个 */
const remove = (row: Project) => {
const hide = message.loading("请求中..", 0);
const onTab = (type: any) => {
active.value = type;
reload({ projectStatus: active.value });
};
/* 删除单个 */
const remove = (row: Project) => {
const hide = message.loading('请求中..', 0);
removeProject(row.projectId)
.then((msg) => {
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
console.log(selection.value);
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchProject(selection.value.map((d) => d.projectId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
console.log(selection.value);
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchProject(selection.value.map((d) => d.projectId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
}
});
};
};
/* 自定义行属性 */
const customRow = (record: Project) => {
/* 自定义行属性 */
const customRow = (record: Project) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
};
reload();
reload();
</script>
<script lang="ts">
export default {
name: "ProjectIndex"
};
export default {
name: 'ProjectIndex'
};
</script>
<style lang="less" scoped>
p {
p {
line-height: 0.8;
}
}
.sys-org-table :deep(.ant-table-body) {
.sys-org-table :deep(.ant-table-body) {
overflow: auto !important;
overflow: overlay !important;
}
}
.sys-org-table :deep(.ant-table-pagination.ant-pagination) {
.sys-org-table :deep(.ant-table-pagination.ant-pagination) {
padding: 0 4px;
margin-bottom: 0;
}
}
.price-edit {
.price-edit {
padding-right: 5px;
}
}
.comments {
.comments {
max-width: 200px;
}
}
.count {
display: flex;
.btn {
margin: 0 12px;
padding: 6px 18px;
background-color: #f3f3f3;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
font-size: 16px;
.divider {
width: 4px;
height: 15px;
border-radius: 8px;
margin-right: 8px;
background-color: #16a90b;
}
.active {
color: #16a90b;
}
}
}
</style>

View File

@@ -0,0 +1,249 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="740"
:visible="visible"
:confirm-loading="loading"
:title="isUpdate ? '修改分类' : '新建分类'"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 6, sm: 4, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 18, sm: 20, xs: 24 } : { flex: '1' }
"
>
<a-row :gutter="16">
<a-col
v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }"
>
<a-form-item label="上级分类" name="parentId">
<a-tree-select
allow-clear
:tree-data="categoryList"
tree-default-expand-all
placeholder="请选择上级分类"
:value="form.parentId || undefined"
:dropdown-style="{ maxHeight: '360px', overflow: 'auto' }"
@update:value="(value?: number) => (form.parentId = value)"
/>
</a-form-item>
<a-form-item label="设备型号" name="title">
<a-input
allow-clear
placeholder="请输入分类名称"
v-model:value="form.title"
@pressEnter="save"
/>
</a-form-item>
<a-form-item label="使用年限" name="yearLife">
<a-input
allow-clear
placeholder="请输入分类名称"
v-model:value="form.yearLife"
@pressEnter="save"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { message } from 'ant-design-vue/es';
import type { FormInstance, Rule } from 'ant-design-vue/es/form';
import { storeToRefs } from 'pinia';
import { useThemeStore } from '@/store/modules/theme';
import useFormData from '@/utils/use-form-data';
import type { TowerModel } from '@/api/tower/model/model';
import { addTowerModel, updateTowerModel } from '@/api/tower/model';
import { FILE_SERVER } from "@/config/setting";
import { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import { uploadFile } from "@/api/system/file";
import { LoginRecordParam } from "@/api/system/login-record/model";
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: TowerModel | null;
// 上级分类id
parentId?: number;
// 全部分类数据
categoryList: TowerModel[];
}>();
// 表单数据
const { form, resetFields, assignFields } = useFormData<TowerModel>({
title: '',
categoryId: undefined,
parentId: undefined,
image: '',
status: 0,
yearLife: undefined,
sortNumber: 100
});
//
const formRef = ref<FormInstance | null>(null);
// 是否是修改
const isUpdate = ref(false);
// 提交状态
const loading = ref(false);
// 已上传数据, 可赋初始值用于回显
const images = ref([]);
// 表单验证规则
const rules = reactive<Record<string, Rule[]>>({
title: [
{
required: true,
message: '请输入分类名称',
type: 'string',
trigger: 'blur'
}
],
sortNumber: [
{
required: true,
message: '请输入排序号',
type: 'number',
trigger: 'blur'
}
],
meta: [
{
type: 'string',
validator: async (_rule: Rule, value: string) => {
if (value) {
const msg = '请输入正确的JSON格式';
try {
const obj = JSON.parse(value);
if (typeof obj !== 'object' || obj === null) {
return Promise.reject(msg);
}
} catch (_e) {
return Promise.reject(msg);
}
}
return Promise.resolve();
},
trigger: 'blur'
}
]
});
// 上传文件
const onUpload = (d: ItemType) => {
uploadFile(<File>d.file)
.then((result) => {
form.image = result.path;
message.success('上传成功');
})
.catch((e) => {
message.error(e.message);
});
};
const onClose = () => {
form.image = ''
}
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const categoryForm = {
...form,
parentId: form.parentId || 0
};
const saveOrUpdate = isUpdate.value ? updateTowerModel : addTowerModel;
saveOrUpdate(categoryForm)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const updateHideValue = (value: boolean) => {
form.status = value ? 0 : 1;
};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
// 头像赋值
images.value = [];
if(props.data.image){
images.value.push({ uid:1, url: props.data.image, status: '' });
}
assignFields({
...props.data,
parentId:
props.data.parentId === 0 ? undefined : props.data.parentId
});
isUpdate.value = true;
} else {
form.parentId = props.parentId;
isUpdate.value = false;
}
} else {
resetFields();
formRef.value?.clearValidate();
}
}
);
</script>
<script lang="ts">
import * as icons from '@/layout/menu-icons';
export default {
components: icons,
data() {
return {
iconData: [
{
title: '已引入的图标',
icons: Object.keys(icons)
}
]
};
}
};
</script>

View File

@@ -0,0 +1,217 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="500"
:visible="visible"
:confirm-loading="loading"
:title="isUpdate ? '修改' : '新建'"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 6, sm: 6, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 18, sm: 20, xs: 24 } : { flex: '1' }
"
>
<a-row :gutter="16">
<a-col
v-bind="styleResponsive ? { md: 22, sm: 24, xs: 24 } : { span: 12 }"
>
<a-form-item label="租赁名称" name="company">
<SelectCompany
:placeholder="`请选择租赁单位`"
v-model:value="form.companyName"
@done="chooseCompany"
/>
</a-form-item>
<a-form-item label="月租金" name="month">
<a-input
allow-clear
placeholder="请输入月租金"
v-model:value="form.month"
/>
</a-form-item>
<a-form-item label="月数" name="num">
<a-input
allow-clear
placeholder="请输入租金"
v-model:value="form.num"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { message } from 'ant-design-vue/es';
import type { FormInstance, Rule } from 'ant-design-vue/es/form';
import { storeToRefs } from 'pinia';
import { useThemeStore } from '@/store/modules/theme';
import useFormData from '@/utils/use-form-data';
import type { TowerRent } from '@/api/tower/rent/model';
import { addTowerRent, updateTowerRent } from '@/api/tower/rent';
import { RuleObject } from 'ant-design-vue/es/form';
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: TowerRent | null;
}>();
const formRef = ref<FormInstance | null>(null);
// 是否是修改
const isUpdate = ref(false);
// 提交状态
const loading = ref(false);
// 表单数据
const { form, resetFields, assignFields } = useFormData<TowerRent>({
rentId: undefined,
rent: undefined,
name: '',
month: undefined,
num: undefined,
totalRent: '',
companyName: '',
image: '',
status: 0,
yearLife: undefined,
sortNumber: 100
});
// 表单验证规则
const rules = reactive<Record<string, Rule[]>>({
company: [
{
required: true,
message: '请选择租赁单位',
type: 'string',
trigger: 'blur',
validator: async (_rule: RuleObject, value: string) => {
console.log(value);
if (form.companyName == '') {
return Promise.reject('请选择租赁单位');
}
return Promise.resolve();
}
}
],
name: [
{
required: true,
message: '请输入名称',
type: 'string',
trigger: 'blur'
}
],
month: [
{
required: true,
message: '请输入租金',
type: 'string',
trigger: 'blur'
}
],
num: [
{
required: true,
message: '请输入月数',
type: 'string',
trigger: 'blur'
}
],
sortNumber: [
{
required: true,
message: '请输入排序号',
type: 'number',
trigger: 'blur'
}
]
});
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const categoryForm = {
...form
};
const saveOrUpdate = isUpdate.value ? updateTowerRent : addTowerRent;
saveOrUpdate(categoryForm)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const chooseCompany = (row) => {
console.log(row);
form.companyName = row.companyName;
form.companyId = row.companyId;
};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
assignFields({
...props.data
});
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
formRef.value?.clearValidate();
}
}
);
</script>
<style lang="less">
.tab-pane {
min-height: 300px;
}
.ml-10 {
margin-left: 5px;
}
</style>

View File

@@ -0,0 +1,194 @@
<template>
<div class="ele-body">
<a-card :bordered="false">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="rentId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:need-page="false"
:expand-icon-column-index="1"
:scroll="{ x: 1200 }"
cache-key="towerRent"
>
<template #toolbar>
<a-space>
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined />
</template>
<span>新建</span>
</a-button>
<!-- 搜索表单 -->
<a-input-search
allow-clear
v-model:value="searchText"
placeholder="请输入搜索关键词"
@search="search"
@pressEnter="search"
/>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key == 'totalRent'">
{{ record.month * record.num }}
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
placement="topRight"
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<RentEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { message } from 'ant-design-vue/es';
import { PlusOutlined } from '@ant-design/icons-vue';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import { messageLoading, toDateString } from 'ele-admin-pro/es';
import type { EleProTable } from 'ele-admin-pro/es';
import type { TowerRent, TowerRentParam } from '@/api/tower/rent/model';
import { listTowerRent, removeTowerRent } from '@/api/tower/rent';
import RentEdit from '@/views/tower/rent/components/rent-edit.vue';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格列配置
const columns = ref<ColumnItem[]>([
{
key: 'index',
width: 48,
align: 'center',
fixed: 'left',
hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
},
{
title: '单位名称',
dataIndex: 'companyName',
key: 'companyName',
showSorterTooltip: false,
ellipsis: true
},
{
title: '月租金',
dataIndex: 'month',
key: 'month',
showSorterTooltip: false,
ellipsis: true
},
{
title: '月数',
dataIndex: 'num',
key: 'num',
showSorterTooltip: false,
ellipsis: true
},
{
title: '租金',
dataIndex: 'totalRent',
key: 'totalRent',
showSorterTooltip: false,
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
sorter: true,
showSorterTooltip: false,
ellipsis: true,
width: 180,
customRender: ({ text }) => toDateString(text)
},
{
title: '操作',
key: 'action',
width: 200,
align: 'center'
}
]);
// 当前编辑数据
const current = ref<TowerRent | null>(null);
const searchText = ref('');
// 是否显示编辑弹窗
const showEdit = ref(false);
// 表格数据源
const datasource: DatasourceFunction = ({ where }) => {
if (searchText.value) {
where.keywords = searchText.value;
}
return listTowerRent({ ...where });
};
/* 刷新表格 */
const reload = (where?: TowerRentParam) => {
tableRef?.value?.reload({ where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: TowerRent | null, id?: number) => {
current.value = row ?? null;
showEdit.value = true;
};
const search = (searchText) => {
reload({ keywords: searchText });
};
/* 删除单个 */
const remove = (row: TowerRent) => {
const hide = messageLoading('请求中..', 0);
removeTowerRent(row.rentId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 自定义行属性 */
const customRow = (record: TowerRent) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
</script>
<script lang="ts">
export default {
name: 'TowerRent'
};
</script>