refactor(系统配置): ♻️ 系统配置

重构系统配置页面
This commit is contained in:
猿小天
2023-03-15 23:19:51 +08:00
parent efbeff6f2d
commit 21842e19f0
4 changed files with 429 additions and 403 deletions

View File

@@ -2,7 +2,7 @@
<div class="layout-parent"> <div class="layout-parent">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<transition :name="setTransitionName" mode="out-in"> <transition :name="setTransitionName" mode="out-in">
<keep-alive :include="getKeepAliveNames"> <keep-alive :include="getKeepAliveNames" v-if="showView">
<component :is="Component" :key="state.refreshRouterViewKey" class="w100" v-show="!isIframePage" /> <component :is="Component" :key="state.refreshRouterViewKey" class="w100" v-show="!isIframePage" />
</keep-alive> </keep-alive>
</transition> </transition>
@@ -14,7 +14,7 @@
</template> </template>
<script setup lang="ts" name="layoutParentView"> <script setup lang="ts" name="layoutParentView">
import { defineAsyncComponent, computed, reactive, onBeforeMount, onUnmounted, nextTick, watch, onMounted } from 'vue'; import { defineAsyncComponent, computed, reactive, onBeforeMount, onUnmounted, nextTick, watch, onMounted,ref,provide } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useKeepALiveNames } from '/@/stores/keepAliveNames'; import { useKeepALiveNames } from '/@/stores/keepAliveNames';
@@ -39,6 +39,19 @@ const state = reactive<ParentViewState>({
iframeList: [], iframeList: [],
}); });
//全局依赖刷新页面
const showView = ref(true)
/**
* 刷新页面
*/
const refreshView=function () {
showView.value = false // 通过v-if移除router-view节点
nextTick(() => {
showView.value = true // DOM更新后再通过v-if添加router-view节点
})
}
provide('refreshView',refreshView)
// 设置主界面切换动画 // 设置主界面切换动画
const setTransitionName = computed(() => { const setTransitionName = computed(() => {
return themeConfig.value.animation; return themeConfig.value.animation;

View File

@@ -51,3 +51,11 @@ export function GetAssociationTable() {
params: {}, params: {},
}); });
} }
export function saveContent (data:any) {
return request({
url: apiPrefix + 'save_content/',
method: 'put',
data: data
})
}

View File

@@ -1,281 +1,282 @@
<template> <template>
<div> <div>
<el-row :gutter="10"> <el-row :gutter="20">
<el-col :span="4">变量标题</el-col> <el-col :span="4">变量标题</el-col>
<el-col :span="10">变量</el-col> <el-col :span="4">变量</el-col>
<el-col :span="4">变量</el-col> <el-col :span="10">变量</el-col>
<el-col :span="2">是否前端配置</el-col> <el-col :span="2" :offset="1">是否前端配置</el-col>
<el-col :span="3" :offset="1">操作</el-col> <el-col :span="3" >操作</el-col>
</el-row> </el-row>
<el-form ref="formRef" :model="form" label-width="240px" label-position="left" style="margin-top: 20px"> <el-form ref="formRef" :model="formData" label-width="0px" label-position="left" style="margin-top: 20px">
<el-form-item <el-form-item
:label="item.title" :prop="['array'].indexOf(item.form_item_type_label) > -1 ? '' : item.key"
:prop="['array'].indexOf(item.form_item_type_label) > -1 ? '' : item.key" :key="index"
:key="index" :rules="item.rule || []"
:rules="item.rule || []" v-for="(item, index) in formList"
v-for="(item, index) in formList" >
> <el-col :span="4">
<template slot="label"> <el-input v-if="item.edit" v-model="item.title" style="display: inline-block; width: 200px" placeholder="请输入标题"></el-input>
<el-input v-if="item.edit" v-model="item.title" style="display: inline-block; width: 200px" placeholder="请输入标题"></el-input> <span v-else>{{ item.title }}</span>
<span v-else>{{ item.title }}</span> </el-col>
</template> <el-col :span="4" >
<el-col :span="11"> <el-input v-if="item.edit" v-model="item.new_key" style="width: 200px" placeholder="请输入变量key">
<!-- 文本 --> <template slot="prepend">
<el-input <span style="padding: 0px 5px">{{ editableTabsItem.key }}</span>
:key="index" </template>
v-if="['text', 'textarea'].indexOf(item.form_item_type_label) > -1" </el-input>
:type="item.form_item_type_label" <span v-else>{{ editableTabsItem.key }}.{{ item.key }}</span>
v-model="form[item.key]" </el-col>
:placeholder="item.placeholder" <el-col :span="10">
clearable <!-- 文本 -->
></el-input> <el-input
:key="index"
v-if="['text', 'textarea'].indexOf(item.form_item_type_label) > -1"
:type="item.form_item_type_label"
v-model="formData[item.key]"
:placeholder="item.placeholder"
clearable
></el-input>
<el-input-number :key="index + 1" v-else-if="item.form_item_type_label === 'number'" v-model="form[item.key]" :min="0"></el-input-number> <el-input-number :key="index + 1" v-else-if="item.form_item_type_label === 'number'" v-model="formData[item.key]" :min="0"></el-input-number>
<!-- datetimedatetime --> <!-- datetimedatetime -->
<el-date-picker <el-date-picker
v-else-if="['datetime', 'date', 'time'].indexOf(item.form_item_type_label) > -1" v-else-if="['datetime', 'date', 'time'].indexOf(item.form_item_type_label) > -1"
v-model="form[item.key]" v-model="formData[item.key]"
:key="index + 2" :key="index + 2"
:type="item.form_item_type_label" :type="item.form_item_type_label"
:placeholder="item.placeholder" :placeholder="item.placeholder"
> >
</el-date-picker> </el-date-picker>
<!-- select --> <!-- select -->
<el-select <el-select
:key="index + 3" :key="index + 3"
v-else-if="item.form_item_type_label === 'select'" v-else-if="item.form_item_type_label === 'select'"
v-model="form[item.key]" v-model="formData[item.key]"
:placeholder="item.placeholder" :placeholder="item.placeholder"
clearable clearable
> >
<el-option v-for="item in dictionary(item.setting) || []" :key="item.value" :label="item.label" :value="item.value"> </el-option> <el-option v-for="item in dictionary(item.setting) || []" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select> </el-select>
<!-- checkbox --> <!-- checkbox -->
<el-checkbox-group <el-checkbox-group
:key="index + 4" :key="index + 4"
v-else-if="item.form_item_type_label === 'checkbox'" v-else-if="item.form_item_type_label === 'checkbox'"
v-model="form[item.key]" v-model="formData[item.key]"
:placeholder="item.placeholder" :placeholder="item.placeholder"
> >
<el-checkbox v-for="item in dictionary(item.setting) || []" :key="item.value" :label="item.value" :value="item.value"> <el-checkbox v-for="item in dictionary(item.setting) || []" :key="item.value" :label="item.value" :value="item.value">
{{ item.label }} {{ item.label }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<!-- radio --> <!-- radio -->
<el-radio-group <el-radio-group
:key="index + 5" :key="index + 5"
v-else-if="item.form_item_type_label === 'radio'" v-else-if="item.form_item_type_label === 'radio'"
v-model="form[item.key]" v-model="formData[item.key]"
:placeholder="item.placeholder" :placeholder="item.placeholder"
clearable clearable
> >
<el-radio v-for="item in dictionary(item.setting) || []" :key="item.value" :label="item.value" :value="item.value"> <el-radio v-for="item in dictionary(item.setting) || []" :key="item.value" :label="item.value" :value="item.value">
{{ item.label }} {{ item.label }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
<!-- switch --> <!-- switch -->
<el-switch <el-switch
:key="index + 6" :key="index + 6"
v-else-if="item.form_item_type_label === 'switch'" v-else-if="item.form_item_type_label === 'switch'"
v-model="form[item.key]" v-model="formData[item.key]"
active-color="#13ce66" active-color="#13ce66"
inactive-color="#ff4949" inactive-color="#ff4949"
> >
</el-switch> </el-switch>
<!-- 图片 --> <!-- 图片 -->
<div v-else-if="['img', 'imgs'].indexOf(item.form_item_type_label) > -1" :key="index + 7"> <div v-else-if="['img', 'imgs'].indexOf(item.form_item_type_label) > -1" :key="index + 7">
<el-upload <el-upload
:action="uploadUrl" :action="uploadUrl"
:headers="uploadHeaders" :headers="uploadHeaders"
name="file" name="file"
:accept="'image/*'" :accept="'image/*'"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:on-success=" :on-success="
(response:any, file:any, fileList:any) => { (response:any, file:any, fileList:any) => {
handleUploadSuccess(response, file, fileList, item.key); handleUploadSuccess(response, file, fileList, item.key);
} }
" "
:on-error="handleError" :on-error="handleError"
:on-exceed="handleExceed" :on-exceed="handleExceed"
:before-remove=" :before-remove="
(file:any, fileList:any) => { (file:any, fileList:any) => {
beforeRemove(file, fileList, item.key); beforeRemove(file, fileList, item.key);
} }
" "
:multiple="item.form_item_type_label !== 'img'" :multiple="item.form_item_type_label !== 'img'"
:limit="item.form_item_type_label === 'img' ? 1 : 5" :limit="item.form_item_type_label === 'img' ? 1 : 5"
:ref="'imgUpload_' + item.key" :ref="'imgUpload_' + item.key"
:data-keyname="item.key" :data-keyname="item.key"
:file-list="item.value ? item.value : []" :file-list="item.value ? item.value : []"
list-type="picture-card" list-type="picture-card"
> >
<i class="el-icon-plus"></i> <i class="el-icon-plus"></i>
<div slot="tip" class="el-upload__tip">选取图片后,需手动上传到服务器,并且只能上传jpg/png文件</div> <div slot="tip" class="el-upload__tip">选取图片后,需手动上传到服务器,并且只能上传jpg/png文件</div>
</el-upload> </el-upload>
<el-dialog :visible.sync="dialogImgVisible"> <el-dialog :visible.sync="dialogImgVisible">
<img width="100%" :src="dialogImageUrl" alt="" /> <img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog> </el-dialog>
</div> </div>
<!-- 文件 --> <!-- 文件 -->
<div v-else-if="['file'].indexOf(item.form_item_type_label) > -1" :key="index + 8"> <div v-else-if="['file'].indexOf(item.form_item_type_label) > -1" :key="index + 8">
<el-upload <el-upload
:action="uploadUrl" :action="uploadUrl"
:headers="uploadHeaders" :headers="uploadHeaders"
name="file" name="file"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:on-success=" :on-success="
(response:any, file:any, fileList:any) => { (response:any, file:any, fileList:any) => {
handleUploadSuccess(response, file, fileList, item.key); handleUploadSuccess(response, file, fileList, item.key);
} }
" "
:on-error="handleError" :on-error="handleError"
:on-exceed="handleExceed" :on-exceed="handleExceed"
:before-remove=" :before-remove="
(file:any, fileList:any) => { (file:any, fileList:any) => {
beforeRemove(file, fileList, item.key); beforeRemove(file, fileList, item.key);
} }
" "
:limit="5" :limit="5"
:ref="'fileUpload_' + item.key" :ref="'fileUpload_' + item.key"
:data-keyname="item.key" :data-keyname="item.key"
:file-list="item.value" :file-list="item.value"
list-type="picture-card" list-type="picture-card"
> >
<i class="el-icon-plus"></i> <i class="el-icon-plus"></i>
<div slot="tip" class="el-upload__tip">选取图片后,需手动上传到服务器,并且只能上传jpg/png文件</div> <div slot="tip" class="el-upload__tip">选取图片后,需手动上传到服务器,并且只能上传jpg/png文件</div>
</el-upload> </el-upload>
<el-dialog :visible.sync="dialogImgVisible"> <el-dialog :visible.sync="dialogImgVisible">
<img width="100%" :src="dialogImageUrl" alt="" /> <img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog> </el-dialog>
</div> </div>
<!-- 关联表 --> <!-- 关联表 -->
<div v-else-if="['foreignkey', 'manytomany'].indexOf(item.form_item_type_label) > -1" :key="index + 9"> <div v-else-if="['foreignkey', 'manytomany'].indexOf(item.form_item_type_label) > -1" :key="index + 9">
<table-selector <table-selector
v-model="form[item.key]" v-model="formData[item.key]"
:el-props="{ :el-props="{
pagination: true, pagination: true,
columns: item.setting.searchField, columns: item.setting.searchField,
}" }"
:dict="{ :dict="{
url: '/api/system/system_config/get_table_data/' + item.id + '/', url: '/api/system/system_config/get_table_data/' + item.id + '/',
value: item.setting.primarykey, value: item.setting.primarykey,
label: item.setting.field, label: item.setting.field,
}" }"
:pagination="true" :pagination="true"
:multiple="item.form_item_type_label === 'manytomany'" :multiple="item.form_item_type_label === 'manytomany'"
></table-selector> ></table-selector>
</div> </div>
<!-- 数组 --> <!-- 数组 -->
<div v-else-if="item.form_item_type_label === 'array'" :key="index + 10"> <div v-else-if="item.form_item_type_label === 'array'" :key="index + 10">
<vxe-table <vxe-table
border border
resizable resizable
auto-resize auto-resize
show-overflow show-overflow
keep-source keep-source
:ref="'xTable_' + item.key" :ref="'xTable_' + item.key"
height="200" height="200"
:edit-rules="validRules" :edit-rules="validRules"
:edit-config="{ trigger: 'click', mode: 'row', showStatus: true }" :edit-config="{ trigger: 'click', mode: 'row', showStatus: true }"
> >
<vxe-column field="title" title="标题" :edit-render="{ autofocus: '.vxe-input--inner' }"> <vxe-column field="title" title="标题" :edit-render="{ autofocus: '.vxe-input--inner' }">
<template #edit="{ row }"> <template #edit="{ row }">
<vxe-input v-model="row.title" type="text"></vxe-input> <vxe-input v-model="row.title" type="text"></vxe-input>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="key" title="键名" :edit-render="{ autofocus: '.vxe-input--inner' }"> <vxe-column field="key" title="键名" :edit-render="{ autofocus: '.vxe-input--inner' }">
<template #edit="{ row }"> <template #edit="{ row }">
<vxe-input v-model="row.key" type="text"></vxe-input> <vxe-input v-model="row.key" type="text"></vxe-input>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="value" title="键值" :edit-render="{}"> <vxe-column field="value" title="键值" :edit-render="{}">
<template #edit="{ row }"> <template #edit="{ row }">
<vxe-input v-model="row.value" type="text"></vxe-input> <vxe-input v-model="row.value" type="text"></vxe-input>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column title="操作" width="100" show-overflow> <vxe-column title="操作" width="100" show-overflow>
<template #default="{ row, index }"> <template #default="{ row, index }">
<el-popover placement="top" width="160" v-model="childRemoveVisible"> <el-popover placement="top" width="160" v-model="childRemoveVisible">
<p>删除后无法恢复,确定删除吗?</p> <p>删除后无法恢复,确定删除吗?</p>
<div style="text-align: right; margin: 0"> <div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="childRemoveVisible = false">取消</el-button> <el-button size="mini" type="text" @click="childRemoveVisible = false">取消</el-button>
<el-button type="primary" size="mini" @click="onRemoveChild(row, index, item.key)">确定</el-button> <el-button type="primary" size="mini" @click="onRemoveChild(row, index, item.key)">确定</el-button>
</div> </div>
<el-button type="text" slot="reference">删除</el-button> <el-button type="text" slot="reference">删除</el-button>
</el-popover> </el-popover>
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
<div> <div>
<el-button size="mini" @click="onAppend('xTable_' + item.key)">追加</el-button> <el-button size="mini" @click="onAppend('xTable_' + item.key)">追加</el-button>
</div> </div>
</div> </div>
</el-col> </el-col>
<el-col :span="4" :offset="1"> <el-col :span="2" :offset="1">
<el-input v-if="item.edit" v-model="item.new_key" style="width: 200px" placeholder="请输入变量key"> <el-switch v-model="item.status" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
<template slot="prepend"> </el-col>
<span style="padding: 0px 5px">{{ editableTabsItem.key }}</span> <el-col :span="3">
</template> <el-button v-if="item.edit" size="mini" type="primary" :icon="Finished" @click="onEditSave(item)">保存</el-button>
</el-input> <el-button v-else size="mini" type="primary" :icon="Edit" @click="onEdit(index)"></el-button>
<span v-else>{{ editableTabsItem.key }}.{{ item.key }}</span> <el-popconfirm title="确定删除该条数据吗" @confirm="onDelRow(item)">
</el-col> <template #reference>
<el-col :span="3" :offset="1"> <el-button size="mini" type="danger" :icon="Delete" ></el-button>
<el-switch v-model="item.status" active-color="#13ce66" inactive-color="#ff4949"> </el-switch> </template>
</el-col> </el-popconfirm>
<el-col :span="2"> </el-col>
<el-button v-if="item.edit" size="mini" type="primary" icon="el-icon-success" @click="onEditSave(item)"></el-button> </el-form-item>
<el-button v-else size="mini" type="primary" icon="el-icon-edit" @click="onEdit(index)"></el-button> <el-form-item>
<el-popconfirm title="确定删除该条数据吗" @confirm="onDelRow(item)"> <el-button type="primary" @click="onSubmit(formRef)">确定</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" slot="reference"></el-button> </el-form-item>
</el-popconfirm> </el-form>
</el-col> </div>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">确定</el-button>
</el-form-item>
</el-form>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import * as api from '../api'; import * as api from '../api';
import { dictionary } from '/@/utils/dictionary'; import { dictionary } from '/@/utils/dictionary';
import { getBaseURL } from '/@/utils/baseUrl'; import { getBaseURL } from '/@/utils/baseUrl';
import { ref, reactive, watch, nextTick } from 'vue'; import { ref, reactive, watch, nextTick,inject } from 'vue';
import type { FormInstance, FormRules, TableInstance } from 'element-plus'; import type { FormInstance, FormRules, TableInstance } from 'element-plus';
import { successMessage, errorMessage } from '/@/utils/message'; import { successMessage, errorMessage } from '/@/utils/message';
import { Session } from '/@/utils/storage'; import { Session } from '/@/utils/storage';
import {Edit,Finished,Delete} from "@element-plus/icons-vue";
const props = defineProps(['options', 'editableTabsItem']); const props = defineProps(['options', 'editableTabsItem']);
let form: any = reactive({}); let formData: any = reactive({});
let formList: any = ref([]); let formList: any = ref([]);
let childTableData = ref([]); let childTableData = ref([]);
let childRemoveVisible = ref(false); let childRemoveVisible = ref(false);
const validRules = reactive<FormRules>({ const validRules = reactive<FormRules>({
title: [ title: [
{ {
required: true, required: true,
message: '必须填写', message: '必须填写',
}, },
], ],
key: [ key: [
{ {
required: true, required: true,
message: '必须填写', message: '必须填写',
}, },
], ],
value: [ value: [
{ {
required: true, required: true,
message: '必须填写', message: '必须填写',
}, },
], ],
}); });
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>()
let uploadUrl = ref(getBaseURL + 'api/system/file/'); let uploadUrl = ref(getBaseURL + 'api/system/file/');
let uploadHeaders = ref({ let uploadHeaders = ref({
Authorization: 'JWT ' + Session.get('token'), Authorization: 'JWT ' + Session.get('token'),
}); });
let dialogImageUrl = ref(''); let dialogImageUrl = ref('');
let dialogImgVisible = ref(false); let dialogImgVisible = ref(false);
@@ -283,222 +284,224 @@ let uploadImgKey = ref(null);
// 获取数据 // 获取数据
const getInit = () => { const getInit = () => {
api.GetList({ parent: props.options.id, limit: 999 }).then((res: any) => { api.GetList({ parent: props.options.id, limit: 999 }).then((res: any) => {
let data = res.data; let data = res.data;
formList = data; formList.value = data;
const formData: any = {}; const _formData: any = {};
for (const item of data) { for (const item of data) {
const key = item.key; const key = item.key;
if (item.value) { if (item.value) {
formData[key] = item.value; _formData[key] = item.value;
} else { } else {
if ([5, 12, 14].indexOf(item.form_item_type) !== -1) { if ([5, 12, 14].indexOf(item.form_item_type) !== -1) {
formData[key] = []; _formData[key] = [];
} else { } else {
formData[key] = undefined; _formData[key] = undefined;
} }
} }
if (item.form_item_type_label === 'array') { if (item.form_item_type_label === 'array') {
console.log('test'); console.log('test');
nextTick(() => { nextTick(() => {
const tableName = 'xTable_' + key; const tableName = 'xTable_' + key;
const tabelRef = ref<TableInstance>(); const tabelRef = ref<TableInstance>();
console.log(tabelRef); console.log(tabelRef);
// const $table = this.$refs[tableName][0]; // const $table = this.$refs[tableName][0];
// $table.loadData(item.chinldern); // $table.loadData(item.chinldern);
}); });
} }
} }
form = JSON.parse(JSON.stringify(formData)); formData = Object.assign(formData, _formData)
}); });
}; };
// 提交数据 // 提交数据
const onSubmit = () => { const onSubmit = (formEl: FormInstance | undefined) => {
// const form = JSON.parse(JSON.stringify(form)); // const form = JSON.parse(JSON.stringify(form));
const keys = Object.keys(form); const keys = Object.keys(formData);
const values = Object.values(form); const values = Object.values(formData);
for (const index in formList) { for (const index in formList.value) {
const item = formList[index]; const item = formList.value[index];
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
const form_item_type_label = item.form_item_type_label; const form_item_type_label = item.form_item_type_label;
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
if (form_item_type_label === 'array') { if (form_item_type_label === 'array') {
const parentId = item.id; const parentId = item.id;
const tableName = 'xTable_' + item.key; const tableName = 'xTable_' + item.key;
// const $table = this.$refs[tableName][0]; // const $table = this.$refs[tableName][0];
// const { tableData } = $table.getTableData(); // const { tableData } = $table.getTableData();
// for (const child of tableData) { // for (const child of tableData) {
// if (!child.id && child.key && child.value) { // if (!child.id && child.key && child.value) {
// child.parent = parentId; // child.parent = parentId;
// child.id = null; // child.id = null;
// formList.push(child); // formList.push(child);
// } // }
// } // }
// // 必填项的判断 // // 必填项的判断
// for (const arr of item.rule) { // for (const arr of item.rule) {
// if (arr.required && tableData.length === 0) { // if (arr.required && tableData.length === 0) {
// errorMessage(item.title + '不能为空'); // errorMessage(item.title + '不能为空');
// return; // return;
// } // }
// } // }
// item.value = tableData; // item.value = tableData;
} }
// 赋值操作 // 赋值操作
keys.map((mapKey, mapIndex) => { keys.map((mapKey, mapIndex) => {
if (mapKey === item.key) { if (mapKey === item.key) {
if (item.form_item_type_label !== 'array') { if (item.form_item_type_label !== 'array') {
item.value = values[mapIndex]; item.value = values[mapIndex];
} }
// 必填项的验证 // 必填项的验证
if (['img', 'imgs'].indexOf(item.form_item_type_label) > -1) { if (['img', 'imgs'].indexOf(item.form_item_type_label) > -1) {
for (const arr of item.rule) { for (const arr of item.rule) {
if (arr.required && item.value === null) { if (arr.required && item.value === null) {
errorMessage(item.title + '不能为空'); errorMessage(item.title + '不能为空');
return; return;
} }
} }
} }
} }
}); });
} }
// formRef.clearValidate(); // formRef.value.clearValidate();
// formRef.validate((valid) => { if (!formEl) return
// if (valid) { formEl.validate((valid:any) => {
// api.saveContent(this.options.id, this.formList).then((res) => { if (valid) {
// this.$message.success('保存成功'); api.saveContent(formList.value).then((res:any) => {
// this.refreshView(); successMessage('保存成功');
// }); refreshView&&refreshView();
// } else { });
// console.log('error submit!!'); } else {
// return false; console.log('error submit!!');
// } return false;
// }); }
});
}; };
// 追加 // 追加
const onAppend = (tableName: any) => { const onAppend = (tableName: any) => {
// const $table = this.$refs[tableName][0]; // const $table = this.$refs[tableName][0];
// const { tableData } = $table.getTableData(); // const { tableData } = $table.getTableData();
// const tableLength = tableData.length; // const tableLength = tableData.length;
// if (tableLength === 0) { // if (tableLength === 0) {
// const { row: newRow } = $table.insert(); // const { row: newRow } = $table.insert();
// console.log(newRow); // console.log(newRow);
// } else { // } else {
// const errMap = $table.validate().catch((errMap: any) => errMap); // const errMap = $table.validate().catch((errMap: any) => errMap);
// if (errMap) { // if (errMap) {
// errorMessage('校验不通过!'); // errorMessage('校验不通过!');
// } else { // } else {
// const { row: newRow } = $table.insert(); // const { row: newRow } = $table.insert();
// console.log(newRow); // console.log(newRow);
// } // }
// } // }
}; };
// 子表删除 // 子表删除
const onRemoveChild = (row: any, index: any, refName: any) => { const onRemoveChild = (row: any, index: any, refName: any) => {
console.log(row, index); console.log(row, index);
if (row.id) { if (row.id) {
api.DelObj(row.id).then((res: any) => { api.DelObj(row.id).then((res: any) => {
// this.refreshView(); // this.refreshView();
}); });
} else { } else {
// this.childTableData.splice(index, 1); // this.childTableData.splice(index, 1);
// const tableName = 'xTable_' + refName; // const tableName = 'xTable_' + refName;
// const tableData = this.$refs[tableName][0].remove(row); // const tableData = this.$refs[tableName][0].remove(row);
// console.log(tableData); // console.log(tableData);
} }
}; };
// 图片预览 // 图片预览
const handlePictureCardPreview = (file: any) => { const handlePictureCardPreview = (file: any) => {
dialogImageUrl = file.url; dialogImageUrl = file.url;
dialogImgVisible.value = true; dialogImgVisible.value = true;
}; };
// 判断是否为图片 // 判断是否为图片
// 封装一个判断图片文件后缀名的方法 // 封装一个判断图片文件后缀名的方法
const isImage = (fileName: any) => { const isImage = (fileName: any) => {
if (typeof fileName !== 'string') return; if (typeof fileName !== 'string') return;
const name = fileName.toLowerCase(); const name = fileName.toLowerCase();
return name.endsWith('.png') || name.endsWith('.jpeg') || name.endsWith('.jpg') || name.endsWith('.png') || name.endsWith('.bmp'); return name.endsWith('.png') || name.endsWith('.jpeg') || name.endsWith('.jpg') || name.endsWith('.png') || name.endsWith('.bmp');
}; };
// 上传成功 // 上传成功
const handleUploadSuccess = (response: any, file: any, fileList: any, imgKey: any) => { const handleUploadSuccess = (response: any, file: any, fileList: any, imgKey: any) => {
const that = this; const that = this;
const { code, msg } = response; const { code, msg } = response;
if (code === 2000) { if (code === 2000) {
const { url } = response.data; const { url } = response.data;
const { name } = file; const { name } = file;
const type = isImage(name); const type = isImage(name);
if (!type) { if (!type) {
errorMessage('只允许上传图片'); errorMessage('只允许上传图片');
} else { } else {
const uploadImgKey = form[imgKey]; const uploadImgKey = formData[imgKey];
if (!uploadImgKey || uploadImgKey === '') { if (!uploadImgKey || uploadImgKey === '') {
form[imgKey] = []; formData[imgKey] = [];
} }
// console.log(len) // console.log(len)
const dict = { const dict = {
name: name, name: name,
url: getBaseURL() + url, url: getBaseURL() + url,
}; };
form[imgKey].push(dict); formData[imgKey].push(dict);
} }
} else { } else {
errorMessage('上传失败,' + JSON.stringify(msg)); errorMessage('上传失败,' + JSON.stringify(msg));
} }
}; };
// 上传失败 // 上传失败
const handleError = () => { const handleError = () => {
errorMessage('上传失败'); errorMessage('上传失败');
}; };
// 上传超出限制 // 上传超出限制
const handleExceed = () => { const handleExceed = () => {
errorMessage('超过文件上传数量'); errorMessage('超过文件上传数量');
}; };
// 删除时的钩子 // 删除时的钩子
const beforeRemove = (file: any, fileList: any, key: any) => { const beforeRemove = (file: any, fileList: any, key: any) => {
var index = 0; var index = 0;
form[key].map((value: any, inx: any) => { formData[key].map((value: any, inx: any) => {
if (value.uid === file.uid) index = inx; if (value.uid === file.uid) index = inx;
}); });
form[key].splice(index, 1); formData[key].splice(index, 1);
}; };
// 配置的行删除 // 配置的行删除
const onDelRow = (obj: any) => { const onDelRow = (obj: any) => {
api.DelObj(obj.id).then((res: any) => { api.DelObj(obj.id).then((res: any) => {
// this.refreshView(); // this.refreshView();
}); });
}; };
// 行编辑 // 行编辑
const onEdit = (index: any) => { const onEdit = (index: any) => {
// that.$set(that.formList[index], 'new_key', that.formList[index].key) formList.value[index].edit =true
// that.$set(that.formList[index], 'edit', true) formList.value[index].new_key =formList.value[index].key
}; };
// 行编辑保存 // 行编辑保存
const refreshView = inject<Function>('refreshView')
const onEditSave = (obj: any) => { const onEditSave = (obj: any) => {
obj.key = JSON.parse(JSON.stringify(obj.new_key)); obj.key = JSON.parse(JSON.stringify(obj.new_key));
api.UpdateObj(obj).then((res: any) => { api.UpdateObj(obj).then((res: any) => {
// this.refreshView(); refreshView && refreshView()
}); });
}; };
watch( watch(
props.options, props.options,
(nv) => { (nv) => {
if (nv && nv.id) { if (nv && nv.id) {
getInit(); getInit();
} }
}, },
{ immediate: true } { immediate: true }
); );
</script> </script>

View File

@@ -11,9 +11,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { useExpose, useCrud } from '@fast-crud/fast-crud'; import { useExpose, useCrud,dict } from '@fast-crud/fast-crud';
import { createCrudOptions } from './curd'; import { createCrudOptions } from './curd';
import RolePermission from '/@/views/system/rolePermission/index.vue'; import RolePermission from '/@/views/system/rolePermission/index.vue';
import * as api from './api'
import _ from "lodash-es";
const rolePermission = ref(); const rolePermission = ref();
defineExpose(rolePermission); defineExpose(rolePermission);
// crud组件的ref // crud组件的ref