feat:表格和gantt两种编辑模式
This commit is contained in:
parent
f7e20bca6a
commit
9c06b88118
1
components.d.ts
vendored
1
components.d.ts
vendored
@ -34,6 +34,7 @@ declare module '@vue/runtime-core' {
|
|||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||||
NDataTable: typeof import('naive-ui')['NDataTable']
|
NDataTable: typeof import('naive-ui')['NDataTable']
|
||||||
NDatePicker: typeof import('naive-ui')['NDatePicker']
|
NDatePicker: typeof import('naive-ui')['NDatePicker']
|
||||||
|
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||||
NDivider: typeof import('naive-ui')['NDivider']
|
NDivider: typeof import('naive-ui')['NDivider']
|
||||||
NEllipsi: typeof import('naive-ui')['NEllipsi']
|
NEllipsi: typeof import('naive-ui')['NEllipsi']
|
||||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||||
|
@ -16,6 +16,10 @@ const themeOverrides: GlobalThemeOverrides = {
|
|||||||
tdColor: '#0000',
|
tdColor: '#0000',
|
||||||
tdColorStriped: 'rgba(37,123,181,0.3)',
|
tdColorStriped: 'rgba(37,123,181,0.3)',
|
||||||
tdColorHover: 'rgba(37,123,181,0.6)',
|
tdColorHover: 'rgba(37,123,181,0.6)',
|
||||||
|
thColorModal: '#257bb5',
|
||||||
|
tdColorModal: '#0000',
|
||||||
|
tdColorStripedModal: 'rgba(37,123,181,0.3)',
|
||||||
|
tdColorHoverModal: 'rgba(37,123,181,0.3)',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -35,7 +39,7 @@ const themeOverrides: GlobalThemeOverrides = {
|
|||||||
<n-notification-provider placement="top" :max="10">
|
<n-notification-provider placement="top" :max="10">
|
||||||
<notification />
|
<notification />
|
||||||
</n-notification-provider>
|
</n-notification-provider>
|
||||||
<router-view />
|
<n-dialog-provider> <router-view /></n-dialog-provider>
|
||||||
<!-- </n-message-provider> -->
|
<!-- </n-message-provider> -->
|
||||||
<!-- </n-theme-editor> -->
|
<!-- </n-theme-editor> -->
|
||||||
</n-config-provider>
|
</n-config-provider>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const main = [
|
const main = [
|
||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
name: '任务-1',
|
name: 'DD-1',
|
||||||
start: '2024-11-15',
|
start: '2024-11-15',
|
||||||
end: '2024-11-21',
|
end: '2024-11-21',
|
||||||
children: [
|
children: [
|
||||||
@ -10,198 +10,168 @@ const main = [
|
|||||||
name: '事件-1-1',
|
name: '事件-1-1',
|
||||||
start: '2024-11-15',
|
start: '2024-11-15',
|
||||||
end: '2024-11-17',
|
end: '2024-11-17',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 122,
|
||||||
|
name: '发射',
|
||||||
|
start: '2024-11-15',
|
||||||
|
end: '2024-11-17',
|
||||||
|
type: 'DD',
|
||||||
avatar:
|
avatar:
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: '事件-1-2',
|
name: '事件-1-2',
|
||||||
start: '2024-11-17',
|
start: '2024-11-17',
|
||||||
end: '2024-11-18',
|
end: '2024-11-18',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: '事件-1-3',
|
name: '事件-1-3',
|
||||||
start: '2024-11-19',
|
start: '2024-11-19',
|
||||||
end: '2024-11-20',
|
end: '2024-11-20',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
name: '事件-1-4',
|
name: '事件-1-4',
|
||||||
start: '2024-11-18',
|
start: '2024-11-18',
|
||||||
end: '2024-11-19',
|
end: '2024-11-19',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 300,
|
id: 300,
|
||||||
name: '任务-2',
|
name: 'DD-2',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
name: '事件-2-1',
|
name: '事件-2-1',
|
||||||
start: '2024-11-18',
|
start: '2024-11-18',
|
||||||
end: '2024-11-21',
|
end: '2024-11-21',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '任务-3',
|
name: 'DD-3',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
name: '事件-3-1',
|
name: '事件-3-1',
|
||||||
start: '2024-11-21',
|
start: '2024-11-21',
|
||||||
end: '2024-11-22',
|
end: '2024-11-22',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 7,
|
id: 7,
|
||||||
name: '事件-3-2',
|
name: '事件-3-2',
|
||||||
start: '2024-11-18',
|
start: '2024-11-18',
|
||||||
end: '2024-11-19',
|
end: '2024-11-19',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '任务-4',
|
name: 'DD-4',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 8,
|
id: 8,
|
||||||
name: '事件-4-1',
|
name: '事件-4-1',
|
||||||
start: '2024-11-20',
|
start: '2024-11-20',
|
||||||
end: '2024-11-21',
|
end: '2024-11-21',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 9,
|
id: 9,
|
||||||
name: '事件-4-2',
|
name: '事件-4-2',
|
||||||
start: '2024-11-25',
|
start: '2024-11-25',
|
||||||
end: '2024-11-26',
|
end: '2024-11-26',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 10,
|
id: 10,
|
||||||
name: '事件-4-3',
|
name: '事件-4-3',
|
||||||
start: '2024-11-17',
|
start: '2024-11-17',
|
||||||
end: '2024-11-18',
|
end: '2024-11-18',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 11,
|
id: 11,
|
||||||
name: '事件-4-4',
|
name: '事件-4-4',
|
||||||
start: '2024-11-22',
|
start: '2024-11-22',
|
||||||
end: '2024-11-25',
|
end: '2024-11-25',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 12,
|
id: 12,
|
||||||
name: '事件-4-5',
|
name: '事件-4-5',
|
||||||
start: '2024-11-23',
|
start: '2024-11-23',
|
||||||
end: '2024-11-24',
|
end: '2024-11-24',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '任务-5',
|
name: 'DD-5',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 13,
|
id: 13,
|
||||||
name: '事件-5-1',
|
name: '事件-5-1',
|
||||||
start: '2024-11-22',
|
start: '2024-11-22',
|
||||||
end: '2024-11-25',
|
end: '2024-11-25',
|
||||||
|
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 14,
|
id: 14,
|
||||||
name: '事件-5-2',
|
name: '事件-5-2',
|
||||||
start: '2024-11-27',
|
start: '2024-11-27',
|
||||||
end: '2024-11-30',
|
end: '2024-11-30',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 15,
|
id: 15,
|
||||||
name: '事件-5-3',
|
name: '事件-5-3',
|
||||||
start: '2024-12-10',
|
start: '2024-12-10',
|
||||||
end: '2024-12-18',
|
end: '2024-12-18',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '任务-6',
|
name: 'DD-6',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 16,
|
id: 16,
|
||||||
name: '事件-6-1',
|
name: '事件-6-1',
|
||||||
start: '2024-11-20',
|
start: '2024-11-20',
|
||||||
end: '2024-11-30',
|
end: '2024-11-30',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 17,
|
id: 17,
|
||||||
name: '事件-6-2',
|
name: '事件-6-2',
|
||||||
start: '2024-12-02',
|
start: '2024-12-02',
|
||||||
end: '2024-12-18',
|
end: '2024-12-18',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '任务-7',
|
name: 'DD-7',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 18,
|
id: 18,
|
||||||
name: '事件-7-1',
|
name: '事件-7-1',
|
||||||
start: '2024-12-22',
|
start: '2024-12-22',
|
||||||
end: '2024-12-28',
|
end: '2024-12-28',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '任务-8',
|
name: 'DD-8',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 19,
|
id: 19,
|
||||||
name: '事件-8-1',
|
name: '事件-8-1',
|
||||||
start: '2024-11-25',
|
start: '2024-11-25',
|
||||||
end: '2024-11-30',
|
end: '2024-11-30',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 20,
|
id: 20,
|
||||||
name: '事件-8-2',
|
name: '事件-8-2',
|
||||||
start: '2024-12-01',
|
start: '2024-12-01',
|
||||||
end: '2024-12-18',
|
end: '2024-12-18',
|
||||||
avatar:
|
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -232,7 +202,7 @@ const sub = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: '脱落-2',
|
name: '脱离-2',
|
||||||
start: '2024-11-19',
|
start: '2024-11-19',
|
||||||
end: '2024-11-20',
|
end: '2024-11-20',
|
||||||
avatar:
|
avatar:
|
||||||
@ -240,9 +210,9 @@ const sub = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
name: '落地-3',
|
name: '落地',
|
||||||
start: '2024-11-18',
|
start: '2024-11-21',
|
||||||
end: '2024-11-19',
|
end: '2024-11-21',
|
||||||
avatar:
|
avatar:
|
||||||
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
||||||
},
|
},
|
||||||
@ -329,6 +299,15 @@ const sub = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const task = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '任务-1',
|
||||||
|
type: 'task',
|
||||||
|
children: main,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
export function getMainGantt(data = {}) {
|
export function getMainGantt(data = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -344,3 +323,11 @@ export function getSubGantt(subId) {
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTask() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(task)
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -22,9 +22,11 @@ const props = defineProps({
|
|||||||
// const modelVisible = ref(props.show)
|
// const modelVisible = ref(props.show)
|
||||||
|
|
||||||
// const emit = defineEmits(['update:show'])
|
// const emit = defineEmits(['update:show'])
|
||||||
const closeModal = () => {
|
// const closeModal = () => {
|
||||||
|
// show.value = false
|
||||||
// emit('update:show', false)
|
// emit('update:show', false)
|
||||||
}
|
// console.log(show)
|
||||||
|
// }
|
||||||
const show = defineModel<boolean>('show')
|
const show = defineModel<boolean>('show')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -33,8 +35,7 @@ const show = defineModel<boolean>('show')
|
|||||||
v-model:show="show"
|
v-model:show="show"
|
||||||
preset="dialog"
|
preset="dialog"
|
||||||
:title="props.title"
|
:title="props.title"
|
||||||
@close="closeModal"
|
class="bg-[#1c202cee] text-white"
|
||||||
class="bg-cool-gray-800 bg-opacity-80 text-white"
|
|
||||||
style="width: auto"
|
style="width: auto"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
@ -24,6 +24,16 @@ const router = createRouter({
|
|||||||
name: 'SubGantt',
|
name: 'SubGantt',
|
||||||
component: () => import('@/views/Gantt/components/SubGantt'),
|
component: () => import('@/views/Gantt/components/SubGantt'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'mainEdit',
|
||||||
|
name: 'MainGanttEdit',
|
||||||
|
component: () => import('@/views/Gantt/components/MainGanttEdit'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'subEdit/:subId',
|
||||||
|
name: 'SubGanttEdit',
|
||||||
|
component: () => import('@/views/Gantt/components/SubGanttEdit'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
115
src/views/Gantt/components/EventList/index.jsx
Normal file
115
src/views/Gantt/components/EventList/index.jsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { NDataTable, NIcon, NButton } from 'naive-ui'
|
||||||
|
import { getMainGantt } from '@/api/gantt'
|
||||||
|
import {
|
||||||
|
HelpCircleOutline,
|
||||||
|
CreateOutline,
|
||||||
|
TrashBinOutline,
|
||||||
|
AddCircleOutline,
|
||||||
|
EnterOutline,
|
||||||
|
} from '@vicons/ionicons5'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '事件名称',
|
||||||
|
key: 'name',
|
||||||
|
width: 220,
|
||||||
|
render: row => {
|
||||||
|
return (
|
||||||
|
<div class="inline-flex items-center gap-2">
|
||||||
|
<NIcon>
|
||||||
|
<HelpCircleOutline />
|
||||||
|
</NIcon>
|
||||||
|
{row.name}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
key: 'start',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
key: 'end',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
key: 'type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '图片',
|
||||||
|
key: 'avatar',
|
||||||
|
render(row) {
|
||||||
|
if (row.avatar) {
|
||||||
|
return <img src={row.avatar} width="50" alt="" />
|
||||||
|
} else {
|
||||||
|
return <span>-</span>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
render(row) {
|
||||||
|
return (
|
||||||
|
<div class="flex justify-end">
|
||||||
|
{!row.avatar ? (
|
||||||
|
<NButton
|
||||||
|
type="success"
|
||||||
|
size="small"
|
||||||
|
quaternary
|
||||||
|
onClick={() => handleEdit(row)}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<AddCircleOutline />
|
||||||
|
</NIcon>
|
||||||
|
</NButton>
|
||||||
|
) : null}
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
quaternary
|
||||||
|
onClick={() => handleEdit(row)}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<CreateOutline />
|
||||||
|
</NIcon>
|
||||||
|
</NButton>
|
||||||
|
{row.name.indexOf('DD') === -1 ? (
|
||||||
|
<NButton
|
||||||
|
type="error"
|
||||||
|
size="small"
|
||||||
|
quaternary
|
||||||
|
onClick={() => handleEdit(row)}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<TrashBinOutline />
|
||||||
|
</NIcon>
|
||||||
|
</NButton>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const tableData = ref([])
|
||||||
|
onMounted(async () => {
|
||||||
|
const res = await getMainGantt()
|
||||||
|
tableData.value = res
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<NDataTable
|
||||||
|
class="h-full"
|
||||||
|
flex-height
|
||||||
|
columns={columns}
|
||||||
|
data={tableData.value}
|
||||||
|
row-key={row => row.name}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -17,9 +17,9 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
const { subId } = route.params
|
const { subId } = route.params
|
||||||
const records = ref([])
|
const records = ref([])
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getGanttData(subId)
|
getGanttData()
|
||||||
})
|
})
|
||||||
async function getGanttData(subId: string) {
|
async function getGanttData() {
|
||||||
if (subId) {
|
if (subId) {
|
||||||
const res = await getSubGantt(subId)
|
const res = await getSubGantt(subId)
|
||||||
records.value = res
|
records.value = res
|
||||||
@ -34,7 +34,7 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
function renderMainTask(dom: HTMLElement) {
|
function renderMainTask(dom: HTMLElement) {
|
||||||
const option = getOption()
|
const option = getOption()
|
||||||
ganttInstance = new Gantt(dom, option)
|
ganttInstance = new Gantt(dom, option)
|
||||||
// window['ganttInstance'] = ganttInstance
|
window['ganttInstance'] = ganttInstance
|
||||||
console.log(ganttInstance)
|
console.log(ganttInstance)
|
||||||
}
|
}
|
||||||
function getOption(): TYPES.GanttConstructorOptions {
|
function getOption(): TYPES.GanttConstructorOptions {
|
||||||
@ -81,7 +81,7 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
taskBar: renderTaskBar(subId),
|
taskBar: renderTaskBar(subId),
|
||||||
timelineHeader: {
|
timelineHeader: {
|
||||||
backgroundColor: headerBgColor,
|
backgroundColor: headerBgColor,
|
||||||
colWidth: 100,
|
colWidth: 140,
|
||||||
verticalLine: {
|
verticalLine: {
|
||||||
lineColor: textColorWithOp,
|
lineColor: textColorWithOp,
|
||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
@ -112,14 +112,14 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
field: 'name',
|
field: 'name',
|
||||||
title: '类型',
|
title: subId ? '事件类型' : '事件主体',
|
||||||
width: '120',
|
width: '120',
|
||||||
mergeCell: true,
|
mergeCell: true,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
if (subId) {
|
if (subId) {
|
||||||
columns.unshift({
|
columns.unshift({
|
||||||
field: 'isCheck',
|
field: 'isChecked',
|
||||||
title: '',
|
title: '',
|
||||||
width: '60',
|
width: '60',
|
||||||
headerType: 'checkbox',
|
headerType: 'checkbox',
|
||||||
@ -165,7 +165,7 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
return taskListTable
|
return taskListTable
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderTaskBar(subId: string) {
|
function renderTaskBar() {
|
||||||
const taskBar = {
|
const taskBar = {
|
||||||
resizable: false,
|
resizable: false,
|
||||||
moveable: false,
|
moveable: false,
|
||||||
@ -179,11 +179,15 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
// stroke:true,
|
// fill: textColor,
|
||||||
|
// fillOpacity: 0.1,
|
||||||
// stroke: textColor,
|
// stroke: textColor,
|
||||||
|
// strokeOpacity: 0.2,
|
||||||
|
// lineWidth: 4,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
})
|
})
|
||||||
if (!subId) {
|
if (!subId) {
|
||||||
container.addEventListener('click', event => {
|
container.addEventListener('click', event => {
|
||||||
@ -304,6 +308,8 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
height,
|
height,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
flexWrap: 'nowrap',
|
flexWrap: 'nowrap',
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -318,7 +324,6 @@ const useGantt = ({ router, route }: GanttParams) => {
|
|||||||
fill: textColor,
|
fill: textColor,
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
maxLineWidth: width,
|
maxLineWidth: width,
|
||||||
boundsPadding: [25, 12, 10, 12],
|
|
||||||
})
|
})
|
||||||
container.add(day)
|
container.add(day)
|
||||||
return {
|
return {
|
||||||
|
389
src/views/Gantt/components/GanttEdit/hooks/ganttEdit.ts
Normal file
389
src/views/Gantt/components/GanttEdit/hooks/ganttEdit.ts
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
import { Group, Image, Text, CheckBox, Rect } from '@visactor/vtable/es/vrender'
|
||||||
|
|
||||||
|
import { useDialog } from 'naive-ui'
|
||||||
|
import { Gantt, tools, TYPES } from '@visactor/vtable-gantt'
|
||||||
|
import { getMainGantt, getSubGantt } from '@/api/Gantt'
|
||||||
|
|
||||||
|
type GanttParams = {
|
||||||
|
route?: any
|
||||||
|
router?: any
|
||||||
|
}
|
||||||
|
let ganttInstance: null | Gantt = null
|
||||||
|
const bgColor = '#1c202c'
|
||||||
|
const headerBgColor = '#33566f22'
|
||||||
|
const textColor = '#65c5e7'
|
||||||
|
const textColorWithOp = '#75fbfd22'
|
||||||
|
const useGanttEdit = ({ router, route }: GanttParams) => {
|
||||||
|
const { subId } = route.params
|
||||||
|
const records = ref([])
|
||||||
|
const dialog = useDialog()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getGanttData()
|
||||||
|
})
|
||||||
|
async function getGanttData() {
|
||||||
|
if (subId) {
|
||||||
|
const res = await getSubGantt(subId)
|
||||||
|
records.value = res
|
||||||
|
ganttInstance?.setRecords(records.value)
|
||||||
|
} else {
|
||||||
|
const res = await getMainGantt()
|
||||||
|
// console.log(res, '----')
|
||||||
|
records.value = res
|
||||||
|
ganttInstance?.setRecords(records.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function renderMainTask(dom: HTMLElement) {
|
||||||
|
const option = getOption()
|
||||||
|
ganttInstance = new Gantt(dom, option)
|
||||||
|
window['ganttInstance'] = ganttInstance
|
||||||
|
console.log(ganttInstance)
|
||||||
|
}
|
||||||
|
function getOption(): TYPES.GanttConstructorOptions {
|
||||||
|
const option = {
|
||||||
|
records: records.value,
|
||||||
|
taskListTable: renderTaskListTable(),
|
||||||
|
tasksShowMode: TYPES.TasksShowMode.Sub_Tasks_Arrange,
|
||||||
|
|
||||||
|
frame: {
|
||||||
|
outerFrameStyle: {
|
||||||
|
borderLineWidth: 2,
|
||||||
|
borderColor: textColor,
|
||||||
|
cornerRadius: 3,
|
||||||
|
},
|
||||||
|
// verticalSplitLineHighlight: {
|
||||||
|
// lineColor: 'green',
|
||||||
|
// lineWidth: 3
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
// backgroundColor: bgColor,
|
||||||
|
horizontalLine: {
|
||||||
|
lineWidth: 1,
|
||||||
|
lineColor: textColorWithOp,
|
||||||
|
},
|
||||||
|
verticalLine: {
|
||||||
|
lineWidth: 1,
|
||||||
|
lineColor: textColorWithOp,
|
||||||
|
lineDash: [4, 8],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
taskList: {
|
||||||
|
// backgroundColor: bgColor,
|
||||||
|
headerStyle: {
|
||||||
|
borderColor: '#e1e4e8',
|
||||||
|
borderLineWidth: 0,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: 'red',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headerRowHeight: 59,
|
||||||
|
rowHeight: subId ? 200 : 100,
|
||||||
|
taskBar: renderTaskBar(),
|
||||||
|
timelineHeader: {
|
||||||
|
backgroundColor: headerBgColor,
|
||||||
|
colWidth: 150,
|
||||||
|
verticalLine: {
|
||||||
|
lineColor: textColorWithOp,
|
||||||
|
lineWidth: 1,
|
||||||
|
lineDash: [4, 2],
|
||||||
|
},
|
||||||
|
horizontalLine: {
|
||||||
|
lineColor: textColorWithOp,
|
||||||
|
lineWidth: 1,
|
||||||
|
lineDash: [4, 2],
|
||||||
|
},
|
||||||
|
scales: getTimeScales('day'),
|
||||||
|
},
|
||||||
|
minDate: '2024-11-14',
|
||||||
|
maxDate: '2024-12-30',
|
||||||
|
|
||||||
|
scrollStyle: {
|
||||||
|
scrollRailColor: 'RGBA(246,246,246,0)',
|
||||||
|
visible: 'focus',
|
||||||
|
width: 6,
|
||||||
|
scrollSliderCornerRadius: 2,
|
||||||
|
scrollSliderColor: 'rgba(255,255,255,0.25)',
|
||||||
|
},
|
||||||
|
underlayBackgroundColor: bgColor,
|
||||||
|
}
|
||||||
|
return option as TYPES.GanttConstructorOptions
|
||||||
|
}
|
||||||
|
function renderColumn() {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
title: subId ? '事件类型' : '事件主体',
|
||||||
|
width: '120',
|
||||||
|
mergeCell: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
// if (subId) {
|
||||||
|
// columns.unshift({
|
||||||
|
// field: 'isChecked',
|
||||||
|
// title: '',
|
||||||
|
// width: '60',
|
||||||
|
// headerType: 'checkbox',
|
||||||
|
// cellType: 'checkbox',
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
return columns
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTaskListTable() {
|
||||||
|
const taskListTable = {
|
||||||
|
columns: renderColumn(),
|
||||||
|
// tableWidth: 'auto',
|
||||||
|
theme: {
|
||||||
|
underlayBackgroundColor: bgColor,
|
||||||
|
headerStyle: {
|
||||||
|
borderColor: textColorWithOp,
|
||||||
|
borderLineWidth: 1,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: textColor,
|
||||||
|
bgColor: headerBgColor,
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 20,
|
||||||
|
hover: {
|
||||||
|
cellBgColor: 'transparent',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
bodyStyle: {
|
||||||
|
borderColor: textColorWithOp,
|
||||||
|
textAlign: 'center',
|
||||||
|
borderLineWidth: 1,
|
||||||
|
autoWrapText: true,
|
||||||
|
fontSize: 16,
|
||||||
|
color: textColor,
|
||||||
|
bgColor: bgColor,
|
||||||
|
hover: {
|
||||||
|
cellBgColor: textColorWithOp,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return taskListTable
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTaskBar() {
|
||||||
|
const taskBar = {
|
||||||
|
resizable: false,
|
||||||
|
moveable: false,
|
||||||
|
startDateField: 'start',
|
||||||
|
endDateField: 'end',
|
||||||
|
// progressField: 'progress',
|
||||||
|
barStyle: { width: subId ? 180 : 60 },
|
||||||
|
customLayout: args => {
|
||||||
|
const { width, height, startDate, endDate, taskRecord } = args
|
||||||
|
|
||||||
|
const container = new Group({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
fill: 'transparent',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center',
|
||||||
|
// alignItems: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
})
|
||||||
|
if (!subId) {
|
||||||
|
container.addEventListener('click', event => {
|
||||||
|
router.push({
|
||||||
|
path: `/gantt/subEdit/${taskRecord.id}`,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subId) {
|
||||||
|
const image = new Image({
|
||||||
|
image: taskRecord.avatar,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
boundsPadding: [0, 0, 10, 0],
|
||||||
|
})
|
||||||
|
container.add(image)
|
||||||
|
}
|
||||||
|
const checkBoxGroup = new Group({
|
||||||
|
width,
|
||||||
|
//height,
|
||||||
|
fill: 'transparent',
|
||||||
|
display: 'flex',
|
||||||
|
})
|
||||||
|
container.add(checkBoxGroup)
|
||||||
|
|
||||||
|
// const checkbox = new CheckBox({
|
||||||
|
// id: taskRecord.id,
|
||||||
|
// text: '',
|
||||||
|
// checked: false,
|
||||||
|
// })
|
||||||
|
// checkBoxGroup.add(checkbox)
|
||||||
|
|
||||||
|
// checkbox.addEventListener('click', event => {
|
||||||
|
// event.stopPropagation()
|
||||||
|
// console.log(checkbox, 'checkbox')
|
||||||
|
// })
|
||||||
|
const name = new Text({
|
||||||
|
text: taskRecord.name,
|
||||||
|
fontSize: 16,
|
||||||
|
fontFamily: 'sans-serif',
|
||||||
|
fill: textColor,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
maxLineWidth: width,
|
||||||
|
textAlign: 'center',
|
||||||
|
// boundsPadding: [0, 0, 0, 10],
|
||||||
|
})
|
||||||
|
checkBoxGroup.add(name)
|
||||||
|
|
||||||
|
const editSymbol = new Image({
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
fill: '#fff',
|
||||||
|
image:
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><g fill="none"><path d="M4.5 2A2.5 2.5 0 0 0 2 4.5v7A2.5 2.5 0 0 0 4.5 14h1.547l.25-1H4.5A1.5 1.5 0 0 1 3 11.5V5h10v1.036c.331-.058.671-.05 1 .023V4.5A2.5 2.5 0 0 0 11.5 2h-7zM3.085 4A1.5 1.5 0 0 1 4.5 3h7a1.5 1.5 0 0 1 1.415 1h-9.83zm11.46 3.455a1.56 1.56 0 0 0-2.207 0l-4.289 4.288a2.777 2.777 0 0 0-.73 1.29l-.303 1.212a.61.61 0 0 0 .739.739l1.211-.303a2.777 2.777 0 0 0 1.29-.73l4.289-4.289a1.56 1.56 0 0 0 0-2.207z" fill="#5c8e9e"></path></g></svg>',
|
||||||
|
boundsPadding: [-2, 0, 0, 10],
|
||||||
|
cursor: 'pointer',
|
||||||
|
})
|
||||||
|
checkBoxGroup.add(editSymbol)
|
||||||
|
|
||||||
|
editSymbol.addEventListener('click', event => {
|
||||||
|
event.stopPropagation()
|
||||||
|
console.log(editSymbol, 'editSymbol')
|
||||||
|
})
|
||||||
|
|
||||||
|
const deleteSymbol = new Image({
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
fill: '#fff',
|
||||||
|
image:
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none"><path d="M16.5 12a5.5 5.5 0 1 1 0 11a5.5 5.5 0 0 1 0-11zM12 1.75a3.25 3.25 0 0 1 3.245 3.066L15.25 5h5.25a.75.75 0 0 1 .102 1.493L20.5 6.5h-.796l-.5 5.087c-.46-.21-.95-.37-1.46-.468l.453-4.619H5.802l1.267 12.872a1.25 1.25 0 0 0 1.117 1.122l.127.006h2.42c.286.551.65 1.056 1.076 1.5H8.313a2.75 2.75 0 0 1-2.714-2.307l-.023-.174L4.295 6.5H3.5a.75.75 0 0 1-.743-.648L2.75 5.75a.75.75 0 0 1 .648-.743L3.5 5h5.25A3.25 3.25 0 0 1 12 1.75zm1.716 12.839l-.07.057l-.057.07a.5.5 0 0 0 0 .568l.057.07l2.147 2.146l-2.147 2.146l-.057.07a.5.5 0 0 0 0 .568l.057.07l.07.057a.5.5 0 0 0 .568 0l.07-.057l2.146-2.147l2.146 2.147l.07.057a.5.5 0 0 0 .568 0l.07-.057l.057-.07a.5.5 0 0 0 0-.568l-.057-.07l-2.147-2.146l2.147-2.146l.057-.07a.5.5 0 0 0 0-.568l-.057-.07l-.07-.057a.5.5 0 0 0-.568 0l-.07.057l-2.146 2.147l-2.146-2.147l-.07-.057a.5.5 0 0 0-.492-.044l-.076.044zM12 3.25a1.75 1.75 0 0 0-1.744 1.606L10.25 5h3.5A1.75 1.75 0 0 0 12 3.25z" fill="#933"></path></g></svg>',
|
||||||
|
boundsPadding: [-2, 0, 0, 10],
|
||||||
|
cursor: 'pointer',
|
||||||
|
})
|
||||||
|
checkBoxGroup.add(deleteSymbol)
|
||||||
|
|
||||||
|
deleteSymbol.addEventListener('click', event => {
|
||||||
|
event.stopPropagation()
|
||||||
|
// console.log(dialog, '----')
|
||||||
|
dialog.warning({
|
||||||
|
title: '警告',
|
||||||
|
content: '确认删除当前事件?',
|
||||||
|
positiveText: '确定',
|
||||||
|
negativeText: '取消',
|
||||||
|
onPositiveClick: () => {},
|
||||||
|
onNegativeClick: () => {},
|
||||||
|
})
|
||||||
|
console.log(deleteSymbol, 'deleteSymbol')
|
||||||
|
})
|
||||||
|
|
||||||
|
const days = new Text({
|
||||||
|
text: `${startDate.toLocaleDateString()} ~ ${endDate.toLocaleDateString()}`,
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: 'sans-serif',
|
||||||
|
fill: textColor,
|
||||||
|
boundsPadding: [10, 0, 0, 0],
|
||||||
|
})
|
||||||
|
container.add(days)
|
||||||
|
const rect = new Rect({
|
||||||
|
width: width,
|
||||||
|
height: 7,
|
||||||
|
fill: {
|
||||||
|
gradient: 'linear',
|
||||||
|
x0: 0,
|
||||||
|
y0: 0,
|
||||||
|
x1: 1,
|
||||||
|
y1: 0,
|
||||||
|
stops: [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: textColor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: textColorWithOp,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
boundsPadding: [10, 0, 0, 0],
|
||||||
|
})
|
||||||
|
container.add(rect)
|
||||||
|
return {
|
||||||
|
rootContainer: container,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hoverBarStyle: {
|
||||||
|
cornerRadius: 2,
|
||||||
|
barOverlayColor: textColorWithOp,
|
||||||
|
},
|
||||||
|
selectedBarStyle: {
|
||||||
|
// cornerRadius: 2,
|
||||||
|
borderColor: textColorWithOp,
|
||||||
|
borderLineWidth: 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return taskBar
|
||||||
|
}
|
||||||
|
function renderGroup(opt: IGroupGraphicAttribute) {
|
||||||
|
return new Group(opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderText(opt: ITextGraphicAttribute) {
|
||||||
|
return new Text(opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderImage(opt: IImageGraphicAttribute) {
|
||||||
|
return new Image(opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeTimeScales(scale: TYPES.ITimelineScale['unit']) {
|
||||||
|
const scales = getTimeScales(scale)
|
||||||
|
ganttInstance && ganttInstance.updateScales(scales)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTimeScales(
|
||||||
|
scale: TYPES.ITimelineScale['unit']
|
||||||
|
): TYPES.ITimelineScale[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
unit: scale,
|
||||||
|
step: 1,
|
||||||
|
customLayout: args => {
|
||||||
|
const { width, height, startDate } = args
|
||||||
|
const container = new Group({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexWrap: 'nowrap',
|
||||||
|
})
|
||||||
|
|
||||||
|
const day = new Text({
|
||||||
|
text:
|
||||||
|
scale === 'day'
|
||||||
|
? startDate.toLocaleDateString()
|
||||||
|
: startDate.toLocaleTimeString(),
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontFamily: 'sans-serif',
|
||||||
|
fill: textColor,
|
||||||
|
textAlign: 'center',
|
||||||
|
maxLineWidth: width,
|
||||||
|
// boundsPadding: [25, 12, 10, 12],
|
||||||
|
})
|
||||||
|
container.add(day)
|
||||||
|
return {
|
||||||
|
rootContainer: container,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return { renderMainTask, changeTimeScales }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useGanttEdit
|
29
src/views/Gantt/components/GanttEdit/index.jsx
Normal file
29
src/views/Gantt/components/GanttEdit/index.jsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import useGanttEdit from './hooks/ganttEdit'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
scale: {
|
||||||
|
type: String,
|
||||||
|
default: 'day',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
const { renderMainTask, changeTimeScales } = useGanttEdit({ route, router })
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
renderMainTask(document.querySelector('#tableContainer'))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
watch(
|
||||||
|
() => props.scale,
|
||||||
|
val => {
|
||||||
|
changeTimeScales(val)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return () => <div id="tableContainer" class="bg-[#1c202c] w-h-full"></div>
|
||||||
|
},
|
||||||
|
})
|
@ -1,10 +1,17 @@
|
|||||||
import { NDatePicker, NRadioButton, NRadioGroup } from 'naive-ui'
|
import { useRouter } from 'vue-router'
|
||||||
|
import { NDatePicker, NRadioButton, NRadioGroup, NButton } from 'naive-ui'
|
||||||
import GanttCom from '../Gantt'
|
import GanttCom from '../Gantt'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
const range = ref()
|
const range = ref()
|
||||||
const value = ref('day')
|
const value = ref('day')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const editEvent = () => {
|
||||||
|
console.log(router)
|
||||||
|
router.push('/gantt/mainEdit')
|
||||||
|
}
|
||||||
return () => (
|
return () => (
|
||||||
<>
|
<>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
@ -13,6 +20,9 @@ export default defineComponent({
|
|||||||
<NRadioButton value="hour" label="日" />
|
<NRadioButton value="hour" label="日" />
|
||||||
<NRadioButton value="day" label="月" />
|
<NRadioButton value="day" label="月" />
|
||||||
</NRadioGroup>
|
</NRadioGroup>
|
||||||
|
<NButton class="ml-auto" type="primary" onClick={editEvent}>
|
||||||
|
编辑事件
|
||||||
|
</NButton>
|
||||||
</div>
|
</div>
|
||||||
<GanttCom scale={value.value} />
|
<GanttCom scale={value.value} />
|
||||||
</>
|
</>
|
||||||
|
45
src/views/Gantt/components/MainGanttEdit/index.jsx
Normal file
45
src/views/Gantt/components/MainGanttEdit/index.jsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { NDatePicker, NRadioButton, NRadioGroup, NButton } from 'naive-ui'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import GanttCom from '../GanttEdit'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
const range = ref()
|
||||||
|
const value = ref('day')
|
||||||
|
|
||||||
|
const addEvent = () => {
|
||||||
|
console.log('tianjia --- event')
|
||||||
|
}
|
||||||
|
const addTask = () => {
|
||||||
|
console.log('tianjiarenwu')
|
||||||
|
}
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const ok = () => {
|
||||||
|
router.push('/gantt')
|
||||||
|
}
|
||||||
|
return () => (
|
||||||
|
<>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<NDatePicker v-model:value={range.value} type="daterange" clearable />
|
||||||
|
<NRadioGroup v-model:value={value.value} name="radiobuttongroup">
|
||||||
|
<NRadioButton value="hour" label="日" />
|
||||||
|
<NRadioButton value="day" label="月" />
|
||||||
|
</NRadioGroup>
|
||||||
|
<div class="ml-auto flex gap-2">
|
||||||
|
<NButton type="primary" onClick={addEvent}>
|
||||||
|
添加事件
|
||||||
|
</NButton>
|
||||||
|
{/* <NButton type="primary" onClick={addTask}>
|
||||||
|
添加任务
|
||||||
|
</NButton> */}
|
||||||
|
<NButton type="primary" onClick={ok}>
|
||||||
|
完成编辑
|
||||||
|
</NButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<GanttCom scale={value.value} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -1,14 +1,30 @@
|
|||||||
import { NButton } from 'naive-ui'
|
import { NButton } from 'naive-ui'
|
||||||
import GanttCom from '../Gantt'
|
import GanttCom from '../Gantt'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const value = ref('day')
|
const value = ref('day')
|
||||||
|
|
||||||
|
const showView = () => {
|
||||||
|
// getCheckboxState
|
||||||
|
const checked = ganttInstance.taskListTableInstance?.getCheckboxState()
|
||||||
|
console.log(checked)
|
||||||
|
}
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<>
|
<>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<NButton>态势展示</NButton>
|
<NButton onClick={showView}>态势展示</NButton>
|
||||||
<NButton>返回</NButton>
|
<NButton
|
||||||
|
onClick={() => {
|
||||||
|
router.go(-1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
返回
|
||||||
|
</NButton>
|
||||||
</div>
|
</div>
|
||||||
<GanttCom scale={value.value} />
|
<GanttCom scale={value.value} />
|
||||||
</>
|
</>
|
||||||
|
33
src/views/Gantt/components/SubGanttEdit/index.jsx
Normal file
33
src/views/Gantt/components/SubGanttEdit/index.jsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { NButton } from 'naive-ui'
|
||||||
|
import GanttCom from '../GanttEdit'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const value = ref('day')
|
||||||
|
|
||||||
|
const showView = () => {
|
||||||
|
// getCheckboxState
|
||||||
|
const checked = ganttInstance.taskListTableInstance?.getCheckboxState()
|
||||||
|
console.log(checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
{/* <NButton onClick={showView}>态势展示</NButton> */}
|
||||||
|
<NButton
|
||||||
|
onClick={() => {
|
||||||
|
router.go(-1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
返回
|
||||||
|
</NButton>
|
||||||
|
</div>
|
||||||
|
<GanttCom scale={value.value} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -0,0 +1,8 @@
|
|||||||
|
const showNewTask = ref(false)
|
||||||
|
const useTask = () => {
|
||||||
|
return {
|
||||||
|
showNewTask,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useTask
|
100
src/views/Gantt/components/TaskList/components/NewTask/index.jsx
Normal file
100
src/views/Gantt/components/TaskList/components/NewTask/index.jsx
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { NForm, NFormItem, NInput, NDataTable, NButton } from 'naive-ui'
|
||||||
|
import ModalCom from '@/components/Modal/index.vue'
|
||||||
|
import { getMainGantt } from '@/api/gantt'
|
||||||
|
import useTask from './hooks'
|
||||||
|
export default defineComponent({
|
||||||
|
// props: {
|
||||||
|
// show: {
|
||||||
|
// type: Boolean,
|
||||||
|
// default: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
setup() {
|
||||||
|
const task = ref({
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
})
|
||||||
|
const columns = [
|
||||||
|
{ type: 'selection' },
|
||||||
|
{
|
||||||
|
title: '事件名称',
|
||||||
|
key: 'name',
|
||||||
|
width: 220,
|
||||||
|
// render: row => {
|
||||||
|
// return (
|
||||||
|
// <div class="inline-flex items-center gap-2">
|
||||||
|
// <NIcon>
|
||||||
|
// <HelpCircleOutline />
|
||||||
|
// </NIcon>
|
||||||
|
// {row.name}
|
||||||
|
// </div>
|
||||||
|
// )
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
key: 'start',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
key: 'end',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
key: 'type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '图片',
|
||||||
|
key: 'avatar',
|
||||||
|
render(row) {
|
||||||
|
if (row.avatar) {
|
||||||
|
return <img src={row.avatar} width="50" alt="" />
|
||||||
|
} else {
|
||||||
|
return <span>-</span>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const tableData = ref([])
|
||||||
|
onMounted(async () => {
|
||||||
|
const res = await getMainGantt()
|
||||||
|
tableData.value = res
|
||||||
|
})
|
||||||
|
const { showNewTask } = useTask()
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
showNewTask.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<ModalCom v-model:show={showNewTask.value} title="新增任务">
|
||||||
|
<NForm
|
||||||
|
class="w-[900px]"
|
||||||
|
model={task}
|
||||||
|
label-placement="left"
|
||||||
|
label-width="auto"
|
||||||
|
>
|
||||||
|
<NFormItem label="任务名称" path="name">
|
||||||
|
<NInput v-model:value={task.value.name} />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="任务描述" path="description">
|
||||||
|
<NInput v-model:value={task.value.description} />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="事件" path="event">
|
||||||
|
<NDataTable
|
||||||
|
class="h-[400px]"
|
||||||
|
flex-height
|
||||||
|
columns={columns}
|
||||||
|
data={tableData.value}
|
||||||
|
row-key={row => row.name}
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
</NForm>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<NButton onClick={close}>取消</NButton>
|
||||||
|
<NButton type="primary">确认</NButton>
|
||||||
|
</div>
|
||||||
|
</ModalCom>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
128
src/views/Gantt/components/TaskList/index.jsx
Normal file
128
src/views/Gantt/components/TaskList/index.jsx
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import { NDataTable, NIcon, NButton } from 'naive-ui'
|
||||||
|
import { getTask } from '@/api/gantt'
|
||||||
|
import {
|
||||||
|
HelpCircleOutline,
|
||||||
|
CreateOutline,
|
||||||
|
TrashBinOutline,
|
||||||
|
AddCircleOutline,
|
||||||
|
EnterOutline,
|
||||||
|
} from '@vicons/ionicons5'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '任务名称/事件名称',
|
||||||
|
key: 'name',
|
||||||
|
width: 220,
|
||||||
|
render: row => {
|
||||||
|
return (
|
||||||
|
<div class="inline-flex items-center gap-2">
|
||||||
|
<NIcon>
|
||||||
|
<HelpCircleOutline />
|
||||||
|
</NIcon>
|
||||||
|
{row.name}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
key: 'start',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
key: 'end',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
key: 'type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '图片',
|
||||||
|
key: 'avatar',
|
||||||
|
render(row) {
|
||||||
|
if (row.avatar) {
|
||||||
|
return <img src={row.avatar} width="50" alt="" />
|
||||||
|
} else {
|
||||||
|
return <span>-</span>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
render(row) {
|
||||||
|
return (
|
||||||
|
<div class="flex justify-end">
|
||||||
|
{row.type === 'task' ? (
|
||||||
|
<>
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
quaternary
|
||||||
|
onClick={() => handleEdit(row)}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<EnterOutline />
|
||||||
|
</NIcon>
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
quaternary
|
||||||
|
onClick={() => handleEdit(row)}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<CreateOutline />
|
||||||
|
</NIcon>
|
||||||
|
</NButton>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
{/* {!row.avatar ? (
|
||||||
|
<NButton
|
||||||
|
type="success"
|
||||||
|
size="small"
|
||||||
|
quaternary
|
||||||
|
onClick={() => handleEdit(row)}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<AddCircleOutline />
|
||||||
|
</NIcon>
|
||||||
|
</NButton>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)} */}
|
||||||
|
|
||||||
|
<NButton
|
||||||
|
type="error"
|
||||||
|
size="small"
|
||||||
|
quaternary
|
||||||
|
onClick={() => handleEdit(row)}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<TrashBinOutline />
|
||||||
|
</NIcon>
|
||||||
|
</NButton>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const tableData = ref([])
|
||||||
|
onMounted(async () => {
|
||||||
|
const res = await getTask()
|
||||||
|
tableData.value = res
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<NDataTable
|
||||||
|
class="h-full"
|
||||||
|
flex-height
|
||||||
|
columns={columns}
|
||||||
|
data={tableData.value}
|
||||||
|
row-key={row => row.name}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -1,8 +1,33 @@
|
|||||||
import { RouterView } from 'vue-router'
|
import { RouterView, useRouter } from 'vue-router'
|
||||||
|
import {
|
||||||
|
NDatePicker,
|
||||||
|
NButton,
|
||||||
|
NFloatButton,
|
||||||
|
NIcon,
|
||||||
|
NDrawer,
|
||||||
|
NDrawerContent,
|
||||||
|
NTabs,
|
||||||
|
NTabPane,
|
||||||
|
} from 'naive-ui'
|
||||||
|
import { ArrowForward } from '@vicons/ionicons5'
|
||||||
import HeaderCom from '../Content/components/Header/index.vue'
|
import HeaderCom from '../Content/components/Header/index.vue'
|
||||||
|
import TaskList from './components/TaskList'
|
||||||
|
import EventList from './components/EventList'
|
||||||
|
import NewTask from './components/TaskList/components/NewTask'
|
||||||
|
import useTask from './components/TaskList/components/NewTask/hooks'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
|
const router = useRouter()
|
||||||
|
const show = ref(false)
|
||||||
|
const range = ref()
|
||||||
|
|
||||||
|
const { showNewTask } = useTask()
|
||||||
|
|
||||||
|
const addNewTask = () => {
|
||||||
|
showNewTask.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const paneClass = `border-1 h-full border-l-0 border-[var(--n-tab-border-color)] !p-2`
|
||||||
return () => (
|
return () => (
|
||||||
<div class="flex flex-col bg-[#1c202c] w-h-full">
|
<div class="flex flex-col bg-[#1c202c] w-h-full">
|
||||||
<div class="relative h-[60px]">
|
<div class="relative h-[60px]">
|
||||||
@ -11,6 +36,85 @@ export default defineComponent({
|
|||||||
<div class="z-30 flex flex-1 flex-col gap-4 p-5">
|
<div class="z-30 flex flex-1 flex-col gap-4 p-5">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</div>
|
</div>
|
||||||
|
<NFloatButton
|
||||||
|
class="z-40"
|
||||||
|
left={-10}
|
||||||
|
bottom={document.body.clientHeight / 2}
|
||||||
|
shape="square"
|
||||||
|
onClick={() => {
|
||||||
|
show.value = true
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<NIcon>
|
||||||
|
<ArrowForward />
|
||||||
|
</NIcon>
|
||||||
|
</NFloatButton>
|
||||||
|
<NDrawer
|
||||||
|
class="h-[100vh] bg-[#1c202cee]"
|
||||||
|
v-model:show={show.value}
|
||||||
|
width={document.body.clientWidth - 300}
|
||||||
|
placement="left"
|
||||||
|
>
|
||||||
|
<NDrawerContent title="任务列表" closable>
|
||||||
|
<div class="flex h-full flex-col gap-2">
|
||||||
|
<NTabs
|
||||||
|
class="h-full"
|
||||||
|
pane-wrapper-class="h-full"
|
||||||
|
type="card"
|
||||||
|
animated
|
||||||
|
placement="left"
|
||||||
|
>
|
||||||
|
<NTabPane class={paneClass} name="任务列表" tab="任务列表">
|
||||||
|
<div class="flex h-full flex-col gap-2">
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<NDatePicker
|
||||||
|
v-model:value={range.value}
|
||||||
|
type="daterange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
<NButton type="primary" onClick={addNewTask}>
|
||||||
|
添加任务
|
||||||
|
</NButton>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<TaskList />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NTabPane>
|
||||||
|
<NTabPane class={paneClass} name="事件列表" tab="事件列表">
|
||||||
|
<div class="flex h-full flex-col gap-2">
|
||||||
|
<div class="flex justify-end gap-2 ">
|
||||||
|
<NDatePicker
|
||||||
|
v-model:value={range.value}
|
||||||
|
type="daterange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
{/* <NButton type="primary" onClick={addNewTask}>
|
||||||
|
添加事件
|
||||||
|
</NButton> */}
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<EventList />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NTabPane>
|
||||||
|
</NTabs>
|
||||||
|
{/* <div class="flex justify-end gap-2 ">
|
||||||
|
<NDatePicker
|
||||||
|
v-model:value={range.value}
|
||||||
|
type="daterange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<TaskList />
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
</NDrawerContent>
|
||||||
|
</NDrawer>
|
||||||
|
|
||||||
|
<NewTask v-model:show={showNewTask.value} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user