mirror of
https://github.com/fastapi-admin/fastapi-admin.git
synced 2026-03-13 10:32:25 +08:00
json view
add example update pypi.yml
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
"vue-element-loading": "^1.1.5",
|
||||
"vue-html5-editor": "^1.1.1",
|
||||
"vue-i18n": "^8.17.3",
|
||||
"vue-json-pretty": "^1.6.3",
|
||||
"vue-router": "^3.1.3",
|
||||
"vue-select": "^3.2.0",
|
||||
"vue-snotify": "^3.2.1",
|
||||
|
||||
@@ -14,7 +14,12 @@
|
||||
</template>
|
||||
<b-img class="type-image" v-else :src="preview(value)" v-bind="field" fluid @click.stop="previewInModal(value)"/>
|
||||
</template>
|
||||
|
||||
<template v-else-if="['json'].includes(field.type)">
|
||||
<b-json-pretty
|
||||
:value=value
|
||||
>
|
||||
</b-json-pretty>
|
||||
</template>
|
||||
<template v-else-if="['audio', 'video'].includes(field.type)">
|
||||
<component :is="field.type" :src="value" controls/>
|
||||
</template>
|
||||
@@ -87,8 +92,10 @@
|
||||
|
||||
<script>
|
||||
import _ from "lodash";
|
||||
import BJsonPretty from "./JsonPretty";
|
||||
|
||||
export default {
|
||||
components: {BJsonPretty},
|
||||
data() {
|
||||
return {
|
||||
previewValue: null,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
v-if="inline"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
<input type="hidden" name="token" :value="auth.token" />
|
||||
<input type="hidden" name="token" :value="auth.token"/>
|
||||
|
||||
<template v-for="(field, name) in fields">
|
||||
<label
|
||||
@@ -40,7 +40,8 @@
|
||||
variant="secondary"
|
||||
@click="$router.go(-1)"
|
||||
v-if="backText"
|
||||
>{{backText}}</b-button>
|
||||
>{{backText}}
|
||||
</b-button>
|
||||
<slot name="extra-buttons"></slot>
|
||||
</slot>
|
||||
</component>
|
||||
@@ -55,7 +56,7 @@
|
||||
enctype="multipart/form-data"
|
||||
v-else
|
||||
>
|
||||
<input type="hidden" name="token" :value="auth.token" />
|
||||
<input type="hidden" name="token" :value="auth.token"/>
|
||||
<b-tabs
|
||||
class="my-3"
|
||||
v-if="groupBy"
|
||||
@@ -140,233 +141,236 @@
|
||||
variant="secondary"
|
||||
@click="$router.go(-1)"
|
||||
v-if="backText"
|
||||
>{{backText}}</b-button>
|
||||
>{{backText}}
|
||||
</b-button>
|
||||
</slot>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import _ from "lodash";
|
||||
import _ from "lodash";
|
||||
|
||||
export default {
|
||||
name: "b-form-builder",
|
||||
components: {},
|
||||
props: {
|
||||
parent: {},
|
||||
subForm: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default() {
|
||||
return "form_" + parseInt(Math.random() * 9999);
|
||||
}
|
||||
},
|
||||
auth: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
col: {
|
||||
type: Number,
|
||||
default: 12
|
||||
},
|
||||
languages: {},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
useFormData: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
submitRawForm: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
groupBy: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
value: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
required: true,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
required: false,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
onSubmit: {
|
||||
type: Function,
|
||||
required: false
|
||||
},
|
||||
beforeSubmit: {
|
||||
type: Function,
|
||||
required: false
|
||||
},
|
||||
action: {},
|
||||
method: {
|
||||
default: "post"
|
||||
},
|
||||
submitText: {
|
||||
default() {
|
||||
return this.$t ? this.$t("actions.save") : "Submit";
|
||||
}
|
||||
},
|
||||
backText: {
|
||||
default() {
|
||||
return this.$t ? this.$t("actions.back") : "Back";
|
||||
}
|
||||
},
|
||||
|
||||
successMessage: {
|
||||
default() {
|
||||
return this.$t ? this.$t("messages.succeed") : "Succeed";
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: null,
|
||||
errors: []
|
||||
};
|
||||
},
|
||||
watch: {},
|
||||
computed: {
|
||||
tag() {
|
||||
return this.subForm ? "div" : "form";
|
||||
},
|
||||
actionUrl() {
|
||||
return global.API_URI + this.action;
|
||||
},
|
||||
groupedFields() {
|
||||
const ret = {};
|
||||
_.keys(_.groupBy(this.fields, this.groupBy)).map(v => {
|
||||
let tabName = v;
|
||||
if (v === "undefined") {
|
||||
v = null;
|
||||
tabName = this.$t("messages.default");
|
||||
}
|
||||
ret[tabName] = _.pickBy(this.fields, field => field.group == v);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getFieldId(name) {
|
||||
if (this.subForm) {
|
||||
return `input_${this.subForm}_${name}`;
|
||||
}
|
||||
return `input_${name}`;
|
||||
},
|
||||
getFieldName(name) {
|
||||
if (this.subForm) {
|
||||
return `${this.subForm}[${name}]`;
|
||||
}
|
||||
return name;
|
||||
},
|
||||
setValue(name, value, lang) {
|
||||
const isIntl = this.fields[name].multilingual || this.fields[name].intl;
|
||||
if (!isIntl) {
|
||||
this.$set(this.model, name, value);
|
||||
// _.set(this.model, name, value);
|
||||
} else if (lang && !_.isObject(this.model[name])) {
|
||||
this.$set(this.model, name, {});
|
||||
} else {
|
||||
this.$set(this.model[name], lang, value);
|
||||
}
|
||||
return this.$emit("input", this.model);
|
||||
},
|
||||
titlize() {},
|
||||
isShowField(field) {
|
||||
return (
|
||||
!field.showWhen || this.model[field.showWhen] || eval(field.showWhen)
|
||||
);
|
||||
},
|
||||
getInputClass() {
|
||||
return [];
|
||||
// const classNames = [];
|
||||
// classNames.push(`col-lg-${field.input_cols ? field.input_cols : "12"}`);
|
||||
// return classNames;
|
||||
},
|
||||
getClass(field) {
|
||||
const cols = field.cols ? field.cols : 12;
|
||||
const classNames = ["col-lg-" + cols, "col-" + Math.min(12, cols * 2)];
|
||||
return classNames;
|
||||
},
|
||||
hasError(name) {
|
||||
return _.find(this.errors, v => v.field == name);
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs.submitButton.click();
|
||||
},
|
||||
handleSubmit() {
|
||||
if (this.beforeSubmit) {
|
||||
const ret = this.beforeSubmit(this.model);
|
||||
if (ret === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.submitRawForm) {
|
||||
this.$refs.form.submit();
|
||||
return true;
|
||||
}
|
||||
if (this.onSubmit) {
|
||||
return this.onSubmit(this.model);
|
||||
}
|
||||
const methodName = String(this.method).toLowerCase();
|
||||
let formData = this.model;
|
||||
if (this.useFormData) {
|
||||
formData = new FormData();
|
||||
_.mapValues(this.model, (v, k) => formData.append(k, v));
|
||||
}
|
||||
this.$http[methodName](this.action, formData)
|
||||
.then(({ data }) => {
|
||||
if (this.successMessage) {
|
||||
this.$snotify.success(this.successMessage);
|
||||
}
|
||||
this.errors = [];
|
||||
this.$emit("success", data);
|
||||
})
|
||||
.catch(({ data, status }) => {
|
||||
if (status == 422) {
|
||||
this.errors = data.message;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.model = Object.assign({}, this.value);
|
||||
|
||||
for (let [k, v] of Object.entries(this.fields)) {
|
||||
if (v.type === "object" && !this.model[k]) {
|
||||
this.$set(this.model, k, {});
|
||||
}
|
||||
}
|
||||
|
||||
this.$watch(
|
||||
"value",
|
||||
val => {
|
||||
this.model = Object.assign({}, val);
|
||||
export default {
|
||||
name: "b-form-builder",
|
||||
components: {},
|
||||
props: {
|
||||
parent: {},
|
||||
subForm: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
// global.console.log(this.fields, this.model)
|
||||
},
|
||||
created() {}
|
||||
};
|
||||
id: {
|
||||
type: String,
|
||||
default() {
|
||||
return "form_" + parseInt(Math.random() * 9999);
|
||||
}
|
||||
},
|
||||
auth: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
col: {
|
||||
type: Number,
|
||||
default: 12
|
||||
},
|
||||
languages: {},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
useFormData: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
submitRawForm: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
groupBy: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
value: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
required: true,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
required: false,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
onSubmit: {
|
||||
type: Function,
|
||||
required: false
|
||||
},
|
||||
beforeSubmit: {
|
||||
type: Function,
|
||||
required: false
|
||||
},
|
||||
action: {},
|
||||
method: {
|
||||
default: "post"
|
||||
},
|
||||
submitText: {
|
||||
default() {
|
||||
return this.$t ? this.$t("actions.save") : "Submit";
|
||||
}
|
||||
},
|
||||
backText: {
|
||||
default() {
|
||||
return this.$t ? this.$t("actions.back") : "Back";
|
||||
}
|
||||
},
|
||||
|
||||
successMessage: {
|
||||
default() {
|
||||
return this.$t ? this.$t("messages.succeed") : "Succeed";
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: null,
|
||||
errors: []
|
||||
};
|
||||
},
|
||||
watch: {},
|
||||
computed: {
|
||||
tag() {
|
||||
return this.subForm ? "div" : "form";
|
||||
},
|
||||
actionUrl() {
|
||||
return global.API_URI + this.action;
|
||||
},
|
||||
groupedFields() {
|
||||
const ret = {};
|
||||
_.keys(_.groupBy(this.fields, this.groupBy)).map(v => {
|
||||
let tabName = v;
|
||||
if (v === "undefined") {
|
||||
v = null;
|
||||
tabName = this.$t("messages.default");
|
||||
}
|
||||
ret[tabName] = _.pickBy(this.fields, field => field.group == v);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getFieldId(name) {
|
||||
if (this.subForm) {
|
||||
return `input_${this.subForm}_${name}`;
|
||||
}
|
||||
return `input_${name}`;
|
||||
},
|
||||
getFieldName(name) {
|
||||
if (this.subForm) {
|
||||
return `${this.subForm}[${name}]`;
|
||||
}
|
||||
return name;
|
||||
},
|
||||
setValue(name, value, lang) {
|
||||
const isIntl = this.fields[name].multilingual || this.fields[name].intl;
|
||||
if (!isIntl) {
|
||||
this.$set(this.model, name, value);
|
||||
// _.set(this.model, name, value);
|
||||
} else if (lang && !_.isObject(this.model[name])) {
|
||||
this.$set(this.model, name, {});
|
||||
} else {
|
||||
this.$set(this.model[name], lang, value);
|
||||
}
|
||||
return this.$emit("input", this.model);
|
||||
},
|
||||
titlize() {
|
||||
},
|
||||
isShowField(field) {
|
||||
return (
|
||||
!field.showWhen || this.model[field.showWhen] || eval(field.showWhen)
|
||||
);
|
||||
},
|
||||
getInputClass() {
|
||||
return [];
|
||||
// const classNames = [];
|
||||
// classNames.push(`col-lg-${field.input_cols ? field.input_cols : "12"}`);
|
||||
// return classNames;
|
||||
},
|
||||
getClass(field) {
|
||||
const cols = field.cols ? field.cols : 12;
|
||||
const classNames = ["col-lg-" + cols, "col-" + Math.min(12, cols * 2)];
|
||||
return classNames;
|
||||
},
|
||||
hasError(name) {
|
||||
return _.find(this.errors, v => v.field == name);
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs.submitButton.click();
|
||||
},
|
||||
handleSubmit() {
|
||||
if (this.beforeSubmit) {
|
||||
const ret = this.beforeSubmit(this.model);
|
||||
if (ret === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.submitRawForm) {
|
||||
this.$refs.form.submit();
|
||||
return true;
|
||||
}
|
||||
if (this.onSubmit) {
|
||||
return this.onSubmit(this.model);
|
||||
}
|
||||
const methodName = String(this.method).toLowerCase();
|
||||
let formData = this.model;
|
||||
if (this.useFormData) {
|
||||
formData = new FormData();
|
||||
_.mapValues(this.model, (v, k) => formData.append(k, v));
|
||||
}
|
||||
this.$http[methodName](this.action, formData)
|
||||
.then(({data}) => {
|
||||
if (this.successMessage) {
|
||||
this.$snotify.success(this.successMessage);
|
||||
}
|
||||
this.errors = [];
|
||||
this.$emit("success", data);
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
if (status == 422) {
|
||||
this.errors = data.message;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.model = Object.assign({}, this.value);
|
||||
|
||||
for (let [k, v] of Object.entries(this.fields)) {
|
||||
if (v.type === "object" && !this.model[k]) {
|
||||
this.$set(this.model, k, {});
|
||||
}
|
||||
}
|
||||
|
||||
this.$watch(
|
||||
"value",
|
||||
val => {
|
||||
this.model = Object.assign({}, val);
|
||||
},
|
||||
{deep: true}
|
||||
);
|
||||
// global.console.log(this.fields, this.model)
|
||||
},
|
||||
created() {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
24
front/src/components/JsonPretty.vue
Normal file
24
front/src/components/JsonPretty.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div>
|
||||
<vue-json-pretty
|
||||
:data=value
|
||||
:highlightMouseoverNode="true"
|
||||
>
|
||||
</vue-json-pretty>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import VueJsonPretty from 'vue-json-pretty'
|
||||
|
||||
export default {
|
||||
name: "b-json-pretty",
|
||||
components: {
|
||||
VueJsonPretty
|
||||
},
|
||||
props: {
|
||||
value: null,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@ import _ from 'lodash'
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store, { types } from './store'
|
||||
import store, {types} from './store'
|
||||
import './http'
|
||||
import i18n from './i18n'
|
||||
import inflection from 'inflection'
|
||||
|
||||
Vue.prototype.$inflection = inflection
|
||||
|
||||
import { sync } from 'vuex-router-sync'
|
||||
import {sync} from 'vuex-router-sync'
|
||||
|
||||
import BootstrapVue from 'bootstrap-vue'
|
||||
import Snotify from 'vue-snotify'
|
||||
@@ -22,6 +23,7 @@ import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||
import './scss/style.scss'
|
||||
|
||||
import "vue-snotify/styles/material.css"
|
||||
|
||||
Vue.use(Snotify)
|
||||
|
||||
Vue.config.productionTip = false
|
||||
@@ -30,9 +32,11 @@ Vue.use(BootstrapVue)
|
||||
import './form'
|
||||
|
||||
import storage from './storage'
|
||||
|
||||
Vue.prototype.$storage = storage
|
||||
|
||||
import VueElementLoading from 'vue-element-loading'
|
||||
|
||||
Vue.component('BLoading', VueElementLoading)
|
||||
|
||||
Vue.prototype._ = _
|
||||
@@ -47,12 +51,8 @@ new Vue({
|
||||
router,
|
||||
store,
|
||||
i18n,
|
||||
watch: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
watch: {},
|
||||
methods: {},
|
||||
render: h => h(App),
|
||||
|
||||
created() {
|
||||
|
||||
@@ -8766,6 +8766,11 @@ vue-i18n@^8.17.0, vue-i18n@^8.17.3:
|
||||
resolved "https://registry.npm.taobao.org/vue-i18n/download/vue-i18n-8.17.3.tgz?cache=0&sync_timestamp=1587630870936&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-i18n%2Fdownload%2Fvue-i18n-8.17.3.tgz#f366082d5784c3c35e8ffda733cb3f3990a3900d"
|
||||
integrity sha1-82YILVeEw8Nej/2nM8s/OZCjkA0=
|
||||
|
||||
vue-json-pretty@^1.6.3:
|
||||
version "1.6.3"
|
||||
resolved "https://registry.npm.taobao.org/vue-json-pretty/download/vue-json-pretty-1.6.3.tgz#c7f378f3c9f68977047de28197735bc2cf81b15b"
|
||||
integrity sha1-x/N488n2iXcEfeKBl3Nbws+BsVs=
|
||||
|
||||
vue-loader@^15.9.1:
|
||||
version "15.9.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.1.tgz#bd2ab8f3d281e51d7b81d15390a58424d142243e"
|
||||
|
||||
Reference in New Issue
Block a user