mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 10:25:52 +02:00
enhance: added error prompt in form
This commit is contained in:
parent
f305701b30
commit
6bc6ceac19
13 changed files with 123 additions and 68 deletions
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
|
@ -78,5 +78,6 @@ declare module '@vue/runtime-core' {
|
|||
StdDataEntryComponentsStdPassword: typeof import('./src/components/StdDataEntry/components/StdPassword.vue')['default']
|
||||
StdDataEntryComponentsStdSelect: typeof import('./src/components/StdDataEntry/components/StdSelect.vue')['default']
|
||||
StdDataEntryComponentsStdSelector: typeof import('./src/components/StdDataEntry/components/StdSelector.vue')['default']
|
||||
StdDataEntryStdFormItem: typeof import('./src/components/StdDataEntry/StdFormItem.vue')['default']
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ const props = defineProps({
|
|||
},
|
||||
beforeSave: {
|
||||
type: Function,
|
||||
default: null
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
exportCsv: {
|
||||
type: Boolean,
|
||||
|
@ -104,11 +105,11 @@ function clear_error() {
|
|||
|
||||
const ok = async () => {
|
||||
clear_error()
|
||||
await props?.beforeSave?.(data)
|
||||
await props?.beforeSave!?.(data)
|
||||
props.api!.save(data.id, data).then((r: any) => {
|
||||
message.success($gettext('Save Successfully'))
|
||||
Object.assign(data, r)
|
||||
const t: Table | null = table.value
|
||||
const t: Table = table.value!
|
||||
t!.get_list()
|
||||
|
||||
}).catch((e: any) => {
|
||||
|
@ -189,7 +190,7 @@ const selectedRowKeys = ref([])
|
|||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.before-edit:last-child {
|
||||
margin-bottom: 10px;
|
||||
:deep(.before-edit:last-child) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {defineComponent} from 'vue'
|
||||
import {Form, FormItem} from 'ant-design-vue'
|
||||
import {Form} from 'ant-design-vue'
|
||||
import StdFormItem from '@/components/StdDataEntry/StdFormItem.vue'
|
||||
import './style.less'
|
||||
|
||||
export default defineComponent({
|
||||
|
@ -11,9 +12,9 @@ export default defineComponent({
|
|||
props.dataList.forEach((v: any) => {
|
||||
if (v.edit.type) {
|
||||
template.push(
|
||||
<FormItem label={v.title()} extra={v.extra}>
|
||||
<StdFormItem dataIndex={v.dataIndex} label={v.title()} extra={v.extra} error={props.error}>
|
||||
{v.edit.type(v.edit, props.dataSource, v.dataIndex)}
|
||||
</FormItem>
|
||||
</StdFormItem>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
46
frontend/src/components/StdDataEntry/StdFormItem.vue
Normal file
46
frontend/src/components/StdDataEntry/StdFormItem.vue
Normal file
|
@ -0,0 +1,46 @@
|
|||
<script setup lang="ts">
|
||||
import {computed} from 'vue'
|
||||
import {useGettext} from 'vue3-gettext'
|
||||
|
||||
const {$gettext} = useGettext()
|
||||
|
||||
export interface Props {
|
||||
dataIndex?: string
|
||||
label?: string
|
||||
extra?: string
|
||||
error?: any
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const tag = computed(() => {
|
||||
return props.error?.[props.dataIndex] ?? ''
|
||||
})
|
||||
|
||||
const valid_status = computed(() => {
|
||||
if (!!tag.value) {
|
||||
return 'error'
|
||||
} else {
|
||||
return 'success'
|
||||
}
|
||||
})
|
||||
|
||||
const help = computed(() => {
|
||||
if (tag.value.indexOf('required') > -1) {
|
||||
return () => $gettext('This field should not be empty')
|
||||
}
|
||||
return () => {
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-form-item :label="label" :extra="extra" :validate-status="valid_status" :help="help?.()"
|
||||
:required="tag.indexOf('required')>-1">
|
||||
<slot/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
|
@ -23,7 +23,7 @@ msgstr ""
|
|||
msgid "Action"
|
||||
msgstr "Action"
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:146
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:147
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:25
|
||||
#: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:28
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:47
|
||||
|
@ -1112,7 +1112,7 @@ msgstr "Save error %{msg}"
|
|||
msgid "Save successfully"
|
||||
msgstr "Saved successfully"
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:109
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:110
|
||||
#, fuzzy
|
||||
msgid "Save Successfully"
|
||||
msgstr "Saved successfully"
|
||||
|
@ -1276,6 +1276,10 @@ msgstr ""
|
|||
msgid "This auto-cert item is invalid, please remove it."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/StdDataEntry/StdFormItem.vue:30
|
||||
msgid "This field should not be empty"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:31
|
||||
msgid ""
|
||||
"To make sure the certification auto-renewal can work normally, we need to "
|
||||
|
|
|
@ -19,7 +19,7 @@ msgstr ""
|
|||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:146
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:147
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:25
|
||||
#: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:28
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:47
|
||||
|
@ -1149,7 +1149,7 @@ msgstr ""
|
|||
msgid "Save successfully"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:109
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:110
|
||||
msgid "Save Successfully"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1305,6 +1305,10 @@ msgstr ""
|
|||
msgid "This auto-cert item is invalid, please remove it."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/StdDataEntry/StdFormItem.vue:30
|
||||
msgid "This field should not be empty"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:31
|
||||
msgid "To make sure the certification auto-renewal can work normally, we need to add a location which can proxy the request from authority to backend, and we need to save this file and reload the Nginx. Are you sure you want to continue?"
|
||||
msgstr ""
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -26,7 +26,7 @@ msgstr "访问日志"
|
|||
msgid "Action"
|
||||
msgstr "操作"
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:146
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:147
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:25
|
||||
#: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:28
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:47
|
||||
|
@ -1086,7 +1086,7 @@ msgstr "保存错误 %{msg}"
|
|||
msgid "Save successfully"
|
||||
msgstr "保存成功"
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:109
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:110
|
||||
msgid "Save Successfully"
|
||||
msgstr "保存成功"
|
||||
|
||||
|
@ -1237,6 +1237,10 @@ msgstr "主题"
|
|||
msgid "This auto-cert item is invalid, please remove it."
|
||||
msgstr "这个证书自动续期项目是无效的,请删除。"
|
||||
|
||||
#: src/components/StdDataEntry/StdFormItem.vue:30
|
||||
msgid "This field should not be empty"
|
||||
msgstr "该字段不能为空"
|
||||
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:31
|
||||
msgid ""
|
||||
"To make sure the certification auto-renewal can work normally, we need to "
|
||||
|
|
|
@ -27,7 +27,7 @@ msgstr "訪問日誌"
|
|||
msgid "Action"
|
||||
msgstr "操作"
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:146
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:147
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:25
|
||||
#: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:28
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:47
|
||||
|
@ -1087,7 +1087,7 @@ msgstr "儲存錯誤 %{msg}"
|
|||
msgid "Save successfully"
|
||||
msgstr "保存成功"
|
||||
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:109
|
||||
#: src/components/StdDataDisplay/StdCurd.vue:110
|
||||
msgid "Save Successfully"
|
||||
msgstr "保存成功"
|
||||
|
||||
|
@ -1240,6 +1240,10 @@ msgstr "外觀樣式"
|
|||
msgid "This auto-cert item is invalid, please remove it."
|
||||
msgstr "此自動證書項無效,請將其刪除。"
|
||||
|
||||
#: src/components/StdDataEntry/StdFormItem.vue:30
|
||||
msgid "This field should not be empty"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:31
|
||||
msgid ""
|
||||
"To make sure the certification auto-renewal can work normally, we need to "
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":"1.9.9","build_id":107,"total_build":177}
|
||||
{"version":"1.9.9","build_id":108,"total_build":178}
|
|
@ -1 +1 @@
|
|||
{"version":"1.9.9","build_id":107,"total_build":177}
|
||||
{"version":"1.9.9","build_id":108,"total_build":178}
|
|
@ -1,68 +1,58 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-playground/locales/zh"
|
||||
ut "github.com/go-playground/universal-translator"
|
||||
val "github.com/go-playground/validator/v10"
|
||||
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"github.com/0xJacky/Nginx-UI/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
val "github.com/go-playground/validator/v10"
|
||||
"net/http"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func ErrHandler(c *gin.Context, err error) {
|
||||
logger.GetLogger().Errorln(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
logger.GetLogger().Errorln(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
type ValidError struct {
|
||||
Key string
|
||||
Message string
|
||||
Key string
|
||||
Message string
|
||||
}
|
||||
|
||||
func BindAndValid(c *gin.Context, target interface{}) bool {
|
||||
errs := make(map[string]string)
|
||||
err := c.ShouldBindJSON(target)
|
||||
if err != nil {
|
||||
logger.Error("bind err", err)
|
||||
uni := ut.New(zh.New())
|
||||
trans, _ := uni.GetTranslator("zh")
|
||||
v, ok := binding.Validator.Engine().(*val.Validate)
|
||||
if ok {
|
||||
_ = zhTranslations.RegisterDefaultTranslations(v, trans)
|
||||
}
|
||||
errs := make(map[string]string)
|
||||
err := c.ShouldBindJSON(target)
|
||||
if err != nil {
|
||||
logger.Error("bind err", err)
|
||||
|
||||
verrs, ok := err.(val.ValidationErrors)
|
||||
verrs, ok := err.(val.ValidationErrors)
|
||||
|
||||
if !ok {
|
||||
logger.Error("valid err", verrs)
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "Requested with wrong parameters",
|
||||
"code": http.StatusNotAcceptable,
|
||||
"error": verrs,
|
||||
})
|
||||
return false
|
||||
}
|
||||
if !ok {
|
||||
logger.Error("valid err", verrs)
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "Requested with wrong parameters",
|
||||
"code": http.StatusNotAcceptable,
|
||||
"error": verrs,
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
for _, value := range verrs {
|
||||
t := reflect.ValueOf(target)
|
||||
realType := t.Type().Elem()
|
||||
field, _ := realType.FieldByName(value.StructField())
|
||||
errs[field.Tag.Get("json")] = value.Translate(trans)
|
||||
}
|
||||
for _, value := range verrs {
|
||||
t := reflect.ValueOf(target)
|
||||
realType := t.Type().Elem()
|
||||
field, _ := realType.FieldByName(value.StructField())
|
||||
errs[field.Tag.Get("json")] = value.Tag()
|
||||
}
|
||||
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"errors": errs,
|
||||
"message": "Requested with wrong parameters",
|
||||
"code": http.StatusNotAcceptable,
|
||||
})
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"errors": errs,
|
||||
"message": "Requested with wrong parameters",
|
||||
"code": http.StatusNotAcceptable,
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue