pull/16/head
bimei 2023-03-06 18:20:20 +08:00
commit ece4cf2760
23 changed files with 235 additions and 54 deletions

19
.env.front Normal file
View File

@ -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
.env.static Normal file
View File

@ -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

View File

@ -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",

View File

@ -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,
() => {

View File

@ -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) {
console.log(val, 'val')
nextTick(() => {
resetFlowCondition()
})
}
},
{
immediate: true
}
)
</script>

View File

@ -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(() => {
//

View File

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

View File

@ -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) {

View File

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

View File

@ -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() //

View File

@ -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: '流程版本',

View File

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

View File

@ -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>

View File

@ -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)

View File

@ -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,

View File

@ -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],

View File

@ -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 () => {

View File

@ -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',

View File

@ -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]
})

View File

@ -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)
})
}
//

View File

@ -332,7 +332,6 @@ const getPostOptions = async () => {
const res = await listSimplePostsApi()
postOptions.value.push(...res)
}
const dataFormater = (val) => {
return deptFormater(deptOptions.value, val)
}
@ -409,15 +408,20 @@ const handleDetail = async (rowId: number) => {
//
const submitForm = async () => {
loading.value = true
//
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
@ -427,6 +431,8 @@ const submitForm = async () => {
await reload()
loading.value = false
}
}
})
}
//
const handleStatusChange = async (row: UserApi.UserVO) => {

View File

@ -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' },
{

1
types/global.d.ts vendored
View File

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