new-map
ihzero 2022-10-20 14:53:47 +08:00
parent 98f7ffd9b0
commit 1f265d6b85
17 changed files with 578 additions and 11535 deletions

View File

@ -1,12 +0,0 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
// The address does not exist
Error = '/error',
}
/**
* @description: Trigger ajax error
*/
export const fireErrorApi = () => defHttp.get({ url: Api.Error });

View File

@ -1,9 +0,0 @@
export interface BasicPageParams {
page: number;
pageSize: number;
}
export interface BasicFetchResult<T> {
items: T[];
total: number;
}

View File

@ -1,5 +0,0 @@
export interface UploadApiResult {
message: string;
code: number;
url: string;
}

View File

@ -0,0 +1,89 @@
import { defHttp } from '/@/utils/http/axios';
import { ErrorMessageMode } from '/#/axios';
/**
* @description:
*/
export function getDevices(params, mode: ErrorMessageMode = 'modal') {
return defHttp.get(
{
url: '/api/devices',
params,
},
{
errorMessageMode: mode,
},
);
}
/**
* @description:
*/
export function getDeviceTypes(mode: ErrorMessageMode = 'modal') {
return defHttp.get(
{
url: '/api/device-types',
},
{
errorMessageMode: mode,
},
);
}
/**
* @description:
*/
export function createDevice(data, mode: ErrorMessageMode = 'modal') {
return defHttp.post(
{
url: '/api/devices',
data,
},
{
errorMessageMode: mode,
},
);
}
/**
* @description:
*/
export function updateDevice(device, data, mode: ErrorMessageMode = 'modal') {
return defHttp.put(
{
url: `/api/devices/${device}`,
data,
},
{
errorMessageMode: mode,
},
);
}
/**
* @description:
*/
export function deleteDevice(device, mode: ErrorMessageMode = 'modal') {
return defHttp.delete(
{
url: `/api/devices/${device}`,
},
{
errorMessageMode: mode,
},
);
}
/**
* @description:
*/
export function getAgriculturalBasic(
params = { per_page: 999999, page: 1 },
mode: ErrorMessageMode = 'modal',
) {
return defHttp.get(
{
url: '/api/agricultural-basic',
params,
},
{
errorMessageMode: mode,
},
);
}

View File

@ -1,22 +0,0 @@
import { UploadApiResult } from './model/uploadModel';
import { defHttp } from '/@/utils/http/axios';
import { UploadFileParams } from '/#/axios';
import { useGlobSetting } from '/@/hooks/setting';
const { uploadUrl = '' } = useGlobSetting();
/**
* @description: Upload interface
*/
export function uploadApi(
params: UploadFileParams,
onUploadProgress: (progressEvent: ProgressEvent) => void,
) {
return defHttp.uploadFile<UploadApiResult>(
{
url: uploadUrl,
onUploadProgress,
},
params,
);
}

View File

@ -5,7 +5,7 @@ import { ErrorMessageMode } from '/#/axios';
enum Api {
Login = '/api/auth/login',
Logout = '/logout',
Logout = '/api/users/logout',
GetUserInfo = '/api/users/info',
GetPermCode = '/getPermCode',
}
@ -37,5 +37,5 @@ export function getPermCode() {
}
export function doLogout() {
return defHttp.get({ url: Api.Logout });
return defHttp.delete({ url: Api.Logout });
}

View File

@ -201,6 +201,10 @@
.@{prefix-cls} {
.ant-drawer-wrapper-body {
overflow: hidden;
display: flex;
flex-flow: column nowrap;
width: 100%;
height: 100%;
}
.ant-drawer-close {
@ -209,10 +213,19 @@
}
}
.ant-drawer-content {
overflow: hidden;
}
.ant-drawer-body {
height: calc(100% - @header-height);
padding: 0;
background-color: @component-background;
flex-grow: 1;
overflow: auto;
font-size: 14px;
line-height: 1.5715;
word-wrap: break-word;
.scrollbar__wrap {
padding: 16px !important;

View File

@ -6,7 +6,7 @@ const main: AppRouteModule = {
component: LAYOUT,
redirect: '/permission/front/page',
meta: {
orderNo: 16,
orderNo: 2,
icon: 'ion:key-outline',
title: '基础数据管理',
},

View File

@ -9,7 +9,7 @@ const dashboard: AppRouteModule = {
component: LAYOUT,
redirect: '/dashboard/analysis',
meta: {
orderNo: 10,
orderNo: 0,
icon: 'ion:grid-outline',
title: t('routes.dashboard.dashboard'),
},

View File

@ -0,0 +1,25 @@
import type { AppRouteModule } from '/@/router/types';
import { LAYOUT } from '/@/router/constant';
const main: AppRouteModule = {
path: '/device',
name: 'Device',
component: LAYOUT,
redirect: '/device/index',
meta: {
orderNo: 3,
icon: 'ion:key-outline',
title: '设备管理',
},
children: [
{
path: 'index',
name: 'DeviceManagement',
component: () => import('/@/views/device/management/index.vue'),
meta: {
title: '设备管理',
},
},
],
};
export default main;

View File

@ -7,7 +7,7 @@ const main: AppRouteModule = {
component: LAYOUT,
redirect: '/permission/front/page',
meta: {
orderNo: 15,
orderNo: 1,
icon: 'ion:key-outline',
title: t('routes.demo.main.meteorological'),
},

View File

@ -0,0 +1,25 @@
import type { AppRouteModule } from '/@/router/types';
import { LAYOUT } from '/@/router/constant';
const main: AppRouteModule = {
path: '/system',
name: 'System',
component: LAYOUT,
redirect: '/permission/front/page',
meta: {
orderNo: 4,
icon: 'ion:key-outline',
title: '系统管理',
},
children: [
{
path: 'management',
name: 'SystemManagement',
component: () => import('/@/views/system/management/index.vue'),
meta: {
title: '设备管理',
},
},
],
};
export default main;

View File

@ -124,7 +124,7 @@ export const useUserStore = defineStore({
},
async getUserInfoAction(): Promise<UserInfo | null> {
if (!this.getToken) return null;
const { info, permissions } = await getUserInfo();
const { info, permissions }: GetUserInfoModel = await getUserInfo();
const userInfo: UserInfo = Object.assign({}, info, { roles: permissions });
const { roles = [] } = userInfo;
if (isArray(roles)) {

View File

@ -0,0 +1,217 @@
<template>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
showFooter
:title="getTitle"
width="500px"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
<script lang="ts">
import { defineComponent, ref, computed, unref } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { FormSchema } from '/@/components/Table';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { getDeviceTypes, getAgriculturalBasic, createDevice } from '/@/api/sys/other';
import { defaultsDeep } from 'lodash-es';
const formSchema: FormSchema[] = [
{
field: 'type',
component: 'Select',
label: '设备类型',
required: true,
componentProps: {
placeholder: '',
options: [],
},
},
{
field: 'agricultural_base_id',
component: 'Select',
label: '基地',
required: true,
componentProps: {
placeholder: '',
options: [],
},
},
{
field: 'sn',
label: '设备编号',
required: true,
component: 'Input',
},
{
field: 'monitoring_point',
label: '监控点',
required: true,
component: 'Input',
},
{
field: 'extends.ip',
label: '设备IP',
required: true,
component: 'Input',
ifShow: ({ values }) => {
return !!(values.type == 1);
},
},
{
field: 'extends.port',
label: '设备端口',
required: true,
component: 'Input',
ifShow: ({ values }) => {
return !!(values.type == 1);
},
},
{
field: 'extends.rtsp_url',
label: 'RTSP地址',
required: true,
component: 'Input',
ifShow: ({ values }) => {
return !!(values.type == 1);
},
},
{
field: 'extends.username',
label: '设备登录名',
required: true,
component: 'Input',
ifShow: ({ values }) => {
return !!(values.type == 1);
},
},
{
field: 'extends.password',
label: '设备登录密码',
required: true,
component: 'Input',
ifShow: ({ values }) => {
return !!(values.type == 1);
},
},
{
field: 'extends.passage',
label: '设备播放通道',
required: true,
component: 'Input',
ifShow: ({ values }) => {
return !!(values.type == 1);
},
},
];
function formatDataByObject(obj): any[] {
const arr: any[] = [];
Object.keys(obj).forEach((e) => {
arr.push({
label: obj[e],
value: e,
});
});
return arr;
}
function formatDataByArray(arr, label = 'name', value = 'id'): any[] {
return arr.reduce((p, c) => {
p.push({
label: c[label],
value: c[value],
});
return p;
}, []);
}
function setValue(keys, value) {
const object = {};
var last = keys.pop();
keys.reduce((o, k) => (o[k] = o[k] || {}), object)[last] = value;
return object;
}
export default defineComponent({
name: 'RoleDrawer',
components: { BasicDrawer, BasicForm },
emits: ['success', 'register'],
setup(_, { emit }) {
const isUpdate = ref(true);
const deviceTypesData = ref<[]>([]);
const agriculturalBasicData = ref<[]>([]);
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema }] = useForm({
labelWidth: 110,
schemas: formSchema,
showActionButtonGroup: false,
});
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
setDrawerProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
if (unref(deviceTypesData).length === 0) {
deviceTypesData.value = await getDeviceTypes();
}
if (unref(agriculturalBasicData).length === 0) {
agriculturalBasicData.value = await getAgriculturalBasic();
}
updateSchema({
field: 'type',
componentProps: {
options: formatDataByObject(deviceTypesData.value),
},
});
updateSchema({
field: 'agricultural_base_id',
componentProps: {
options: formatDataByArray(agriculturalBasicData.value),
},
});
if (unref(isUpdate)) {
setFieldsValue({
...data.record,
});
}
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备'));
async function handleSubmit() {
try {
const values = await validate();
let params = {};
for (const key in values) {
params = defaultsDeep({}, params, setValue(key.split('.'), values[key]));
}
setDrawerProps({ confirmLoading: true });
if (!unref(isUpdate)) {
await createDevice(params);
} else {
await createDevice(params);
}
closeDrawer();
emit('success');
} finally {
setDrawerProps({ confirmLoading: false });
}
}
return {
registerForm,
registerDrawer,
getTitle,
handleSubmit,
};
},
});
</script>

View File

@ -0,0 +1,188 @@
<template>
<div dense>
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #toolbar>
<a-button type="primary" @click="handleCreate"></a-button>
</template>
<template #action="{ record }">
<TableAction
:actions="[
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
popConfirm: {
title: '是否确认删除',
placement: 'topRight',
confirm: handleDelete.bind(null, record),
},
},
]"
/>
</template>
</BasicTable>
<DeviceDrawer @register="registerDrawer" @success="handleSuccess" />
</div>
</template>
<script lang="ts">
// import { PageWrapper } from '/@/components/Page';
import { BasicTable, useTable } from '/@/components/Table';
import { Card } from 'ant-design-vue';
import { defineComponent, reactive } from 'vue';
import { getDevices } from '/@/api/sys/other';
import { BasicColumn, FormSchema, TableAction } from '/@/components/Table';
import { h } from 'vue';
import { Tag } from 'ant-design-vue';
import { useDrawer } from '/@/components/Drawer';
import DeviceDrawer from './DeviceDrawer.vue';
import { deleteDevice } from '/@/api/sys/other';
export const columns: BasicColumn[] = [
{
title: '类型',
dataIndex: 'type',
},
{
title: '设备编号',
dataIndex: 'sn',
},
{
title: '基地',
dataIndex: 'base_name',
},
{
title: '监控点',
dataIndex: 'monitoring_point',
},
{
title: '状态',
dataIndex: 'status',
customRender: ({ record }) => {
const status = record.status;
// : 0 , 1 线, 2 线, 3
const list = [
{
value: 0,
color: 'red',
label: '禁用',
},
{
value: 1,
color: 'green',
label: '在线',
},
{
value: 2,
color: 'pink',
label: '离线',
},
{
value: 3,
color: 'orange',
label: '故障',
},
];
const item = list.find((e) => e.value === status);
const color = item?.color ?? 'red';
const text = item?.label ?? status;
return h(Tag, { color: color }, () => text);
},
},
];
export const searchFormSchema: FormSchema[] = [
{
field: 'account',
label: '',
component: 'Input',
colProps: { span: 4 },
},
{
field: 'nickname',
label: '',
component: 'Input',
colProps: { span: 4 },
componentProps: {
placeholder: '请输入1',
},
},
];
export default defineComponent({
components: {
[Card.name]: Card,
BasicTable,
TableAction,
DeviceDrawer,
},
setup() {
const [registerDrawer, { openDrawer }] = useDrawer();
const searchInfo = reactive<Recordable>({});
const [registerTable, { reload, updateTableDataRecord }] = useTable({
api: getDevices,
rowKey: 'id',
columns,
formConfig: {
labelWidth: 0,
schemas: searchFormSchema,
autoSubmitOnEnter: true,
rowProps: { gutter: [16, 0] },
},
useSearchForm: true,
showTableSetting: false,
bordered: true,
handleSearchInfoFn(info) {
console.log('handleSearchInfoFn', info);
return info;
},
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
slots: { customRender: 'action' },
fixed: undefined,
},
});
function handleCreate() {
openDrawer(true, {
isUpdate: false,
});
}
function handleEdit(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
});
}
async function handleDelete(record: Recordable) {
try {
await deleteDevice(record.id);
} finally {
reload();
}
}
function handleSuccess() {
reload();
}
return {
searchInfo,
handleEdit,
handleDelete,
handleSuccess,
registerDrawer,
handleCreate,
registerTable,
};
},
});
</script>
<style scoped></style>

View File

@ -0,0 +1,15 @@
<template>
<div> 设备管理</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
return {};
},
});
</script>
<style scoped></style>

11481
yarn.lock

File diff suppressed because it is too large Load Diff