Browse Source

Merge branch 'master' of https://gitee.com/yudaocode/yudao-ui-admin-vue3 into dev

# Conflicts:
#	src/views/ai/mindmap/index/components/Right.vue
#	src/views/ai/mindmap/index/index.vue
YunaiV 10 months ago
parent
commit
fb08357e8f
32 changed files with 187 additions and 129 deletions
  1. 0 1
      .gitignore
  2. 1 1
      package.json
  3. 1 1
      src/api/bpm/definition/index.ts
  4. 1 0
      src/api/bpm/model/index.ts
  5. 2 11
      src/api/bpm/processInstance/index.ts
  6. 1 1
      src/components/ConfigGlobal/src/ConfigGlobal.vue
  7. 2 2
      src/components/DictTag/src/DictTag.vue
  8. 1 0
      src/components/DiyEditor/components/ComponentLibrary.vue
  9. 49 9
      src/components/Editor/src/Editor.vue
  10. 1 0
      src/components/UploadFile/src/UploadFile.vue
  11. 9 7
      src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue
  12. 10 8
      src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue
  13. 3 1
      src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
  14. 1 1
      src/config/axios/service.ts
  15. 5 0
      src/layout/components/Menu/src/Menu.vue
  16. 1 1
      src/layout/components/UserInfo/src/components/LockPage.vue
  17. 1 1
      src/router/modules/remaining.ts
  18. 0 1
      src/utils/dict.ts
  19. 1 2
      src/views/ai/chat/index/index.vue
  20. 4 4
      src/views/bpm/processInstance/detail/index.vue
  21. 19 5
      src/views/bpm/processInstance/index.vue
  22. 2 1
      src/views/infra/fileConfig/index.vue
  23. 1 1
      src/views/infra/webSocket/index.vue
  24. 19 1
      src/views/mall/product/category/index.vue
  25. 1 1
      src/views/mall/product/spu/form/index.vue
  26. 6 0
      src/views/mall/product/spu/index.vue
  27. 9 48
      src/views/pay/app/components/channel/WeixinChannelForm.vue
  28. 3 1
      src/views/pay/order/OrderDetail.vue
  29. 3 1
      src/views/pay/refund/RefundDetail.vue
  30. 21 14
      src/views/pay/wallet/balance/index.vue
  31. 3 3
      src/views/system/operatelog/index.vue
  32. 6 1
      src/views/system/sms/channel/index.vue

+ 0 - 1
.gitignore

@@ -2,7 +2,6 @@ node_modules
 .DS_Store
 dist
 dist-ssr
-*.local
 /dist*
 pnpm-debug
 auto-*.d.ts

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "yudao-ui-admin-vue3",
-  "version": "2.1.0-snapshot",
+  "version": "2.2.0-snapshot",
   "description": "基于vue3、vite4、element-plus、typesScript",
   "author": "xingyu",
   "private": false,

+ 1 - 1
src/api/bpm/definition/index.ts

@@ -1,6 +1,6 @@
 import request from '@/config/axios'
 
-export const getProcessDefinition = async (id: number, key: string) => {
+export const getProcessDefinition = async (id?: string, key?: string) => {
   return await request.get({
     url: '/bpm/process-definition/get',
     params: { id, key }

+ 1 - 0
src/api/bpm/model/index.ts

@@ -5,6 +5,7 @@ export type ProcessDefinitionVO = {
   version: number
   deploymentTIme: string
   suspensionState: number
+  formType?: number
 }
 
 export type ModelVO = {

+ 2 - 11
src/api/bpm/processInstance/index.ts

@@ -1,4 +1,5 @@
 import request from '@/config/axios'
+import { ProcessDefinitionVO } from '@/api/bpm/model'
 
 export type Task = {
   id: string
@@ -18,17 +19,7 @@ export type ProcessInstanceVO = {
   businessKey: string
   createTime: string
   endTime: string
-}
-
-export type ProcessInstanceCopyVO = {
-  type: number
-  taskName: string
-  taskKey: string
-  processInstanceName: string
-  processInstanceKey: string
-  startUserId: string
-  options: string[]
-  reason: string
+  processDefinition?: ProcessDefinitionVO
 }
 
 export const getProcessInstanceMyPage = async (params: any) => {

+ 1 - 1
src/components/ConfigGlobal/src/ConfigGlobal.vue

@@ -54,7 +54,7 @@ const currentLocale = computed(() => localeStore.currentLocale)
   <ElConfigProvider
     :namespace="variables.elNamespace"
     :locale="currentLocale.elLocale"
-    :message="{ max: 1 }"
+    :message="{ max: 5 }"
     :size="size"
   >
     <slot></slot>

+ 2 - 2
src/components/DictTag/src/DictTag.vue

@@ -22,8 +22,8 @@ export default defineComponent({
       const dictOptions = getDictOptions(dictType)
       dictOptions.forEach((dict: DictDataType) => {
         if (dict.value === value) {
-          if (dict.colorType + '' === 'primary' || dict.colorType + '' === 'default') {
-            dict.colorType = ''
+          if (dict.colorType + '' === 'default') {
+            dict.colorType = 'info'
           }
           dictData.value = dict
         }

+ 1 - 0
src/components/DiyEditor/components/ComponentLibrary.vue

@@ -95,6 +95,7 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
 .editor-left {
   z-index: 1;
   flex-shrink: 0;
+  user-select: none;
   box-shadow: 8px 0 8px -8px rgb(0 0 0 / 12%);
 
   :deep(.el-collapse) {

+ 49 - 9
src/components/Editor/src/Editor.vue

@@ -96,11 +96,6 @@ const editorConfig = computed((): IEditorConfig => {
           // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
           allowedFileTypes: ['image/*'],
 
-          // 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
-          meta: { updateSupport: 0 },
-          // 将 meta 拼接到 url 参数中,默认 false
-          metaWithUrl: true,
-
           // 自定义增加 http  header
           headers: {
             Accept: '*',
@@ -108,9 +103,6 @@ const editorConfig = computed((): IEditorConfig => {
             'tenant-id': getTenantId()
           },
 
-          // 跨域是否传递 cookie ,默认为 false
-          withCredentials: true,
-
           // 超时时间,默认为 10 秒
           timeout: 5 * 1000, // 5 秒
 
@@ -119,7 +111,7 @@ const editorConfig = computed((): IEditorConfig => {
 
           // 上传之前触发
           onBeforeUpload(file: File) {
-            console.log(file)
+            // console.log(file)
             return file
           },
           // 上传进度的回调函数
@@ -142,6 +134,54 @@ const editorConfig = computed((): IEditorConfig => {
           customInsert(res: any, insertFn: InsertFnType) {
             insertFn(res.data, 'image', res.data)
           }
+        },
+        ['uploadVideo']: {
+          server: import.meta.env.VITE_UPLOAD_URL,
+          // 单个文件的最大体积限制,默认为 10M
+          maxFileSize: 10 * 1024 * 1024,
+          // 最多可上传几个文件,默认为 100
+          maxNumberOfFiles: 10,
+          // 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []
+          allowedFileTypes: ['video/*'],
+
+          // 自定义增加 http  header
+          headers: {
+            Accept: '*',
+            Authorization: 'Bearer ' + getAccessToken(),
+            'tenant-id': getTenantId()
+          },
+
+          // 超时时间,默认为 30 秒
+          timeout: 15 * 1000, // 15 秒
+
+          // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
+          fieldName: 'file',
+
+          // 上传之前触发
+          onBeforeUpload(file: File) {
+            // console.log(file)
+            return file
+          },
+          // 上传进度的回调函数
+          onProgress(progress: number) {
+            // progress 是 0-100 的数字
+            console.log('progress', progress)
+          },
+          onSuccess(file: File, res: any) {
+            console.log('onSuccess', file, res)
+          },
+          onFailed(file: File, res: any) {
+            alert(res.message)
+            console.log('onFailed', file, res)
+          },
+          onError(file: File, err: any, res: any) {
+            alert(err.message)
+            console.error('onError', file, err, res)
+          },
+          // 自定义插入图片
+          customInsert(res: any, insertFn: InsertFnType) {
+            insertFn(res.data, 'mp4', res.data)
+          }
         }
       },
       uploadImgShowBase64: true

+ 1 - 0
src/components/UploadFile/src/UploadFile.vue

@@ -32,6 +32,7 @@
           格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b> 的文件
         </div>
       </template>
+      <!-- TODO @puhui999:1)表单展示的时候,位置会偏掉,已发微信;2)disable 的时候,应该把【删除】按钮也隐藏掉? -->
       <template #file="row">
         <div class="flex items-center">
           <span>{{ row.file.name }}</span>

+ 9 - 7
src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue

@@ -43,9 +43,6 @@ import { CommonStatusEnum } from '@/utils/constants'
 /** BPM 流程 表单 */
 defineOptions({ name: 'ProcessListenerDialog' })
 
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
 const dialogVisible = ref(false) // 弹窗的是否展示
 const loading = ref(true) // 列表的加载中
 const list = ref<ProcessListenerVO[]>([]) // 列表的数据
@@ -53,17 +50,23 @@ const total = ref(0) // 列表的总页数
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
-  type: undefined,
+  type: '',
   status: CommonStatusEnum.ENABLE
 })
 
 /** 打开弹窗 */
 const open = async (type: string) => {
+  queryParams.pageNo = 1
+  queryParams.type = type
+  getList()
   dialogVisible.value = true
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 查询列表 */
+const getList = async () => {
   loading.value = true
   try {
-    queryParams.pageNo = 1
-    queryParams.type = type
     const data = await ProcessListenerApi.getProcessListenerPage(queryParams)
     list.value = data.list
     total.value = data.total
@@ -71,7 +74,6 @@ const open = async (type: string) => {
     loading.value = false
   }
 }
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
 /** 提交表单 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调

+ 10 - 8
src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue

@@ -28,9 +28,6 @@ import { ProcessExpressionApi, ProcessExpressionVO } from '@/api/bpm/processExpr
 /** BPM 流程 表单 */
 defineOptions({ name: 'ProcessExpressionDialog' })
 
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
 const dialogVisible = ref(false) // 弹窗的是否展示
 const loading = ref(true) // 列表的加载中
 const list = ref<ProcessExpressionVO[]>([]) // 列表的数据
@@ -38,17 +35,23 @@ const total = ref(0) // 列表的总页数
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
-  type: undefined,
+  type: '',
   status: CommonStatusEnum.ENABLE
 })
 
 /** 打开弹窗 */
-const open = async (type: string) => {
+const open = (type: string) => {
+  queryParams.pageNo = 1
+  queryParams.type = type
+  getList()
   dialogVisible.value = true
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 查询列表 */
+const getList = async () => {
   loading.value = true
   try {
-    queryParams.pageNo = 1
-    queryParams.type = type
     const data = await ProcessExpressionApi.getProcessExpressionPage(queryParams)
     list.value = data.list
     total.value = data.total
@@ -56,7 +59,6 @@ const open = async (type: string) => {
     loading.value = false
   }
 }
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
 /** 提交表单 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调

+ 3 - 1
src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue

@@ -135,6 +135,7 @@ import * as PostApi from '@/api/system/post'
 import * as UserApi from '@/api/system/user'
 import * as UserGroupApi from '@/api/bpm/userGroup'
 import ProcessExpressionDialog from './ProcessExpressionDialog.vue'
+import { ProcessExpressionVO } from '@/api/bpm/processExpression'
 
 defineOptions({ name: 'UserTask' })
 const props = defineProps({
@@ -197,8 +198,9 @@ const processExpressionDialogRef = ref()
 const openProcessExpressionDialog = async () => {
   processExpressionDialogRef.value.open()
 }
-const selectProcessExpression = (expression) => {
+const selectProcessExpression = (expression: ProcessExpressionVO) => {
   userTaskForm.value.candidateParam = [expression.expression]
+  updateElementTask()
 }
 
 watch(

+ 1 - 1
src/config/axios/service.ts

@@ -81,7 +81,7 @@ service.interceptors.request.use(
   (error: AxiosError) => {
     // Do something with request error
     console.log(error) // for debug
-    Promise.reject(error)
+    return Promise.reject(error)
   }
 )
 

+ 5 - 0
src/layout/components/Menu/src/Menu.vue

@@ -90,6 +90,11 @@ export default defineComponent({
           backgroundColor="var(--left-menu-bg-color)"
           textColor="var(--left-menu-text-color)"
           activeTextColor="var(--left-menu-text-active-color)"
+          popperClass={
+            unref(menuMode) === 'vertical'
+              ? `${prefixCls}-popper--vertical`
+              : `${prefixCls}-popper--horizontal`
+          }
           onSelect={menuSelect}
         >
           {{

+ 1 - 1
src/layout/components/UserInfo/src/components/LockPage.vue

@@ -52,7 +52,7 @@ async function goLogin() {
   // 登出后清理
   deleteUserCache() // 清空用户缓存
   tagsViewStore.delAllViews()
-  resetRouter() // 重置静态路由表
+  // resetRouter() // 重置静态路由表
   lockStore.resetLockInfo()
   replace('/login')
 }

+ 1 - 1
src/router/modules/remaining.ts

@@ -341,7 +341,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/mall/product/spu/form/index.vue'),
         name: 'ProductSpuAdd',
         meta: {
-          noCache: true,
+          noCache: false, // 需要缓存
           hidden: true,
           canTo: true,
           icon: 'ep:edit',

+ 0 - 1
src/utils/dict.ts

@@ -125,7 +125,6 @@ export enum DICT_TYPE {
   SYSTEM_SMS_TEMPLATE_TYPE = 'system_sms_template_type',
   SYSTEM_SMS_SEND_STATUS = 'system_sms_send_status',
   SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status',
-  SYSTEM_ERROR_CODE_TYPE = 'system_error_code_type',
   SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type',
   SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status',
   SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type',

+ 1 - 2
src/views/ai/chat/index/index.vue

@@ -27,7 +27,7 @@
           <el-button size="small" class="btn">
             <Icon icon="ep:download" color="#787878" />
           </el-button>
-          <el-button size="small" class="btn" @click="handleGoTopMessage" >
+          <el-button size="small" class="btn" @click="handleGoTopMessage">
             <Icon icon="ep:top" color="#787878" />
           </el-button>
         </div>
@@ -119,7 +119,6 @@ import MessageList from './components/message/MessageList.vue'
 import MessageListEmpty from './components/message/MessageListEmpty.vue'
 import MessageLoading from './components/message/MessageLoading.vue'
 import MessageNewConversation from './components/message/MessageNewConversation.vue'
-import { Download, Top } from '@element-plus/icons-vue'
 
 /** AI 聊天对话 列表 */
 defineOptions({ name: 'AiChat' })

+ 4 - 4
src/views/bpm/processInstance/detail/index.vue

@@ -47,10 +47,10 @@
           <el-form-item label="抄送人" prop="copyUserIds">
             <el-select v-model="auditForms[index].copyUserIds" multiple placeholder="请选择抄送人">
               <el-option
-                v-for="item in userOptions"
-                :key="item.id"
-                :label="item.nickname"
-                :value="item.id"
+                v-for="itemx in userOptions"
+                :key="itemx.id"
+                :label="itemx.nickname"
+                :value="itemx.id"
               />
             </el-select>
           </el-form-item>

+ 19 - 5
src/views/bpm/processInstance/index.vue

@@ -76,7 +76,7 @@
           type="primary"
           plain
           v-hasPermi="['bpm:process-instance:query']"
-          @click="handleCreate()"
+          @click="handleCreate(undefined)"
         >
           <Icon icon="ep:plus" class="mr-5px" /> 发起流程
         </el-button>
@@ -146,7 +146,7 @@
           >
             取消
           </el-button>
-          <el-button link type="primary" v-else @click="handleCreate(scope.row.id)">
+          <el-button link type="primary" v-else @click="handleCreate(scope.row)">
             重新发起
           </el-button>
         </template>
@@ -167,6 +167,8 @@ import { dateFormatter, formatPast2 } from '@/utils/formatTime'
 import { ElMessageBox } from 'element-plus'
 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
 import { CategoryApi } from '@/api/bpm/category'
+import { ProcessInstanceVO } from '@/api/bpm/processInstance'
+import * as DefinitionApi from '@/api/bpm/definition'
 
 defineOptions({ name: 'BpmProcessInstanceMy' })
 
@@ -214,10 +216,22 @@ const resetQuery = () => {
 }
 
 /** 发起流程操作 **/
-const handleCreate = (id) => {
-  router.push({
+const handleCreate = async (row?: ProcessInstanceVO) => {
+  // 如果是【业务表单】,不支持重新发起
+  if (row?.id) {
+    const processDefinitionDetail = await DefinitionApi.getProcessDefinition(
+      row.processDefinitionId
+    )
+    debugger
+    if (processDefinitionDetail.formType === 20) {
+      message.error('重新发起流程失败,原因:该流程使用业务表单,不支持重新发起')
+      return
+    }
+  }
+  // 跳转发起流程界面
+  await router.push({
     name: 'BpmProcessInstanceCreate',
-    query: { processInstanceId: id }
+    query: { processInstanceId: row?.id }
   })
 }
 

+ 2 - 1
src/views/infra/fileConfig/index.vue

@@ -206,7 +206,8 @@ const handleMaster = async (id) => {
 const handleTest = async (id) => {
   try {
     const response = await FileConfigApi.testFileConfig(id)
-    message.alert('测试通过,上传文件成功!访问地址:' + response)
+    await message.confirm('是否要访问该文件?', '测试上传成功')
+    window.open(response, '_blank')
   } catch {}
 }
 

+ 1 - 1
src/views/infra/webSocket/index.vue

@@ -86,7 +86,7 @@ const getTagColor = computed(() => (getIsOpen.value ? 'success' : 'red')) // Web
 
 /** 发起 WebSocket 连接 */
 const { status, data, send, close, open } = useWebSocket(server.value, {
-  autoReconnect: false,
+  autoReconnect: true,
   heartbeat: true
 })
 

+ 19 - 1
src/views/mall/product/category/index.vue

@@ -56,7 +56,7 @@
         width="180"
         :formatter="dateFormatter"
       />
-      <el-table-column label="操作" align="center">
+      <el-table-column label="操作" align="center" min-width="180">
         <template #default="scope">
           <el-button
             link
@@ -66,6 +66,15 @@
           >
             编辑
           </el-button>
+          <el-button
+            link
+            type="primary"
+            v-if="scope.row.parentId > 0"
+            @click="handleViewSpu(scope.row.id)"
+            v-hasPermi="['product:spu:query']"
+          >
+            查看商品
+          </el-button>
           <el-button
             link
             type="danger"
@@ -142,6 +151,15 @@ const handleDelete = async (id: number) => {
   } catch {}
 }
 
+/** 查看商品操作 */
+const router = useRouter() // 路由
+const handleViewSpu = (id: number) => {
+  router.push({
+    name: 'ProductSpu',
+    query: { categoryId: id }
+  })
+}
+
 /** 初始化 **/
 onMounted(() => {
   getList()

+ 1 - 1
src/views/mall/product/spu/form/index.vue

@@ -63,7 +63,7 @@ import SkuForm from './SkuForm.vue'
 import DeliveryForm from './DeliveryForm.vue'
 import { convertToInteger, floatToFixed2, formatToFraction } from '@/utils'
 
-defineOptions({ name: 'ProductSpuForm' })
+defineOptions({ name: 'ProductSpuAdd' })
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗

+ 6 - 0
src/views/mall/product/spu/index.vue

@@ -244,6 +244,7 @@ import * as ProductCategoryApi from '@/api/mall/product/category'
 defineOptions({ name: 'ProductSpu' })
 
 const message = useMessage() // 消息弹窗
+const route = useRoute() // 路由
 const { t } = useI18n() // 国际化
 const { push } = useRouter() // 路由跳转
 
@@ -431,6 +432,11 @@ onActivated(() => {
 
 /** 初始化 **/
 onMounted(async () => {
+  // 解析路由的 categoryId
+  if (route.query.categoryId) {
+    queryParams.value.categoryId = Number(route.query.categoryId)
+  }
+  // 获得商品信息
   await getTabsCount()
   await getList()
   // 获得分类树

+ 9 - 48
src/views/pay/app/components/channel/WeixinChannelForm.vue

@@ -52,9 +52,6 @@
               v-model="formData.config.mchKey"
               placeholder="请输入商户密钥"
               clearable
-              :style="{ width: '100%' }"
-              type="textarea"
-              :autosize="{ minRows: 8, maxRows: 8 }"
             />
           </el-form-item>
           <el-form-item
@@ -92,9 +89,6 @@
               v-model="formData.config.apiV3Key"
               placeholder="请输入 API V3 密钥"
               clearable
-              :style="{ width: '100%' }"
-              type="textarea"
-              :autosize="{ minRows: 8, maxRows: 8 }"
             />
           </el-form-item>
           <el-form-item
@@ -126,35 +120,13 @@
               </el-button>
             </el-upload>
           </el-form-item>
-          <el-form-item
-            label-width="180px"
-            label="apiclient_cert.pem证书"
-            prop="config.privateCertContent"
-          >
+          <el-form-item label-width="180px" label="证书序列号" prop="config.certSerialNo">
             <el-input
-              v-model="formData.config.privateCertContent"
-              type="textarea"
-              placeholder="请上传apiclient_cert.pem证书"
-              readonly
-              :autosize="{ minRows: 8, maxRows: 8 }"
-              :style="{ width: '100%' }"
+              v-model="formData.config.certSerialNo"
+              placeholder="请输入证书序列号"
+              clearable
             />
           </el-form-item>
-          <el-form-item label-width="180px" label="" prop="privateCertContentFile">
-            <el-upload
-              ref="privateCertContentFile"
-              :limit="1"
-              accept=".pem"
-              action=""
-              :before-upload="pemFileBeforeUpload"
-              :http-request="privateCertContentUpload"
-            >
-              <el-button type="primary">
-                <Icon icon="ep:upload" class="mr-5px" />
-                点击上传
-              </el-button>
-            </el-upload>
-          </el-form-item>
         </div>
         <el-form-item label-width="180px" label="备注" prop="remark">
           <el-input v-model="formData.remark" :style="{ width: '100%' }" />
@@ -193,7 +165,7 @@ const formData = ref<any>({
     mchKey: '',
     keyContent: '',
     privateKeyContent: '',
-    privateCertContent: '',
+    certSerialNo: '',
     apiV3Key: ''
   }
 })
@@ -210,8 +182,8 @@ const formRules = {
   'config.privateKeyContent': [
     { required: true, message: '请上传 apiclient_key.pem 证书', trigger: 'blur' }
   ],
-  'config.privateCertContent': [
-    { required: true, message: '请上传 apiclient_cert.pem证 书', trigger: 'blur' }
+  'config.certSerialNo': [
+    { required: true, message: '请输入证书序列号', trigger: 'blur' }
   ],
   'config.apiV3Key': [{ required: true, message: '请上传 api V3 密钥值', trigger: 'blur' }]
 }
@@ -278,7 +250,7 @@ const resetForm = (appId, code) => {
       mchKey: '',
       keyContent: '',
       privateKeyContent: '',
-      privateCertContent: '',
+      certSerialNo: '',
       apiV3Key: ''
     }
   }
@@ -286,7 +258,7 @@ const resetForm = (appId, code) => {
 }
 
 /**
- * apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem 上传前的校验
+ * apiclient_cert.p12、apiclient_key.pem 上传前的校验
  */
 const fileBeforeUpload = (file, fileAccept) => {
   let format = '.' + file.name.split('.')[1]
@@ -321,17 +293,6 @@ const privateKeyContentUpload = async (event) => {
   readFile.readAsText(event.file)
 }
 
-/**
- * 读取 apiclient_cert.pem 到 privateCertContent 字段
- */
-const privateCertContentUpload = async (event) => {
-  const readFile = new FileReader()
-  readFile.onload = (e: any) => {
-    formData.value.config.privateCertContent = e.target.result
-  }
-  readFile.readAsText(event.file)
-}
-
 /**
  * 读取 apiclient_cert.p12 到 keyContent 字段
  */

+ 3 - 1
src/views/pay/order/OrderDetail.vue

@@ -62,7 +62,9 @@
     <el-divider />
     <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
       <el-descriptions-item label="支付通道异步回调内容">
-        <el-text>{{ detailData.extension.channelNotifyData }}</el-text>
+        <el-text style="white-space: pre-wrap; word-break: break-word">
+          {{ detailData.extension.channelNotifyData }}
+        </el-text>
       </el-descriptions-item>
     </el-descriptions>
   </Dialog>

+ 3 - 1
src/views/pay/refund/RefundDetail.vue

@@ -62,7 +62,9 @@
     </el-descriptions>
     <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
       <el-descriptions-item label="支付通道异步回调内容">
-        {{ refundDetail.channelNotifyData }}
+        <el-text style="white-space: pre-wrap; word-break: break-word">
+          {{ refundDetail.channelNotifyData }}
+        </el-text>
       </el-descriptions-item>
     </el-descriptions>
   </Dialog>

+ 21 - 14
src/views/pay/wallet/balance/index.vue

@@ -8,15 +8,30 @@
       :inline="true"
       label-width="68px"
     >
-      <el-form-item label="用户昵称" prop="nickname">
+      <el-form-item label="用户编号" prop="userId">
         <el-input
-          v-model="queryParams.nickname"
-          placeholder="请输入用户昵称"
+          v-model="queryParams.userId"
+          placeholder="请输入用户编号"
           clearable
           @keyup.enter="handleQuery"
           class="!w-240px"
         />
       </el-form-item>
+      <el-form-item label="用户类型" prop="userType">
+        <el-select
+          v-model="queryParams.userType"
+          placeholder="请选择用户类型"
+          clearable
+          class="!w-240px"
+        >
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.USER_TYPE)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
         <el-date-picker
           v-model="queryParams.createTime"
@@ -39,12 +54,7 @@
   <ContentWrap>
     <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
       <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="用户昵称" align="center" prop="nickname" />
-      <el-table-column label="头像" align="center" prop="avatar" width="80px">
-        <template #default="scope">
-          <img :src="scope.row.avatar" style="width: 40px" />
-        </template>
-      </el-table-column>
+      <el-table-column label="用户编号" align="center" prop="userId" />
       <el-table-column label="用户类型" align="center" prop="userType">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType" />
@@ -97,20 +107,17 @@ import WalletForm from './WalletForm.vue'
 
 defineOptions({ name: 'WalletBalance' })
 
-const message = useMessage() // 消息弹窗
-const { t } = useI18n() // 国际化
-
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
-  nickname: null,
+  userId: null,
+  userType: null,
   createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
 
 /** 查询列表 */
 const getList = async () => {

+ 3 - 3
src/views/system/operatelog/index.vue

@@ -35,10 +35,10 @@
           class="!w-240px"
         />
       </el-form-item>
-      <el-form-item label="操作模块" prop="subType">
+      <el-form-item label="操作" prop="subType">
         <el-input
           v-model="queryParams.subType"
-          placeholder="请输入操作模块"
+          placeholder="请输入操作"
           clearable
           @keyup.enter="handleQuery"
           class="!w-240px"
@@ -105,7 +105,7 @@
         :formatter="dateFormatter"
       />
       <el-table-column label="业务编号" align="center" prop="bizId" width="120" />
-      <el-table-column label="IP" align="center" prop="userIp" width="120" />
+      <el-table-column label="操作 IP" align="center" prop="userIp" width="120" />
       <el-table-column label="操作" align="center" fixed="right" width="60">
         <template #default="scope">
           <el-button

+ 6 - 1
src/views/system/sms/channel/index.vue

@@ -18,7 +18,12 @@
         />
       </el-form-item>
       <el-form-item label="启用状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择启用状态" clearable>
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择启用状态"
+          class="!w-240px"
+          clearable
+        >
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
             :key="dict.value"