完成:保养记录和厂内维修模块

This commit is contained in:
gxwebsoft
2024-02-25 19:33:03 +08:00
parent 08f83ed015
commit aa56030cbd
16 changed files with 1442 additions and 400 deletions

View File

@@ -1,3 +1,3 @@
VITE_APP_NAME=后台管理系统 VITE_APP_NAME=后台管理系统
#VITE_API_URL=http://127.0.0.1:10041/api VITE_API_URL=http://127.0.0.1:10041/api
VITE_API_URL=http://1.14.159.185:10041/api #VITE_API_URL=http://1.14.159.185:10041/api

View File

@@ -1,43 +1,43 @@
import type { PageParam } from "@/api"; import type { PageParam } from '@/api';
import { Dayjs } from "dayjs"; import { Dayjs } from 'dayjs';
export interface Accessory { export interface Accessory {
accessoryId?: undefined; accessoryId?: undefined;
accessoryName?: string; accessoryName?: string;
accessoryNo?: string; accessoryNo?: string;
accessoryCategory?: object; accessoryCategory?: object;
accessoryModel?: string; accessoryModel?: string;
accessoryModelMultiple?: string[]; accessoryModelMultiple?: string[];
accessorySpecs?: string; accessorySpecs?: string;
accessoryPrice?: number; accessoryPrice?: number;
accessoryNum?: number; accessoryNum?: number;
accessoryUnit?: string; accessoryUnit?: string;
accessoryStock?: string; accessoryStock?: string;
companyNo?: string; companyNo?: string;
companyName?: string; companyName?: string;
manufactor?: string; manufactor?: string;
manufactorNo?: string; manufactorNo?: string;
accessoryWeight?: string; accessoryWeight?: string;
lifeYear?: number; lifeYear?: number;
factoryDate?: string; factoryDate?: string;
scrapDate?: string; scrapDate?: string;
status?: number; status?: number;
comments?: string; comments?: string;
sortNumber?: number; sortNumber?: number;
userId?: number; userId?: number;
deleted?: number; deleted?: number;
tenantId?: number; tenantId?: number;
createTime?: string; createTime?: string;
updateTime?: string; updateTime?: string;
buyDate?: string | Dayjs; buyDate?: string | Dayjs;
} }
/** /**
* 搜索条件 * 搜索条件
*/ */
export interface AccessoryParam extends PageParam { export interface AccessoryParam extends PageParam {
accessoryId?: number; accessoryId?: number;
accessoryName?: string; accessoryName?: string;
status?: number; status?: number;
keywords?: string; keywords?: string;
} }

View File

@@ -0,0 +1,109 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type {
SecurityPlant,
SecurityPlantParam
} from '@/api/tower/security-plant/model';
/**
* 分页查询仓库
*/
export async function pageSecurityPlant(params: SecurityPlantParam) {
const res = await request.get<ApiResult<PageResult<SecurityPlant>>>(
'/tower/tower-security-plant/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询仓库列表
*/
export async function listSecurityPlant(params?: SecurityPlantParam) {
const res = await request.get<ApiResult<SecurityPlant[]>>(
'/tower/tower-security-plant',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加仓库
*/
export async function addSecurityPlant(data: SecurityPlant) {
const res = await request.post<ApiResult<unknown>>(
'/tower/tower-security-plant',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改仓库
*/
export async function updateSecurityPlant(data: SecurityPlant) {
const res = await request.put<ApiResult<unknown>>(
'/tower/tower-security-plant',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 绑定仓库
*/
export async function bindSecurityPlant(data: SecurityPlant) {
const res = await request.put<ApiResult<unknown>>(
'/tower/tower-security-plant/bind',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除仓库
*/
export async function removeSecurityPlant(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
'/tower/tower-security-plant/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除仓库
*/
export async function removeBatchSecurityPlant(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
'/tower/tower-security-plant/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}

View File

@@ -0,0 +1,39 @@
import type { PageParam } from '@/api';
export interface SecurityPlant {
securityPlantId?: number;
securityId?: number;
projectName?: string;
projectId?: number;
securityCode?: string;
regionName?: string;
longitude?: string;
latitude?: string;
country?: string;
province?: string;
city?: string;
region?: string;
address?: string;
status?: number;
confirmStatus?: number;
userId?: number;
confirmId?: number;
comments?: string;
sortNumber?: number;
accessoryName?: string;
accessoryCategory?: object;
accessoryNo?: string;
accessorySpecs?: string;
accessoryModel?: string;
}
/**
* 搜索条件
*/
export interface SecurityPlantParam extends PageParam {
securityId?: number;
projectId?: number;
projectName?: string;
status?: number;
keywords?: string;
}

View File

@@ -2,6 +2,7 @@ import type { PageParam } from '@/api';
export interface SecurityRecord { export interface SecurityRecord {
securityRecordId?: number; securityRecordId?: number;
securityId?: number;
projectName?: string; projectName?: string;
projectId?: number; projectId?: number;
securityCode?: string; securityCode?: string;
@@ -17,6 +18,11 @@ export interface SecurityRecord {
userId?: number; userId?: number;
comments?: string; comments?: string;
sortNumber?: number; sortNumber?: number;
accessoryName?: string;
accessoryCategory?: object;
accessoryNo?: string;
accessorySpecs?: string;
accessoryModel?: string;
} }
/** /**

View File

@@ -1,7 +1,7 @@
import type { PageParam } from '@/api'; import type { PageParam } from '@/api';
export interface Security { export interface Security {
type: number; type?: number;
securityId?: number; securityId?: number;
projectName?: string; projectName?: string;
projectId?: number; projectId?: number;
@@ -22,6 +22,10 @@ export interface Security {
userId?: number; userId?: number;
comments?: string; comments?: string;
sortNumber?: number; sortNumber?: number;
accessoryNo?: string;
accessoryCategory?: object;
accessoryModel?: string;
accessorySpecs?: string;
} }
/** /**

View File

@@ -0,0 +1,157 @@
<template>
<ele-modal
:width="750"
:visible="visible"
:maskClosable="false"
:title="title"
:footer="null"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
>
<ele-pro-table
ref="tableRef"
row-key="customerId"
:datasource="datasource"
:columns="columns"
:customRow="customRow"
:pagination="false"
>
<template #toolbar>
<a-input-search
allow-clear
v-model:value="searchText"
placeholder="请输入搜索关键词"
style="width: 200px"
@search="reload"
@pressEnter="reload"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'customerLogo'">
<a-image
v-if="record.customerAvatar"
:src="FILE_THUMBNAIL + record.customerAvatar"
:preview="false"
:width="45"
/>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button type="link">选择</a-button>
</a-space>
</template>
</template>
</ele-pro-table>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import {
ColumnItem,
DatasourceFunction
} from 'ele-admin-pro/es/ele-pro-table/types';
import { pageCustomer } from '@/api/oa/customer';
import { FILE_THUMBNAIL } from '@/config/setting';
import { EleProTable } from 'ele-admin-pro';
import { Customer, CustomerParam } from '@/api/oa/customer/model';
import { pageAccessory } from '@/api/tower/accessory';
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 标题
title?: string;
// 企业类型
customerType?: string;
// 修改回显的数据
data?: Customer | null;
}>();
const emit = defineEmits<{
(e: 'done', data: Customer): void;
(e: 'update:visible', visible: boolean): void;
}>();
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 搜索内容
const searchText = ref(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: 'accessoryNo'
},
{
title: '配件分类',
dataIndex: 'accessoryCategory'
},
{
title: '适用设备型号',
dataIndex: 'accessoryModel'
},
{
title: '配件规格',
dataIndex: 'accessorySpecs'
},
{
title: '操作',
key: 'action',
align: 'center'
}
]);
// 表格数据源
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
// where = {};
// 搜索条件
// if (searchText.value) {
// where.keywords = searchText.value;
// }
// if (props.customerType == 'empty') {
// where.emptyType = true;
// } else {
// where.customerType = props.customerType;
// }
// where.isStaff = true;
return pageAccessory({
...where,
...orders,
page,
limit
});
};
/* 搜索 */
const reload = (where?: CustomerParam) => {
tableRef?.value?.reload({ page: 1, where });
};
/* 自定义行属性 */
const customRow = (record: Customer) => {
return {
// 行点击事件
onClick: () => {
updateVisible(false);
emit('done', record);
}
};
};
</script>
<style lang="less"></style>

View File

@@ -0,0 +1,61 @@
<template>
<div>
<a-input-group compact>
<a-input
disabled
style="width: calc(100% - 32px)"
v-model:value="value"
:placeholder="placeholder"
/>
<a-button @click="openEdit">
<template #icon><BulbOutlined class="ele-text-warning" /></template>
</a-button>
</a-input-group>
<!-- 选择弹窗 -->
<SelectData
v-model:visible="showEdit"
:data="current"
:title="placeholder"
:customer-type="customerType"
@done="onChange"
/>
</div>
</template>
<script lang="ts" setup>
import { BulbOutlined } from '@ant-design/icons-vue';
import { ref } from 'vue';
import SelectData from './components/select-data.vue';
import { Customer } from '@/api/oa/customer/model';
withDefaults(
defineProps<{
value?: any;
customerType?: string;
placeholder?: string;
}>(),
{
placeholder: '请选择数据'
}
);
const emit = defineEmits<{
(e: 'done', Customer): void;
(e: 'clear'): void;
}>();
// 是否显示编辑弹窗
const showEdit = ref(false);
// 当前编辑数据
const current = ref<Customer | null>(null);
/* 打开编辑弹窗 */
const openEdit = (row?: Customer) => {
current.value = row ?? null;
showEdit.value = true;
};
const onChange = (row) => {
emit('done', row);
};
</script>

View File

@@ -1,406 +1,406 @@
<template> <template>
<div class="page"> <div class="page">
<div class="ele-body"> <div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }"> <a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table <ele-pro-table
ref="tableRef" ref="tableRef"
row-key="accessoryId" row-key="accessoryId"
:columns="columns" :columns="columns"
:datasource="datasource" :datasource="datasource"
v-model:selection="selection" v-model:selection="selection"
:customRow="customRow" :customRow="customRow"
tool-class="ele-toolbar-form" tool-class="ele-toolbar-form"
:scroll="{ x: 3000 }" :scroll="{ x: 3000 }"
class="sys-org-table" class="sys-org-table"
> >
<template #toolbar> <template #toolbar>
<search <search
@search="reload" @search="reload"
:selection="selection" :selection="selection"
@add="openEdit" @add="openEdit"
@remove="removeBatch" @remove="removeBatch"
@batchMove="openMove" @batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'accessoryName'">
<a-avatar
:size="30"
:src="`${record.accessoryAvatar}`"
style="margin-right: 4px"
:srcset="`https://file.wsdns.cn/${record.accessoryAvatar}`"
>
<template #icon>
<UserOutlined />
</template>
</a-avatar>
<a-tooltip title="查看详情">
<a href="#" @click="openInfo(record)">{{
record.accessoryName
}}</a>
</a-tooltip>
</template>
<template v-if="column.key === 'progress'">
<div v-for="(d, i) in progressDict" :key="i">
<span v-if="d.value === record.progress">{{ d.label }}</span>
</div>
</template>
<template v-if="column.key === 'accessoryType'">
<div v-for="(d, i) in JSON.parse(accessoryType)" :key="i">
<span v-if="d.value === record.accessoryType">{{
d.value
}}</span>
</div>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">正常</a-tag>
<a-tag v-if="record.status === 1" color="red">待审核</a-tag>
<a-tag v-if="record.status === 2" color="purple">已驳回</a-tag>
</template>
<template v-if="column.key === 'nickname'">
<a-tooltip :title="`${record.nickname}`">
<a-avatar :src="record.userAvatar" size="small" />
</a-tooltip>
</template>
<template v-if="column.key === 'createTime'">
<a-tooltip :title="`${toDateString(record.createTime)}`">
{{ timeAgo(record.createTime) }}
</a-tooltip>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<!-- <a-divider type="vertical" />-->
<!-- <a>库存分布</a>-->
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<AccessoryEdit
v-model:visible="showEdit"
:data="current"
:category-list="data"
:model-tree="data2"
:model-list="data2List"
@done="reload"
/> />
<!-- 批量转移弹窗 --> </template>
<!-- <AccessoryMove v-model:visible="showMove" :data="selection" @done="batchMove" />--> <template #bodyCell="{ column, record }">
</div> <template v-if="column.key === 'accessoryName'">
<a-avatar
:size="30"
:src="`${record.accessoryAvatar}`"
style="margin-right: 4px"
:srcset="`https://file.wsdns.cn/${record.accessoryAvatar}`"
>
<template #icon>
<UserOutlined />
</template>
</a-avatar>
<a-tooltip title="查看详情">
<a href="#" @click="openInfo(record)">{{
record.accessoryName
}}</a>
</a-tooltip>
</template>
<template v-if="column.key === 'progress'">
<div v-for="(d, i) in progressDict" :key="i">
<span v-if="d.value === record.progress">{{ d.label }}</span>
</div>
</template>
<template v-if="column.key === 'accessoryType'">
<div v-for="(d, i) in JSON.parse(accessoryType)" :key="i">
<span v-if="d.value === record.accessoryType">{{
d.value
}}</span>
</div>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">正常</a-tag>
<a-tag v-if="record.status === 1" color="red">待审核</a-tag>
<a-tag v-if="record.status === 2" color="purple">已驳回</a-tag>
</template>
<template v-if="column.key === 'nickname'">
<a-tooltip :title="`${record.nickname}`">
<a-avatar :src="record.userAvatar" size="small" />
</a-tooltip>
</template>
<template v-if="column.key === 'createTime'">
<a-tooltip :title="`${toDateString(record.createTime)}`">
{{ timeAgo(record.createTime) }}
</a-tooltip>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<!-- <a-divider type="vertical" />-->
<!-- <a>库存分布</a>-->
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<AccessoryEdit
v-model:visible="showEdit"
:data="current"
:category-list="data"
:model-tree="data2"
:model-list="data2List"
@done="reload"
/>
<!-- 批量转移弹窗 -->
<!-- <AccessoryMove v-model:visible="showMove" :data="selection" @done="batchMove" />-->
</div> </div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, createVNode, ref } from "vue"; import { computed, createVNode, ref } from 'vue';
import { message, Modal } from "ant-design-vue"; import { message, Modal } from 'ant-design-vue';
import { import {
ExclamationCircleOutlined, ExclamationCircleOutlined,
UserOutlined UserOutlined
} from "@ant-design/icons-vue"; } from '@ant-design/icons-vue';
import type { EleProTable } from "ele-admin-pro"; import type { EleProTable } from 'ele-admin-pro';
import type { import type {
DatasourceFunction, DatasourceFunction,
ColumnItem ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types"; } from 'ele-admin-pro/es/ele-pro-table/types';
import { toDateString, toTreeData } from "ele-admin-pro"; import { toDateString, toTreeData } from 'ele-admin-pro';
import Search from "./components/search.vue"; import Search from './components/search.vue';
import AccessoryEdit from "./components/accessory-edit.vue"; import AccessoryEdit from './components/accessory-edit.vue';
import { import {
pageAccessory, pageAccessory,
removeAccessory, removeAccessory,
removeBatchAccessory removeBatchAccessory
} from "@/api/tower/accessory"; } from '@/api/tower/accessory';
import { timeAgo } from "ele-admin-pro"; import { timeAgo } from 'ele-admin-pro';
import type { Accessory, AccessoryParam } from "@/api/tower/accessory/model"; import type { Accessory, AccessoryParam } from '@/api/tower/accessory/model';
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from '@/store/modules/user';
import { Category } from "@/api/goods/category/model"; import { Category } from '@/api/goods/category/model';
import { listCategory } from "@/api/goods/category"; import { listCategory } from '@/api/goods/category';
import { listTowerModel } from "@/api/tower/model"; import { listTowerModel } from '@/api/tower/model';
import { TowerModel } from "@/api/tower/model/model"; import { TowerModel } from '@/api/tower/model/model';
const userStore = useUserStore(); const userStore = useUserStore();
// 当前用户信息 // 当前用户信息
const loginUser = computed(() => userStore.info ?? {}); const loginUser = computed(() => userStore.info ?? {});
const accessoryType = localStorage.getItem("accessoryType"); const accessoryType = localStorage.getItem('accessoryType');
// 表格实例 // 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据 // 表格选中数据
const selection = ref<Accessory[]>([]); const selection = ref<Accessory[]>([]);
// 当前编辑数据 // 当前编辑数据
const current = ref<Accessory | null>(null); const current = ref<Accessory | null>(null);
// 树形数据 // 树形数据
const data = ref<Category[]>([]); const data = ref<Category[]>([]);
const data2 = ref<TowerModel[]>([]); const data2 = ref<TowerModel[]>([]);
const data2List = ref<TowerModel[]>([]); const data2List = ref<TowerModel[]>([]);
// 是否显示资产详情 // 是否显示资产详情
const showInfo = ref(false); const showInfo = ref(false);
// 是否显示编辑弹窗 // 是否显示编辑弹窗
const showEdit = ref(false); const showEdit = ref(false);
// 是否显示批量移动弹窗 // 是否显示批量移动弹窗
const showMove = ref(false); const showMove = ref(false);
// 加载状态 // 加载状态
const loading = ref(true); const loading = ref(true);
// 树展开的key // 树展开的key
const expandedRowKeys = ref<number[]>([]); const expandedRowKeys = ref<number[]>([]);
// 树选中的key // 树选中的key
const selectedRowKeys = ref<number[]>([]); const selectedRowKeys = ref<number[]>([]);
// 表格数据源 // 表格数据源
const datasource: DatasourceFunction = ({ const datasource: DatasourceFunction = ({
page, page,
limit, limit,
where, where,
orders, orders,
filters filters
}) => { }) => {
if (filters) { if (filters) {
where.progress = filters.progress; where.progress = filters.progress;
where.accessorySource = filters.accessorySource; where.accessorySource = filters.accessorySource;
where.accessoryType = filters.accessoryType; where.accessoryType = filters.accessoryType;
where.status = filters.status; where.status = filters.status;
} }
return pageAccessory({ return pageAccessory({
...where, ...where,
...orders, ...orders,
page, page,
limit limit
}); });
}; };
// 表格列配置 // 表格列配置
const columns = ref<ColumnItem[]>([ const columns = ref<ColumnItem[]>([
{ {
key: "index", key: 'index',
width: 48, width: 48,
align: "center", align: 'center',
fixed: "left", fixed: 'left',
hideInSetting: true, hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0) customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
}, },
{ {
title: "配件编号", title: '配件编号',
dataIndex: "accessoryNo" dataIndex: 'accessoryNo'
}, },
{ {
title: "生成厂家", title: '生产厂家',
dataIndex: "accessoryName" dataIndex: 'accessoryName'
}, },
{ {
title: "配件分类", title: '配件分类',
dataIndex: "accessoryCategory" dataIndex: 'accessoryCategory'
}, },
{ {
title: "适用设备型号", title: '适用设备型号',
dataIndex: "accessoryModel" dataIndex: 'accessoryModel'
}, },
{ {
title: "配件规格", title: '配件规格',
dataIndex: "accessorySpecs" dataIndex: 'accessorySpecs'
}, },
{ {
title: "单价", title: '单价',
dataIndex: "accessoryPrice" dataIndex: 'accessoryPrice'
}, },
{ {
title: "购买数量", title: '购买数量',
dataIndex: "accessoryNum" dataIndex: 'accessoryNum'
}, },
{ {
title: "配件单位", title: '配件单位',
dataIndex: "accessoryUnit" dataIndex: 'accessoryUnit'
}, },
{ {
title: "产权单位名称", title: '产权单位名称',
dataIndex: "companyName" dataIndex: 'companyName'
}, },
{ {
title: "制造厂商", title: '制造厂商',
dataIndex: "manufactor" dataIndex: 'manufactor'
}, },
{ {
title: "制造厂商编号", title: '制造厂商编号',
dataIndex: "manufactorNo" dataIndex: 'manufactorNo'
}, },
{ {
title: "使用年限", title: '使用年限',
dataIndex: "lifeYear" dataIndex: 'lifeYear'
}, },
{ {
title: "出厂日期", title: '出厂日期',
dataIndex: "factoryDate", dataIndex: 'factoryDate',
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd") customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
}, },
{ {
title: "报废日期", title: '报废日期',
dataIndex: "scrapDate", dataIndex: 'scrapDate',
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd") customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
}, },
{ {
title: "操作", title: '操作',
key: "action", key: 'action',
width: 200, width: 200,
fixed: "right", fixed: 'right',
align: "center", align: 'center',
hideInSetting: true hideInSetting: true
} }
]); ]);
/* 搜索 */ /* 搜索 */
const reload = (where?: AccessoryParam) => { const reload = (where?: AccessoryParam) => {
console.log(where); console.log(where);
selection.value = []; selection.value = [];
tableRef?.value?.reload({ where: where }); tableRef?.value?.reload({ where: where });
}; };
/* 打开编辑弹窗 */ /* 打开编辑弹窗 */
const openEdit = (row?: Accessory) => { const openEdit = (row?: Accessory) => {
current.value = row ?? null; current.value = row ?? null;
showEdit.value = true; showEdit.value = true;
}; };
/* 打开批量移动弹窗 */ /* 打开批量移动弹窗 */
const openMove = () => { const openMove = () => {
showMove.value = true; showMove.value = true;
}; };
/* 打开用户详情弹窗 */ /* 打开用户详情弹窗 */
const openInfo = (row?: Accessory) => { const openInfo = (row?: Accessory) => {
current.value = row ?? null; current.value = row ?? null;
showInfo.value = true; showInfo.value = true;
}; };
/* 删除单个 */ /* 删除单个 */
const remove = (row: Accessory) => { const remove = (row: Accessory) => {
const hide = message.loading("请求中..", 0); const hide = message.loading('请求中..', 0);
removeAccessory(row.accessoryId) removeAccessory(row.accessoryId)
.then((msg) => { .then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量转移 */
const batchMove = (userId) => {
console.log(userId, '批量转移0000');
console.log(selection.value);
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchAccessory(
selection.value.map((d) => {
if (loginUser.value.userId === d.userId) {
return d.accessoryId;
}
})
)
.then((msg) => {
hide(); hide();
message.success(msg); message.success(msg);
reload(); reload();
}) })
.catch((e) => { .catch((e) => {
hide(); hide();
message.error(e.message); message.error(e.message);
}); });
}; }
/* 批量转移 */
const batchMove = (userId) => {
console.log(userId, "批量转移0000");
console.log(selection.value);
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchAccessory(
selection.value.map((d) => {
if (loginUser.value.userId === d.userId) {
return d.accessoryId;
}
})
)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
}); });
}; };
/* 查询 */ /* 查询 */
const query = () => { const query = () => {
loading.value = true; loading.value = true;
listCategory() listCategory()
.then((list) => { .then((list) => {
loading.value = false; loading.value = false;
const eks: number[] = []; const eks: number[] = [];
list.forEach((d) => { list.forEach((d) => {
d.key = d.categoryId; d.key = d.categoryId;
d.value = d.categoryId; d.value = d.categoryId;
if (typeof d.categoryId === "number") { if (typeof d.categoryId === 'number') {
eks.push(d.categoryId); eks.push(d.categoryId);
} }
});
expandedRowKeys.value = eks;
data.value = toTreeData({
data: list,
idField: "categoryId",
parentIdField: "parentId"
});
if (list.length) {
if (typeof list[0].categoryId === "number") {
selectedRowKeys.value = [list[0].categoryId];
}
} else {
selectedRowKeys.value = [];
}
})
.catch((e) => {
loading.value = false;
message.error(e.message);
}); });
}; expandedRowKeys.value = eks;
data.value = toTreeData({
/* 自定义行属性 */ data: list,
const customRow = (record: Accessory) => { idField: 'categoryId',
return { parentIdField: 'parentId'
// 行点击事件 });
onClick: () => { if (list.length) {
// console.log(record); if (typeof list[0].categoryId === 'number') {
}, selectedRowKeys.value = [list[0].categoryId];
// 行双击事件 }
onDblclick: () => { } else {
openEdit(record); selectedRowKeys.value = [];
} }
}; })
}; .catch((e) => {
loading.value = false;
message.error(e.message);
});
};
query(); /* 自定义行属性 */
const customRow = (record: Accessory) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script> </script>
<script lang="ts"> <script lang="ts">
export default { export default {
name: "Accessory" name: 'Accessory'
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.sys-org-table :deep(.ant-table-body) { .sys-org-table :deep(.ant-table-body) {
overflow: auto !important; overflow: auto !important;
overflow: overlay !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; padding: 0 4px;
margin-bottom: 0; margin-bottom: 0;
} }
</style> </style>

View File

@@ -0,0 +1,237 @@
<!-- 编辑弹窗 -->
<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="projectName">
<TowerAccessory
:placeholder="`请选择构件`"
v-model:value="form.projectName"
@done="chooseProject"
/>
</a-form-item>
<a-form-item label="配件编号" name="accessoryNo">
<a-input
allow-clear
placeholder="请选择构件"
:disabled="true"
v-model:value="form.accessoryNo"
/>
</a-form-item>
<a-form-item label="配件分类" name="accessoryCategory">
<a-input
allow-clear
placeholder="请选择构件"
:disabled="true"
v-model:value="form.accessoryCategory"
/>
</a-form-item>
<a-form-item label="适用设备型号" name="accessoryModel">
<a-input
allow-clear
placeholder="请选择构件"
:disabled="true"
v-model:value="form.accessoryModel"
/>
</a-form-item>
<a-form-item label="配件规格" name="accessorySpecs">
<a-input
allow-clear
placeholder="请选择构件"
:disabled="true"
v-model:value="form.accessorySpecs"
/>
</a-form-item>
<a-form-item label="保养内容" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入保养内容"
v-model:value="form.comments"
/>
</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 { Security } from '@/api/tower/security/model';
import { Accessory } from '@/api/tower/accessory/model';
import {
addSecurityPlant,
updateSecurityPlant
} from '@/api/tower/security-plant';
import { SecurityPlant } from '@/api/tower/security-plant/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?: Security | null;
}>();
const formRef = ref<FormInstance | null>(null);
// 是否是修改
const isUpdate = ref(false);
// 提交状态
const loading = ref(false);
// 表单数据
const { form, resetFields, assignFields } = useFormData<SecurityPlant>({
securityPlantId: undefined,
securityId: undefined,
projectId: undefined,
projectName: undefined,
securityCode: undefined,
accessoryCategory: undefined,
address: '',
status: 0,
sortNumber: 100
});
// 表单验证规则
const rules = reactive<Record<string, Rule[]>>({
projectName: [
{
required: true,
message: '请选择构件',
type: 'string',
trigger: 'blur'
}
],
model: [
{
required: true,
message: '请输入设备型号',
type: 'string',
trigger: 'blur'
}
],
yearLife: [
{
required: true,
message: '请输入设备使用年限',
type: 'number',
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
? updateSecurityPlant
: addSecurityPlant;
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 chooseProject = (row: Accessory) => {
form.projectId = row.accessoryId;
form.projectName = row.accessoryName;
form.securityId = row.accessoryId;
form.accessoryNo = row.accessoryNo;
form.accessorySpecs = row.accessorySpecs;
form.accessoryModel = row.accessoryModel;
form.accessoryCategory = row.accessoryCategory;
};
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,251 @@
<template>
<div class="ele-body">
<a-card :bordered="false">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="securityPlantId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:expand-icon-column-index="1"
:scroll="{ x: 1200 }"
cache-key="towerModel"
>
<template #toolbar>
<a-space>
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined />
</template>
<span>新建</span>
</a-button>
<ProjectSelectModel
:placeholder="`请选择项目`"
v-model:value="projectName"
@done="chooseProject"
/>
<!-- <a-radio-group v-model:value="searchStatus" @change="onStatus">-->
<!-- <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-group>-->
<a-range-picker
v-model:value="dateRange"
@change="onRange"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'userId'">
{{ `${record.nickname}` }}
</template>
<template v-if="column.key === 'images'">
<a-image :src="record.images" :width="120" />
</template>
<template v-if="column.key === 'longitude'">
{{ `${record.longitude}, ${record.latitude}` }}
</template>
<template v-if="column.key === 'confirmId'">
{{ `${record.confirmId > 0 ? record.confirmNickname : '-'}` }}
</template>
<template v-if="column.key === 'confirmStatus'">
<a-tag v-if="record.confirmStatus == 0" color="red">待确认</a-tag>
<a-tag v-if="record.confirmStatus == 1" color="green">已确认</a-tag>
</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>
<!-- 编辑弹窗 -->
<SecurityPlantEdit
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 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 {
SecurityPlant,
SecurityPlantParam
} from '@/api/tower/security-plant/model';
import {
pageSecurityPlant,
removeSecurityPlant
} from '@/api/tower/security-plant';
import SecurityPlantEdit from './components/security-plant-edit.vue';
import { Project } from '@/api/tower/project/model';
import { PlusOutlined } from '@ant-design/icons-vue';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '配件编号',
dataIndex: 'accessoryNo',
key: 'accessoryNo'
},
{
title: '生产厂家',
dataIndex: 'accessoryName',
key: 'accessoryName'
},
{
title: '配件分类',
dataIndex: 'accessoryCategory',
key: 'accessoryCategory'
},
{
title: '适用设备型号',
dataIndex: 'accessoryModel',
key: 'accessoryModel'
},
{
title: '配件规格',
dataIndex: 'accessorySpecs',
key: 'accessorySpecs'
},
{
title: '保养内容',
dataIndex: 'comments',
key: 'comments'
},
{
title: '操作人员',
dataIndex: 'userId',
key: 'userId',
width: 180
},
{
title: '确认人员',
dataIndex: 'confirmId',
key: 'confirmId',
width: 180
},
{
title: '确认状态',
dataIndex: 'confirmStatus',
key: 'confirmStatus',
width: 180
},
{
title: '创建时间',
dataIndex: 'createTime',
width: 180,
customRender: ({ text }) => toDateString(text)
}
]);
// 当前编辑数据
const current = ref<SecurityPlant | null>(null);
const searchText = ref('');
// 是否显示编辑弹窗
const showEdit = ref(false);
const projectName = ref('');
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
/* 搜索 */
const onRange = () => {
const [d1, d2] = dateRange.value ?? [];
reload({
createTimeStart: d1 ? d1 + ' 00:00:00' : '',
createTimeEnd: d2 ? d2 + ' 23:59:59' : ''
});
};
// 表格数据源
const datasource: DatasourceFunction = ({ where }) => {
if (searchText.value && searchText.value != '') {
where.keywords = searchText.value;
}
return pageSecurityPlant({ ...where });
};
/* 刷新表格 */
const reload = (where?: SecurityPlantParam) => {
tableRef?.value?.reload({ where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: SecurityPlant | null, id?: number) => {
current.value = row ?? null;
showEdit.value = true;
};
const search = (searchText) => {
reload({ keywords: searchText });
};
const chooseProject = (row: Project) => {
reload({ projectId: row.projectId });
};
const onStatus = (e: any) => {
console.log(e.target.value);
const status = e.target.value;
reload({ status });
};
/* 删除单个 */
const remove = (row: SecurityPlant) => {
const hide = messageLoading('请求中..', 0);
removeSecurityPlant(row.securityPlantId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 自定义行属性 */
const customRow = (plant: SecurityPlant) => {
return {
// 行点击事件
onClick: () => {
// console.log(plant);
},
// 行双击事件
onDblclick: () => {
openEdit(plant);
}
};
};
</script>
<script lang="ts">
export default {
name: 'TowerSecurityPlant'
};
</script>

View File

@@ -1,10 +1,10 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<template xmlns=""> <template>
<ele-modal <ele-modal
:width="500" :width="500"
:visible="visible" :visible="visible"
:confirm-loading="loading" :confirm-loading="loading"
:title="isUpdate ? '修改保养计划' : '新建保养计划'" :title="isUpdate ? '修改保养记录' : '新建保养记录'"
:body-style="{ paddingBottom: '8px' }" :body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible" @update:visible="updateVisible"
@ok="save" @ok="save"
@@ -22,18 +22,52 @@
<a-col <a-col
v-bind="styleResponsive ? { md: 22, sm: 24, xs: 24 } : { span: 12 }" v-bind="styleResponsive ? { md: 22, sm: 24, xs: 24 } : { span: 12 }"
> >
<a-form-item label="项目名称" name="name"> <a-form-item label="选择构件" name="projectName">
<ProjectSelectModel <TowerAccessory
:placeholder="`请选择项目`" :placeholder="`请选择构件`"
v-model:value="form.projectName" v-model:value="form.projectName"
@done="chooseProject" @done="chooseProject"
/> />
</a-form-item> </a-form-item>
<a-form-item label="所在地" name="address"> <a-form-item label="配件编号" name="accessoryNo">
<a-input <a-input
allow-clear allow-clear
placeholder="请输入项目地址" placeholder="请选择构件"
v-model:value="form.address" :disabled="true"
v-model:value="form.accessoryNo"
/>
</a-form-item>
<a-form-item label="配件分类" name="accessoryCategory">
<a-input
allow-clear
placeholder="请选择构件"
:disabled="true"
v-model:value="form.accessoryCategory"
/>
</a-form-item>
<a-form-item label="适用设备型号" name="accessoryModel">
<a-input
allow-clear
placeholder="请选择构件"
:disabled="true"
v-model:value="form.accessoryModel"
/>
</a-form-item>
<a-form-item label="配件规格" name="accessorySpecs">
<a-input
allow-clear
placeholder="请选择构件"
:disabled="true"
v-model:value="form.accessorySpecs"
/>
</a-form-item>
<a-form-item label="保养内容" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入保养内容"
v-model:value="form.comments"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@@ -50,8 +84,12 @@
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import useFormData from '@/utils/use-form-data'; import useFormData from '@/utils/use-form-data';
import type { Security } from '@/api/tower/security/model'; import type { Security } from '@/api/tower/security/model';
import { addSecurity, updateSecurity } from '@/api/tower/security'; import { Accessory } from '@/api/tower/accessory/model';
import { Project } from '@/api/tower/project/model'; import {
addSecurityRecord,
updateSecurityRecord
} from '@/api/tower/security-record';
import { SecurityRecord } from '@/api/tower/security-record/model';
// 是否开启响应式布局 // 是否开启响应式布局
const themeStore = useThemeStore(); const themeStore = useThemeStore();
@@ -76,11 +114,13 @@
const loading = ref(false); const loading = ref(false);
// 表单数据 // 表单数据
const { form, resetFields, assignFields } = useFormData<Security>({ const { form, resetFields, assignFields } = useFormData<SecurityRecord>({
securityRecordId: undefined,
securityId: undefined, securityId: undefined,
projectId: undefined, projectId: undefined,
projectName: undefined, projectName: undefined,
securityCode: undefined, securityCode: undefined,
accessoryCategory: undefined,
address: '', address: '',
status: 0, status: 0,
sortNumber: 100 sortNumber: 100
@@ -88,10 +128,10 @@
// 表单验证规则 // 表单验证规则
const rules = reactive<Record<string, Rule[]>>({ const rules = reactive<Record<string, Rule[]>>({
name: [ projectName: [
{ {
required: true, required: true,
message: '请输入设备名称', message: '请选择构件',
type: 'string', type: 'string',
trigger: 'blur' trigger: 'blur'
} }
@@ -134,7 +174,9 @@
const categoryForm = { const categoryForm = {
...form ...form
}; };
const saveOrUpdate = isUpdate.value ? updateSecurity : addSecurity; const saveOrUpdate = isUpdate.value
? updateSecurityRecord
: addSecurityRecord;
saveOrUpdate(categoryForm) saveOrUpdate(categoryForm)
.then((msg) => { .then((msg) => {
loading.value = false; loading.value = false;
@@ -155,11 +197,14 @@
emit('update:visible', value); emit('update:visible', value);
}; };
const chooseProject = (row: Project) => { const chooseProject = (row: Accessory) => {
console.log(row); form.projectId = row.accessoryId;
form.projectId = row.projectId; form.projectName = row.accessoryName;
form.projectName = row.projectName; form.securityId = row.accessoryId;
form.address = row.projectAddress; form.accessoryNo = row.accessoryNo;
form.accessorySpecs = row.accessorySpecs;
form.accessoryModel = row.accessoryModel;
form.accessoryCategory = row.accessoryCategory;
}; };
watch( watch(

View File

@@ -14,17 +14,23 @@
> >
<template #toolbar> <template #toolbar>
<a-space> <a-space>
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined />
</template>
<span>新建</span>
</a-button>
<ProjectSelectModel <ProjectSelectModel
:placeholder="`请选择项目`" :placeholder="`请选择项目`"
v-model:value="projectName" v-model:value="projectName"
@done="chooseProject" @done="chooseProject"
/> />
<a-radio-group v-model:value="searchStatus" @change="onStatus"> <!-- <a-radio-group v-model:value="searchStatus" @change="onStatus">-->
<a-radio-button value="0">正常</a-radio-button> <!-- <a-radio-button value="0">正常</a-radio-button>-->
<a-radio-button value="1">待修</a-radio-button> <!-- <a-radio-button value="1">待修</a-radio-button>-->
<a-radio-button value="2">异常已修</a-radio-button> <!-- <a-radio-button value="2">异常已修</a-radio-button>-->
<a-radio-button value="3">异常未修</a-radio-button> <!-- <a-radio-button value="3">异常未修</a-radio-button>-->
</a-radio-group> <!-- </a-radio-group>-->
<a-range-picker <a-range-picker
v-model:value="dateRange" v-model:value="dateRange"
@change="onRange" @change="onRange"
@@ -44,7 +50,7 @@
{{ `${record.longitude}, ${record.latitude}` }} {{ `${record.longitude}, ${record.latitude}` }}
</template> </template>
<template v-if="column.key === 'status'"> <template v-if="column.key === 'status'">
<a-tag v-if="record.status == 0">正常</a-tag> <a-tag v-if="record.status == 0" color="green">已保养</a-tag>
<a-tag v-if="record.status == 1" color="red">待修</a-tag> <a-tag v-if="record.status == 1" color="red">待修</a-tag>
<a-tag v-if="record.status == 2" color="green">异常已修</a-tag> <a-tag v-if="record.status == 2" color="green">异常已修</a-tag>
<a-tag v-if="record.status == 3" color="orange">异常未修</a-tag> <a-tag v-if="record.status == 3" color="orange">异常未修</a-tag>
@@ -93,6 +99,7 @@
} from '@/api/tower/security-record'; } from '@/api/tower/security-record';
import SecurityRecordEdit from './components/security-record-edit.vue'; import SecurityRecordEdit from './components/security-record-edit.vue';
import { Project } from '@/api/tower/project/model'; import { Project } from '@/api/tower/project/model';
import { PlusOutlined } from '@ant-design/icons-vue';
// 表格实例 // 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
@@ -100,31 +107,48 @@
// 表格列配置 // 表格列配置
const columns = ref<ColumnItem[]>([ const columns = ref<ColumnItem[]>([
{ {
title: '操作人', title: '配件编号',
dataIndex: 'userId', dataIndex: 'accessoryNo',
key: 'userId' key: 'accessoryNo'
}, },
{ {
title: '现场图片', title: '生产厂家',
dataIndex: 'images', dataIndex: 'accessoryName',
key: 'images' key: 'accessoryName'
}, },
{ {
title: '定位', title: '配件分类',
dataIndex: 'longitude', dataIndex: 'accessoryCategory',
key: 'longitude' key: 'accessoryCategory'
}, },
{ {
title: '备注说明', title: '适用设备型号',
dataIndex: 'accessoryModel',
key: 'accessoryModel'
},
{
title: '配件规格',
dataIndex: 'accessorySpecs',
key: 'accessorySpecs'
},
{
title: '保养内容',
dataIndex: 'comments', dataIndex: 'comments',
key: 'comments' key: 'comments'
}, },
{ {
title: '完成状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
key: 'status', key: 'status',
width: 180 width: 180
}, },
{
title: '保养人',
dataIndex: 'userId',
key: 'userId',
width: 180
},
{ {
title: '创建时间', title: '创建时间',
dataIndex: 'createTime', dataIndex: 'createTime',

View File

@@ -1,7 +1,7 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<template xmlns=""> <template xmlns="">
<ele-modal <ele-modal
:width="500" :width="1000"
:visible="visible" :visible="visible"
:confirm-loading="loading" :confirm-loading="loading"
:title="isUpdate ? '修改保养计划' : '新建保养计划'" :title="isUpdate ? '修改保养计划' : '新建保养计划'"
@@ -22,20 +22,45 @@
<a-col <a-col
v-bind="styleResponsive ? { md: 22, sm: 24, xs: 24 } : { span: 12 }" v-bind="styleResponsive ? { md: 22, sm: 24, xs: 24 } : { span: 12 }"
> >
<a-form-item label="项目名称" name="name"> <a-form-item label="项目名称" name="projectName">
<ProjectSelectModel <ProjectSelectModel
:placeholder="`请选择项目`" :placeholder="`请选择项目`"
v-model:value="form.projectName" v-model:value="form.projectName"
@done="chooseProject" @done="chooseProject"
/> />
</a-form-item> </a-form-item>
<a-form-item label="所在地" name="address"> <a-form-item label="所在地" name="address">
<a-input <a-input
allow-clear allow-clear
placeholder="请输入项目地址" placeholder="请输入项目地址"
v-model:value="form.address" v-model:value="form.address"
/>
</a-form-item>
<a-form-item label="现场图片" name="files">
<ele-image-upload
v-model:value="files"
:item-style="{ width: '90px', height: '90px' }"
:limit="20"
:upload-handler="uploadHandler"
@upload="onUpload"
/> />
</a-form-item> </a-form-item>
<a-form-item label="备注说明" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入备注说明"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">正常</a-radio>
<a-radio :value="1">待修</a-radio>
<a-radio :value="2">异常已修</a-radio>
<a-radio :value="3">异常未修</a-radio>
</a-radio-group>
</a-form-item>
</a-col> </a-col>
</a-row> </a-row>
</a-form> </a-form>
@@ -52,6 +77,8 @@
import type { Security } from '@/api/tower/security/model'; import type { Security } from '@/api/tower/security/model';
import { addSecurity, updateSecurity } from '@/api/tower/security'; import { addSecurity, updateSecurity } from '@/api/tower/security';
import { Project } from '@/api/tower/project/model'; import { Project } from '@/api/tower/project/model';
import type { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import { uploadFile } from "@/api/system/file";
// 是否开启响应式布局 // 是否开启响应式布局
const themeStore = useThemeStore(); const themeStore = useThemeStore();
@@ -74,6 +101,8 @@
const isUpdate = ref(false); const isUpdate = ref(false);
// 提交状态 // 提交状态
const loading = ref(false); const loading = ref(false);
// 已上传数据, 可赋初始值用于回显
const files = ref<ItemType[]>([]);
// 表单数据 // 表单数据
const { form, resetFields, assignFields } = useFormData<Security>({ const { form, resetFields, assignFields } = useFormData<Security>({
@@ -83,12 +112,14 @@
securityCode: undefined, securityCode: undefined,
address: '', address: '',
status: 0, status: 0,
sortNumber: 100 files: '',
sortNumber: 100,
comments: ''
}); });
// 表单验证规则 // 表单验证规则
const rules = reactive<Record<string, Rule[]>>({ const rules = reactive<Record<string, Rule[]>>({
name: [ projectName: [
{ {
required: true, required: true,
message: '请输入设备名称', message: '请输入设备名称',
@@ -122,6 +153,41 @@
] ]
}); });
/* 上传事件 */
const uploadHandler = (file: File) => {
const item: ItemType = {
file,
uid: (file as any).uid,
name: file.name
};
if (!file.type.startsWith('image')) {
message.error('只能选择图片');
return;
}
if (file.size / 1024 / 1024 > 2) {
message.error('大小不能超过 2MB');
return;
}
onUpload(item);
};
// 上传文件
const onUpload = (d: ItemType) => {
uploadFile(<File>d.file)
.then((result) => {
files.value.push({
uid: result.id,
url: result.url,
status: "done"
})
message.success('上传成功');
})
.catch((e) => {
message.error(e.message);
});
};
/* 保存编辑 */ /* 保存编辑 */
const save = () => { const save = () => {
if (!formRef.value) { if (!formRef.value) {
@@ -132,7 +198,8 @@
.then(() => { .then(() => {
loading.value = true; loading.value = true;
const categoryForm = { const categoryForm = {
...form ...form,
files: JSON.stringify(files.value)
}; };
const saveOrUpdate = isUpdate.value ? updateSecurity : addSecurity; const saveOrUpdate = isUpdate.value ? updateSecurity : addSecurity;
saveOrUpdate(categoryForm) saveOrUpdate(categoryForm)
@@ -170,6 +237,18 @@
assignFields({ assignFields({
...props.data ...props.data
}); });
files.value = [];
if (props.data.files) {
const arr = JSON.parse(props.data.files);
arr.map((d, i) => {
files.value.push({
uid: d.uid,
url: d.url,
status: 'done'
});
});
}
isUpdate.value = true; isUpdate.value = true;
} else { } else {
isUpdate.value = false; isUpdate.value = false;

View File

@@ -43,6 +43,19 @@
</a-space> </a-space>
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'userId'">
{{ `${record.nickname ? record.nickname : ''}` }}
</template>
<template v-if="column.key === 'files'">
<a-image-preview-group v-if="record.files">
<a-image
:width="70"
v-for="(item, index) in JSON.parse(record.files)"
:key="index"
:src="item.url"
/>
</a-image-preview-group>
</template>
<template v-if="column.key === 'status'"> <template v-if="column.key === 'status'">
<a-tag v-if="record.status == 0">正常</a-tag> <a-tag v-if="record.status == 0">正常</a-tag>
<a-tag v-if="record.status == 1" color="red">待修</a-tag> <a-tag v-if="record.status == 1" color="red">待修</a-tag>
@@ -117,7 +130,7 @@
key: 'projectName' key: 'projectName'
}, },
{ {
title: '保养编号', title: '检查编号',
dataIndex: 'securityCode', dataIndex: 'securityCode',
key: 'securityCode' key: 'securityCode'
}, },
@@ -128,11 +141,28 @@
showSorterTooltip: false, showSorterTooltip: false,
ellipsis: true ellipsis: true
}, },
{
title: '现场图片',
dataIndex: 'files',
width: 300,
key: 'files'
},
{
title: '操作人',
dataIndex: 'userId',
key: 'userId',
width: 120,
align: 'center',
showSorterTooltip: false,
ellipsis: true
},
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
key: 'status', key: 'status',
width: 180 width: 120,
align: 'center'
}, },
{ {
title: '生成时间', title: '生成时间',

View File

@@ -129,7 +129,7 @@
key: 'projectName' key: 'projectName'
}, },
{ {
title: '保养编号', title: '应急编号',
dataIndex: 'securityCode', dataIndex: 'securityCode',
key: 'securityCode' key: 'securityCode'
}, },