Forráskód Böngészése

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

bimei 2 éve
szülő
commit
ece4cf2760

+ 19 - 0
.env.front

@@ -0,0 +1,19 @@
+# 本地开发环境
+NODE_ENV=development
+
+VITE_DEV=true
+
+# 请求路径
+VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
+
+# 上传路径
+VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
+
+# 接口前缀
+VITE_API_BASEPATH=/dev-api
+
+# 接口地址
+VITE_API_URL=/admin-api
+
+# 打包路径
+VITE_BASE_PATH=/

+ 31 - 0
.env.static

@@ -0,0 +1,31 @@
+# 开发环境
+NODE_ENV=production
+
+VITE_DEV=false
+
+# 请求路径
+VITE_BASE_URL='http://localhost:48080'
+
+# 上传路径
+VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
+
+# 接口前缀
+VITE_API_BASEPATH=
+
+# 接口地址
+VITE_API_URL=/admin-api
+
+# 是否删除debugger
+VITE_DROP_DEBUGGER=true
+
+# 是否删除console.log
+VITE_DROP_CONSOLE=true
+
+# 是否sourcemap
+VITE_SOURCEMAP=false
+
+# 打包路径
+VITE_BASE_PATH=/admin-ui-vue3/
+
+# 输出路径
+VITE_OUT_DIR=dist-dev

+ 2 - 0
package.json

@@ -7,10 +7,12 @@
   "scripts": {
     "i": "pnpm install",
     "dev": "vite --mode base",
+    "front": "vite --mode front",
     "ts:check": "vue-tsc --noEmit",
     "build:pro": "node --max_old_space_size=8000 ./node_modules/vite/bin/vite.js build --mode pro",
     "build:dev": "node --max_old_space_size=8000 ./node_modules/vite/bin/vite.js build --mode dev",
     "build:test": "node --max_old_space_size=8000 ./node_modules/vite/bin/vite.js build --mode test",
+    "build:static": "node --max_old_space_size=8000 ./node_modules/vite/bin/vite.js build --mode static",
     "serve:pro": "vite preview --mode pro",
     "serve:dev": "vite preview --mode dev",
     "serve:test": "vite preview --mode test",

+ 7 - 10
src/components/XTable/src/XTable.vue

@@ -13,7 +13,6 @@ import { useDesign } from '@/hooks/web/useDesign'
 import { XTableProps } from './type'
 import { isBoolean, isFunction } from '@/utils/is'
 import styleCss from './style/dark.scss'
-
 import download from '@/utils/download'
 
 const { t } = useI18n()
@@ -26,14 +25,13 @@ const prefixCls = getPrefixCls('x-vxe-table')
 
 const attrs = useAttrs()
 const emit = defineEmits(['register'])
-
 const removeStyles = () => {
-  var filename = 'cssTheme'
+  const filename = 'cssTheme'
   //移除引入的文件名
-  var targetelement = 'style'
-  var targetattr = 'id'
-  var allsuspects = document.getElementsByTagName(targetelement)
-  for (var i = allsuspects.length; i >= 0; i--) {
+  const targetelement = 'style'
+  const targetattr = 'id'
+  let allsuspects = document.getElementsByTagName(targetelement)
+  for (let i = allsuspects.length; i >= 0; i--) {
     if (
       allsuspects[i] &&
       allsuspects[i].getAttribute(targetattr) != null &&
@@ -45,13 +43,12 @@ const removeStyles = () => {
   }
 }
 const reImport = () => {
-  var head = document.getElementsByTagName('head')[0]
-  var style = document.createElement('style')
+  let head = document.getElementsByTagName('head')[0]
+  let style = document.createElement('style')
   style.innerText = styleCss
   style.id = 'cssTheme'
   head.appendChild(style)
 }
-
 watch(
   () => appStore.getIsDark,
   () => {

+ 9 - 6
src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue

@@ -80,7 +80,8 @@ const resetFlowCondition = () => {
   if (
     bpmnElementSourceRef.value &&
     bpmnElementSourceRef.value.default &&
-    bpmnElementSourceRef.value.default.id === bpmnElement.value.id
+    bpmnElementSourceRef.value.default.id === bpmnElement.value.id &&
+    flowConditionForm.value.type == 'default'
   ) {
     // 默认
     flowConditionForm.value = { type: 'default' }
@@ -176,11 +177,13 @@ onBeforeUnmount(() => {
 watch(
   () => props.businessObject,
   (val) => {
-    if (val) {
-      nextTick(() => {
-        resetFlowCondition()
-      })
-    }
+    console.log(val, 'val')
+    nextTick(() => {
+      resetFlowCondition()
+    })
+  },
+  {
+    immediate: true
   }
 )
 </script>

+ 44 - 2
src/views/bpm/form/formEditor.vue

@@ -3,9 +3,21 @@
     <!-- 表单设计器 -->
     <fc-designer ref="designer" height="780px">
       <template #handle>
+        <XButton type="primary" title="生成JSON" @click="showJson" />
+        <XButton type="primary" title="生成Options" @click="showOption" />
         <XButton type="primary" :title="t('action.save')" @click="handleSave" />
       </template>
     </fc-designer>
+    <Dialog :title="dialogTitle" v-model="dialogVisible1" maxHeight="600">
+      <div ref="editor" v-if="dialogVisible1">
+        <XTextButton style="float: right" :title="t('common.copy')" @click="copy(formValue)" />
+        <el-scrollbar height="580">
+          <pre>
+            {{ formValue }}
+          </pre>
+        </el-scrollbar>
+      </div>
+    </Dialog>
     <!-- 表单保存的弹窗 -->
     <XModal v-model="dialogVisible" title="保存表单">
       <el-form ref="formRef" :model="formValues" :rules="formRules" label-width="80px">
@@ -48,13 +60,18 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { CommonStatusEnum } from '@/utils/constants'
 import * as FormApi from '@/api/bpm/form'
 import { encodeConf, encodeFields, setConfAndFields } from '@/utils/formCreate'
+import { useClipboard } from '@vueuse/core'
+
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息
 const { query } = useRoute() // 路由
 
 const designer = ref() // 表单设计器
-
+const type = ref(-1)
+const formValue = ref('')
+const dialogTitle = ref('')
 const dialogVisible = ref(false) // 弹窗是否展示
+const dialogVisible1 = ref(false) // 弹窗是否展示
 const dialogLoading = ref(false) // 弹窗的加载中
 const formRef = ref<FormInstance>()
 const formRules = reactive({
@@ -98,7 +115,32 @@ const submitForm = async () => {
     dialogLoading.value = false
   }
 }
-
+const showJson = () => {
+  openModel('生成JSON')
+  type.value = 0
+  formValue.value = designer.value.getRule()
+}
+const showOption = () => {
+  openModel('生成Options')
+  type.value = 1
+  formValue.value = designer.value.getOption()
+}
+const openModel = (title: string) => {
+  dialogVisible1.value = true
+  dialogTitle.value = title
+}
+/** 复制 **/
+const copy = async (text: string) => {
+  const { copy, copied, isSupported } = useClipboard({ source: text })
+  if (!isSupported) {
+    message.error(t('common.copyError'))
+  } else {
+    await copy()
+    if (unref(copied)) {
+      message.success(t('common.copySuccess'))
+    }
+  }
+}
 // ========== 初始化 ==========
 onMounted(() => {
   // 场景一:新增表单

+ 1 - 0
src/views/bpm/group/group.data.ts

@@ -16,6 +16,7 @@ const crudSchemas = reactive<VxeCrudSchema>({
   primaryType: 'id',
   primaryTitle: '编号',
   action: true,
+  searchSpan: 8,
   columns: [
     {
       title: '组名',

+ 7 - 1
src/views/bpm/oa/leave/detail.vue

@@ -2,6 +2,7 @@
   <ContentWrap>
     <!-- 详情 -->
     <Descriptions :schema="allSchemas.detailSchema" :data="formData" />
+    <el-button @click="routerReturn" type="primary">返回</el-button>
   </ContentWrap>
 </template>
 
@@ -9,7 +10,8 @@
 // 业务相关的 import
 import * as LeaveApi from '@/api/bpm/leave'
 import { allSchemas } from '@/views/bpm/oa/leave/leave.data'
-
+import { useRouter } from 'vue-router'
+const router = useRouter()
 const { query } = useRoute() // 查询参数
 const message = useMessage() // 消息弹窗
 
@@ -22,6 +24,10 @@ const formData = ref({
   reason: undefined
 })
 
+const routerReturn = () => {
+  router.back()
+}
+
 onMounted(() => {
   id.value = query.id
   if (!id.value) {

+ 1 - 0
src/views/bpm/oa/leave/leave.data.ts

@@ -16,6 +16,7 @@ const crudSchemas = reactive<VxeCrudSchema>({
   primaryTitle: '申请编号',
   action: true,
   actionWidth: '260',
+  searchSpan: 8,
   columns: [
     {
       title: t('common.status'),

+ 5 - 0
src/views/bpm/processInstance/create.vue

@@ -3,6 +3,10 @@
     <!-- 第一步,通过流程定义的列表,选择对应的流程 -->
     <div v-if="!selectProcessInstance">
       <XTable @register="registerTable">
+        <!-- 流程分类 -->
+        <template #category_default="{ row }">
+          <DictTag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="Number(row?.category)" />
+        </template>
         <template #version_default="{ row }">
           <el-tag v-if="row">v{{ row.version }}</el-tag>
         </template>
@@ -56,6 +60,7 @@ import * as DefinitionApi from '@/api/bpm/definition'
 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
 import { setConfAndFields2 } from '@/utils/formCreate'
 import { ApiAttrs } from '@form-create/element-ui/types/config'
+import { DICT_TYPE } from '@/utils/dict'
 
 const router = useRouter() // 路由
 const message = useMessage() // 消息

+ 6 - 1
src/views/bpm/processInstance/process.create.ts

@@ -14,7 +14,12 @@ const crudSchemas = reactive<VxeCrudSchema>({
       title: '流程分类',
       field: 'category',
       dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
-      dictClass: 'number'
+      dictClass: 'number',
+      table: {
+        slots: {
+          default: 'category_default'
+        }
+      }
     },
     {
       title: '流程版本',

+ 1 - 0
src/views/bpm/task/todo/todo.data.ts

@@ -7,6 +7,7 @@ const crudSchemas = reactive<VxeCrudSchema>({
   primaryKey: 'id',
   primaryType: null,
   action: true,
+  searchSpan: 8,
   columns: [
     {
       title: '任务编号',

+ 10 - 2
src/views/bpm/taskAssignRule/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap>
     <!-- 列表 -->
-    <XTable @register="registerTable">
+    <XTable @register="registerTable" ref="xGrid">
       <template #options_default="{ row }">
         <span :key="option" v-for="option in row.options">
           <el-tag>
@@ -145,11 +145,12 @@ import { listSimpleUserGroupsApi } from '@/api/bpm/userGroup'
 import { listSimpleDeptApi } from '@/api/system/dept'
 import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 import { handleTree, defaultProps } from '@/utils/tree'
-import { allSchemas, rules } from './taskAssignRule.data'
+import { allSchemas, rules, idShowActionClick } from './taskAssignRule.data'
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 const { query } = useRoute()
+const xGrid = ref()
 
 // ========== 列表相关 ==========
 
@@ -165,6 +166,8 @@ const taskAssignScriptDictDatas = getDictOptions(DICT_TYPE.BPM_TASK_ASSIGN_SCRIP
 const modelId = query.modelId
 // 流程定义的编号。如果 processDefinitionId 非空,则用于流程定义的查看,不支持配置
 const processDefinitionId = query.processDefinitionId
+let isShow = idShowActionClick(modelId)
+
 // 查询参数
 const queryParams = reactive({
   modelId: modelId,
@@ -346,5 +349,10 @@ onMounted(() => {
   listSimpleUserGroupsApi().then((data) => {
     userGroupOptions.value.push(...data)
   })
+  if (!isShow) {
+    setTimeout(() => {
+      xGrid.value.Ref.hideColumn('actionbtns')
+    }, 100)
+  }
 })
 </script>

+ 8 - 0
src/views/bpm/taskAssignRule/taskAssignRule.data.ts

@@ -43,4 +43,12 @@ const crudSchemas = reactive<VxeCrudSchema>({
     }
   ]
 })
+
+export const idShowActionClick = (modelId?: any) => {
+  if (modelId) {
+    return true
+  } else {
+    return false
+  }
+}
 export const { allSchemas } = useVxeCrudSchemas(crudSchemas)

+ 9 - 1
src/views/system/dept/dept.data.ts

@@ -6,7 +6,15 @@ const { t } = useI18n() // 国际化
 export const rules = reactive({
   name: [required],
   sort: [required],
-  email: [required],
+  // email: [required],
+  email: [
+    { required: true, message: t('profile.rules.mail'), trigger: 'blur' },
+    {
+      type: 'email',
+      message: t('profile.rules.truemail'),
+      trigger: ['blur', 'change']
+    }
+  ],
   phone: [
     {
       len: 11,

+ 11 - 1
src/views/system/mail/account/account.data.ts

@@ -1,8 +1,18 @@
 import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
 
+const { t } = useI18n() // 国际化
+
 // 表单校验
 export const rules = reactive({
-  mail: [required],
+  // mail: [required],
+  mail: [
+    { required: true, message: t('profile.rules.mail'), trigger: 'blur' },
+    {
+      type: 'email',
+      message: t('profile.rules.truemail'),
+      trigger: ['blur', 'change']
+    }
+  ],
   username: [required],
   password: [required],
   host: [required],

+ 8 - 8
src/views/system/role/index.vue

@@ -131,7 +131,6 @@
                 ref="treeRef"
                 node-key="id"
                 show-checkbox
-                :default-checked-keys="defaultCheckedKeys"
                 :check-strictly="!checkStrictly"
                 :props="defaultProps"
                 :data="treeOptions"
@@ -255,7 +254,6 @@ const dialogScopeVisible = ref(false)
 const dialogScopeTitle = ref('数据权限')
 const actionScopeType = ref('')
 const dataScopeDictDatas = ref()
-const defaultCheckedKeys = ref()
 // 选项
 const checkStrictly = ref(true)
 const treeNodeAll = ref(false)
@@ -268,13 +266,16 @@ const handleScope = async (type: string, row: RoleApi.RoleVO) => {
   dataScopeForm.id = row.id
   dataScopeForm.name = row.name
   dataScopeForm.code = row.code
+  actionScopeType.value = type
+  dialogScopeVisible.value = true
   if (type === 'menu') {
     const menuRes = await listSimpleMenusApi()
     treeOptions.value = handleTree(menuRes)
     const role = await PermissionApi.listRoleMenusApi(row.id)
     if (role) {
-      // treeRef.value!.setCheckedKeys(role as unknown as Array<number>)
-      defaultCheckedKeys.value = role
+      role?.forEach((item: any) => {
+        unref(treeRef)?.setChecked(item, true, false)
+      })
     }
   } else if (type === 'data') {
     const deptRes = await listSimpleDeptApi()
@@ -282,12 +283,11 @@ const handleScope = async (type: string, row: RoleApi.RoleVO) => {
     const role = await RoleApi.getRoleApi(row.id)
     dataScopeForm.dataScope = role.dataScope
     if (role.dataScopeDeptIds) {
-      // treeRef.value!.setCheckedKeys(role.dataScopeDeptIds as unknown as Array<number>, false)
-      defaultCheckedKeys.value = role.dataScopeDeptIds
+      role.dataScopeDeptIds?.forEach((item: any) => {
+        unref(treeRef)?.setChecked(item, true, false)
+      })
     }
   }
-  actionScopeType.value = type
-  dialogScopeVisible.value = true
 }
 // 保存权限
 const submitScope = async () => {

+ 10 - 3
src/views/system/role/role.data.ts

@@ -9,12 +9,19 @@ export const rules = reactive({
 })
 // CrudSchema
 const crudSchemas = reactive<VxeCrudSchema>({
-  primaryKey: 'id',
-  primaryTitle: '角色编号',
-  primaryType: 'seq',
+  // primaryKey: 'id',
+  // primaryTitle: '角色编号',
+  // primaryType: 'seq',
   action: true,
   actionWidth: '400px',
   columns: [
+    {
+      title: '角色编号',
+      field: 'id',
+      table: {
+        width: 200
+      }
+    },
     {
       title: '角色名称',
       field: 'name',

+ 18 - 0
src/views/system/tenant/tenant.data.ts

@@ -27,6 +27,24 @@ export const rules = reactive({
   contactMobile: [required],
   accountCount: [required],
   expireTime: [required],
+  username: [
+    required,
+    {
+      min: 4,
+      max: 30,
+      trigger: 'blur',
+      message: '用户名称长度为 4-30 个字符'
+    }
+  ],
+  password: [
+    required,
+    {
+      min: 4,
+      max: 16,
+      trigger: 'blur',
+      message: '密码长度为 4-16 位'
+    }
+  ],
   domain: [required],
   status: [required]
 })

+ 3 - 1
src/views/system/tenantPackage/index.vue

@@ -135,7 +135,9 @@ const handleUpdate = async (rowId: number) => {
   const res = await TenantPackageApi.getTenantPackageApi(rowId)
   unref(formRef)?.setValues(res)
   // 设置选中
-  unref(treeRef)?.setCheckedKeys(res.menuIds)
+  res.menuIds?.forEach((item: any) => {
+    unref(treeRef)?.setChecked(item, true, false)
+  })
 }
 
 // 提交按钮

+ 23 - 17
src/views/system/user/index.vue

@@ -332,7 +332,6 @@ const getPostOptions = async () => {
   const res = await listSimplePostsApi()
   postOptions.value.push(...res)
 }
-
 const dataFormater = (val) => {
   return deptFormater(deptOptions.value, val)
 }
@@ -409,24 +408,31 @@ const handleDetail = async (rowId: number) => {
 
 // 提交按钮
 const submitForm = async () => {
-  loading.value = true
   // 提交请求
-  try {
-    const data = unref(formRef)?.formModel as UserApi.UserVO
-    if (actionType.value === 'create') {
-      await UserApi.createUserApi(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await UserApi.updateUserApi(data)
-      message.success(t('common.updateSuccess'))
+  const elForm = unref(formRef)?.getElFormRef()
+  if (!elForm) return
+  elForm.validate(async (valid) => {
+    if (valid) {
+      try {
+        const data = unref(formRef)?.formModel as UserApi.UserVO
+        if (actionType.value === 'create') {
+          await UserApi.createUserApi(data)
+          loading.value = true
+          message.success(t('common.createSuccess'))
+        } else {
+          await UserApi.updateUserApi(data)
+          loading.value = true
+          message.success(t('common.updateSuccess'))
+        }
+        dialogVisible.value = false
+      } finally {
+        // unref(formRef)?.setSchema(allSchemas.formSchema)
+        // 刷新列表
+        await reload()
+        loading.value = false
+      }
     }
-    dialogVisible.value = false
-  } finally {
-    // unref(formRef)?.setSchema(allSchemas.formSchema)
-    // 刷新列表
-    await reload()
-    loading.value = false
-  }
+  })
 }
 // 改变用户状态操作
 const handleStatusChange = async (row: UserApi.UserVO) => {

+ 2 - 0
src/views/system/user/user.data.ts

@@ -5,6 +5,8 @@ const { t } = useI18n()
 export const rules = reactive({
   username: [required],
   nickname: [required],
+  password: [required],
+  deptId: [required],
   email: [
     { required: true, message: t('profile.rules.mail'), trigger: 'blur' },
     {

+ 0 - 1
types/global.d.ts

@@ -1,4 +1,3 @@
-import type { CSSProperties } from 'vue'
 declare global {
   declare interface Fn<T = any> {
     (...arg: T[]): T