mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-11-04 08:06:12 +08:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master'
This commit is contained in:
		@ -31,7 +31,7 @@
 | 
			
		||||
    "@wangeditor/editor-for-vue": "^5.1.10",
 | 
			
		||||
    "@zxcvbn-ts/core": "^2.1.0",
 | 
			
		||||
    "animate.css": "^4.1.1",
 | 
			
		||||
    "axios": "^1.1.3",
 | 
			
		||||
    "axios": "^0.27.2",
 | 
			
		||||
    "crypto-js": "^4.1.1",
 | 
			
		||||
    "dayjs": "^1.11.6",
 | 
			
		||||
    "echarts": "^5.4.0",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								yudao-ui-admin-vue3/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										13
									
								
								yudao-ui-admin-vue3/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@ -23,7 +23,7 @@ specifiers:
 | 
			
		||||
  '@zxcvbn-ts/core': ^2.1.0
 | 
			
		||||
  animate.css: ^4.1.1
 | 
			
		||||
  autoprefixer: ^10.4.13
 | 
			
		||||
  axios: ^1.1.3
 | 
			
		||||
  axios: ^0.27.2
 | 
			
		||||
  crypto-js: ^4.1.1
 | 
			
		||||
  dayjs: ^1.11.6
 | 
			
		||||
  echarts: ^5.4.0
 | 
			
		||||
@ -87,7 +87,7 @@ dependencies:
 | 
			
		||||
  '@wangeditor/editor-for-vue': 5.1.12_95363b7c2c964a937bf2a01c911df30e
 | 
			
		||||
  '@zxcvbn-ts/core': 2.1.0
 | 
			
		||||
  animate.css: 4.1.1
 | 
			
		||||
  axios: 1.1.3
 | 
			
		||||
  axios: 0.27.2
 | 
			
		||||
  crypto-js: 4.1.1
 | 
			
		||||
  dayjs: 1.11.6
 | 
			
		||||
  echarts: 5.4.0
 | 
			
		||||
@ -2175,12 +2175,11 @@ packages:
 | 
			
		||||
      - debug
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /axios/1.1.3:
 | 
			
		||||
    resolution: {integrity: sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==}
 | 
			
		||||
  /axios/0.27.2:
 | 
			
		||||
    resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      follow-redirects: 1.15.2
 | 
			
		||||
      form-data: 4.0.0
 | 
			
		||||
      proxy-from-env: 1.1.0
 | 
			
		||||
    transitivePeerDependencies:
 | 
			
		||||
      - debug
 | 
			
		||||
    dev: false
 | 
			
		||||
@ -5790,10 +5789,6 @@ packages:
 | 
			
		||||
    engines: {node: '>=6'}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /proxy-from-env/1.1.0:
 | 
			
		||||
    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /prr/1.0.1:
 | 
			
		||||
    resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ import axios, {
 | 
			
		||||
  AxiosResponse,
 | 
			
		||||
  AxiosError
 | 
			
		||||
} from 'axios'
 | 
			
		||||
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
 | 
			
		||||
import { useMessage } from '@/hooks/web/useMessage'
 | 
			
		||||
import qs from 'qs'
 | 
			
		||||
import { config } from '@/config/axios/config'
 | 
			
		||||
import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } from '@/utils/auth'
 | 
			
		||||
@ -17,6 +17,7 @@ import { useCache } from '@/hooks/web/useCache'
 | 
			
		||||
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
 | 
			
		||||
const { result_code, base_url, request_timeout } = config
 | 
			
		||||
 | 
			
		||||
const message = useMessage()
 | 
			
		||||
// 需要忽略的提示。忽略后,自动 Promise.reject('error')
 | 
			
		||||
const ignoreMsgs = [
 | 
			
		||||
  '无效的刷新令牌', // 刷新令牌被删除时,不用提示
 | 
			
		||||
@ -46,9 +47,9 @@ service.interceptors.request.use(
 | 
			
		||||
      ;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token
 | 
			
		||||
    }
 | 
			
		||||
    // 设置租户
 | 
			
		||||
    if (tenantEnable) {
 | 
			
		||||
    if (tenantEnable && tenantEnable === 'true') {
 | 
			
		||||
      const tenantId = getTenantId()
 | 
			
		||||
      if (tenantId) service.defaults.headers.common['tenant-id'] = tenantId
 | 
			
		||||
      if (tenantId) (config as Recordable).headers.common['tenant-id'] = tenantId
 | 
			
		||||
    }
 | 
			
		||||
    const params = config.params || {}
 | 
			
		||||
    const data = config.data || false
 | 
			
		||||
@ -129,7 +130,6 @@ service.interceptors.response.use(
 | 
			
		||||
          // 2.1 刷新成功,则回放队列的请求 + 当前请求
 | 
			
		||||
          setToken((await refreshTokenRes).data.data)
 | 
			
		||||
          config.headers!.Authorization = 'Bearer ' + getAccessToken()
 | 
			
		||||
          service.defaults.headers.Authorization = 'Bearer ' + getAccessToken()
 | 
			
		||||
          requestList.forEach((cb: any) => {
 | 
			
		||||
            cb()
 | 
			
		||||
          })
 | 
			
		||||
@ -157,10 +157,10 @@ service.interceptors.response.use(
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    } else if (code === 500) {
 | 
			
		||||
      ElMessage.error(t('sys.api.errMsg500'))
 | 
			
		||||
      message.error(t('sys.api.errMsg500'))
 | 
			
		||||
      return Promise.reject(new Error(msg))
 | 
			
		||||
    } else if (code === 901) {
 | 
			
		||||
      ElMessage.error(
 | 
			
		||||
      message.error(
 | 
			
		||||
        '<div>' +
 | 
			
		||||
          t('sys.api.errMsg901') +
 | 
			
		||||
          '</div>' +
 | 
			
		||||
@ -175,9 +175,7 @@ service.interceptors.response.use(
 | 
			
		||||
        // hard coding:忽略这个提示,直接登出
 | 
			
		||||
        console.log(msg)
 | 
			
		||||
      } else {
 | 
			
		||||
        ElNotification.error({
 | 
			
		||||
          title: msg
 | 
			
		||||
        })
 | 
			
		||||
        message.notifyError(msg)
 | 
			
		||||
      }
 | 
			
		||||
      return Promise.reject('error')
 | 
			
		||||
    } else {
 | 
			
		||||
@ -186,16 +184,16 @@ service.interceptors.response.use(
 | 
			
		||||
  },
 | 
			
		||||
  (error: AxiosError) => {
 | 
			
		||||
    console.log('err' + error) // for debug
 | 
			
		||||
    let { message } = error
 | 
			
		||||
    let { message: msg } = error
 | 
			
		||||
    const { t } = useI18n()
 | 
			
		||||
    if (message === 'Network Error') {
 | 
			
		||||
      message = t('sys.api.errorMessage')
 | 
			
		||||
    } else if (message.includes('timeout')) {
 | 
			
		||||
      message = t('sys.api.apiTimeoutMessage')
 | 
			
		||||
    } else if (message.includes('Request failed with status code')) {
 | 
			
		||||
      message = t('sys.api.apiRequestFailed') + message.substr(message.length - 3)
 | 
			
		||||
    if (msg === 'Network Error') {
 | 
			
		||||
      msg = t('sys.api.errorMessage')
 | 
			
		||||
    } else if (msg.includes('timeout')) {
 | 
			
		||||
      msg = t('sys.api.apiTimeoutMessage')
 | 
			
		||||
    } else if (msg.includes('Request failed with status code')) {
 | 
			
		||||
      msg = t('sys.api.apiRequestFailed') + msg.substr(msg.length - 3)
 | 
			
		||||
    }
 | 
			
		||||
    ElMessage.error(message)
 | 
			
		||||
    message.error(msg)
 | 
			
		||||
    return Promise.reject(error)
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
@ -207,11 +205,8 @@ const handleAuthorized = () => {
 | 
			
		||||
  const { t } = useI18n()
 | 
			
		||||
  if (!isRelogin.show) {
 | 
			
		||||
    isRelogin.show = true
 | 
			
		||||
    ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), {
 | 
			
		||||
      confirmButtonText: t('login.relogin'),
 | 
			
		||||
      cancelButtonText: t('common.cancel'),
 | 
			
		||||
      type: 'warning'
 | 
			
		||||
    })
 | 
			
		||||
    message
 | 
			
		||||
      .confirm(t('sys.api.timeoutMessage'))
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        const { wsCache } = useCache()
 | 
			
		||||
        resetRouter() // 重置静态路由表
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,9 @@
 | 
			
		||||
 | 
			
		||||
import WebStorageCache from 'web-storage-cache'
 | 
			
		||||
 | 
			
		||||
type CacheType = 'sessionStorage' | 'localStorage'
 | 
			
		||||
type CacheType = 'localStorage' | 'sessionStorage'
 | 
			
		||||
 | 
			
		||||
export const useCache = (type: CacheType = 'sessionStorage') => {
 | 
			
		||||
export const useCache = (type: CacheType = 'localStorage') => {
 | 
			
		||||
  const wsCache: WebStorageCache = new WebStorageCache({
 | 
			
		||||
    storage: type
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
@ -121,10 +121,10 @@ const filterSearchSchema = (crudSchema: VxeCrudSchema[]): VxeFormItemProps[] =>
 | 
			
		||||
          props: { placeholder: t('common.selectText') }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const searchSchemaItem = {
 | 
			
		||||
        // 默认为 input
 | 
			
		||||
        span: 6,
 | 
			
		||||
        span: 8,
 | 
			
		||||
        folding: searchSchema.length > 2,
 | 
			
		||||
        itemRender: itemRender,
 | 
			
		||||
        ...schemaItem.search,
 | 
			
		||||
        field: schemaItem.field,
 | 
			
		||||
@ -140,7 +140,7 @@ const filterSearchSchema = (crudSchema: VxeCrudSchema[]): VxeFormItemProps[] =>
 | 
			
		||||
  const buttons: VxeFormItemProps = {
 | 
			
		||||
    span: 24,
 | 
			
		||||
    align: 'center',
 | 
			
		||||
    collapseNode: true,
 | 
			
		||||
    collapseNode: searchSchema.length > 3,
 | 
			
		||||
    itemRender: {
 | 
			
		||||
      name: '$buttons',
 | 
			
		||||
      children: [
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { computed, reactive } from 'vue'
 | 
			
		||||
import { VxeGridProps } from 'vxe-table'
 | 
			
		||||
import { SizeType, VxeGridProps } from 'vxe-table'
 | 
			
		||||
import { useAppStore } from '@/store/modules/app'
 | 
			
		||||
import { VxeAllSchemas } from './useVxeCrudSchemas'
 | 
			
		||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
			
		||||
@ -18,20 +18,27 @@ interface UseVxeGridConfig<T = any> {
 | 
			
		||||
const appStore = useAppStore()
 | 
			
		||||
 | 
			
		||||
const currentSize = computed(() => {
 | 
			
		||||
  if (appStore.getCurrentSize === 'small') {
 | 
			
		||||
    return 'small'
 | 
			
		||||
  } else if (appStore.getCurrentSize === 'large') {
 | 
			
		||||
    return 'mini'
 | 
			
		||||
  } else {
 | 
			
		||||
    return 'medium'
 | 
			
		||||
  let resSize: SizeType = 'small'
 | 
			
		||||
  const appsize = appStore.getCurrentSize
 | 
			
		||||
  switch (appsize) {
 | 
			
		||||
    case 'large':
 | 
			
		||||
      resSize = 'medium'
 | 
			
		||||
      break
 | 
			
		||||
    case 'default':
 | 
			
		||||
      resSize = 'small'
 | 
			
		||||
      break
 | 
			
		||||
    case 'small':
 | 
			
		||||
      resSize = 'mini'
 | 
			
		||||
      break
 | 
			
		||||
  }
 | 
			
		||||
  return resSize
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const useVxeGrid = <T = any>(config?: UseVxeGridConfig<T>) => {
 | 
			
		||||
  const gridOptions = reactive<VxeGridProps>({
 | 
			
		||||
    loading: true,
 | 
			
		||||
    size: currentSize.value,
 | 
			
		||||
    height: 800,
 | 
			
		||||
    size: currentSize as any,
 | 
			
		||||
    height: 700,
 | 
			
		||||
    rowConfig: {
 | 
			
		||||
      isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
 | 
			
		||||
      isHover: true // 当鼠标移到行时,是否要高亮当前行
 | 
			
		||||
@ -90,10 +97,12 @@ export const useVxeGrid = <T = any>(config?: UseVxeGridConfig<T>) => {
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
  const delList = (ids: string | number | string[] | number[]) => {
 | 
			
		||||
    return new Promise(async () => {
 | 
			
		||||
      message.delConfirm().then(() => {
 | 
			
		||||
        config?.delListApi && config?.delListApi(ids)
 | 
			
		||||
        message.success(t('common.delSuccess'))
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  return {
 | 
			
		||||
    gridOptions,
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,6 @@ import enUS from 'vxe-table/lib/locale/lang/en-US'
 | 
			
		||||
import {
 | 
			
		||||
  // 全局对象
 | 
			
		||||
  VXETable,
 | 
			
		||||
 | 
			
		||||
  // 表格功能
 | 
			
		||||
  Filter,
 | 
			
		||||
  Edit,
 | 
			
		||||
@ -15,7 +14,6 @@ import {
 | 
			
		||||
  Export,
 | 
			
		||||
  Keyboard,
 | 
			
		||||
  Validator,
 | 
			
		||||
 | 
			
		||||
  // 可选组件
 | 
			
		||||
  Icon,
 | 
			
		||||
  Column,
 | 
			
		||||
@ -42,7 +40,6 @@ import {
 | 
			
		||||
  Modal,
 | 
			
		||||
  List,
 | 
			
		||||
  Pulldown,
 | 
			
		||||
 | 
			
		||||
  // 表格
 | 
			
		||||
  Table
 | 
			
		||||
} from 'vxe-table'
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,154 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="flex">
 | 
			
		||||
    <el-card class="w-1/2 dict" :gutter="12" shadow="always">
 | 
			
		||||
      <template #header>
 | 
			
		||||
        <div class="card-header">
 | 
			
		||||
          <span>字典分类</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </template>
 | 
			
		||||
      <Search
 | 
			
		||||
        :schema="DictTypeSchemas.allSchemas.searchSchema"
 | 
			
		||||
        @search="setTypeSearchParams"
 | 
			
		||||
        @reset="setTypeSearchParams"
 | 
			
		||||
      />
 | 
			
		||||
      <!-- 操作工具栏 -->
 | 
			
		||||
      <div class="mb-10px">
 | 
			
		||||
        <XButton
 | 
			
		||||
          type="primary"
 | 
			
		||||
          preIcon="ep:zoom-in"
 | 
			
		||||
          :title="t('action.add')"
 | 
			
		||||
          v-hasPermi="['system:dict:create']"
 | 
			
		||||
          @click="handleTypeCreate()"
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
      <!-- 列表 -->
 | 
			
		||||
      <Table
 | 
			
		||||
        @row-click="onClickType"
 | 
			
		||||
        :columns="DictTypeSchemas.allSchemas.tableColumns"
 | 
			
		||||
        :selection="false"
 | 
			
		||||
        :data="typeTableObject.tableList"
 | 
			
		||||
        :loading="typeTableObject.loading"
 | 
			
		||||
        :pagination="{
 | 
			
		||||
          total: typeTableObject.total
 | 
			
		||||
        }"
 | 
			
		||||
        :highlight-current-row="true"
 | 
			
		||||
        v-model:pageSize="typeTableObject.pageSize"
 | 
			
		||||
        v-model:currentPage="typeTableObject.currentPage"
 | 
			
		||||
        @register="typeRegister"
 | 
			
		||||
      >
 | 
			
		||||
        <template #status="{ row }">
 | 
			
		||||
          <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
        <template #action="{ row }">
 | 
			
		||||
          <XTextButton
 | 
			
		||||
            preIcon="ep:edit"
 | 
			
		||||
            :title="t('action.edit')"
 | 
			
		||||
            v-hasPermi="['system:dict:update']"
 | 
			
		||||
            @click="handleTypeUpdate(row)"
 | 
			
		||||
          />
 | 
			
		||||
          <XTextButton
 | 
			
		||||
            preIcon="ep:delete"
 | 
			
		||||
            :title="t('action.del')"
 | 
			
		||||
            v-hasPermi="['system:dict:delete']"
 | 
			
		||||
            @click="delTypeList(row.id, false)"
 | 
			
		||||
          />
 | 
			
		||||
        </template>
 | 
			
		||||
      </Table>
 | 
			
		||||
    </el-card>
 | 
			
		||||
    <el-card class="w-1/2 dict" style="margin-left: 10px" :gutter="12" shadow="hover">
 | 
			
		||||
      <template #header>
 | 
			
		||||
        <div class="card-header">
 | 
			
		||||
          <span>字典数据</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </template>
 | 
			
		||||
      <!-- 列表 -->
 | 
			
		||||
      <div v-if="!tableTypeSelect">
 | 
			
		||||
        <span>请从左侧选择</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div v-if="tableTypeSelect">
 | 
			
		||||
        <Search
 | 
			
		||||
          :schema="DictDataSchemas.allSchemas.searchSchema"
 | 
			
		||||
          @search="setDataSearchParams"
 | 
			
		||||
          @reset="setDataSearchParams"
 | 
			
		||||
        />
 | 
			
		||||
        <!-- 操作工具栏 -->
 | 
			
		||||
        <div class="mb-10px">
 | 
			
		||||
          <XButton
 | 
			
		||||
            type="primary"
 | 
			
		||||
            preIcon="ep:zoom-in"
 | 
			
		||||
            :title="t('action.add')"
 | 
			
		||||
            v-hasPermi="['system:dict:create']"
 | 
			
		||||
            @click="handleDataCreate()"
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
        <Table
 | 
			
		||||
          :columns="DictDataSchemas.allSchemas.tableColumns"
 | 
			
		||||
          :selection="false"
 | 
			
		||||
          :data="dataTableObject.tableList"
 | 
			
		||||
          :loading="dataTableObject.loading"
 | 
			
		||||
          :pagination="{
 | 
			
		||||
            total: dataTableObject.total
 | 
			
		||||
          }"
 | 
			
		||||
          v-model:pageSize="dataTableObject.pageSize"
 | 
			
		||||
          v-model:currentPage="dataTableObject.currentPage"
 | 
			
		||||
          @register="dataRegister"
 | 
			
		||||
        >
 | 
			
		||||
          <template #status="{ row }">
 | 
			
		||||
            <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
 | 
			
		||||
          </template>
 | 
			
		||||
          <template #action="{ row }">
 | 
			
		||||
            <XTextButton
 | 
			
		||||
              v-hasPermi="['system:dict:update']"
 | 
			
		||||
              preIcon="ep:edit"
 | 
			
		||||
              :title="t('action.edit')"
 | 
			
		||||
              @click="handleDataUpdate(row)"
 | 
			
		||||
            />
 | 
			
		||||
            <XTextButton
 | 
			
		||||
              v-hasPermi="['system:dict:delete']"
 | 
			
		||||
              preIcon="ep:delete"
 | 
			
		||||
              :title="t('action.del')"
 | 
			
		||||
              @click="delDataList(row.id, false)"
 | 
			
		||||
            />
 | 
			
		||||
          </template>
 | 
			
		||||
        </Table>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-card>
 | 
			
		||||
    <XModal id="dictModel" v-model="dialogVisible" :title="dialogTitle">
 | 
			
		||||
      <template #default>
 | 
			
		||||
        <Form
 | 
			
		||||
          v-if="['typeCreate', 'typeUpdate'].includes(actionType)"
 | 
			
		||||
          :schema="DictTypeSchemas.allSchemas.formSchema"
 | 
			
		||||
          :rules="DictTypeSchemas.dictTypeRules"
 | 
			
		||||
          ref="typeFormRef"
 | 
			
		||||
        />
 | 
			
		||||
        <Form
 | 
			
		||||
          v-if="['dataCreate', 'dataUpdate'].includes(actionType)"
 | 
			
		||||
          :schema="DictDataSchemas.allSchemas.formSchema"
 | 
			
		||||
          :rules="DictDataSchemas.dictDataRules"
 | 
			
		||||
          ref="dataFormRef"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
      <!-- 操作按钮 -->
 | 
			
		||||
      <template #footer>
 | 
			
		||||
        <XButton
 | 
			
		||||
          v-if="['typeCreate', 'typeUpdate'].includes(actionType)"
 | 
			
		||||
          type="primary"
 | 
			
		||||
          :title="t('action.save')"
 | 
			
		||||
          :loading="actionLoading"
 | 
			
		||||
          @click="submitTypeForm"
 | 
			
		||||
        />
 | 
			
		||||
        <XButton
 | 
			
		||||
          v-if="['dataCreate', 'dataUpdate'].includes(actionType)"
 | 
			
		||||
          type="primary"
 | 
			
		||||
          :title="t('action.save')"
 | 
			
		||||
          :loading="actionLoading"
 | 
			
		||||
          @click="submitDataForm"
 | 
			
		||||
        />
 | 
			
		||||
        <XButton :title="t('dialog.close')" @click="dialogVisible = false" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </XModal>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ref, unref, onMounted } from 'vue'
 | 
			
		||||
import { DICT_TYPE } from '@/utils/dict'
 | 
			
		||||
@ -148,155 +299,3 @@ onMounted(async () => {
 | 
			
		||||
  typeTableObject.tableList[0] && onClickType(typeTableObject.tableList[0])
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="flex">
 | 
			
		||||
    <el-card class="w-1/2 dict" :gutter="12" shadow="always">
 | 
			
		||||
      <template #header>
 | 
			
		||||
        <div class="card-header">
 | 
			
		||||
          <span>字典分类</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </template>
 | 
			
		||||
      <Search
 | 
			
		||||
        :schema="DictTypeSchemas.allSchemas.searchSchema"
 | 
			
		||||
        @search="setTypeSearchParams"
 | 
			
		||||
        @reset="setTypeSearchParams"
 | 
			
		||||
      />
 | 
			
		||||
      <!-- 操作工具栏 -->
 | 
			
		||||
      <div class="mb-10px">
 | 
			
		||||
        <el-button type="primary" v-hasPermi="['system:dict:create']" @click="handleTypeCreate">
 | 
			
		||||
          <Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }}
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
      <!-- 列表 -->
 | 
			
		||||
      <Table
 | 
			
		||||
        @row-click="onClickType"
 | 
			
		||||
        :columns="DictTypeSchemas.allSchemas.tableColumns"
 | 
			
		||||
        :selection="false"
 | 
			
		||||
        :data="typeTableObject.tableList"
 | 
			
		||||
        :loading="typeTableObject.loading"
 | 
			
		||||
        :pagination="{
 | 
			
		||||
          total: typeTableObject.total
 | 
			
		||||
        }"
 | 
			
		||||
        :highlight-current-row="true"
 | 
			
		||||
        v-model:pageSize="typeTableObject.pageSize"
 | 
			
		||||
        v-model:currentPage="typeTableObject.currentPage"
 | 
			
		||||
        @register="typeRegister"
 | 
			
		||||
      >
 | 
			
		||||
        <template #status="{ row }">
 | 
			
		||||
          <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
        <template #action="{ row }">
 | 
			
		||||
          <el-button
 | 
			
		||||
            link
 | 
			
		||||
            type="primary"
 | 
			
		||||
            v-hasPermi="['system:dict:update']"
 | 
			
		||||
            @click="handleTypeUpdate(row)"
 | 
			
		||||
          >
 | 
			
		||||
            <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }}
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button
 | 
			
		||||
            link
 | 
			
		||||
            type="primary"
 | 
			
		||||
            v-hasPermi="['system:dict:delete']"
 | 
			
		||||
            @click="delTypeList(row.id, false)"
 | 
			
		||||
          >
 | 
			
		||||
            <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </Table>
 | 
			
		||||
    </el-card>
 | 
			
		||||
    <el-card class="w-1/2 dict" style="margin-left: 10px" :gutter="12" shadow="hover">
 | 
			
		||||
      <template #header>
 | 
			
		||||
        <div class="card-header">
 | 
			
		||||
          <span>字典数据</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </template>
 | 
			
		||||
      <!-- 列表 -->
 | 
			
		||||
      <div v-if="!tableTypeSelect">
 | 
			
		||||
        <span>请从左侧选择</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div v-if="tableTypeSelect">
 | 
			
		||||
        <Search
 | 
			
		||||
          :schema="DictDataSchemas.allSchemas.searchSchema"
 | 
			
		||||
          @search="setDataSearchParams"
 | 
			
		||||
          @reset="setDataSearchParams"
 | 
			
		||||
        />
 | 
			
		||||
        <!-- 操作工具栏 -->
 | 
			
		||||
        <div class="mb-10px">
 | 
			
		||||
          <el-button type="primary" v-hasPermi="['system:dict:create']" @click="handleDataCreate">
 | 
			
		||||
            <Icon icon="ep:zoom-in" class="mr-1px" /> {{ t('action.add') }}
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
        <Table
 | 
			
		||||
          :columns="DictDataSchemas.allSchemas.tableColumns"
 | 
			
		||||
          :selection="false"
 | 
			
		||||
          :data="dataTableObject.tableList"
 | 
			
		||||
          :loading="dataTableObject.loading"
 | 
			
		||||
          :pagination="{
 | 
			
		||||
            total: dataTableObject.total
 | 
			
		||||
          }"
 | 
			
		||||
          v-model:pageSize="dataTableObject.pageSize"
 | 
			
		||||
          v-model:currentPage="dataTableObject.currentPage"
 | 
			
		||||
          @register="dataRegister"
 | 
			
		||||
        >
 | 
			
		||||
          <template #status="{ row }">
 | 
			
		||||
            <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
 | 
			
		||||
          </template>
 | 
			
		||||
          <template #action="{ row }">
 | 
			
		||||
            <el-button
 | 
			
		||||
              link
 | 
			
		||||
              type="primary"
 | 
			
		||||
              v-hasPermi="['system:dict:update']"
 | 
			
		||||
              @click="handleDataUpdate(row)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }}
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              link
 | 
			
		||||
              type="primary"
 | 
			
		||||
              v-hasPermi="['system:dict:delete']"
 | 
			
		||||
              @click="delDataList(row.id, false)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </Table>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-card>
 | 
			
		||||
    <Dialog v-model="dialogVisible" :title="dialogTitle">
 | 
			
		||||
      <Form
 | 
			
		||||
        v-if="['typeCreate', 'typeUpdate'].includes(actionType)"
 | 
			
		||||
        :schema="DictTypeSchemas.allSchemas.formSchema"
 | 
			
		||||
        :rules="DictTypeSchemas.dictTypeRules"
 | 
			
		||||
        ref="typeFormRef"
 | 
			
		||||
      />
 | 
			
		||||
      <Form
 | 
			
		||||
        v-if="['dataCreate', 'dataUpdate'].includes(actionType)"
 | 
			
		||||
        :schema="DictDataSchemas.allSchemas.formSchema"
 | 
			
		||||
        :rules="DictDataSchemas.dictDataRules"
 | 
			
		||||
        ref="dataFormRef"
 | 
			
		||||
      />
 | 
			
		||||
      <!-- 操作按钮 -->
 | 
			
		||||
      <template #footer>
 | 
			
		||||
        <el-button
 | 
			
		||||
          v-if="['typeCreate', 'typeUpdate'].includes(actionType)"
 | 
			
		||||
          type="primary"
 | 
			
		||||
          :loading="actionLoading"
 | 
			
		||||
          @click="submitTypeForm"
 | 
			
		||||
        >
 | 
			
		||||
          {{ t('action.save') }}
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          v-if="['dataCreate', 'dataUpdate'].includes(actionType)"
 | 
			
		||||
          type="primary"
 | 
			
		||||
          :loading="actionLoading"
 | 
			
		||||
          @click="submitDataForm"
 | 
			
		||||
        >
 | 
			
		||||
          {{ t('action.save') }}
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
 | 
			
		||||
      </template>
 | 
			
		||||
    </Dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@ -60,9 +60,9 @@
 | 
			
		||||
    <template #footer>
 | 
			
		||||
      <XButton
 | 
			
		||||
        v-if="['create', 'update'].includes(actionType)"
 | 
			
		||||
        :loading="actionLoading"
 | 
			
		||||
        :title="t('action.save')"
 | 
			
		||||
        type="primary"
 | 
			
		||||
        :title="t('action.save')"
 | 
			
		||||
        :loading="actionLoading"
 | 
			
		||||
        @click="submitForm"
 | 
			
		||||
      />
 | 
			
		||||
      <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
 | 
			
		||||
@ -79,35 +79,31 @@ import { rules, allSchemas } from './post.data'
 | 
			
		||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
			
		||||
import { useMessage } from '@/hooks/web/useMessage'
 | 
			
		||||
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
 | 
			
		||||
import { VxeFormEvents, VxeGridInstance } from 'vxe-table'
 | 
			
		||||
import { VxeGridInstance } from 'vxe-table'
 | 
			
		||||
import { FormExpose } from '@/components/Form'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
const message = useMessage() // 消息弹窗
 | 
			
		||||
const xGrid = ref<VxeGridInstance>()
 | 
			
		||||
const formRef = ref<FormExpose>() // 表单 Ref
 | 
			
		||||
const dialogVisible = ref(false) // 是否显示弹出层
 | 
			
		||||
const dialogTitle = ref('edit') // 弹出层标题
 | 
			
		||||
const actionType = ref('') // 操作按钮的类型
 | 
			
		||||
const actionLoading = ref(false) // 按钮Loading
 | 
			
		||||
const xGrid = ref<VxeGridInstance>() // grid Ref
 | 
			
		||||
const formRef = ref<FormExpose>() // 表单 Ref
 | 
			
		||||
const detailRef = ref() // 详情 Ref
 | 
			
		||||
 | 
			
		||||
const { gridOptions } = useVxeGrid<PostVO>({
 | 
			
		||||
  allSchemas: allSchemas,
 | 
			
		||||
  getListApi: PostApi.getPostPageApi
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
// 设置标题
 | 
			
		||||
const setDialogTile = (type: string) => {
 | 
			
		||||
  dialogTitle.value = t('action.' + type)
 | 
			
		||||
  actionType.value = type
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
}
 | 
			
		||||
// ========== 详情相关 ==========
 | 
			
		||||
const detailRef = ref() // 详情 Ref
 | 
			
		||||
// 详情操作
 | 
			
		||||
const handleDetail = (row: PostVO) => {
 | 
			
		||||
  setDialogTile('detail')
 | 
			
		||||
  detailRef.value = row
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 新增操作
 | 
			
		||||
const handleCreate = () => {
 | 
			
		||||
  setDialogTile('create')
 | 
			
		||||
@ -115,6 +111,12 @@ const handleCreate = () => {
 | 
			
		||||
  unref(formRef)?.getElFormRef()?.resetFields()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 详情操作
 | 
			
		||||
const handleDetail = (row: PostVO) => {
 | 
			
		||||
  setDialogTile('detail')
 | 
			
		||||
  detailRef.value = row
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 修改操作
 | 
			
		||||
const handleUpdate = async (rowId: number) => {
 | 
			
		||||
  setDialogTile('update')
 | 
			
		||||
@ -122,6 +124,7 @@ const handleUpdate = async (rowId: number) => {
 | 
			
		||||
  const res = await PostApi.getPostApi(rowId)
 | 
			
		||||
  unref(formRef)?.setValues(res)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除操作
 | 
			
		||||
const handleDelete = async (rowId: number) => {
 | 
			
		||||
  message
 | 
			
		||||
@ -134,8 +137,9 @@ const handleDelete = async (rowId: number) => {
 | 
			
		||||
      xGrid.value?.commitProxy('query')
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 提交按钮
 | 
			
		||||
const submitForm: VxeFormEvents.Submit = async () => {
 | 
			
		||||
const submitForm = async () => {
 | 
			
		||||
  const elForm = unref(formRef)?.getElFormRef()
 | 
			
		||||
  if (!elForm) return
 | 
			
		||||
  elForm.validate(async (valid) => {
 | 
			
		||||
@ -151,7 +155,6 @@ const submitForm: VxeFormEvents.Submit = async () => {
 | 
			
		||||
          await PostApi.updatePostApi(data)
 | 
			
		||||
          message.success(t('common.updateSuccess'))
 | 
			
		||||
        }
 | 
			
		||||
        // 操作成功,重新加载列表
 | 
			
		||||
        dialogVisible.value = false
 | 
			
		||||
      } finally {
 | 
			
		||||
        actionLoading.value = false
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import { reactive } from 'vue'
 | 
			
		||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
			
		||||
import { required } from '@/utils/formRules'
 | 
			
		||||
import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
 | 
			
		||||
import { DICT_TYPE } from '@/utils/dict'
 | 
			
		||||
import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
 | 
			
		||||
// 表单校验
 | 
			
		||||
@ -17,7 +17,7 @@ const crudSchemas = reactive<VxeCrudSchema[]>([
 | 
			
		||||
  {
 | 
			
		||||
    title: t('common.index'),
 | 
			
		||||
    field: 'id',
 | 
			
		||||
    type: 'index',
 | 
			
		||||
    type: 'seq',
 | 
			
		||||
    form: {
 | 
			
		||||
      show: false
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user