Explorar el Código

Merge branch 'develop' of http://192.168.11.14:51037/gitadmin/tuoheng_pilot_web into yufei

tags/v1.0.0
余菲 hace 2 años
padre
commit
d103054f04
Se han modificado 30 ficheros con 1780 adiciones y 30 borrados
  1. +2
    -2
      .env
  2. +59
    -0
      src/api/equipment/box.js
  3. +59
    -0
      src/api/equipment/mount.js
  4. +59
    -0
      src/api/equipment/uva.js
  5. +47
    -0
      src/api/system/user.js
  6. +3
    -3
      src/router/routes/modules/index.js
  7. +26
    -0
      src/utils/dictionary.js
  8. +2
    -1
      src/utils/http/interceptors.js
  9. +5
    -0
      src/utils/is.js
  10. +134
    -0
      src/views/equipment-library/box-manage/components/BoxModal.vue
  11. +82
    -2
      src/views/equipment-library/box-manage/index.vue
  12. +19
    -0
      src/views/equipment-library/box-manage/tools/form.js
  13. +14
    -0
      src/views/equipment-library/box-manage/tools/search.js
  14. +117
    -0
      src/views/equipment-library/box-manage/tools/table.js
  15. +0
    -17
      src/views/equipment-library/equipment-manage/index.vue
  16. +135
    -0
      src/views/equipment-library/mount-manage/components/MountModal.vue
  17. +97
    -0
      src/views/equipment-library/mount-manage/index.vue
  18. +21
    -0
      src/views/equipment-library/mount-manage/tools/form.js
  19. +14
    -0
      src/views/equipment-library/mount-manage/tools/search.js
  20. +124
    -0
      src/views/equipment-library/mount-manage/tools/table.js
  21. +144
    -0
      src/views/equipment-library/uva-manage/components/UVAModal.vue
  22. +83
    -3
      src/views/equipment-library/uva-manage/index.vue
  23. +26
    -0
      src/views/equipment-library/uva-manage/tools/form.js
  24. +14
    -0
      src/views/equipment-library/uva-manage/tools/search.js
  25. +122
    -0
      src/views/equipment-library/uva-manage/tools/table.js
  26. +140
    -0
      src/views/user-manage/components/UserModal.vue
  27. +56
    -2
      src/views/user-manage/index.vue
  28. +30
    -0
      src/views/user-manage/tools/form.js
  29. +14
    -0
      src/views/user-manage/tools/search.js
  30. +132
    -0
      src/views/user-manage/tools/table.js

+ 2
- 2
.env Ver fichero

@@ -1,8 +1,8 @@
# title
VITE_APP_TITLE = '河湖长眼'
VITE_APP_TITLE = '智飞'

# 端口号
VITE_PORT = 3000
VITE_PORT = 3050


VITE_SERVER = "/pilot/admin"

+ 59
- 0
src/api/equipment/box.js Ver fichero

@@ -0,0 +1,59 @@
import { defAxios as request } from '@/utils/http'

/**
* 获取云盒列表(分页)
* @param {Object}
* @returns
*/
export function boxPage(params) {
return request({
url: '/cloudBox/index',
method: 'get',
params
})
}

/**
* 获取云盒列表
* params
* @returns
*/
export function boxAll() {
return request({
url: '/cloudBox/getList',
method: 'get'
})
}

/**
* 创建盒子
* @returns
*/
export function boxCreate(data) {
return request({
url: '/cloudBox/add',
method: 'post',
data
})
}
/**
* 编辑盒子
* @returns
*/
export function boxUpdate(data) {
return request({
url: '/cloudBox/edit',
method: 'put',
data
})
}
/**
* 删除盒子
* @returns
*/
export function boxDelete(ids) {
return request({
url: `/cloudBox/delete/${ids}`,
method: 'delete'
})
}

+ 59
- 0
src/api/equipment/mount.js Ver fichero

@@ -0,0 +1,59 @@
import { defAxios as request } from '@/utils/http'

/**
* 获取挂载设备列表(分页)
* @param {Object}
* @returns
*/
export function mountPage(params) {
return request({
url: '/equipmentMount/index',
method: 'get',
params
})
}

/**
* 获取挂载设备
* params
* @returns
*/
export function mountAll() {
return request({
url: '/equipmentMount/getList',
method: 'get'
})
}

/**
* 创建挂载设备
* @returns
*/
export function mountCreate(data) {
return request({
url: '/equipmentMount/add',
method: 'post',
data
})
}
/**
* 编辑挂载设备
* @returns
*/
export function mountUpdate(data) {
return request({
url: '/equipmentMount/edit',
method: 'put',
data
})
}
/**
* 删除挂载设备
* @returns
*/
export function mountDelete(ids) {
return request({
url: `/equipmentMount/delete/${ids}`,
method: 'delete'
})
}

+ 59
- 0
src/api/equipment/uva.js Ver fichero

@@ -0,0 +1,59 @@
import { defAxios as request } from '@/utils/http'

/**
* 获取挂载设备列表(分页)
* @param {Object}
* @returns
*/
export function uvaPage(params) {
return request({
url: '/equipment/index',
method: 'get',
params
})
}

/**
* 获取挂载设备
* params
* @returns
*/
export function uvaAll() {
return request({
url: '/equipment/getList',
method: 'get'
})
}

/**
* 创建挂载设备
* @returns
*/
export function uvaCreate(data) {
return request({
url: '/equipment/add',
method: 'post',
data
})
}
/**
* 编辑挂载设备
* @returns
*/
export function uvaUpdate(data) {
return request({
url: '/equipment/edit',
method: 'put',
data
})
}
/**
* 删除挂载设备
* @returns
*/
export function uvaDelete(ids) {
return request({
url: `/equipment/delete/${ids}`,
method: 'delete'
})
}

+ 47
- 0
src/api/system/user.js Ver fichero

@@ -0,0 +1,47 @@
import { defAxios as request } from '@/utils/http'

/**
* 获取用户列表(分页)
* @param {Object}
* @returns
*/
export function userPage(params) {
return request({
url: '/user/index',
method: 'get',
params
})
}

/**
* 创建用户
* @returns
*/
export function userCreate(data) {
return request({
url: '/user/add',
method: 'post',
data
})
}
/**
* 编辑用户
* @returns
*/
export function userUpdate(data) {
return request({
url: '/user/edit',
method: 'put',
data
})
}
/**
* 删除用户
* @returns
*/
export function userDelete(ids) {
return request({
url: `/delete/${ids}`,
method: 'delete'
})
}

+ 3
- 3
src/router/routes/modules/index.js Ver fichero

@@ -70,12 +70,12 @@ export default [
}
},
{
path: 'equipment-manage',
component: () => import('@/views/equipment-library/equipment-manage/index.vue'),
path: 'mount-manage',
component: () => import('@/views/equipment-library/mount-manage/index.vue'),
name: 'EquipmentMount',
title: '挂载设备',
meta: {
title: '盒子管理',
title: '挂载设备',
role: ['admin']
}
},

+ 26
- 0
src/utils/dictionary.js Ver fichero

@@ -28,3 +28,29 @@ export const MENU_STATUS = [
{ label: '在用', value: 1 },
{ label: '停用', value: 2 }
]

export const ROLE_TYPE = [
{ label: '管理员', value: 1 },
{ label: '飞手', value: 2 }
]

export const EQUIPMENT_TYPE = [
{ label: '高清相机', value: 1 },
{ label: '多光谱相机', value: 2 },
{ label: '空中喊话', value: 3 },
{ label: '大功率照明', value: 4 },
{ label: '双光热成像相机', value: 5 },
{ label: '抛投钩', value: 6 },
{ label: '抛投绳', value: 7 },
{ label: '无人机喷火枪', value: 8 },
{ label: '灭火弹抛投器', value: 9 },
{ label: '气体采集盒', value: 10 },
{ label: '无人机取水器', value: 11 },
{ label: '其他', value: 12 }
]

export const POWER_TYPE = [
{ label: '电动', value: 1 },
{ label: '油动', value: 2 },
{ label: '混合', value: 3 }
]

+ 2
- 1
src/utils/http/interceptors.js Ver fichero

@@ -13,7 +13,8 @@ export function setupInterceptor(service) {
if (isWithoutToken(config)) {
return config
}
const token = getToken()
// const token = getToken()
const token = 'token'
if (token) {
config.headers.Authorization = token
return config

+ 5
- 0
src/utils/is.js Ver fichero

@@ -105,6 +105,11 @@ export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}

export function isPhone(phone) {
const reg = /^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57])[0-9]{8}$/
return reg.test(phone)
}

export const isServer = typeof window === 'undefined'

export const isClient = !isServer

+ 134
- 0
src/views/equipment-library/box-manage/components/BoxModal.vue Ver fichero

@@ -0,0 +1,134 @@
<template>
<Modal
:options="getModalOptions"
:on-positive-click="handleConfirm"
:on-negative-click="handleClose"
:on-close="handleClose"
>
<template #Context>
<n-form
ref="formRef"
:model="BoxForm"
:rules="BoxRules"
:label-width="80"
label-placement="left"
require-mark-placement="left"
:disabled="disabled"
>
<template v-for="(item,index) in getFormOptions" :key="index">
<n-form-item :label="item.label" :path="item.key">
<n-input v-if="item.type === 'input'" v-model:value="BoxForm[item.key]" v-bind="item.props" />
</n-form-item>
</template>
</n-form>
</template>
</Modal>
</template>

<script>
import { form } from '../tools/form.js'
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
import { boxCreate, boxUpdate } from '@/api/equipment/box.js'
import Modal from '@/components/Modal/index.vue'
export default defineComponent({
name: 'BoxModal',
components: { Modal },
props: {
visible: {
type: Boolean,
default: false
},
type: {
type: String,
default: 'create'
},
data: {
type: Object,
default: () => {}
}
},
emits: {
'update:visible': null,
'reload': null
},
setup(props, { emit }) {
const MODAL_TYPE = {
'create': '新建盒子信息',
'preview': '盒子详情',
'update': '编辑盒子信息'
}
const { BoxForm, BoxRules } = form
const formRef = ref()
const data = reactive({
BoxForm: {
...BoxForm,
...props.data
},
BoxRules: {
...BoxRules
},
disabled: props.type === 'preview'
})

const getModalOptions = computed(() => {
return {
title: MODAL_TYPE[props.type],
show: props.visible,
negativeText: '取消',
positiveText: '确认'
}
})

const getFormOptions = computed(() => {
return {
...form.formItem
}
})

function handleConfirm() {
formRef.value?.validate((errors) => {
if (!errors) {
const params = { ...data.BoxForm }
if (params.id) {
/* 编辑 */
boxUpdate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
} else {
/* 新增 */
boxCreate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
}
} else {
$message.error('请完善必填信息')
}
})
}

/* 关闭弹窗 */
const handleClose = () => {
emit('update:visible', false)
}

return {
...toRefs(data),
formRef,
getModalOptions,
getFormOptions,
handleConfirm,
handleClose
}
}
})
</script>
<style scoped lang='scss'>
</style>

+ 82
- 2
src/views/equipment-library/box-manage/index.vue Ver fichero

@@ -1,17 +1,97 @@
<template>
<div>
盒子管理
<n-card>
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
<data-table
ref="tableRef"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
size="large"
@update:checked-row-keys="handleCheck"
>
<template #tableTitle>
<n-button type="primary" @click="handleModal"> 新建 </n-button>
<n-popconfirm
negative-text="取消"
positive-text="确认"
@positive-click="handleDelete"
>
<template #trigger>
<n-button type="primary"> 删除 </n-button>
</template>
确认要删除选中数据吗?
</n-popconfirm>
</template>
</data-table>
</n-card>
</div>
<!-- 新增、编辑弹窗 -->
<BoxModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
</template>

<script>
import search from './tools/search.js'
import table from './tools/table.js'
import headSearch from '@/components/Search/index.vue'
import dataTable from '@/components/DataTable/index.vue'
import BoxModal from './components/BoxModal.vue'
import { ref, unref, toRefs, reactive, onUnmounted } from 'vue'
import { boxPage } from '@/api/equipment/box.js'

export default {
name: 'BoxManage',
components: { dataTable, BoxModal, headSearch },
setup() {
const data = reactive({
...toRefs(table),
search
})

const loadDataTable = async(res) => {
const _params = {
...unref(data.searchParams),
...res
}
return await boxPage(_params)
}

// 新增
function handleModal() {
data.rowData = null
data.modalType = 'create'
data.modalShow = true
}

const selectedIds = ref([])
function handleCheck(rowKeys) {
selectedIds.value = rowKeys
}

function handleDelete() {
if (selectedIds.value.length) {
data.deleteData(selectedIds.value)
} else {
$message.warning('请至少选中一条数据')
}
}

onUnmounted(() => {
data.searchParams = null
})

return {
...toRefs(data),
loadDataTable,
handleModal,
handleDelete,
handleCheck
}
}
}

</script>
<style scoped lang='scss'>
.n-button + .n-button {
margin-left: 10px;
}
</style>

+ 19
- 0
src/views/equipment-library/box-manage/tools/form.js Ver fichero

@@ -0,0 +1,19 @@
import { reactive } from 'vue'

export const form = reactive({
BoxForm: {
boxSn: null,
boxName: null,
streamCode: null
},
BoxRules: {
boxSn: [{ required: true, message: '请输入设备编号', trigger: 'blur' }],
boxName: [{ required: true, message: '请输入盒子名称', type: 'string', trigger: 'blur' }],
streamCode: [{ required: true, type: 'number', message: '请输入通道编码', trigger: 'blur' }]
},
formItem: [
{ type: 'input', key: 'boxSn', label: '设备编号', props: { maxlength: '20', placeholder: '请输入设备编号', clearable: true }},
{ type: 'input', key: 'boxName', label: '盒子名称', props: { maxlength: '20', placeholder: '请输入盒子名称', clearable: true }},
{ type: 'input', key: 'streamCode', label: '通道编码', props: { maxlength: '20', placeholder: '请输入通道编码', clearable: true }}
]
})

+ 14
- 0
src/views/equipment-library/box-manage/tools/search.js Ver fichero

@@ -0,0 +1,14 @@
import { reactive } from 'vue'

const data = reactive([
{
label: '盒子名称',
key: 'boxName',
props: {
placeholder: '请输入盒子名称'
}
}
])

export default data


+ 117
- 0
src/views/equipment-library/box-manage/tools/table.js Ver fichero

@@ -0,0 +1,117 @@
import { h, ref, reactive } from 'vue'
import TableAction from '@/components/DataTable/tools/Action.vue'
import { boxDelete } from '@/api/equipment/box.js'

/* 注册table */
const tableRef = ref()
const searchParams = ref()

function handleSearch(params) {
searchParams.value = { ...params }
tableRef.value.reFetch({ searchParams })
}

/**
* @description: 获取数据及操作
* @param {*} row 单行数据
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
* @return {*}
*/
function getRowData(row, type) {
data.rowData = row
data.modalType = type
data.modalShow = true
}

// 删除接口
function deleteData(data) {
boxDelete(data)
.then((res) => {
if (res.code === 0) {
handleSearch()
}
})
.catch((e) => {
console.log(e)
})
}

const data = reactive({
tableRef,
searchParams,
rowData: {},
modalType: 'create',
modalShow: false,
configModalShow: false,
handleSearch,
deleteData,
columns: [
{ type: 'selection' },
{
title: '设备编号',
key: 'boxSn',
align: 'center'
},
{
title: '盒子名称',
key: 'boxName',
align: 'center'
},
{
title: '通道编码',
key: 'streamCode',
align: 'center',
Minwidth: 160
},
{
title: '创建时间',
key: 'createTime',
align: 'center',
Minwidth: 160
},
{
title: '创建人',
key: 'createUser',
align: 'center',
width: 100
},
{
title: '操作',
align: 'center',
width: 150,
fixed: 'right',
render(row) {
return h(TableAction, {
actions: [
{
label: '编辑',
type: 'button',
props: {
type: 'primary',
text: true,
onClick: getRowData.bind(null, row, 'update')
},
auth: 'basic_list'
},
{
label: '删除',
type: 'popconfirm',
auth: 'basic_list',
tip: '确定删除这条数据吗?',
props: {
onPositiveClick: deleteData.bind(null, [row.id])
},
ButtonProps: {
text: true,
type: 'primary'
}
}
],
align: 'center'
})
}
}
]
})

export default data

+ 0
- 17
src/views/equipment-library/equipment-manage/index.vue Ver fichero

@@ -1,17 +0,0 @@
<template>
<div>
挂载设备
</div>
</template>

<script>
export default {
name: 'EquipmentManage',
setup() {

}
}

</script>
<style scoped lang='scss'>
</style>

+ 135
- 0
src/views/equipment-library/mount-manage/components/MountModal.vue Ver fichero

@@ -0,0 +1,135 @@
<template>
<Modal
:options="getModalOptions"
:on-positive-click="handleConfirm"
:on-negative-click="handleClose"
:on-close="handleClose"
>
<template #Context>
<n-form
ref="formRef"
:model="mountForm"
:rules="mountRules"
:label-width="80"
label-placement="left"
require-mark-placement="left"
:disabled="disabled"
>
<template v-for="(item,index) in getFormOptions" :key="index">
<n-form-item :label="item.label" :path="item.key">
<n-input v-if="item.type === 'input'" v-model:value="mountForm[item.key]" v-bind="item.props" />
<n-select v-if="item.type === 'select'" v-model:value="mountForm[item.key]" v-bind="item.props" />
</n-form-item>
</template>
</n-form>
</template>
</Modal>
</template>

<script>
import { form } from '../tools/form.js'
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
import { mountCreate, mountUpdate } from '@/api/equipment/mount.js'
import Modal from '@/components/Modal/index.vue'
export default defineComponent({
name: 'MountModal',
components: { Modal },
props: {
visible: {
type: Boolean,
default: false
},
type: {
type: String,
default: 'create'
},
data: {
type: Object,
default: () => {}
}
},
emits: {
'update:visible': null,
'reload': null
},
setup(props, { emit }) {
const MODAL_TYPE = {
'create': '新建盒子信息',
'preview': '盒子详情',
'update': '编辑盒子信息'
}
const { mountForm, mountRules } = form
const formRef = ref()
const data = reactive({
mountForm: {
...mountForm,
...props.data
},
mountRules: {
...mountRules
},
disabled: props.type === 'preview'
})

const getModalOptions = computed(() => {
return {
title: MODAL_TYPE[props.type],
show: props.visible,
negativeText: '取消',
positiveText: '确认'
}
})

const getFormOptions = computed(() => {
return {
...form.formItem
}
})

function handleConfirm() {
formRef.value?.validate((errors) => {
if (!errors) {
const params = { ...data.mountForm }
if (params.id) {
/* 编辑 */
mountUpdate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
} else {
/* 新增 */
mountCreate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
}
} else {
$message.error('请完善必填信息')
}
})
}

/* 关闭弹窗 */
const handleClose = () => {
emit('update:visible', false)
}

return {
...toRefs(data),
formRef,
getModalOptions,
getFormOptions,
handleConfirm,
handleClose
}
}
})
</script>
<style scoped lang='scss'>
</style>

+ 97
- 0
src/views/equipment-library/mount-manage/index.vue Ver fichero

@@ -0,0 +1,97 @@
<template>
<div>
<n-card>
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
<data-table
ref="tableRef"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
size="large"
@update:checked-row-keys="handleCheck"
>
<template #tableTitle>
<n-button type="primary" @click="handleModal"> 新建 </n-button>
<n-popconfirm
negative-text="取消"
positive-text="确认"
@positive-click="handleDelete"
>
<template #trigger>
<n-button type="primary"> 删除 </n-button>
</template>
确认要删除选中数据吗?
</n-popconfirm>
</template>
</data-table>
</n-card>
</div>
<!-- 新增、编辑弹窗 -->
<MountModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
</template>

<script>
import search from './tools/search.js'
import table from './tools/table.js'
import headSearch from '@/components/Search/index.vue'
import dataTable from '@/components/DataTable/index.vue'
import MountModal from './components/MountModal.vue'
import { ref, unref, toRefs, reactive, onUnmounted } from 'vue'
import { mountPage } from '@/api/equipment/mount.js'

export default {
name: 'BoxManage',
components: { dataTable, MountModal, headSearch },
setup() {
const data = reactive({
...toRefs(table),
search
})

const loadDataTable = async(res) => {
const _params = {
...unref(data.searchParams),
...res
}
return await mountPage(_params)
}

// 新增
function handleModal() {
data.rowData = null
data.modalType = 'create'
data.modalShow = true
}

const selectedIds = ref([])
function handleCheck(rowKeys) {
selectedIds.value = rowKeys
}

function handleDelete() {
if (selectedIds.value.length) {
data.deleteData(selectedIds.value)
} else {
$message.warning('请至少选中一条数据')
}
}

onUnmounted(() => {
data.searchParams = null
})

return {
...toRefs(data),
loadDataTable,
handleModal,
handleDelete,
handleCheck
}
}
}
</script>
<style scoped lang='scss'>
.n-button + .n-button {
margin-left: 10px;
}
</style>

+ 21
- 0
src/views/equipment-library/mount-manage/tools/form.js Ver fichero

@@ -0,0 +1,21 @@
import { reactive } from 'vue'
import { EQUIPMENT_TYPE } from '@/utils/dictionary.js'

export const form = reactive({
mountForm: {
code: null,
name: null,
type: null
},
mountRules: {
boxSn: [{ required: true, message: '请输入设备编号', trigger: 'blur' }],
name: [{ required: true, message: '请输入盒子名称', type: 'string', trigger: 'blur' }],
type: [{ required: true, type: 'number', message: '请输入通道编码', trigger: 'blur' }]
},
formItem: [
{ type: 'input', key: 'code', label: '设备编号', props: { maxlength: '20', placeholder: '请输入设备编号', clearable: true }},
{ type: 'input', key: 'name', label: '盒子名称', props: { maxlength: '20', placeholder: '请输入盒子名称', clearable: true }},
{ type: 'select', key: 'type', label: '设备类型', props: { options: EQUIPMENT_TYPE, clearable: true }},
{ type: 'input', key: 'note', label: '备注', props: { type: 'textarea', autosize: { maxlength: '200', minRows: 3, maxRows: 3 }}}
]
})

+ 14
- 0
src/views/equipment-library/mount-manage/tools/search.js Ver fichero

@@ -0,0 +1,14 @@
import { reactive } from 'vue'

const data = reactive([
{
label: '设备名称',
key: 'name',
props: {
placeholder: '请输入设备名称'
}
}
])

export default data


+ 124
- 0
src/views/equipment-library/mount-manage/tools/table.js Ver fichero

@@ -0,0 +1,124 @@
import { h, ref, reactive } from 'vue'
import TableTags from '@/components/DataTable/tools/Tags.vue'
import TableAction from '@/components/DataTable/tools/Action.vue'
import { mountDelete } from '@/api/equipment/mount.js'
import { EQUIPMENT_TYPE } from '@/utils/dictionary.js'

/* 注册table */
const tableRef = ref()
const searchParams = ref()

function handleSearch(params) {
searchParams.value = { ...params }
tableRef.value.reFetch({ searchParams })
}

/**
* @description: 获取数据及操作
* @param {*} row 单行数据
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
* @return {*}
*/
function getRowData(row, type) {
data.rowData = row
data.modalType = type
data.modalShow = true
}

// 删除接口
function deleteData(data) {
mountDelete(data)
.then((res) => {
if (res.code === 0) {
handleSearch()
}
})
.catch((e) => {
console.log(e)
})
}

const data = reactive({
tableRef,
searchParams,
rowData: {},
modalType: 'create',
modalShow: false,
configModalShow: false,
handleSearch,
deleteData,
columns: [
{ type: 'selection' },
{
title: '设备编号',
key: 'code',
align: 'center'
},
{
title: '设备名称',
key: 'name',
align: 'center'
},
{
title: '设备类型',
key: 'type',
align: 'center',
render(row) {
return h(TableTags, {
data: row.type,
filters: EQUIPMENT_TYPE
})
}
},
{
title: '创建时间',
key: 'createTime',
align: 'center',
Minwidth: 160
},
{
title: '创建人',
key: 'createUser',
align: 'center',
width: 100
},
{
title: '操作',
align: 'center',
width: 150,
fixed: 'right',
render(row) {
return h(TableAction, {
actions: [
{
label: '编辑',
type: 'button',
props: {
type: 'primary',
text: true,
onClick: getRowData.bind(null, row, 'update')
},
auth: 'basic_list'
},
{
label: '删除',
type: 'popconfirm',
auth: 'basic_list',
tip: '确定删除这条数据吗?',
props: {
onPositiveClick: deleteData.bind(null, [row.id])
},
ButtonProps: {
text: true,
type: 'primary'
}
}
],
align: 'center'
})
}
}
]
})

export default data

+ 144
- 0
src/views/equipment-library/uva-manage/components/UVAModal.vue Ver fichero

@@ -0,0 +1,144 @@
<template>
<Modal
:options="getModalOptions"
:on-positive-click="handleConfirm"
:on-negative-click="handleClose"
:on-close="handleClose"
>
<template #Context>
<n-form
ref="formRef"
:model="uvaForm"
:rules="uvaRules"
:label-width="80"
label-placement="left"
require-mark-placement="left"
:disabled="disabled"
>
<template v-for="(item,index) in getFormOptions" :key="index">
<n-form-item :label="item.label" :path="item.key">
<n-input v-if="item.type === 'input'" v-model:value="uvaForm[item.key]" v-bind="item.props" />
<n-select v-if="item.type === 'select'" v-model:value="uvaForm[item.key]" v-bind="item.props" />
<n-input-number v-if="item.type === 'number'" v-model:value="uvaForm[item.key]" v-bind="item.props">
<template v-if="item.suffix" #suffix>
{{ item.suffix }}
</template>
</n-input-number>
</n-form-item>
</template>
</n-form>
</template>
</Modal>
</template>

<script>
import { form } from '../tools/form.js'
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
import { uvaCreate, uvaUpdate } from '@/api/equipment/uva.js'
import Modal from '@/components/Modal/index.vue'
export default defineComponent({
name: 'UvaModal',
components: { Modal },
props: {
visible: {
type: Boolean,
default: false
},
type: {
type: String,
default: 'create'
},
data: {
type: Object,
default: () => {}
}
},
emits: {
'update:visible': null,
'reload': null
},
setup(props, { emit }) {
const MODAL_TYPE = {
'create': '新建盒子信息',
'preview': '盒子详情',
'update': '编辑盒子信息'
}
const { uvaForm, uvaRules } = form
const formRef = ref()
const data = reactive({
uvaForm: {
...uvaForm,
...props.data
},
uvaRules: {
...uvaRules
},
disabled: props.type === 'preview'
})

const getModalOptions = computed(() => {
return {
title: MODAL_TYPE[props.type],
show: props.visible,
negativeText: '取消',
positiveText: '确认'
}
})

const getFormOptions = computed(() => {
return {
...form.formItem
}
})

function handleConfirm() {
formRef.value?.validate((errors) => {
if (!errors) {
const params = { ...data.uvaForm }
if (params.id) {
/* 编辑 */
uvaUpdate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
} else {
/* 新增 */
uvaCreate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
}
} else {
$message.error('请完善必填信息')
}
})
}

/* 关闭弹窗 */
const handleClose = () => {
emit('update:visible', false)
}

return {
...toRefs(data),
formRef,
getModalOptions,
getFormOptions,
handleConfirm,
handleClose
}
}
})
</script>

<style scoped lang='scss'>
.n-input-number{
width: 100%;
}
</style>

+ 83
- 3
src/views/equipment-library/uva-manage/index.vue Ver fichero

@@ -1,17 +1,97 @@
<template>
<div>
无人机管理
<n-card>
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
<data-table
ref="tableRef"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
size="large"
@update:checked-row-keys="handleCheck"
>
<template #tableTitle>
<n-button type="primary" @click="handleModal"> 新建 </n-button>
<n-popconfirm
negative-text="取消"
positive-text="确认"
@positive-click="handleDelete"
>
<template #trigger>
<n-button type="primary"> 删除 </n-button>
</template>
确认要删除选中数据吗?
</n-popconfirm>
</template>
</data-table>
</n-card>
</div>
<!-- 新增、编辑弹窗 -->
<UVAModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
</template>

<script>
import search from './tools/search.js'
import table from './tools/table.js'
import headSearch from '@/components/Search/index.vue'
import dataTable from '@/components/DataTable/index.vue'
import UVAModal from './components/UVAModal.vue'
import { ref, unref, toRefs, reactive, onUnmounted } from 'vue'
import { uvaPage } from '@/api/equipment/uva.js'

export default {
name: 'UVAManage',
name: 'BoxManage',
components: { dataTable, UVAModal, headSearch },
setup() {
const data = reactive({
...toRefs(table),
search
})

const loadDataTable = async(res) => {
const _params = {
...unref(data.searchParams),
...res
}
return await uvaPage(_params)
}

// 新增
function handleModal() {
data.rowData = null
data.modalType = 'create'
data.modalShow = true
}

const selectedIds = ref([])
function handleCheck(rowKeys) {
selectedIds.value = rowKeys
}

function handleDelete() {
if (selectedIds.value.length) {
data.deleteData(selectedIds.value)
} else {
$message.warning('请至少选中一条数据')
}
}

onUnmounted(() => {
data.searchParams = null
})

return {
...toRefs(data),
loadDataTable,
handleModal,
handleDelete,
handleCheck
}
}
}

</script>
<style scoped lang='scss'>
.n-button + .n-button {
margin-left: 10px;
}
</style>

+ 26
- 0
src/views/equipment-library/uva-manage/tools/form.js Ver fichero

@@ -0,0 +1,26 @@
import { reactive } from 'vue'
import { POWER_TYPE } from '@/utils/dictionary.js'

export const form = reactive({
uvaForm: {
code: null,
name: null,
powerType: null,
accuracy: null,
manufacturer: null
},
uvaRules: {
code: [{ required: true, message: '请输入设备编号', trigger: 'blur' }],
name: [{ required: true, message: '请输入盒子名称', type: 'string', trigger: 'blur' }],
powerType: [{ required: true, type: 'number', message: '请选择动力类型', trigger: 'blur' }],
accuracy: [{ required: true, type: 'number', message: '请输入定位精度', trigger: 'blur' }],
manufacturer: [{ required: true, message: '请输入生产厂家', trigger: 'blur' }]
},
formItem: [
{ type: 'input', key: 'code', label: '设备编号', props: { maxlength: '20', placeholder: '请输入设备编号', clearable: true }},
{ type: 'input', key: 'name', label: '设备名称', props: { maxlength: '20', placeholder: '请输入盒子名称', clearable: true }},
{ type: 'select', key: 'powerType', label: '动力类型', props: { options: POWER_TYPE, clearable: true }},
{ type: 'number', key: 'accuracy', label: '定位精度', props: { min: 0, placeholder: '请输入通道编码', showButton: false, clearable: true }, suffix: '米' },
{ type: 'input', key: 'manufacturer', label: '生产厂家', props: { maxlength: '20', placeholder: '请输入生产厂家', clearable: true }}
]
})

+ 14
- 0
src/views/equipment-library/uva-manage/tools/search.js Ver fichero

@@ -0,0 +1,14 @@
import { reactive } from 'vue'

const data = reactive([
{
label: '设备名称',
key: 'name',
props: {
placeholder: '请输入设备名称'
}
}
])

export default data


+ 122
- 0
src/views/equipment-library/uva-manage/tools/table.js Ver fichero

@@ -0,0 +1,122 @@
import { h, ref, reactive } from 'vue'
import TableTags from '@/components/DataTable/tools/Tags.vue'
import TableAction from '@/components/DataTable/tools/Action.vue'
import { uvaDelete } from '@/api/equipment/uva.js'
import { POWER_TYPE } from '@/utils/dictionary.js'

/* 注册table */
const tableRef = ref()
const searchParams = ref()

function handleSearch(params) {
searchParams.value = { ...params }
tableRef.value.reFetch({ searchParams })
}

/**
* @description: 获取数据及操作
* @param {*} row 单行数据
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
* @return {*}
*/
function getRowData(row, type) {
data.rowData = row
data.modalType = type
data.modalShow = true
}

// 删除接口
function deleteData(data) {
uvaDelete(data)
.then((res) => {
if (res.code === 0) {
handleSearch()
}
})
.catch((e) => {
console.log(e)
})
}

const data = reactive({
tableRef,
searchParams,
rowData: {},
modalType: 'create',
modalShow: false,
configModalShow: false,
handleSearch,
deleteData,
columns: [
{ type: 'selection' },
{
title: '设备编号',
key: 'code',
align: 'center'
},
{
title: '设备名称',
key: 'name',
align: 'center'
},
{
title: '动力类型',
key: 'powerType',
align: 'center',
render(row) {
return h(TableTags, {
data: row.powerType,
filters: POWER_TYPE
})
}
},
{
title: '定位精度',
key: 'accuracy',
align: 'center'
},
{
title: '生产厂家',
key: 'manufacturer',
align: 'center'
},
{
title: '操作',
align: 'center',
width: 150,
fixed: 'right',
render(row) {
return h(TableAction, {
actions: [
{
label: '编辑',
type: 'button',
props: {
type: 'primary',
text: true,
onClick: getRowData.bind(null, row, 'update')
},
auth: 'basic_list'
},
{
label: '删除',
type: 'popconfirm',
auth: 'basic_list',
tip: '确定删除这条数据吗?',
props: {
onPositiveClick: deleteData.bind(null, [row.id])
},
ButtonProps: {
text: true,
type: 'primary'
}
}
],
align: 'center'
})
}
}
]
})

export default data

+ 140
- 0
src/views/user-manage/components/UserModal.vue Ver fichero

@@ -0,0 +1,140 @@
<template>
<Modal
:options="getModalOptions"
:on-positive-click="handleConfirm"
:on-negative-click="handleClose"
:on-close="handleClose"
>
<template #Context>
<n-form
ref="formRef"
:model="userForm"
:rules="userRules"
:label-width="80"
label-placement="left"
require-mark-placement="left"
:disabled="disabled"
>
<template v-for="(item,index) in getFormOptions" :key="index">
<n-form-item :label="item.label" :path="item.key">
<n-input v-if="item.type === 'input'" v-model:value="userForm[item.key]" v-bind="item.props" />
<n-select v-if="item.type === 'select'" v-model:value="userForm[item.key]" v-bind="item.props" />
</n-form-item>
</template>
</n-form>
</template>
</Modal>
</template>

<script>
import { form } from '../tools/form.js'
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
import { userCreate, userUpdate } from '@/api/system/user.js'
import Modal from '@/components/Modal/index.vue'
export default defineComponent({
name: 'UserModal',
components: { Modal },
props: {
visible: {
type: Boolean,
default: false
},
type: {
type: String,
default: 'create'
},
data: {
type: Object,
default: () => {}
}
},
emits: {
'update:visible': null,
'reload': null
},
setup(props, { emit }) {
const MODAL_TYPE = {
'create': '新建盒子信息',
'preview': '盒子详情',
'update': '编辑盒子信息'
}
const { userForm, userRules } = form
const formRef = ref()
const data = reactive({
userForm: {
...userForm,
...props.data
},
userRules: {
...userRules
},
disabled: props.type === 'preview'
})

const getModalOptions = computed(() => {
return {
title: MODAL_TYPE[props.type],
show: props.visible,
negativeText: '取消',
positiveText: '确认'
}
})

const getFormOptions = computed(() => {
const formOptions = [
...form.formItem
]
if (props.type !== 'create') {
formOptions.splice(4, 1)
}
return formOptions
})

function handleConfirm() {
formRef.value?.validate((errors) => {
if (!errors) {
const params = { ...data.userForm }
if (params.id) {
/* 编辑 */
delete params['password']
userUpdate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
} else {
/* 新增 */
userCreate(params)
.then(res => {
if (res.code === 0) {
emit('reload')
handleClose()
}
})
}
} else {
$message.error('请完善必填信息')
}
})
}

/* 关闭弹窗 */
const handleClose = () => {
emit('update:visible', false)
}

return {
...toRefs(data),
formRef,
getModalOptions,
getFormOptions,
handleConfirm,
handleClose
}
}
})
</script>
<style scoped lang='scss'>
</style>

+ 56
- 2
src/views/user-manage/index.vue Ver fichero

@@ -1,17 +1,71 @@
<template>
<div>
人员管理
<n-card>
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
<data-table
ref="tableRef"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
size="large"
>
<template #tableTitle>
<n-button type="primary" @click="handleModal"> 新建 </n-button>
</template>
</data-table>
</n-card>
</div>
<!-- 新增、编辑弹窗 -->
<UserModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
</template>

<script>
import search from './tools/search.js'
import table from './tools/table.js'
import headSearch from '@/components/Search/index.vue'
import dataTable from '@/components/DataTable/index.vue'
import UserModal from './components/UserModal.vue'
import { unref, toRefs, reactive, onUnmounted } from 'vue'
import { userPage } from '@/api/system/user.js'

export default {
name: 'UserManage',
components: { dataTable, UserModal, headSearch },
setup() {
const data = reactive({
...toRefs(table),
search
})

const loadDataTable = async(res) => {
const _params = {
...unref(data.searchParams),
...res
}
return await userPage(_params)
}

// 新增
function handleModal() {
data.rowData = null
data.modalType = 'create'
data.modalShow = true
}

onUnmounted(() => {
data.searchParams = null
})

return {
...toRefs(data),
loadDataTable,
handleModal
}
}
}

</script>
<style scoped lang='scss'>
.n-button + .n-button {
margin-left: 10px;
}
</style>

+ 30
- 0
src/views/user-manage/tools/form.js Ver fichero

@@ -0,0 +1,30 @@
import { reactive } from 'vue'
import { ROLE_TYPE } from '@/utils/dictionary.js'
import { isPhone } from '@/utils/is.js'

export const form = reactive({
userForm: {
realname: null,
mobile: null,
type: null,
username: null,
password: null
},
userRules: {
realname: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
mobile: [
// { required: true, message: '请输入联系电话', type: 'string', trigger: 'blur' },
{ required: true, message: '请输入正确的联系电话', pattern: /^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57])[0-9]{8}$/, trigger: 'blur' }
],
type: [{ required: true, type: 'number', message: '请选择身份', trigger: 'blur' }],
username: [{ required: true, message: '请输入帐号', trigger: 'blur' }],
password: [{ required: true, message: '请输入初始密码', trigger: 'blur' }]
},
formItem: [
{ type: 'input', key: 'realname', label: '姓名', props: { maxlength: '20', placeholder: '请输入姓名', clearable: true }},
{ type: 'input', key: 'mobile', label: '联系电话', props: { maxlength: '20', placeholder: '请输入联系电话', clearable: true }},
{ type: 'select', key: 'type', label: '身份选择', props: { options: ROLE_TYPE, clearable: true }},
{ type: 'input', key: 'username', label: '帐号', props: { maxlength: '20', placeholder: '请输入帐号', clearable: true }},
{ type: 'input', key: 'password', label: '初始密码', props: { maxlength: '20', placeholder: '请输入初始密码', clearable: true }}
]
})

+ 14
- 0
src/views/user-manage/tools/search.js Ver fichero

@@ -0,0 +1,14 @@
import { reactive } from 'vue'

const data = reactive([
{
label: '设备名称',
key: 'name',
props: {
placeholder: '请输入设备名称'
}
}
])

export default data


+ 132
- 0
src/views/user-manage/tools/table.js Ver fichero

@@ -0,0 +1,132 @@
import { h, ref, reactive } from 'vue'
import TableTags from '@/components/DataTable/tools/Tags.vue'
import TableSwitch from '@/components/DataTable/tools/Switch.vue'
import TableAction from '@/components/DataTable/tools/Action.vue'
import { ROLE_TYPE } from '@/utils/dictionary.js'
import { userUpdate } from '@/api/system/user.js'

/* 注册table */
const tableRef = ref()
const searchParams = ref()

function handleSearch(params) {
searchParams.value = { ...params }
tableRef.value.reFetch({ searchParams })
}

/**
* @description: 获取数据及操作
* @param {*} row 单行数据
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
* @return {*}
*/
function getRowData(row, type) {
data.rowData = row
data.modalType = type
data.modalShow = true
}

// 设置状态
function changeStatus(row) {
userUpdate({ id: row.data.id, status: row.value }).then(res => {
if (res.code === 0) {
handleSearch()
}
}).catch(e => {
console.log(e)
})
}

const data = reactive({
tableRef,
searchParams,
rowData: {},
modalType: 'create',
modalShow: false,
configModalShow: false,
handleSearch,
columns: [
{
title: '序号',
key: 'key',
render: (_, index) => {
return `${index + 1}`
},
align: 'center',
width: 100
},
{
title: '角色',
key: 'type',
align: 'center',
render(row) {
return h(TableTags, {
data: row.type,
filters: ROLE_TYPE
})
}
},
{
title: '姓名',
key: 'realname',
align: 'center'
},
{
title: '手机号',
key: 'mobile',
align: 'center',
Minwidth: 160
},
{
title: '任务次数',
key: 'taskCount',
align: 'center',
Minwidth: 160
},
{
title: '上次登录时间',
key: 'loginTime',
align: 'center'
},
{
title: '状态',
key: 'status',
align: 'center',
width: 100,
render(row) {
return h(TableSwitch, {
data: { id: row.id, status: row.status },
rowKey: 'status',
checkedValue: 1,
uncheckedValue: 2,
onChange: changeStatus.bind(row)
})
}
},
{
title: '操作',
align: 'center',
width: 150,
fixed: 'right',
render(row) {
return h(TableAction, {
actions: [
{
label: '编辑',
type: 'button',
props: {
type: 'primary',
text: true,
onClick: getRowData.bind(null, row, 'update')
},
auth: 'basic_list'
}
],
align: 'center'
})
}
}
]
})

export default data

Cargando…
Cancelar
Guardar