Commit 33fb112dfecc23df103e8039f57097a451238519
1 parent
7041baf1
feat:【infra】移动端 admin uniapp 的代码生成的初始化
Showing
7 changed files
with
921 additions
and
0 deletions
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
| ... | ... | @@ -137,6 +137,16 @@ public class CodegenEngine { |
| 137 | 137 | vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) |
| 138 | 138 | .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("api/api.ts"), |
| 139 | 139 | vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) |
| 140 | + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("api/api.ts"), | |
| 141 | + vue3UniappFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) | |
| 142 | + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/index.vue"), | |
| 143 | + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/index.vue")) | |
| 144 | + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("components/search-form.vue"), | |
| 145 | + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/components/search-form.vue")) | |
| 146 | + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/form/index.vue"), | |
| 147 | + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/form/index.vue")) | |
| 148 | + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/detail/index.vue"), | |
| 149 | + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/detail/index.vue")) | |
| 140 | 150 | // VUE3_VBEN2_ANTD_SCHEMA |
| 141 | 151 | .put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/data.ts"), |
| 142 | 152 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) |
| ... | ... | @@ -617,6 +627,15 @@ public class CodegenEngine { |
| 617 | 627 | "src/" + path; |
| 618 | 628 | } |
| 619 | 629 | |
| 630 | + private static String vue3AdminUniappTemplatePath(String path) { | |
| 631 | + return "codegen/vue3_admin_uniapp/" + path + ".vm"; | |
| 632 | + } | |
| 633 | + | |
| 634 | + private static String vue3UniappFilePath(String path) { | |
| 635 | + return "yudao-ui-${sceneEnum.basePackage}-uniapp/" + // 顶级目录 | |
| 636 | + "src/" + path; | |
| 637 | + } | |
| 638 | + | |
| 620 | 639 | private static String vue3VbenFilePath(String path) { |
| 621 | 640 | return "yudao-ui-${sceneEnum.basePackage}-vben/" + // 顶级目录 |
| 622 | 641 | "src/" + path; | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/api/api.ts.vm
0 → 100644
| 1 | +import type { PageParam, PageResult } from '@/http/types' | |
| 2 | +import { http } from '@/http/http' | |
| 3 | + | |
| 4 | +// TODO @AI:不使用 baseUrl,而是参考之前的,直接写在每个方法里。 | |
| 5 | +#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") | |
| 6 | +const baseUrl = '${baseURL}' | |
| 7 | + | |
| 8 | +#set ($primaryJavaType = $primaryColumn.javaType.toLowerCase()) | |
| 9 | +#if(${primaryJavaType} == "long" || ${primaryJavaType} == "integer" || ${primaryJavaType} == "short" || ${primaryJavaType} == "double" || ${primaryJavaType} == "bigdecimal" || ${primaryJavaType} == "byte") | |
| 10 | +#set ($primaryTsType = "number") | |
| 11 | +#else | |
| 12 | +#set ($primaryTsType = "string") | |
| 13 | +#end | |
| 14 | + | |
| 15 | +/** ${table.classComment}信息 */ | |
| 16 | +export interface ${simpleClassName} { | |
| 17 | +#foreach ($column in $columns) | |
| 18 | + #if ($column.primaryKey || $column.createOperation || $column.updateOperation || $column.listOperationResult) | |
| 19 | + #set ($javaType = $column.javaType.toLowerCase()) | |
| 20 | + #set ($optional = $column.nullable || $column.primaryKey) | |
| 21 | + #if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") | |
| 22 | + ${column.javaField}#if($optional)?#end: number | |
| 23 | + #elseif(${javaType} == "boolean") | |
| 24 | + ${column.javaField}#if($optional)?#end: boolean | |
| 25 | + #else | |
| 26 | + ${column.javaField}#if($optional)?#end: string | |
| 27 | + #end | |
| 28 | + #end | |
| 29 | +#end | |
| 30 | +} | |
| 31 | + | |
| 32 | +/** 获取${table.classComment}分页列表 */ | |
| 33 | +export function get${simpleClassName}Page(params: PageParam) { | |
| 34 | + return http.get<PageResult<${simpleClassName}>>(baseUrl + '/page', params) | |
| 35 | +} | |
| 36 | + | |
| 37 | +/** 获取${table.classComment}详情 */ | |
| 38 | +export function get${simpleClassName}(id: ${primaryTsType}) { | |
| 39 | + return http.get<${simpleClassName}>(baseUrl + '/get?id=' + id) | |
| 40 | +} | |
| 41 | + | |
| 42 | +/** 创建${table.classComment} */ | |
| 43 | +export function create${simpleClassName}(data: ${simpleClassName}) { | |
| 44 | + return http.post<number>(baseUrl + '/create', data) | |
| 45 | +} | |
| 46 | + | |
| 47 | +/** 更新${table.classComment} */ | |
| 48 | +export function update${simpleClassName}(data: ${simpleClassName}) { | |
| 49 | + return http.put<boolean>(baseUrl + '/update', data) | |
| 50 | +} | |
| 51 | + | |
| 52 | +/** 删除${table.classComment} */ | |
| 53 | +export function delete${simpleClassName}(id: ${primaryTsType}) { | |
| 54 | + return http.delete<boolean>(baseUrl + '/delete?id=' + id) | |
| 55 | +} | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/components/search-form.vue.vm
0 → 100644
| 1 | +<template> | |
| 2 | + <wd-search | |
| 3 | + :placeholder="searchPlaceholder" | |
| 4 | + :hide-cancel="true" | |
| 5 | + disabled | |
| 6 | + @click="visible = true" | |
| 7 | + /> | |
| 8 | + | |
| 9 | + <wd-popup | |
| 10 | + v-model="visible" | |
| 11 | + position="top" | |
| 12 | + custom-style="border-radius: 0 0 24rpx 24rpx;" | |
| 13 | + safe-area-inset-top | |
| 14 | + @close="visible = false" | |
| 15 | + > | |
| 16 | + <view class="p-32rpx"> | |
| 17 | + <view class="mb-24rpx text-32rpx text-[#333] font-semibold"> | |
| 18 | + 搜索${table.classComment} | |
| 19 | + </view> | |
| 20 | + | |
| 21 | +#set ($hasDict = 0) | |
| 22 | +#foreach ($column in $columns) | |
| 23 | + #if ($hasDict == 0 && $column.listOperation && $column.dictType && "" != $column.dictType) | |
| 24 | + #set ($hasDict = 1) | |
| 25 | + #end | |
| 26 | +#end | |
| 27 | + | |
| 28 | +#foreach($column in $columns) | |
| 29 | + #if ($column.listOperation) | |
| 30 | + #set ($dictType = $column.dictType) | |
| 31 | + #set ($javaField = $column.javaField) | |
| 32 | + #set ($javaType = $column.javaType) | |
| 33 | + #set ($comment = $column.columnComment) | |
| 34 | + #set ($dictMethod = "getDictOptions") | |
| 35 | + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | |
| 36 | + #set ($dictMethod = "getIntDictOptions") | |
| 37 | + #elseif ($javaType == "String") | |
| 38 | + #set ($dictMethod = "getStrDictOptions") | |
| 39 | + #elseif ($javaType == "Boolean") | |
| 40 | + #set ($dictMethod = "getBoolDictOptions") | |
| 41 | + #end | |
| 42 | + | |
| 43 | + #if ($column.htmlType == "input") | |
| 44 | + <view class="mb-24rpx"> | |
| 45 | + <view class="mb-12rpx text-28rpx text-[#666]"> | |
| 46 | + ${comment} | |
| 47 | + </view> | |
| 48 | + <wd-input | |
| 49 | + v-model="formData.${javaField}" | |
| 50 | + placeholder="请输入${comment}" | |
| 51 | + clearable | |
| 52 | + /> | |
| 53 | + </view> | |
| 54 | + #elseif (($column.htmlType == "select" || $column.htmlType == "radio") && $dictType && "" != $dictType) | |
| 55 | + <view class="mb-32rpx"> | |
| 56 | + <view class="mb-12rpx text-28rpx text-[#666]"> | |
| 57 | + ${comment} | |
| 58 | + </view> | |
| 59 | + <wd-radio-group v-model="formData.${javaField}" shape="button" size="medium"> | |
| 60 | + <wd-radio :value="-1"> | |
| 61 | + 全部 | |
| 62 | + </wd-radio> | |
| 63 | + <wd-radio | |
| 64 | + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | |
| 65 | + :key="dict.value" | |
| 66 | + :value="dict.value" | |
| 67 | + > | |
| 68 | + {{ dict.label }} | |
| 69 | + </wd-radio> | |
| 70 | + </wd-radio-group> | |
| 71 | + </view> | |
| 72 | + #else | |
| 73 | + <view class="mb-24rpx"> | |
| 74 | + <view class="mb-12rpx text-28rpx text-[#666]"> | |
| 75 | + ${comment} | |
| 76 | + </view> | |
| 77 | + <wd-input | |
| 78 | + v-model="formData.${javaField}" | |
| 79 | + placeholder="请输入${comment}" | |
| 80 | + clearable | |
| 81 | + /> | |
| 82 | + </view> | |
| 83 | + #end | |
| 84 | + #end | |
| 85 | +#end | |
| 86 | + | |
| 87 | + <view class="w-full flex justify-center gap-24rpx"> | |
| 88 | + <wd-button class="flex-1" plain @click="handleReset"> | |
| 89 | + 重置 | |
| 90 | + </wd-button> | |
| 91 | + <wd-button class="flex-1" type="primary" @click="handleSearch"> | |
| 92 | + 搜索 | |
| 93 | + </wd-button> | |
| 94 | + </view> | |
| 95 | + </view> | |
| 96 | + </wd-popup> | |
| 97 | +</template> | |
| 98 | + | |
| 99 | +<script lang="ts" setup> | |
| 100 | +import { computed, reactive, ref, watch } from 'vue' | |
| 101 | + | |
| 102 | +#set ($hasDict = 0) | |
| 103 | +#set ($hasGetDictOptions = 0) | |
| 104 | +#set ($hasGetIntDictOptions = 0) | |
| 105 | +#set ($hasGetStrDictOptions = 0) | |
| 106 | +#set ($hasGetBoolDictOptions = 0) | |
| 107 | +#foreach($column in $columns) | |
| 108 | + #if ($column.listOperation && $column.dictType && "" != $column.dictType) | |
| 109 | + #set ($hasDict = 1) | |
| 110 | + #if ($column.htmlType == "select" || $column.htmlType == "radio") | |
| 111 | + #if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short") | |
| 112 | + #set ($hasGetIntDictOptions = 1) | |
| 113 | + #elseif ($column.javaType == "String") | |
| 114 | + #set ($hasGetStrDictOptions = 1) | |
| 115 | + #elseif ($column.javaType == "Boolean") | |
| 116 | + #set ($hasGetBoolDictOptions = 1) | |
| 117 | + #else | |
| 118 | + #set ($hasGetDictOptions = 1) | |
| 119 | + #end | |
| 120 | + #end | |
| 121 | + #end | |
| 122 | +#end | |
| 123 | +#if ($hasDict == 1) | |
| 124 | +import { DICT_TYPE } from '@/utils/constants' | |
| 125 | +import { | |
| 126 | + #if ($hasGetDictOptions == 1) | |
| 127 | + getDictOptions, | |
| 128 | + #end | |
| 129 | + #if ($hasGetIntDictOptions == 1) | |
| 130 | + getIntDictOptions, | |
| 131 | + #end | |
| 132 | + #if ($hasGetStrDictOptions == 1) | |
| 133 | + getStrDictOptions, | |
| 134 | + #end | |
| 135 | + #if ($hasGetBoolDictOptions == 1) | |
| 136 | + getBoolDictOptions, | |
| 137 | + #end | |
| 138 | + getDictLabel, | |
| 139 | +} from '@/hooks/useDict' | |
| 140 | +#end | |
| 141 | + | |
| 142 | +/** 搜索表单数据 */ | |
| 143 | +export interface SearchFormData { | |
| 144 | +#foreach($column in $columns) | |
| 145 | + #if ($column.listOperation) | |
| 146 | + #set ($javaType = $column.javaType.toLowerCase()) | |
| 147 | + #if ($column.dictType && "" != $column.dictType) | |
| 148 | + #if(${javaType} == "string") | |
| 149 | + ${column.javaField}?: string | number | |
| 150 | + #elseif(${javaType} == "boolean") | |
| 151 | + ${column.javaField}?: boolean | number | |
| 152 | + #else | |
| 153 | + ${column.javaField}?: number | |
| 154 | + #end | |
| 155 | + #elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") | |
| 156 | + ${column.javaField}?: number | |
| 157 | + #elseif(${javaType} == "boolean") | |
| 158 | + ${column.javaField}?: boolean | |
| 159 | + #else | |
| 160 | + ${column.javaField}?: string | |
| 161 | + #end | |
| 162 | + #end | |
| 163 | +#end | |
| 164 | +} | |
| 165 | + | |
| 166 | +const props = defineProps<{ | |
| 167 | + searchParams?: Partial<SearchFormData> | |
| 168 | +}>() | |
| 169 | + | |
| 170 | +const emit = defineEmits<{ | |
| 171 | + search: [data: SearchFormData] | |
| 172 | + reset: [] | |
| 173 | +}>() | |
| 174 | + | |
| 175 | +const visible = ref(false) | |
| 176 | + | |
| 177 | +/** 搜索条件 placeholder 拼接 */ | |
| 178 | +const searchPlaceholder = computed(() => { | |
| 179 | + const conditions: string[] = [] | |
| 180 | +#foreach($column in $columns) | |
| 181 | + #if ($column.listOperation) | |
| 182 | + #set ($dictType = $column.dictType) | |
| 183 | + #set ($javaField = $column.javaField) | |
| 184 | + #set ($javaType = $column.javaType.toLowerCase()) | |
| 185 | + #set ($comment = $column.columnComment) | |
| 186 | + #if ($dictType && "" != $dictType) | |
| 187 | + if (props.searchParams?.${javaField} !== undefined && props.searchParams.${javaField} !== -1) { | |
| 188 | + conditions.push('${comment}:' + getDictLabel(DICT_TYPE.$dictType.toUpperCase(), props.searchParams.${javaField})) | |
| 189 | + } | |
| 190 | + #else | |
| 191 | + #if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte" || ${javaType} == "boolean") | |
| 192 | + if (props.searchParams?.${javaField} !== undefined) { | |
| 193 | + conditions.push('${comment}:' + props.searchParams.${javaField}) | |
| 194 | + } | |
| 195 | + #else | |
| 196 | + if (props.searchParams?.${javaField}) { | |
| 197 | + conditions.push('${comment}:' + props.searchParams.${javaField}) | |
| 198 | + } | |
| 199 | + #end | |
| 200 | + #end | |
| 201 | + #end | |
| 202 | +#end | |
| 203 | + return conditions.length > 0 ? conditions.join(' | ') : '搜索${table.classComment}' | |
| 204 | +}) | |
| 205 | + | |
| 206 | +const formData = reactive<SearchFormData>({ | |
| 207 | +#foreach($column in $columns) | |
| 208 | + #if ($column.listOperation) | |
| 209 | + #if ($column.dictType && "" != $column.dictType) | |
| 210 | + #set ($javaType = $column.javaType.toLowerCase()) | |
| 211 | + #if(${javaType} == "string") | |
| 212 | + ${column.javaField}: -1 as number | string, | |
| 213 | + #elseif(${javaType} == "boolean") | |
| 214 | + ${column.javaField}: -1 as number | boolean, | |
| 215 | + #else | |
| 216 | + ${column.javaField}: -1 as number, | |
| 217 | + #end | |
| 218 | + #else | |
| 219 | + ${column.javaField}: undefined, | |
| 220 | + #end | |
| 221 | + #end | |
| 222 | +#end | |
| 223 | +}) | |
| 224 | + | |
| 225 | +watch(visible, (val) => { | |
| 226 | + if (val && props.searchParams) { | |
| 227 | +#foreach($column in $columns) | |
| 228 | + #if ($column.listOperation) | |
| 229 | + #if ($column.dictType && "" != $column.dictType) | |
| 230 | + formData.${column.javaField} = props.searchParams.${column.javaField} ?? -1 | |
| 231 | + #else | |
| 232 | + formData.${column.javaField} = props.searchParams.${column.javaField} | |
| 233 | + #end | |
| 234 | + #end | |
| 235 | +#end | |
| 236 | + } | |
| 237 | +}) | |
| 238 | + | |
| 239 | +function handleSearch() { | |
| 240 | + visible.value = false | |
| 241 | + emit('search', { ...formData } as SearchFormData) | |
| 242 | +} | |
| 243 | + | |
| 244 | +function handleReset() { | |
| 245 | +#foreach($column in $columns) | |
| 246 | + #if ($column.listOperation) | |
| 247 | + #if ($column.dictType && "" != $column.dictType) | |
| 248 | + formData.${column.javaField} = -1 | |
| 249 | + #else | |
| 250 | + formData.${column.javaField} = undefined | |
| 251 | + #end | |
| 252 | + #end | |
| 253 | +#end | |
| 254 | + visible.value = false | |
| 255 | + emit('reset') | |
| 256 | +} | |
| 257 | +</script> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail/index.vue.vm
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="page-container"> | |
| 3 | + <wd-navbar | |
| 4 | + title="${table.classComment}详情" | |
| 5 | + left-arrow placeholder safe-area-inset-top fixed | |
| 6 | + @click-left="handleBack" | |
| 7 | + /> | |
| 8 | + | |
| 9 | + <view> | |
| 10 | + <wd-cell-group border> | |
| 11 | +#foreach($column in $columns) | |
| 12 | + #if ($column.primaryKey || $column.listOperationResult || $column.createOperation || $column.updateOperation) | |
| 13 | + #set ($javaField = $column.javaField) | |
| 14 | + #set ($comment = $column.columnComment) | |
| 15 | + #if ($column.dictType && "" != $column.dictType) | |
| 16 | + <wd-cell title="${comment}"> | |
| 17 | + <dict-tag :type="DICT_TYPE.${column.dictType.toUpperCase()}" :value="formData?.${javaField}" /> | |
| 18 | + </wd-cell> | |
| 19 | + #elseif ($column.javaType == "LocalDateTime") | |
| 20 | + <wd-cell title="${comment}" :value="formatDateTime(formData?.${javaField}) || '-'" /> | |
| 21 | + #else | |
| 22 | + <wd-cell title="${comment}" :value="String(formData?.${javaField} ?? '-')" /> | |
| 23 | + #end | |
| 24 | + #end | |
| 25 | +#end | |
| 26 | + </wd-cell-group> | |
| 27 | + </view> | |
| 28 | + | |
| 29 | + <view class="fixed bottom-0 left-0 right-0 bg-white p-24rpx"> | |
| 30 | + <view class="w-full flex gap-24rpx"> | |
| 31 | + <wd-button | |
| 32 | + v-if="hasAccessByCodes(['${permissionPrefix}:update'])" | |
| 33 | + class="flex-1" type="warning" @click="handleEdit" | |
| 34 | + > | |
| 35 | + 编辑 | |
| 36 | + </wd-button> | |
| 37 | + <wd-button | |
| 38 | + v-if="hasAccessByCodes(['${permissionPrefix}:delete'])" | |
| 39 | + class="flex-1" type="error" :loading="deleting" @click="handleDelete" | |
| 40 | + > | |
| 41 | + 删除 | |
| 42 | + </wd-button> | |
| 43 | + </view> | |
| 44 | + </view> | |
| 45 | + </view> | |
| 46 | +</template> | |
| 47 | + | |
| 48 | +<script lang="ts" setup> | |
| 49 | +import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' | |
| 50 | +import { onMounted, ref } from 'vue' | |
| 51 | +import { useToast } from 'wot-design-uni' | |
| 52 | +import { delete${simpleClassName}, get${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' | |
| 53 | +import { useAccess } from '@/hooks/useAccess' | |
| 54 | +import { navigateBackPlus } from '@/utils' | |
| 55 | +#set ($hasDict = 0) | |
| 56 | +#foreach($column in $columns) | |
| 57 | + #if ($hasDict == 0 && $column.dictType && "" != $column.dictType) | |
| 58 | + #set ($hasDict = 1) | |
| 59 | + #end | |
| 60 | +#end | |
| 61 | +#if ($hasDict == 1) | |
| 62 | +import { DICT_TYPE } from '@/utils/constants' | |
| 63 | +#end | |
| 64 | +#set ($hasDateTime = 0) | |
| 65 | +#foreach($column in $columns) | |
| 66 | + #if ($hasDateTime == 0 && $column.javaType == "LocalDateTime") | |
| 67 | + #set ($hasDateTime = 1) | |
| 68 | + #end | |
| 69 | +#end | |
| 70 | +#if ($hasDateTime == 1) | |
| 71 | +import { formatDateTime } from '@/utils/date' | |
| 72 | +#end | |
| 73 | + | |
| 74 | +const props = defineProps<{ | |
| 75 | + id?: number | any | |
| 76 | +}>() | |
| 77 | + | |
| 78 | +definePage({ | |
| 79 | + style: { | |
| 80 | + navigationBarTitleText: '', | |
| 81 | + navigationStyle: 'custom', | |
| 82 | + }, | |
| 83 | +}) | |
| 84 | + | |
| 85 | +const { hasAccessByCodes } = useAccess() | |
| 86 | +const toast = useToast() | |
| 87 | +const formData = ref<${simpleClassName}>() | |
| 88 | +const deleting = ref(false) | |
| 89 | + | |
| 90 | +function handleBack() { | |
| 91 | + navigateBackPlus('/pages-${table.moduleName}/${table.businessName}/index') | |
| 92 | +} | |
| 93 | + | |
| 94 | +async function getDetail() { | |
| 95 | + if (!props.id) { | |
| 96 | + return | |
| 97 | + } | |
| 98 | + try { | |
| 99 | + toast.loading('加载中...') | |
| 100 | + formData.value = await get${simpleClassName}(props.id) | |
| 101 | + } finally { | |
| 102 | + toast.close() | |
| 103 | + } | |
| 104 | +} | |
| 105 | + | |
| 106 | +function handleEdit() { | |
| 107 | + uni.navigateTo({ | |
| 108 | + url: '/pages-${table.moduleName}/${table.businessName}/form/index?id=' + props.id, | |
| 109 | + }) | |
| 110 | +} | |
| 111 | + | |
| 112 | +function handleDelete() { | |
| 113 | + if (!props.id) { | |
| 114 | + return | |
| 115 | + } | |
| 116 | + uni.showModal({ | |
| 117 | + title: '提示', | |
| 118 | + content: '确定要删除该${table.classComment}吗?', | |
| 119 | + success: async (res) => { | |
| 120 | + if (!res.confirm) { | |
| 121 | + return | |
| 122 | + } | |
| 123 | + deleting.value = true | |
| 124 | + try { | |
| 125 | + await delete${simpleClassName}(props.id) | |
| 126 | + toast.success('删除成功') | |
| 127 | + setTimeout(() => { | |
| 128 | + handleBack() | |
| 129 | + }, 500) | |
| 130 | + } finally { | |
| 131 | + deleting.value = false | |
| 132 | + } | |
| 133 | + }, | |
| 134 | + }) | |
| 135 | +} | |
| 136 | + | |
| 137 | +onMounted(() => { | |
| 138 | + getDetail() | |
| 139 | +}) | |
| 140 | +</script> | |
| 141 | + | |
| 142 | +<style lang="scss" scoped> | |
| 143 | +</style> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form/index.vue.vm
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="page-container"> | |
| 3 | + <wd-navbar | |
| 4 | + :title="getTitle" | |
| 5 | + left-arrow placeholder safe-area-inset-top fixed | |
| 6 | + @click-left="handleBack" | |
| 7 | + /> | |
| 8 | + | |
| 9 | + <view> | |
| 10 | + <wd-form ref="formRef" :model="formData" :rules="formRules"> | |
| 11 | + <wd-cell-group border> | |
| 12 | +#foreach($column in $columns) | |
| 13 | + #if (($column.createOperation || $column.updateOperation) && !$column.primaryKey) | |
| 14 | + #set ($dictType = $column.dictType) | |
| 15 | + #set ($javaField = $column.javaField) | |
| 16 | + #set ($javaType = $column.javaType) | |
| 17 | + #set ($comment = $column.columnComment) | |
| 18 | + #set ($dictMethod = "getDictOptions") | |
| 19 | + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | |
| 20 | + #set ($dictMethod = "getIntDictOptions") | |
| 21 | + #elseif ($javaType == "String") | |
| 22 | + #set ($dictMethod = "getStrDictOptions") | |
| 23 | + #elseif ($javaType == "Boolean") | |
| 24 | + #set ($dictMethod = "getBoolDictOptions") | |
| 25 | + #end | |
| 26 | + | |
| 27 | + #if (${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer" || ${javaType.toLowerCase()} == "short" || ${javaType.toLowerCase()} == "double" || ${javaType.toLowerCase()} == "bigdecimal" || ${javaType.toLowerCase()} == "byte") | |
| 28 | + <wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center> | |
| 29 | + <wd-input-number | |
| 30 | + v-model="formData.${javaField}" | |
| 31 | + :min="0" | |
| 32 | + /> | |
| 33 | + </wd-cell> | |
| 34 | + #elseif (${javaType.toLowerCase()} == "boolean") | |
| 35 | + <wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center> | |
| 36 | + <wd-switch v-model="formData.${javaField}" /> | |
| 37 | + </wd-cell> | |
| 38 | + #elseif ($column.htmlType == "textarea") | |
| 39 | + <wd-textarea | |
| 40 | + v-model="formData.${javaField}" | |
| 41 | + label="${comment}" | |
| 42 | + label-width="180rpx" | |
| 43 | + placeholder="请输入${comment}" | |
| 44 | + :maxlength="200" | |
| 45 | + show-word-limit | |
| 46 | + clearable | |
| 47 | + /> | |
| 48 | + #elseif (($column.htmlType == "select" || $column.htmlType == "radio") && $dictType && "" != $dictType) | |
| 49 | + <wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center> | |
| 50 | + <wd-radio-group v-model="formData.${javaField}" shape="button" size="medium"> | |
| 51 | + <wd-radio | |
| 52 | + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | |
| 53 | + :key="dict.value" | |
| 54 | + :value="dict.value" | |
| 55 | + > | |
| 56 | + {{ dict.label }} | |
| 57 | + </wd-radio> | |
| 58 | + </wd-radio-group> | |
| 59 | + </wd-cell> | |
| 60 | + #else | |
| 61 | + <wd-input | |
| 62 | + v-model="formData.${javaField}" | |
| 63 | + label="${comment}" | |
| 64 | + label-width="180rpx" | |
| 65 | + prop="${javaField}" | |
| 66 | + clearable | |
| 67 | + placeholder="请输入${comment}" | |
| 68 | + /> | |
| 69 | + #end | |
| 70 | + #end | |
| 71 | +#end | |
| 72 | + </wd-cell-group> | |
| 73 | + </wd-form> | |
| 74 | + </view> | |
| 75 | + | |
| 76 | + <view class="fixed bottom-0 left-0 right-0 bg-white p-24rpx"> | |
| 77 | + <wd-button | |
| 78 | + type="primary" | |
| 79 | + block | |
| 80 | + :loading="formLoading" | |
| 81 | + @click="handleSubmit" | |
| 82 | + > | |
| 83 | + 保存 | |
| 84 | + </wd-button> | |
| 85 | + </view> | |
| 86 | + </view> | |
| 87 | +</template> | |
| 88 | + | |
| 89 | +<script lang="ts" setup> | |
| 90 | +import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' | |
| 91 | +import { computed, onMounted, ref } from 'vue' | |
| 92 | +import { useToast } from 'wot-design-uni' | |
| 93 | +import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' | |
| 94 | +import { navigateBackPlus } from '@/utils' | |
| 95 | + | |
| 96 | +#set ($primaryJavaType = $primaryColumn.javaType.toLowerCase()) | |
| 97 | +#if(${primaryJavaType} == "long" || ${primaryJavaType} == "integer" || ${primaryJavaType} == "short" || ${primaryJavaType} == "double" || ${primaryJavaType} == "bigdecimal" || ${primaryJavaType} == "byte") | |
| 98 | +#set ($primaryTsType = "number") | |
| 99 | +#else | |
| 100 | +#set ($primaryTsType = "string") | |
| 101 | +#end | |
| 102 | + | |
| 103 | +#set ($hasDict = 0) | |
| 104 | +#set ($hasGetDictOptions = 0) | |
| 105 | +#set ($hasGetIntDictOptions = 0) | |
| 106 | +#set ($hasGetStrDictOptions = 0) | |
| 107 | +#set ($hasGetBoolDictOptions = 0) | |
| 108 | +#foreach ($column in $columns) | |
| 109 | + #if (($column.createOperation || $column.updateOperation) && !$column.primaryKey | |
| 110 | + && ($column.htmlType == "select" || $column.htmlType == "radio") | |
| 111 | + && $column.dictType && "" != $column.dictType) | |
| 112 | + #set ($hasDict = 1) | |
| 113 | + #if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short") | |
| 114 | + #set ($hasGetIntDictOptions = 1) | |
| 115 | + #elseif ($column.javaType == "String") | |
| 116 | + #set ($hasGetStrDictOptions = 1) | |
| 117 | + #elseif ($column.javaType == "Boolean") | |
| 118 | + #set ($hasGetBoolDictOptions = 1) | |
| 119 | + #else | |
| 120 | + #set ($hasGetDictOptions = 1) | |
| 121 | + #end | |
| 122 | + #end | |
| 123 | +#end | |
| 124 | +#if ($hasDict == 1) | |
| 125 | +import { DICT_TYPE } from '@/utils/constants' | |
| 126 | +import { | |
| 127 | + #if ($hasGetDictOptions == 1) | |
| 128 | + getDictOptions, | |
| 129 | + #end | |
| 130 | + #if ($hasGetIntDictOptions == 1) | |
| 131 | + getIntDictOptions, | |
| 132 | + #end | |
| 133 | + #if ($hasGetStrDictOptions == 1) | |
| 134 | + getStrDictOptions, | |
| 135 | + #end | |
| 136 | + #if ($hasGetBoolDictOptions == 1) | |
| 137 | + getBoolDictOptions, | |
| 138 | + #end | |
| 139 | +} from '@/hooks/useDict' | |
| 140 | +#end | |
| 141 | + | |
| 142 | +const props = defineProps<{ | |
| 143 | + id?: ${primaryTsType} | any | |
| 144 | +}>() | |
| 145 | + | |
| 146 | +definePage({ | |
| 147 | + style: { | |
| 148 | + navigationBarTitleText: '', | |
| 149 | + navigationStyle: 'custom', | |
| 150 | + }, | |
| 151 | +}) | |
| 152 | + | |
| 153 | +const toast = useToast() | |
| 154 | +const getTitle = computed(() => props.id ? '编辑${table.classComment}' : '新增${table.classComment}') | |
| 155 | +const formLoading = ref(false) | |
| 156 | + | |
| 157 | +// TODO @AI:date + 时间范围,需要特殊处理;参考 /Users/yunai/Java/yudao-ui-admin-uniapp-next-v4/src/pages/message/components/search-form.vue 里的开始结束时间的处理;注意,index.vue.vm 也要调整; | |
| 158 | +const formData = ref<${simpleClassName}>({ | |
| 159 | +#foreach($column in $columns) | |
| 160 | + #if (($column.createOperation || $column.updateOperation) || $column.primaryKey) | |
| 161 | + #set ($javaType = $column.javaType.toLowerCase()) | |
| 162 | + #if ($column.primaryKey) | |
| 163 | + ${column.javaField}: undefined, | |
| 164 | + #elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") | |
| 165 | + ${column.javaField}: 0, | |
| 166 | + #elseif(${javaType} == "boolean") | |
| 167 | + ${column.javaField}: false, | |
| 168 | + #else | |
| 169 | + ${column.javaField}: '', | |
| 170 | + #end | |
| 171 | + #end | |
| 172 | +#end | |
| 173 | +}) | |
| 174 | + | |
| 175 | +const formRules = { | |
| 176 | +#foreach($column in $columns) | |
| 177 | + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey) | |
| 178 | + ${column.javaField}: [{ required: true, message: '${column.columnComment}不能为空' }], | |
| 179 | + #end | |
| 180 | +#end | |
| 181 | +} | |
| 182 | + | |
| 183 | +const formRef = ref() | |
| 184 | + | |
| 185 | +function handleBack() { | |
| 186 | + navigateBackPlus('/pages-${table.moduleName}/${table.businessName}/index') | |
| 187 | +} | |
| 188 | + | |
| 189 | +async function getDetail() { | |
| 190 | + if (!props.id) { | |
| 191 | + return | |
| 192 | + } | |
| 193 | + formData.value = await get${simpleClassName}(props.id) | |
| 194 | +} | |
| 195 | + | |
| 196 | +async function handleSubmit() { | |
| 197 | + const { valid } = await formRef.value.validate() | |
| 198 | + if (!valid) { | |
| 199 | + return | |
| 200 | + } | |
| 201 | + | |
| 202 | + formLoading.value = true | |
| 203 | + try { | |
| 204 | + if (props.id) { | |
| 205 | + await update${simpleClassName}(formData.value) | |
| 206 | + toast.success('修改成功') | |
| 207 | + } else { | |
| 208 | + await create${simpleClassName}(formData.value) | |
| 209 | + toast.success('新增成功') | |
| 210 | + } | |
| 211 | + setTimeout(() => { | |
| 212 | + handleBack() | |
| 213 | + }, 500) | |
| 214 | + } finally { | |
| 215 | + formLoading.value = false | |
| 216 | + } | |
| 217 | +} | |
| 218 | + | |
| 219 | +onMounted(() => { | |
| 220 | + getDetail() | |
| 221 | +}) | |
| 222 | +</script> | |
| 223 | + | |
| 224 | +<style lang="scss" scoped> | |
| 225 | +</style> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/index.vue.vm
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="page-container"> | |
| 3 | + <!-- 顶部导航栏 --> | |
| 4 | + <wd-navbar | |
| 5 | + title="${table.classComment}管理" | |
| 6 | + left-arrow placeholder safe-area-inset-top fixed | |
| 7 | + @click-left="handleBack" | |
| 8 | + /> | |
| 9 | + | |
| 10 | + <!-- 搜索组件 --> | |
| 11 | + <SearchForm | |
| 12 | + :search-params="queryParams" | |
| 13 | + @search="handleQuery" | |
| 14 | + @reset="handleReset" | |
| 15 | + /> | |
| 16 | + | |
| 17 | + <!-- ${table.classComment}列表 --> | |
| 18 | + <view class="p-24rpx"> | |
| 19 | + <view | |
| 20 | + v-for="item in list" | |
| 21 | + :key="item.${primaryColumn.javaField}" | |
| 22 | + class="mb-24rpx overflow-hidden rounded-12rpx bg-white shadow-sm" | |
| 23 | + @click="handleDetail(item)" | |
| 24 | + > | |
| 25 | + <!-- TODO @AI:下面的 view 部分代码,缩进可能不太对; --> | |
| 26 | + <view class="p-24rpx"> | |
| 27 | +#set ($titleField = "") | |
| 28 | +#set ($statusField = "") | |
| 29 | +#set ($statusDictType = "") | |
| 30 | +#foreach($column in $columns) | |
| 31 | + #if ($titleField == "" && !$column.primaryKey && $column.listOperationResult) | |
| 32 | + #set ($titleField = $column.javaField) | |
| 33 | + #set ($titleComment = $column.columnComment) | |
| 34 | + #end | |
| 35 | + #if ($statusField == "" && $column.listOperationResult && $column.dictType && "" != $column.dictType) | |
| 36 | + #set ($statusField = $column.javaField) | |
| 37 | + #set ($statusDictType = $column.dictType) | |
| 38 | + #end | |
| 39 | +#end | |
| 40 | + <view class="mb-16rpx flex items-center justify-between"> | |
| 41 | + <view class="text-32rpx text-[#333] font-semibold"> | |
| 42 | + {{ item.#if($titleField != "")${titleField}#else ${primaryColumn.javaField}#end }} | |
| 43 | + </view> | |
| 44 | +#if($statusField != "") | |
| 45 | + <dict-tag :type="DICT_TYPE.$statusDictType.toUpperCase()" :value="item.$statusField" /> | |
| 46 | +#end | |
| 47 | + </view> | |
| 48 | +#set ($infoCount = 0) | |
| 49 | +#foreach($column in $columns) | |
| 50 | + #if ($column.listOperationResult && !$column.primaryKey && $column.javaField != $titleField && $column.javaField != $statusField) | |
| 51 | + #if ($infoCount < 2) | |
| 52 | + <view class="mb-12rpx flex items-center text-28rpx text-[#666]"> | |
| 53 | + <text class="mr-8rpx text-[#999]">${column.columnComment}:</text> | |
| 54 | + <text class="line-clamp-1">{{ item.${column.javaField} }}</text> | |
| 55 | + </view> | |
| 56 | + #set ($infoCount = $infoCount + 1) | |
| 57 | + #end | |
| 58 | + #end | |
| 59 | +#end | |
| 60 | + </view> | |
| 61 | + </view> | |
| 62 | + | |
| 63 | + <!-- 加载更多 --> | |
| 64 | + <view v-if="loadMoreState !== 'loading' && list.length === 0" class="py-100rpx text-center"> | |
| 65 | + <wd-status-tip image="content" tip="暂无${table.classComment}数据" /> | |
| 66 | + </view> | |
| 67 | + <wd-loadmore | |
| 68 | + v-if="list.length > 0" | |
| 69 | + :state="loadMoreState" | |
| 70 | + @reload="loadMore" | |
| 71 | + /> | |
| 72 | + </view> | |
| 73 | + | |
| 74 | + <!-- 新增按钮 --> | |
| 75 | + <wd-fab | |
| 76 | + v-if="hasAccessByCodes(['${permissionPrefix}:create'])" | |
| 77 | + position="right-bottom" | |
| 78 | + type="primary" | |
| 79 | + :expandable="false" | |
| 80 | + @click="handleAdd" | |
| 81 | + /> | |
| 82 | + </view> | |
| 83 | +</template> | |
| 84 | + | |
| 85 | +<script lang="ts" setup> | |
| 86 | +import type { SearchFormData } from './components/search-form.vue' | |
| 87 | +import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' | |
| 88 | +import type { LoadMoreState } from '@/http/types' | |
| 89 | +import { onReachBottom } from '@dcloudio/uni-app' | |
| 90 | +import { onMounted, reactive, ref } from 'vue' | |
| 91 | +import { get${simpleClassName}Page } from '@/api/${table.moduleName}/${table.businessName}' | |
| 92 | +import { useAccess } from '@/hooks/useAccess' | |
| 93 | +import { navigateBackPlus } from '@/utils' | |
| 94 | +import SearchForm from './components/search-form.vue' | |
| 95 | +#set ($hasDict = 0) | |
| 96 | +#foreach($column in $columns) | |
| 97 | + #if ($hasDict == 0 && $column.listOperationResult && $column.dictType && "" != $column.dictType) | |
| 98 | + #set ($hasDict = 1) | |
| 99 | + #end | |
| 100 | +#end | |
| 101 | +#if ($hasDict == 1) | |
| 102 | +import { DICT_TYPE } from '@/utils/constants' | |
| 103 | +#end | |
| 104 | + | |
| 105 | +definePage({ | |
| 106 | + style: { | |
| 107 | + navigationBarTitleText: '', | |
| 108 | + navigationStyle: 'custom', | |
| 109 | + }, | |
| 110 | +}) | |
| 111 | + | |
| 112 | +const { hasAccessByCodes } = useAccess() | |
| 113 | +const total = ref(0) | |
| 114 | +const list = ref<${simpleClassName}[]>([]) | |
| 115 | +const loadMoreState = ref<LoadMoreState>('loading') // 加载更多状态 | |
| 116 | + | |
| 117 | +const queryParams = reactive({ | |
| 118 | + pageNo: 1, | |
| 119 | + pageSize: 10, | |
| 120 | +#foreach($column in $columns) | |
| 121 | + #if ($column.listOperation) | |
| 122 | + #set ($javaType = $column.javaType.toLowerCase()) | |
| 123 | + #if ($column.dictType && "" != $column.dictType) | |
| 124 | + #if(${javaType} == "string") | |
| 125 | + ${column.javaField}: -1 as number | string, // -1 表示全部 | |
| 126 | + #elseif(${javaType} == "boolean") | |
| 127 | + ${column.javaField}: -1 as number | boolean, // -1 表示全部 | |
| 128 | + #else | |
| 129 | + ${column.javaField}: -1 as number, // -1 表示全部 | |
| 130 | + #end | |
| 131 | + #elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") | |
| 132 | + ${column.javaField}: undefined as number | undefined, | |
| 133 | + #elseif(${javaType} == "boolean") | |
| 134 | + ${column.javaField}: undefined as boolean | undefined, | |
| 135 | + #else | |
| 136 | + ${column.javaField}: undefined as string | undefined, | |
| 137 | + #end | |
| 138 | + #end | |
| 139 | +#end | |
| 140 | +}) | |
| 141 | + | |
| 142 | +/** 返回上一页 */ | |
| 143 | +function handleBack() { | |
| 144 | + navigateBackPlus() | |
| 145 | +} | |
| 146 | + | |
| 147 | +/** 查询${table.classComment}列表 */ | |
| 148 | +async function getList() { | |
| 149 | + loadMoreState.value = 'loading' | |
| 150 | + try { | |
| 151 | + const data = await get${simpleClassName}Page({ | |
| 152 | + ...queryParams, | |
| 153 | +#foreach($column in $columns) | |
| 154 | + #if ($column.listOperation && $column.dictType && "" != $column.dictType) | |
| 155 | + ${column.javaField}: queryParams.${column.javaField} === -1 ? undefined : queryParams.${column.javaField}, | |
| 156 | + #end | |
| 157 | +#end | |
| 158 | + }) | |
| 159 | + list.value = [...list.value, ...data.list] | |
| 160 | + total.value = data.total | |
| 161 | + loadMoreState.value = list.value.length >= total.value ? 'finished' : 'loading' | |
| 162 | + } catch { | |
| 163 | + queryParams.pageNo = queryParams.pageNo > 1 ? queryParams.pageNo - 1 : 1 | |
| 164 | + loadMoreState.value = 'error' | |
| 165 | + } | |
| 166 | +} | |
| 167 | + | |
| 168 | +/** 搜索按钮操作 */ | |
| 169 | +function handleQuery(data?: SearchFormData) { | |
| 170 | +#foreach($column in $columns) | |
| 171 | + #if ($column.listOperation) | |
| 172 | + queryParams.${column.javaField} = data?.${column.javaField}#if ($column.dictType && "" != $column.dictType) ?? -1#end | |
| 173 | + #end | |
| 174 | +#end | |
| 175 | + queryParams.pageNo = 1 | |
| 176 | + list.value = [] | |
| 177 | + getList() | |
| 178 | +} | |
| 179 | + | |
| 180 | +/** 重置按钮操作 */ | |
| 181 | +function handleReset() { | |
| 182 | + handleQuery() | |
| 183 | +} | |
| 184 | + | |
| 185 | +/** 加载更多 */ | |
| 186 | +function loadMore() { | |
| 187 | + if (loadMoreState.value === 'finished') { | |
| 188 | + return | |
| 189 | + } | |
| 190 | + queryParams.pageNo++ | |
| 191 | + getList() | |
| 192 | +} | |
| 193 | + | |
| 194 | +/** 新增${table.classComment} */ | |
| 195 | +function handleAdd() { | |
| 196 | + uni.navigateTo({ | |
| 197 | + url: '/pages-${table.moduleName}/${table.businessName}/form/index', | |
| 198 | + }) | |
| 199 | +} | |
| 200 | + | |
| 201 | +/** 查看详情 */ | |
| 202 | +function handleDetail(item: ${simpleClassName}) { | |
| 203 | + uni.navigateTo({ | |
| 204 | + url: '/pages-${table.moduleName}/${table.businessName}/detail/index?id=' + item.${primaryColumn.javaField}, | |
| 205 | + }) | |
| 206 | +} | |
| 207 | + | |
| 208 | +/** 触底加载更多 */ | |
| 209 | +onReachBottom(() => { | |
| 210 | + loadMore() | |
| 211 | +}) | |
| 212 | + | |
| 213 | +/** 初始化 */ | |
| 214 | +onMounted(() => { | |
| 215 | + getList() | |
| 216 | +}) | |
| 217 | +</script> | |
| 218 | + | |
| 219 | +<style lang="scss" scoped> | |
| 220 | +</style> | ... | ... |