diff --git a/package.json b/package.json index 8458556f..219303e6 100644 --- a/package.json +++ b/package.json @@ -26,12 +26,14 @@ "@vuepic/vue-datepicker": "^3.6.3", "axios": "^1.6.7", "bma-org-chart": "^0.0.8", + "highlight.js": "^11.10.0", "keycloak-js": "^20.0.2", "moment": "^2.29.4", "pinia": "^2.0.29", "quasar": "^2.11.1", "socket.io-client": "^4.7.4", "structure-chart": "^0.0.9", + "v-code-diff": "^1.12.0", "vue": "^3.4.15", "vue-currency-input": "^3.0.5", "vue-router": "^4.1.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31201bb2..af1a5006 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ importers: bma-org-chart: specifier: ^0.0.8 version: 0.0.8(typescript@4.7.4) + highlight.js: + specifier: ^11.10.0 + version: 11.10.0 keycloak-js: specifier: ^20.0.2 version: 20.0.5 @@ -62,6 +65,9 @@ importers: structure-chart: specifier: ^0.0.9 version: 0.0.9(typescript@4.7.4) + v-code-diff: + specifier: ^1.12.0 + version: 1.12.0(vue@3.4.31(typescript@4.7.4)) vue: specifier: ^3.4.15 version: 3.4.31(typescript@4.7.4) @@ -524,6 +530,18 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@intlify/core-base@9.13.1': + resolution: {integrity: sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@9.13.1': + resolution: {integrity: sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==} + engines: {node: '>= 16'} + + '@intlify/shared@9.13.1': + resolution: {integrity: sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==} + engines: {node: '>= 16'} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1369,6 +1387,13 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + diff-match-patch@1.0.5: + resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1853,6 +1878,10 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + highlight.js@11.10.0: + resolution: {integrity: sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==} + engines: {node: '>=12.0.0'} + hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -3302,6 +3331,15 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true + v-code-diff@1.12.0: + resolution: {integrity: sha512-vvdCBG02mIIiW6Gx6jF119hzxELt+6TlJIwchglR1JYzboHePNxIkVBjR/aoAOVlsGa+5Vtb77cd/N84nrXWPA==} + peerDependencies: + '@vue/composition-api': ^1.4.9 + vue: ^2.6.0 || >=3.0.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -3384,6 +3422,12 @@ packages: peerDependencies: eslint: '>=6.0.0' + vue-i18n@9.13.1: + resolution: {integrity: sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + vue-router@4.4.0: resolution: {integrity: sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==} peerDependencies: @@ -3939,6 +3983,18 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@intlify/core-base@9.13.1': + dependencies: + '@intlify/message-compiler': 9.13.1 + '@intlify/shared': 9.13.1 + + '@intlify/message-compiler@9.13.1': + dependencies: + '@intlify/shared': 9.13.1 + source-map-js: 1.2.0 + + '@intlify/shared@9.13.1': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -4941,6 +4997,10 @@ snapshots: detect-libc@2.0.3: optional: true + diff-match-patch@1.0.5: {} + + diff@5.2.0: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -5580,6 +5640,8 @@ snapshots: he@1.2.0: {} + highlight.js@11.10.0: {} + hosted-git-info@2.8.9: {} hosted-git-info@4.1.0: @@ -7124,6 +7186,15 @@ snapshots: uuid@8.3.2: {} + v-code-diff@1.12.0(vue@3.4.31(typescript@4.7.4)): + dependencies: + diff: 5.2.0 + diff-match-patch: 1.0.5 + highlight.js: 11.10.0 + vue: 3.4.31(typescript@4.7.4) + vue-demi: 0.14.8(vue@3.4.31(typescript@4.7.4)) + vue-i18n: 9.13.1(vue@3.4.31(typescript@4.7.4)) + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -7195,6 +7266,13 @@ snapshots: transitivePeerDependencies: - supports-color + vue-i18n@9.13.1(vue@3.4.31(typescript@4.7.4)): + dependencies: + '@intlify/core-base': 9.13.1 + '@intlify/shared': 9.13.1 + '@vue/devtools-api': 6.6.3 + vue: 3.4.31(typescript@4.7.4) + vue-router@4.4.0(vue@3.4.31(typescript@4.7.4)): dependencies: '@vue/devtools-api': 6.6.3 diff --git a/src/main.ts b/src/main.ts index 646376a1..1944466d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,6 +14,11 @@ import th from "quasar/lang/th"; import "@vuepic/vue-datepicker/dist/main.css"; import http from "./plugins/http"; import { createPinia } from "pinia"; + +import CodeDiff from "v-code-diff"; +import json from "highlight.js/lib/languages/json"; + +CodeDiff.hljs.registerLanguage("json", json); // organization // position // positionEmployee @@ -31,6 +36,7 @@ const pinia = createPinia(); // เพิ่ม Global Filters ลงใน App app.config.globalProperties.$filters = filters; +app.use(CodeDiff); app.use(router); app.use(pinia); app.use(qDraggableTable); diff --git a/src/modules/03_logs/components/DialogDataDiff.vue b/src/modules/03_logs/components/DialogDataDiff.vue new file mode 100644 index 00000000..23c7dead --- /dev/null +++ b/src/modules/03_logs/components/DialogDataDiff.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/modules/03_logs/components/LogTable.vue b/src/modules/03_logs/components/LogTable.vue index 1bf51f98..336d543f 100644 --- a/src/modules/03_logs/components/LogTable.vue +++ b/src/modules/03_logs/components/LogTable.vue @@ -5,8 +5,13 @@ import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/modules/03_logs/stores/main"; import { storeToRefs } from "pinia"; import { useRoute } from "vue-router"; + +import DialogDataDiff from "@/modules/03_logs/components/DialogDataDiff.vue"; + const route = useRoute(); +import type { ResLog } from "@/modules/03_logs/interface/response/Main"; + /** importStore*/ const storeData = useDataStore(); const { logData, size, searchAfter, systemName, date } = storeToRefs(storeData); @@ -90,6 +95,7 @@ const columns = ref([ sort: (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), }, + { name: "responseDescription", align: "left", @@ -101,8 +107,27 @@ const columns = ref([ sort: (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), }, + { + name: "dataDiff", + align: "left", + label: "ข้อมูลที่เปลี่ยนแปลง", + field: "dataDiff", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, ]); +const openDialog = ref(false); +const currentlogData = + ref>(); +const currentDataDiff = ref<{ + before: string; + after: string; +}>({ + before: "", + after: "", +}); + const inputSearch = defineModel("inputSearch"); const pagination = ref({ page: 1, @@ -118,6 +143,7 @@ const visibleColumns = ref([ "responseCode", "logType", "responseDescription", + "dataDiff", ]); function handleScroll(event: any) { @@ -302,6 +328,36 @@ onMounted(() => { {{ col.value ?? "-" }} +
+ + ดูรายละเอียด + +
+
{{ col.value === "" || col.value === null ? "-" : col.value }} {{ col.value }} @@ -313,6 +369,101 @@ onMounted(() => {
+ + +
+
+
+ {{ + { + startTimeStamp: "เวลา", + username: "ผู้ใช้", + host: "Host", + endpoint: "Endpoint", + method: "Method", + responseCode: "Response Code", + logType: "สถานะ", + responseDescription: "ข้อความ", + dataDiff: "ข้อมูลที่เปลี่ยนแปลง", + }[index] || index + }} +
+ +
+ {{ date2Thai(new Date(item), false, true) }} +
+ +
+ {{ + item ?? "-" + }} +
+ +
+ {{ item ?? "-" }} +
+ +
+ {{ item }} +
+ +
+ +
+
+
+
diff --git a/src/modules/03_logs/interface/response/Main.ts b/src/modules/03_logs/interface/response/Main.ts index eccb7813..f0f2dd6d 100644 --- a/src/modules/03_logs/interface/response/Main.ts +++ b/src/modules/03_logs/interface/response/Main.ts @@ -13,14 +13,21 @@ interface ResRound { interface ResLog { endTimeStamp: Date; - endpoint: string; - host: string; - logType: string; - method: string; + dataDiff?: { + // + before: string; + after: string; + }; + endpoint: string; // + host: string; // + logType: string; // + method: string; // processTime: number; - responseCode: number; + responseCode: number; // startTimeStamp: Date; systemName: string; + username: string; // + responseDescription: string; // tId: string; } diff --git a/src/modules/04_system/components/formSchedule .vue b/src/modules/04_system/components/formSchedule .vue index df8bfbf0..d47c260a 100644 --- a/src/modules/04_system/components/formSchedule .vue +++ b/src/modules/04_system/components/formSchedule .vue @@ -41,7 +41,7 @@ watch(typeTime, () => {
-
+
{
-
+