ソースを参照

review:【system】邮箱管理的开发:70% 评审具体的实现
review:【system】短信管理的开发

YunaiV 4 ヶ月 前
コミット
0357425ac7

+ 1 - 1
src/api/system/mail/account/index.ts

@@ -1,6 +1,7 @@
 import type { PageParam, PageResult } from '@/http/types'
 import { http } from '@/http/http'
 
+/** 邮箱账号信息 */
 export interface MailAccount {
   id?: number
   mail: string
@@ -10,7 +11,6 @@ export interface MailAccount {
   port: number
   sslEnable: boolean
   starttlsEnable: boolean
-  remark?: string
   createTime?: string
 }
 

+ 1 - 0
src/api/system/mail/log/index.ts

@@ -1,6 +1,7 @@
 import type { PageParam, PageResult } from '@/http/types'
 import { http } from '@/http/http'
 
+/** 邮件日志信息 */
 export interface MailLog {
   id?: number
   userId?: number

+ 2 - 0
src/api/system/mail/template/index.ts

@@ -1,6 +1,7 @@
 import type { PageParam, PageResult } from '@/http/types'
 import { http } from '@/http/http'
 
+/** 邮件模板信息 */
 export interface MailTemplate {
   id?: number
   name: string
@@ -15,6 +16,7 @@ export interface MailTemplate {
   createTime?: string
 }
 
+/** 发送邮件请求 */
 export interface MailSendReqVO {
   templateCode: string
   templateParams: Record<string, any>

+ 11 - 4
src/pages-system/mail/account/detail/index.vue

@@ -1,11 +1,13 @@
 <template>
   <view class="yd-page-container">
+    <!-- 顶部导航栏 -->
     <wd-navbar
       title="邮箱账号详情"
       left-arrow placeholder safe-area-inset-top fixed
       @click-left="handleBack"
     />
 
+    <!-- 详情内容 -->
     <view>
       <wd-cell-group border>
         <wd-cell title="编号" :value="String(formData?.id ?? '-')" />
@@ -19,12 +21,12 @@
         <wd-cell title="是否开启 STARTTLS">
           <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="formData?.starttlsEnable" />
         </wd-cell>
-        <wd-cell title="备注" :value="String(formData?.remark ?? '-')" />
         <wd-cell title="创建时间" :value="formatDateTime(formData?.createTime) || '-'" />
       </wd-cell-group>
     </view>
 
-    <view class="safe-area-inset-bottom fixed bottom-0 left-0 right-0 bg-white p-24rpx">
+    <!-- 底部操作按钮 -->
+    <view class="fixed bottom-0 left-0 right-0 bg-white p-24rpx">
       <view class="w-full flex gap-24rpx">
         <wd-button
           v-if="hasAccessByCodes(['system:mail-account:update'])"
@@ -44,10 +46,10 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailAccount } from '@/api/system/mail/account/index'
+import type { MailAccount } from '@/api/system/mail/account'
 import { onMounted, ref } from 'vue'
 import { useToast } from 'wot-design-uni'
-import { deleteMailAccount, getMailAccount } from '@/api/system/mail/account/index'
+import { deleteMailAccount, getMailAccount } from '@/api/system/mail/account'
 import { useAccess } from '@/hooks/useAccess'
 import { navigateBackPlus } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
@@ -69,10 +71,12 @@ const toast = useToast()
 const formData = ref<MailAccount>()
 const deleting = ref(false)
 
+/** 返回上一页 */
 function handleBack() {
   navigateBackPlus('/pages-system/mail/index')
 }
 
+/** 加载详情 */
 async function getDetail() {
   if (!props.id) {
     return
@@ -85,12 +89,14 @@ async function getDetail() {
   }
 }
 
+/** 编辑 */
 function handleEdit() {
   uni.navigateTo({
     url: `/pages-system/mail/account/form/index?id=${props.id}`,
   })
 }
 
+/** 删除 */
 function handleDelete() {
   if (!props.id) {
     return
@@ -116,6 +122,7 @@ function handleDelete() {
   })
 }
 
+/** 初始化 */
 onMounted(() => {
   getDetail()
 })

+ 19 - 19
src/pages-system/mail/account/form/index.vue

@@ -1,11 +1,13 @@
 <template>
   <view class="yd-page-container">
+    <!-- 顶部导航栏 -->
     <wd-navbar
       :title="getTitle"
       left-arrow placeholder safe-area-inset-top fixed
       @click-left="handleBack"
     />
 
+    <!-- 表单区域 -->
     <view>
       <wd-form ref="formRef" :model="formData" :rules="formRules">
         <wd-cell-group border>
@@ -67,19 +69,19 @@
               </wd-radio>
             </wd-radio-group>
           </wd-cell>
-          <wd-textarea
-            v-model="formData.remark"
-            label="备注"
-            label-width="220rpx"
-            clearable
-            placeholder="请输入备注"
-          />
         </wd-cell-group>
       </wd-form>
     </view>
 
-    <view class="safe-area-inset-bottom fixed bottom-0 left-0 right-0 bg-white p-24rpx">
-      <wd-button type="primary" block :loading="formLoading" @click="handleSubmit">
+    <!-- 底部保存按钮 -->
+    <!-- TODO @芋艿: -->
+    <view class="fixed bottom-0 left-0 right-0 bg-white p-24rpx">
+      <wd-button
+        type="primary"
+        block
+        :loading="formLoading"
+        @click="handleSubmit"
+      >
         保存
       </wd-button>
     </view>
@@ -87,10 +89,10 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailAccount } from '@/api/system/mail/account/index'
+import type { MailAccount } from '@/api/system/mail/account'
 import { computed, onMounted, ref } from 'vue'
 import { useToast } from 'wot-design-uni'
-import { createMailAccount, getMailAccount, updateMailAccount } from '@/api/system/mail/account/index'
+import { createMailAccount, getMailAccount, updateMailAccount } from '@/api/system/mail/account'
 import { getBoolDictOptions } from '@/hooks/useDict'
 import { navigateBackPlus } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
@@ -107,7 +109,7 @@ definePage({
 })
 
 const toast = useToast()
-const getTitle = computed(() => (props.id ? '编辑邮箱账号' : '新增邮箱账号'))
+const getTitle = computed(() => props.id ? '编辑邮箱账号' : '新增邮箱账号')
 const formLoading = ref(false)
 const formData = ref<MailAccount>({
   id: undefined,
@@ -118,9 +120,7 @@ const formData = ref<MailAccount>({
   port: 25,
   sslEnable: true,
   starttlsEnable: false,
-  remark: '',
 })
-
 const formRules = {
   mail: [{ required: true, message: '邮箱不能为空' }],
   username: [{ required: true, message: '用户名不能为空' }],
@@ -130,23 +130,22 @@ const formRules = {
   sslEnable: [{ required: true, message: '是否开启 SSL 不能为空' }],
   starttlsEnable: [{ required: true, message: '是否开启 STARTTLS 不能为空' }],
 }
+const formRef = ref()
 
-const formRef = ref<any>()
-
+/** 返回上一页 */
 function handleBack() {
   navigateBackPlus('/pages-system/mail/index')
 }
 
+/** 加载详情 */
 async function getDetail() {
   if (!props.id) {
     return
   }
   formData.value = await getMailAccount(props.id)
-  if (formData.value.password === undefined) {
-    formData.value.password = ''
-  }
 }
 
+/** 提交表单 */
 async function handleSubmit() {
   const { valid } = await formRef.value.validate()
   if (!valid) {
@@ -170,6 +169,7 @@ async function handleSubmit() {
   }
 }
 
+/** 初始化 */
 onMounted(() => {
   getDetail()
 })

+ 15 - 7
src/pages-system/mail/components/account-list.vue

@@ -1,7 +1,9 @@
 <template>
   <view>
+    <!-- 搜索组件 -->
     <AccountSearchForm @search="handleQuery" @reset="handleReset" />
 
+    <!-- 账号列表 -->
     <view class="p-24rpx">
       <view
         v-for="item in list"
@@ -19,10 +21,6 @@
             <text class="mr-8rpx shrink-0 text-[#999]">用户名:</text>
             <text class="min-w-0 flex-1 truncate">{{ item.username || '-' }}</text>
           </view>
-          <view class="mb-12rpx flex items-center text-28rpx text-[#666]">
-            <text class="mr-8rpx shrink-0 text-[#999]">SMTP:</text>
-            <text class="min-w-0 flex-1 truncate">{{ item.host }}:{{ item.port }}</text>
-          </view>
           <view class="mb-12rpx flex items-center text-28rpx text-[#666]">
             <text class="mr-8rpx text-[#999]">创建时间:</text>
             <text>{{ formatDateTime(item.createTime) || '-' }}</text>
@@ -30,6 +28,7 @@
         </view>
       </view>
 
+      <!-- 加载更多 -->
       <view v-if="loadMoreState !== 'loading' && list.length === 0" class="py-100rpx text-center">
         <wd-status-tip image="content" tip="暂无邮箱账号数据" />
       </view>
@@ -40,6 +39,7 @@
       />
     </view>
 
+    <!-- 新增按钮 -->
     <wd-fab
       v-if="hasAccessByCodes(['system:mail-account:create'])"
       position="right-bottom"
@@ -51,10 +51,10 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailAccount } from '@/api/system/mail/account/index'
+import type { MailAccount } from '@/api/system/mail/account'
 import type { LoadMoreState } from '@/http/types'
-import { onMounted, ref } from 'vue'
-import { getMailAccountPage } from '@/api/system/mail/account/index'
+import { ref } from 'vue'
+import { getMailAccountPage } from '@/api/system/mail/account'
 import { useAccess } from '@/hooks/useAccess'
 import { formatDateTime } from '@/utils/date'
 import AccountSearchForm from './account-search-form.vue'
@@ -68,6 +68,7 @@ const queryParams = ref({
   pageSize: 10,
 })
 
+/** 查询列表 */
 async function getList() {
   loadMoreState.value = 'loading'
   try {
@@ -81,6 +82,7 @@ async function getList() {
   }
 }
 
+/** 搜索按钮操作 */
 function handleQuery(data?: Record<string, any>) {
   queryParams.value = {
     ...data,
@@ -91,10 +93,12 @@ function handleQuery(data?: Record<string, any>) {
   getList()
 }
 
+/** 重置按钮操作 */
 function handleReset() {
   handleQuery()
 }
 
+/** 加载更多 */
 function loadMore() {
   if (loadMoreState.value === 'finished') {
     return
@@ -103,22 +107,26 @@ function loadMore() {
   getList()
 }
 
+/** 新增 */
 function handleAdd() {
   uni.navigateTo({
     url: '/pages-system/mail/account/form/index',
   })
 }
 
+/** 查看详情 */
 function handleDetail(item: MailAccount) {
   uni.navigateTo({
     url: `/pages-system/mail/account/detail/index?id=${item.id}`,
   })
 }
 
+/** 触底加载更多 */
 onReachBottom(() => {
   loadMore()
 })
 
+/** 初始化 */
 onMounted(() => {
   getList()
 })

+ 27 - 6
src/pages-system/mail/components/account-search-form.vue

@@ -1,21 +1,39 @@
 <template>
+  <!-- 搜索框入口 -->
   <view @click="visible = true">
     <wd-search :placeholder="placeholder" hide-cancel disabled />
   </view>
 
+  <!-- 搜索弹窗 -->
   <wd-popup v-model="visible" position="top" @close="visible = false">
     <view class="yd-search-form-container" :style="{ paddingTop: `${getNavbarHeight()}px` }">
       <view class="yd-search-form-item">
-        <view class="yd-search-form-label">邮箱</view>
-        <wd-input v-model="formData.mail" placeholder="请输入邮箱" clearable />
+        <view class="yd-search-form-label">
+          邮箱
+        </view>
+        <wd-input
+          v-model="formData.mail"
+          placeholder="请输入邮箱"
+          clearable
+        />
       </view>
       <view class="yd-search-form-item">
-        <view class="yd-search-form-label">用户名</view>
-        <wd-input v-model="formData.username" placeholder="请输入用户名" clearable />
+        <view class="yd-search-form-label">
+          用户名
+        </view>
+        <wd-input
+          v-model="formData.username"
+          placeholder="请输入用户名"
+          clearable
+        />
       </view>
       <view class="yd-search-form-actions">
-        <wd-button class="flex-1" plain @click="handleReset">重置</wd-button>
-        <wd-button class="flex-1" type="primary" @click="handleSearch">搜索</wd-button>
+        <wd-button class="flex-1" plain @click="handleReset">
+          重置
+        </wd-button>
+        <wd-button class="flex-1" type="primary" @click="handleSearch">
+          搜索
+        </wd-button>
       </view>
     </view>
   </wd-popup>
@@ -36,6 +54,7 @@ const formData = reactive({
   username: undefined as string | undefined,
 })
 
+/** 搜索条件 placeholder 拼接 */
 const placeholder = computed(() => {
   const conditions: string[] = []
   if (formData.mail) {
@@ -47,6 +66,7 @@ const placeholder = computed(() => {
   return conditions.length > 0 ? conditions.join(' | ') : '搜索邮箱账号'
 })
 
+/** 搜索 */
 function handleSearch() {
   visible.value = false
   emit('search', {
@@ -55,6 +75,7 @@ function handleSearch() {
   })
 }
 
+/** 重置 */
 function handleReset() {
   formData.mail = undefined
   formData.username = undefined

+ 14 - 3
src/pages-system/mail/components/log-list.vue

@@ -1,7 +1,9 @@
 <template>
   <view>
+    <!-- 搜索组件 -->
     <LogSearchForm @search="handleQuery" @reset="handleReset" />
 
+    <!-- 日志列表 -->
     <view class="p-24rpx">
       <view
         v-for="item in list"
@@ -31,6 +33,7 @@
         </view>
       </view>
 
+      <!-- 加载更多 -->
       <view v-if="loadMoreState !== 'loading' && list.length === 0" class="py-100rpx text-center">
         <wd-status-tip image="content" tip="暂无邮件日志数据" />
       </view>
@@ -44,10 +47,10 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailLog } from '@/api/system/mail/log/index'
+import type { MailLog } from '@/api/system/mail/log'
 import type { LoadMoreState } from '@/http/types'
-import { onMounted, ref } from 'vue'
-import { getMailLogPage } from '@/api/system/mail/log/index'
+import { ref } from 'vue'
+import { getMailLogPage } from '@/api/system/mail/log'
 import { DICT_TYPE } from '@/utils/constants'
 import { formatDateTime } from '@/utils/date'
 import LogSearchForm from './log-search-form.vue'
@@ -60,6 +63,7 @@ const queryParams = ref({
   pageSize: 10,
 })
 
+/** 格式化邮件列表 */
 function formatMails(mails?: string[]) {
   if (!mails || mails.length === 0) {
     return '-'
@@ -67,6 +71,7 @@ function formatMails(mails?: string[]) {
   return mails.join('、')
 }
 
+/** 查询列表 */
 async function getList() {
   loadMoreState.value = 'loading'
   try {
@@ -80,6 +85,7 @@ async function getList() {
   }
 }
 
+/** 搜索按钮操作 */
 function handleQuery(data?: Record<string, any>) {
   queryParams.value = {
     ...data,
@@ -90,10 +96,12 @@ function handleQuery(data?: Record<string, any>) {
   getList()
 }
 
+/** 重置按钮操作 */
 function handleReset() {
   handleQuery()
 }
 
+/** 加载更多 */
 function loadMore() {
   if (loadMoreState.value === 'finished') {
     return
@@ -102,16 +110,19 @@ function loadMore() {
   getList()
 }
 
+/** 查看详情 */
 function handleDetail(item: MailLog) {
   uni.navigateTo({
     url: `/pages-system/mail/log/detail/index?id=${item.id}`,
   })
 }
 
+/** 触底加载更多 */
 onReachBottom(() => {
   loadMore()
 })
 
+/** 初始化 */
 onMounted(() => {
   getList()
 })

+ 25 - 3
src/pages-system/mail/components/log-search-form.vue

@@ -1,15 +1,21 @@
 <template>
+  <!-- 搜索框入口 -->
   <view @click="visible = true">
     <wd-search :placeholder="placeholder" hide-cancel disabled />
   </view>
 
+  <!-- 搜索弹窗 -->
   <wd-popup v-model="visible" position="top" @close="visible = false">
     <view class="yd-search-form-container" :style="{ paddingTop: `${getNavbarHeight()}px` }">
       <view class="yd-search-form-item">
         <view class="yd-search-form-label">
           用户编号
         </view>
-        <wd-input v-model="formData.userId" placeholder="请输入用户编号" clearable />
+        <wd-input
+          v-model="formData.userId"
+          placeholder="请输入用户编号"
+          clearable
+        />
       </view>
       <view class="yd-search-form-item">
         <view class="yd-search-form-label">
@@ -59,7 +65,11 @@
         <view class="yd-search-form-label">
           模板编号
         </view>
-        <wd-input v-model="formData.templateId" placeholder="请输入模板编号" clearable />
+        <wd-input
+          v-model="formData.templateId"
+          placeholder="请输入模板编号"
+          clearable
+        />
       </view>
       <view class="yd-search-form-item">
         <view class="yd-search-form-label">
@@ -111,7 +121,7 @@
 
 <script lang="ts" setup>
 import { computed, onMounted, reactive, ref } from 'vue'
-import { getSimpleMailAccountList } from '@/api/system/mail/account/index'
+import { getSimpleMailAccountList } from '@/api/system/mail/account'
 import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
 import { getNavbarHeight } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
@@ -132,17 +142,23 @@ const formData = reactive({
   templateId: undefined as number | undefined,
 })
 
+/** 邮箱账号列表 */
 const accountList = ref<{ id?: number, mail: string }[]>([])
+
+/** 邮箱账号选项 */
 const accountOptions = computed(() => {
   return accountList.value.map(item => ({
     value: item.id,
     label: item.mail,
   }))
 })
+
+/** 获取邮箱账号名称 */
 function getAccountMail(accountId?: number) {
   return accountList.value.find(item => item.id === accountId)?.mail
 }
 
+/** 搜索条件 placeholder 拼接 */
 const placeholder = computed(() => {
   const conditions: string[] = []
   if (formData.sendTime?.[0] && formData.sendTime?.[1]) {
@@ -166,19 +182,23 @@ const placeholder = computed(() => {
   return conditions.length > 0 ? conditions.join(' | ') : '搜索邮件日志'
 })
 
+// 时间范围选择器状态
 const visibleSendTime = ref<[boolean, boolean]>([false, false])
 const tempSendTime = ref<[number, number]>([Date.now(), Date.now()])
 
+/** 发送时间[0]确认 */
 function handleSendTime0Confirm() {
   formData.sendTime = [tempSendTime.value[0], formData.sendTime?.[1]]
   visibleSendTime.value[0] = false
 }
 
+/** 发送时间[1]确认 */
 function handleSendTime1Confirm() {
   formData.sendTime = [formData.sendTime?.[0], tempSendTime.value[1]]
   visibleSendTime.value[1] = false
 }
 
+/** 搜索 */
 function handleSearch() {
   visible.value = false
   const dateRange = formatDateRange(formData.sendTime)
@@ -193,6 +213,7 @@ function handleSearch() {
   })
 }
 
+/** 重置 */
 function handleReset() {
   formData.sendTime = [undefined, undefined]
   formData.userId = undefined
@@ -204,6 +225,7 @@ function handleReset() {
   emit('reset')
 }
 
+/** 初始化 */
 onMounted(async () => {
   try {
     accountList.value = await getSimpleMailAccountList()

+ 15 - 3
src/pages-system/mail/components/template-list.vue

@@ -1,7 +1,9 @@
 <template>
   <view>
+    <!-- 搜索组件 -->
     <TemplateSearchForm @search="handleQuery" @reset="handleReset" />
 
+    <!-- 模板列表 -->
     <view class="p-24rpx">
       <view
         v-for="item in list"
@@ -31,6 +33,7 @@
         </view>
       </view>
 
+      <!-- 加载更多 -->
       <view v-if="loadMoreState !== 'loading' && list.length === 0" class="py-100rpx text-center">
         <wd-status-tip image="content" tip="暂无邮件模板数据" />
       </view>
@@ -41,6 +44,7 @@
       />
     </view>
 
+    <!-- 新增按钮 -->
     <wd-fab
       v-if="hasAccessByCodes(['system:mail-template:create'])"
       position="right-bottom"
@@ -52,10 +56,10 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailTemplate } from '@/api/system/mail/template/index'
+import type { MailTemplate } from '@/api/system/mail/template'
 import type { LoadMoreState } from '@/http/types'
-import { onMounted, ref } from 'vue'
-import { getMailTemplatePage } from '@/api/system/mail/template/index'
+import { ref } from 'vue'
+import { getMailTemplatePage } from '@/api/system/mail/template'
 import { useAccess } from '@/hooks/useAccess'
 import { DICT_TYPE } from '@/utils/constants'
 import { formatDateTime } from '@/utils/date'
@@ -70,6 +74,7 @@ const queryParams = ref({
   pageSize: 10,
 })
 
+/** 查询列表 */
 async function getList() {
   loadMoreState.value = 'loading'
   try {
@@ -83,6 +88,7 @@ async function getList() {
   }
 }
 
+/** 搜索按钮操作 */
 function handleQuery(data?: Record<string, any>) {
   queryParams.value = {
     ...data,
@@ -93,10 +99,12 @@ function handleQuery(data?: Record<string, any>) {
   getList()
 }
 
+/** 重置按钮操作 */
 function handleReset() {
   handleQuery()
 }
 
+/** 加载更多 */
 function loadMore() {
   if (loadMoreState.value === 'finished') {
     return
@@ -105,22 +113,26 @@ function loadMore() {
   getList()
 }
 
+/** 新增 */
 function handleAdd() {
   uni.navigateTo({
     url: '/pages-system/mail/template/form/index',
   })
 }
 
+/** 查看详情 */
 function handleDetail(item: MailTemplate) {
   uni.navigateTo({
     url: `/pages-system/mail/template/detail/index?id=${item.id}`,
   })
 }
 
+/** 触底加载更多 */
 onReachBottom(() => {
   loadMore()
 })
 
+/** 初始化 */
 onMounted(() => {
   getList()
 })

+ 25 - 3
src/pages-system/mail/components/template-search-form.vue

@@ -1,21 +1,31 @@
 <template>
+  <!-- 搜索框入口 -->
   <view @click="visible = true">
     <wd-search :placeholder="placeholder" hide-cancel disabled />
   </view>
 
+  <!-- 搜索弹窗 -->
   <wd-popup v-model="visible" position="top" @close="visible = false">
     <view class="yd-search-form-container" :style="{ paddingTop: `${getNavbarHeight()}px` }">
       <view class="yd-search-form-item">
         <view class="yd-search-form-label">
           模板编码
         </view>
-        <wd-input v-model="formData.code" placeholder="请输入模板编码" clearable />
+        <wd-input
+          v-model="formData.code"
+          placeholder="请输入模板编码"
+          clearable
+        />
       </view>
       <view class="yd-search-form-item">
         <view class="yd-search-form-label">
           模板名称
         </view>
-        <wd-input v-model="formData.name" placeholder="请输入模板名称" clearable />
+        <wd-input
+          v-model="formData.name"
+          placeholder="请输入模板名称"
+          clearable
+        />
       </view>
       <view class="yd-search-form-item">
         <view class="yd-search-form-label">
@@ -94,7 +104,7 @@
 
 <script lang="ts" setup>
 import { computed, onMounted, reactive, ref } from 'vue'
-import { getSimpleMailAccountList } from '@/api/system/mail/account/index'
+import { getSimpleMailAccountList } from '@/api/system/mail/account'
 import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
 import { getNavbarHeight } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
@@ -114,17 +124,23 @@ const formData = reactive({
   createTime: [undefined, undefined] as [number | undefined, number | undefined],
 })
 
+/** 邮箱账号列表 */
 const accountList = ref<{ id?: number, mail: string }[]>([])
+
+/** 邮箱账号选项 */
 const accountOptions = computed(() => {
   return accountList.value.map(item => ({
     value: item.id,
     label: item.mail,
   }))
 })
+
+/** 获取邮箱账号名称 */
 function getAccountMail(accountId?: number) {
   return accountList.value.find(item => item.id === accountId)?.mail
 }
 
+/** 搜索条件 placeholder 拼接 */
 const placeholder = computed(() => {
   const conditions: string[] = []
   if (formData.status !== -1) {
@@ -145,19 +161,23 @@ const placeholder = computed(() => {
   return conditions.length > 0 ? conditions.join(' | ') : '搜索邮件模板'
 })
 
+// 时间范围选择器状态
 const visibleCreateTime = ref<[boolean, boolean]>([false, false])
 const tempCreateTime = ref<[number, number]>([Date.now(), Date.now()])
 
+/** 创建时间[0]确认 */
 function handleCreateTime0Confirm() {
   formData.createTime = [tempCreateTime.value[0], formData.createTime?.[1]]
   visibleCreateTime.value[0] = false
 }
 
+/** 创建时间[1]确认 */
 function handleCreateTime1Confirm() {
   formData.createTime = [formData.createTime?.[0], tempCreateTime.value[1]]
   visibleCreateTime.value[1] = false
 }
 
+/** 搜索 */
 function handleSearch() {
   visible.value = false
   const dateRange = formatDateRange(formData.createTime)
@@ -171,6 +191,7 @@ function handleSearch() {
   })
 }
 
+/** 重置 */
 function handleReset() {
   formData.status = -1
   formData.code = undefined
@@ -181,6 +202,7 @@ function handleReset() {
   emit('reset')
 }
 
+/** 初始化 */
 onMounted(async () => {
   try {
     accountList.value = await getSimpleMailAccountList()

+ 5 - 1
src/pages-system/mail/index.vue

@@ -1,11 +1,13 @@
 <template>
   <view class="yd-page-container">
+    <!-- 顶部导航栏 -->
     <wd-navbar
       title="邮件管理"
       left-arrow placeholder safe-area-inset-top fixed
       @click-left="handleBack"
     />
 
+    <!-- Tab 切换 -->
     <view class="bg-white">
       <wd-tabs v-model="tabIndex" shrink @change="handleTabChange">
         <wd-tab title="邮箱账号" />
@@ -13,7 +15,7 @@
         <wd-tab title="邮件日志" />
       </wd-tabs>
     </view>
-
+    <!-- 列表内容 -->
     <AccountList v-show="tabType === 'account'" />
     <TemplateList v-show="tabType === 'template'" />
     <LogList v-show="tabType === 'log'" />
@@ -38,10 +40,12 @@ const tabTypes: string[] = ['account', 'template', 'log']
 const tabIndex = ref(0)
 const tabType = computed<string>(() => tabTypes[tabIndex.value])
 
+/** Tab 切换 */
 function handleTabChange({ index }: { index: number }) {
   tabIndex.value = index
 }
 
+/** 返回上一页 */
 function handleBack() {
   navigateBackPlus()
 }

+ 10 - 2
src/pages-system/mail/log/detail/index.vue

@@ -1,11 +1,13 @@
 <template>
   <view class="yd-page-container">
+    <!-- 顶部导航栏 -->
     <wd-navbar
       title="邮件日志详情"
       left-arrow placeholder safe-area-inset-top fixed
       @click-left="handleBack"
     />
 
+    <!-- 详情内容 -->
     <view>
       <wd-cell-group border>
         <wd-cell title="日志编号" :value="String(formData?.id ?? '-')" />
@@ -28,10 +30,10 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailLog } from '@/api/system/mail/log/index'
+import type { MailLog } from '@/api/system/mail/log'
 import { onMounted, ref } from 'vue'
 import { useToast } from 'wot-design-uni'
-import { getMailLogPage } from '@/api/system/mail/log/index'
+import { getMailLogPage } from '@/api/system/mail/log'
 import { navigateBackPlus } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
 import { formatDateTime } from '@/utils/date'
@@ -50,10 +52,12 @@ definePage({
 const toast = useToast()
 const formData = ref<MailLog>()
 
+/** 返回上一页 */
 function handleBack() {
   navigateBackPlus('/pages-system/mail/index')
 }
 
+/** 格式化接收信息 */
 function formatReceiveInfo(data?: MailLog) {
   if (!data) {
     return '-'
@@ -71,12 +75,15 @@ function formatReceiveInfo(data?: MailLog) {
   return lines.length > 0 ? lines.join(';') : '-'
 }
 
+/** 加载详情 - 由于没有单独的获取详情接口,通过列表接口获取 */
 async function getDetail() {
   if (!props.id) {
     return
   }
   try {
     toast.loading('加载中...')
+    // 通过分页接口获取单条数据
+    // TODO @AI:使用 getMailLog 认为它存在!我去支持下;
     const data = await getMailLogPage({ pageNo: 1, pageSize: 1, id: props.id })
     if (data.list && data.list.length > 0) {
       formData.value = data.list[0]
@@ -86,6 +93,7 @@ async function getDetail() {
   }
 }
 
+/** 初始化 */
 onMounted(() => {
   getDetail()
 })

+ 8 - 4
src/pages-system/mail/template/detail/components/send-form.vue

@@ -2,7 +2,7 @@
   <wd-popup v-model="visible" position="bottom" closable custom-style="border-radius: 16rpx 16rpx 0 0;">
     <view class="p-24rpx">
       <view class="mb-24rpx text-32rpx text-[#333] font-semibold">
-        测试发送邮件
+        发送测试邮件
       </view>
       <wd-form ref="sendFormRef" :model="sendFormData" :rules="sendFormRules">
         <wd-cell-group border>
@@ -47,7 +47,6 @@
           </template>
         </wd-cell-group>
       </wd-form>
-
       <view class="mt-24rpx">
         <wd-button type="primary" block :loading="sendLoading" @click="handleSendSubmit">
           发送
@@ -58,10 +57,10 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailTemplate } from '@/api/system/mail/template/index'
+import type { MailTemplate } from '@/api/system/mail/template'
 import { computed, ref, watch } from 'vue'
 import { useToast } from 'wot-design-uni'
-import { sendMail } from '@/api/system/mail/template/index'
+import { sendMail } from '@/api/system/mail/template'
 
 const props = defineProps<{
   modelValue: boolean
@@ -94,6 +93,7 @@ const sendFormData = ref({
   templateParams: {} as Record<string, string>,
 })
 
+/** 发送表单校验规则 */
 const sendFormRules = computed(() => {
   const rules: Record<string, any> = {
     toMails: [{ required: true, message: '收件邮箱不能为空' }],
@@ -106,6 +106,8 @@ const sendFormRules = computed(() => {
   return rules
 })
 
+/** 格式化邮箱列表 */
+// TODO @AI:需要 isEmail 校验下,validator 里有
 function normalizeMailList(text: string) {
   return text
     .split(/[,,;;\s]+/)
@@ -113,6 +115,7 @@ function normalizeMailList(text: string) {
     .filter(Boolean)
 }
 
+/** 初始化发送表单 */
 function initSendForm() {
   sendFormData.value = {
     content: props.template?.content || '',
@@ -137,6 +140,7 @@ watch(
   },
 )
 
+/** 提交发送 */
 async function handleSendSubmit() {
   const { valid } = await sendFormRef.value.validate()
   if (!valid) {

+ 22 - 6
src/pages-system/mail/template/detail/index.vue

@@ -1,11 +1,13 @@
 <template>
   <view class="yd-page-container">
+    <!-- 顶部导航栏 -->
     <wd-navbar
       title="邮件模板详情"
       left-arrow placeholder safe-area-inset-top fixed
       @click-left="handleBack"
     />
 
+    <!-- 详情内容 -->
     <view>
       <wd-cell-group border>
         <wd-cell title="模板编号" :value="String(formData?.id ?? '-')" />
@@ -23,9 +25,11 @@
       </wd-cell-group>
     </view>
 
+    <!-- 发送测试邮件弹窗 -->
     <SendForm v-model="sendVisible" :template="formData" />
 
-    <view class="safe-area-inset-bottom fixed bottom-0 left-0 right-0 bg-white p-24rpx">
+    <!-- 底部操作按钮 -->
+    <view class="fixed bottom-0 left-0 right-0 bg-white p-24rpx">
       <view class="w-full flex gap-24rpx">
         <wd-button
           v-if="hasAccessByCodes(['system:mail-template:send-mail'])"
@@ -51,12 +55,12 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailAccount } from '@/api/system/mail/account/index'
-import type { MailTemplate } from '@/api/system/mail/template/index'
+import type { MailAccount } from '@/api/system/mail/account'
+import type { MailTemplate } from '@/api/system/mail/template'
 import { onMounted, ref } from 'vue'
 import { useToast } from 'wot-design-uni'
-import { getSimpleMailAccountList } from '@/api/system/mail/account/index'
-import { deleteMailTemplate, getMailTemplate } from '@/api/system/mail/template/index'
+import { getSimpleMailAccountList } from '@/api/system/mail/account'
+import { deleteMailTemplate, getMailTemplate } from '@/api/system/mail/template'
 import { useAccess } from '@/hooks/useAccess'
 import { navigateBackPlus } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
@@ -78,17 +82,24 @@ const { hasAccessByCodes } = useAccess()
 const toast = useToast()
 const formData = ref<MailTemplate>()
 const deleting = ref(false)
+
+// 发送测试邮件相关
 const sendVisible = ref(false)
 
+/** 邮箱账号列表 */
 const accountList = ref<MailAccount[]>([])
+
+/** 获取邮箱账号名称 */
 function getAccountMail(accountId?: number) {
-  return accountList.value.find(item => item.id === accountId)?.mail
+  return accountList.value.find((item: MailAccount) => item.id === accountId)?.mail
 }
 
+/** 返回上一页 */
 function handleBack() {
   navigateBackPlus('/pages-system/mail/index')
 }
 
+/** 加载邮箱账号列表 */
 async function loadAccountList() {
   try {
     accountList.value = await getSimpleMailAccountList()
@@ -97,6 +108,7 @@ async function loadAccountList() {
   }
 }
 
+/** 加载详情 */
 async function getDetail() {
   if (!props.id) {
     return
@@ -109,12 +121,14 @@ async function getDetail() {
   }
 }
 
+/** 编辑 */
 function handleEdit() {
   uni.navigateTo({
     url: `/pages-system/mail/template/form/index?id=${props.id}`,
   })
 }
 
+/** 删除 */
 function handleDelete() {
   if (!props.id) {
     return
@@ -140,10 +154,12 @@ function handleDelete() {
   })
 }
 
+/** 打开发送测试邮件弹窗 */
 function handleSendTest() {
   sendVisible.value = true
 }
 
+/** 初始化 */
 onMounted(async () => {
   await loadAccountList()
   await getDetail()

+ 25 - 10
src/pages-system/mail/template/form/index.vue

@@ -1,11 +1,13 @@
 <template>
   <view class="yd-page-container">
+    <!-- 顶部导航栏 -->
     <wd-navbar
       :title="getTitle"
       left-arrow placeholder safe-area-inset-top fixed
       @click-left="handleBack"
     />
 
+    <!-- 表单区域 -->
     <view>
       <wd-form ref="formRef" :model="formData" :rules="formRules">
         <wd-cell-group border>
@@ -78,8 +80,14 @@
       </wd-form>
     </view>
 
-    <view class="safe-area-inset-bottom fixed bottom-0 left-0 right-0 bg-white p-24rpx">
-      <wd-button type="primary" block :loading="formLoading" @click="handleSubmit">
+    <!-- 底部保存按钮 -->
+    <view class="fixed bottom-0 left-0 right-0 bg-white p-24rpx">
+      <wd-button
+        type="primary"
+        block
+        :loading="formLoading"
+        @click="handleSubmit"
+      >
         保存
       </wd-button>
     </view>
@@ -87,12 +95,12 @@
 </template>
 
 <script lang="ts" setup>
-import type { MailAccount } from '@/api/system/mail/account/index'
-import type { MailTemplate } from '@/api/system/mail/template/index'
+import type { MailAccount } from '@/api/system/mail/account'
+import type { MailTemplate } from '@/api/system/mail/template'
 import { computed, onMounted, ref } from 'vue'
 import { useToast } from 'wot-design-uni'
-import { getSimpleMailAccountList } from '@/api/system/mail/account/index'
-import { createMailTemplate, getMailTemplate, updateMailTemplate } from '@/api/system/mail/template/index'
+import { getSimpleMailAccountList } from '@/api/system/mail/account'
+import { createMailTemplate, getMailTemplate, updateMailTemplate } from '@/api/system/mail/template'
 import { getIntDictOptions } from '@/hooks/useDict'
 import { navigateBackPlus } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
@@ -109,7 +117,7 @@ definePage({
 })
 
 const toast = useToast()
-const getTitle = computed(() => (props.id ? '编辑邮件模板' : '新增邮件模板'))
+const getTitle = computed(() => props.id ? '编辑邮件模板' : '新增邮件模板')
 const formLoading = ref(false)
 const formData = ref<MailTemplate>({
   id: undefined,
@@ -122,7 +130,6 @@ const formData = ref<MailTemplate>({
   status: 0,
   remark: '',
 })
-
 const formRules = {
   name: [{ required: true, message: '模板名称不能为空' }],
   code: [{ required: true, message: '模板编码不能为空' }],
@@ -131,10 +138,13 @@ const formRules = {
   content: [{ required: true, message: '模板内容不能为空' }],
   status: [{ required: true, message: '开启状态不能为空' }],
 }
+const formRef = ref()
 
-const formRef = ref<any>()
-
+/** 邮箱账号列表 */
 const accountList = ref<MailAccount[]>([])
+
+/** 邮箱账号选项 */
+// TODO @AI:直接使用 accountList,参考 https://wot-ui.cn/component/picker.html ,支持通过 label-key 和 value-key;
 const accountOptions = computed(() => {
   return accountList.value.map(item => ({
     value: item.id,
@@ -142,14 +152,17 @@ const accountOptions = computed(() => {
   }))
 })
 
+/** 返回上一页 */
 function handleBack() {
   navigateBackPlus('/pages-system/mail/index')
 }
 
+/** 加载邮箱账号列表 */
 async function loadAccountList() {
   accountList.value = await getSimpleMailAccountList()
 }
 
+/** 加载详情 */
 async function getDetail() {
   if (!props.id) {
     return
@@ -157,6 +170,7 @@ async function getDetail() {
   formData.value = await getMailTemplate(props.id)
 }
 
+/** 提交表单 */
 async function handleSubmit() {
   const { valid } = await formRef.value.validate()
   if (!valid) {
@@ -180,6 +194,7 @@ async function handleSubmit() {
   }
 }
 
+/** 初始化 */
 onMounted(async () => {
   await loadAccountList()
   await getDetail()

+ 1 - 0
src/pages-system/sms/channel/form/index.vue

@@ -129,6 +129,7 @@ const formRules = {
 const formRef = ref()
 
 /** 渠道编码选项 */
+// TODO @AI:直接使用 getStrDictOptions(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE) 在 html 里;别的模块,也是这么干的
 const channelCodeOptions = computed(() => {
   return getStrDictOptions(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE).map(item => ({
     value: item.value,

+ 1 - 0
src/pages-system/sms/log/detail/index.vue

@@ -76,6 +76,7 @@ async function getDetail() {
   try {
     toast.loading('加载中...')
     // 通过分页接口获取单条数据
+    // TODO @AI:使用 getMailLog 认为它存在!我去支持下;
     const data = await getSmsLogPage({ pageNo: 1, pageSize: 1, id: props.id })
     if (data.list && data.list.length > 0) {
       formData.value = data.list[0]

+ 3 - 0
src/pages-system/sms/template/detail/components/send-form.vue

@@ -78,6 +78,7 @@ const sendFormData = ref({
   templateParams: {} as Record<string, string>,
 })
 
+/** 发送表单校验规则 */
 const sendFormRules = computed(() => {
   const rules: Record<string, any> = {
     mobile: [{ required: true, message: '手机号码不能为空' }],
@@ -90,6 +91,7 @@ const sendFormRules = computed(() => {
   return rules
 })
 
+/** 初始化发送表单 */
 function initSendForm() {
   sendFormData.value = {
     content: props.template?.content || '',
@@ -112,6 +114,7 @@ watch(
   },
 )
 
+/** 提交发送 */
 async function handleSendSubmit() {
   const { valid } = await sendFormRef.value.validate()
   if (!valid) {