更改view为抽屉展示,增加导出确认提示

This commit is contained in:
嘉泽 2023-11-25 21:14:27 +08:00
parent 70e9f966c3
commit 514a9a32b3
4 changed files with 140 additions and 39 deletions

View File

@ -9,6 +9,7 @@ import (
"bytes"
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
)
@ -21,18 +22,18 @@ func (l *gCurd) webViewTplData(ctx context.Context, in *CurdPreviewInput) (data
func (l *gCurd) generateWebViewItem(ctx context.Context, in *CurdPreviewInput) string {
buffer := bytes.NewBuffer(nil)
for _, field := range in.masterFields {
if !field.IsEdit {
continue
}
// if !field.IsEdit {
// continue
// }
var (
defaultComponent = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n {{ formValue.%s }}\n </n-descriptions-item>", field.Dc, field.TsName)
defaultComponent = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">{{ params.%s }}</div>\n </div>", field.Dc, field.TsName)
component string
)
switch field.FormMode {
case FormModeInputTextarea, FormModeInputEditor:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <span v-html=\"formValue.%s\"></span></n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <span v-html=\"params.%s\"></span>\n </div>\n </div>", field.Dc, field.TsName)
case FormModeInputDynamic:
component = defaultComponent
@ -44,28 +45,28 @@ func (l *gCurd) generateWebViewItem(ctx context.Context, in *CurdPreviewInput) s
component = defaultComponent
case FormModeRadio, FormModeSelect:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-tag\n :type=\"getOptionTag(options.%s, formValue?.%s)\"\n size=\"small\"\n class=\"min-left-space\"\n >{{ getOptionLabel(options.%s, formValue?.%s) }}</n-tag\n >\n </n-descriptions-item>", field.Dc, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <n-tag\n :type=\"getOptionTag(options.%s, params?.%s)\"\n size=\"small\"\n class=\"min-left-space\"\n >{{ getOptionLabel(options.%s, params?.%s) }}</n-tag\n >\n </div>\n </div>", field.Dc, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
case FormModeCheckbox, FormModeSelectMultiple:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <template v-for=\"(item, key) in formValue?.%s\" :key=\"key\">\n <n-tag\n :type=\"getOptionTag(options.%s, item)\"\n size=\"small\"\n class=\"min-left-space\"\n >{{ getOptionLabel(options.%s, item) }}</n-tag\n >\n </template>\n </n-descriptions-item>", field.Dc, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <template v-for=\"(item, key) in params?.%s\" :key=\"key\">\n <n-tag\n :type=\"getOptionTag(options.%s, item)\"\n size=\"small\"\n class=\"min-left-space\"\n >{{ getOptionLabel(options.%s, item) }}\n </n-tag>\n </template>\n </div>\n </div>", field.Dc, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
case FormModeUploadImage:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"formValue.%s\"\n /></n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <n-image\n style=\"margin-left: 10px; height: 100px; width: 100px\"\n :src=\"params.%s\"\n />\n </div>\n </div>", field.Dc, field.TsName)
case FormModeUploadImages:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <n-image-group>\n <n-space>\n <span v-for=\"(item, key) in formValue?.%s\" :key=\"key\">\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"item\" />\n </span>\n </n-space>\n </n-image-group>\n </n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <n-image-group>\n <n-space>\n <span v-for=\"(item, key) in params?.%s\" :key=\"key\">\n <n-image\n style=\"margin-left: 10px; height: 100px; width: 100px\"\n :src=\"item\"\n />\n </span>\n </n-space>\n </n-image-group>\n </div>\n </div>", field.Dc, field.TsName)
case FormModeUploadFile:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <div\n class=\"upload-card\"\n v-show=\"formValue.%s !== ''\"\n @click=\"download(formValue.%s)\"\n >\n <div class=\"upload-card-item\" style=\"height: 100px; width: 100px\">\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\">{{ getFileExt(formValue.%s) }}</n-avatar>\n </div>\n </div>\n </div>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName, field.TsName, field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\"\n ><div\n class=\"upload-card\"\n v-show=\"params.attachfile !== ''\"\n @click=\"download(params.%s)\"\n >\n <div class=\"upload-card-item\" style=\"height: 100px; width: 100px\">\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\">{{\n getFileExt(params.attachfile)\n }}</n-avatar>\n </div>\n </div>\n </div>\n </div></div\n >\n </div>", field.TsName, field.TsName)
case FormModeUploadFiles:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <div class=\"upload-card\">\n <n-space style=\"gap: 0px 0px\">\n <div\n class=\"upload-card-item\"\n style=\"height: 100px; width: 100px\"\n v-for=\"(item, key) in formValue.%s\"\n :key=\"key\"\n >\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\" @click=\"download(item)\">{{\n getFileExt(item)\n }}</n-avatar>\n </div>\n </div>\n </div>\n </n-space>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <div class=\"upload-card\">\n <n-space style=\"gap: 0px 0px\">\n <div\n class=\"upload-card-item\"\n style=\"height: 100px; width: 100px\"\n v-for=\"(item, key) in params.%s\"\n :key=\"key\"\n >\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\" @click=\"download(item)\">{{\n getFileExt(item)\n }}</n-avatar>\n </div>\n </div>\n </div>\n </n-space>\n </div>\n </div>\n </div>", field.Dc, field.TsName)
case FormModeSwitch:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-switch v-model:value=\"formValue.%s\" :unchecked-value=\"2\" :checked-value=\"1\" :disabled=\"true\"\n /></n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <n-switch\n v-model:value=\"params.%s\"\n :unchecked-value=\"2\"\n :checked-value=\"1\"\n :disabled=\"true\"\n />\n </div>\n </div>", field.Dc, field.TsName)
case FormModeRate:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\"\n ><n-rate readonly :default-value=\"formValue.%s\"\n /></n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf(" <div class=\"item\">\n <div>%s</div>\n <div class=\"value\">\n <n-rate readonly :default-value=\"params.%s\" />\n </div>\n </div>", field.Dc, field.TsName)
default:
component = defaultComponent

View File

@ -37,7 +37,7 @@ INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type
SET @listId = LAST_INSERT_ID();
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) }
-- 详情
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '@{.tableComment}详情', '@{.varName | LcFirst}View', 'view/:id?', '', '2', '', '/@{.apiPrefix}/view', '', '/@{.componentPrefix}/view', '0', '@{.varName | LcFirst}Index', '0', '0', '', '0', '1', '0', '2', '', '20', '', '1', @now, @now);
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '@{.tableComment}详情', '@{.varName | LcFirst}View', 'view/:id?', '', '3', '', '/@{.apiPrefix}/view', '', '/@{.componentPrefix}/view', '0', '@{.varName | LcFirst}Index', '0', '0', '', '0', '1', '0', '2', '', '20', '', '1', @now, @now);
@{end}
-- 菜单按钮

View File

@ -2,7 +2,7 @@
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="@{.tableComment}">
<!-- 这是由系统生成的CURD表格你可以将此行注释改为表格的描述 -->
<!-- @{.tableComment}列表页 -->
</n-card>
</div>
<n-card :bordered="false" class="proCard">
@ -26,7 +26,6 @@
:row-key="(row) => row.id"
ref="actionRef"
:actionColumn="actionColumn"
:checked-row-keys="checkedIds"
@update:checked-row-keys="onCheckedRow"
:scroll-x="1090"
:resizeHeightOffset="-10000"
@ -82,6 +81,7 @@
:showModal="showModal"
:formParams="formParams"
/>@{end}
@{ if eq .options.Step.HasView true } <View @updateShowView="updateShowView" :formParams="formParams" :showView="showView" />@{end}
</div>
</template>
@ -97,6 +97,8 @@
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) } import { useRouter } from 'vue-router';@{end}
import { getOptionLabel } from '@/utils/hotgo';
@{ if eq .options.Step.HasEdit true } import Edit from './edit.vue';@{end}
@{ if eq .options.Step.HasView true } import View from './view.vue';@{end}
const { hasPermission } = usePermission();
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) } const router = useRouter();@{end}
const actionRef = ref();
@ -106,6 +108,7 @@
const batchDeleteDisabled = ref(true);
const checkedIds = ref([]);
const showModal = ref(false);
const showView = ref(false);
const formParams = ref<State>();
const actionColumn = reactive({
@ -189,7 +192,12 @@
}
@{ if eq .options.Step.HasView true }
function handleView(record: Recordable) {
router.push({ name: '@{.varName | LcFirst}View', params: { id: record.@{.pk.TsName} } });
showView.value = true;
formParams.value = newState(record as State);
}
function updateShowView(value) {
showView.value = value;
}@{end}
@{ if eq .options.Step.HasEdit true }
function handleEdit(record: Recordable) {
@ -223,8 +231,6 @@
negativeText: '取消',
onPositiveClick: () => {
Delete({ id: checkedIds.value }).then((_res) => {
batchDeleteDisabled.value = true;
checkedIds.value = [];
message.success('删除成功');
reloadTable();
});
@ -236,8 +242,19 @@
}@{end}
@{ if eq .options.Step.HasExport true } function handleExport() {
message.loading('正在导出列表...', { duration: 1200 });
Export(searchFormRef.value?.formModel);
dialog.warning({
title: '警告',
content: '是否确定执行此操作',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
message.loading('正在导出列表...', { duration: 1200 });
Export(searchFormRef.value?.formModel);
},
onNegativeClick: () => {
// message.error('取消');
},
});
}@{end}
@{ if eq .options.Step.HasStatus true } function handleStatus(record: Recordable, status: number) {

View File

@ -1,29 +1,35 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="@{.tableComment}详情"> <!-- CURD详情页--> </n-card>
</div>
<n-card :bordered="false" class="proCard mt-4" size="small" :segmented="{ content: true }">
<n-descriptions label-placement="left" class="py-2" column="4">
<n-drawer v-model:show="isShowView" :width="502">
<n-drawer-content title="@{.tableComment}详情">
<div class="view">
<div class="section">
<div class="section-bd">
@{.item}
</n-descriptions>
</n-card>
</div>
</div>
</div>
<template #footer>
<n-button @click="closeView">关闭</n-button>
</template>
</n-drawer-content>
</n-drawer>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue';
import { computed, watch, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useMessage } from 'naive-ui';
import { View } from '@{.importWebApi}';
import { newState, options } from './model';
import { newState, State, options } from './model';
import { getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils';
import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
const { getAppTheme } = useDesignSetting();
const message = useMessage();
const router = useRouter();
const id = Number(router.currentRoute.value.params.id);
const formValue = ref(newState(null));
const fileAvatarCSS = computed(() => {
return {
'--n-merged-size': `var(--n-avatar-size-override, 80px)`,
@ -31,18 +37,95 @@
};
});
const emit = defineEmits(['updateShowView']);
interface Props {
showView: boolean;
formParams?: State;
}
const props = withDefaults(defineProps<Props>(), {
showView: false,
formParams: () => {
return newState(null);
},
});
const isShowView = computed({
get: () => {
return props.showView;
},
set: (value) => {
emit('updateShowView', value);
},
});
const viewLoading = ref(false);
const params = ref<State>(props.formParams);
function closeView() {
isShowView.value = false;
}
//下载
function download(url: string) {
window.open(url);
}
onMounted(async () => {
if (id < 1) {
message.error('@{.pk.Dc}不正确请检查');
return;
function loadForm(value) {
viewLoading.value = true;
View({ id: value.id })
.then((res) => {
params.value = res;
})
.finally(() => {
viewLoading.value = false;
});
}
watch(
() => props.formParams,
(value) => {
console.log('watch数据', value);
loadForm(value);
}
formValue.value = await View({ @{.pk.TsName}: id });
});
);
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
.view {
.section {
padding: 5px 0;
border-bottom: 1px dashed #eeeeee;
&-hd {
padding-left: 10px;
border-left: 3px solid v-bind(getAppTheme);
font-weight: 500;
font-size: 14px;
line-height: 16px;
color: #303133;
}
&-bd {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 0 0 calc((100% - 60px) / 1);
display: flex;
margin: 16px 30px 0 0;
font-size: 13px;
color: #666;
&:nth-child(1n + 1) {
margin: 16px 0 0;
}
}
.value {
flex: 1;
}
}
}
</style>