commit
						5f957195df
					
				|  | @ -10,7 +10,7 @@ export namespace Demo03StudentApi { | ||||||
|     name?: string; // 名字
 |     name?: string; // 名字
 | ||||||
|     score?: number; // 分数
 |     score?: number; // 分数
 | ||||||
|   } |   } | ||||||
|   // TODO @puhui999:要不要每个 interface 之间,有个空行
 | 
 | ||||||
|   /** 学生班级信息 */ |   /** 学生班级信息 */ | ||||||
|   export interface Demo03Grade { |   export interface Demo03Grade { | ||||||
|     id: number; // 编号
 |     id: number; // 编号
 | ||||||
|  | @ -18,6 +18,7 @@ export namespace Demo03StudentApi { | ||||||
|     name?: string; // 名字
 |     name?: string; // 名字
 | ||||||
|     teacher?: string; // 班主任
 |     teacher?: string; // 班主任
 | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   /** 学生信息 */ |   /** 学生信息 */ | ||||||
|   export interface Demo03Student { |   export interface Demo03Student { | ||||||
|     id: number; // 编号
 |     id: number; // 编号
 | ||||||
|  | @ -61,7 +62,7 @@ export function exportDemo03Student(params: any) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ==================== 子表(学生课程) ====================
 | // ==================== 子表(学生课程) ====================
 | ||||||
| // TODO @puhui999:==================== 后面,加个空行,会更清晰一点
 | 
 | ||||||
| /** 获得学生课程列表 */ | /** 获得学生课程列表 */ | ||||||
| export function getDemo03CourseListByStudentId(studentId: number) { | export function getDemo03CourseListByStudentId(studentId: number) { | ||||||
|   return requestClient.get<Demo03StudentApi.Demo03Course[]>( |   return requestClient.get<Demo03StudentApi.Demo03Course[]>( | ||||||
|  | @ -70,6 +71,7 @@ export function getDemo03CourseListByStudentId(studentId: number) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ==================== 子表(学生班级) ====================
 | // ==================== 子表(学生班级) ====================
 | ||||||
|  | 
 | ||||||
| /** 获得学生班级 */ | /** 获得学生班级 */ | ||||||
| export function getDemo03GradeByStudentId(studentId: number) { | export function getDemo03GradeByStudentId(studentId: number) { | ||||||
|   return requestClient.get<Demo03StudentApi.Demo03Grade>( |   return requestClient.get<Demo03StudentApi.Demo03Grade>( | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||||
| import type { InfraCodegenApi } from '#/api/infra/codegen'; | import type { InfraCodegenApi } from '#/api/infra/codegen'; | ||||||
| import type { SystemMenuApi } from '#/api/system/menu'; | import type { SystemMenuApi } from '#/api/system/menu'; | ||||||
| import type { Recordable } from '@vben/types'; | import type { Recordable } from '@vben/types'; | ||||||
| import type { ComputedRef } from 'vue'; |  | ||||||
| 
 | 
 | ||||||
| import { IconifyIcon } from '@vben/icons'; | import { IconifyIcon } from '@vben/icons'; | ||||||
| 
 | 
 | ||||||
|  | @ -388,18 +387,17 @@ export function useGridFormSchema(): VbenFormSchema[] { | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const dataSourceConfigList = await getDataSourceConfigList(); | ||||||
| /** 列表的字段 */ | /** 列表的字段 */ | ||||||
| // TODO @puhui999:getDataSourceConfigName,要不改成 data.ts 加载 list,然后使用。
 |  | ||||||
| export function useGridColumns<T = InfraCodegenApi.CodegenTable>( | export function useGridColumns<T = InfraCodegenApi.CodegenTable>( | ||||||
|   onActionClick: OnActionClickFn<T>, |   onActionClick: OnActionClickFn<T>, | ||||||
|   getDataSourceConfigName: ComputedRef<(cellValue: number) => string>, |  | ||||||
| ): VxeTableGridOptions['columns'] { | ): VxeTableGridOptions['columns'] { | ||||||
|   return [ |   return [ | ||||||
|     { |     { | ||||||
|       field: 'dataSourceConfigId', |       field: 'dataSourceConfigId', | ||||||
|       title: '数据源', |       title: '数据源', | ||||||
|       minWidth: 120, |       minWidth: 120, | ||||||
|       formatter: ({ cellValue }) => getDataSourceConfigName.value(cellValue), |       formatter: ({ cellValue }) => dataSourceConfigList.find((item) => item.id === cellValue)?.name || '', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       field: 'tableName', |       field: 'tableName', | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ import { getCodegenTable, updateCodegenTable } from '#/api/infra/codegen'; | ||||||
| import { $t } from '#/locales'; | import { $t } from '#/locales'; | ||||||
| import { ref, unref } from 'vue'; | import { ref, unref } from 'vue'; | ||||||
| 
 | 
 | ||||||
|  | import { useTabs } from '@vben/hooks'; | ||||||
| import { useRoute, useRouter } from 'vue-router'; | import { useRoute, useRouter } from 'vue-router'; | ||||||
| 
 | 
 | ||||||
| const route = useRoute(); | const route = useRoute(); | ||||||
|  | @ -72,7 +73,6 @@ const submitForm = async () => { | ||||||
|       content: $t('ui.actionMessage.operationSuccess'), |       content: $t('ui.actionMessage.operationSuccess'), | ||||||
|       key: 'action_process_msg', |       key: 'action_process_msg', | ||||||
|     }); |     }); | ||||||
|     // TODO @puhui999:保存的时候,修改的 tab 没关闭哈 |  | ||||||
|     close(); |     close(); | ||||||
|   } catch (error) { |   } catch (error) { | ||||||
|     console.error('保存失败', error); |     console.error('保存失败', error); | ||||||
|  | @ -80,9 +80,10 @@ const submitForm = async () => { | ||||||
|     hideLoading(); |     hideLoading(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | const tabs = useTabs(); | ||||||
| /** 返回列表 */ | /** 返回列表 */ | ||||||
| const close = () => { | const close = () => { | ||||||
|  |   tabs.closeCurrentTab(); | ||||||
|   router.push('/infra/codegen'); |   router.push('/infra/codegen'); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -137,9 +138,7 @@ getDetail(); | ||||||
|       <div class="mt-4 flex justify-end space-x-2"> |       <div class="mt-4 flex justify-end space-x-2"> | ||||||
|         <Button v-show="currentStep > 0" @click="prevStep">上一步</Button> |         <Button v-show="currentStep > 0" @click="prevStep">上一步</Button> | ||||||
|         <Button v-show="currentStep < steps.length - 1" @click="nextStep">下一步</Button> |         <Button v-show="currentStep < steps.length - 1" @click="nextStep">下一步</Button> | ||||||
|         <Button type="primary" :loading="loading" @click="submitForm"> |         <Button type="primary" :loading="loading" @click="submitForm"> 保存 </Button> | ||||||
|           保存 |  | ||||||
|         </Button> |  | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   </Page> |   </Page> | ||||||
|  |  | ||||||
|  | @ -1,9 +1,4 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| // TODO @puhui999:bug 同一个预览,点击多次,第二次不展示; |  | ||||||
| // TODO @puhui999:体验优化:左边的树,默认展开所有节点;这样体验好点哈 |  | ||||||
| // TODO @puhui999:展示代码时,前两行是空的,可能要看下 |  | ||||||
| // TODO @puhui999:要不预览代码,默认全屏? |  | ||||||
| 
 |  | ||||||
| // TODO @芋艿:待定,vben2.0 有 CodeEditor,不确定官方后续会不会迁移!!! | // TODO @芋艿:待定,vben2.0 有 CodeEditor,不确定官方后续会不会迁移!!! | ||||||
| import type { InfraCodegenApi } from '#/api/infra/codegen'; | import type { InfraCodegenApi } from '#/api/infra/codegen'; | ||||||
| 
 | 
 | ||||||
|  | @ -47,27 +42,30 @@ const previewFiles = ref<InfraCodegenApi.CodegenPreview[]>([]); | ||||||
| const activeKey = ref<string>(''); | const activeKey = ref<string>(''); | ||||||
| 
 | 
 | ||||||
| /** 代码地图 */ | /** 代码地图 */ | ||||||
| const codeMap = new Map<string, string>(); | const codeMap = ref<Map<string, string>>(new Map<string, string>()); | ||||||
| const setCodeMode = (key: string, lang: string, code: string) => { | const setCodeMap = (key: string, lang: string, code: string) => { | ||||||
|   // 处理可能的缩进问题,特别是对Java文件 |   // 处理可能的缩进问题,特别是对Java文件 | ||||||
|   const trimmedCode = code.trimStart(); |   const trimmedCode = code.trimStart(); | ||||||
| 
 |   // 如果已有缓存则不重新构建 | ||||||
|  |   if (codeMap.value.has(key)) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|   try { |   try { | ||||||
|     const highlightedCode = hljs.highlight(trimmedCode, { |     const highlightedCode = hljs.highlight(trimmedCode, { | ||||||
|       language: lang, |       language: lang, | ||||||
|     }).value; |     }).value; | ||||||
|     codeMap.set(key, highlightedCode); |     codeMap.value.set(key, highlightedCode); | ||||||
|   } catch { |   } catch { | ||||||
|     codeMap.set(key, trimmedCode); |     codeMap.value.set(key, trimmedCode); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| const removeCodeMapKey = (targetKey: any) => { | const removeCodeMapKey = (targetKey: any) => { | ||||||
|   // 只有一个代码视图时不允许删除 |   // 只有一个代码视图时不允许删除 | ||||||
|   if (codeMap.size === 1) { |   if (codeMap.value.size === 1) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   if (codeMap.has(targetKey)) { |   if (codeMap.value.has(targetKey)) { | ||||||
|     codeMap.delete(targetKey); |     codeMap.value.delete(targetKey); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -98,7 +96,7 @@ const handleNodeClick = (_: any[], e: any) => { | ||||||
|   if (!file) return; |   if (!file) return; | ||||||
| 
 | 
 | ||||||
|   const lang = file.filePath.split('.').pop() || ''; |   const lang = file.filePath.split('.').pop() || ''; | ||||||
|   setCodeMode(activeKey.value, lang, file.code); |   setCodeMap(activeKey.value, lang, file.code); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** 处理文件树 */ | /** 处理文件树 */ | ||||||
|  | @ -179,11 +177,11 @@ const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => { | ||||||
| /** 模态框实例 */ | /** 模态框实例 */ | ||||||
| const [Modal, modalApi] = useVbenModal({ | const [Modal, modalApi] = useVbenModal({ | ||||||
|   footer: false, |   footer: false, | ||||||
|   class: 'w-3/5', |   fullscreen: true, | ||||||
|   async onOpenChange(isOpen: boolean) { |   async onOpenChange(isOpen: boolean) { | ||||||
|     if (!isOpen) { |     if (!isOpen) { | ||||||
|       // 关闭时清除代码视图缓存 |       // 关闭时清除代码视图缓存 | ||||||
|       codeMap.clear(); |       codeMap.value.clear(); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -202,7 +200,7 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|         activeKey.value = data[0]?.filePath || ''; |         activeKey.value = data[0]?.filePath || ''; | ||||||
|         const lang = activeKey.value.split('.').pop() || ''; |         const lang = activeKey.value.split('.').pop() || ''; | ||||||
|         const code = data[0]?.code || ''; |         const code = data[0]?.code || ''; | ||||||
|         setCodeMode(activeKey.value, lang, code); |         setCodeMap(activeKey.value, lang, code); | ||||||
|       } |       } | ||||||
|     } finally { |     } finally { | ||||||
|       loading.value = false; |       loading.value = false; | ||||||
|  | @ -215,18 +213,22 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|   <Modal title="代码预览"> |   <Modal title="代码预览"> | ||||||
|     <div class="flex h-full" v-loading="loading"> |     <div class="flex h-full" v-loading="loading"> | ||||||
|       <!-- 文件树 --> |       <!-- 文件树 --> | ||||||
|       <div class="w-1/3 border-r border-gray-200 pr-4 dark:border-gray-700"> |       <div class="h-full w-1/3 overflow-auto border-r border-gray-200 pr-4 dark:border-gray-700"> | ||||||
|         <DirectoryTree v-model:active-key="activeKey" @select="handleNodeClick" :tree-data="fileTree" /> |         <DirectoryTree | ||||||
|  |           v-if="fileTree.length > 0" | ||||||
|  |           default-expand-all | ||||||
|  |           v-model:active-key="activeKey" | ||||||
|  |           @select="handleNodeClick" | ||||||
|  |           :tree-data="fileTree" | ||||||
|  |         /> | ||||||
|       </div> |       </div> | ||||||
|       <!-- 代码预览 --> |       <!-- 代码预览 --> | ||||||
|       <div class="w-2/3 pl-4"> |       <div class="h-full w-2/3 overflow-auto pl-4"> | ||||||
|         <Tabs v-model:active-key="activeKey" hide-add type="editable-card" @edit="removeCodeMapKey"> |         <Tabs v-model:active-key="activeKey" hide-add type="editable-card" @edit="removeCodeMapKey"> | ||||||
|           <Tabs.TabPane v-for="key in codeMap.keys()" :key="key" :tab="key.split('/').pop()"> |           <Tabs.TabPane v-for="key in codeMap.keys()" :key="key" :tab="key.split('/').pop()"> | ||||||
|             <div class="h-[calc(100%-40px)] overflow-auto"> |             <div class="h-full rounded-md bg-gray-50 !p-0 text-gray-800 dark:bg-gray-800 dark:text-gray-200"> | ||||||
|               <pre class="overflow-auto rounded-md bg-gray-50 p-4 text-gray-800 dark:bg-gray-800 dark:text-gray-200"> |  | ||||||
|               <!-- eslint-disable-next-line vue/no-v-html --> |               <!-- eslint-disable-next-line vue/no-v-html --> | ||||||
|               <code v-html="codeMap.get(activeKey)" class="code-highlight"></code> |               <code v-html="codeMap.get(activeKey)" class="code-highlight"></code> | ||||||
|               </pre> |  | ||||||
|             </div> |             </div> | ||||||
|           </Tabs.TabPane> |           </Tabs.TabPane> | ||||||
|           <template #rightExtra> |           <template #rightExtra> | ||||||
|  | @ -248,13 +250,6 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|   background: transparent; |   background: transparent; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* 代码块内容无缩进 */ |  | ||||||
| :deep(pre) { |  | ||||||
|   padding: 1rem; |  | ||||||
|   margin: 0; |  | ||||||
|   white-space: pre; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* 关键字 */ | /* 关键字 */ | ||||||
| :deep(.hljs-keyword) { | :deep(.hljs-keyword) { | ||||||
|   @apply text-purple-600 dark:text-purple-400; |   @apply text-purple-600 dark:text-purple-400; | ||||||
|  |  | ||||||
|  | @ -52,22 +52,16 @@ export function useFormSchema(): VbenFormSchema[] { | ||||||
|         valueFormat: 'x', |         valueFormat: 'x', | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|     // TODO 【富文本】@puhui999:@芋艿:后续要封装下;单独 pr
 |  | ||||||
|     { |     { | ||||||
|       fieldName: 'description', |       fieldName: 'description', | ||||||
|       label: '简介', |       label: '简介', | ||||||
|       rules: 'required', |       rules: 'required', | ||||||
|       component: 'Editor', |       component: 'RichTextarea', | ||||||
|     }, |     }, | ||||||
|     // TODO 【文件上传】@puhui999:@芋艿:后续要封装下;单独 pr
 |  | ||||||
|     { |     { | ||||||
|       fieldName: 'avatar', |       fieldName: 'avatar', | ||||||
|       label: '头像', |       label: '头像', | ||||||
|       component: 'FileUpload', |       component: 'ImageUpload', | ||||||
|       componentProps: { |  | ||||||
|         fileType: 'image', |  | ||||||
|         maxCount: 1, |  | ||||||
|       }, |  | ||||||
|     }, |     }, | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|  | @ -91,6 +85,7 @@ export function useGridFormSchema(): VbenFormSchema[] { | ||||||
|       componentProps: { |       componentProps: { | ||||||
|         allowClear: true, |         allowClear: true, | ||||||
|         options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), |         options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | ||||||
|  |         placeholder: '请选择性别', | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -25,15 +25,9 @@ function onRefresh() { | ||||||
|   gridApi.query(); |   gridApi.query(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** 导出表格 */ |  | ||||||
| async function onExport() { |  | ||||||
|   const data = await exportDemo01Contact(await gridApi.formApi.getValues()); |  | ||||||
|   downloadByData(data, '示例联系人.xls'); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** 创建示例联系人 */ | /** 创建示例联系人 */ | ||||||
| function onCreate() { | function onCreate() { | ||||||
|   formModalApi.setData(null).open(); |   formModalApi.setData({}).open(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** 编辑示例联系人 */ | /** 编辑示例联系人 */ | ||||||
|  | @ -60,18 +54,23 @@ async function onDelete(row: Demo01ContactApi.Demo01Contact) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** 导出表格 */ | ||||||
|  | async function onExport() { | ||||||
|  |   const data = await exportDemo01Contact(await gridApi.formApi.getValues()); | ||||||
|  |   downloadByData(data, '示例联系人.xls'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** 表格操作按钮的回调函数 */ | /** 表格操作按钮的回调函数 */ | ||||||
| function onActionClick({ code, row }: OnActionClickParams<Demo01ContactApi.Demo01Contact>) { | function onActionClick({ code, row }: OnActionClickParams<Demo01ContactApi.Demo01Contact>) { | ||||||
|   switch (code) { |   switch (code) { | ||||||
|     case 'delete': { |  | ||||||
|       onDelete(row); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|     // TODO @puhui999:edit 放在 delete 前面哈。好理解一点,修改 => 删除 |  | ||||||
|     case 'edit': { |     case 'edit': { | ||||||
|       onEdit(row); |       onEdit(row); | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|  |     case 'delete': { | ||||||
|  |       onDelete(row); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -47,6 +47,7 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|   }, |   }, | ||||||
|   async onOpenChange(isOpen: boolean) { |   async onOpenChange(isOpen: boolean) { | ||||||
|     if (!isOpen) { |     if (!isOpen) { | ||||||
|  |       formData.value = undefined; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -55,9 +56,7 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|     if (!data) { |     if (!data) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     if (data.id) { |     if (data.id) { | ||||||
|       // 编辑 TODO @puhui999:1)这里注释,“编辑”去掉;2)data.id 上面的空行去掉; |  | ||||||
|       modalApi.lock(); |       modalApi.lock(); | ||||||
|       try { |       try { | ||||||
|         data = await getDemo01Contact(data.id); |         data = await getDemo01Contact(data.id); | ||||||
|  |  | ||||||
|  | @ -1,14 +1,11 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| // TODO @puhui999:需要看看,vben 哪里改下哈。一个是 vben 右上角的站内信、一个是点击查看所有消息,应该跳转到这里。 | import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||||
| import type { |  | ||||||
|   OnActionClickParams, |  | ||||||
|   VxeTableGridOptions, |  | ||||||
| } from '#/adapter/vxe-table'; |  | ||||||
| import type { SystemNotifyMessageApi } from '#/api/system/notify/message'; | import type { SystemNotifyMessageApi } from '#/api/system/notify/message'; | ||||||
| 
 | 
 | ||||||
|  | import { DocAlert } from '#/components/doc-alert'; | ||||||
|  | import Detail from './modules/detail.vue'; | ||||||
| import { Page, useVbenModal } from '@vben/common-ui'; | import { Page, useVbenModal } from '@vben/common-ui'; | ||||||
| import { MdiCheckboxMarkedCircleOutline } from '@vben/icons'; | import { MdiCheckboxMarkedCircleOutline } from '@vben/icons'; | ||||||
| 
 |  | ||||||
| import { Button, message } from 'ant-design-vue'; | import { Button, message } from 'ant-design-vue'; | ||||||
| 
 | 
 | ||||||
| import { useVbenVxeGrid } from '#/adapter/vxe-table'; | import { useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||||
|  | @ -17,10 +14,8 @@ import { | ||||||
|   updateAllNotifyMessageRead, |   updateAllNotifyMessageRead, | ||||||
|   updateNotifyMessageRead, |   updateNotifyMessageRead, | ||||||
| } from '#/api/system/notify/message'; | } from '#/api/system/notify/message'; | ||||||
| import { DocAlert } from '#/components/doc-alert'; |  | ||||||
| 
 | 
 | ||||||
| import { useGridColumns, useGridFormSchema } from './data'; | import { useGridColumns, useGridFormSchema } from './data'; | ||||||
| import Detail from './modules/detail.vue'; |  | ||||||
| 
 | 
 | ||||||
| const [DetailModal, detailModalApi] = useVbenModal({ | const [DetailModal, detailModalApi] = useVbenModal({ | ||||||
|   connectedComponent: Detail, |   connectedComponent: Detail, | ||||||
|  | @ -68,9 +63,7 @@ async function onMarkRead() { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const ids = rows.map( |   const ids = rows.map((row: SystemNotifyMessageApi.SystemNotifyMessage) => row.id); | ||||||
|     (row: SystemNotifyMessageApi.SystemNotifyMessage) => row.id, |  | ||||||
|   ); |  | ||||||
|   message.loading({ |   message.loading({ | ||||||
|     content: '正在标记已读...', |     content: '正在标记已读...', | ||||||
|     duration: 0, |     duration: 0, | ||||||
|  | @ -106,10 +99,7 @@ async function onMarkAllRead() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** 表格操作按钮的回调函数 */ | /** 表格操作按钮的回调函数 */ | ||||||
| function onActionClick({ | function onActionClick({ code, row }: OnActionClickParams<SystemNotifyMessageApi.SystemNotifyMessage>) { | ||||||
|   code, |  | ||||||
|   row, |  | ||||||
| }: OnActionClickParams<SystemNotifyMessageApi.SystemNotifyMessage>) { |  | ||||||
|   switch (code) { |   switch (code) { | ||||||
|     case 'detail': { |     case 'detail': { | ||||||
|       onDetail(row); |       onDetail(row); | ||||||
|  | @ -149,9 +139,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ | ||||||
|       search: true, |       search: true, | ||||||
|     }, |     }, | ||||||
|     checkboxConfig: { |     checkboxConfig: { | ||||||
|       checkMethod: (params: { |       checkMethod: (params: { row: SystemNotifyMessageApi.SystemNotifyMessage }) => !params.row.readStatus, | ||||||
|         row: SystemNotifyMessageApi.SystemNotifyMessage; |  | ||||||
|       }) => !params.row.readStatus, |  | ||||||
|       highlight: true, |       highlight: true, | ||||||
|     }, |     }, | ||||||
|   } as VxeTableGridOptions<SystemNotifyMessageApi.SystemNotifyMessage>, |   } as VxeTableGridOptions<SystemNotifyMessageApi.SystemNotifyMessage>, | ||||||
|  |  | ||||||
|  | @ -2,13 +2,14 @@ import type { VbenFormSchema } from '#/adapter/form'; | ||||||
| import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; | import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||||
| import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | ||||||
| 
 | 
 | ||||||
| import { useAccess } from '@vben/access'; |  | ||||||
| 
 |  | ||||||
| import { z } from '#/adapter/form'; | import { z } from '#/adapter/form'; | ||||||
| import { CommonStatusEnum } from '#/utils/constants'; | import { getSimpleUserList } from '#/api/system/user'; | ||||||
|  | import { CommonStatusEnum, UserTypeEnum } from '#/utils/constants'; | ||||||
| import { getRangePickerDefaultProps } from '#/utils/date'; | import { getRangePickerDefaultProps } from '#/utils/date'; | ||||||
| import { DICT_TYPE, getDictOptions } from '#/utils/dict'; | import { DICT_TYPE, getDictOptions } from '#/utils/dict'; | ||||||
| 
 | 
 | ||||||
|  | import { useAccess } from '@vben/access'; | ||||||
|  | 
 | ||||||
| const { hasAccessByCodes } = useAccess(); | const { hasAccessByCodes } = useAccess(); | ||||||
| 
 | 
 | ||||||
| /** 新增/修改的表单 */ | /** 新增/修改的表单 */ | ||||||
|  | @ -63,10 +64,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||||||
|       label: '模板类型', |       label: '模板类型', | ||||||
|       component: 'Select', |       component: 'Select', | ||||||
|       componentProps: { |       componentProps: { | ||||||
|         options: getDictOptions( |         options: getDictOptions(DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, 'number'), | ||||||
|           DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, |  | ||||||
|           'number', |  | ||||||
|         ), |  | ||||||
|         class: 'w-full', |         class: 'w-full', | ||||||
|         placeholder: '请选择模板类型', |         placeholder: '请选择模板类型', | ||||||
|       }, |       }, | ||||||
|  | @ -130,10 +128,7 @@ export function useGridFormSchema(): VbenFormSchema[] { | ||||||
|       label: '模板类型', |       label: '模板类型', | ||||||
|       component: 'Select', |       component: 'Select', | ||||||
|       componentProps: { |       componentProps: { | ||||||
|         options: getDictOptions( |         options: getDictOptions(DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, 'number'), | ||||||
|           DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, |  | ||||||
|           'number', |  | ||||||
|         ), |  | ||||||
|         allowClear: true, |         allowClear: true, | ||||||
|         placeholder: '请选择模板类型', |         placeholder: '请选择模板类型', | ||||||
|       }, |       }, | ||||||
|  | @ -170,13 +165,47 @@ export function useSendNotifyFormSchema(): VbenFormSchema[] { | ||||||
|         show: () => false, |         show: () => false, | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |       fieldName: 'userType', | ||||||
|  |       label: '用户类型', | ||||||
|  |       component: 'RadioGroup', | ||||||
|  |       componentProps: { | ||||||
|  |         options: getDictOptions(DICT_TYPE.USER_TYPE, 'number'), | ||||||
|  |       }, | ||||||
|  |       rules: z.number().default(UserTypeEnum.MEMBER), | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|       fieldName: 'userId', |       fieldName: 'userId', | ||||||
|       label: '用户编号', |       label: '接收人ID', | ||||||
|       component: 'Input', |       component: 'Input', | ||||||
|       componentProps: { |       componentProps: { | ||||||
|         placeholder: '请输入用户编号', |         placeholder: '请输入用户编号', | ||||||
|       }, |       }, | ||||||
|  |       dependencies: { | ||||||
|  |         show(values) { | ||||||
|  |           return values.userType === UserTypeEnum.MEMBER; | ||||||
|  |         }, | ||||||
|  |         triggerFields: ['userType'], | ||||||
|  |       }, | ||||||
|  |       rules: 'required', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       fieldName: 'userId', | ||||||
|  |       label: '接收人', | ||||||
|  |       component: 'ApiSelect', | ||||||
|  |       componentProps: { | ||||||
|  |         api: getSimpleUserList, | ||||||
|  |         class: 'w-full', | ||||||
|  |         labelField: 'nickname', | ||||||
|  |         valueField: 'id', | ||||||
|  |         placeholder: '请选择接收人', | ||||||
|  |       }, | ||||||
|  |       dependencies: { | ||||||
|  |         show(values) { | ||||||
|  |           return values.userType === UserTypeEnum.ADMIN; | ||||||
|  |         }, | ||||||
|  |         triggerFields: ['userType'], | ||||||
|  |       }, | ||||||
|       rules: 'required', |       rules: 'required', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|  | @ -192,9 +221,9 @@ export function useSendNotifyFormSchema(): VbenFormSchema[] { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** 列表的字段 */ | /** 列表的字段 */ | ||||||
| export function useGridColumns< | export function useGridColumns<T = SystemNotifyTemplateApi.SystemNotifyTemplate>( | ||||||
|   T = SystemNotifyTemplateApi.SystemNotifyTemplate, |   onActionClick: OnActionClickFn<T>, | ||||||
| >(onActionClick: OnActionClickFn<T>): VxeTableGridOptions['columns'] { | ): VxeTableGridOptions['columns'] { | ||||||
|   return [ |   return [ | ||||||
|     { |     { | ||||||
|       field: 'id', |       field: 'id', | ||||||
|  |  | ||||||
|  | @ -1,28 +1,20 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import type { | import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||||
|   OnActionClickParams, |  | ||||||
|   VxeTableGridOptions, |  | ||||||
| } from '#/adapter/vxe-table'; |  | ||||||
| import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | ||||||
| 
 | 
 | ||||||
|  | import { DocAlert } from '#/components/doc-alert'; | ||||||
|  | import Form from './modules/form.vue'; | ||||||
|  | import SendForm from './modules/send-form.vue'; | ||||||
| import { Page, useVbenModal } from '@vben/common-ui'; | import { Page, useVbenModal } from '@vben/common-ui'; | ||||||
| import { Download, Plus } from '@vben/icons'; | import { Download, Plus } from '@vben/icons'; | ||||||
| 
 |  | ||||||
| import { Button, message } from 'ant-design-vue'; | import { Button, message } from 'ant-design-vue'; | ||||||
| 
 | 
 | ||||||
| import { useVbenVxeGrid } from '#/adapter/vxe-table'; | import { useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||||
| import { | import { deleteNotifyTemplate, exportNotifyTemplate, getNotifyTemplatePage } from '#/api/system/notify/template'; | ||||||
|   deleteNotifyTemplate, |  | ||||||
|   exportNotifyTemplate, |  | ||||||
|   getNotifyTemplatePage, |  | ||||||
| } from '#/api/system/notify/template'; |  | ||||||
| import { DocAlert } from '#/components/doc-alert'; |  | ||||||
| import { $t } from '#/locales'; | import { $t } from '#/locales'; | ||||||
| import { downloadByData } from '#/utils/download'; | import { downloadByData } from '#/utils/download'; | ||||||
| 
 | 
 | ||||||
| import { useGridColumns, useGridFormSchema } from './data'; | import { useGridColumns, useGridFormSchema } from './data'; | ||||||
| import Form from './modules/form.vue'; |  | ||||||
| import SendForm from './modules/send-form.vue'; |  | ||||||
| 
 | 
 | ||||||
| const [FormModal, formModalApi] = useVbenModal({ | const [FormModal, formModalApi] = useVbenModal({ | ||||||
|   connectedComponent: Form, |   connectedComponent: Form, | ||||||
|  | @ -80,10 +72,7 @@ async function onDelete(row: SystemNotifyTemplateApi.SystemNotifyTemplate) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** 表格操作按钮的回调函数 */ | /** 表格操作按钮的回调函数 */ | ||||||
| function onActionClick({ | function onActionClick({ code, row }: OnActionClickParams<SystemNotifyTemplateApi.SystemNotifyTemplate>) { | ||||||
|   code, |  | ||||||
|   row, |  | ||||||
| }: OnActionClickParams<SystemNotifyTemplateApi.SystemNotifyTemplate>) { |  | ||||||
|   switch (code) { |   switch (code) { | ||||||
|     case 'delete': { |     case 'delete': { | ||||||
|       onDelete(row); |       onDelete(row); | ||||||
|  | @ -138,20 +127,11 @@ const [Grid, gridApi] = useVbenVxeGrid({ | ||||||
|     <SendModal /> |     <SendModal /> | ||||||
|     <Grid table-title="站内信模板列表"> |     <Grid table-title="站内信模板列表"> | ||||||
|       <template #toolbar-tools> |       <template #toolbar-tools> | ||||||
|         <Button |         <Button type="primary" @click="onCreate" v-access:code="['system:notify-template:create']"> | ||||||
|           type="primary" |  | ||||||
|           @click="onCreate" |  | ||||||
|           v-access:code="['system:notify-template:create']" |  | ||||||
|         > |  | ||||||
|           <Plus class="size-5" /> |           <Plus class="size-5" /> | ||||||
|           {{ $t('ui.actionTitle.create', ['站内信模板']) }} |           {{ $t('ui.actionTitle.create', ['站内信模板']) }} | ||||||
|         </Button> |         </Button> | ||||||
|         <Button |         <Button type="primary" class="ml-2" @click="onExport" v-access:code="['system:notify-template:export']"> | ||||||
|           type="primary" |  | ||||||
|           class="ml-2" |  | ||||||
|           @click="onExport" |  | ||||||
|           v-access:code="['system:notify-template:export']" |  | ||||||
|         > |  | ||||||
|           <Download class="size-5" /> |           <Download class="size-5" /> | ||||||
|           {{ $t('ui.actionTitle.export') }} |           {{ $t('ui.actionTitle.export') }} | ||||||
|         </Button> |         </Button> | ||||||
|  |  | ||||||
|  | @ -1,28 +1,20 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | ||||||
| 
 | 
 | ||||||
| import { computed, ref } from 'vue'; |  | ||||||
| 
 |  | ||||||
| import { useVbenModal } from '@vben/common-ui'; | import { useVbenModal } from '@vben/common-ui'; | ||||||
| 
 |  | ||||||
| import { message } from 'ant-design-vue'; | import { message } from 'ant-design-vue'; | ||||||
| 
 | 
 | ||||||
| import { useVbenForm } from '#/adapter/form'; | import { useVbenForm } from '#/adapter/form'; | ||||||
| import { | import { createNotifyTemplate, getNotifyTemplate, updateNotifyTemplate } from '#/api/system/notify/template'; | ||||||
|   createNotifyTemplate, |  | ||||||
|   getNotifyTemplate, |  | ||||||
|   updateNotifyTemplate, |  | ||||||
| } from '#/api/system/notify/template'; |  | ||||||
| import { $t } from '#/locales'; | import { $t } from '#/locales'; | ||||||
|  | import { computed, ref } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { useFormSchema } from '../data'; | import { useFormSchema } from '../data'; | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['success']); | const emit = defineEmits(['success']); | ||||||
| const formData = ref<SystemNotifyTemplateApi.SystemNotifyTemplate>(); | const formData = ref<SystemNotifyTemplateApi.SystemNotifyTemplate>(); | ||||||
| const getTitle = computed(() => { | const getTitle = computed(() => { | ||||||
|   return formData.value?.id |   return formData.value?.id ? $t('ui.actionTitle.edit', ['站内信模板']) : $t('ui.actionTitle.create', ['站内信模板']); | ||||||
|     ? $t('ui.actionTitle.edit', ['站内信模板']) |  | ||||||
|     : $t('ui.actionTitle.create', ['站内信模板']); |  | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const [Form, formApi] = useVbenForm({ | const [Form, formApi] = useVbenForm({ | ||||||
|  | @ -39,12 +31,9 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|     } |     } | ||||||
|     modalApi.lock(); |     modalApi.lock(); | ||||||
|     // 提交表单 |     // 提交表单 | ||||||
|     const data = |     const data = (await formApi.getValues()) as SystemNotifyTemplateApi.SystemNotifyTemplate; | ||||||
|       (await formApi.getValues()) as SystemNotifyTemplateApi.SystemNotifyTemplate; |  | ||||||
|     try { |     try { | ||||||
|       await (formData.value?.id |       await (formData.value?.id ? updateNotifyTemplate(data) : createNotifyTemplate(data)); | ||||||
|         ? updateNotifyTemplate(data) |  | ||||||
|         : createNotifyTemplate(data)); |  | ||||||
|       // 关闭并提示 |       // 关闭并提示 | ||||||
|       await modalApi.close(); |       await modalApi.close(); | ||||||
|       emit('success'); |       emit('success'); | ||||||
|  | @ -60,9 +49,9 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|     if (!isOpen) { |     if (!isOpen) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     // 加载数据 |     // 加载数据 | ||||||
|     const data = |     const data = modalApi.getData<SystemNotifyTemplateApi.SystemNotifyTemplate>(); | ||||||
|       modalApi.getData<SystemNotifyTemplateApi.SystemNotifyTemplate>(); |  | ||||||
|     if (!data || !data.id) { |     if (!data || !data.id) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1,15 +1,13 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; | ||||||
| 
 | 
 | ||||||
| import { ref } from 'vue'; |  | ||||||
| 
 |  | ||||||
| import { useVbenModal } from '@vben/common-ui'; | import { useVbenModal } from '@vben/common-ui'; | ||||||
| 
 |  | ||||||
| import { message } from 'ant-design-vue'; | import { message } from 'ant-design-vue'; | ||||||
| 
 | 
 | ||||||
| import { useVbenForm } from '#/adapter/form'; | import { useVbenForm } from '#/adapter/form'; | ||||||
| import { sendNotify } from '#/api/system/notify/template'; | import { sendNotify } from '#/api/system/notify/template'; | ||||||
| import { $t } from '#/locales'; | import { $t } from '#/locales'; | ||||||
|  | import { ref } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { useSendNotifyFormSchema } from '../data'; | import { useSendNotifyFormSchema } from '../data'; | ||||||
| 
 | 
 | ||||||
|  | @ -24,7 +22,6 @@ const [Form, formApi] = useVbenForm({ | ||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| // TODO @puhui999:有个用户类型的选项。不同的用户类型,对应的接收人处理不同。 |  | ||||||
| const [Modal, modalApi] = useVbenModal({ | const [Modal, modalApi] = useVbenModal({ | ||||||
|   async onConfirm() { |   async onConfirm() { | ||||||
|     const { valid } = await formApi.validate(); |     const { valid } = await formApi.validate(); | ||||||
|  | @ -42,6 +39,7 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|     } |     } | ||||||
|     const data: SystemNotifyTemplateApi.SystemNotifySendReqVO = { |     const data: SystemNotifyTemplateApi.SystemNotifySendReqVO = { | ||||||
|       userId: values.userId, |       userId: values.userId, | ||||||
|  |       userType: values.userType, | ||||||
|       templateCode: formData.value?.code || '', |       templateCode: formData.value?.code || '', | ||||||
|       templateParams: paramsObj, |       templateParams: paramsObj, | ||||||
|     }; |     }; | ||||||
|  | @ -67,8 +65,7 @@ const [Modal, modalApi] = useVbenModal({ | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     // 获取数据 |     // 获取数据 | ||||||
|     const data = |     const data = modalApi.getData<SystemNotifyTemplateApi.SystemNotifyTemplate>(); | ||||||
|       modalApi.getData<SystemNotifyTemplateApi.SystemNotifyTemplate>(); |  | ||||||
|     if (!data || !data.id) { |     if (!data || !data.id) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 芋道源码
						芋道源码