feat: 我的看板

main
许宏杰 2 months ago
parent 47c74ff7fd
commit ef86b9c093

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

@ -20,8 +20,8 @@ export enum EditEnum {
export enum PageEnum {
// 登录
BASE_LOGIN = '/chat/1745227092138',
BASE_LOGIN_NAME = 'chat',
BASE_LOGIN = '/ai',
BASE_LOGIN_NAME = 'ai',
//重定向
REDIRECT = '/redirect',

@ -5,7 +5,9 @@ import { PageEnum } from '@/enums/pageEnum'
import { GoReload } from '@/components/GoReload'
export const LoginRoute: RouteRecordRaw = {
path:'/ai',
// path: PageEnum.BASE_LOGIN,
// name: PageEnum.BASE_LOGIN_NAME,
path: '/ai',
name: 'ai',
component: () => import('@/views/AI/index.vue'),
meta: {
@ -13,18 +15,19 @@ export const LoginRoute: RouteRecordRaw = {
},
children: [
{
path: '/',
redirect: '/chat/1745227092138'
},
{
path: '/chat/:id',
name: 'chat',
component: () => import('@/views/AI/chat/index.vue')
path: '',
redirect: '/myBoard'
},
{
path: '/board/:id',
name: 'board',
component: () => import('@/views/chart/index.vue')
},
{
path: '/myBoard',
name: 'myBoard',
component: () => import('@/views/AI/myBoard/index.vue')
}
]
}

@ -8,7 +8,8 @@ const routerAllowList = [
PageEnum.BASE_LOGIN_NAME,
// 预览
PreviewEnum.CHART_PREVIEW_NAME,
'board'
'board',
'myBoard'
]
export function createRouterGuards(router: Router) {
@ -27,10 +28,9 @@ export function createRouterGuards(router: Router) {
if (isErrorPage === -1) {
next({ name: PageEnum.ERROR_PAGE_NAME_404 })
}
// @ts-ignore
if (!routerAllowList.includes(to.name) && !loginCheck()) {
next({ name: PageEnum.BASE_LOGIN_NAME })
next({ name: 'myBoard' })
}
next()
})

@ -0,0 +1,14 @@
@font-face {
font-family: "DingTalk JinBuTi-Regular";
src: url("./font/YouSheBiaoTiHei-2.ttf");
}
@font-face {
font-family: "AlibabaPuHuiTi-Regular";
src: url("./font/AlibabaSans-Regular.otf");
}
@font-face {
font-family: "AlibabaPuHuiTi-Medium";
src: url("./font/AlibabaSans-Medium.otf");
}

@ -1,3 +1,6 @@
@import url('./font.css');
//
// logo
.amap-logo {

@ -96,12 +96,12 @@ const getMessageInfo = id => {
onMounted(() => {
fetchList()
messageList()
// messageList()
})
defineExpose({
fetchList,
messageList
// messageList
})
</script>

@ -1,7 +1,10 @@
<template>
<div class="ai-logo">
<img src="~@/assets/images/ai/ai-logo.png" alt="" class="logo-img" />
<span class="logo-title">AI助手</span>
<div class="logo-title">
<span >亨通数科BI</span>
<span >智能看板驾驶舱</span>
</div>
</div>
</template>
@ -13,15 +16,23 @@
align-items: center;
justify-content: center;
margin-bottom: 50px;
gap: 10px;
.logo-img {
height: 36px;
width: 36px;
margin-right: 10px;
height: 42px;
width: 42px;
}
.logo-title {
font-size: 28px;
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 20px;
color: #ffffff;
font-weight: 400;
font-family: "DingTalk JinBuTi-Regular";
span{
display: inline-block;
line-height: 21px;
}
}
}
</style>

@ -11,16 +11,30 @@
:key="index"
@click="handlerPath(item.path, index)"
>
<n-icon size="20">
<n-icon size="20" v-show="item.id === 1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path
d="M368.5 240H272v-96.5c0-8.8-7.2-16-16-16s-16 7.2-16 16V240h-96.5c-8.8 0-16 7.2-16 16 0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7H240v96.5c0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7 8.8 0 16-7.2 16-16V272h96.5c8.8 0 16-7.2 16-16s-7.2-16-16-16z"
/>
</svg> </n-icon
>新建{{ item.name }}
</svg>
</n-icon>
<n-icon size="20" v-show="item.id === 2">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
<defs></defs>
<circle cx="22" cy="24" r="2" fill="currentColor"></circle>
<path
d="M29.777 23.479A8.64 8.64 0 0 0 22 18a8.64 8.64 0 0 0-7.777 5.479L14 24l.223.521A8.64 8.64 0 0 0 22 30a8.64 8.64 0 0 0 7.777-5.479L30 24zM22 28a4 4 0 1 1 4-4a4.005 4.005 0 0 1-4 4z"
fill="currentColor"
></path>
<path
d="M12 28H7V7h3v3h12V7h3v9h2V7a2 2 0 0 0-2-2h-3V4a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v1H7a2 2 0 0 0-2 2v21a2 2 0 0 0 2 2h5zm0-24h8v4h-8z"
fill="currentColor"
></path>
</svg>
</n-icon>
{{ item.name }}
</div>
</div>
<ai-history ref="history"></ai-history>
</div>
<div class="right-container">
<router-view :key="route.fullPath"></router-view>
@ -33,11 +47,11 @@ import { useRoute, useRouter } from 'vue-router'
import { createProjectApi, historyMessageRoom, historyMessageRoomUpdata } from '@/api/path'
import { getUUID } from '@/utils'
import { ResultEnum } from '@/enums/httpEnum'
import { AiLogo, AiHistory } from './components'
import { AiLogo } from './components'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const chartEditStore = useChartEditStore()
import { ref } from 'vue'
import { onMounted, ref } from 'vue'
import useMessageRoomStore from '@/store/modules/messageRoom'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
@ -48,45 +62,15 @@ const route = useRoute()
const history = ref(null)
const menuList = [
{ name: '聊天', path: '/chat' },
{ name: '数据看板', path: '/board' }
{ id: 1, name: '新建数据看板', path: 'board' },
{ id: 2, name: '查看我的看板', path: 'myBoard' }
]
const ehcatrsType = ['pie', 'line', 'bar']
const getCurrentRoute = path => {
return route.path.includes(path)
}
const saveMessage = async path => {
//
if (useMessageRoom.messageRoom.content.length > 0) {
useMessageRoom.messageRoom.content.forEach(instance => {
if (ehcatrsType.includes(instance.type) && instance.chartInstanceItem) {
instance.chartInstanceItem.dispose()
}
})
const jsonData = JSON.stringify(useMessageRoom.messageRoom.content)
let res
try {
if (useMessageRoom.messageRoom.id) {
res = await historyMessageRoomUpdata({ content: jsonData, id: useMessageRoom.messageRoom.id })
} else {
res = await historyMessageRoom({ content: jsonData, createUserId: systemStore.userInfo.userId || 1 })
}
if (res && res.code == 200) {
useMessageRoom.resetList({ id: undefined, createUserId: undefined, content: [] }) //
history.value.messageList()
router.push(path + '/' + Date.now())
}
} catch {
console.log('保存出错')
router.push(path + '/' + Date.now())
}
} else {
router.push(path + '/' + Date.now())
}
}
const handlerBoard = async path => {
const handlerBoard = async (path = 'board') => {
try {
//
const res = await createProjectApi({
@ -99,23 +83,23 @@ const handlerBoard = async path => {
})
if (res && res.code === ResultEnum.SUCCESS) {
const { id } = res.data
router.push(path + '/' + id)
router.push(`/${path}/` + id)
}
} catch (error) {
window['$message'].error(window['$t']('project.create_failure'))
}
}
const handlerPath = (path, index) => {
history.value.fetchList()
chartEditStore.setComponentList()
chartEditStore.setEdit(false)
onMounted(() => {
// handlerBoard()
// router.push('/myBoard')
})
saveMessage(path)
if (index === 1) {
handlerBoard(path)
}
const handlerPath = (path, index) => {
history.value.fetchList() //
chartEditStore.setComponentList() //
chartEditStore.setEdit(false) //
handlerBoard(path) //
}
</script>
@ -125,9 +109,9 @@ const handlerPath = (path, index) => {
color: #fff;
display: flex;
.left-menu {
width: 12%;
width: 260px;
box-sizing: border-box;
padding: 50px 20px;
padding: 41px 30px;
background: url('../../assets/images/ai/menu-bg.png');
background-size: 100% 100%;
.menu-list {
@ -136,15 +120,19 @@ const handlerPath = (path, index) => {
gap: 20px;
}
.menu-item {
display: flex;
align-items: center;
gap: 5px;
color: inherit;
text-decoration: none;
cursor: pointer;
height: 38px;
border-radius: 4px 4px 4px 4px;
border: 1px solid #474d59;
letter-spacing: 2px;
font-size: 14px;
font-weight: 400;
font-family: 'AlibabaPuHuiTi-Regular';
}
.active-link,
.menu-item:active {

@ -0,0 +1,151 @@
<template>
<!-- 我的看板 -->
<div class="myBoard-container">
<div class="list">
<div class="list-item" v-for="item in boardLsit" :key="item.id" @click="previewHandle(item)">
<div class="item-operation">
<img @click="deleteHandle(item)" src="~@/assets/images/ai/icon-delet.png" class="operation-item" alt="" />
<img @click="editHandle(item)" src="~@/assets/images/ai/icon-edit.png" class="operation-item" alt="" />
</div>
<img :src="item.indexImage" class="item-cover" alt="" />
<div class="item-name">{{ item.projectName }}</div>
</div>
</div>
<div class="pagination">
<n-pagination
:page="paginat.page"
:page-size="paginat.limit"
:item-count="paginat.count"
:page-sizes="[12, 24, 36, 48]"
@update:page="changePage"
@update:page-size="changeSize"
show-size-picker
/>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, reactive } from 'vue'
import { goDialog, httpErrorHandle } from '@/utils'
import { openNewWindow, previewPath } from '@/utils'
import { useRouter } from 'vue-router'
import { projectListApi, deleteProjectApi } from '@/api/path'
let boardLsit = ref([])
const router = useRouter()
const paginat = reactive({
//
page: 1,
//
limit: 12,
//
count: 10
})
const fetchList = async () => {
const res = await projectListApi(paginat)
boardLsit.value = res.data
paginat.count = res.data.count
console.log(boardLsit.value)
}
//
const changePage = _page => {
paginat.page = _page
fetchList()
}
//
const changeSize = _size => {
paginat.limit = _size
fetchList()
}
//
const deleteHandle = cardData => {
goDialog({
type: 'delete',
promise: true,
onPositiveCallback: () =>
new Promise(res => {
res(
deleteProjectApi({
ids: cardData.id
})
)
}),
promiseResCallback: res => {
if (res.code === 200) {
window['$message'].success(window['$t']('global.r_delete_success'))
fetchList()
return
}
httpErrorHandle()
}
})
}
//
const editHandle = cardData => {
if (!cardData) return
router.push(`/board/` + cardData.id)
}
//
const previewHandle = cardData => {
openNewWindow(previewPath(cardData.id))
}
onMounted(() => {
fetchList()
})
</script>
<style lang="scss" scoped>
.myBoard-container {
box-sizing: border-box;
height: 100vh;
padding: 20px 20px 0 20px;
.list {
max-height: 92%;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
gap: 20px;
.list-item {
cursor: pointer;
box-sizing: border-box;
// -
width: calc((100% / 4) - (20px * 1) + (20px / 4));
background: #282a31;
padding: 15px;
border-radius: 6px;
display: flex;
flex-direction: column;
gap: 10px;
.item-operation {
display: flex;
flex-direction: row-reverse;
gap: 11px;
.operation-item {
height: 13px;
width: 13px;
}
}
.item-cover {
display: block;
flex: 1;
width: 100%;
border-radius: 6px;
}
.item-name {
font-size: 16px;
color: #ffffff;
font-weight: 500;
font-family: 'AlibabaPuHuiTi-Medium';
}
}
}
.pagination {
height: 8%;
display: flex;
align-items: center;
justify-content: flex-end;
}
}
</style>

@ -0,0 +1,167 @@
<template>
<div class="ai-container">
<div class="left-menu">
<ai-logo></ai-logo>
<div class="menu-list">
<div
class="menu-item flex-box"
:class="getCurrentRoute(item.path) ? 'active-link' : ''"
:to="item.path"
v-for="(item, index) in menuList"
:key="index"
@click="handlerPath(item.path, index)"
>
<n-icon size="20">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path
d="M368.5 240H272v-96.5c0-8.8-7.2-16-16-16s-16 7.2-16 16V240h-96.5c-8.8 0-16 7.2-16 16 0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7H240v96.5c0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7 8.8 0 16-7.2 16-16V272h96.5c8.8 0 16-7.2 16-16s-7.2-16-16-16z"
/>
</svg> </n-icon
>新建{{ item.name }}
</div>
</div>
</div>
<div class="right-container">
<router-view :key="route.fullPath"></router-view>
</div>
</div>
</template>
<script setup>
import { useRoute, useRouter } from 'vue-router'
import { createProjectApi, historyMessageRoom, historyMessageRoomUpdata } from '@/api/path'
import { getUUID } from '@/utils'
import { ResultEnum } from '@/enums/httpEnum'
import { AiLogo } from './components'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const chartEditStore = useChartEditStore()
import { onMounted, ref } from 'vue'
import useMessageRoomStore from '@/store/modules/messageRoom'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
const systemStore = useSystemStore()
const useMessageRoom = useMessageRoomStore()
const router = useRouter()
const route = useRoute()
const history = ref(null)
const menuList = [
// { name: '', path: '/chat' },
{ name: '数据看板', path: 'board' }
]
const ehcatrsType = ['pie', 'line', 'bar']
const getCurrentRoute = path => {
return route.path.includes(path)
}
const saveMessage = async path => {
//
if (useMessageRoom.messageRoom.content.length > 0) {
useMessageRoom.messageRoom.content.forEach(instance => {
if (ehcatrsType.includes(instance.type) && instance.chartInstanceItem) {
instance.chartInstanceItem.dispose()
}
})
const jsonData = JSON.stringify(useMessageRoom.messageRoom.content)
let res
try {
if (useMessageRoom.messageRoom.id) {
res = await historyMessageRoomUpdata({ content: jsonData, id: useMessageRoom.messageRoom.id })
} else {
res = await historyMessageRoom({ content: jsonData, createUserId: systemStore.userInfo.userId || 1 })
}
if (res && res.code == 200) {
useMessageRoom.resetList({ id: undefined, createUserId: undefined, content: [] }) //
history.value.messageList()
router.push(path + '/' + Date.now())
}
} catch {
console.log('保存出错')
router.push(path + '/' + Date.now())
}
} else {
router.push(path + '/' + Date.now())
}
}
const handlerBoard = async (path='board') => {
try {
//
const res = await createProjectApi({
//
projectName: getUUID(),
// remarks
remarks: null,
//
indexImage: null
})
if (res && res.code === ResultEnum.SUCCESS) {
const { id } = res.data
router.push(`/${path}/`+ id)
}
} catch (error) {
window['$message'].error(window['$t']('project.create_failure'))
}
}
onMounted(()=>{
// handlerBoard()
})
const handlerPath = (path, index) => {
history.value.fetchList()//
chartEditStore.setComponentList()//
chartEditStore.setEdit(false)//
handlerBoard(path)//
}
</script>
<style lang="scss" scoped>
.ai-container {
height: 100vh;
color: #fff;
display: flex;
.left-menu {
width: 260px;
box-sizing: border-box;
padding: 41px 30px;
background: url('../../assets/images/ai/menu-bg.png');
background-size: 100% 100%;
.menu-list {
display: flex;
flex-direction: column;
gap: 20px;
}
.menu-item {
color: inherit;
text-decoration: none;
cursor: pointer;
height: 38px;
border-radius: 4px 4px 4px 4px;
border: 1px solid #474d59;
letter-spacing: 2px;
font-size: 14px;
}
.active-link,
.menu-item:active {
color: #507afc;
border-color: #507afc;
background: rgba(80, 122, 252, 0.2);
}
}
.right-container {
flex: 1;
overflow-x: auto;
}
}
.flex-box {
display: flex;
align-items: center;
justify-content: center;
}
</style>

@ -59,13 +59,13 @@ export const dragHandle = async (e: DragEvent) => {
}
//默认切换成动态请求
if(chartsType.package === 'Charts'){
if(chartsType.package === 'Charts' || chartsType.package === 'Tables'){
newComponent.request.requestDataType = 1
}else{
newComponent.request.requestDataType =0
}
console.log(newComponent,'创建新图表')
console.log(newComponent,'创建新图表',) //chartsType.package
setComponentPosition(newComponent, e.offsetX - newComponent.attr.w / 2, e.offsetY - newComponent.attr.h / 2)
chartEditStore.addComponentList(newComponent, false, true)

Loading…
Cancel
Save