first commit
This commit is contained in:
commit
eb2f504652
32490 changed files with 5731109 additions and 0 deletions
27
node_modules/structure-chart/README.md
generated
vendored
Normal file
27
node_modules/structure-chart/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Structure Chart
|
||||
|
||||
## วิธีใช้
|
||||
|
||||
```
|
||||
// import Structure Chart Component
|
||||
import { StructChart } from 'structure-chart'
|
||||
import 'structure-chart/structure-chart.css' // or import 'structure-chart/dist/style.css'
|
||||
|
||||
// import Data from static file or API
|
||||
import chartData from '@/assets/structChartData'
|
||||
const dataSource = ref(chartData)
|
||||
|
||||
// onClick Event
|
||||
const chartClick = (data: any) => {
|
||||
console.log(data.value)
|
||||
}
|
||||
|
||||
<StructChart
|
||||
:dataSource="data"
|
||||
@onElementClick="chartClick"
|
||||
:config="{
|
||||
'minZoom': 0.5,
|
||||
'maxZoom': 3
|
||||
}"
|
||||
/>
|
||||
```
|
||||
15
node_modules/structure-chart/dist/components/StructChart.vue.d.ts
generated
vendored
Normal file
15
node_modules/structure-chart/dist/components/StructChart.vue.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import type { PropType } from 'vue';
|
||||
import type { IStructConfig } from '../stores/StructStore';
|
||||
declare const _sfc_main: import("vue").DefineComponent<{
|
||||
config: PropType<IStructConfig>;
|
||||
dataSource: ObjectConstructor;
|
||||
}, {
|
||||
savePNG: (scale?: number) => Promise<void>;
|
||||
savePDF: (scale?: number) => Promise<void>;
|
||||
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "onElementClick"[], "onElementClick", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
||||
config: PropType<IStructConfig>;
|
||||
dataSource: ObjectConstructor;
|
||||
}>> & {
|
||||
onOnElementClick?: ((...args: any[]) => any) | undefined;
|
||||
}, {}>;
|
||||
export default _sfc_main;
|
||||
6
node_modules/structure-chart/dist/components/StructChartNode.vue.d.ts
generated
vendored
Normal file
6
node_modules/structure-chart/dist/components/StructChartNode.vue.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
declare const _sfc_main: import("vue").DefineComponent<{
|
||||
dataSource: ObjectConstructor;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
||||
dataSource: ObjectConstructor;
|
||||
}>>, {}>;
|
||||
export default _sfc_main;
|
||||
13990
node_modules/structure-chart/dist/index-d950fc13.js
generated
vendored
Normal file
13990
node_modules/structure-chart/dist/index-d950fc13.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2
node_modules/structure-chart/dist/index.d.ts
generated
vendored
Normal file
2
node_modules/structure-chart/dist/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import StructChart from './components/StructChart.vue';
|
||||
export { StructChart };
|
||||
5768
node_modules/structure-chart/dist/index.es-ebdebaec.js
generated
vendored
Normal file
5768
node_modules/structure-chart/dist/index.es-ebdebaec.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
470
node_modules/structure-chart/dist/purify.es-4f9a0368.js
generated
vendored
Normal file
470
node_modules/structure-chart/dist/purify.es-4f9a0368.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
30
node_modules/structure-chart/dist/stores/StructStore.d.ts
generated
vendored
Normal file
30
node_modules/structure-chart/dist/stores/StructStore.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @interface IStructConfig
|
||||
* Configuration of StructureChart
|
||||
*/
|
||||
export interface IStructConfig {
|
||||
'minZoom'?: number;
|
||||
'maxZoom'?: number;
|
||||
}
|
||||
export declare const useStructStore: import("pinia").StoreDefinition<"StructStore", import("pinia")._UnwrapAll<Pick<{
|
||||
config: import("vue").Ref<{
|
||||
minZoom?: number | undefined;
|
||||
maxZoom?: number | undefined;
|
||||
}>;
|
||||
dataSource: import("vue").Ref<any>;
|
||||
selectedElement: import("vue").Ref<any>;
|
||||
}, "dataSource" | "config" | "selectedElement">>, Pick<{
|
||||
config: import("vue").Ref<{
|
||||
minZoom?: number | undefined;
|
||||
maxZoom?: number | undefined;
|
||||
}>;
|
||||
dataSource: import("vue").Ref<any>;
|
||||
selectedElement: import("vue").Ref<any>;
|
||||
}, never>, Pick<{
|
||||
config: import("vue").Ref<{
|
||||
minZoom?: number | undefined;
|
||||
maxZoom?: number | undefined;
|
||||
}>;
|
||||
dataSource: import("vue").Ref<any>;
|
||||
selectedElement: import("vue").Ref<any>;
|
||||
}, never>>;
|
||||
6
node_modules/structure-chart/dist/structure-chart.js
generated
vendored
Normal file
6
node_modules/structure-chart/dist/structure-chart.js
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { S as p } from "./index-d950fc13.js";
|
||||
import "vue";
|
||||
import "pinia";
|
||||
export {
|
||||
p as StructChart
|
||||
};
|
||||
283
node_modules/structure-chart/dist/structure-chart.umd.cjs
generated
vendored
Normal file
283
node_modules/structure-chart/dist/structure-chart.umd.cjs
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/structure-chart/dist/style.css
generated
vendored
Normal file
1
node_modules/structure-chart/dist/style.css
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
@charset "UTF-8";.node-container[data-v-2fe285ed]{border-collapse:collapse;margin:0 auto}.root-node td[data-v-2fe285ed]{text-align:center;width:100%}.element-container[data-v-2fe285ed]{background:white;border:1px solid #f0efef;border-radius:5px;box-sizing:border-box;box-shadow:0 20px 20px -20px #a3a5ae36;display:inline-flex;flex-direction:column;position:relative;margin:0 1px 2px;min-width:9rem;text-align:left;transition-duration:.25s}.element-container[data-v-2fe285ed]:hover{box-shadow:0 6px 10px #7c7c7c;cursor:pointer;transform:scale(1.05);z-index:20}.root-element[data-v-2fe285ed]{border-top:3px solid hsl(212,86%,64%)}.child-element[data-v-2fe285ed]{border-top:3px solid hsl(180,62%,55%);width:99%}.subchild-element[data-v-2fe285ed]{border-top:3px solid #995511}.section-primary[data-v-2fe285ed],.section-secondary[data-v-2fe285ed],.section-list[data-v-2fe285ed]{font-family:sans-serif;display:flex;align-items:center;padding:6px 15px 6px 20px;bottom:0;justify-content:space-between}.section-primary .column-content[data-v-2fe285ed],.section-secondary .column-content[data-v-2fe285ed],.section-list .column-content[data-v-2fe285ed]{min-width:120px}.section-primary .column-side[data-v-2fe285ed],.section-secondary .column-side[data-v-2fe285ed],.section-list .column-side[data-v-2fe285ed]{margin-left:20px}.section-primary .column-side .side-button[data-v-2fe285ed],.section-secondary .column-side .side-button[data-v-2fe285ed],.section-list .column-side .side-button[data-v-2fe285ed]{background-color:#d9d9d9;border:1px solid white;border-radius:8px;color:#717181;display:inline-grid;align-items:center;min-width:32px;max-width:auto;padding:0 8px;height:36px;text-align:center}.section-primary .header[data-v-2fe285ed],.section-secondary .header[data-v-2fe285ed],.section-tertiary .header[data-v-2fe285ed]{color:#334454;font-size:1.1rem;line-height:1.5rem;margin:0}.section-primary .header[data-v-2fe285ed]{font-weight:700!important}.section-secondary[data-v-2fe285ed],.section-tertiary[data-v-2fe285ed]{border-top:1px solid #d9d9d9}.section-secondary .header[data-v-2fe285ed]{font-weight:500!important}.section-tertiary[data-v-2fe285ed]{background:#fafafa;padding-left:10px}.section-tertiary .header[data-v-2fe285ed]{font-weight:300!important}.section-tertiary .header[data-v-2fe285ed]:before{content:"\2022";color:#394b5c;font-weight:700;display:inline-block;width:.9em}.node-children[data-v-2fe285ed]{vertical-align:top}.nodeline[data-v-2fe285ed]{height:1.75rem}.nodeline-down[data-v-2fe285ed]{background:#B0B4B0;margin-left:auto;margin-right:auto;margin-top:-1rem;margin-bottom:-1rem;height:1.9rem;width:.125rem;float:none}.nodeline-top[data-v-2fe285ed]{border-top-color:#b0b4b0;border-top-style:solid;border-top-width:2px}.nodeline-bottom[data-v-2fe285ed]{border-bottom-color:#b0b4b0;border-bottom-style:solid;border-bottom-width:2px}.nodeline-right[data-v-2fe285ed]{border-right-color:#b0b4b0;border-right-style:solid;border-right-width:2px}.nodeline-left[data-v-2fe285ed]{border-left-color:#b0b4b0;border-left-style:solid;border-left-width:2px}.subchild-section[data-v-2fe285ed]{margin-left:1rem;border-collapse:collapse}.subchild-section-nodeline[data-v-2fe285ed]{min-width:20px;max-width:30px}.subchild-more[data-v-2fe285ed]{background:transparent url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPgo8c3ZnIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDE2IDE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiMwMDAwMDAiIGNsYXNzPSJiaSBiaS1jYXJldC1kb3duLWZpbGwiPgogIDxwYXRoIGQ9Ik03LjI0NyAxMS4xNCAyLjQ1MSA1LjY1OEMxLjg4NSA1LjAxMyAyLjM0NSA0IDMuMjA0IDRoOS41OTJhMSAxIDAgMCAxIC43NTMgMS42NTlsLTQuNzk2IDUuNDhhMSAxIDAgMCAxLTEuNTA2IDB6Ii8+Cjwvc3ZnPg==) no-repeat center bottom;background-size:16px;border:1px solid white;border-radius:5px;cursor:pointer;padding:5px 10px;color:#300;width:36px;height:40px;text-align:center}.struct-chart[data-v-70ed3ff9]{width:100vw;height:100vh;background-color:#fff;user-select:none}.struct-chart-container[data-v-70ed3ff9]{width:auto;height:auto}
|
||||
59
node_modules/structure-chart/package.json
generated
vendored
Normal file
59
node_modules/structure-chart/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"name": "structure-chart",
|
||||
"version": "0.0.9",
|
||||
"description": "Structure Chart",
|
||||
"keywords": [
|
||||
"vue",
|
||||
"vue3",
|
||||
"structure",
|
||||
"chart"
|
||||
],
|
||||
"author": "Suchin Prasongbundit",
|
||||
"type": "module",
|
||||
"main": "./dist/structure-chart.umd.js",
|
||||
"module": "./dist/structure-chart.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/structure-chart.js",
|
||||
"require": "./dist/structure-chart.umd.js"
|
||||
},
|
||||
"./structure-chart.css": "./dist/style.css",
|
||||
"./dist/*": "./dist/*"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check build-only",
|
||||
"build-npm": "vue-tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
||||
},
|
||||
"dependencies": {
|
||||
"html2canvas": "^1.4.1",
|
||||
"jspdf": "^2.5.1",
|
||||
"panzoom": "^9.4.3",
|
||||
"pinia": "^2.0.32",
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.2.0",
|
||||
"@types/node": "^18.14.2",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-plugin-vue": "^9.9.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"sass": "^1.61.0",
|
||||
"typescript": "~4.8.4",
|
||||
"vite": "^4.1.4",
|
||||
"vite-plugin-dts": "^2.2.0",
|
||||
"vue-tsc": "^1.2.0"
|
||||
}
|
||||
}
|
||||
25
node_modules/structure-chart/src/App.vue
generated
vendored
Normal file
25
node_modules/structure-chart/src/App.vue
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import StructChart from './components/StructChart.vue'
|
||||
import chartData from './assets/structChartData2'
|
||||
const dataSource = ref(chartData)
|
||||
|
||||
const chartRef = ref()
|
||||
|
||||
const savePNG = () => {
|
||||
chartRef.value.savePNG()
|
||||
}
|
||||
const savePDF = () => {
|
||||
chartRef.value.savePDF()
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<button @click="savePNG()">Save PNG</button>
|
||||
<button @click="savePDF()">Save PDF</button>
|
||||
<StructChart ref="chartRef" :dataSource="dataSource"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
272
node_modules/structure-chart/src/assets/structChartData.ts
generated
vendored
Normal file
272
node_modules/structure-chart/src/assets/structChartData.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/**
|
||||
* ข้อมูลจะเริ่มต้นที่ Root ที่มีเพียงอันเดียว แล้วแตกรากลงมา ชื่อฟิลด์ต่าง ๆ จะพยายามให้เหมือนกับ TreeList ฟิลด์ไหนใช้ชื่อต่างกันก็ระบุมาได้นะว่าใน TreeList ใช้อะไร จะได้ใช้ให้เหมือนกัน
|
||||
* - Object ส่วนที่เป็นหน่วยงานประกอบด้วย
|
||||
* - deptID : Unique ID ของสำนัก/ฝ่าย/กอง เป็น Int หรือ String ก็ได้ ขอแค่ระบุให้ชัด
|
||||
* - departmentName : ชื่อสำนัก/ฝ่าย/กอง
|
||||
* - totalPositionCount : จำนวนตำแหน่งทั้งหมดในหน่วยงาน หรือในส่วนงานย่อย
|
||||
* - totalPositionVacant : จำนวนตำแหน่งว่างทั้งหมดในหน่วยงาน
|
||||
* - นอกจากนั้นในแต่ละหน่วยงานยังมี Object ได้อีก 3 แบบคือ
|
||||
* - heads : เป็น Array ของ Object ที่เก็บตำแหน่งระดับหัวหน้า
|
||||
* - offcier : เป็น Array ของ Object ที่เก็บตำแหน่งระดับเจ้าหน้าที่
|
||||
* - children : เป็น Array ของหน่วยงานย่อย ซึ่ง Root ของ children ต้องเป็น Object ของหน่วยงานเสมอ
|
||||
* - Object ส่วนที่เป็นตำแหน่งประกอบด้วย
|
||||
* - positionID : Unique ID ของประเภทตำแหน่งนั้น เงื่อนไขเหมือน deptID
|
||||
* - positionName : ชื่อตำแหน่ง
|
||||
* - positionNum : เลขที่ประจำตำแหน่ง เช่น กทข.
|
||||
* - totalPositionCount : จำนวนตำแหน่งทั้งหมด
|
||||
* - totalPositionVacant : จำนวนตำแหน่งว่างทั้งหมด
|
||||
*/
|
||||
const chartData = { // root ของข้อมูลเป็น Object (ไม่ใช่ Array แบบ TreeList)
|
||||
deptID: 1, // Unique ID ของสำนัก/ฝ่าย/กอง (ถ้ามี?)
|
||||
departmentName: "สำนักงานเลขานุการผู้ว่าราชการกรุงเทพมหานคร", // ชื่อสำนัก/ฝ่าย/กอง
|
||||
totalPositionCount: 75, // จำนวนตำแหน่งทั้งหมดในหน่วยงาน
|
||||
totalPositionVacant: 2, // จำนวนตำแหน่งว่างทั้งหมดในหน่วยงาน
|
||||
heads: [ // Array ของผู้บริหารในหน่วยงานนั้น ๆ (ผู้อำนวยการ/หัวหน้า)
|
||||
{
|
||||
positionID: 2, // Unique ID ของประเภทตำแหน่งนั้น (ถ้ามี?)
|
||||
positionName: "ผู้อำนวยการสูง", // ชื่อตำแหน่ง
|
||||
positionNum: "(หัวหน้าสำนักงาน)", // เลขที่ประจำตำแหน่ง (ถ้ามี) เช่นพวก กทข.
|
||||
totalPositionCount: 1, // จำนวนตำแหน่งทั้งหมด
|
||||
totalPositionVacant: 0 // จำนวนตำแหน่งว่างทั้งหมด
|
||||
}
|
||||
],
|
||||
officer: [ // Array ของเจ้าหน้าที่ในหน่วยงาน (รายการตำแหน่งในหน่วยงานที่ขึ้นตรงกับ deptID นั้น ๆ)
|
||||
],
|
||||
children: [ // Array ของหน่วยงานย่อย เช่น ฝ่าย กอง
|
||||
{ // โครงสร้างที่เหลือจะเหมือนกับส่วน Root ทุกอย่าง คือแต่ละหน่วยงานย่อย มี heads ไว้ระบุหัวหน้า ผู้อำนวยการ มี Officer ไว้ระบุรายการตำแหน่งในหน่วยงาน มี Children ไว้ระบุหน่วยงานย่อย
|
||||
deptID: 3,
|
||||
departmentName: "ฝ่ายบริหารทั่วไป",
|
||||
totalPositionCount: 14,
|
||||
totalPositionVacant: 0,
|
||||
heads: [
|
||||
{
|
||||
positionID: 2,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ชพ. (หัวหน้าฝ่าย)",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
],
|
||||
officer: [
|
||||
{
|
||||
positionID: 3,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ปก./ชก",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0
|
||||
},
|
||||
{
|
||||
positionID: 4,
|
||||
positionName: "นักทรัพยากรบุคคล",
|
||||
positionNum: "ปก./ชก.",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacnt: 0
|
||||
},
|
||||
{
|
||||
positionID: 5,
|
||||
positionName: "นักวิชาการเงินและบัญชี",
|
||||
positionNum: "ปก./ชก.",
|
||||
totalPositionCount: 2,
|
||||
totalPositionVacnt: 0
|
||||
},
|
||||
{
|
||||
positionID: 6,
|
||||
positionName: "นักวิชาการพัสดุ",
|
||||
positionNum: "ปก./ชก.",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacnt: 0
|
||||
},
|
||||
{
|
||||
positionID: 7,
|
||||
positionName: "เจ้าพนักงานการเงินและบัญชี",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 3,
|
||||
totalPositionVacnt: 0
|
||||
},
|
||||
{
|
||||
positionID: 8,
|
||||
positionName: "เจ้าพนักงานพัสดุ",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacnt: 0
|
||||
},
|
||||
{
|
||||
positionID: 9,
|
||||
positionName: "เจ้าพนักงานธุรการ",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 4,
|
||||
totalPositionVacnt: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
deptID: 4,
|
||||
departmentName: "ส่วนประสานนโยบาย",
|
||||
totalPositionCount: 15,
|
||||
totalPositionVacant: 0,
|
||||
heads: [
|
||||
{
|
||||
positionID: 10,
|
||||
positionName: "ผู้อำนวยการต้น",
|
||||
positionNum: "(ผู้อำนวยการส่วน)",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0,
|
||||
}
|
||||
],
|
||||
children: [
|
||||
{
|
||||
deptID: 11,
|
||||
departmentName: "กลุ่มงานประชุม",
|
||||
totalPositionCount: 6,
|
||||
totalPositionVacant: 0,
|
||||
heads: [
|
||||
{
|
||||
positionID: 11,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0,
|
||||
}
|
||||
],
|
||||
officer: [
|
||||
{
|
||||
positionID: 12,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ปก./ชก.",
|
||||
totalPositionCount: 4,
|
||||
totalPositionVacant: 0
|
||||
},
|
||||
{
|
||||
positionID: 13,
|
||||
positionName: "เจ้าพนักงานธุรการ",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
deptID: 12,
|
||||
departmentName: "กลุ่มงานการเมืองและประสานนโยบาย",
|
||||
totalPositionCount: 8,
|
||||
totalPositionVacant: 0,
|
||||
heads: [
|
||||
{
|
||||
positionID: 14,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0,
|
||||
}
|
||||
],
|
||||
officer: [
|
||||
{
|
||||
positionID: 15,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ปก./ชก.",
|
||||
totalPositionCount: 4,
|
||||
totalPositionVacant: 0
|
||||
},
|
||||
{
|
||||
positionID: 16,
|
||||
positionName: "เจ้าพนักงานสถิติ",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0
|
||||
},
|
||||
{
|
||||
positionID: 17,
|
||||
positionName: "เจ้าพนักงานธุรการ",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 2,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
deptID: 14,
|
||||
departmentName: "ส่วนเรื่องราวร้องทุกข์",
|
||||
totalPositionCount: 15,
|
||||
totalPositionVacant: 0,
|
||||
heads: [
|
||||
{
|
||||
positionID: 18,
|
||||
positionName: "ผู้อำนวยการต้น",
|
||||
positionNum: "(ผู้อำนวยการส่วน)",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
],
|
||||
children: [
|
||||
{
|
||||
deptID: 15,
|
||||
departmentName: "กลุ่มงานรับเรื่องราวร้องทุกข์",
|
||||
totalPositionCount: 7,
|
||||
totalPositionVacant: 0,
|
||||
heads: [
|
||||
{
|
||||
positionID: 19,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
],
|
||||
officer: [
|
||||
{
|
||||
positionID: 20,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ปก./ชก.",
|
||||
totalPositionCount: 4,
|
||||
totalPositionVacant: 0
|
||||
},
|
||||
{
|
||||
positionID: 21,
|
||||
positionName: "เจ้าพนักงานธุรการ",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 2,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
deptID: 16,
|
||||
departmentName: "กลุ่มงานตรวจสอบ ติดตามและประมวลผล",
|
||||
totalPositionCount: 7,
|
||||
totalPositionVacant: 0,
|
||||
heads: [
|
||||
{
|
||||
positionID: 22,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
|
||||
totalPositionCount: 1,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
],
|
||||
officer: [
|
||||
{
|
||||
positionID: 23,
|
||||
positionName: "นักจัดการงานทั่วไป",
|
||||
positionNum: "ปก./ชก.",
|
||||
totalPositionCount: 4,
|
||||
totalPositionVacant: 0
|
||||
},
|
||||
{
|
||||
positionID: 24,
|
||||
positionName: "เจ้าพนักงานธุรการ",
|
||||
positionNum: "ปง./ชง.",
|
||||
totalPositionCount: 2,
|
||||
totalPositionVacant: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default chartData
|
||||
1189
node_modules/structure-chart/src/assets/structChartData2.ts
generated
vendored
Normal file
1189
node_modules/structure-chart/src/assets/structChartData2.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
153
node_modules/structure-chart/src/components/StructChart.vue
generated
vendored
Normal file
153
node_modules/structure-chart/src/components/StructChart.vue
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
<script setup lang="ts">
|
||||
/**
|
||||
* import Vue's Stuff
|
||||
*/
|
||||
import { computed, watch, onMounted } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import panzoom from 'panzoom'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { jsPDF } from "jspdf"
|
||||
|
||||
/**
|
||||
* import Chart Node componenet
|
||||
*/
|
||||
import StructChartNode from './StructChartNode.vue'
|
||||
|
||||
/**
|
||||
* import Pinia Store
|
||||
*/
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useStructStore } from '../stores/StructStore'
|
||||
import type { IStructConfig } from '../stores/StructStore'
|
||||
const { config, dataSource, selectedElement } = storeToRefs(useStructStore())
|
||||
|
||||
/**
|
||||
* define Prop (Pass down value)
|
||||
*/
|
||||
const props = defineProps({
|
||||
config: Object as PropType<IStructConfig>, // Chart configuration
|
||||
dataSource: Object, // Data Source
|
||||
})
|
||||
|
||||
/**
|
||||
* define Emit (Child to Parent value)
|
||||
*/
|
||||
const emit = defineEmits([
|
||||
'onElementClick', // Event call when user click each element
|
||||
])
|
||||
|
||||
/**
|
||||
* Computed Property
|
||||
* - minZoom : if parent don't send minZoom value, use default from StructStore (0.5)
|
||||
* - maxZoom : if parent don't send maxZoom value, use default from StructStore (2)
|
||||
*/
|
||||
const minZoom = computed(() => props.config?.minZoom ? props.config.minZoom : config.value.minZoom)
|
||||
const maxZoom = computed(() => props.config?.maxZoom ? props.config.maxZoom : config.value.maxZoom)
|
||||
|
||||
/**
|
||||
* จับภาพหน้าจอออกมาเป็น canvas object ส่งให้ฟังก์ชันอื่น ๆ นำไปประมวลผลต่อ
|
||||
* @param scale ขนาดของภาพที่ต้องการ ค่าพื้นฐานคือ 3 เท่าของหน้าจอ
|
||||
*/
|
||||
const captureChart = async(scale: number = 3) => {
|
||||
return await html2canvas(document.querySelector('.struct-chart-container') as HTMLElement, {
|
||||
scale: scale,
|
||||
width: (document.querySelector('.struct-chart-container') as HTMLElement).scrollWidth,
|
||||
height: (document.querySelector('.struct-chart-container') as HTMLElement).scrollHeight
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* จับภาพหน้าจอออกมาเป็น PNG แล้วดาวน์โหลด
|
||||
* @param scale ขนาดของภาพที่ต้องการ ค่าพื้นฐานคือ 3 เท่าของหน้าจอ
|
||||
*/
|
||||
const savePNG = async(scale: number = 3) => {
|
||||
let canvas = await captureChart(scale)
|
||||
let anchor = document.createElement('a')
|
||||
anchor.href = canvas.toDataURL('image/png')
|
||||
anchor.download = 'structure-chart.png'
|
||||
anchor.click()
|
||||
anchor.remove()
|
||||
}
|
||||
|
||||
/**
|
||||
* savePDF - save canvas to PNG format and embed in PDF file then download.
|
||||
*/
|
||||
const savePDF = async(scale: number = 3) => {
|
||||
let canvas = await captureChart(scale)
|
||||
const doc = new jsPDF('l', 'px', 'a4')
|
||||
// const doc = new jsPDF('p', 'px', 'a4')
|
||||
let pageWidth = doc.internal.pageSize.getWidth()
|
||||
let pageHeight = doc.internal.pageSize.getHeight()
|
||||
|
||||
let widthRatio = pageWidth / canvas.width
|
||||
let heightRatio = pageHeight / canvas.height
|
||||
let canvasRatio = widthRatio > heightRatio ? heightRatio : widthRatio
|
||||
|
||||
let canvasWidth = canvas.width * canvasRatio;
|
||||
let canvasHeight = canvas.height * canvasRatio;
|
||||
|
||||
let marginX = (pageWidth - canvasWidth) / 2
|
||||
let marginY = (pageHeight - canvasHeight) / 2
|
||||
doc.addImage(canvas.toDataURL('image/png'), 'PNG', marginX, marginY, canvasWidth, canvasHeight);
|
||||
doc.save('structure-chart.pdf');
|
||||
}
|
||||
|
||||
// export method to public
|
||||
defineExpose({ savePNG, savePDF })
|
||||
|
||||
/**
|
||||
* onMounted:
|
||||
* - assign dataSource to internal Store
|
||||
* - init panzoom
|
||||
*/
|
||||
onMounted(async () => {
|
||||
dataSource.value = props.dataSource
|
||||
|
||||
// PanZoom
|
||||
// let element = document.querySelector('.struct-chart-container')
|
||||
// panzoom(element as HTMLElement, { // or let instance = panzoom(...)
|
||||
// smoothScroll: true,
|
||||
// minZoom: minZoom.value,
|
||||
// maxZoom: maxZoom.value
|
||||
// })
|
||||
})
|
||||
|
||||
/**
|
||||
* watch if dataSource change -> update internal Store
|
||||
*/
|
||||
watch(() => props.dataSource, (newVal) => {
|
||||
dataSource.value = newVal
|
||||
// if (dataSourceLock.value === undefined) dataSourceLock.value = newVal
|
||||
})
|
||||
|
||||
/**
|
||||
* watch if user click element (selectedElement in internal Store change value)
|
||||
*/
|
||||
watch(selectedElement, () => {
|
||||
// emit onElementClick when user select element
|
||||
emit('onElementClick', selectedElement)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="struct-chart">
|
||||
<div class="struct-chart-container">
|
||||
<StructChartNode :dataSource="props.dataSource" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.struct-chart {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: white;
|
||||
// cursor: grab;
|
||||
user-select: none;
|
||||
}
|
||||
.struct-chart-container {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
449
node_modules/structure-chart/src/components/StructChartNode.vue
generated
vendored
Normal file
449
node_modules/structure-chart/src/components/StructChartNode.vue
generated
vendored
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
<script setup lang="ts">
|
||||
import { toRefs, watch, onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useStructStore } from '../stores/StructStore'
|
||||
|
||||
const { dataSource, selectedElement } = storeToRefs(useStructStore())
|
||||
|
||||
const props = defineProps({
|
||||
dataSource: Object
|
||||
})
|
||||
|
||||
const propDataSource = toRefs(props).dataSource
|
||||
|
||||
onMounted(() => {
|
||||
// console.log(propDataSource?.value)
|
||||
})
|
||||
|
||||
watch(() => props.dataSource, (newVal) => {
|
||||
// console.log(newVal)
|
||||
})
|
||||
|
||||
const onElementSelected = (data: any) => {
|
||||
selectedElement.value = data
|
||||
}
|
||||
|
||||
const onSideElementClick = (data: any) => {
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
const numberFormat = (data: number) => {
|
||||
return new Intl.NumberFormat().format(data)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="node-container">
|
||||
<tbody>
|
||||
<!-- ส่วนนี้คือ Root Node เช่น "สำนักงานเลขานุการผู้ว่าราชการกรุงเทพมหานคร" -->
|
||||
<template v-if="propDataSource">
|
||||
<tr class="root-node">
|
||||
<td :colspan="propDataSource.children?.length * 2">
|
||||
<div class="element-container root-element" @click="onElementSelected(propDataSource?.deptID)">
|
||||
<div class="section-primary">
|
||||
<div class="column-content">
|
||||
<span class="header">{{ propDataSource.departmentName }}</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button" @click.stop="onSideElementClick('test')">
|
||||
{{ numberFormat(propDataSource.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ถ้ามีรายการตำแหน่งของ ผอ. -->
|
||||
<template v-if="propDataSource.heads.length > 0">
|
||||
<template v-for="head in propDataSource.heads" :key="head.positionID">
|
||||
<div class="section-secondary">
|
||||
<div class="column-content">
|
||||
<span class="header">{{ head.positionName }} {{ head.positionNum }}</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(head.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<!-- ถ้ามีรายการตำแหน่งของเจ้าหน้าที่ -->
|
||||
<template v-if="propDataSource.officer.length > 0">
|
||||
<div class="section-tertiary">
|
||||
<template v-for="officer in propDataSource.officer" :key="officer.positionID">
|
||||
<div class="section-list">
|
||||
<div class="column-content">
|
||||
<span class="header">
|
||||
{{ officer.positionName }} {{ officer.positionNum }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(officer.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<!-- เส้นแบ่ง Node -->
|
||||
<template v-if="propDataSource?.children?.length > 0">
|
||||
<tr class="nodeline">
|
||||
<td :colspan="propDataSource?.children?.length * 2">
|
||||
<div class="nodeline-down"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="nodeline">
|
||||
<td class="nodeline-right"></td>
|
||||
<template v-for="n in propDataSource?.children?.length - 1" v-bind:key="n">
|
||||
<td class="nodeline-left nodeline-top"></td>
|
||||
<td class="nodeline-right nodeline-top"></td>
|
||||
</template>
|
||||
<td class="nodeline-left"></td>
|
||||
</tr>
|
||||
|
||||
<!-- Child Node ทั้งหมดอยู่ที่นี่ -->
|
||||
<tr class="node-children">
|
||||
<!-- วนรอบเพื่อแสดง Root ของ Child Node เป็นคอลัมน์ต่าง ๆ การแสดงผลจะเป็นแบบแนวนอนสำหรับ Child Node ลำดับแรก จากนั้นจะเป็นแบบแนวตั้งในลำดับถัด ๆ ไป -->
|
||||
<template v-for="child in propDataSource?.children" :key="child.deptID">
|
||||
<td colspan="2">
|
||||
<!-- ส่วนนี้คือ Root ของ Child Node เช่น "ฝ่ายบริหารทั่วไป" -->
|
||||
<div class="element-container child-element" @click="onElementSelected(child?.deptID)">
|
||||
<div class="section-primary">
|
||||
<div class="column-content">
|
||||
<span class="header">{{ child.departmentName }}</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(child.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ถ้ามีรายการตำแหน่ง ผอ. -->
|
||||
<template v-if="child.heads?.length > 0">
|
||||
<template v-for="head in child.heads" :key="head.positionID">
|
||||
<div class="section-secondary">
|
||||
<div class="column-content">
|
||||
<span class="header">{{ head.positionName }} {{ head.positionNum }}</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(head.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<!-- ถ้ามีรายการตำแหน่งพนักงาน -->
|
||||
<template v-if="child.officer?.length > 0">
|
||||
<div class="section-tertiary">
|
||||
<template v-for="officer in child.officer" :key="officer.positionID">
|
||||
<div class="section-list">
|
||||
<div class="column-content">
|
||||
<span class="header">
|
||||
{{ officer.positionName }} {{ officer.positionNum }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(officer.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<!-- ถ้ามีกลุ่ม/กองย่อยภายใต้ Child Node นี้ เช่น "กลุ่มงานประชุม" -->
|
||||
<template v-if="child.children?.length > 0">
|
||||
<table class="subchild-section">
|
||||
<tbody>
|
||||
<template v-for="(group, index) in child.children" :key="group.deptID">
|
||||
<tr>
|
||||
<td class="nodeline-left nodeline-bottom subchild-section-nodeline"></td>
|
||||
<td rowspan="2">
|
||||
<div class="element-container subchild-element" @click="onElementSelected(group?.deptID)" >
|
||||
<div class="section-primary">
|
||||
<div class="column-content">
|
||||
<span class="header">
|
||||
{{ group.departmentName }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(group.totalPositionCount) }}
|
||||
</div>
|
||||
<template v-if="group.children?.length > 0">
|
||||
<span class="subchild-more"></span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="group.heads?.length > 0">
|
||||
<template v-for="groupHead in group.heads"
|
||||
:key="groupHead.positionID">
|
||||
<div class="section-secondary">
|
||||
<div class="column-content">
|
||||
<span class="header">{{ groupHead.positionName }} {{
|
||||
groupHead.positionNum }}</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(groupHead.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="group.officer?.length > 0">
|
||||
<div class="section-tertiary">
|
||||
<template v-for="groupOfficer in group.officer"
|
||||
:key="groupOfficer.positionID">
|
||||
<div class="section-list">
|
||||
<div class="column-content">
|
||||
<span class="header">
|
||||
{{ groupOfficer.positionName }} {{
|
||||
groupOfficer.positionNum }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="column-side">
|
||||
<div class="side-button">
|
||||
{{ numberFormat(groupOfficer.totalPositionCount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<template v-if="index != child.children.length - 1">
|
||||
<td class="nodeline-left nodeline-top subchild-section-nodeline"></td>
|
||||
</template>
|
||||
<template v-else>
|
||||
<td></td>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
/**
|
||||
* 1 level = 1 node
|
||||
* แต่ละ node มีสิ่งที่เรียกว่า element
|
||||
* 1 element = 1 person/dept
|
||||
*/
|
||||
|
||||
// container ของทั้ง node (level)
|
||||
.node-container {
|
||||
border-collapse: collapse;
|
||||
margin: 0 auto 0 auto;
|
||||
}
|
||||
|
||||
// root node element
|
||||
.root-node {
|
||||
td {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// container ของ element
|
||||
.element-container {
|
||||
background: white;
|
||||
border: 1px solid #f0efef;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0px 20px 20px -20px hsla(229, 6%, 66%, 0.212);
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
margin: 0 1px 2px 1px;
|
||||
min-width: 9rem;
|
||||
text-align: left;
|
||||
transition-duration: 250ms;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 6px 10px #7c7c7c;
|
||||
cursor: pointer;
|
||||
transform: scale(1.05);
|
||||
z-index: 20;
|
||||
}
|
||||
}
|
||||
|
||||
// กรณีเป็น root element ใช้สีฟ้า
|
||||
.root-element {
|
||||
border-top: 3px solid hsl(212, 86%, 64%);
|
||||
}
|
||||
|
||||
// กรณีเป็น child element ใช้สีเขียว
|
||||
.child-element {
|
||||
border-top: 3px solid hsl(180, 62%, 55%);
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
// กรณีเป็น sub child element ใช้สีน้ำตาล
|
||||
.subchild-element {
|
||||
border-top: 3px solid #995511;
|
||||
}
|
||||
|
||||
.section-primary,
|
||||
.section-secondary,
|
||||
.section-list {
|
||||
font-family: sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 15px 6px 20px;
|
||||
bottom: 0;
|
||||
justify-content: space-between;
|
||||
|
||||
.column-content {
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.column-side {
|
||||
margin-left: 20px;
|
||||
|
||||
.side-button {
|
||||
background-color: #d9d9d9;
|
||||
border: 1px solid white;
|
||||
// border-radius: 50%;
|
||||
border-radius: 8px;
|
||||
color: #717181;
|
||||
display: inline-grid;
|
||||
align-items: center;
|
||||
min-width: 32px;
|
||||
max-width: auto;
|
||||
padding: 0 8px;
|
||||
height: 36px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-primary, .section-secondary, .section-tertiary {
|
||||
.header {
|
||||
color: #334454;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.section-primary {
|
||||
.header {
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.section-secondary,
|
||||
.section-tertiary {
|
||||
border-top: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.section-secondary {
|
||||
.header {
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
}
|
||||
.section-tertiary {
|
||||
background: #fafafa;
|
||||
padding-left: 10px;
|
||||
|
||||
.header {
|
||||
font-weight: 300 !important;
|
||||
}
|
||||
.header::before {
|
||||
content: "\2022";
|
||||
color: #394b5c;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
width: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
.node-children {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.nodeline {
|
||||
height: 1.75rem;
|
||||
}
|
||||
|
||||
// $line-color: #D2D6DB;
|
||||
$line-color: #B0B4B0;
|
||||
|
||||
.nodeline-down {
|
||||
background: $line-color;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: -1rem;
|
||||
margin-bottom: -1rem;
|
||||
height: 1.9rem;
|
||||
width: 0.125rem;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.nodeline-top {
|
||||
border-top-color: $line-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 2px;
|
||||
}
|
||||
|
||||
.nodeline-bottom {
|
||||
border-bottom-color: $line-color;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
|
||||
.nodeline-right {
|
||||
border-right-color: $line-color;
|
||||
border-right-style: solid;
|
||||
border-right-width: 2px;
|
||||
}
|
||||
|
||||
.nodeline-left {
|
||||
border-left-color: $line-color;
|
||||
border-left-style: solid;
|
||||
border-left-width: 2px;
|
||||
}
|
||||
|
||||
.subchild-section {
|
||||
margin-left: 1rem;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.subchild-section-nodeline {
|
||||
min-width: 20px;
|
||||
max-width: 30px;
|
||||
}
|
||||
|
||||
.subchild-more {
|
||||
background: transparent url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPgo8c3ZnIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDE2IDE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiMwMDAwMDAiIGNsYXNzPSJiaSBiaS1jYXJldC1kb3duLWZpbGwiPgogIDxwYXRoIGQ9Ik03LjI0NyAxMS4xNCAyLjQ1MSA1LjY1OEMxLjg4NSA1LjAxMyAyLjM0NSA0IDMuMjA0IDRoOS41OTJhMSAxIDAgMCAxIC43NTMgMS42NTlsLTQuNzk2IDUuNDhhMSAxIDAgMCAxLTEuNTA2IDB6Ii8+Cjwvc3ZnPg==) no-repeat center bottom;
|
||||
background-size: 16px;
|
||||
border: 1px solid white;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
padding: 5px 10px;
|
||||
color: #330000;
|
||||
width: 36px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
3
node_modules/structure-chart/src/index.ts
generated
vendored
Normal file
3
node_modules/structure-chart/src/index.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import StructChart from './components/StructChart.vue'
|
||||
|
||||
export { StructChart }
|
||||
7
node_modules/structure-chart/src/main.ts
generated
vendored
Normal file
7
node_modules/structure-chart/src/main.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(createPinia())
|
||||
app.mount('#app')
|
||||
32
node_modules/structure-chart/src/stores/StructStore.ts
generated
vendored
Normal file
32
node_modules/structure-chart/src/stores/StructStore.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
/**
|
||||
* @interface IStructConfig
|
||||
* Configuration of StructureChart
|
||||
*/
|
||||
export interface IStructConfig {
|
||||
'minZoom'?: number,
|
||||
'maxZoom'?: number
|
||||
}
|
||||
|
||||
export const useStructStore = defineStore('StructStore', () => {
|
||||
|
||||
// StructureChart configuration
|
||||
const config = ref<IStructConfig>({
|
||||
'minZoom': 0.5,
|
||||
'maxZoom': 2.0
|
||||
})
|
||||
|
||||
// ข้อมูลที่กำลังแสดงอยู่
|
||||
const dataSource = ref()
|
||||
|
||||
// Current (Active) Node
|
||||
const selectedElement = ref()
|
||||
|
||||
return {
|
||||
config,
|
||||
dataSource,
|
||||
selectedElement
|
||||
}
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue