mirror of
https://gitee.com/myxzgzs/boyue-ui-admin-vue3
synced 2025-08-08 16:32:43 +08:00
Merge branch 'master' of https://gitee.com/yudaocode/yudao-ui-admin-vue3 into feature/bpm
This commit is contained in:
commit
45ac20e5c3
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "yudao-ui-admin-vue3",
|
||||
"version": "2.4.0-snapshot",
|
||||
"version": "2.4.1-snapshot",
|
||||
"description": "基于vue3、vite4、element-plus、typesScript",
|
||||
"author": "xingyu",
|
||||
"private": false,
|
||||
|
12298
pnpm-lock.yaml
generated
12298
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -83,5 +83,5 @@ export const reqCheck = (data: any) => {
|
||||
|
||||
// 通过短信重置密码
|
||||
export const smsResetPassword = (data: any) => {
|
||||
return request.post({ url: '/system/auth/sms-reset-password', data })
|
||||
return request.post({ url: '/system/auth/reset-password', data })
|
||||
}
|
||||
|
@ -51,7 +51,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ComponentStyle, usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { ComponentStyle } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
/**
|
||||
* 组件容器属性:目前右边部分
|
||||
@ -61,7 +62,7 @@ defineOptions({ name: 'ComponentContainer' })
|
||||
|
||||
const props = defineProps<{ modelValue: ComponentStyle }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
const treeData = [
|
||||
{
|
||||
|
@ -93,14 +93,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CarouselProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 轮播图属性面板
|
||||
defineOptions({ name: 'CarouselProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: CarouselProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -68,15 +68,20 @@
|
||||
</el-form>
|
||||
</ComponentContainerProperty>
|
||||
<!-- 优惠券选择 -->
|
||||
<CouponSelect ref="couponSelectDialog" v-model:multiple-selection="couponList" />
|
||||
<CouponSelect
|
||||
ref="couponSelectDialog"
|
||||
v-model:multiple-selection="couponList"
|
||||
:take-type="CouponTemplateTakeTypeEnum.USER.type"
|
||||
@change="handleCouponSelect"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CouponCardProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import * as CouponTemplateApi from '@/api/mall/promotion/coupon/couponTemplate'
|
||||
import { floatToFixed2 } from '@/utils'
|
||||
import { PromotionDiscountTypeEnum } from '@/utils/constants'
|
||||
import { CouponTemplateTakeTypeEnum, PromotionDiscountTypeEnum } from '@/utils/constants'
|
||||
import CouponSelect from '@/views/mall/promotion/coupon/components/CouponSelect.vue'
|
||||
|
||||
// 优惠券卡片属性面板
|
||||
@ -84,7 +89,7 @@ defineOptions({ name: 'CouponCardProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: CouponCardProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 优惠券列表
|
||||
const couponList = ref<CouponTemplateApi.CouponTemplateVO[]>([])
|
||||
@ -93,11 +98,21 @@ const couponSelectDialog = ref()
|
||||
const handleAddCoupon = () => {
|
||||
couponSelectDialog.value.open()
|
||||
}
|
||||
watch(
|
||||
() => couponList.value,
|
||||
() => {
|
||||
const handleCouponSelect = () => {
|
||||
formData.value.couponIds = couponList.value.map((coupon) => coupon.id)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => formData.value.couponIds,
|
||||
async () => {
|
||||
if (formData.value.couponIds?.length > 0) {
|
||||
couponList.value = await CouponTemplateApi.getCouponTemplateList(formData.value.couponIds)
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
|
@ -45,12 +45,12 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DividerProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'DividerProperty' })
|
||||
const props = defineProps<{ modelValue: DividerProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
//线类型
|
||||
const BORDER_TYPES = [
|
||||
|
@ -31,14 +31,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { FloatingActionButtonProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 悬浮按钮属性面板
|
||||
defineOptions({ name: 'FloatingActionButtonProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: FloatingActionButtonProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -20,7 +20,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { HotZoneProperty } from '@/components/DiyEditor/components/mobile/HotZone/config'
|
||||
import HotZoneEditDialog from './components/HotZoneEditDialog/index.vue'
|
||||
|
||||
@ -29,7 +29,7 @@ defineOptions({ name: 'HotZoneProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: HotZoneProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 热区编辑对话框
|
||||
const editDialogRef = ref()
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ImageBarProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 图片展示属性面板
|
||||
defineOptions({ name: 'ImageBarProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: ImageBarProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -56,7 +56,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { MagicCubeProperty } from '@/components/DiyEditor/components/mobile/MagicCube/config'
|
||||
|
||||
/** 广告魔方属性面板 */
|
||||
@ -64,7 +64,7 @@ defineOptions({ name: 'MagicCubeProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: MagicCubeProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 选中的热区
|
||||
const selectedHotAreaIndex = ref(-1)
|
||||
|
@ -48,7 +48,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import {
|
||||
EMPTY_MENU_GRID_ITEM_PROPERTY,
|
||||
MenuGridProperty
|
||||
@ -59,7 +59,7 @@ defineOptions({ name: 'MenuGridProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: MenuGridProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -28,7 +28,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import {
|
||||
EMPTY_MENU_LIST_ITEM_PROPERTY,
|
||||
MenuListProperty
|
||||
@ -39,7 +39,7 @@ defineOptions({ name: 'MenuListProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: MenuListProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -58,7 +58,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import {
|
||||
EMPTY_MENU_SWIPER_ITEM_PROPERTY,
|
||||
MenuSwiperProperty
|
||||
@ -70,7 +70,7 @@ defineOptions({ name: 'MenuSwiperProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: MenuSwiperProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -64,17 +64,22 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { NavigationBarCellProperty } from '../config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'NavigationBarCellProperty' })
|
||||
|
||||
const props = defineProps<{
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
modelValue: NavigationBarCellProperty[]
|
||||
isMp: boolean
|
||||
}>()
|
||||
}>(),
|
||||
{
|
||||
modelValue: () => [],
|
||||
isMp: true
|
||||
}
|
||||
)
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData: cellList } = usePropertyForm(props.modelValue, emit)
|
||||
if (!cellList.value) cellList.value = []
|
||||
const cellList = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 单元格数量:小程序6个(右侧胶囊按钮占了2个),其它平台8个
|
||||
const cellCount = computed(() => (props.isMp ? 6 : 8))
|
||||
|
@ -4,7 +4,7 @@
|
||||
<div v-for="(cell, cellIndex) in cellList" :key="cellIndex" :style="getCellStyle(cell)">
|
||||
<span v-if="cell.type === 'text'">{{ cell.text }}</span>
|
||||
<img v-else-if="cell.type === 'image'" :src="cell.imgUrl" alt="" class="h-full w-full" />
|
||||
<SearchBar v-else :property="getSearchProp" />
|
||||
<SearchBar v-else :property="getSearchProp(cell)" />
|
||||
</div>
|
||||
</div>
|
||||
<img
|
||||
@ -51,14 +51,14 @@ const getCellStyle = (cell: NavigationBarCellProperty) => {
|
||||
} as StyleValue
|
||||
}
|
||||
// 获得搜索框属性
|
||||
const getSearchProp = (cell: NavigationBarCellProperty) => {
|
||||
const getSearchProp = computed(() => (cell: NavigationBarCellProperty) => {
|
||||
return {
|
||||
height: 30,
|
||||
showScan: false,
|
||||
placeholder: cell.placeholder,
|
||||
borderRadius: cell.borderRadius
|
||||
} as SearchProperty
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.navigation-bar {
|
||||
|
@ -66,7 +66,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NavigationBarProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import NavigationBarCellProperty from '@/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'NavigationBarProperty' })
|
||||
@ -77,7 +77,7 @@ const rules = {
|
||||
|
||||
const props = defineProps<{ modelValue: NavigationBarProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
if (!formData.value._local) {
|
||||
formData.value._local = { previewMp: true, previewOther: false }
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NoticeBarProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
// 通知栏属性面板
|
||||
defineOptions({ name: 'NoticeBarProperty' })
|
||||
// 表单校验
|
||||
@ -40,7 +40,7 @@ const rules = {
|
||||
|
||||
const props = defineProps<{ modelValue: NoticeBarProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PageConfigProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'PageConfigProperty' })
|
||||
// 表单校验
|
||||
@ -28,7 +28,7 @@ const rules = {}
|
||||
|
||||
const props = defineProps<{ modelValue: PageConfigProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -25,14 +25,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PopoverProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 弹窗广告属性面板
|
||||
defineOptions({ name: 'PopoverProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: PopoverProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -135,7 +135,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProductCardProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import SpuShowcase from '@/views/mall/product/spu/components/SpuShowcase.vue'
|
||||
|
||||
// 商品卡片属性面板
|
||||
@ -143,7 +143,7 @@ defineOptions({ name: 'ProductCardProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: ProductCardProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -85,7 +85,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProductListProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import SpuShowcase from '@/views/mall/product/spu/components/SpuShowcase.vue'
|
||||
|
||||
// 商品栏属性面板
|
||||
@ -93,7 +93,7 @@ defineOptions({ name: 'ProductListProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: ProductListProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PromotionArticleProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import * as ArticleApi from '@/api/mall/promotion/article/index'
|
||||
|
||||
// 营销文章属性面板
|
||||
@ -33,7 +33,7 @@ defineOptions({ name: 'PromotionArticleProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: PromotionArticleProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
// 文章列表
|
||||
const articles = ref<ArticleApi.ArticleVO>([])
|
||||
|
||||
|
@ -140,7 +140,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PromotionCombinationProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import * as CombinationActivityApi from '@/api/mall/promotion/combination/combinationActivity'
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
import CombinationShowcase from '@/views/mall/promotion/combination/components/CombinationShowcase.vue'
|
||||
@ -150,7 +150,7 @@ defineOptions({ name: 'PromotionCombinationProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: PromotionCombinationProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
// 活动列表
|
||||
const activityList = ref<CombinationActivityApi.CombinationActivityVO[]>([])
|
||||
onMounted(async () => {
|
||||
|
@ -140,7 +140,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PromotionPointProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import PointShowcase from '@/views/mall/promotion/point/components/PointShowcase.vue'
|
||||
|
||||
// 秒杀属性面板
|
||||
@ -148,7 +148,7 @@ defineOptions({ name: 'PromotionPointProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: PromotionPointProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -140,7 +140,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PromotionSeckillProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
import SeckillShowcase from '@/views/mall/promotion/seckill/components/SeckillShowcase.vue'
|
||||
@ -150,7 +150,7 @@ defineOptions({ name: 'PromotionSeckillProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: PromotionSeckillProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
// 活动列表
|
||||
const activityList = ref<SeckillActivityApi.SeckillActivityVO[]>([])
|
||||
onMounted(async () => {
|
||||
|
@ -59,7 +59,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { SearchProperty } from '@/components/DiyEditor/components/mobile/SearchBar/config'
|
||||
|
||||
/** 搜索框属性面板 */
|
||||
@ -67,7 +67,7 @@ defineOptions({ name: 'SearchProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: SearchProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -80,13 +80,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TabBarProperty, component, THEME_LIST } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
// 底部导航栏
|
||||
defineOptions({ name: 'TabBarProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: TabBarProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 将数据库的值更新到右侧属性栏
|
||||
component.property.items = formData.value.items
|
||||
|
@ -101,13 +101,13 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { TitleBarProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'TitleBarProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: TitleBarProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 表单校验
|
||||
const rules = {}
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { UserCardProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 用户卡片属性面板
|
||||
defineOptions({ name: 'UserCardProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: UserCardProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { UserCouponProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 用户卡券属性面板
|
||||
defineOptions({ name: 'UserCouponProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: UserCouponProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { UserOrderProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 用户订单属性面板
|
||||
defineOptions({ name: 'UserOrderProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: UserOrderProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { UserWalletProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 用户资产属性面板
|
||||
defineOptions({ name: 'UserWalletProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: UserWalletProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -42,14 +42,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { VideoPlayerProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
// 视频播放属性面板
|
||||
defineOptions({ name: 'VideoPlayerProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: VideoPlayerProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
@ -110,7 +110,7 @@
|
||||
<el-tag
|
||||
v-if="showPageConfig"
|
||||
:effect="selectedComponent?.uid === pageConfigComponent.uid ? 'dark' : 'plain'"
|
||||
:type="selectedComponent?.uid === pageConfigComponent.uid ? '' : 'info'"
|
||||
:type="selectedComponent?.uid === pageConfigComponent.uid ? 'primary' : 'info'"
|
||||
size="large"
|
||||
@click="handleComponentSelected(pageConfigComponent)"
|
||||
>
|
||||
@ -121,7 +121,7 @@
|
||||
<el-tag
|
||||
v-if="component.position === 'fixed'"
|
||||
:effect="selectedComponent?.uid === component.uid ? 'dark' : 'plain'"
|
||||
:type="selectedComponent?.uid === component.uid ? '' : 'info'"
|
||||
:type="selectedComponent?.uid === component.uid ? 'primary' : 'info'"
|
||||
closable
|
||||
size="large"
|
||||
@click="handleComponentSelected(component)"
|
||||
@ -191,7 +191,7 @@ import { cloneDeep, includes } from 'lodash-es'
|
||||
import { component as PAGE_CONFIG_COMPONENT } from '@/components/DiyEditor/components/mobile/PageConfig/config'
|
||||
import { component as NAVIGATION_BAR_COMPONENT } from './components/mobile/NavigationBar/config'
|
||||
import { component as TAB_BAR_COMPONENT } from './components/mobile/TabBar/config'
|
||||
import { isString } from '@/utils/is'
|
||||
import { isEmpty, isString } from '@/utils/is'
|
||||
import { DiyComponent, DiyComponentLibrary, PageConfig } from '@/components/DiyEditor/util'
|
||||
import { componentConfigs } from '@/components/DiyEditor/components/mobile'
|
||||
import { array, oneOfType } from 'vue-types'
|
||||
@ -238,24 +238,42 @@ const props = defineProps({
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
const modelValue = isString(props.modelValue)
|
||||
const modelValue =
|
||||
isString(props.modelValue) && !isEmpty(props.modelValue)
|
||||
? (JSON.parse(props.modelValue) as PageConfig)
|
||||
: props.modelValue
|
||||
pageConfigComponent.value.property = modelValue?.page || PAGE_CONFIG_COMPONENT.property
|
||||
pageConfigComponent.value.property =
|
||||
(typeof modelValue !== 'string' && modelValue?.page) || PAGE_CONFIG_COMPONENT.property
|
||||
navigationBarComponent.value.property =
|
||||
modelValue?.navigationBar || NAVIGATION_BAR_COMPONENT.property
|
||||
tabBarComponent.value.property = modelValue?.tabBar || TAB_BAR_COMPONENT.property
|
||||
(typeof modelValue !== 'string' && modelValue?.navigationBar) ||
|
||||
NAVIGATION_BAR_COMPONENT.property
|
||||
tabBarComponent.value.property =
|
||||
(typeof modelValue !== 'string' && modelValue?.tabBar) || TAB_BAR_COMPONENT.property
|
||||
// 查找对应的页面组件
|
||||
pageComponents.value = (modelValue?.components || []).map((item) => {
|
||||
pageComponents.value = ((typeof modelValue !== 'string' && modelValue?.components) || []).map(
|
||||
(item) => {
|
||||
const component = componentConfigs[item.id]
|
||||
return { ...component, property: item.property }
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
/** 选择组件修改其属性后更新它的配置 */
|
||||
watch(
|
||||
selectedComponent,
|
||||
(val: any) => {
|
||||
if (!val || selectedComponentIndex.value === -1) {
|
||||
return
|
||||
}
|
||||
pageComponents.value[selectedComponentIndex.value] = selectedComponent.value!
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 保存
|
||||
const handleSave = () => {
|
||||
// 发送保存通知
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ref, Ref } from 'vue'
|
||||
import { PageConfigProperty } from '@/components/DiyEditor/components/mobile/PageConfig/config'
|
||||
import { NavigationBarProperty } from '@/components/DiyEditor/components/mobile/NavigationBar/config'
|
||||
import { TabBarProperty } from '@/components/DiyEditor/components/mobile/TabBar/config'
|
||||
@ -78,34 +77,6 @@ export interface PageConfig {
|
||||
// 页面组件,只保留组件ID,组件属性
|
||||
export interface PageComponent extends Pick<DiyComponent<any>, 'id' | 'property'> {}
|
||||
|
||||
// 属性表单监听
|
||||
export function usePropertyForm<T>(modelValue: T, emit: Function): { formData: Ref<T> } {
|
||||
const formData = ref<T>()
|
||||
// 监听属性数据变动
|
||||
watch(
|
||||
() => modelValue,
|
||||
() => {
|
||||
formData.value = modelValue
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
// 监听表单数据变动
|
||||
watch(
|
||||
() => formData.value,
|
||||
() => {
|
||||
emit('update:modelValue', formData.value)
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
return { formData } as { formData: Ref<T> }
|
||||
}
|
||||
|
||||
// 页面组件库
|
||||
export const PAGE_LIBS = [
|
||||
{
|
||||
|
@ -13,9 +13,16 @@
|
||||
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 p-8px" style="background-color: var(--app-content-bg-color);">
|
||||
<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" style="color: #8a909c;" />
|
||||
<Icon
|
||||
icon="ic:round-drag-indicator"
|
||||
class="drag-icon cursor-move"
|
||||
style="color: #8a909c"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除">
|
||||
<Icon
|
||||
@ -47,7 +54,7 @@
|
||||
<script setup lang="ts">
|
||||
// 拖拽组件
|
||||
import VueDraggable from 'vuedraggable'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { any, array } from 'vue-types'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
@ -66,7 +73,7 @@ const props = defineProps({
|
||||
})
|
||||
// 定义事件
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
const formData = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 处理添加
|
||||
const handleAdd = () => formData.value.push(cloneDeep(props.emptyItem || {}))
|
||||
|
@ -75,7 +75,7 @@ watch(
|
||||
|
||||
<template>
|
||||
<ElIcon :class="prefixCls" :color="color" :size="size">
|
||||
<svg v-if="isLocal" :class="getSvgClass" aria-hidden="true">
|
||||
<svg v-if="isLocal" :class="getSvgClass">
|
||||
<use :xlink:href="symbolId" />
|
||||
</svg>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-input v-model="valueRef" v-bind="$attrs">
|
||||
<el-input v-model="modelValue" v-bind="$attrs">
|
||||
<template #append>
|
||||
<el-color-picker v-model="colorRef" :predefine="PREDEFINE_COLORS" />
|
||||
<el-color-picker v-model="color" :predefine="PREDEFINE_COLORS" />
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
@ -9,6 +9,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { PREDEFINE_COLORS } from '@/utils/color'
|
||||
import { useVModels } from '@vueuse/core'
|
||||
|
||||
/**
|
||||
* 带颜色选择器输入框
|
||||
@ -19,33 +20,8 @@ const props = defineProps({
|
||||
modelValue: propTypes.string.def('').isRequired,
|
||||
color: propTypes.string.def('').isRequired
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val: string) => {
|
||||
if (val === unref(valueRef)) return
|
||||
valueRef.value = val
|
||||
}
|
||||
)
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'update:color'])
|
||||
|
||||
// 输入框的值
|
||||
const valueRef = ref(props.modelValue)
|
||||
watch(
|
||||
() => valueRef.value,
|
||||
(val: string) => {
|
||||
emit('update:modelValue', val)
|
||||
}
|
||||
)
|
||||
// 颜色
|
||||
const colorRef = ref(props.color)
|
||||
watch(
|
||||
() => colorRef.value,
|
||||
(val: string) => {
|
||||
emit('update:color', val)
|
||||
}
|
||||
)
|
||||
const { modelValue, color } = useVModels(props, emit)
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-input-group__append) {
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import SimpleProcessModel from './SimpleProcessModel.vue'
|
||||
import { updateBpmSimpleModel, getBpmSimpleModel } from '@/api/bpm/simple'
|
||||
import { SimpleFlowNode, NodeType, NodeId, NODE_DEFAULT_TEXT } from './consts'
|
||||
import { getModel } from '@/api/bpm/model'
|
||||
import { getForm, FormVO } from '@/api/bpm/form'
|
||||
@ -35,6 +34,7 @@ import * as DeptApi from '@/api/system/dept'
|
||||
import * as PostApi from '@/api/system/post'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import * as UserGroupApi from '@/api/bpm/userGroup'
|
||||
import { BpmModelFormType } from '@/utils/constants'
|
||||
|
||||
defineOptions({
|
||||
name: 'SimpleProcessDesigner'
|
||||
@ -168,7 +168,7 @@ onMounted(async () => {
|
||||
const bpmnModel = await getModel(props.modelId)
|
||||
if (bpmnModel) {
|
||||
formType.value = bpmnModel.formType
|
||||
if (formType.value === 10) {
|
||||
if (formType.value === BpmModelFormType.NORMAL && bpmnModel.formId) {
|
||||
const bpmnForm = (await getForm(bpmnModel.formId)) as unknown as FormVO
|
||||
formFields.value = bpmnForm?.fields
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<!-- 列表选择通用组件,参考 ProductList 组件使用 -->
|
||||
<!-- TODO 芋艿:可能会移除 -->
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" :appendToBody="true" :scroll="true" :title="title" width="60%">
|
||||
<el-table
|
||||
|
@ -449,3 +449,18 @@ export function jsonParse(str: string) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param name
|
||||
* @param start
|
||||
* @param end
|
||||
*/
|
||||
|
||||
export const sliceName = (name: string,start: number, end : number) => {
|
||||
if (name.length > end) {
|
||||
return name.slice(start, end)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
@ -88,6 +88,9 @@
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-image v-if="row.icon" :src="row.icon" class="h-38px w-38px mr-10px rounded" />
|
||||
<div v-else class="flow-icon">
|
||||
<span style="font-size: 12px; color: #fff">{{ sliceName(row.name,0,2) }}</span>
|
||||
</div>
|
||||
{{ row.name }}
|
||||
</div>
|
||||
</template>
|
||||
@ -249,6 +252,11 @@
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<!-- 弹窗:表单详情 -->
|
||||
<Dialog title="表单详情" :fullscreen="true" v-model="formDetailVisible">
|
||||
<form-create :rule="formDetailPreview.rule" :option="formDetailPreview.option" />
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -265,6 +273,7 @@ import { useAppStore } from '@/store/modules/app'
|
||||
import { cloneDeep, isEqual } from 'lodash-es'
|
||||
import { useTagsView } from '@/hooks/web/useTagsView'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { sliceName } from '@/utils/index'
|
||||
|
||||
defineOptions({ name: 'BpmModel' })
|
||||
|
||||
@ -437,11 +446,10 @@ const handleChangeState = async (row: any) => {
|
||||
/** 发布流程 */
|
||||
const handleDeploy = async (row: any) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.confirm('是否部署该流程!!')
|
||||
await message.confirm('是否确认发布该流程?')
|
||||
// 发起部署
|
||||
await ModelApi.deployModel(row.id)
|
||||
message.success(t('部署成功'))
|
||||
message.success(t('发布成功'))
|
||||
// 刷新列表
|
||||
emit('success')
|
||||
} catch {}
|
||||
@ -464,7 +472,7 @@ const formDetailPreview = ref({
|
||||
option: {}
|
||||
})
|
||||
const handleFormDetail = async (row: any) => {
|
||||
if (row.formType == 10) {
|
||||
if (row.formType == BpmModelFormType.NORMAL) {
|
||||
// 设置表单
|
||||
const data = await FormApi.getForm(row.formId)
|
||||
setConfAndFields2(formDetailPreview, data.conf, data.fields)
|
||||
@ -617,6 +625,17 @@ watchEffect(() => {
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.flow-icon {
|
||||
display: flex;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
margin-right: 10px;
|
||||
background-color: var(--el-color-primary);
|
||||
border-radius: 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.category-draggable-model {
|
||||
:deep(.el-table__cell) {
|
||||
overflow: hidden;
|
||||
|
@ -6,7 +6,7 @@
|
||||
class="!w-440px"
|
||||
v-model="modelData.key"
|
||||
:disabled="!!modelData.id"
|
||||
placeholder="请输入流标标识"
|
||||
placeholder="请输入流程标识,以字母或下划线开头"
|
||||
/>
|
||||
<el-tooltip
|
||||
class="item"
|
||||
@ -41,7 +41,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程图标" prop="icon" class="mb-20px">
|
||||
<el-form-item label="流程图标" class="mb-20px">
|
||||
<UploadImg v-model="modelData.icon" :limit="1" height="64px" width="64px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程描述" prop="description" class="mb-20px">
|
||||
@ -155,7 +155,6 @@ const rules = {
|
||||
name: [{ required: true, message: '流程名称不能为空', trigger: 'blur' }],
|
||||
key: [{ required: true, message: '流程标识不能为空', trigger: 'blur' }],
|
||||
category: [{ required: true, message: '流程分类不能为空', trigger: 'blur' }],
|
||||
icon: [{ required: true, message: '流程图标不能为空', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }],
|
||||
visible: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }],
|
||||
managerUserIds: [{ required: true, message: '流程管理员不能为空', trigger: 'blur' }]
|
||||
|
@ -285,9 +285,8 @@ const handleSave = async () => {
|
||||
} else {
|
||||
// 新增场景
|
||||
formData.value.id = await ModelApi.createModel(modelData)
|
||||
message.success('新增成功')
|
||||
try {
|
||||
await message.confirm('创建流程成功,是否继续编辑?')
|
||||
await message.confirm('流程创建成功,是否继续编辑?')
|
||||
// 用户点击继续编辑,跳转到编辑页面
|
||||
await nextTick()
|
||||
// 先删除当前页签
|
||||
@ -317,7 +316,6 @@ const handleDeploy = async () => {
|
||||
if (!formData.value.id) {
|
||||
await message.confirm('是否确认发布该流程?')
|
||||
}
|
||||
|
||||
// 校验所有步骤
|
||||
await validateAllSteps()
|
||||
|
||||
|
@ -58,7 +58,16 @@
|
||||
>
|
||||
<template #default>
|
||||
<div class="flex">
|
||||
<el-image :src="definition.icon" class="w-32px h-32px" />
|
||||
<el-image
|
||||
v-if="definition.icon"
|
||||
:src="definition.icon"
|
||||
class="w-32px h-32px"
|
||||
/>
|
||||
<div v-else class="flow-icon">
|
||||
<span style="font-size: 12px; color: #fff">{{
|
||||
sliceName(definition.name,0,2)
|
||||
}}</span>
|
||||
</div>
|
||||
<el-text class="!ml-10px" size="large">{{ definition.name }}</el-text>
|
||||
</div>
|
||||
</template>
|
||||
@ -88,6 +97,7 @@ import * as ProcessInstanceApi from '@/api/bpm/processInstance'
|
||||
import { CategoryApi, CategoryVO } from '@/api/bpm/category'
|
||||
import ProcessDefinitionDetail from './ProcessDefinitionDetail.vue'
|
||||
import { groupBy } from 'lodash-es'
|
||||
import { sliceName } from '@/utils/index'
|
||||
|
||||
defineOptions({ name: 'BpmProcessInstanceCreate' })
|
||||
|
||||
@ -282,13 +292,25 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.flow-icon {
|
||||
display: flex;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 10px;
|
||||
background-color: var(--el-color-primary);
|
||||
border-radius: 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.process-definition-container::before {
|
||||
content: '';
|
||||
border-left: 1px solid #e6e6e6;
|
||||
position: absolute;
|
||||
left: 20.8%;
|
||||
height: 100%;
|
||||
border-left: 1px solid #e6e6e6;
|
||||
content: '';
|
||||
}
|
||||
|
||||
:deep() {
|
||||
.definition-item-card {
|
||||
.el-card__body {
|
||||
|
@ -66,7 +66,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="产品单价" fixed="right" min-width="120">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
|
||||
<el-form-item
|
||||
:prop="`${$index}.productPrice`"
|
||||
:rules="formRules.productPrice"
|
||||
class="mb-0px!"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="row.productPrice"
|
||||
controls-position="right"
|
||||
@ -153,6 +157,7 @@ const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref([])
|
||||
const formRules = reactive({
|
||||
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
|
||||
productPrice: [{ required: true, message: '产品单价不能为空', trigger: 'blur' }],
|
||||
count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref([]) // 表单 Ref
|
||||
|
@ -7,7 +7,7 @@
|
||||
<el-descriptions-item label="任务名称">
|
||||
{{ detailData.name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="任务名称">
|
||||
<el-descriptions-item label="任务状态">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="detailData.status" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="处理器的名字">
|
||||
|
@ -52,7 +52,9 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
|
||||
const formData = ref<DiyTemplateApi.DiyTemplatePropertyVO>()
|
||||
const formRef = ref() // 表单 Ref
|
||||
// 当前编辑的属性
|
||||
const currentFormData = ref<DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>()
|
||||
const currentFormData = ref<DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>({
|
||||
property: ''
|
||||
} as DiyPageApi.DiyPageVO)
|
||||
// templateItem 对应的缓存
|
||||
const currentFormDataMap = ref<
|
||||
Map<string, DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>
|
||||
@ -92,17 +94,21 @@ const handleTemplateItemChange = (val: number) => {
|
||||
// 编辑模板
|
||||
if (val === 0) {
|
||||
libs.value = templateLibs
|
||||
currentFormData.value = isEmpty(data) ? formData.value : data
|
||||
currentFormData.value = (isEmpty(data) ? formData.value : data) as
|
||||
| DiyTemplateApi.DiyTemplatePropertyVO
|
||||
| DiyPageApi.DiyPageVO
|
||||
return
|
||||
}
|
||||
|
||||
// 编辑页面
|
||||
libs.value = PAGE_LIBS
|
||||
currentFormData.value = isEmpty(data)
|
||||
currentFormData.value = (
|
||||
isEmpty(data)
|
||||
? formData.value!.pages.find(
|
||||
(page: DiyPageApi.DiyPageVO) => page.name === templateItems[val].name
|
||||
)
|
||||
: data
|
||||
) as DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
@ -170,7 +176,9 @@ const recoverPageIndex = () => {
|
||||
sessionStorage.removeItem(DIY_PAGE_INDEX_KEY)
|
||||
|
||||
// 重新初始化数据
|
||||
currentFormData.value = formData.value
|
||||
currentFormData.value = formData.value as
|
||||
| DiyTemplateApi.DiyTemplatePropertyVO
|
||||
| DiyPageApi.DiyPageVO
|
||||
currentFormDataMap.value = new Map<
|
||||
string,
|
||||
DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO
|
||||
|
@ -279,8 +279,9 @@ const handleSendMessage = async (event: any) => {
|
||||
return
|
||||
}
|
||||
// 1. 校验消息是否为空
|
||||
if (isEmpty(unref(message.value))) {
|
||||
if (isEmpty(unref(message.value)?.trim())) {
|
||||
messageTool.notifyWarning('请输入消息后再发送哦!')
|
||||
message.value = ''
|
||||
return
|
||||
}
|
||||
// 2. 组织发送消息
|
||||
|
@ -37,22 +37,22 @@ const { data, close, open } = useWebSocket(server.value, {
|
||||
})
|
||||
|
||||
/** 监听 WebSocket 数据 */
|
||||
watchEffect(() => {
|
||||
if (!data.value) {
|
||||
return
|
||||
}
|
||||
watch(
|
||||
() => data.value,
|
||||
(newData) => {
|
||||
if (!newData) return
|
||||
try {
|
||||
// 1. 收到心跳
|
||||
if (data.value === 'pong') {
|
||||
return
|
||||
}
|
||||
if (newData === 'pong') return
|
||||
|
||||
// 2.1 解析 type 消息类型
|
||||
const jsonMessage = JSON.parse(data.value)
|
||||
const jsonMessage = JSON.parse(newData)
|
||||
const type = jsonMessage.type
|
||||
if (!type) {
|
||||
message.error('未知的消息类型:' + data.value)
|
||||
message.error('未知的消息类型:' + newData)
|
||||
return
|
||||
}
|
||||
|
||||
// 2.2 消息类型:KEFU_MESSAGE_TYPE
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
|
||||
const message = JSON.parse(jsonMessage.content)
|
||||
@ -62,6 +62,7 @@ watchEffect(() => {
|
||||
keFuChatBoxRef.value?.refreshMessageList(message)
|
||||
return
|
||||
}
|
||||
|
||||
// 2.3 消息类型:KEFU_MESSAGE_ADMIN_READ
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ) {
|
||||
// 更新会话已读
|
||||
@ -70,7 +71,11 @@ watchEffect(() => {
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
immediate: false // 不立即执行
|
||||
}
|
||||
)
|
||||
// ======================= WebSocket end =======================
|
||||
|
||||
/** 加载指定会话的消息列表 */
|
||||
|
@ -26,9 +26,23 @@
|
||||
placeholder="请输入微信 APPID"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px">
|
||||
<a
|
||||
href="https://pay.weixin.qq.com/index.php/extend/merchant_appid/mapay_platform/account_manage"
|
||||
target="_blank"
|
||||
>
|
||||
前往微信商户平台查看 APPID
|
||||
</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户号" label-width="180px" prop="config.mchId">
|
||||
<el-input v-model="formData.config.mchId" :style="{ width: '100%' }" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label-width="180px">
|
||||
<a href="https://pay.weixin.qq.com/index.php/extend/pay_setting" target="_blank">
|
||||
前往微信商户平台查看商户号
|
||||
</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="渠道状态" label-width="180px" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
@ -123,6 +137,14 @@
|
||||
placeholder="请输入证书序列号"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px">
|
||||
<a
|
||||
href="https://pay.weixin.qq.com/index.php/core/cert/api_cert#/api-cert-manage"
|
||||
target="_blank"
|
||||
>
|
||||
前往微信商户平台查看证书序列号
|
||||
</a>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label="备注" label-width="180px" prop="remark">
|
||||
<el-input v-model="formData.remark" :style="{ width: '100%' }" />
|
||||
|
@ -53,6 +53,10 @@
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
新增
|
||||
</el-button>
|
||||
<el-button plain type="danger" @click="toggleExpandAll">
|
||||
<Icon class="mr-5px" icon="ep:sort" />
|
||||
展开/折叠
|
||||
</el-button>
|
||||
<el-button plain @click="refreshMenu">
|
||||
<Icon class="mr-5px" icon="ep:refresh" />
|
||||
刷新菜单缓存
|
||||
@ -63,149 +67,169 @@
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<div style="height: 700px">
|
||||
<!-- AutoResizer 自动调节大小 -->
|
||||
<el-auto-resizer>
|
||||
<template #default="{ height, width }">
|
||||
<!-- Virtualized Table 虚拟化表格:高性能,解决表格在大数据量下的卡顿问题 -->
|
||||
<template #default="{ width }">
|
||||
<el-table-v2
|
||||
v-loading="loading"
|
||||
v-model:expanded-row-keys="expandedRowKeys"
|
||||
:columns="columns"
|
||||
:data="list"
|
||||
:expand-column-key="columns[0].key"
|
||||
:height="1000"
|
||||
:width="width"
|
||||
:height="height"
|
||||
expand-column-key="name"
|
||||
fixed
|
||||
row-key="id"
|
||||
/>
|
||||
</template>
|
||||
</el-auto-resizer>
|
||||
</div>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<MenuForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="tsx" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { handleTree } from '@/utils/tree'
|
||||
import * as MenuApi from '@/api/system/menu'
|
||||
import { MenuVO } from '@/api/system/menu'
|
||||
import MenuForm from './MenuForm.vue'
|
||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
||||
import { h } from 'vue'
|
||||
import { Column, ElButton } from 'element-plus'
|
||||
import DictTag from '@/components/DictTag/src/DictTag.vue'
|
||||
import { Icon } from '@/components/Icon'
|
||||
import { hasPermission } from '@/directives/permission/hasPermi'
|
||||
import { ElButton, TableV2FixedDir } from 'element-plus'
|
||||
import { checkPermi } from '@/utils/permission'
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
||||
|
||||
defineOptions({ name: 'SystemMenu' })
|
||||
|
||||
// 虚拟列表表格
|
||||
const columns = [
|
||||
{
|
||||
key: 'name',
|
||||
title: '菜单名称',
|
||||
dataKey: 'name',
|
||||
width: 250,
|
||||
fixed: TableV2FixedDir.LEFT
|
||||
},
|
||||
{
|
||||
key: 'icon',
|
||||
title: '图标',
|
||||
dataKey: 'icon',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
cellRenderer: ({ cellData: icon }) => <Icon icon={icon} />
|
||||
},
|
||||
{
|
||||
key: 'sort',
|
||||
title: '排序',
|
||||
dataKey: 'sort',
|
||||
width: 60
|
||||
},
|
||||
{
|
||||
key: 'permission',
|
||||
title: '权限标识',
|
||||
dataKey: 'permission',
|
||||
width: 300
|
||||
},
|
||||
{
|
||||
key: 'component',
|
||||
title: '组件路径',
|
||||
dataKey: 'component',
|
||||
width: 500
|
||||
},
|
||||
{
|
||||
key: 'componentName',
|
||||
title: '组件名称',
|
||||
dataKey: 'componentName',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
title: '状态',
|
||||
dataKey: 'status',
|
||||
width: 60,
|
||||
fixed: TableV2FixedDir.RIGHT,
|
||||
cellRenderer: ({ rowData }) => {
|
||||
// 检查权限
|
||||
if (!checkPermi(['system:menu:update'])) {
|
||||
return <DictTag type={DICT_TYPE.COMMON_STATUS} value={rowData.status} />
|
||||
}
|
||||
|
||||
// 如果有权限,渲染 ElSwitch
|
||||
return (
|
||||
<ElSwitch
|
||||
v-model={rowData.status}
|
||||
active-value={CommonStatusEnum.ENABLE}
|
||||
inactive-value={CommonStatusEnum.DISABLE}
|
||||
loading={menuStatusUpdating[rowData.id]}
|
||||
class="ml-4px"
|
||||
onChange={(val) => handleStatusChanged(rowData, val)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'operations',
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 160,
|
||||
fixed: TableV2FixedDir.RIGHT,
|
||||
cellRenderer: ({ rowData }) => {
|
||||
// 定义按钮列表
|
||||
const buttons = []
|
||||
|
||||
// 检查权限并添加按钮
|
||||
if (checkPermi(['system:menu:update'])) {
|
||||
buttons.push(
|
||||
<ElButton key="edit" link type="primary" onClick={() => openForm('update', rowData.id)}>
|
||||
修改
|
||||
</ElButton>
|
||||
)
|
||||
}
|
||||
if (checkPermi(['system:menu:create'])) {
|
||||
buttons.push(
|
||||
<ElButton
|
||||
key="create"
|
||||
link
|
||||
type="primary"
|
||||
onClick={() => openForm('create', undefined, rowData.id)}
|
||||
>
|
||||
新增
|
||||
</ElButton>
|
||||
)
|
||||
}
|
||||
if (checkPermi(['system:menu:delete'])) {
|
||||
buttons.push(
|
||||
<ElButton key="delete" link type="danger" onClick={() => handleDelete(rowData.id)}>
|
||||
删除
|
||||
</ElButton>
|
||||
)
|
||||
}
|
||||
// 如果没有权限,返回 null
|
||||
if (buttons.length === 0) {
|
||||
return null
|
||||
}
|
||||
// 渲染按钮列表
|
||||
return <>{buttons}</>
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const { wsCache } = useCache()
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
// 表格的 column 字段
|
||||
const columns: Column[] = [
|
||||
{
|
||||
dataKey: 'name',
|
||||
title: '菜单名称',
|
||||
width: 250
|
||||
},
|
||||
{
|
||||
dataKey: 'icon',
|
||||
title: '图标',
|
||||
width: 150,
|
||||
cellRenderer: ({ rowData }) => {
|
||||
return h(Icon, {
|
||||
icon: rowData.icon
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
dataKey: 'sort',
|
||||
title: '排序',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
dataKey: 'permission',
|
||||
title: '权限标识',
|
||||
width: 240
|
||||
},
|
||||
{
|
||||
dataKey: 'component',
|
||||
title: '组件路径',
|
||||
width: 240
|
||||
},
|
||||
{
|
||||
dataKey: 'componentName',
|
||||
title: '组件名称',
|
||||
width: 240
|
||||
},
|
||||
{
|
||||
dataKey: 'status',
|
||||
title: '状态',
|
||||
width: 160,
|
||||
cellRenderer: ({ rowData }) => {
|
||||
return h(ElSwitch, {
|
||||
modelValue: rowData.status,
|
||||
activeValue: CommonStatusEnum.ENABLE,
|
||||
inactiveValue: CommonStatusEnum.DISABLE,
|
||||
loading: menuStatusUpdating.value[rowData.id],
|
||||
disabled: !hasPermission(['system:menu:update']),
|
||||
onChange: (val) => handleStatusChanged(rowData, val as number)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
dataKey: 'operation',
|
||||
title: '操作',
|
||||
width: 200,
|
||||
cellRenderer: ({ rowData }) => {
|
||||
return h(
|
||||
'div',
|
||||
{},
|
||||
[
|
||||
hasPermission(['system:menu:update']) &&
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
link: true,
|
||||
type: 'primary',
|
||||
onClick: () => openForm('update', rowData.id)
|
||||
},
|
||||
() => '修改'
|
||||
),
|
||||
hasPermission(['system:menu:create']) &&
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
link: true,
|
||||
type: 'primary',
|
||||
onClick: () => openForm('create', undefined, rowData.id)
|
||||
},
|
||||
() => '新增'
|
||||
),
|
||||
hasPermission(['system:menu:delete']) &&
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
link: true,
|
||||
type: 'danger',
|
||||
onClick: () => handleDelete(rowData.id)
|
||||
},
|
||||
() => '删除'
|
||||
)
|
||||
].filter(Boolean)
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<any>([]) // 列表的数据
|
||||
const list = ref<any[]>([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
name: undefined,
|
||||
status: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const isExpandAll = ref(false) // 是否展开,默认全部折叠
|
||||
const refreshTable = ref(true) // 重新渲染表格状态
|
||||
|
||||
// 添加展开行控制
|
||||
const expandedRowKeys = ref<number[]>([])
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
@ -235,6 +259,18 @@ const openForm = (type: string, id?: number, parentId?: number) => {
|
||||
formRef.value.open(type, id, parentId)
|
||||
}
|
||||
|
||||
/** 展开/折叠操作 */
|
||||
const toggleExpandAll = () => {
|
||||
if (!isExpandAll.value) {
|
||||
// 展开所有
|
||||
expandedRowKeys.value = list.value.map((item) => item.id)
|
||||
} else {
|
||||
// 折叠所有
|
||||
expandedRowKeys.value = []
|
||||
}
|
||||
isExpandAll.value = !isExpandAll.value
|
||||
}
|
||||
|
||||
/** 刷新菜单缓存按钮操作 */
|
||||
const refreshMenu = async () => {
|
||||
try {
|
||||
|
@ -124,6 +124,7 @@
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
:disabled="!checkPermi(['system:user:update'])"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
Loading…
x
Reference in New Issue
Block a user