pull/533/head
YunaiV 2024-08-26 21:58:12 +08:00
commit c3b210d2b5
35 changed files with 807 additions and 144 deletions

View File

@ -30,6 +30,6 @@ export const KeFuConversationApi = {
},
// 删除客服会话
deleteConversation: async (id: number) => {
return await request.get({ url: '/promotion/kefu-conversation/delete?id' + id })
return await request.delete({ url: `/promotion/kefu-conversation/delete?id=${id}`})
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

1
src/assets/svgs/send.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724297262365" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1396" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M707.91 103c16.28 0 29.522 13.007 29.897 29.195l0.009 0.706v111.878a29.96 29.96 0 0 1-0.898 7.3l171.177-0.001c16.28 0 29.522 13.007 29.897 29.195l0.008 0.706v637.12c0 16.278-13.01 29.518-29.2 29.893l-0.705 0.008H270.884c-16.28 0-29.522-13.007-29.897-29.195l-0.008-0.706V787.274c0-16.514 13.389-29.9 29.905-29.9 16.28 0 29.522 13.007 29.897 29.194l0.008 0.706v101.924h577.4V311.88h-577.4v88.787c0 16.278-13.009 29.518-29.2 29.893l-0.705 0.008c-16.28 0-29.522-13.008-29.897-29.195l-0.008-0.706V281.979c0-16.278 13.009-29.518 29.2-29.893l0.705-0.008h408.019a29.916 29.916 0 0 1-0.89-6.593l-0.008-0.706v-81.978H132.808v407.113h385.787L408.223 456.982c-11.36-11.624-11.329-30.143-0.066-41.729l0.554-0.555c11.625-11.358 30.147-11.327 41.734-0.066l0.555 0.554 161.028 164.762c11.244 11.504 11.344 29.793 0.362 41.42l-0.55 0.565-161.027 161.849c-11.648 11.707-30.583 11.757-42.292 0.11-11.524-11.461-11.754-29.979-0.657-41.723l0.546-0.563 111.319-111.89H102.905c-16.28 0-29.522-13.007-29.897-29.195l-0.008-0.705V132.9c0-16.278 13.01-29.518 29.2-29.893l0.705-0.008H707.91z" p-id="1397"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -165,6 +165,7 @@ $toolbar-position: -55px;
width: 80px;
height: 25px;
font-size: 12px;
color: #6a6a6a;
line-height: 25px;
text-align: center;
background: #fff;

View File

@ -13,9 +13,9 @@
class="mb-4px flex flex-col gap-4px border border-gray-2 border-rounded rounded border-solid p-8px"
>
<!-- 操作按钮区 -->
<div class="m--8px m-b-4px flex flex-row items-center justify-between bg-gray-1 p-8px">
<div class="m--8px m-b-4px flex flex-row items-center justify-between p-8px" style="background-color: var(--app-content-bg-color);">
<el-tooltip content="拖动排序">
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
<Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" style="color: #8a909c;" />
</el-tooltip>
<el-tooltip content="删除">
<Icon

View File

@ -7,26 +7,41 @@ const props = defineProps({
src: propTypes.string.def('')
})
const loading = ref(true)
const height = ref('')
const frameRef = ref<HTMLElement | null>(null)
const init = () => {
height.value = document.documentElement.clientHeight - 94.5 + 'px'
nextTick(() => {
loading.value = true
if (!frameRef.value) return
frameRef.value.onload = () => {
loading.value = false
}
onMounted(() => {
setTimeout(() => {
init()
}, 300)
})
}
onMounted(() => {
init()
})
watch(
() => props.src,
() => {
init()
}
)
</script>
<template>
<div v-loading="loading" :style="'height:' + height">
<div
v-loading="loading"
class="w-full h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-2px)]"
>
<iframe
ref="frameRef"
:src="props.src"
frameborder="no"
frameborder="0"
scrolling="auto"
style="width: 100%; height: 100%"
height="100%"
width="100%"
allowfullscreen="true"
webkitallowfullscreen="true"
mozallowfullscreen="true"
></iframe>
</div>
</template>

View File

@ -17,7 +17,7 @@ const title = computed(() => appStore.getTitle)
<template>
<div
:class="prefixCls"
class="h-[var(--app-footer-height)] bg-[var(--app-content-bg-color)] text-center leading-[var(--app-footer-height)] text-[var(--el-text-color-placeholder)] dark:bg-[var(--el-bg-color)]"
class="h-[var(--app-footer-height)] bg-[var(--app-content-bg-color)] text-center leading-[var(--app-footer-height)] text-[var(--el-text-color-placeholder)] dark:bg-[var(--el-bg-color)] overflow-hidden"
>
<span class="text-14px">Copyright ©2022-{{ title }}</span>
</div>

View File

@ -195,6 +195,16 @@ $prefix-cls: #{$namespace}-menu;
}
}
//
&__vertical {
:deep(.#{$elNamespace}-menu--vertical) {
&:not(.#{$elNamespace}-menu--collapse) .#{$elNamespace}-sub-menu__title,
.#{$elNamespace}-menu-item {
padding-right: 0;
}
}
}
//
&__horizontal {
height: calc(var(--top-tool-height)) !important;

View File

@ -139,7 +139,7 @@ export default defineComponent({
id={`${variables.namespace}-menu`}
class={[
prefixCls,
'relative bg-[var(--left-menu-bg-color)] top-1px layout-border__right',
'relative bg-[var(--left-menu-bg-color)] layout-border__right',
{
'w-[var(--tab-menu-max-width)]': !unref(collapse),
'w-[var(--tab-menu-min-width)]': unref(collapse)
@ -147,7 +147,7 @@ export default defineComponent({
]}
onMouseleave={mouseleave}
>
<ElScrollbar class="!h-[calc(100%-var(--tab-menu-collapse-height)-1px)]">
<ElScrollbar class="!h-[calc(100%-var(--tab-menu-collapse-height))]">
<div>
{() => {
return unref(tabRouters).map((v) => {
@ -199,7 +199,7 @@ export default defineComponent({
{
'!left-[var(--tab-menu-min-width)]': unref(collapse),
'!left-[var(--tab-menu-max-width)]': !unref(collapse),
'!w-[calc(var(--left-menu-max-width)+1px)]': unref(showMenu) || unref(fixedMenu),
'!w-[var(--left-menu-max-width)]': unref(showMenu) || unref(fixedMenu),
'!w-0': !unref(showMenu) && !unref(fixedMenu)
}
]}

View File

@ -280,7 +280,7 @@ watch(
</span>
<div class="flex-1 overflow-hidden">
<ElScrollbar ref="scrollbarRef" class="h-full" @scroll="scroll">
<div class="h-full flex">
<div class="h-[var(--tags-view-height)] flex">
<ContextMenu
v-for="item in visitedViews"
:key="item.fullPath"
@ -491,10 +491,10 @@ $prefix-cls: #{$namespace}-tags-view;
&::before {
position: absolute;
top: 1px;
top: 0;
left: 0;
width: 100%;
height: calc(100% - 1px);
height: 100%;
border-left: 1px solid var(--el-border-color);
content: '';
}
@ -502,10 +502,10 @@ $prefix-cls: #{$namespace}-tags-view;
&--first {
&::before {
position: absolute;
top: 1px;
top: 0;
left: 0;
width: 100%;
height: calc(100% - 1px);
height: 100%;
border-right: 1px solid var(--el-border-color);
border-left: none;
content: '';
@ -515,7 +515,7 @@ $prefix-cls: #{$namespace}-tags-view;
&__item {
position: relative;
top: 2px;
top: 3px;
height: calc(100% - 6px);
padding-right: 15px;
margin-left: 4px;
@ -523,6 +523,7 @@ $prefix-cls: #{$namespace}-tags-view;
cursor: pointer;
border: 1px solid #d9d9d9;
border-radius: 2px;
box-sizing: border-box;
&--close {
position: absolute;
@ -562,10 +563,11 @@ $prefix-cls: #{$namespace}-tags-view;
}
&__item--immerse {
top: 3px;
top: 2px;
height: calc(100% - 3px);
padding-right: 35px;
margin: 0 -10px;
border: 1px solid transparent;
border: none !important;
-webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='68' height='34' viewBox='0 0 68 34' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='m27,0c-7.99582,0 -11.95105,0.00205 -12,12l0,6c0,8.284 -0.48549,16.49691 -8.76949,16.49691l54.37857,-0.11145c-8.284,0 -8.60908,-8.10146 -8.60908,-16.38546l0,-6c0.11145,-12.08445 -4.38441,-12 -12,-12l-13,0z' fill='%23409eff'/%3E%3C/svg%3E")
12 27 15;

View File

@ -126,7 +126,7 @@ export const useRenderLayout = () => {
<ToolHeader class="flex-1"></ToolHeader>
</div>
<div class="absolute left-0 top-[var(--logo-height)+1px] h-[calc(100%-1px-var(--logo-height))] w-full flex">
<div class="absolute left-0 top-[var(--logo-height)] h-[calc(100%-var(--logo-height))] w-full flex">
<Menu class="relative layout-border__right !h-full"></Menu>
<div
class={[
@ -157,9 +157,9 @@ export const useRenderLayout = () => {
'layout-border__bottom absolute',
{
'!fixed top-0 left-0 z-10': fixedHeader.value,
'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)] mt-[calc(var(--logo-height)+1px)]':
'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)] mt-[var(--logo-height)]':
collapse.value && fixedHeader.value,
'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)] mt-[calc(var(--logo-height)+1px)]':
'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)] mt-[var(--logo-height)]':
!collapse.value && fixedHeader.value
}
]}
@ -190,24 +190,14 @@ export const useRenderLayout = () => {
<Menu class="h-[var(--top-tool-height)] flex-1 px-10px"></Menu>
<ToolHeader></ToolHeader>
</div>
<div
class={[
`${prefixCls}-content`,
'w-full',
{
'h-[calc(100%-var(--app-footer-height))]': !fixedHeader.value,
'h-[calc(100%-var(--tags-view-height)-var(--app-footer-height))]': fixedHeader.value
}
]}
>
<div class={[`${prefixCls}-content`, 'w-full h-[calc(100%-var(--top-tool-height))]']}>
<ElScrollbar
v-loading={pageLoading.value}
class={[
`${prefixCls}-content-scrollbar`,
{
'mt-[var(--tags-view-height)] !pb-[calc(var(--tags-view-height)+var(--app-footer-height))]':
fixedHeader.value,
'pb-[var(--app-footer-height)]': !fixedHeader.value
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
fixedHeader.value
}
]}
>
@ -216,7 +206,7 @@ export const useRenderLayout = () => {
class={[
'layout-border__bottom layout-border__top relative',
{
'!fixed w-full top-[calc(var(--top-tool-height)+1px)] left-0': fixedHeader.value
'!fixed w-full top-[var(--top-tool-height)] left-0': fixedHeader.value
}
]}
style="transition: width var(--transition-time-02), left var(--transition-time-02);"
@ -238,7 +228,7 @@ export const useRenderLayout = () => {
<ToolHeader class="flex-1"></ToolHeader>
</div>
<div class="absolute left-0 top-[var(--logo-height)] h-[calc(100%-var(--logo-height))] w-[calc(100%-2px)] flex">
<div class="absolute left-0 top-[var(--logo-height)] h-[calc(100%-var(--logo-height))] w-full flex">
<TabMenu></TabMenu>
<div
class={[
@ -270,18 +260,16 @@ export const useRenderLayout = () => {
{tagsView.value ? (
<TagsView
class={[
'relative layout-border__bottom layout-border__top',
'relative layout-border__bottom',
{
'!fixed top-0 left-0 z-10': fixedHeader.value,
'w-[calc(100%-var(--tab-menu-min-width))] !left-[var(--tab-menu-min-width)] mt-[var(--logo-height)]':
collapse.value && fixedHeader.value,
collapse.value && fixedHeader.value && !fixedMenu.value,
'w-[calc(100%-var(--tab-menu-max-width))] !left-[var(--tab-menu-max-width)] mt-[var(--logo-height)]':
!collapse.value && fixedHeader.value,
'!fixed top-0 !left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] z-10':
fixedHeader.value && fixedMenu.value,
'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] !left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
!collapse.value && fixedHeader.value && !fixedMenu.value,
'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] !left-[calc(var(--tab-menu-min-width)+var(--left-menu-max-width))] mt-[var(--logo-height)]':
collapse.value && fixedHeader.value && fixedMenu.value,
'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] !left-[var(--tab-menu-max-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] !left-[calc(var(--tab-menu-max-width)+var(--left-menu-max-width))] mt-[var(--logo-height)]':
!collapse.value && fixedHeader.value && fixedMenu.value
}
]}

View File

@ -56,20 +56,20 @@ export const defaultShortcuts = [
*
* @param date new Date()
* @param format
* @description format `YYYY-mm、YYYY-mm-dd`
* @description format "YYYY-mm-dd HH:MM:SS QQQQ"
* @description format "YYYY-mm-dd HH:MM:SS WWW"
* @description format "YYYY-mm-dd HH:MM:SS ZZZ"
* @description format + + "YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ"
* @description format `YYYY-MM、YYYY-MM-DD`
* @description format "YYYY-MM-DD HH:mm:ss QQQQ"
* @description format "YYYY-MM-DD HH:mm:ss WWW"
* @description format "YYYY-MM-DD HH:mm:ss ZZZ"
* @description format + + "YYYY-MM-DD HH:mm:ss WWW QQQQ ZZZ"
* @returns
*/
export function formatDate(date: Date, format?: string): string {
// 日期不存在,则返回空
if (!date) {
return '';
return ''
}
// 日期存在,则进行格式化
return date ? dayjs(date).format(format ?? 'YYYY-MM-DD HH:mm:ss') : '';
return date ? dayjs(date).format(format ?? 'YYYY-MM-DD HH:mm:ss') : ''
}
/**
@ -110,7 +110,7 @@ export function getWeek(dateTime: Date): number {
* @description param 3 60 * 60* 24 * 1000 * 3
* @returns
*/
export function formatPast(param: string | Date, format = 'YYYY-mm-dd HH:MM:SS'): string {
export function formatPast(param: string | Date, format = 'YYYY-MM-DD HH:mm:ss'): string {
// 传入格式处理、存储转换值
let t: any, s: number
// 获取js 时间戳

View File

@ -0,0 +1,588 @@
<template>
<ContentWrap :bodyStyle="{ padding: '10px 20px' }" class="position-relative">
<!-- TODO @GoldenZqqq建议 svgs 里面新建一个 bpm把相关的图标放进去哈 -->
<Icon
class="!position-fixed right-80px"
:size="130"
:icon="`svg-icon:audit${processInstance.status}`"
/>
<div class="text-#878c93">编号{{ id }}</div>
<el-divider class="!my-8px" />
<div class="flex items-center gap-5 mb-10px">
<div class="text-26px font-bold mb-5px">{{ processInstance.name }}</div>
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="processInstance.status" />
</div>
<div class="flex items-center gap-5 mb-10px text-13px">
<div class="bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600">
<img class="rounded-full h-28px" src="@/assets/imgs/avatar.jpg" alt="" />
{{ processInstance?.startUser?.nickname }}
</div>
<div class="text-#878c93"> {{ formatDate(processInstance.startTime) }} 提交 </div>
</div>
<el-tabs>
<!-- 表单信息 -->
<el-tab-pane label="表单信息">
<el-row :gutter="10">
<el-col :span="18" class="!flex !flex-col formCol">
<!-- 表单信息 -->
<div v-loading="processInstanceLoading" class="form-box flex flex-col mb-30px flex-1">
<!-- 情况一流程表单 -->
<el-col
v-if="processInstance?.processDefinition?.formType === 10"
:offset="6"
:span="16"
>
<form-create
v-model="detailForm.value"
v-model:api="fApi"
:option="detailForm.option"
:rule="detailForm.rule"
/>
</el-col>
<!-- 情况二业务表单 -->
<div v-if="processInstance?.processDefinition?.formType === 20">
<BusinessFormComponent :id="processInstance.businessKey" />
</div>
</div>
<!-- TODO @GoldenZqqq可以把下面 runningTask 拆一个小组件么 -->
<el-affix target=".formCol" position="bottom" class="h-50px" v-if="runningTask?.id">
<el-divider class="!mb-8px !mt-0" />
<div
class="pl-50px text-14px flex items-center color-#32373c dark:color-#fff font-bold btn-container"
>
<el-popover :visible="passVisible" placement="top-end" :width="500" trigger="click">
<template #reference>
<el-button plain type="success" @click="openPopover('1')">
<Icon icon="ep:select" />&nbsp; 通过
</el-button>
</template>
<div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
<el-form
label-position="top"
class="mb-auto"
ref="formRef"
:model="auditForm"
:rules="auditRule"
label-width="100px"
>
<el-form-item
v-if="processInstance && processInstance.startUser"
label="流程发起人"
>
{{ processInstance?.startUser.nickname }}
<el-tag size="small" type="info" class="ml-8px">
{{ processInstance?.startUser.deptName }}
</el-tag>
</el-form-item>
<el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
<template #header>
<span class="el-icon-picture-outline">
填写表单{{ runningTask?.formName }}
</span>
</template>
<form-create
v-model="approveForm.value"
v-model:api="approveFormFApi"
:option="approveForm.option"
:rule="approveForm.rule"
/>
</el-card>
<el-form-item label="审批建议" prop="reason">
<el-input
v-model="auditForm.reason"
placeholder="请输入审批建议"
type="textarea"
/>
</el-form-item>
<el-form-item label="抄送人" prop="copyUserIds">
<el-select
v-model="auditForm.copyUserIds"
multiple
placeholder="请选择抄送人"
>
<el-option
v-for="itemx in userOptions"
:key="itemx.id"
:label="itemx.nickname"
:value="itemx.id"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
:disabled="formLoading"
type="success"
@click="handleAudit(true)"
>
通过
</el-button>
<el-button @click="passVisible = false"> 取消 </el-button>
</el-form-item>
</el-form>
</div>
</el-popover>
<el-popover
:visible="rejectVisible"
placement="top-end"
:width="500"
trigger="click"
>
<template #reference>
<el-button class="mr-20px" plain type="danger" @click="openPopover('2')">
<Icon icon="ep:close" />&nbsp; 拒绝
</el-button>
</template>
<div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
<el-form
label-position="top"
class="mb-auto"
ref="formRef"
:model="auditForm"
:rules="auditRule"
label-width="100px"
>
<el-form-item
v-if="processInstance && processInstance.startUser"
label="流程发起人"
>
{{ processInstance?.startUser.nickname }}
<el-tag size="small" type="info" class="ml-8px">
{{ processInstance?.startUser.deptName }}
</el-tag>
</el-form-item>
<el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
<template #header>
<span class="el-icon-picture-outline">
填写表单{{ runningTask?.formName }}
</span>
</template>
<form-create
v-model="approveForm.value"
v-model:api="approveFormFApi"
:option="approveForm.option"
:rule="approveForm.rule"
/>
</el-card>
<el-form-item label="审批建议" prop="reason">
<el-input
v-model="auditForm.reason"
placeholder="请输入审批建议"
type="textarea"
/>
</el-form-item>
<el-form-item label="抄送人" prop="copyUserIds">
<el-select
v-model="auditForm.copyUserIds"
multiple
placeholder="请选择抄送人"
>
<el-option
v-for="itemx in userOptions"
:key="itemx.id"
:label="itemx.nickname"
:value="itemx.id"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
:disabled="formLoading"
type="danger"
@click="handleAudit(false)"
>
拒绝
</el-button>
<el-button @click="rejectVisible = false"> 取消 </el-button>
</el-form-item>
</el-form>
</div>
</el-popover>
<div @click="handleSend"> <Icon :size="14" icon="svg-icon:send" />&nbsp;抄送 </div>
<div @click="openTaskUpdateAssigneeForm">
<Icon :size="14" icon="fa:share-square-o" />&nbsp;转交
</div>
<div @click="handleDelegate">
<Icon :size="14" icon="ep:position" />&nbsp;委派
</div>
<div @click="handleSign"> <Icon :size="14" icon="ep:plus" />&nbsp;加签 </div>
<div @click="handleBack"> <Icon :size="14" icon="fa:mail-reply" />&nbsp;退回 </div>
</div>
</el-affix>
<!-- TODO @GoldenZqqq后续这个也拆个小组件出来 -->
</el-col>
<el-col :span="6">
<el-timeline class="pt-20px">
<el-timeline-item type="primary" size="large">
<div class="flex flex-col items-start gap-2">
<div class="font-bold"> 发起人{{ processInstance?.startUser?.nickname }}</div>
<el-tag type="success">发起</el-tag>
<div class="text-#a5a5a5 text-12px">
发起时间{{ formatDate(processInstance.startTime) }}
</div>
</div>
</el-timeline-item>
<el-timeline-item
v-for="(activity, index) in tasks"
:key="index"
type="primary"
size="large"
>
<div class="flex flex-col items-start gap-2">
<div class="font-bold"> 审批人{{ activity.assigneeUser?.nickname }}</div>
<dict-tag
:type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value="activity.status"
/>
<!-- TODO暂无该字段 -->
<div v-if="activity.receiveTime" class="text-#a5a5a5 text-12px">
接收时间{{ formatDate(activity.receiveTime) }}
</div>
<div v-if="activity.createTime" class="text-#a5a5a5 text-12px">
审批时间{{ formatDate(activity.createTime) }}
</div>
<div v-if="activity.opinion" class="text-#a5a5a5 text-12px w-100%">
<div class="mb-5px">审批意见</div>
<div
class="w-100% border-1px border-#a5a5a5 border-dashed rounded py-5px px-15px text-#2d2d2d"
>
{{ activity.opinion }}
</div>
</div>
</div>
<!-- 该节点用户的头像 -->
<!-- <template #dot>
<img :src="activity?.avatar" alt="" />
</template> -->
</el-timeline-item>
</el-timeline>
</el-col>
</el-row>
</el-tab-pane>
<!-- 流程图 -->
<el-tab-pane label="流程图">
<!-- 高亮流程图 -->
<ProcessInstanceBpmnViewer
:id="`${id}`"
:bpmn-xml="bpmnXml"
:loading="processInstanceLoading"
:process-instance="processInstance"
:tasks="tasks"
/>
</el-tab-pane>
<!-- 流转记录 -->
<el-tab-pane label="流转记录">
<!-- 审批记录 -->
<ProcessInstanceTaskList
:loading="tasksLoad"
:process-instance="processInstance"
:tasks="tasks"
@refresh="getTaskList"
/>
</el-tab-pane>
<!-- 流转评论 -->
<el-tab-pane label="流转评论"> 流转评论 </el-tab-pane>
</el-tabs>
<!-- 弹窗转派审批人 -->
<TaskTransferForm ref="taskTransferFormRef" @success="getDetail" />
<!-- 弹窗回退节点 -->
<TaskReturnForm ref="taskReturnFormRef" @success="getDetail" />
<!-- 弹窗委派将任务委派给别人处理处理完成后会重新回到原审批人手中-->
<TaskDelegateForm ref="taskDelegateForm" @success="getDetail" />
<!-- 弹窗加签当前任务审批人为A向前加签选了一个C则需要C先审批然后再是A审批向后加签BA审批完需要B再审批完才算完成这个任务节点 -->
<TaskSignCreateForm ref="taskSignCreateFormRef" @success="getDetail" />
</ContentWrap>
</template>
<script lang="ts" setup>
import { formatDate } from '@/utils/formatTime'
import { DICT_TYPE } from '@/utils/dict'
import { useUserStore } from '@/store/modules/user'
import { setConfAndFields2 } from '@/utils/formCreate'
import type { ApiAttrs } from '@form-create/element-ui/types/config'
import * as DefinitionApi from '@/api/bpm/definition'
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import * as TaskApi from '@/api/bpm/task'
import ProcessInstanceBpmnViewer from './ProcessInstanceBpmnViewer.vue'
import ProcessInstanceTaskList from './ProcessInstanceTaskList.vue'
import TaskReturnForm from './dialog/TaskReturnForm.vue'
import TaskDelegateForm from './dialog/TaskDelegateForm.vue'
import TaskTransferForm from './dialog/TaskTransferForm.vue'
import TaskSignCreateForm from './dialog/TaskSignCreateForm.vue'
import { registerComponent } from '@/utils/routerHelper'
import { isEmpty } from '@/utils/is'
import * as UserApi from '@/api/system/user'
defineOptions({ name: 'BpmProcessInstanceDetail' })
const { query } = useRoute() //
const message = useMessage() //
const { proxy } = getCurrentInstance() as any
const userId = useUserStore().getUser.id //
const id = query.id as unknown as string //
const processInstanceLoading = ref(false) //
const formLoading = ref(false) //
const passVisible = ref(false) //
const rejectVisible = ref(false) //
const processInstance = ref<any>({}) //
const bpmnXml = ref('') // BPMN XML
const tasksLoad = ref(true) //
const tasks = ref<any[]>([]) //
// ========== ==========
const runningTask = ref<any>({}) //
const formRef = ref()
const auditForm = ref<any>({}) //
const auditRule = reactive({
reason: [{ required: true, message: '审批建议不能为空', trigger: 'blur' }]
})
const approveForm = ref<any>({}) //
const approveFormFApi = ref<any>({}) // approveForms fAPi
// ========== ==========
const fApi = ref<ApiAttrs>() //
const detailForm = ref({
rule: [],
option: {},
value: {}
}) //
/** 监听 approveFormFApis实现它对应的 form-create 初始化后,隐藏掉对应的表单提交按钮 */
watch(
() => approveFormFApi.value,
(val) => {
val?.btn?.show(false)
val?.resetBtn?.show(false)
},
{
deep: true
}
)
/** 处理审批通过和不通过的操作 */
const handleAudit = async (pass) => {
formLoading.value = true
try {
const auditFormRef = proxy.$refs['formRef']
// 1.2
const elForm = unref(auditFormRef)
if (!elForm) return
const valid = await elForm.validate()
if (!valid) return
// 2.1
const data = {
id: runningTask.value.id,
reason: auditForm.value.reason,
copyUserIds: auditForm.value.copyUserIds
}
if (pass) {
// approveForm + data
const formCreateApi = approveFormFApi.value
if (Object.keys(formCreateApi)?.length > 0) {
await formCreateApi.validate()
// @ts-ignore
data.variables = approveForm.value.value
}
await TaskApi.approveTask(data)
message.success('审批通过成功')
} else {
await TaskApi.rejectTask(data)
message.success('审批不通过成功')
}
// 2.2
getDetail()
} finally {
formLoading.value = false
}
}
/** 转派审批人 */
const taskTransferFormRef = ref()
const openTaskUpdateAssigneeForm = () => {
taskTransferFormRef.value.open(runningTask.value.id)
}
/** 处理审批退回的操作 */
const taskDelegateForm = ref()
const handleDelegate = async () => {
taskDelegateForm.value.open(runningTask.value.id)
}
/** 处理审批退回的操作 */
const taskReturnFormRef = ref()
const handleBack = async () => {
taskReturnFormRef.value.open(runningTask.value.id)
}
/** 处理审批加签的操作 */
const taskSignCreateFormRef = ref()
const handleSign = async () => {
taskSignCreateFormRef.value.open(runningTask.value.id)
}
/** 获得详情 */
const getDetail = () => {
// 1.
getProcessInstance()
// 2.
getTaskList()
}
/** 加载流程实例 */
const BusinessFormComponent = ref<any>(null) //
const getProcessInstance = async () => {
try {
processInstanceLoading.value = true
const data = await ProcessInstanceApi.getProcessInstance(id)
if (!data) {
message.error('查询不到流程信息!')
return
}
processInstance.value = data
//
const processDefinition = data.processDefinition
if (processDefinition.formType === 10) {
setConfAndFields2(
detailForm,
processDefinition.formConf,
processDefinition.formFields,
data.formVariables
)
nextTick().then(() => {
fApi.value?.btn.show(false)
fApi.value?.resetBtn.show(false)
fApi.value?.disabled(true)
})
} else {
// data.processDefinition.formCustomViewPath /crm/contract/detail/index.vue
BusinessFormComponent.value = registerComponent(data.processDefinition.formCustomViewPath)
}
//
bpmnXml.value = (await DefinitionApi.getProcessDefinition(processDefinition.id))?.bpmnXml
} finally {
processInstanceLoading.value = false
}
}
/** 加载任务列表 */
const getTaskList = async () => {
runningTask.value = {}
auditForm.value = {}
approveForm.value = {}
approveFormFApi.value = {}
try {
//
tasksLoad.value = true
const data = await TaskApi.getTaskListByProcessInstanceId(id)
tasks.value = []
// 1.1
data.forEach((task) => {
if (task.status !== 4) {
tasks.value.push(task)
}
})
// 1.2
tasks.value.sort((a, b) => {
//
if (a.endTime && b.endTime) {
return b.endTime - a.endTime
} else if (a.endTime) {
return 1
} else if (b.endTime) {
return -1
//
} else {
return b.createTime - a.createTime
}
})
//
loadRunningTask(tasks.value)
} finally {
tasksLoad.value = false
}
}
/**
* 设置 runningTasks 中的任务
*/
const loadRunningTask = (tasks) => {
tasks.forEach((task) => {
if (!isEmpty(task.children)) {
loadRunningTask(task.children)
}
// 2.1
if (task.status !== 1 && task.status !== 6) {
return
}
// 2.2
if (!task.assigneeUser || task.assigneeUser.id !== userId) {
return
}
// 2.3
runningTask.value = { ...task }
auditForm.value = {
reason: '',
copyUserIds: []
}
// 2.4 approve
if (task.formId && task.formConf) {
const tempApproveForm = {}
setConfAndFields2(tempApproveForm, task.formConf, task.formFields, task.formVariables)
approveForm.value = tempApproveForm
} else {
approveForm.value = {} //
}
})
}
/* 抄送 TODO */
const handleSend = () => {}
const openPopover = (flag) => {
passVisible.value = false
rejectVisible.value = false
formRef.value.resetFields()
flag === '1' ? (passVisible.value = true) : (rejectVisible.value = true)
}
/** 初始化 */
const userOptions = ref<UserApi.UserVO[]>([]) //
onMounted(async () => {
getDetail()
//
userOptions.value = await UserApi.getSimpleUserList()
})
</script>
<style lang="scss" scoped>
.form-box {
:deep(.el-card) {
border: none;
}
}
:deep(.el-affix--fixed) {
background-color: var(--el-bg-color);
}
.btn-container {
> div {
margin: 0 15px;
cursor: pointer;
display: flex;
align-items: center;
&:hover {
color: #6db5ff;
}
}
}
</style>

View File

@ -2,8 +2,8 @@
<doc-alert title="数据库 MyBatis" url="https://doc.iocoder.cn/mybatis/" />
<doc-alert title="多数据源(读写分离)" url="https://doc.iocoder.cn/dynamic-datasource/" />
<ContentWrap>
<IFrame v-if="!loading" :src="url" />
<ContentWrap :bodyStyle="{ padding: '0px' }" class="!mb-0">
<IFrame v-if="!loading" v-loading="loading" :src="url" />
</ContentWrap>
</template>
<script lang="ts" setup>

View File

@ -1,7 +1,7 @@
<template>
<doc-alert title="服务监控" url="https://doc.iocoder.cn/server-monitor/" />
<ContentWrap>
<ContentWrap :bodyStyle="{ padding: '0px' }" class="!mb-0">
<IFrame v-if="!loading" v-loading="loading" :src="src" />
</ContentWrap>
</template>

View File

@ -1,7 +1,7 @@
<template>
<doc-alert title="服务监控" url="https://doc.iocoder.cn/server-monitor/" />
<ContentWrap>
<ContentWrap :bodyStyle="{ padding: '0px' }" class="!mb-0">
<IFrame v-if="!loading" v-loading="loading" :src="src" />
</ContentWrap>
</template>

View File

@ -1,8 +1,8 @@
<template>
<doc-alert title="接口文档" url="https://doc.iocoder.cn/api-doc/" />
<ContentWrap>
<IFrame :src="src" />
<ContentWrap :bodyStyle="{ padding: '0px' }" class="!mb-0">
<IFrame v-if="!loading" v-loading="loading" :src="src" />
</ContentWrap>
</template>
<script lang="ts" setup>

View File

@ -29,6 +29,17 @@
</el-table-column>
<el-table-column align="center" label="销量" min-width="90" prop="salesCount" />
<el-table-column align="center" label="库存" min-width="90" prop="stock" />
<el-table-column v-if="spuData.length > 1 && isDelete" align="center" label="操作" min-width="90" >
<template #default="scope">
<el-button
type="primary"
link
@click="deleteSpu(scope.row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script generic="T extends Spu" lang="ts" setup>
@ -40,10 +51,13 @@ import { SpuProperty } from '@/views/mall/promotion/components/index'
defineOptions({ name: 'PromotionSpuAndSkuList' })
const message = useMessage() //
const props = defineProps<{
spuList: T[]
ruleConfig: RuleConfig[]
spuPropertyListP: SpuProperty<T>[]
isDelete?: boolean //spu
}>()
const spuData = ref<Spu[]>([]) // spu
@ -77,6 +91,19 @@ const imagePreview = (imgUrl: string) => {
})
}
//
const emits = defineEmits<{
(e: 'delete', spuId: number): void
}>()
/** 多选时可以删除spu **/
const deleteSpu = async (spuId: number) => {
await message.confirm('是否删除商品编号为' + spuId + '的数据?')
let index = spuData.value.findIndex((item) => item.id == spuId)
spuData.value.splice(index,1);
emits('delete',spuId)
}
/**
* 将传进来的值赋值给 skuList
*/

View File

@ -19,6 +19,8 @@
:rule-config="ruleConfig"
:spu-list="spuList"
:spu-property-list-p="spuPropertyList"
:isDelete="true"
@delete="deleteSpu"
>
<el-table-column align="center" label="优惠金额" min-width="168">
<template #default="{ row: sku }">
@ -47,6 +49,7 @@ import { cloneDeep } from 'lodash-es'
import * as DiscountActivityApi from '@/api/mall/promotion/discount/discountActivity'
import * as ProductSpuApi from '@/api/mall/product/spu'
import { getPropertyList, RuleConfig } from '@/views/mall/product/spu/components'
import {formatToFraction} from "@/utils";
defineOptions({ name: 'PromotionDiscountActivityForm' })
@ -65,8 +68,8 @@ const spuAndSkuListRef = ref() // sku 限时折扣 配置组件Ref
const ruleConfig: RuleConfig[] = []
const spuList = ref<DiscountActivityApi.SpuExtension[]>([]) // spu
const spuPropertyList = ref<SpuProperty<DiscountActivityApi.SpuExtension>[]>([])
const spuIds = ref<number[]>([]);
const selectSpu = (spuId: number, skuIds: number[]) => {
formRef.value.setValues({ spuId })
getSpuDetails(spuId, skuIds)
}
/**
@ -75,14 +78,22 @@ const selectSpu = (spuId: number, skuIds: number[]) => {
const getSpuDetails = async (
spuId: number,
skuIds: number[] | undefined,
products?: DiscountActivityApi.DiscountProductVO[]
products?: DiscountActivityApi.DiscountProductVO[],
type?: string
) => {
const spuProperties: SpuProperty<DiscountActivityApi.SpuExtension>[] = []
//spu
if(spuIds.value.includes(spuId)){
if(type !== "load"){
message.error("数据重复选择!")
}
return;
}
spuIds.value.push(spuId)
const res = (await ProductSpuApi.getSpuDetailList([spuId])) as DiscountActivityApi.SpuExtension[]
if (res.length == 0) {
return
}
spuList.value = []
//spuList.value = []
//
const spu = res[0]
const selectSkus =
@ -100,15 +111,19 @@ const getSpuDetails = async (
config = product || config
}
sku.productConfig = config
sku.price = formatToFraction(sku.price)
sku.marketPrice = formatToFraction(sku.marketPrice)
sku.costPrice = formatToFraction(sku.costPrice)
sku.firstBrokeragePrice = formatToFraction(sku.firstBrokeragePrice)
sku.secondBrokeragePrice = formatToFraction(sku.secondBrokeragePrice)
})
spu.skus = selectSkus as DiscountActivityApi.SkuExtension[]
spuProperties.push({
spuPropertyList.value.push({
spuId: spu.id!,
spuDetail: spu,
propertyList: getPropertyList(spu)
})
spuList.value.push(spu)
spuPropertyList.value = spuProperties
}
// ================= end =================
@ -126,8 +141,10 @@ const open = async (type: string, id?: number) => {
const data = (await DiscountActivityApi.getDiscountActivity(
id
)) as DiscountActivityApi.DiscountActivityVO
const supId = data.products[0].spuId
await getSpuDetails(supId!, data.products?.map((sku) => sku.skuId), data.products)
for (let productsKey in data.products) {
const supId = data.products[productsKey].spuId
await getSpuDetails(supId!, data.products?.map((sku) => sku.skuId), data.products,"load")
}
formRef.value.setValues(data)
} finally {
formLoading.value = false
@ -149,9 +166,20 @@ const submitForm = async () => {
const data = formRef.value.formModel as DiscountActivityApi.DiscountActivityVO
//
const products = cloneDeep(spuAndSkuListRef.value.getSkuConfigs('productConfig'))
let timp = false;
products.forEach((item: DiscountActivityApi.DiscountProductVO) => {
item.discountType = data['discountType']
if(item.discountPrice != null && item.discountPrice > 0){
item.discountType = 1
}else if(item.discountPercent != null && item.discountPercent > 0){
item.discountType = 2
}else{
timp = true
}
})
if(timp){
message.error("优惠金额和折扣百分比需要填写一个");
return;
}
data.products = products
//
if (formType.value === 'create') {
@ -173,7 +201,16 @@ const submitForm = async () => {
const resetForm = async () => {
spuList.value = []
spuPropertyList.value = []
spuIds.value = []
await nextTick()
formRef.value.getElFormRef().resetFields()
}
/**
* 删除spu
*/
const deleteSpu = (spuId: number) => {
spuIds.value.splice(spuIds.value.findIndex((item) => item == spuId), 1)
spuPropertyList.value.splice(spuPropertyList.value.findIndex((item) => item.spuId == spuId), 1)
}
</script>

View File

@ -72,17 +72,6 @@ const crudSchemas = reactive<CrudSchema[]>([
width: 120
}
},
{
label: '优惠类型',
field: 'discountType',
dictType: DICT_TYPE.PROMOTION_DISCOUNT_TYPE,
dictClass: 'number',
isSearch: true,
form: {
component: 'Radio',
value: 1
}
},
{
label: '活动商品',
field: 'spuId',

View File

@ -70,17 +70,17 @@
~ {{ formatDate(scope.row.endTime, 'YYYY-MM-DD') }}
</template>
</el-table-column>
<el-table-column label="商品图片" prop="spuName" min-width="80">
<template #default="scope">
<el-image
:src="scope.row.picUrl"
class="h-40px w-40px"
:preview-src-list="[scope.row.picUrl]"
preview-teleported
/>
</template>
</el-table-column>
<el-table-column label="商品标题" prop="spuName" min-width="300" />
<!-- <el-table-column label="商品图片" prop="spuName" min-width="80">-->
<!-- <template #default="scope">-->
<!-- <el-image-->
<!-- :src="scope.row.picUrl"-->
<!-- class="h-40px w-40px"-->
<!-- :preview-src-list="[scope.row.picUrl]"-->
<!-- preview-teleported-->
<!-- />-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="商品标题" prop="spuName" min-width="300" />-->
<el-table-column label="活动状态" align="center" prop="status" min-width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />

View File

@ -71,6 +71,7 @@
<MessageItem :message="item">
<ProductItem
v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
:spuId="getMessageContent(item).spuId"
:picUrl="getMessageContent(item).picUrl"
:price="getMessageContent(item).price"
:skuText="getMessageContent(item).introduction"
@ -393,7 +394,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
border-left: 5px solid transparent;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
border-right: 5px solid #ffffff;
border-right: 5px solid var(--app-content-bg-color);
}
}
}
@ -412,7 +413,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
right: -19px;
top: calc(50% - 10px);
position: absolute;
border-left: 5px solid #ffffff;
border-left: 5px solid var(--app-content-bg-color);
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
border-right: 5px solid transparent;
@ -422,9 +423,9 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
//
.kefu-message {
color: #333;
color: #A9A9A9;
border-radius: 5px;
box-shadow: 3px 5px 15px rgba(0, 0, 0, 0.2);
box-shadow: 3px 3px 5px rgba(220,220,220, 0.1);
padding: 5px 10px;
width: auto;
max-width: 50%;
@ -432,7 +433,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
display: inline-block !important;
position: relative;
word-break: break-all;
background-color: #ffffff;
background-color: var(--app-content-bg-color);
transition: all 0.2s;
&:hover {
@ -454,7 +455,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
.chat-tools {
width: 100%;
border: #e4e0e0 solid 1px;
border: var(--el-border-color) solid 1px;
border-radius: 10px;
height: 44px;
}

View File

@ -1,6 +1,7 @@
<template>
<ProductItem
v-for="item in list"
:spu-id="item.spuId"
:key="item.id"
:picUrl="item.picUrl"
:price="item.price"

View File

@ -1,5 +1,5 @@
<template>
<div v-if="isObject(getMessageContent)">
<div v-if="isObject(getMessageContent)" @click="openDetail(getMessageContent.id)" style="cursor: pointer;">
<div :key="getMessageContent.id" class="order-list-card-box mt-14px">
<div class="order-card-header flex items-center justify-between p-x-5px">
<div class="order-no">订单号{{ getMessageContent.no }}</div>
@ -9,6 +9,7 @@
</div>
<div v-for="item in getMessageContent.items" :key="item.id" class="border-bottom">
<ProductItem
:spu-id="item.spuId"
:num="item.count"
:picUrl="item.picUrl"
:price="item.price"
@ -36,6 +37,8 @@ import { KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
import { isObject } from '@/utils/is'
import ProductItem from '@/views/mall/promotion/kefu/components/message/ProductItem.vue'
const { push } = useRouter()
defineOptions({ name: 'OrderItem' })
const props = defineProps<{
message?: KeFuMessageRespVO
@ -46,6 +49,12 @@ const getMessageContent = computed(() =>
typeof props.message !== 'undefined' ? jsonParse(props!.message!.content) : props.order
)
/** 查看订单详情 */
const openDetail = (id: number) => {
console.log(getMessageContent)
push({ name: 'TradeOrderDetail', params: { id } })
}
/**
* 格式化订单状态的颜色
*
@ -97,7 +106,7 @@ function formatOrderStatus(order: any) {
.order-list-card-box {
border-radius: 10px;
padding: 10px;
border: 1px #6a6a6a solid;
border: 1px var(--el-border-color) solid;
background-color: var(--app-content-bg-color);
.order-card-header {

View File

@ -1,5 +1,5 @@
<template>
<div>
<div @click.stop="openDetail(props.spuId)" style="cursor: pointer;">
<div>
<slot name="top"></slot>
</div>
@ -15,6 +15,7 @@
class="order-img"
fit="contain"
preview-teleported
@click.stop
/>
</div>
<div
@ -53,8 +54,14 @@
<script lang="ts" setup>
import { fenToYuan } from '@/utils'
const { push } = useRouter()
defineOptions({ name: 'ProductItem' })
const props = defineProps({
spuId: {
type: Number,
default: 0
},
picUrl: {
type: String,
default: 'https://img1.baidu.com/it/u=1601695551,235775011&fm=26&fmt=auto'
@ -107,13 +114,19 @@ const skuString = computed(() => {
}
return props.skuText
})
/** 查看商品详情 */
const openDetail = (spuId: number) => {
console.log(props.spuId)
push({ name: 'ProductSpuDetail', params: { id: spuId } })
}
</script>
<style lang="scss" scoped>
.ss-order-card-warp {
padding: 20px;
border-radius: 10px;
border: 1px #6a6a6a solid;
border: 1px var(--el-border-color) solid;
background-color: var(--app-content-bg-color);
.img-box {
@ -134,7 +147,7 @@ const skuString = computed(() => {
.tool-box {
position: absolute;
right: 0px;
right: 0;
bottom: -10px;
}
}

View File

@ -325,13 +325,13 @@ onMounted(async () => {
align-items: center;
min-height: 30px;
padding: 10px;
background-color: #f7f8fa;
background-color: var(--app-content-bg-color);
&::before {
position: absolute;
top: 10px;
left: 13px;
border-color: transparent #f7f8fa transparent transparent; /* 尖角颜色,左侧朝向 */
border-color: transparent var(--app-content-bg-color) transparent transparent; /* 尖角颜色,左侧朝向 */
border-style: solid;
border-width: 8px; /* 调整尖角大小 */
content: '';

View File

@ -106,14 +106,8 @@
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
<el-dialog
v-model="mapDialogVisible"
title="获取经纬度"
append-to-body
width="500px"
class="mapBox"
>
<iframe id="mapPage" width="100%" height="100%" frameborder="0" :src="tencentLbsUrl"></iframe>
<el-dialog v-model="mapDialogVisible" title="获取经纬度" append-to-body>
<IFrame class="h-609px" :src="tencentLbsUrl" />
</el-dialog>
</Dialog>
</template>
@ -266,8 +260,3 @@ onMounted(async () => {
await initTencentLbsMap()
})
</script>
<style lang="scss">
.mapBox .el-dialog__body {
height: 640px !important;
}
</style>

View File

@ -2,8 +2,10 @@
<ContentWrap>
<doc-alert title="大屏设计器" url="https://doc.iocoder.cn/report/screen/" />
<ContentWrap :bodyStyle="{ padding: '0px' }" class="!mb-0">
<IFrame :src="src" />
</ContentWrap>
</ContentWrap>
</template>
<script lang="ts" setup>
defineOptions({ name: 'GoView' })

View File

@ -2,14 +2,15 @@
<ContentWrap>
<doc-alert title="报表设计器" url="https://doc.iocoder.cn/report/" />
<ContentWrap :bodyStyle="{ padding: '0px' }" class="!mb-0">
<IFrame :src="src" />
</ContentWrap>
</ContentWrap>
</template>
<script lang="ts" setup>
import { getAccessToken } from '@/utils/auth'
defineOptions({ name: 'JimuReport' })
const BASE_URL = import.meta.env.VITE_BASE_URL
const src = ref(BASE_URL + '/jmreport/list?token=' + getAccessToken())
const src = ref(import.meta.env.VITE_BASE_URL + '/jmreport/list?token=' + getAccessToken())
</script>

View File

@ -8,7 +8,7 @@
<el-tag>{{ formData.code }}</el-tag>
</el-form-item>
<el-form-item label="菜单权限">
<el-card class="cardHeight">
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
<template #header>
全选/全不选:
<el-switch
@ -151,10 +151,3 @@ const handleCheckedTreeExpand = () => {
}
}
</script>
<style lang="scss" scoped>
.cardHeight {
width: 100%;
max-height: 400px;
overflow-y: scroll;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<Dialog v-model="dialogVisible" title="菜单权限" width="800">
<Dialog v-model="dialogVisible" title="数据权限" width="800">
<el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px">
<el-form-item label="角色名称">
<el-tag>{{ formData.name }}</el-tag>
@ -21,9 +21,9 @@
<el-form-item
v-if="formData.dataScope === SystemDataScopeEnum.DEPT_CUSTOM"
label="权限范围"
style="display: flex"
label-width="80px"
>
<el-card class="card" shadow="never">
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
<template #header>
全选/全不选:
<el-switch

View File

@ -11,7 +11,7 @@
<el-input v-model="formData.name" placeholder="请输入套餐名" />
</el-form-item>
<el-form-item label="菜单权限">
<el-card class="cardHeight">
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
<template #header>
全选/全不选:
<el-switch
@ -185,10 +185,3 @@ const handleCheckedTreeExpand = () => {
}
}
</script>
<style lang="scss" scoped>
.cardHeight {
width: 100%;
max-height: 400px;
overflow-y: scroll;
}
</style>

View File

@ -12,7 +12,7 @@ export default defineConfig({
${selector} {
display: flex;
height: 100%;
padding: 1px 10px 0;
padding: 0 10px;
cursor: pointer;
align-items: center;
transition: background var(--transition-time-02);