@ramathibodi/nuxt-commons 0.1.50 → 0.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/components/form/ActionPad.vue +70 -60
- package/dist/runtime/components/form/EditPad.vue +144 -0
- package/dist/runtime/components/form/Table.vue +0 -6
- package/dist/runtime/components/form/TableData.vue +82 -0
- package/dist/runtime/components/model/Pad.vue +26 -74
- package/dist/runtime/composables/document/templateFormTable.js +1 -1
- package/dist/runtime/composables/userPermission.d.ts +1 -1
- package/dist/runtime/plugins/permission.js +4 -4
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -2,32 +2,35 @@
|
|
|
2
2
|
import {computed, defineExpose, ref, watchEffect} from 'vue'
|
|
3
3
|
import {cloneDeep, isEqual} from 'lodash-es'
|
|
4
4
|
import type {FormDialogCallback} from '../../types/formDialog'
|
|
5
|
+
import FormPadComponent from './Pad.vue'
|
|
5
6
|
|
|
6
|
-
interface Props {
|
|
7
|
+
interface Props extends /* @vue-ignore */ InstanceType<typeof FormPadComponent['$props']> {
|
|
7
8
|
title?: string
|
|
8
9
|
initialData?: object
|
|
9
|
-
|
|
10
|
-
updateCaption?: string
|
|
10
|
+
saveCaption?: string
|
|
11
11
|
cancelCaption?: string
|
|
12
|
+
readonly?: boolean
|
|
12
13
|
showTitle?: boolean
|
|
14
|
+
skipValidation?:boolean
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
const props = withDefaults(defineProps<Props>(), {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
saveCaption: 'บันทึก',
|
|
19
|
+
cancelCaption: 'ยกเลิก',
|
|
20
|
+
readonly: false,
|
|
19
21
|
showTitle: false,
|
|
22
|
+
skipValidation:false
|
|
20
23
|
})
|
|
21
24
|
|
|
22
25
|
const isSaving = ref<boolean>(false)
|
|
23
26
|
const formPadRef = ref()
|
|
24
|
-
const formOriginalData = ref<object>()
|
|
25
27
|
const formData = ref<object>({})
|
|
28
|
+
const formDataOriginalValue = ref<object>()
|
|
26
29
|
|
|
27
30
|
const emit = defineEmits(['create', 'update'])
|
|
28
31
|
|
|
29
32
|
function save() {
|
|
30
|
-
if (formPadRef.value
|
|
33
|
+
if (props.skipValidation || formPadRef.value?.isValid) {
|
|
31
34
|
isSaving.value = true
|
|
32
35
|
emit((isCreating.value) ? 'create' : 'update', cloneDeep(formData.value), callback)
|
|
33
36
|
}
|
|
@@ -38,7 +41,8 @@ function cancel() {
|
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
function reset() {
|
|
41
|
-
|
|
44
|
+
formDataOriginalValue.value = undefined
|
|
45
|
+
formPadRef.value?.reset()
|
|
42
46
|
loadFormData()
|
|
43
47
|
}
|
|
44
48
|
|
|
@@ -53,11 +57,11 @@ const callback: FormDialogCallback = {
|
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
const isDataChange = computed(() => {
|
|
56
|
-
return !((isCreating.value) ? isEqual(formData.value, createOriginalValue.value) : isEqual(formData.value,
|
|
60
|
+
return !((isCreating.value) ? isEqual(formData.value, createOriginalValue.value) : isEqual(formData.value, formDataOriginalValue.value))
|
|
57
61
|
})
|
|
58
62
|
|
|
59
63
|
const isCreating = computed(() => {
|
|
60
|
-
return !
|
|
64
|
+
return !formDataOriginalValue.value
|
|
61
65
|
})
|
|
62
66
|
|
|
63
67
|
const createOriginalValue = computed(() => {
|
|
@@ -65,69 +69,75 @@ const createOriginalValue = computed(() => {
|
|
|
65
69
|
})
|
|
66
70
|
|
|
67
71
|
const loadFormData = () => {
|
|
68
|
-
if (
|
|
69
|
-
formData.value = cloneDeep(
|
|
72
|
+
if (formDataOriginalValue.value) {
|
|
73
|
+
formData.value = cloneDeep(formDataOriginalValue.value)
|
|
70
74
|
}
|
|
71
75
|
else {
|
|
72
76
|
formData.value = Object.assign({}, props.initialData)
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
|
|
80
|
+
const operation = ref({ isDataChange, isCreating, isSaving, save, cancel })
|
|
81
|
+
|
|
76
82
|
watchEffect(loadFormData)
|
|
77
83
|
|
|
78
84
|
function setOriginalData(originalData?: object) {
|
|
79
|
-
|
|
85
|
+
formDataOriginalValue.value = originalData
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
defineExpose({setOriginalData,
|
|
88
|
+
defineExpose({setOriginalData,operation,formPad: formPadRef})
|
|
83
89
|
</script>
|
|
84
90
|
|
|
85
91
|
<template>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
<VCard flat>
|
|
93
|
+
<VToolbar v-if="showTitle">
|
|
94
|
+
<slot name="titleToolbar" :operation="operation">
|
|
95
|
+
<VToolbarTitle>
|
|
96
|
+
<slot name="title" :operation="operation">
|
|
97
|
+
{{ (isCreating) ? "New" : "Edit" }} {{ title }}
|
|
98
|
+
</slot>
|
|
99
|
+
</VToolbarTitle>
|
|
91
100
|
</slot>
|
|
92
|
-
</
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
>
|
|
101
|
-
<template #default="slotData">
|
|
102
|
-
<slot
|
|
103
|
-
v-bind="slotData"
|
|
104
|
-
:is-creating="isCreating"
|
|
105
|
-
:is-data-change="isDataChange"
|
|
106
|
-
/>
|
|
107
|
-
</template>
|
|
108
|
-
</form-pad>
|
|
109
|
-
</VCardText>
|
|
110
|
-
<VCardActions>
|
|
111
|
-
<slot name="action" :save="save" :cancel="cancel">
|
|
112
|
-
<VSpacer />
|
|
113
|
-
<VBtn
|
|
114
|
-
color="primary"
|
|
115
|
-
variant="flat"
|
|
116
|
-
:loading="isSaving"
|
|
117
|
-
:disabled="!isDataChange"
|
|
118
|
-
@click="save"
|
|
119
|
-
>
|
|
120
|
-
{{ (isCreating) ? createCaption : updateCaption }}
|
|
121
|
-
</VBtn>
|
|
122
|
-
<VBtn
|
|
123
|
-
color="error"
|
|
124
|
-
variant="flat"
|
|
125
|
-
:disabled="isSaving"
|
|
126
|
-
@click="cancel"
|
|
101
|
+
</VToolbar>
|
|
102
|
+
<VCardText>
|
|
103
|
+
<form-pad
|
|
104
|
+
ref="formPadRef"
|
|
105
|
+
v-model="formData"
|
|
106
|
+
:readonly="readonly"
|
|
107
|
+
isolated
|
|
108
|
+
v-bind="$attrs"
|
|
127
109
|
>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
110
|
+
<template #default="slotData">
|
|
111
|
+
<slot
|
|
112
|
+
v-bind="slotData"
|
|
113
|
+
:is-creating="isCreating"
|
|
114
|
+
:is-data-change="isDataChange"
|
|
115
|
+
/>
|
|
116
|
+
</template>
|
|
117
|
+
</form-pad>
|
|
118
|
+
</VCardText>
|
|
119
|
+
<VCardActions>
|
|
120
|
+
<slot name="action" :operation="operation">
|
|
121
|
+
<VSpacer />
|
|
122
|
+
<VBtn
|
|
123
|
+
color="primary"
|
|
124
|
+
variant="flat"
|
|
125
|
+
:loading="isSaving"
|
|
126
|
+
:disabled="!isDataChange"
|
|
127
|
+
@click="save"
|
|
128
|
+
v-if="!readonly"
|
|
129
|
+
>
|
|
130
|
+
{{ saveCaption }}
|
|
131
|
+
</VBtn>
|
|
132
|
+
<VBtn
|
|
133
|
+
color="error"
|
|
134
|
+
variant="flat"
|
|
135
|
+
:disabled="isSaving"
|
|
136
|
+
@click="cancel"
|
|
137
|
+
>
|
|
138
|
+
{{ cancelCaption }}
|
|
139
|
+
</VBtn>
|
|
140
|
+
</slot>
|
|
141
|
+
</VCardActions>
|
|
142
|
+
</VCard>
|
|
133
143
|
</template>
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import {computed, defineExpose, ref, watchEffect} from 'vue'
|
|
3
|
+
import {cloneDeep, isEqual} from 'lodash-es'
|
|
4
|
+
import type {FormDialogCallback} from '../../types/formDialog'
|
|
5
|
+
import FormPadComponent from './Pad.vue'
|
|
6
|
+
|
|
7
|
+
interface Props extends /* @vue-ignore */ InstanceType<typeof FormPadComponent['$props']> {
|
|
8
|
+
title?: string
|
|
9
|
+
initialData?: object
|
|
10
|
+
formData?: object
|
|
11
|
+
saveCaption?: string
|
|
12
|
+
cancelCaption?: string
|
|
13
|
+
readonly?: boolean
|
|
14
|
+
showTitle?: boolean
|
|
15
|
+
skipValidation?:boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
19
|
+
saveCaption: 'บันทึก',
|
|
20
|
+
cancelCaption: 'ยกเลิก',
|
|
21
|
+
readonly: false,
|
|
22
|
+
showTitle: false,
|
|
23
|
+
skipValidation:false
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const isSaving = ref<boolean>(false)
|
|
27
|
+
const formPadRef = ref()
|
|
28
|
+
const formData = ref<object>({})
|
|
29
|
+
const formDataOriginalValue = ref<object>()
|
|
30
|
+
|
|
31
|
+
const emit = defineEmits(['create', 'update'])
|
|
32
|
+
|
|
33
|
+
function save() {
|
|
34
|
+
if (props.skipValidation || formPadRef.value?.isValid) {
|
|
35
|
+
isSaving.value = true
|
|
36
|
+
emit((isCreating.value) ? 'create' : 'update', cloneDeep(formData.value), callback)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function cancel() {
|
|
41
|
+
reset()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function reset() {
|
|
45
|
+
formDataOriginalValue.value = undefined
|
|
46
|
+
formPadRef.value?.reset()
|
|
47
|
+
loadFormData()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const callback: FormDialogCallback = {
|
|
51
|
+
done: function () {
|
|
52
|
+
isSaving.value = false
|
|
53
|
+
},
|
|
54
|
+
error: function () {
|
|
55
|
+
isSaving.value = false
|
|
56
|
+
},
|
|
57
|
+
setData: function (item: object) {
|
|
58
|
+
formData.value = cloneDeep(item)
|
|
59
|
+
formDataOriginalValue.value = cloneDeep(item)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const isDataChange = computed(() => {
|
|
64
|
+
return !((isCreating.value) ? isEqual(formData.value, createOriginalValue.value) : isEqual(formData.value, formDataOriginalValue.value))
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const isCreating = computed(() => {
|
|
68
|
+
return !props.formData
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const createOriginalValue = computed(() => {
|
|
72
|
+
return Object.assign({}, props.initialData)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const loadFormData = () => {
|
|
76
|
+
if (props.formData) {
|
|
77
|
+
formData.value = cloneDeep(props.formData)
|
|
78
|
+
formDataOriginalValue.value = cloneDeep(props.formData)
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
formData.value = Object.assign({}, props.initialData)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const operation = ref({ isDataChange, isCreating, isSaving, save, cancel })
|
|
86
|
+
|
|
87
|
+
watchEffect(loadFormData)
|
|
88
|
+
|
|
89
|
+
defineExpose({operation,formPad:formPadRef})
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<template>
|
|
93
|
+
<VCard flat>
|
|
94
|
+
<VToolbar v-if="showTitle">
|
|
95
|
+
<slot name="titleToolbar" :operation="operation">
|
|
96
|
+
<VToolbarTitle>
|
|
97
|
+
<slot name="title" :operation="operation">
|
|
98
|
+
{{ (isCreating) ? "New" : "Edit" }} {{ title }}
|
|
99
|
+
</slot>
|
|
100
|
+
</VToolbarTitle>
|
|
101
|
+
</slot>
|
|
102
|
+
</VToolbar>
|
|
103
|
+
<VCardText>
|
|
104
|
+
<form-pad
|
|
105
|
+
ref="formPadRef"
|
|
106
|
+
v-model="formData"
|
|
107
|
+
:readonly="readonly"
|
|
108
|
+
isolated
|
|
109
|
+
v-bind="$attrs"
|
|
110
|
+
>
|
|
111
|
+
<template #default="slotData">
|
|
112
|
+
<slot
|
|
113
|
+
v-bind="slotData"
|
|
114
|
+
:is-creating="isCreating"
|
|
115
|
+
:is-data-change="isDataChange"
|
|
116
|
+
/>
|
|
117
|
+
</template>
|
|
118
|
+
</form-pad>
|
|
119
|
+
</VCardText>
|
|
120
|
+
<VCardActions>
|
|
121
|
+
<slot name="action" :operation="operation">
|
|
122
|
+
<VSpacer />
|
|
123
|
+
<VBtn
|
|
124
|
+
color="primary"
|
|
125
|
+
variant="flat"
|
|
126
|
+
:loading="isSaving"
|
|
127
|
+
:disabled="!isDataChange"
|
|
128
|
+
@click="save"
|
|
129
|
+
v-if="!readonly"
|
|
130
|
+
>
|
|
131
|
+
{{ saveCaption }}
|
|
132
|
+
</VBtn>
|
|
133
|
+
<VBtn
|
|
134
|
+
color="error"
|
|
135
|
+
variant="flat"
|
|
136
|
+
:disabled="isSaving"
|
|
137
|
+
@click="cancel"
|
|
138
|
+
>
|
|
139
|
+
{{ cancelCaption }}
|
|
140
|
+
</VBtn>
|
|
141
|
+
</slot>
|
|
142
|
+
</VCardActions>
|
|
143
|
+
</VCard>
|
|
144
|
+
</template>
|
|
@@ -26,7 +26,6 @@ interface Props extends /* @vue-ignore */ InstanceType<typeof VDataTable['$props
|
|
|
26
26
|
inputPadOnly?: boolean
|
|
27
27
|
saveAndStay?: boolean
|
|
28
28
|
stringFields?: Array<string>
|
|
29
|
-
items?: Record<string, any>[]
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -85,11 +84,6 @@ watch(items, (newValue) => {
|
|
|
85
84
|
emit('update:modelValue', newValue)
|
|
86
85
|
}, { deep: true })
|
|
87
86
|
|
|
88
|
-
onMounted(()=>{
|
|
89
|
-
if (props.items){
|
|
90
|
-
items.value = props.items
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
87
|
|
|
94
88
|
function createItem(item: Record<string, any>, callback?: FormDialogCallback) {
|
|
95
89
|
if (items.value.length > 0) item[props.modelKey] = Math.max(...items.value.map(i => i[props.modelKey] || 0)) + 1
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {VDataTable} from 'vuetify/components/VDataTable'
|
|
3
|
+
import {computed, onMounted, ref, useAttrs, watch} from 'vue'
|
|
4
|
+
import {omit} from "lodash-es";
|
|
5
|
+
interface Props extends /* @vue-ignore */ InstanceType<typeof VDataTable['$props']> {
|
|
6
|
+
title: string
|
|
7
|
+
modelValue?: Record<string, any>[]
|
|
8
|
+
modelKey?: string
|
|
9
|
+
toolbarColor?: string
|
|
10
|
+
items : Record<string, any>
|
|
11
|
+
}
|
|
12
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
13
|
+
modelKey: 'id',
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const emit = defineEmits(['update:modelValue'])
|
|
17
|
+
const attrs = useAttrs()
|
|
18
|
+
const plainAttrs = computed(() => {
|
|
19
|
+
return omit(attrs, ['modelValue', 'onUpdate:modelValue'])
|
|
20
|
+
})
|
|
21
|
+
const modelValue = ref()
|
|
22
|
+
const setDataItems = ()=>{
|
|
23
|
+
modelValue.value = props.items
|
|
24
|
+
}
|
|
25
|
+
watch(() => props.modelValue, (newValue) => {
|
|
26
|
+
if (!Array.isArray(newValue) || !newValue.every(item => typeof item === 'object')) {
|
|
27
|
+
modelValue.value = []
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
let maxKey = 0
|
|
31
|
+
|
|
32
|
+
newValue.forEach((item) => {
|
|
33
|
+
if (!item.hasOwnProperty(props.modelKey)) {
|
|
34
|
+
maxKey = Math.max(maxKey, ...newValue.map(i => i[props.modelKey] || 0))
|
|
35
|
+
item[props.modelKey] = maxKey + 1
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
modelValue.value = newValue
|
|
40
|
+
}
|
|
41
|
+
}, { immediate: true })
|
|
42
|
+
|
|
43
|
+
watch(modelValue, (newValue) => {
|
|
44
|
+
emit('update:modelValue', newValue)
|
|
45
|
+
}, { deep: true })
|
|
46
|
+
|
|
47
|
+
onMounted(()=>{
|
|
48
|
+
setDataItems()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
<template>
|
|
55
|
+
<form-table
|
|
56
|
+
v-bind="plainAttrs"
|
|
57
|
+
v-model="modelValue"
|
|
58
|
+
:title="props.title"
|
|
59
|
+
:toolbarColor="props.toolbarColor"
|
|
60
|
+
:model-key="props.modelKey"
|
|
61
|
+
:insertable="false"
|
|
62
|
+
:importable="false"
|
|
63
|
+
:exportable="false"
|
|
64
|
+
:searchable="false"
|
|
65
|
+
hide-default-footer>
|
|
66
|
+
<!-- @ts-ignore -->
|
|
67
|
+
<template
|
|
68
|
+
v-for="(_, name, index) in ($slots as {})"
|
|
69
|
+
:key="index"
|
|
70
|
+
#[name]="slotData"
|
|
71
|
+
>
|
|
72
|
+
<slot
|
|
73
|
+
:name="name"
|
|
74
|
+
v-bind="((slotData || {}) as object)"
|
|
75
|
+
/>
|
|
76
|
+
</template>
|
|
77
|
+
</form-table>
|
|
78
|
+
</template>
|
|
79
|
+
|
|
80
|
+
<style scoped>
|
|
81
|
+
|
|
82
|
+
</style>
|
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { computed,
|
|
3
|
-
import { cloneDeep, isEqual } from 'lodash-es'
|
|
2
|
+
import { computed, useTemplateRef, defineExpose } from 'vue'
|
|
4
3
|
import { type GraphqlModelItemProps, useGraphqlModelItem } from '../../composables/graphqlModelItem'
|
|
4
|
+
import EditPad from '../form/EditPad.vue'
|
|
5
5
|
|
|
6
6
|
defineOptions({
|
|
7
7
|
inheritAttrs: false,
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
interface Props {
|
|
11
|
-
title?: string
|
|
12
|
-
initialData?: object
|
|
13
|
-
saveCaption?: string
|
|
14
|
-
cancelCaption?: string
|
|
10
|
+
interface Props extends /* @vue-ignore */ InstanceType<typeof EditPad['$props']> {
|
|
15
11
|
}
|
|
16
12
|
|
|
17
13
|
const props = withDefaults(defineProps<Props & GraphqlModelItemProps>(), {
|
|
18
|
-
saveCaption: 'บันทึก',
|
|
19
|
-
cancelCaption: 'ยกเลิก',
|
|
20
14
|
fields: () => ['*'],
|
|
21
15
|
})
|
|
22
16
|
|
|
@@ -25,92 +19,43 @@ const { item,
|
|
|
25
19
|
createItem, updateItem,
|
|
26
20
|
reload, isLoading } = useGraphqlModelItem(props)
|
|
27
21
|
|
|
28
|
-
const
|
|
29
|
-
const formData = ref<object>({})
|
|
22
|
+
const editPad = useTemplateRef<typeof EditPad>("editPadRef")
|
|
30
23
|
|
|
31
|
-
const canSave = computed(() => { return (canCreate.value &&
|
|
24
|
+
const canSave = computed<boolean>(() => { return ((canCreate.value && editPad.value?.operation?.isCreating?.value) || canUpdate.value) as boolean})
|
|
32
25
|
|
|
33
|
-
const
|
|
34
|
-
return
|
|
26
|
+
const operation : any = computed(()=>{
|
|
27
|
+
return Object.assign({},editPad.value?.operation,{canSave,reload,item})
|
|
35
28
|
})
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
return !item.value
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
const createOriginalValue = computed(() => {
|
|
42
|
-
return Object.assign({}, props.initialData)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
const loadFormData = () => {
|
|
46
|
-
if (item.value) {
|
|
47
|
-
formData.value = cloneDeep(item.value)
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
formData.value = Object.assign({}, props.initialData)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
watchEffect(loadFormData)
|
|
55
|
-
|
|
56
|
-
function save() {
|
|
57
|
-
if (formPadRef.value.isValid) {
|
|
58
|
-
if (isCreating.value) createItem(formData.value)
|
|
59
|
-
else updateItem(formData.value)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function cancel() {
|
|
64
|
-
formPadRef.value.reset()
|
|
65
|
-
loadFormData()
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const operation = ref({save, cancel, reload, item, canSave, isLoading,isDataChange,isCreating})
|
|
69
|
-
|
|
70
|
-
defineExpose({ save, cancel, reload, item, isLoading })
|
|
30
|
+
defineExpose({ operation, formPad: editPad.value?.formPad })
|
|
71
31
|
</script>
|
|
72
32
|
|
|
73
33
|
<template>
|
|
74
|
-
<
|
|
75
|
-
<
|
|
34
|
+
<FormEditPad v-bind="$attrs" :form-data="item" ref="editPadRef" @create="createItem" @update="updateItem">
|
|
35
|
+
<template #titleToolbar>
|
|
76
36
|
<slot name="titleToolbar" :operation="operation">
|
|
77
37
|
<VToolbarTitle>
|
|
78
38
|
<slot name="title" :operation="operation">
|
|
79
39
|
{{ title }}
|
|
80
40
|
<v-icon
|
|
81
|
-
|
|
82
|
-
|
|
41
|
+
size="small"
|
|
42
|
+
@click="reload"
|
|
83
43
|
>
|
|
84
44
|
mdi mdi-refresh
|
|
85
45
|
</v-icon>
|
|
86
46
|
</slot>
|
|
87
47
|
</VToolbarTitle>
|
|
88
48
|
</slot>
|
|
89
|
-
</
|
|
90
|
-
<
|
|
91
|
-
<form-pad
|
|
92
|
-
ref="formPadRef"
|
|
93
|
-
v-model="formData"
|
|
94
|
-
isolated
|
|
95
|
-
>
|
|
96
|
-
<template #default="slotData">
|
|
97
|
-
<slot
|
|
98
|
-
v-bind="slotData"
|
|
99
|
-
:is-creating="isCreating"
|
|
100
|
-
:is-data-change="isDataChange"
|
|
101
|
-
/>
|
|
102
|
-
</template>
|
|
103
|
-
</form-pad>
|
|
104
|
-
</VCardText>
|
|
105
|
-
<VCardActions>
|
|
49
|
+
</template>
|
|
50
|
+
<template #action="slotData">
|
|
106
51
|
<slot name="action" :operation="operation">
|
|
107
52
|
<VSpacer />
|
|
108
53
|
<VBtn
|
|
109
54
|
color="primary"
|
|
110
55
|
variant="flat"
|
|
111
56
|
:loading="isLoading"
|
|
112
|
-
:disabled="!isDataChange || !canSave"
|
|
113
|
-
@click="save"
|
|
57
|
+
:disabled="!slotData.operation?.isDataChange || !canSave"
|
|
58
|
+
@click="slotData.operation?.save"
|
|
114
59
|
>
|
|
115
60
|
{{ saveCaption }}
|
|
116
61
|
</VBtn>
|
|
@@ -118,11 +63,18 @@ defineExpose({ save, cancel, reload, item, isLoading })
|
|
|
118
63
|
color="error"
|
|
119
64
|
variant="flat"
|
|
120
65
|
:disabled="isLoading"
|
|
121
|
-
@click="cancel"
|
|
66
|
+
@click="slotData.operation?.cancel"
|
|
122
67
|
>
|
|
123
68
|
{{ cancelCaption }}
|
|
124
69
|
</VBtn>
|
|
125
70
|
</slot>
|
|
126
|
-
</
|
|
127
|
-
|
|
71
|
+
</template>
|
|
72
|
+
<template #default="slotData">
|
|
73
|
+
<slot
|
|
74
|
+
v-bind="slotData"
|
|
75
|
+
:is-creating="isCreating"
|
|
76
|
+
:is-data-change="isDataChange"
|
|
77
|
+
/>
|
|
78
|
+
</template>
|
|
79
|
+
</FormEditPad>
|
|
128
80
|
</template>
|
|
@@ -37,7 +37,7 @@ export function processTemplateFormTableData(item, parentTemplates) {
|
|
|
37
37
|
</template>`;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
item.inputType = "
|
|
40
|
+
item.inputType = "FormTableData";
|
|
41
41
|
return processDefaultTemplate(item, tableTemplate, `title="${tableOptions.title}"
|
|
42
42
|
:headers='${escapeObjectForInlineBinding(tableHeader)}'
|
|
43
43
|
:items='${escapeObjectForInlineBinding(tableItems)}'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const useUserPermission: () =>
|
|
1
|
+
export declare const useUserPermission: () => import("../types/permission").PermissionPlugin;
|
|
@@ -11,18 +11,18 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
11
11
|
const arr = normalize(input);
|
|
12
12
|
return arr.length === 0 || arr.every((v) => v.trim() === "");
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
const check = (permissionIds) => {
|
|
15
15
|
if (isBlank(permissionIds)) return true;
|
|
16
16
|
const auth = useAuthentication();
|
|
17
17
|
const perms = normalize(permissionIds);
|
|
18
18
|
return perms.some((id) => auth?.hasPermission(id));
|
|
19
|
-
}
|
|
20
|
-
|
|
19
|
+
};
|
|
20
|
+
const checkAll = (permissionIds) => {
|
|
21
21
|
if (isBlank(permissionIds)) return true;
|
|
22
22
|
const auth = useAuthentication();
|
|
23
23
|
const perms = normalize(permissionIds);
|
|
24
24
|
return perms.every((id) => auth?.hasPermission(id));
|
|
25
|
-
}
|
|
25
|
+
};
|
|
26
26
|
nuxtApp.vueApp.directive("permission", (el, binding, vnode) => {
|
|
27
27
|
if (!check(binding.value)) {
|
|
28
28
|
vnode?.um?.forEach?.((um) => um());
|