Compare commits

...

3 Commits

22 changed files with 678 additions and 35 deletions

3
.env
View File

@ -5,7 +5,6 @@ VITE_APP_TITLE = '智慧河长'
VITE_PORT = 3000
# VITE_SERVER = "/hhz/admin/api"
VITE_SERVER = ""
VITE_SERVER = "/hhz/admin"
VITE_PLATFORM = "tuoheng-hhz-admin"

View File

@ -12,5 +12,4 @@ VITE_APP_GLOB_BASE_API = '/api'
VITE_AUTHORITY = 'http://192.168.11.11:8090'
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
VITE_REDIRECT_URI = 'http://192.168.11.11:8086/login'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='

View File

@ -5,7 +5,7 @@ VITE_PUBLIC_PATH = '/'
VITE_APP_USE_MOCK = false
# proxy
VITE_PROXY = [["/api-local","http://127.0.0.1:8002/api"],["/api-mock","http://127.0.0.1:8003"]]
VITE_PROXY = [["/api-local","http://127.0.0.1:8002"],["/api-mock","http://127.0.0.1:8003"]]
# base api
VITE_APP_GLOB_BASE_API = '/api-local'
@ -15,5 +15,4 @@ VITE_APP_GLOB_BASE_API_MOCK = '/api-mock'
VITE_AUTHORITY = 'http://192.168.11.11:8090'
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
VITE_REDIRECT_URI = 'http://192.168.12.8:3000/login'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='

View File

@ -12,5 +12,4 @@ VITE_APP_GLOB_BASE_API = '/api'
VITE_AUTHORITY = 'https://oidc.t-aaron.com'
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
VITE_REDIRECT_URI = 'https://dsp-portal.t-aaron.com/login'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='

View File

@ -10,7 +10,6 @@ VITE_PROXY = [["/api","http://192.168.11.241:9011/api"]]
# base api
VITE_APP_GLOB_BASE_API = '/api'
VITE_AUTHORITY = 'https://oidc.test.t-aaron.com'
VITE_AUTHORITY = 'https://login-test.t-aaron.com/'
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
VITE_REDIRECT_URI = 'http://192.168.11.241:8086/login'
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='

View File

@ -20,10 +20,11 @@ export const refreshToken = () => {
* @param {String} roleId 角色Id
* @return {*}
*/
export const fetchPermission = (roleId) => {
export const fetchPermission = (params) => {
return request({
url: `/permission/getRolePermission/${roleId}`,
method: 'GET'
url: `/permission/getRolePermission/`,
method: 'GET',
params
})
}

12
src/api/common/index.js Normal file
View File

@ -0,0 +1,12 @@
import { defAxios as request } from '@/utils/http'
/**
* @description: 获取问题列表数据
* @return {Object}
*/
export function getQuestionTree() {
return request({
url: '/question/getTree',
method: 'get'
})
}

24
src/api/report/river.js Normal file
View File

@ -0,0 +1,24 @@
import { defAxios as request } from '@/utils/http'
/**
* @description: 分页查询巡河报告列表
* @return {*}
*/
export function fetchReportList(params) {
return request({
url: '/reportPatrol/indexNew',
method: 'get',
params
})
}
/**
* @description: 获取报告详情
* @return {*}
*/
export function reportDetail(params) {
return request({
url: '/report/detail',
method: 'get',
params
})
}

View File

@ -1,11 +1,3 @@
/*
* @Author: whyafterme
* @Date: 2022-11-03 11:31:21
* @LastEditTime: 2022-11-21 09:02:20
* @LastEditors: whyafterme
* @Description:
* @FilePath: \new\src\router\guard\permission-guard.js
*/
import { useUserStore } from '@/store/modules/user'
import { usePermissionStore } from '@/store/modules/permission'
import { NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '@/router/routes'

View File

@ -102,7 +102,7 @@ export const usePermissionStore = defineStore('permission', {
},
async generateRoutes(roleId) {
try {
const res = await fetchPermission(roleId)
const res = await fetchPermission({ roleId, clientId: 'tuoheng-hhz-admin' })
// const res = await fetchPermission(3)
if (res.code === 0) {
const { opMenusList, permissionsList } = res.data

View File

@ -15,8 +15,7 @@ export function setupInterceptor(service) {
const userInfo = await getUserInfo()
if (userInfo) {
const { token_type, access_token } = userInfo
// config.headers.Authorization = `${token_type} ${access_token}`
config.headers.Authorization = '70aa58b4-dda7-446d-8cbf-8e6d6ab89a02'
config.headers.Authorization = `${token_type} ${access_token}`
const { VITE_CLIENT_ID } = import.meta.env
config.headers['Client-Id'] = VITE_CLIENT_ID
return config

View File

@ -4,7 +4,7 @@ let oidcManager = null
export const initServe = () => {
if (oidcManager) return oidcManager
const { VITE_AUTHORITY, VITE_CLIENT_ID, VITE_CLIENT_SECRET, VITE_REDIRECT_URI } = import.meta.env
const { VITE_AUTHORITY, VITE_CLIENT_ID, VITE_CLIENT_SECRET } = import.meta.env
oidcManager = new UserManager({
/* 认证服务器 */
authority: VITE_AUTHORITY,
@ -12,8 +12,8 @@ export const initServe = () => {
client_id: VITE_CLIENT_ID,
client_secret: VITE_CLIENT_SECRET,
/* 回调客户端页面 */
redirect_uri: VITE_REDIRECT_URI,
post_logout_redirect_uri: VITE_REDIRECT_URI,
redirect_uri: `${window.location.origin}/login`,
post_logout_redirect_uri: `${window.location.origin}/login`,
response_type: 'code',
/* 授权范围 */
scope: 'openid profile',

View File

@ -34,7 +34,7 @@ export default {
return item.clientId === VITE_CLIENT_ID
})
if (authority && (authority.includes(VITE_PLATFORM) || authority.includes('admin'))) {
fetchPermission(roleId)
fetchPermission({ roleId, clientId: 'tuoheng-hhz-admin' })
.then(res => {
const { opMenusList } = res.data
const path = opMenusList[0].path

View File

@ -0,0 +1,81 @@
<template>
<n-drawer v-bind="getDrawerOptions">
<n-drawer-content :title="getDrawerOptions.title">
<ResultReport v-if="getDrawerOptions.show" :report-id="getPatrolId" />
</n-drawer-content>
</n-drawer>
</template>
<script>
import { defineComponent, watch, computed, reactive, toRefs } from 'vue'
import ResultReport from './ResultReport.vue'
export default defineComponent({
name: 'ReportDrawer',
components: { ResultReport },
props: {
/* 可见 */
visible: {
type: Boolean,
default: false
},
type: {
type: String,
default: 'river'
},
/* 选中的数据 */
data: {
type: Object,
default: () => {}
}
},
emits: {
'update:visible': null
},
setup(props, { emit }) {
const DRAWER_TYPE = {
'river': '巡河报告',
'result': '处理结果'
}
/* 获取抽屉的信息 */
const getDrawerOptions = computed(() => {
return {
title: DRAWER_TYPE[props.type],
show: props.visible,
trapFocus: false,
width: '100%',
placement: 'right'
}
})
const getPatrolId = computed(() => {
return props.data.patrolId
})
/**
* @description: 返回
* @return {*}
*/
function handleBack() {
emit('update:visible', false)
}
return {
getDrawerOptions,
getPatrolId,
handleBack
}
}
})
</script>
<style scoped lang='scss'>
.draw-button{
text-align: center;
line-height: 40px;
margin-top: 40px;
.n-button+.n-button{
margin-left: 30px;
}
}
</style>

View File

@ -0,0 +1,336 @@
<template>
<div id="pdfCentent">
<!-- 河道信息 -->
<div class="report__container">
<div class="report__title">河道信息</div>
<ul class="report__table">
<li v-for="(item, index) in streamList" :key="index" class="table__item">
<div class="item__title">{{ item.label }}</div>
<div class="item__content"><span>{{ reportMessage[item.key] }}</span></div>
</li>
</ul>
</div>
<div class="report__container">
<div class="report__title">巡检信息</div>
<ul class="report__table">
<li v-for="(item, index) in inspectionList" :key="index" class="table__item">
<div class="item__title">{{ item.label }}</div>
<div v-if="item.options" class="item__content">
<span>{{ item.options[reportMessage[item.key]] }}</span>
</div>
<div v-else class="item__content">{{ reportMessage[item.key] }}</div>
</li>
</ul>
</div>
<div class="report__container">
<div class="report__title">巡检结果</div>
<div class="report__table is--merge">
<div class="merge__header">
<div class="header__item">项目</div>
<div class="header__item">巡检内容</div>
<div class="header__item">巡检监测结果</div>
</div>
<div class="merge__table">
<ul class="table__container">
<li v-for="(item, index) in resultList" :key="index" class="table__content" style="margin-top: -1px;">
<span class="merge__title">{{ item.name }}</span>
<ul>
<li v-for="(cItem, cIndex) in item.type" :key="cIndex" class="merge__item" style="margin-bottom: -1px;">
<span v-if="cItem.content.length" class="merge__name">{{ cItem.name }}</span>
<ul v-if="cItem.content.length">
<li v-for="(sItem,sIndex) in cItem.content" :key="sIndex" class="content-item">
<div class="inspection-content" style="margin-right: -1px;">{{ sItem.content }}</div>
<div class="inspection-result">{{ filterResult(sItem.code) }}</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<!-- 问题清单 -->
<!-- <div v-show="imageList.length" class="report__container">
<div class="report__title">问题清单</div>
<ul class="image-list">
<li v-for="(item, index) in imageList" :key="index" class="image-item">
<div class="lon-lat image-index">
问题{{ index+1 }}
</div>
<div class="lon-lat">
<div class="position-label">
<span>坐标</span>
</div>
<div class="position-value">
<span>{{ item.longitude }}, {{ item.latitude }}</span>
</div>
</div>
<div class="lon-lat">
<div class="position-label">
<span>问题描述</span>
</div>
<div class="position-value">
<span>{{ item.content }}</span>
</div>
</div>
<div class="lon-lat">
<div class="position-image-lable">
<span>问题图片</span>
</div>
<div class="position-value">
<img class="problem-img" :src="item.fileImage" alt="">
</div>
</div>
<div class="lon-lat image-index">
处理结果
</div>
<div class="lon-lat">
<div class="position-label">
<span>处理人</span>
</div>
<div class="position-value">
<span>{{ item.handerName }}</span>
</div>
</div>
<div class="lon-lat">
<div class="position-label">
<span>处理时间</span>
</div>
<div class="position-value">
<span>{{ item.handTime }}</span>
</div>
</div>
<div class="lon-lat">
<div class="position-label">
<span>备注</span>
</div>
<div class="position-value">
<span>{{ item.handContent }}</span>
</div>
</div>
<div v-for="(i, j) in item.handImg" :key="j" class="lon-lat">
<div class="position-image-lable">
<span>结果图片</span>
<span v-show="item.handImg.length>1">{{ j+1 }}</span>
</div>
<div class="position-value">
<img class="result-img" :src="i" alt="">
</div>
</div>
</li>
</ul>
</div> -->
<!-- <div class="download_box">
<a-button :loading="downloadFlag" class="export-btn" type="primary" @click="exportReport">下载</a-button>
</div> -->
</div>
</template>
<script>
import { reportDetail } from '@/api/report/river.js'
import { getQuestionTree } from '@/api/common/index.js'
import { defineComponent, watch, computed, reactive, toRefs } from 'vue'
export default defineComponent({
name: 'ResultReport',
props: {
reportId: {
type: [String, Number],
default: null
}
},
setup(props, { emit }) {
const data = reactive({
streamList: [
{ label: '责任单位', key: 'streamArea' },
{ label: '河道名称', key: 'streamName' },
{ label: '河段长(公里)', key: 'streamLength' },
{ label: '巡检里程(公里)', key: 'streamLength' },
{ label: '起讫位置', key: 'streamLocation' }
],
inspectionList: [
{ label: '天气情况', key: 'weather' },
{ label: '巡查人数', key: 'inspectionPeopleCount' },
{ label: '巡查人员', key: 'flightHandName' },
{ label: '巡查方式', key: 'inspectionWay', options: { 1: '无人机', 2: '机场', 3: '人工' }},
{ label: '巡查设备', key: 'inspectionDevice' },
{ label: '巡查日期', key: 'inspectionTime' },
{ label: '飞行高度', key: 'flightHeight' },
{ label: '巡查类型', key: 'inspectionType', options: { 1: '常规巡河', 2: '其它' }},
{ label: '问题点数量', key: 'questionCount' }
],
resultList: [],
reportMessage: {}
})
const queryResult = (async() => {
const res = await getQuestionTree({ reportId: props.reportId })
if (res.code === 0) {
data.resultList = res.data
}
})()
const queryDetail = (async() => {
const res = await reportDetail({ reportId: props.reportId })
if (res.code === 0) {
data.reportMessage = res.data
}
})()
const filterResult = (code) => {
const list = data.reportMessage?.inspectionResult || []
const result = list.find((item) => {
return item.code === code
})
return result?.totalCount
}
return {
...toRefs(data),
queryResult,
queryDetail,
filterResult
}
}
})
</script>
<style scoped lang='scss'>
*{
box-sizing: border-box;
}
.report__container {
width: 100%;
padding: 0 30px 20px 30px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
.report__title {
width: 100%;
padding: 10px 0;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
font-weight: 600;
}
.report__table {
border-top: 1px solid rgba(220,223,230,1);
border-left: 1px solid rgba(220,223,230,1);
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
width: 800px;
&.is--merge{
align-items: flex-start;
.merge__header{
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
}
.header__item{
padding: 6px;
text-align: center;
background: rgba(245,247,250,1);
&:nth-child(1){
width: 171px;
border-bottom: 1px solid rgba(220,223,230,1);
}
&:nth-child(2){
flex: 1;
border-left: 1px solid rgba(220,223,230,1);
border-right: 1px solid rgba(220,223,230,1);
}
&:nth-child(3){
width: 160px;
border-right: 1px solid rgba(220,223,230,1);
}
}
}
.table__item {
display: flex;
justify-content: center;
align-items: stretch;
width: 100%;
}
.item__title {
width: 40%;
background: rgba(245,247,250,1);
height: 30px;
text-align: center;
line-height: 30px;
border-right: 1px solid rgba(220,223,230,1);
border-bottom: 1px solid rgba(220,223,230,1);
}
.item__content {
width: 60%;
height: 30px;
text-align: center;
line-height: 30px;
border-right: 1px solid rgba(220,223,230,1);
border-bottom: 1px solid rgba(220,223,230,1);
}
}
.merge__table{
width: 100%;
.table__container{
margin-bottom: 0;
.table__content{
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
border-right: 1px solid rgba(220,223,230,1);
border-bottom: 1px solid rgba(220,223,230,1);
.merge__title{
width: 70px;
text-align: center;
}
ul{
flex: 1;
flex-shrink: 0;
}
.merge__item{
display: flex;
justify-content: flex-start;
align-items: center;
border-top: 1px solid rgba(220,223,230,1);
border-left: 1px solid rgba(220,223,230,1);
}
.merge__name{
width: 100px;
text-align: center;
}
.content-item {
display: flex;
justify-content: flex-start;
align-items: center;
}
.inspection-content {
flex: 1;
flex-shrink: 0;
height: 30px;
line-height: 30px;
text-align: center;
border-left: 1px solid rgba(220,223,230,1);
border-right: 1px solid rgba(220,223,230,1);
border-bottom: 1px solid rgba(220,223,230,1);
}
.inspection-result {
width: 160px;
height: 30px;
line-height: 30px;
text-align: center;
border-bottom: 1px solid rgba(220,223,230,1);
}
}
}
}
}
</style>

View File

@ -0,0 +1,25 @@
<!--
* @Author: whyafterme
* @Date: 2022-11-23 15:41:37
* @LastEditTime: 2022-11-23 15:45:22
* @LastEditors: whyafterme
* @Description:
* @FilePath: \new\src\views\reports\river-report\components\RiverReport.vue
-->
<template>
<div>
1
</div>
</template>
<script>
export default {
name: 'RiverReport',
setup() {
}
}
</script>
<style scoped lang='scss'>
</style>

View File

@ -1,17 +1,60 @@
<template>
<div>
报告管理
<n-card>
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
<data-table
ref="tableRef"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
:scroll-x="1200"
size="large"
/>
</n-card>
</div>
<!-- 新增编辑弹窗 -->
<ReportDrawer v-model:visible="drawerShow" :type="drawerType" :data="rowData" />
</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 ReportDrawer from './components/ReportDrawer.vue'
import { fetchReportList } from '@/api/report/river.js'
import { unref, toRefs, reactive, onUnmounted } from 'vue'
export default {
name: 'RiverReports',
components: { dataTable, ReportDrawer, headSearch },
setup() {
const data = reactive({
...toRefs(table),
search
})
const loadDataTable = async(res) => {
const _params = {
...unref(data.searchParams),
...res
}
return await fetchReportList(_params)
}
onUnmounted(() => {
data.searchParams = null
})
return {
...toRefs(data),
loadDataTable
}
}
}
</script>
<style scoped lang='scss'>
.n-button + .n-button {
margin-left: 10px;
}
</style>

View File

@ -0,0 +1,28 @@
import { reactive } from 'vue'
const data = reactive([
{
label: '报告编码',
key: 'reportNo',
props: {
placeholder: '请输入报告编码'
}
},
{
label: '任务编码',
key: 'inspectionCode',
props: {
placeholder: '请输入任务编码'
}
},
{
label: '任务名称',
key: 'inspectionName',
props: {
placeholder: '请输入任务名称'
}
}
])
export default data

View File

@ -0,0 +1,107 @@
import { h, ref, reactive } from 'vue'
import TableAction from '@/components/DataTable/tools/Action.vue'
/* 注册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.drawerType = type
data.drawerShow = true
}
const data = reactive({
tableRef,
searchParams,
rowData: {},
drawerType: 'create',
drawerShow: false,
handleSearch,
columns: [
{
title: '任务编码',
key: 'inspectionCode',
align: 'center',
width: 200
},
{
title: '任务名称',
key: 'inspectionName',
align: 'center',
ellipsis: {
tooltip: true
},
width: 400
},
{
title: '巡检河道',
key: 'streamName',
align: 'center',
width: 200
},
{
title: '巡检时间',
key: 'inspectionTime',
align: 'center',
width: 200
},
{
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, 'preview')
// },
// auth: 'basic_list'
// },
{
label: '巡河报告',
type: 'button',
props: {
type: 'primary',
text: true,
onClick: getRowData.bind(null, row, 'river')
},
auth: 'basic_list'
},
{
label: '处理结果',
type: 'button',
props: {
type: 'primary',
text: true,
onClick: getRowData.bind(null, row, 'result')
},
auth: 'basic_list'
}
],
align: 'center'
})
}
}
]
})
export default data

View File

@ -21,7 +21,7 @@ function handleSearch(params) {
* @return {*}
*/
function getRowData(row, type) {
data.rowData = type === 'create' ? { pid: row.id } : row
data.rowData = row || {}
data.modalType = type
data.modalShow = true
}

View File

@ -25,7 +25,7 @@ export const form = reactive({
{ type: 'input', key: 'guide', label: '公告摘要', props: { maxlength: '20', placeholder: '请输入公告摘要', clearable: true }},
{ type: 'editor', key: 'content', label: '通知内容', props: { height: 300 }}
{ type: 'editor', key: 'content', label: '通知内容', props: { height: 350 }}
]
})

View File

@ -22,7 +22,7 @@ function handleSearch(params) {
* @return {*}
*/
function getRowData(row, type) {
data.rowData = type === 'create' ? { pid: row.id } : row
data.rowData = row || {}
data.modalType = type
data.modalShow = true
}