mirror of
https://gitee.com/hhyykk/ipms-sjy-ui.git
synced 2025-09-11 07:31:54 +08:00
Merge branch 'dev' of https://gitee.com/wangbosheng/yudao-ui-admin-vue3 into dev
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="APP" setup>
|
||||
import { isDark } from '@/utils/is'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -32,6 +32,7 @@ $prefix-cls: #{$namespace}-app;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
padding: 0 !important;
|
||||
@@ -43,6 +44,7 @@ body {
|
||||
@extend .size;
|
||||
}
|
||||
}
|
||||
|
||||
.#{$prefix-cls}-grey-mode {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
@@ -17,17 +17,17 @@ export interface CategoryVO {
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* 分类图片
|
||||
* 移动端分类图
|
||||
*/
|
||||
picUrl: string
|
||||
/**
|
||||
* PC 端分类图
|
||||
*/
|
||||
bigPicUrl?: string
|
||||
/**
|
||||
* 分类排序
|
||||
*/
|
||||
sort?: number
|
||||
/**
|
||||
* 分类描述
|
||||
*/
|
||||
description?: string
|
||||
sort: number
|
||||
/**
|
||||
* 开启状态
|
||||
*/
|
||||
|
39
src/api/mall/product/management/spu.ts
Normal file
39
src/api/mall/product/management/spu.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import request from '@/config/axios'
|
||||
import type { SpuType } from './type/spuType' // TODO @puhui999: type 和 api 一起放,简单一点哈~
|
||||
|
||||
// TODO @puhui999:中英文之间有空格
|
||||
|
||||
// 获得spu列表 TODO @puhui999:这个是 getSpuPage 哈
|
||||
export const getSpuList = (params: PageParam) => {
|
||||
return request.get({ url: '/product/spu/page', params })
|
||||
}
|
||||
|
||||
// 获得spu列表tabsCount
|
||||
export const getTabsCount = () => {
|
||||
return request.get({ url: '/product/spu/tabsCount' })
|
||||
}
|
||||
|
||||
// 创建商品spu
|
||||
export const createSpu = (data: SpuType) => {
|
||||
return request.post({ url: '/product/spu/create', data })
|
||||
}
|
||||
|
||||
// 更新商品spu
|
||||
export const updateSpu = (data: SpuType) => {
|
||||
return request.put({ url: '/product/spu/update', data })
|
||||
}
|
||||
|
||||
// 更新商品spu status
|
||||
export const updateStatus = (data: { id: number; status: number }) => {
|
||||
return request.put({ url: '/product/spu/updateStatus', data })
|
||||
}
|
||||
|
||||
// 获得商品 spu
|
||||
export const getSpu = (id: number) => {
|
||||
return request.get({ url: `/product/spu/get-detail?id=${id}` })
|
||||
}
|
||||
|
||||
// 删除商品Spu
|
||||
export const deleteSpu = (id: number) => {
|
||||
return request.delete({ url: `/product/spu/delete?id=${id}` })
|
||||
}
|
79
src/api/mall/product/management/type/skuType.ts
Normal file
79
src/api/mall/product/management/type/skuType.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
export interface Property {
|
||||
/**
|
||||
* 属性编号
|
||||
*
|
||||
* 关联 {@link ProductPropertyDO#getId()}
|
||||
*/
|
||||
propertyId?: number
|
||||
/**
|
||||
* 属性值编号
|
||||
*
|
||||
* 关联 {@link ProductPropertyValueDO#getId()}
|
||||
*/
|
||||
valueId?: number
|
||||
/**
|
||||
* 属性值名称
|
||||
*/
|
||||
valueName?: string
|
||||
}
|
||||
|
||||
export interface SkuType {
|
||||
/**
|
||||
* 商品 SKU 编号,自增
|
||||
*/
|
||||
id?: number
|
||||
/**
|
||||
* SPU 编号
|
||||
*/
|
||||
spuId?: number
|
||||
/**
|
||||
* 属性数组,JSON 格式
|
||||
*/
|
||||
properties?: Property[]
|
||||
/**
|
||||
* 商品价格,单位:分
|
||||
*/
|
||||
price?: number
|
||||
/**
|
||||
* 市场价,单位:分
|
||||
*/
|
||||
marketPrice?: number
|
||||
/**
|
||||
* 成本价,单位:分
|
||||
*/
|
||||
costPrice?: number
|
||||
/**
|
||||
* 商品条码
|
||||
*/
|
||||
barCode?: string
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
picUrl?: string
|
||||
/**
|
||||
* 库存
|
||||
*/
|
||||
stock?: number
|
||||
/**
|
||||
* 商品重量,单位:kg 千克
|
||||
*/
|
||||
weight?: number
|
||||
/**
|
||||
* 商品体积,单位:m^3 平米
|
||||
*/
|
||||
volume?: number
|
||||
|
||||
/**
|
||||
* 一级分销的佣金,单位:分
|
||||
*/
|
||||
subCommissionFirstPrice?: number
|
||||
/**
|
||||
* 二级分销的佣金,单位:分
|
||||
*/
|
||||
subCommissionSecondPrice?: number
|
||||
|
||||
/**
|
||||
* 商品销量
|
||||
*/
|
||||
salesCount?: number
|
||||
}
|
25
src/api/mall/product/management/type/spuType.ts
Normal file
25
src/api/mall/product/management/type/spuType.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { SkuType } from './skuType'
|
||||
|
||||
export interface SpuType {
|
||||
id?: number
|
||||
name?: string // 商品名称
|
||||
categoryId?: number | null // 商品分类
|
||||
keyword?: string // 关键字
|
||||
unit?: number | null // 单位
|
||||
picUrl?: string // 商品封面图
|
||||
sliderPicUrls?: string[] // 商品轮播图
|
||||
introduction?: string // 商品简介
|
||||
deliveryTemplateId?: number // 运费模版
|
||||
specType?: boolean // 商品规格
|
||||
subCommissionType?: boolean // 分销类型
|
||||
skus: SkuType[] // sku数组
|
||||
description?: string // 商品详情
|
||||
sort?: string // 商品排序
|
||||
giveIntegral?: number // 赠送积分
|
||||
virtualSalesCount?: number // 虚拟销量
|
||||
recommendHot?: boolean // 是否热卖
|
||||
recommendBenefit?: boolean // 是否优惠
|
||||
recommendBest?: boolean // 是否精品
|
||||
recommendNew?: boolean // 是否新品
|
||||
recommendGood?: boolean // 是否优品
|
||||
}
|
@@ -71,8 +71,8 @@ export const getPropertyList = (params: any) => {
|
||||
}
|
||||
|
||||
// 获得属性项列表
|
||||
export const getPropertyListAndValue = (params: any) => {
|
||||
return request.get({ url: '/product/property/get-value-list', params })
|
||||
export const getPropertyListAndValue = (data: any) => {
|
||||
return request.post({ url: '/product/property/get-value-list', data })
|
||||
}
|
||||
|
||||
// ------------------------ 属性值 -------------------
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface AccountVO {
|
||||
id?: number
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
|
@@ -39,9 +39,9 @@ export const getMerchant = (id: number) => {
|
||||
}
|
||||
|
||||
// 根据商户名称搜索商户列表
|
||||
export const getMerchantListByName = (name: string) => {
|
||||
export const getMerchantListByName = (name?: string) => {
|
||||
return request.get({
|
||||
url: '/pay/merchant/list-by-name?id=',
|
||||
url: '/pay/merchant/list-by-name',
|
||||
params: {
|
||||
name: name
|
||||
}
|
||||
|
@@ -88,6 +88,11 @@ export const getOrder = async (id: number) => {
|
||||
return await request.get({ url: '/pay/order/get?id=' + id })
|
||||
}
|
||||
|
||||
// 获得支付订单的明细
|
||||
export const getOrderDetail = async (id: number) => {
|
||||
return await request.get({ url: '/pay/order/get-detail?id=' + id })
|
||||
}
|
||||
|
||||
// 新增支付订单
|
||||
export const createOrder = async (data: OrderVO) => {
|
||||
return await request.post({ url: '/pay/order/create', data })
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface NotifyTemplateVO {
|
||||
id: number
|
||||
id?: number
|
||||
name: string
|
||||
nickname: string
|
||||
code: string
|
||||
content: string
|
||||
type: number
|
||||
@@ -11,36 +12,29 @@ export interface NotifyTemplateVO {
|
||||
remark: string
|
||||
}
|
||||
|
||||
export interface NotifyTemplatePageReqVO extends PageParam {
|
||||
name?: string
|
||||
code?: string
|
||||
status?: number
|
||||
createTime?: Date[]
|
||||
}
|
||||
|
||||
export interface NotifySendReqVO {
|
||||
userId: number
|
||||
userId: number | null
|
||||
templateCode: string
|
||||
templateParams: Map<String, Object>
|
||||
}
|
||||
|
||||
// 查询站内信模板列表
|
||||
export const getNotifyTemplatePageApi = async (params: NotifyTemplatePageReqVO) => {
|
||||
export const getNotifyTemplatePage = async (params: PageParam) => {
|
||||
return await request.get({ url: '/system/notify-template/page', params })
|
||||
}
|
||||
|
||||
// 查询站内信模板详情
|
||||
export const getNotifyTemplateApi = async (id: number) => {
|
||||
export const getNotifyTemplate = async (id: number) => {
|
||||
return await request.get({ url: '/system/notify-template/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增站内信模板
|
||||
export const createNotifyTemplateApi = async (data: NotifyTemplateVO) => {
|
||||
export const createNotifyTemplate = async (data: NotifyTemplateVO) => {
|
||||
return await request.post({ url: '/system/notify-template/create', data })
|
||||
}
|
||||
|
||||
// 修改站内信模板
|
||||
export const updateNotifyTemplateApi = async (data: NotifyTemplateVO) => {
|
||||
export const updateNotifyTemplate = async (data: NotifyTemplateVO) => {
|
||||
return await request.put({ url: '/system/notify-template/update', data })
|
||||
}
|
||||
|
||||
@@ -50,6 +44,6 @@ export const deleteNotifyTemplateApi = async (id: number) => {
|
||||
}
|
||||
|
||||
// 发送站内信
|
||||
export const sendNotifyApi = (data: NotifySendReqVO) => {
|
||||
export const sendNotify = (data: NotifySendReqVO) => {
|
||||
return request.post({ url: '/system/notify-template/send-notify', data })
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="BackTop" setup>
|
||||
import { ElBacktop } from 'element-plus'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ConfigGlobal" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useLocaleStore } from '@/store/modules/locale'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
@@ -51,9 +51,9 @@ const currentLocale = computed(() => localeStore.currentLocale)
|
||||
|
||||
<template>
|
||||
<ElConfigProvider
|
||||
:namespace="variables.elNamespace"
|
||||
:locale="currentLocale.elLocale"
|
||||
:message="{ max: 1 }"
|
||||
:namespace="variables.elNamespace"
|
||||
:size="size"
|
||||
>
|
||||
<slot></slot>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ContentDetailWrap" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
@@ -21,7 +21,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="[`${prefixCls}-container`]" ref="contentDetailWrap">
|
||||
<div ref="contentDetailWrap" :class="[`${prefixCls}-container`]">
|
||||
<Sticky :offset="offset">
|
||||
<div
|
||||
:class="[
|
||||
@@ -31,7 +31,7 @@ onMounted(() => {
|
||||
>
|
||||
<div :class="[`${prefixCls}-header__back`, 'flex pl-10px pr-10px ']">
|
||||
<ElButton @click="emit('back')">
|
||||
<Icon icon="ep:arrow-left" class="mr-5px" />
|
||||
<Icon class="mr-5px" icon="ep:arrow-left" />
|
||||
{{ t('common.back') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
@@ -47,7 +47,9 @@ onMounted(() => {
|
||||
</Sticky>
|
||||
<div style="padding: var(--app-content-padding)">
|
||||
<ElCard :class="[`${prefixCls}-body`, 'mb-20px']" shadow="never">
|
||||
<div> <slot></slot> </div>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</ElCard>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ContentWrap" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
@@ -21,7 +21,7 @@ defineProps({
|
||||
<template #content>
|
||||
<div class="max-w-200px">{{ message }}</div>
|
||||
</template>
|
||||
<Icon class="ml-5px" icon="ep:question-filled" :size="14" />
|
||||
<Icon :size="14" class="ml-5px" icon="ep:question-filled" />
|
||||
</ElTooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="CountTo" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { isNumber } from '@/utils/is'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Crontab" setup>
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { PropType } from 'vue'
|
||||
|
||||
interface shortcutsType {
|
||||
text: string
|
||||
value: string
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
@@ -501,7 +503,7 @@ const submit = () => {
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<el-input v-model="defaultValue" v-bind="$attrs" class="input-with-select">
|
||||
<el-input v-model="defaultValue" class="input-with-select" v-bind="$attrs">
|
||||
<template #append>
|
||||
<el-select v-model="select" placeholder="生成器" style="width: 115px">
|
||||
<el-option label="每分钟" value="0 * * * * ?" />
|
||||
@@ -522,11 +524,11 @@ const submit = () => {
|
||||
</el-input>
|
||||
|
||||
<el-dialog
|
||||
title="cron规则生成器"
|
||||
v-model="dialogVisible"
|
||||
:width="580"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
title="cron规则生成器"
|
||||
>
|
||||
<div class="sc-cron">
|
||||
<el-tabs>
|
||||
@@ -546,38 +548,38 @@ const submit = () => {
|
||||
<el-radio-button label="3">指定</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围" v-if="cronValue.second.type == '1'">
|
||||
<el-form-item v-if="cronValue.second.type == '1'" label="范围">
|
||||
<el-input-number
|
||||
v-model="cronValue.second.range.start"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
<span style="padding: 0 15px">-</span>
|
||||
<el-input-number
|
||||
v-model="cronValue.second.range.end"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="间隔" v-if="cronValue.second.type == '2'">
|
||||
<el-form-item v-if="cronValue.second.type == '2'" label="间隔">
|
||||
<el-input-number
|
||||
v-model="cronValue.second.loop.start"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
秒开始,每
|
||||
<el-input-number
|
||||
v-model="cronValue.second.loop.end"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
秒执行一次
|
||||
</el-form-item>
|
||||
<el-form-item label="指定" v-if="cronValue.second.type == '3'">
|
||||
<el-form-item v-if="cronValue.second.type == '3'" label="指定">
|
||||
<el-select v-model="cronValue.second.appoint" multiple style="width: 100%">
|
||||
<el-option
|
||||
v-for="(item, index) in data.second"
|
||||
@@ -605,38 +607,38 @@ const submit = () => {
|
||||
<el-radio-button label="3">指定</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围" v-if="cronValue.minute.type == '1'">
|
||||
<el-form-item v-if="cronValue.minute.type == '1'" label="范围">
|
||||
<el-input-number
|
||||
v-model="cronValue.minute.range.start"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
<span style="padding: 0 15px">-</span>
|
||||
<el-input-number
|
||||
v-model="cronValue.minute.range.end"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="间隔" v-if="cronValue.minute.type == '2'">
|
||||
<el-form-item v-if="cronValue.minute.type == '2'" label="间隔">
|
||||
<el-input-number
|
||||
v-model="cronValue.minute.loop.start"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
分钟开始,每
|
||||
<el-input-number
|
||||
v-model="cronValue.minute.loop.end"
|
||||
:min="0"
|
||||
:max="59"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
分钟执行一次
|
||||
</el-form-item>
|
||||
<el-form-item label="指定" v-if="cronValue.minute.type == '3'">
|
||||
<el-form-item v-if="cronValue.minute.type == '3'" label="指定">
|
||||
<el-select v-model="cronValue.minute.appoint" multiple style="width: 100%">
|
||||
<el-option
|
||||
v-for="(item, index) in data.minute"
|
||||
@@ -664,38 +666,38 @@ const submit = () => {
|
||||
<el-radio-button label="3">指定</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围" v-if="cronValue.hour.type == '1'">
|
||||
<el-form-item v-if="cronValue.hour.type == '1'" label="范围">
|
||||
<el-input-number
|
||||
v-model="cronValue.hour.range.start"
|
||||
:min="0"
|
||||
:max="23"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
<span style="padding: 0 15px">-</span>
|
||||
<el-input-number
|
||||
v-model="cronValue.hour.range.end"
|
||||
:min="0"
|
||||
:max="23"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="间隔" v-if="cronValue.hour.type == '2'">
|
||||
<el-form-item v-if="cronValue.hour.type == '2'" label="间隔">
|
||||
<el-input-number
|
||||
v-model="cronValue.hour.loop.start"
|
||||
:min="0"
|
||||
:max="23"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
小时开始,每
|
||||
<el-input-number
|
||||
v-model="cronValue.hour.loop.end"
|
||||
:min="0"
|
||||
:max="23"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
小时执行一次
|
||||
</el-form-item>
|
||||
<el-form-item label="指定" v-if="cronValue.hour.type == '3'">
|
||||
<el-form-item v-if="cronValue.hour.type == '3'" label="指定">
|
||||
<el-select v-model="cronValue.hour.appoint" multiple style="width: 100%">
|
||||
<el-option
|
||||
v-for="(item, index) in data.hour"
|
||||
@@ -725,38 +727,38 @@ const submit = () => {
|
||||
<el-radio-button label="5">不指定</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围" v-if="cronValue.day.type == '1'">
|
||||
<el-form-item v-if="cronValue.day.type == '1'" label="范围">
|
||||
<el-input-number
|
||||
v-model="cronValue.day.range.start"
|
||||
:min="1"
|
||||
:max="31"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
<span style="padding: 0 15px">-</span>
|
||||
<el-input-number
|
||||
v-model="cronValue.day.range.end"
|
||||
:min="1"
|
||||
:max="31"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="间隔" v-if="cronValue.day.type == '2'">
|
||||
<el-form-item v-if="cronValue.day.type == '2'" label="间隔">
|
||||
<el-input-number
|
||||
v-model="cronValue.day.loop.start"
|
||||
:min="1"
|
||||
:max="31"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
号开始,每
|
||||
<el-input-number
|
||||
v-model="cronValue.day.loop.end"
|
||||
:min="1"
|
||||
:max="31"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
天执行一次
|
||||
</el-form-item>
|
||||
<el-form-item label="指定" v-if="cronValue.day.type == '3'">
|
||||
<el-form-item v-if="cronValue.day.type == '3'" label="指定">
|
||||
<el-select v-model="cronValue.day.appoint" multiple style="width: 100%">
|
||||
<el-option
|
||||
v-for="(item, index) in data.day"
|
||||
@@ -784,38 +786,38 @@ const submit = () => {
|
||||
<el-radio-button label="3">指定</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围" v-if="cronValue.month.type == '1'">
|
||||
<el-form-item v-if="cronValue.month.type == '1'" label="范围">
|
||||
<el-input-number
|
||||
v-model="cronValue.month.range.start"
|
||||
:min="1"
|
||||
:max="12"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
<span style="padding: 0 15px">-</span>
|
||||
<el-input-number
|
||||
v-model="cronValue.month.range.end"
|
||||
:min="1"
|
||||
:max="12"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="间隔" v-if="cronValue.month.type == '2'">
|
||||
<el-form-item v-if="cronValue.month.type == '2'" label="间隔">
|
||||
<el-input-number
|
||||
v-model="cronValue.month.loop.start"
|
||||
:min="1"
|
||||
:max="12"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
月开始,每
|
||||
<el-input-number
|
||||
v-model="cronValue.month.loop.end"
|
||||
:min="1"
|
||||
:max="12"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
月执行一次
|
||||
</el-form-item>
|
||||
<el-form-item label="指定" v-if="cronValue.month.type == '3'">
|
||||
<el-form-item v-if="cronValue.month.type == '3'" label="指定">
|
||||
<el-select v-model="cronValue.month.appoint" multiple style="width: 100%">
|
||||
<el-option
|
||||
v-for="(item, index) in data.month"
|
||||
@@ -846,7 +848,7 @@ const submit = () => {
|
||||
<el-radio-button label="5">不指定</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围" v-if="cronValue.week.type == '1'">
|
||||
<el-form-item v-if="cronValue.week.type == '1'" label="范围">
|
||||
<el-select v-model="cronValue.week.range.start">
|
||||
<el-option
|
||||
v-for="(item, index) in data.week"
|
||||
@@ -865,12 +867,12 @@ const submit = () => {
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="间隔" v-if="cronValue.week.type == '2'">
|
||||
<el-form-item v-if="cronValue.week.type == '2'" label="间隔">
|
||||
第
|
||||
<el-input-number
|
||||
v-model="cronValue.week.loop.start"
|
||||
:min="1"
|
||||
:max="4"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
周的星期
|
||||
@@ -884,7 +886,7 @@ const submit = () => {
|
||||
</el-select>
|
||||
执行一次
|
||||
</el-form-item>
|
||||
<el-form-item label="指定" v-if="cronValue.week.type == '3'">
|
||||
<el-form-item v-if="cronValue.week.type == '3'" label="指定">
|
||||
<el-select v-model="cronValue.week.appoint" multiple style="width: 100%">
|
||||
<el-option
|
||||
v-for="(item, index) in data.week"
|
||||
@@ -894,7 +896,7 @@ const submit = () => {
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="最后一周" v-if="cronValue.week.type == '4'">
|
||||
<el-form-item v-if="cronValue.week.type == '4'" label="最后一周">
|
||||
<el-select v-model="cronValue.week.last">
|
||||
<el-option
|
||||
v-for="(item, index) in data.week"
|
||||
@@ -924,12 +926,12 @@ const submit = () => {
|
||||
<el-radio-button label="3">指定</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围" v-if="cronValue.year.type == '1'">
|
||||
<el-form-item v-if="cronValue.year.type == '1'" label="范围">
|
||||
<el-input-number v-model="cronValue.year.range.start" controls-position="right" />
|
||||
<span style="padding: 0 15px">-</span>
|
||||
<el-input-number v-model="cronValue.year.range.end" controls-position="right" />
|
||||
</el-form-item>
|
||||
<el-form-item label="间隔" v-if="cronValue.year.type == '2'">
|
||||
<el-form-item v-if="cronValue.year.type == '2'" label="间隔">
|
||||
<el-input-number v-model="cronValue.year.loop.start" controls-position="right" />
|
||||
年开始,每
|
||||
<el-input-number
|
||||
@@ -939,7 +941,7 @@ const submit = () => {
|
||||
/>
|
||||
年执行一次
|
||||
</el-form-item>
|
||||
<el-form-item label="指定" v-if="cronValue.year.type == '3'">
|
||||
<el-form-item v-if="cronValue.year.type == '3'" label="指定">
|
||||
<el-select v-model="cronValue.year.appoint" multiple style="width: 100%">
|
||||
<el-option
|
||||
v-for="(item, index) in data.year"
|
||||
@@ -968,16 +970,19 @@ const submit = () => {
|
||||
padding: 0 7px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.sc-cron-num {
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sc-cron-num h2 {
|
||||
font-size: 12px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.sc-cron-num h4 {
|
||||
display: block;
|
||||
height: 32px;
|
||||
@@ -988,13 +993,16 @@ const submit = () => {
|
||||
background: var(--el-color-primary-light-9);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.sc-cron:deep(.el-tabs__item.is-active) .sc-cron-num h4 {
|
||||
background: var(--el-color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .sc-cron-num h4 {
|
||||
background: var(--el-color-white);
|
||||
}
|
||||
|
||||
.input-with-select .el-input-group__prepend {
|
||||
background-color: var(--el-fill-color-blank);
|
||||
}
|
||||
|
@@ -2,26 +2,26 @@
|
||||
<div>
|
||||
<Dialog
|
||||
v-model="dialogVisible"
|
||||
:title="t('cropper.modalTitle')"
|
||||
width="800px"
|
||||
maxHeight="380px"
|
||||
:canFullscreen="false"
|
||||
:title="t('cropper.modalTitle')"
|
||||
maxHeight="380px"
|
||||
width="800px"
|
||||
>
|
||||
<div :class="prefixCls">
|
||||
<div :class="`${prefixCls}-left`">
|
||||
<div :class="`${prefixCls}-cropper`">
|
||||
<CropperImage
|
||||
v-if="src"
|
||||
:circled="circled"
|
||||
:src="src"
|
||||
height="300px"
|
||||
:circled="circled"
|
||||
@cropend="handleCropend"
|
||||
@ready="handleReady"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div :class="`${prefixCls}-toolbar`">
|
||||
<el-upload :fileList="[]" accept="image/*" :beforeUpload="handleBeforeUpload">
|
||||
<el-upload :beforeUpload="handleBeforeUpload" :fileList="[]" accept="image/*">
|
||||
<el-tooltip :content="t('cropper.selectImage')" placement="bottom">
|
||||
<XButton preIcon="ant-design:upload-outlined" type="primary" />
|
||||
</el-tooltip>
|
||||
@@ -29,64 +29,64 @@
|
||||
<el-space>
|
||||
<el-tooltip :content="t('cropper.btn_reset')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
:disabled="!src"
|
||||
preIcon="ant-design:reload-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
type="primary"
|
||||
@click="handlerToolbar('reset')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_rotate_left')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
:disabled="!src"
|
||||
preIcon="ant-design:rotate-left-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
type="primary"
|
||||
@click="handlerToolbar('rotate', -45)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_rotate_right')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
:disabled="!src"
|
||||
preIcon="ant-design:rotate-right-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
type="primary"
|
||||
@click="handlerToolbar('rotate', 45)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_scale_x')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
:disabled="!src"
|
||||
preIcon="vaadin:arrows-long-h"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
type="primary"
|
||||
@click="handlerToolbar('scaleX')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_scale_y')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
:disabled="!src"
|
||||
preIcon="vaadin:arrows-long-v"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
type="primary"
|
||||
@click="handlerToolbar('scaleY')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_zoom_in')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
:disabled="!src"
|
||||
preIcon="ant-design:zoom-in-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
type="primary"
|
||||
@click="handlerToolbar('zoom', 0.1)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_zoom_out')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
:disabled="!src"
|
||||
preIcon="ant-design:zoom-out-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
type="primary"
|
||||
@click="handlerToolbar('zoom', -0.1)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
@@ -95,14 +95,14 @@
|
||||
</div>
|
||||
<div :class="`${prefixCls}-right`">
|
||||
<div :class="`${prefixCls}-preview`">
|
||||
<img :src="previewSource" v-if="previewSource" :alt="t('cropper.preview')" />
|
||||
<img v-if="previewSource" :alt="t('cropper.preview')" :src="previewSource" />
|
||||
</div>
|
||||
<template v-if="previewSource">
|
||||
<div :class="`${prefixCls}-group`">
|
||||
<el-avatar :src="previewSource" size="large" />
|
||||
<el-avatar :src="previewSource" :size="48" />
|
||||
<el-avatar :src="previewSource" :size="64" />
|
||||
<el-avatar :src="previewSource" :size="80" />
|
||||
<el-avatar :size="48" :src="previewSource" />
|
||||
<el-avatar :size="64" :src="previewSource" />
|
||||
<el-avatar :size="80" :src="previewSource" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -113,7 +113,7 @@
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="CopperModal" setup>
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { dataURLtoBlob } from '@/utils/filt'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@@ -173,12 +173,15 @@ async function handleOk() {
|
||||
const blob = dataURLtoBlob(previewSource.value)
|
||||
emit('uploadSuccess', { source: previewSource.value, data: blob, filename: filename })
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
defineExpose({ openModal, closeModal })
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
@@ -3,14 +3,14 @@
|
||||
<img
|
||||
v-show="isReady"
|
||||
ref="imgElRef"
|
||||
:src="src"
|
||||
:alt="alt"
|
||||
:crossorigin="crossorigin"
|
||||
:src="src"
|
||||
:style="getImageStyle"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Cropper" setup>
|
||||
import { CSSProperties, PropType } from 'vue'
|
||||
import Cropper from 'cropperjs'
|
||||
import 'cropperjs/dist/cropper.css'
|
||||
|
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="user-info-head" @click="open()">
|
||||
<img :src="sourceValue" v-if="sourceValue" class="img-circle img-lg" alt="avatar" />
|
||||
<el-button :class="`${prefixCls}-upload-btn`" @click="open()" v-if="showBtn">
|
||||
<img v-if="sourceValue" :src="sourceValue" alt="avatar" class="img-circle img-lg" />
|
||||
<el-button v-if="showBtn" :class="`${prefixCls}-upload-btn`" @click="open()">
|
||||
{{ btnText ? btnText : t('cropper.selectImage') }}
|
||||
</el-button>
|
||||
<CopperModal
|
||||
ref="cropperModelRef"
|
||||
@upload-success="handleUploadSuccess"
|
||||
:srcValue="sourceValue"
|
||||
@upload-success="handleUploadSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="CropperAvatar" setup>
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
@@ -54,9 +54,11 @@ function handleUploadSuccess({ source, data, filename }) {
|
||||
function open() {
|
||||
cropperModelRef.value.openModal()
|
||||
}
|
||||
|
||||
function close() {
|
||||
cropperModelRef.value.closeModal()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
@@ -104,17 +106,21 @@ $prefix-cls: #{$namespace}--cropper-avatar;
|
||||
margin: 10px auto;
|
||||
}
|
||||
}
|
||||
|
||||
.user-info-head {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.user-info-head:hover:after {
|
||||
content: '+';
|
||||
position: absolute;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Descriptions" setup>
|
||||
import { PropType } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -84,7 +84,7 @@ const toggleClick = () => {
|
||||
<div class="flex items-center">
|
||||
{{ title }}
|
||||
<ElTooltip v-if="message" :content="message" placement="right">
|
||||
<Icon icon="ep:warning" class="ml-5px" />
|
||||
<Icon class="ml-5px" icon="ep:warning" />
|
||||
</ElTooltip>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,8 +95,8 @@ const toggleClick = () => {
|
||||
<div v-show="show" :class="[`${prefixCls}-content`, 'p-10px']">
|
||||
<ElDescriptions
|
||||
:column="props.columns"
|
||||
border
|
||||
:direction="mobile ? 'vertical' : 'horizontal'"
|
||||
border
|
||||
v-bind="getBindValue"
|
||||
>
|
||||
<template v-if="slots['extra']" #extra>
|
||||
@@ -114,8 +114,8 @@ const toggleClick = () => {
|
||||
:row="{
|
||||
label: item.label
|
||||
}"
|
||||
>{{ item.label }}</slot
|
||||
>
|
||||
>{{ item.label }}
|
||||
</slot>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Dialog" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { isNumber } from '@/utils/is'
|
||||
|
||||
@@ -59,13 +59,13 @@ const dialogStyle = computed(() => {
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-bind="getBindValue"
|
||||
:fullscreen="isFullscreen"
|
||||
destroy-on-close
|
||||
lock-scroll
|
||||
draggable
|
||||
:width="width"
|
||||
:close-on-click-modal="true"
|
||||
:fullscreen="isFullscreen"
|
||||
:width="width"
|
||||
destroy-on-close
|
||||
draggable
|
||||
lock-scroll
|
||||
v-bind="getBindValue"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex justify-between">
|
||||
@@ -74,8 +74,8 @@ const dialogStyle = computed(() => {
|
||||
</slot>
|
||||
<Icon
|
||||
v-if="fullscreen"
|
||||
class="mr-22px cursor-pointer is-hover mt-2px z-10"
|
||||
:icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'"
|
||||
class="mr-22px cursor-pointer is-hover mt-2px z-10"
|
||||
color="var(--el-color-info)"
|
||||
@click="toggleFull"
|
||||
/>
|
||||
@@ -83,7 +83,7 @@ const dialogStyle = computed(() => {
|
||||
</template>
|
||||
|
||||
<!-- 情况一:如果 scroll 为 true,说明开启滚动条 -->
|
||||
<ElScrollbar :style="dialogStyle" v-if="scroll">
|
||||
<ElScrollbar v-if="scroll" :style="dialogStyle">
|
||||
<slot></slot>
|
||||
</ElScrollbar>
|
||||
<!-- 情况二:如果 scroll 为 false,说明关闭滚动条滚动条 -->
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="EChart" setup>
|
||||
import type { EChartsOption } from 'echarts'
|
||||
import echarts from '@/plugins/echarts'
|
||||
import { debounce } from 'lodash-es'
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Editor" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { IDomEditor, IEditorConfig, i18nChangeLanguage } from '@wangeditor/editor'
|
||||
import { i18nChangeLanguage, IDomEditor, IEditorConfig } from '@wangeditor/editor'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { isNumber } from '@/utils/is'
|
||||
import { ElMessage } from 'element-plus'
|
||||
@@ -20,7 +20,7 @@ const props = defineProps({
|
||||
editorId: propTypes.string.def('wangeEditor-1'),
|
||||
height: propTypes.oneOfType([Number, String]).def('500px'),
|
||||
editorConfig: {
|
||||
type: Object as PropType<IEditorConfig>,
|
||||
type: Object as PropType<Partial<IEditorConfig>>,
|
||||
default: () => undefined
|
||||
},
|
||||
readonly: propTypes.bool.def(false),
|
||||
@@ -147,6 +147,7 @@ const editorConfig = computed((): IEditorConfig => {
|
||||
props.editorConfig || {}
|
||||
)
|
||||
})
|
||||
|
||||
const editorStyle = computed(() => {
|
||||
return {
|
||||
height: isNumber(props.height) ? `${props.height}px` : props.height
|
||||
@@ -188,8 +189,8 @@ defineExpose({
|
||||
<!-- 编辑器 -->
|
||||
<Editor
|
||||
v-model="valueHtml"
|
||||
:editorId="editorId"
|
||||
:defaultConfig="editorConfig"
|
||||
:editorId="editorId"
|
||||
:style="editorStyle"
|
||||
@on-change="handleChange"
|
||||
@on-created="handleCreated"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Error" setup>
|
||||
import pageError from '@/assets/svgs/404.svg'
|
||||
import networkError from '@/assets/svgs/500.svg'
|
||||
import noPermission from '@/assets/svgs/403.svg'
|
||||
@@ -46,7 +46,7 @@ const btnClick = () => {
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<div class="text-center">
|
||||
<img width="350" :src="errorMap[type].url" alt="" />
|
||||
<img :src="errorMap[type].url" alt="" width="350" />
|
||||
<div class="text-14px text-[var(--el-color-info)]">{{ errorMap[type].message }}</div>
|
||||
<div class="mt-20px">
|
||||
<ElButton type="primary" @click="btnClick">{{ errorMap[type].buttonText }}</ElButton>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import type { Slots } from 'vue'
|
||||
import { getSlot } from '@/utils/tsxHelper'
|
||||
import { PlaceholderMoel } from './types'
|
||||
import { PlaceholderModel } from './types'
|
||||
import { FormSchema } from '@/types/form'
|
||||
import { ColProps } from '@/types/components'
|
||||
|
||||
@@ -10,7 +10,7 @@ import { ColProps } from '@/types/components'
|
||||
* @returns 返回提示信息对象
|
||||
* @description 用于自动设置placeholder
|
||||
*/
|
||||
export const setTextPlaceholder = (schema: FormSchema): PlaceholderMoel => {
|
||||
export const setTextPlaceholder = (schema: FormSchema): PlaceholderModel => {
|
||||
const { t } = useI18n()
|
||||
const textMap = ['Input', 'Autocomplete', 'InputNumber', 'InputPassword']
|
||||
const selectMap = ['Select', 'SelectV2', 'TimePicker', 'DatePicker', 'TimeSelect', 'TimeSelect']
|
||||
@@ -108,8 +108,8 @@ export const setItemComponentSlots = (
|
||||
/**
|
||||
*
|
||||
* @param schema Form表单结构化数组
|
||||
* @param formModel FormMoel
|
||||
* @returns FormMoel
|
||||
* @param formModel FormModel
|
||||
* @returns FormModel
|
||||
* @description 生成对应的formModel
|
||||
*/
|
||||
export const initModel = (schema: FormSchema[], formModel: Recordable) => {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { FormSchema } from '@/types/form'
|
||||
|
||||
export interface PlaceholderMoel {
|
||||
export interface PlaceholderModel {
|
||||
placeholder?: string
|
||||
startPlaceholder?: string
|
||||
endPlaceholder?: string
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="IFrame" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -20,11 +20,11 @@ onMounted(() => {
|
||||
<template>
|
||||
<div v-loading="loading" :style="'height:' + height">
|
||||
<iframe
|
||||
ref="frameRef"
|
||||
:src="props.src"
|
||||
style="width: 100%; height: 100%"
|
||||
frameborder="no"
|
||||
scrolling="auto"
|
||||
ref="frameRef"
|
||||
style="width: 100%; height: 100%"
|
||||
></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Icon" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import Iconify from '@purge-icons/generated'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -72,7 +72,7 @@ watch(
|
||||
|
||||
<template>
|
||||
<ElIcon :class="prefixCls" :color="color" :size="size">
|
||||
<svg v-if="isLocal" aria-hidden="true" :class="getSvgClass">
|
||||
<svg v-if="isLocal" :class="getSvgClass" aria-hidden="true">
|
||||
<use :xlink:href="symbolId" />
|
||||
</svg>
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="IconSelect" setup>
|
||||
import { CSSProperties } from 'vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { IconJson } from '@/components/Icon/src/data'
|
||||
@@ -95,7 +95,7 @@ watch(
|
||||
return props.modelValue
|
||||
},
|
||||
() => {
|
||||
if (props.modelValue) {
|
||||
if (props.modelValue && props.modelValue.indexOf(':') >= 0) {
|
||||
currentActiveType.value = props.modelValue.substring(0, props.modelValue.indexOf(':') + 1)
|
||||
icon.value = props.modelValue.substring(props.modelValue.indexOf(':') + 1)
|
||||
}
|
||||
@@ -116,13 +116,13 @@ watch(
|
||||
<ElInput v-model="inputValue" @click="visible = !visible">
|
||||
<template #append>
|
||||
<ElPopover
|
||||
:width="350"
|
||||
trigger="click"
|
||||
popper-class="pure-popper"
|
||||
:popper-options="{
|
||||
placement: 'auto'
|
||||
}"
|
||||
:visible="visible"
|
||||
:width="350"
|
||||
popper-class="pure-popper"
|
||||
trigger="click"
|
||||
>
|
||||
<template #reference>
|
||||
<div
|
||||
@@ -133,7 +133,7 @@ watch(
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<ElInput class="p-2" v-model="filterValue" placeholder="搜索图标" clearable />
|
||||
<ElInput v-model="filterValue" class="p-2" clearable placeholder="搜索图标" />
|
||||
<ElDivider border-style="dashed" />
|
||||
|
||||
<ElTabs v-model="currentActiveType" @tab-click="handleClick">
|
||||
@@ -143,15 +143,15 @@ watch(
|
||||
:label="pane.label"
|
||||
:name="pane.name"
|
||||
>
|
||||
<ElDivider class="tab-divider" border-style="dashed" />
|
||||
<ElDivider border-style="dashed" class="tab-divider" />
|
||||
<ElScrollbar height="220px">
|
||||
<ul class="flex flex-wrap px-2 ml-2">
|
||||
<li
|
||||
v-for="(item, key) in pageList"
|
||||
:key="key"
|
||||
:style="iconItemStyle(item)"
|
||||
:title="item"
|
||||
class="icon-item p-2 w-1/10 cursor-pointer mr-2 mt-1 flex justify-center items-center border border-solid"
|
||||
:style="iconItemStyle(item)"
|
||||
@click="onChangeIcon(item)"
|
||||
>
|
||||
<Icon :icon="currentActiveType + item" />
|
||||
@@ -163,13 +163,13 @@ watch(
|
||||
<ElDivider border-style="dashed" />
|
||||
|
||||
<ElPagination
|
||||
small
|
||||
:total="iconCount"
|
||||
:page-size="pageSize"
|
||||
:current-page="currentPage"
|
||||
:page-size="pageSize"
|
||||
:total="iconCount"
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
class="flex items-center justify-center h-10"
|
||||
layout="prev, pager, next"
|
||||
small
|
||||
@current-change="onCurrentChange"
|
||||
/>
|
||||
</ElPopover>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ImageViewer" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="InfoTip" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
@@ -34,14 +34,14 @@ const keyClick = (key: string) => {
|
||||
]"
|
||||
>
|
||||
<div v-if="title" :class="[`${prefixCls}__header`, 'flex items-center']">
|
||||
<Icon icon="ep:warning-filled" :size="22" color="var(--el-color-primary)" />
|
||||
<Icon :size="22" color="var(--el-color-primary)" icon="ep:warning-filled" />
|
||||
<span :class="[`${prefixCls}__title`, 'pl-5px text-16px font-bold']">{{ title }}</span>
|
||||
</div>
|
||||
<div :class="`${prefixCls}__content`">
|
||||
<p v-for="(item, $index) in schema" :key="$index" class="text-14px mt-15px">
|
||||
<Highlight
|
||||
:keys="typeof item === 'string' ? [] : item.keys"
|
||||
:color="highlightColor"
|
||||
:keys="typeof item === 'string' ? [] : item.keys"
|
||||
@click="keyClick"
|
||||
>
|
||||
{{ showIndex ? `${$index + 1}、` : '' }}{{ typeof item === 'string' ? item : item.label }}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="InputPassword" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useConfigGlobal } from '@/hooks/web/useConfigGlobal'
|
||||
import { zxcvbn } from '@zxcvbn-ts/core'
|
||||
import type { ZxcvbnResult } from '@zxcvbn-ts/core'
|
||||
import { zxcvbn } from '@zxcvbn-ts/core'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
@@ -57,9 +57,9 @@ const getIconName = computed(() => (unref(textType) === 'password' ? 'ep:hide' :
|
||||
|
||||
<template>
|
||||
<div :class="[prefixCls, `${prefixCls}--${configGlobal?.size}`]">
|
||||
<ElInput v-bind="$attrs" v-model="valueRef" :type="textType">
|
||||
<ElInput v-model="valueRef" :type="textType" v-bind="$attrs">
|
||||
<template #suffix>
|
||||
<Icon class="el-input__icon cursor-pointer" :icon="getIconName" @click="changeTextType" />
|
||||
<Icon :icon="getIconName" class="el-input__icon cursor-pointer" @click="changeTextType" />
|
||||
</template>
|
||||
</ElInput>
|
||||
<div
|
||||
|
@@ -2,19 +2,19 @@
|
||||
<template>
|
||||
<el-pagination
|
||||
v-show="total > 0"
|
||||
class="float-right mt-15px mb-15px"
|
||||
:background="true"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:page-sizes="[10, 20, 30, 50, 100]"
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:background="true"
|
||||
:page-sizes="[10, 20, 30, 50, 100]"
|
||||
:pager-count="pagerCount"
|
||||
:total="total"
|
||||
class="float-right mt-15px mb-15px"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
<script name="Pagination" setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { PropType, nextTick, ref, watch, computed, unref } from 'vue'
|
||||
import QRCode from 'qrcode'
|
||||
import { QRCodeRenderersOptions } from 'qrcode'
|
||||
<script lang="ts" name="Qrcode" setup>
|
||||
import { computed, nextTick, PropType, ref, unref, watch } from 'vue'
|
||||
import QRCode, { QRCodeRenderersOptions } from 'qrcode'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -230,7 +229,7 @@ const disabledClick = () => {
|
||||
@click="disabledClick"
|
||||
>
|
||||
<div class="absolute top-[50%] left-[50%] font-bold">
|
||||
<Icon icon="ep:refresh-right" :size="30" color="var(--el-color-primary)" />
|
||||
<Icon :size="30" color="var(--el-color-primary)" icon="ep:refresh-right" />
|
||||
<div>{{ disabledText }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Search" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
@@ -100,25 +100,25 @@ const setVisible = () => {
|
||||
<template>
|
||||
<!-- update by 芋艿:class="-mb-15px" 用于降低和 ContentWrap 组件的底部距离,避免空隙过大 -->
|
||||
<Form
|
||||
:is-custom="false"
|
||||
:label-width="labelWidth"
|
||||
hide-required-asterisk
|
||||
:inline="inline"
|
||||
:is-col="isCol"
|
||||
:is-custom="false"
|
||||
:label-width="labelWidth"
|
||||
:schema="newSchema"
|
||||
@register="register"
|
||||
class="-mb-15px"
|
||||
hide-required-asterisk
|
||||
@register="register"
|
||||
>
|
||||
<template #action>
|
||||
<div v-if="layout === 'inline'">
|
||||
<!-- update by 芋艿:去除搜索的 type="primary",颜色变淡一点 -->
|
||||
<ElButton v-if="showSearch" @click="search">
|
||||
<Icon icon="ep:search" class="mr-5px" />
|
||||
<Icon class="mr-5px" icon="ep:search" />
|
||||
{{ t('common.query') }}
|
||||
</ElButton>
|
||||
<!-- update by 芋艿:将 icon="ep:refresh-right" 修改成 icon="ep:refresh",和 ruoyi-vue 搜索保持一致 -->
|
||||
<ElButton v-if="showReset" @click="reset">
|
||||
<Icon icon="ep:refresh" class="mr-5px" />
|
||||
<Icon class="mr-5px" icon="ep:refresh" />
|
||||
{{ t('common.reset') }}
|
||||
</ElButton>
|
||||
<ElButton v-if="expand" text @click="setVisible">
|
||||
@@ -129,19 +129,19 @@ const setVisible = () => {
|
||||
<slot name="actionMore"></slot>
|
||||
</div>
|
||||
</template>
|
||||
<template #[name] v-for="name in Object.keys($slots)" :key="name"
|
||||
><slot :name="name"></slot
|
||||
></template>
|
||||
<template v-for="name in Object.keys($slots)" :key="name" #[name]>
|
||||
<slot :name="name"></slot>
|
||||
</template>
|
||||
</Form>
|
||||
|
||||
<template v-if="layout === 'bottom'">
|
||||
<div :style="bottonButtonStyle">
|
||||
<ElButton v-if="showSearch" type="primary" @click="search">
|
||||
<Icon icon="ep:search" class="mr-5px" />
|
||||
<Icon class="mr-5px" icon="ep:search" />
|
||||
{{ t('common.query') }}
|
||||
</ElButton>
|
||||
<ElButton v-if="showReset" @click="reset">
|
||||
<Icon icon="ep:refresh-right" class="mr-5px" />
|
||||
<Icon class="mr-5px" icon="ep:refresh-right" />
|
||||
{{ t('common.reset') }}
|
||||
</ElButton>
|
||||
<ElButton v-if="expand" text @click="setVisible">
|
||||
|
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Sticky" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { isClient, useEventListener, useWindowSize } from '@vueuse/core'
|
||||
import type { CSSProperties } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
// 距离顶部或者底部的距离(单位px)
|
||||
offset: propTypes.number.def(0),
|
||||
@@ -120,7 +121,7 @@ const reset = () => {
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div :style="{ height: height, zIndex: zIndex }" ref="refSticky">
|
||||
<div ref="refSticky" :style="{ height: height, zIndex: zIndex }">
|
||||
<div
|
||||
:class="className"
|
||||
:style="{
|
||||
|
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Tooltip" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
defineProps({
|
||||
titel: propTypes.string.def(''),
|
||||
message: propTypes.string.def(''),
|
||||
|
@@ -1,42 +1,42 @@
|
||||
<template>
|
||||
<div :class="mode == 'pop' ? 'mask' : ''" v-show="showBox">
|
||||
<div v-show="showBox" :class="mode == 'pop' ? 'mask' : ''">
|
||||
<div
|
||||
:class="mode == 'pop' ? 'verifybox' : ''"
|
||||
:style="{ 'max-width': parseInt(imgSize.width) + 20 + 'px' }"
|
||||
>
|
||||
<div class="verifybox-top" v-if="mode == 'pop'">
|
||||
<div v-if="mode == 'pop'" class="verifybox-top">
|
||||
{{ t('captcha.verification') }}
|
||||
<span class="verifybox-close" @click="closeBox">
|
||||
<i class="iconfont icon-close"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="verifybox-bottom" :style="{ padding: mode == 'pop' ? '10px' : '0' }">
|
||||
<div :style="{ padding: mode == 'pop' ? '10px' : '0' }" class="verifybox-bottom">
|
||||
<!-- 验证码容器 -->
|
||||
<component
|
||||
v-if="componentType"
|
||||
:is="componentType"
|
||||
:captchaType="captchaType"
|
||||
:type="verifyType"
|
||||
:figure="figure"
|
||||
:arith="arith"
|
||||
:mode="mode"
|
||||
:vSpace="vSpace"
|
||||
:explain="explain"
|
||||
:imgSize="imgSize"
|
||||
:blockSize="blockSize"
|
||||
:barSize="barSize"
|
||||
v-if="componentType"
|
||||
ref="instance"
|
||||
:arith="arith"
|
||||
:barSize="barSize"
|
||||
:blockSize="blockSize"
|
||||
:captchaType="captchaType"
|
||||
:explain="explain"
|
||||
:figure="figure"
|
||||
:imgSize="imgSize"
|
||||
:mode="mode"
|
||||
:type="verifyType"
|
||||
:vSpace="vSpace"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/babel">
|
||||
<script name="Verify" type="text/babel">
|
||||
/**
|
||||
* Verify 验证码组件
|
||||
* @description 分发验证码使用
|
||||
* */
|
||||
import { VerifySlide, VerifyPoints } from './Verify'
|
||||
import { VerifyPoints, VerifySlide } from './Verify'
|
||||
import { computed, ref, toRefs, watchEffect } from 'vue'
|
||||
|
||||
export default {
|
||||
@@ -155,6 +155,7 @@ export default {
|
||||
border-radius: 5px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.verifybox-top {
|
||||
padding: 0 15px;
|
||||
height: 40px;
|
||||
@@ -165,10 +166,12 @@ export default {
|
||||
border-bottom: 1px solid #e4e7eb;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.verifybox-bottom {
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.verifybox-close {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
@@ -178,6 +181,7 @@ export default {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -189,6 +193,7 @@ export default {
|
||||
/* display: none; */
|
||||
transition: all 0.5s;
|
||||
}
|
||||
|
||||
.verify-tips {
|
||||
text-indent: 10px;
|
||||
position: absolute;
|
||||
@@ -199,22 +204,27 @@ export default {
|
||||
line-height: 30px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.suc-bg {
|
||||
background-color: rgba(92, 184, 92, 0.5);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#7f5CB85C, endcolorstr=#7f5CB85C);
|
||||
}
|
||||
|
||||
.err-bg {
|
||||
background-color: rgba(217, 83, 79, 0.5);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#7fD9534F, endcolorstr=#7fD9534F);
|
||||
}
|
||||
|
||||
.tips-enter,
|
||||
.tips-leave-to {
|
||||
bottom: -30px;
|
||||
}
|
||||
|
||||
.tips-enter-active,
|
||||
.tips-leave-active {
|
||||
transition: bottom 0.5s;
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
/*常规验证码*/
|
||||
.verify-code {
|
||||
|
@@ -2,20 +2,20 @@
|
||||
<div style="position: relative">
|
||||
<div class="verify-img-out">
|
||||
<div
|
||||
class="verify-img-panel"
|
||||
:style="{
|
||||
width: setSize.imgWidth,
|
||||
height: setSize.imgHeight,
|
||||
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
|
||||
'margin-bottom': vSpace + 'px'
|
||||
}"
|
||||
class="verify-img-panel"
|
||||
>
|
||||
<div class="verify-refresh" style="z-index: 3" @click="refresh" v-show="showRefresh">
|
||||
<div v-show="showRefresh" class="verify-refresh" style="z-index: 3" @click="refresh">
|
||||
<i class="iconfont icon-refresh"></i>
|
||||
</div>
|
||||
<img
|
||||
:src="'data:image/png;base64,' + pointBackImgBase"
|
||||
ref="canvas"
|
||||
:src="'data:image/png;base64,' + pointBackImgBase"
|
||||
alt=""
|
||||
style="width: 100%; height: 100%; display: block"
|
||||
@click="bindingClick ? canvasClick($event) : undefined"
|
||||
@@ -24,7 +24,6 @@
|
||||
<div
|
||||
v-for="(tempPoint, index) in tempPoints"
|
||||
:key="index"
|
||||
class="point-area"
|
||||
:style="{
|
||||
'background-color': '#1abd6c',
|
||||
color: '#fff',
|
||||
@@ -38,6 +37,7 @@
|
||||
top: parseInt(tempPoint.y - 10) + 'px',
|
||||
left: parseInt(tempPoint.x - 10) + 'px'
|
||||
}"
|
||||
class="point-area"
|
||||
>
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
@@ -45,19 +45,19 @@
|
||||
</div>
|
||||
<!-- 'height': this.barSize.height, -->
|
||||
<div
|
||||
class="verify-bar-area"
|
||||
:style="{
|
||||
width: setSize.imgWidth,
|
||||
color: barAreaColor,
|
||||
'border-color': barAreaBorderColor,
|
||||
'line-height': barSize.height
|
||||
}"
|
||||
class="verify-bar-area"
|
||||
>
|
||||
<span class="verify-msg">{{ text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/babel" setup>
|
||||
<script name="VerifyPoints" setup type="text/babel">
|
||||
/**
|
||||
* VerifyPoints
|
||||
* @description 点选
|
||||
@@ -65,7 +65,7 @@
|
||||
import { resetSize } from './../utils/util'
|
||||
import { aesEncrypt } from './../utils/ase'
|
||||
import { getCode, reqCheck } from '@/api/login'
|
||||
import { onMounted, reactive, ref, nextTick, toRefs, getCurrentInstance } from 'vue'
|
||||
import { getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
//弹出式pop,固定fixed
|
||||
|
@@ -2,20 +2,20 @@
|
||||
<div style="position: relative">
|
||||
<div
|
||||
v-if="type === '2'"
|
||||
class="verify-img-out"
|
||||
:style="{ height: parseInt(setSize.imgHeight) + vSpace + 'px' }"
|
||||
class="verify-img-out"
|
||||
>
|
||||
<div class="verify-img-panel" :style="{ width: setSize.imgWidth, height: setSize.imgHeight }">
|
||||
<div :style="{ width: setSize.imgWidth, height: setSize.imgHeight }" class="verify-img-panel">
|
||||
<img
|
||||
:src="'data:image/png;base64,' + backImgBase"
|
||||
alt=""
|
||||
style="width: 100%; height: 100%; display: block"
|
||||
/>
|
||||
<div class="verify-refresh" @click="refresh" v-show="showRefresh">
|
||||
<div v-show="showRefresh" class="verify-refresh" @click="refresh">
|
||||
<i class="iconfont icon-refresh"></i>
|
||||
</div>
|
||||
<transition name="tips">
|
||||
<span class="verify-tips" v-if="tipWords" :class="passFlag ? 'suc-bg' : 'err-bg'">
|
||||
<span v-if="tipWords" :class="passFlag ? 'suc-bg' : 'err-bg'" class="verify-tips">
|
||||
{{ tipWords }}
|
||||
</span>
|
||||
</transition>
|
||||
@@ -23,24 +23,21 @@
|
||||
</div>
|
||||
<!-- 公共部分 -->
|
||||
<div
|
||||
class="verify-bar-area"
|
||||
:style="{ width: setSize.imgWidth, height: barSize.height, 'line-height': barSize.height }"
|
||||
class="verify-bar-area"
|
||||
>
|
||||
<span class="verify-msg" v-text="text"></span>
|
||||
<div
|
||||
class="verify-left-bar"
|
||||
:style="{
|
||||
width: leftBarWidth !== undefined ? leftBarWidth : barSize.height,
|
||||
height: barSize.height,
|
||||
'border-color': leftBarBorderColor,
|
||||
transaction: transitionWidth
|
||||
}"
|
||||
class="verify-left-bar"
|
||||
>
|
||||
<span class="verify-msg" v-text="finishText"></span>
|
||||
<div
|
||||
class="verify-move-block"
|
||||
@touchstart="start"
|
||||
@mousedown="start"
|
||||
:style="{
|
||||
width: barSize.height,
|
||||
height: barSize.height,
|
||||
@@ -48,17 +45,20 @@
|
||||
left: moveBlockLeft,
|
||||
transition: transitionLeft
|
||||
}"
|
||||
class="verify-move-block"
|
||||
@mousedown="start"
|
||||
@touchstart="start"
|
||||
>
|
||||
<i :class="['verify-icon iconfont', iconClass]" :style="{ color: iconColor }"></i>
|
||||
<div
|
||||
v-if="type === '2'"
|
||||
class="verify-sub-block"
|
||||
:style="{
|
||||
width: Math.floor((parseInt(setSize.imgWidth) * 47) / 310) + 'px',
|
||||
height: setSize.imgHeight,
|
||||
top: '-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
|
||||
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight
|
||||
}"
|
||||
class="verify-sub-block"
|
||||
>
|
||||
<img
|
||||
:src="'data:image/png;base64,' + blockBackImgBase"
|
||||
@@ -71,7 +71,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/babel" setup>
|
||||
<script name="VerifySlide" setup type="text/babel">
|
||||
/**
|
||||
* VerifySlide
|
||||
* @description 滑块
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="XButton" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
@@ -30,9 +30,9 @@ const getBindValue = computed(() => {
|
||||
|
||||
<template>
|
||||
<el-button v-bind="getBindValue" @click="onClick">
|
||||
<Icon :icon="preIcon" v-if="preIcon" class="mr-1px" />
|
||||
<Icon v-if="preIcon" :icon="preIcon" class="mr-1px" />
|
||||
{{ title ? title : '' }}
|
||||
<Icon :icon="postIcon" v-if="postIcon" class="mr-1px" />
|
||||
<Icon v-if="postIcon" :icon="postIcon" class="mr-1px" />
|
||||
</el-button>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
@@ -40,6 +40,7 @@ const getBindValue = computed(() => {
|
||||
margin-left: 0;
|
||||
padding: 8px 4px;
|
||||
}
|
||||
|
||||
:deep(.el-button.is-link) {
|
||||
margin-left: 0;
|
||||
padding: 8px 4px;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="XTextButton" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { PropType } from 'vue'
|
||||
|
||||
@@ -29,9 +29,9 @@ const getBindValue = computed(() => {
|
||||
|
||||
<template>
|
||||
<el-button link v-bind="getBindValue" @click="onClick">
|
||||
<Icon :icon="preIcon" v-if="preIcon" class="mr-1px" />
|
||||
<Icon v-if="preIcon" :icon="preIcon" class="mr-1px" />
|
||||
{{ title ? title : '' }}
|
||||
<Icon :icon="postIcon" v-if="postIcon" class="mr-1px" />
|
||||
<Icon v-if="postIcon" :icon="postIcon" class="mr-1px" />
|
||||
</el-button>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
@@ -39,6 +39,7 @@ const getBindValue = computed(() => {
|
||||
margin-left: 0;
|
||||
padding: 8px 4px;
|
||||
}
|
||||
|
||||
:deep(.el-button.is-link) {
|
||||
margin-left: 0;
|
||||
padding: 8px 4px;
|
||||
|
@@ -1,3 +0,0 @@
|
||||
import XModal from './src/XModal.vue'
|
||||
|
||||
export { XModal }
|
@@ -1,44 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
const slots = useSlots()
|
||||
|
||||
const props = defineProps({
|
||||
id: propTypes.string.def('model_1'),
|
||||
modelValue: propTypes.bool.def(false),
|
||||
fullscreen: propTypes.bool.def(false),
|
||||
loading: propTypes.bool.def(false),
|
||||
title: propTypes.string.def('弹窗'),
|
||||
width: propTypes.string.def('40%'),
|
||||
height: propTypes.string,
|
||||
minWidth: propTypes.string.def('460'),
|
||||
minHeight: propTypes.string.def('320'),
|
||||
showFooter: propTypes.bool.def(true),
|
||||
maskClosable: propTypes.bool.def(false),
|
||||
escClosable: propTypes.bool.def(false)
|
||||
})
|
||||
|
||||
const getBindValue = computed(() => {
|
||||
const attrs = useAttrs()
|
||||
const obj = { ...attrs, ...props }
|
||||
return obj
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<vxe-modal v-bind="getBindValue" destroy-on-close show-zoom resize transfer>
|
||||
<template v-if="slots.header" #header>
|
||||
<slot name="header"></slot>
|
||||
</template>
|
||||
<ElScrollbar>
|
||||
<template v-if="slots.default" #default>
|
||||
<slot name="default"></slot>
|
||||
</template>
|
||||
</ElScrollbar>
|
||||
<template v-if="slots.corner" #corner>
|
||||
<slot name="corner"></slot>
|
||||
</template>
|
||||
<template v-if="slots.footer" #footer>
|
||||
<slot name="footer"></slot>
|
||||
</template>
|
||||
</vxe-modal>
|
||||
</template>
|
@@ -1,3 +0,0 @@
|
||||
import XTable from './src/XTable.vue'
|
||||
|
||||
export { XTable }
|
@@ -1,442 +0,0 @@
|
||||
<template>
|
||||
<VxeGrid v-bind="getProps" ref="xGrid" :class="`${prefixCls}`" class="xtable-scrollbar">
|
||||
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
|
||||
<slot :name="item" v-bind="data || {}"></slot>
|
||||
</template>
|
||||
</VxeGrid>
|
||||
</template>
|
||||
<script setup lang="ts" name="XTable">
|
||||
import { PropType } from 'vue'
|
||||
import { SizeType, VxeGridInstance } from 'vxe-table'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { XTableProps } from './type'
|
||||
import { isBoolean, isFunction } from '@/utils/is'
|
||||
import styleCss from './style/dark.scss?inline'
|
||||
import download from '@/utils/download'
|
||||
|
||||
const { t } = useI18n()
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
const prefixCls = getPrefixCls('x-vxe-table')
|
||||
|
||||
const attrs = useAttrs()
|
||||
const emit = defineEmits(['register'])
|
||||
const removeStyles = () => {
|
||||
const filename = 'cssTheme'
|
||||
//移除引入的文件名
|
||||
const targetelement = 'style'
|
||||
const targetattr = 'id'
|
||||
const allsuspects = document.getElementsByTagName(targetelement)
|
||||
for (let i = allsuspects.length; i >= 0; i--) {
|
||||
if (
|
||||
allsuspects[i] &&
|
||||
allsuspects[i].getAttribute(targetattr) != null &&
|
||||
allsuspects[i].getAttribute(targetattr)?.indexOf(filename) != -1
|
||||
) {
|
||||
console.log(allsuspects[i], 'node')
|
||||
allsuspects[i].parentNode?.removeChild(allsuspects[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
const reImport = () => {
|
||||
const head = document.getElementsByTagName('head')[0]
|
||||
const style = document.createElement('style')
|
||||
style.innerText = styleCss
|
||||
style.id = 'cssTheme'
|
||||
head.appendChild(style)
|
||||
}
|
||||
watch(
|
||||
() => appStore.getIsDark,
|
||||
() => {
|
||||
if (appStore.getIsDark) {
|
||||
reImport()
|
||||
}
|
||||
if (!appStore.getIsDark) {
|
||||
removeStyles()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const currentSize = computed(() => {
|
||||
let resSize: SizeType = 'small'
|
||||
const appsize = appStore.getCurrentSize
|
||||
switch (appsize) {
|
||||
case 'large':
|
||||
resSize = 'medium'
|
||||
break
|
||||
case 'default':
|
||||
resSize = 'small'
|
||||
break
|
||||
case 'small':
|
||||
resSize = 'mini'
|
||||
break
|
||||
}
|
||||
return resSize
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
options: {
|
||||
type: Object as PropType<XTableProps>,
|
||||
default: () => {}
|
||||
}
|
||||
})
|
||||
const innerProps = ref<Partial<XTableProps>>()
|
||||
|
||||
const getProps = computed(() => {
|
||||
const options = innerProps.value || props.options
|
||||
options.size = currentSize as any
|
||||
options.height = 700
|
||||
getOptionInitConfig(options)
|
||||
getColumnsConfig(options)
|
||||
getProxyConfig(options)
|
||||
getPageConfig(options)
|
||||
getToolBarConfig(options)
|
||||
// console.log(options);
|
||||
return {
|
||||
...options,
|
||||
...attrs
|
||||
}
|
||||
})
|
||||
|
||||
const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
|
||||
|
||||
let proxyForm = false
|
||||
|
||||
const getOptionInitConfig = (options: XTableProps) => {
|
||||
options.size = currentSize as any
|
||||
options.rowConfig = {
|
||||
isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
|
||||
isHover: true // 当鼠标移到行时,是否要高亮当前行
|
||||
}
|
||||
}
|
||||
|
||||
// columns
|
||||
const getColumnsConfig = (options: XTableProps) => {
|
||||
const { allSchemas } = options
|
||||
if (!allSchemas) return
|
||||
if (allSchemas.printSchema) {
|
||||
options.printConfig = {
|
||||
columns: allSchemas.printSchema
|
||||
}
|
||||
}
|
||||
if (allSchemas.formSchema) {
|
||||
proxyForm = true
|
||||
options.formConfig = {
|
||||
enabled: true,
|
||||
titleWidth: 110,
|
||||
titleAlign: 'right',
|
||||
items: allSchemas.searchSchema
|
||||
}
|
||||
}
|
||||
if (allSchemas.tableSchema) {
|
||||
options.columns = allSchemas.tableSchema
|
||||
}
|
||||
}
|
||||
|
||||
// 动态请求
|
||||
const getProxyConfig = (options: XTableProps) => {
|
||||
const { getListApi, proxyConfig, data, isList } = options
|
||||
if (proxyConfig || data) return
|
||||
if (getListApi && isFunction(getListApi)) {
|
||||
if (!isList) {
|
||||
options.proxyConfig = {
|
||||
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
||||
form: proxyForm, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
||||
props: { result: 'list', total: 'total' },
|
||||
ajax: {
|
||||
query: async ({ page, form }) => {
|
||||
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
||||
if (options.params) {
|
||||
queryParams = Object.assign(queryParams, options.params)
|
||||
}
|
||||
if (!options?.treeConfig) {
|
||||
queryParams.pageSize = page.pageSize
|
||||
queryParams.pageNo = page.currentPage
|
||||
}
|
||||
return new Promise(async (resolve) => {
|
||||
resolve(await getListApi(queryParams))
|
||||
})
|
||||
},
|
||||
delete: ({ body }) => {
|
||||
return new Promise(async (resolve) => {
|
||||
if (options.deleteApi) {
|
||||
resolve(await options.deleteApi(JSON.stringify(body)))
|
||||
} else {
|
||||
Promise.reject('未设置deleteApi')
|
||||
}
|
||||
})
|
||||
},
|
||||
queryAll: ({ form }) => {
|
||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
||||
return new Promise(async (resolve) => {
|
||||
if (options.getAllListApi) {
|
||||
resolve(await options.getAllListApi(queryParams))
|
||||
} else {
|
||||
resolve(await getListApi(queryParams))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
options.proxyConfig = {
|
||||
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
||||
form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
||||
props: { result: 'data' },
|
||||
ajax: {
|
||||
query: ({ form }) => {
|
||||
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
||||
if (options?.params) {
|
||||
queryParams = Object.assign(queryParams, options.params)
|
||||
}
|
||||
return new Promise(async (resolve) => {
|
||||
resolve(await getListApi(queryParams))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.exportListApi) {
|
||||
options.exportConfig = {
|
||||
filename: options?.exportName,
|
||||
// 默认选中类型
|
||||
type: 'csv',
|
||||
// 自定义数据量列表
|
||||
modes: options?.getAllListApi ? ['current', 'all'] : ['current'],
|
||||
columns: options?.allSchemas?.printSchema
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
const getPageConfig = (options: XTableProps) => {
|
||||
const { pagination, pagerConfig, treeConfig, isList } = options
|
||||
if (isList) return
|
||||
if (treeConfig) {
|
||||
options.treeConfig = options.treeConfig
|
||||
return
|
||||
}
|
||||
if (pagerConfig) return
|
||||
if (pagination) {
|
||||
if (isBoolean(pagination)) {
|
||||
options.pagerConfig = {
|
||||
border: false, // 带边框
|
||||
background: false, // 带背景颜色
|
||||
perfect: false, // 配套的样式
|
||||
pageSize: 10, // 每页大小
|
||||
pagerCount: 7, // 显示页码按钮的数量
|
||||
autoHidden: false, // 当只有一页时自动隐藏
|
||||
pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
|
||||
layouts: [
|
||||
'PrevJump',
|
||||
'PrevPage',
|
||||
'JumpNumber',
|
||||
'NextPage',
|
||||
'NextJump',
|
||||
'Sizes',
|
||||
'FullJump',
|
||||
'Total'
|
||||
]
|
||||
}
|
||||
return
|
||||
}
|
||||
options.pagerConfig = pagination
|
||||
} else {
|
||||
if (pagination != false) {
|
||||
options.pagerConfig = {
|
||||
border: false, // 带边框
|
||||
background: false, // 带背景颜色
|
||||
perfect: false, // 配套的样式
|
||||
pageSize: 10, // 每页大小
|
||||
pagerCount: 7, // 显示页码按钮的数量
|
||||
autoHidden: false, // 当只有一页时自动隐藏
|
||||
pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
|
||||
layouts: [
|
||||
'Sizes',
|
||||
'PrevJump',
|
||||
'PrevPage',
|
||||
'Number',
|
||||
'NextPage',
|
||||
'NextJump',
|
||||
'FullJump',
|
||||
'Total'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tool bar
|
||||
const getToolBarConfig = (options: XTableProps) => {
|
||||
const { toolBar, toolbarConfig, topActionSlots } = options
|
||||
if (toolbarConfig) return
|
||||
if (toolBar) {
|
||||
if (!isBoolean(toolBar)) {
|
||||
console.info(2)
|
||||
options.toolbarConfig = toolBar
|
||||
return
|
||||
}
|
||||
} else if (topActionSlots != false) {
|
||||
options.toolbarConfig = {
|
||||
slots: { buttons: 'toolbar_buttons' }
|
||||
}
|
||||
} else {
|
||||
options.toolbarConfig = {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新列表
|
||||
const reload = () => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
g.commitProxy('query')
|
||||
}
|
||||
|
||||
// 删除
|
||||
const deleteData = async (id: string | number) => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
const options = innerProps.value || props.options
|
||||
if (!options.deleteApi) {
|
||||
console.error('未传入delListApi')
|
||||
return
|
||||
}
|
||||
return new Promise(async () => {
|
||||
message.delConfirm().then(async () => {
|
||||
await (options?.deleteApi && options?.deleteApi(id))
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
const deleteBatch = async () => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
const rows = g.getCheckboxRecords() || g.getRadioRecord()
|
||||
let ids: any[] = []
|
||||
if (rows.length == 0) {
|
||||
message.error('请选择数据')
|
||||
return
|
||||
} else {
|
||||
rows.forEach((row) => {
|
||||
ids.push(row.id)
|
||||
})
|
||||
}
|
||||
const options = innerProps.value || props.options
|
||||
if (options.deleteListApi) {
|
||||
return new Promise(async () => {
|
||||
message.delConfirm().then(async () => {
|
||||
await (options?.deleteListApi && options?.deleteListApi(ids))
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
reload()
|
||||
})
|
||||
})
|
||||
} else if (options.deleteApi) {
|
||||
return new Promise(async () => {
|
||||
message.delConfirm().then(async () => {
|
||||
ids.forEach(async (id) => {
|
||||
await (options?.deleteApi && options?.deleteApi(id))
|
||||
})
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
reload()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
console.error('未传入delListApi')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 导出
|
||||
const exportList = async (fileName?: string) => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
const options = innerProps.value || props.options
|
||||
if (!options?.exportListApi) {
|
||||
console.error('未传入exportListApi')
|
||||
return
|
||||
}
|
||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
|
||||
message.exportConfirm().then(async () => {
|
||||
const res = await (options?.exportListApi && options?.exportListApi(queryParams))
|
||||
download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls')
|
||||
})
|
||||
}
|
||||
|
||||
// 获取查询参数
|
||||
const getSearchData = () => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
|
||||
return queryParams
|
||||
}
|
||||
|
||||
// 获取当前列
|
||||
const getCurrentColumn = () => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
return g.getCurrentColumn()
|
||||
}
|
||||
|
||||
// 获取当前选中列,redio
|
||||
const getRadioRecord = () => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
return g.getRadioRecord(false)
|
||||
}
|
||||
|
||||
// 获取当前选中列,checkbox
|
||||
const getCheckboxRecords = () => {
|
||||
const g = unref(xGrid)
|
||||
if (!g) {
|
||||
return
|
||||
}
|
||||
return g.getCheckboxRecords(false)
|
||||
}
|
||||
const setProps = (prop: Partial<XTableProps>) => {
|
||||
innerProps.value = { ...unref(innerProps), ...prop }
|
||||
}
|
||||
|
||||
defineExpose({ reload, Ref: xGrid, getSearchData, deleteData, exportList })
|
||||
emit('register', {
|
||||
reload,
|
||||
getSearchData,
|
||||
setProps,
|
||||
deleteData,
|
||||
deleteBatch,
|
||||
exportList,
|
||||
getCurrentColumn,
|
||||
getRadioRecord,
|
||||
getCheckboxRecords
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import './style/index.scss';
|
||||
</style>
|
@@ -1,81 +0,0 @@
|
||||
// 修改样式变量
|
||||
//@import 'vxe-table/styles/variable.scss';
|
||||
|
||||
/*font*/
|
||||
$vxe-font-color: #e5e7eb;
|
||||
// $vxe-font-size: 14px !default;
|
||||
// $vxe-font-size-medium: 16px !default;
|
||||
// $vxe-font-size-small: 14px !default;
|
||||
// $vxe-font-size-mini: 12px !default;
|
||||
|
||||
/*color*/
|
||||
$vxe-primary-color: #409eff !default;
|
||||
$vxe-success-color: #67c23a !default;
|
||||
$vxe-info-color: #909399 !default;
|
||||
$vxe-warning-color: #e6a23c !default;
|
||||
$vxe-danger-color: #f56c6c !default;
|
||||
$vxe-disabled-color: #bfbfbf !default;
|
||||
$vxe-primary-disabled-color: #c0c4cc !default;
|
||||
|
||||
/*loading*/
|
||||
$vxe-loading-color: $vxe-primary-color !default;
|
||||
$vxe-loading-background-color: #1d1e1f !default;
|
||||
$vxe-loading-z-index: 999 !default;
|
||||
|
||||
/*icon*/
|
||||
$vxe-icon-font-family: Verdana, Arial, Tahoma !default;
|
||||
$vxe-icon-background-color: #e5e7eb !default;
|
||||
|
||||
/*toolbar*/
|
||||
$vxe-toolbar-background-color: #1d1e1f !default;
|
||||
$vxe-toolbar-button-border: #dcdfe6 !default;
|
||||
$vxe-toolbar-custom-active-background-color: #d9dadb !default;
|
||||
$vxe-toolbar-panel-background-color: #e5e7eb !default;
|
||||
|
||||
$vxe-table-font-color: #e5e7eb;
|
||||
$vxe-table-header-background-color: #1d1e1f;
|
||||
$vxe-table-body-background-color: #141414;
|
||||
$vxe-table-row-striped-background-color: #1d1d1d;
|
||||
$vxe-table-row-hover-background-color: #1d1e1f;
|
||||
$vxe-table-row-hover-striped-background-color: #1e1e1e;
|
||||
$vxe-table-footer-background-color: #1d1e1f;
|
||||
$vxe-table-row-current-background-color: #302d2d;
|
||||
$vxe-table-column-current-background-color: #302d2d;
|
||||
$vxe-table-column-hover-background-color: #302d2d;
|
||||
$vxe-table-row-hover-current-background-color: #302d2d;
|
||||
$vxe-table-row-checkbox-checked-background-color: #3e3c37 !default;
|
||||
$vxe-table-row-hover-checkbox-checked-background-color: #615a4a !default;
|
||||
$vxe-table-menu-background-color: #1d1e1f;
|
||||
$vxe-table-border-width: 1px !default;
|
||||
$vxe-table-border-color: #4c4d4f !default;
|
||||
$vxe-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default;
|
||||
$vxe-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default;
|
||||
|
||||
$vxe-form-background-color: #141414;
|
||||
|
||||
/*pager*/
|
||||
$vxe-pager-background-color: #1d1e1f !default;
|
||||
$vxe-pager-perfect-background-color: #262727 !default;
|
||||
$vxe-pager-perfect-button-background-color: #a7a3a3 !default;
|
||||
|
||||
$vxe-input-background-color: #141414;
|
||||
$vxe-input-border-color: #4c4d4f !default;
|
||||
|
||||
$vxe-select-option-hover-background-color: #262626 !default;
|
||||
$vxe-select-panel-background-color: #141414 !default;
|
||||
$vxe-select-empty-color: #262626 !default;
|
||||
$vxe-optgroup-title-color: #909399 !default;
|
||||
|
||||
/*button*/
|
||||
$vxe-button-default-background-color: #262626;
|
||||
$vxe-button-dropdown-panel-background-color: #141414;
|
||||
|
||||
/*modal*/
|
||||
$vxe-modal-header-background-color: #141414;
|
||||
$vxe-modal-body-background-color: #141414;
|
||||
$vxe-modal-border-color: #3b3b3b;
|
||||
|
||||
/*pulldown*/
|
||||
$vxe-pulldown-panel-background-color: #262626 !default;
|
||||
|
||||
@import 'vxe-table/styles/index.scss';
|
@@ -1,6 +0,0 @@
|
||||
// @import 'vxe-table/styles/variable.scss';
|
||||
// @import 'vxe-table/styles/modules.scss';
|
||||
// @import './theme/light.scss';
|
||||
i {
|
||||
border-color: initial;
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
// 修改样式变量
|
||||
// /*font*/
|
||||
// $vxe-font-size: 12px !default;
|
||||
// $vxe-font-size-medium: 16px !default;
|
||||
// $vxe-font-size-small: 14px !default;
|
||||
// $vxe-font-size-mini: 12px !default;
|
||||
/*color*/
|
||||
$vxe-primary-color: #409eff !default;
|
||||
$vxe-success-color: #67c23a !default;
|
||||
$vxe-info-color: #909399 !default;
|
||||
$vxe-warning-color: #e6a23c !default;
|
||||
$vxe-danger-color: #f56c6c !default;
|
||||
$vxe-disabled-color: #bfbfbf !default;
|
||||
$vxe-primary-disabled-color: #c0c4cc !default;
|
||||
|
||||
@import 'vxe-table/styles/index.scss';
|
@@ -1,26 +0,0 @@
|
||||
import { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
||||
import type { VxeGridProps, VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table'
|
||||
|
||||
export type XTableProps<D = any> = VxeGridProps<D> & {
|
||||
allSchemas?: CrudSchema
|
||||
height?: number // 高度 默认730
|
||||
topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽
|
||||
treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置
|
||||
isList?: boolean // 是否不带分页的list
|
||||
getListApi?: Function // 获取列表接口
|
||||
getAllListApi?: Function // 获取全部数据接口 用于 vxe 导出
|
||||
deleteApi?: Function // 删除接口
|
||||
deleteListApi?: Function // 批量删除接口
|
||||
exportListApi?: Function // 导出接口
|
||||
exportName?: string // 导出文件夹名称
|
||||
params?: any // 其他查询参数
|
||||
pagination?: boolean | VxeGridPropTypes.PagerConfig // 分页配置参数
|
||||
toolBar?: boolean | VxeGridPropTypes.ToolbarConfig // 右侧工具栏配置参数
|
||||
}
|
||||
export type XColumns = VxeGridPropTypes.Columns
|
||||
|
||||
export type VxeTableColumn = {
|
||||
field: string
|
||||
title?: string
|
||||
children?: VxeTableColumn[]
|
||||
} & Recordable
|
@@ -188,7 +188,13 @@
|
||||
<!-- <div id="js-properties-panel" class="panel"></div> -->
|
||||
<!-- <div class="my-process-designer__canvas" ref="bpmn-canvas"></div> -->
|
||||
</div>
|
||||
<XModal title="预览" width="80%" height="90%" v-model="previewModelVisible" destroy-on-close>
|
||||
<Dialog
|
||||
title="预览"
|
||||
v-model="previewModelVisible"
|
||||
width="80%"
|
||||
:scroll="true"
|
||||
max-height="600px"
|
||||
>
|
||||
<!-- append-to-body -->
|
||||
<div v-highlight>
|
||||
<code class="hljs">
|
||||
@@ -196,10 +202,7 @@
|
||||
{{ previewResult }}
|
||||
</code>
|
||||
</div>
|
||||
<!-- <pre>
|
||||
<code class="hljs" v-html="highlightedCode(previewType, previewResult)"></code>
|
||||
</pre> -->
|
||||
</XModal>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -231,7 +234,7 @@ import activitiModdleExtension from './plugins/extension-moddle/activiti'
|
||||
import flowableModdleExtension from './plugins/extension-moddle/flowable'
|
||||
// 引入json转换与高亮
|
||||
// import xml2js from 'xml-js'
|
||||
import xml2js from 'fast-xml-parser'
|
||||
// import xml2js from 'fast-xml-parser'
|
||||
import { XmlNode, XmlNodeType, parseXmlString } from 'steady-xml'
|
||||
// 代码高亮插件
|
||||
// import hljs from 'highlight.js/lib/highlight'
|
||||
@@ -626,7 +629,7 @@ const elementsAlign = (align) => {
|
||||
const previewProcessXML = () => {
|
||||
console.log(bpmnModeler.saveXML, 'bpmnModeler')
|
||||
bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
|
||||
console.log(xml, 'xml111111')
|
||||
// console.log(xml, 'xml111111')
|
||||
previewResult.value = xml
|
||||
previewType.value = 'xml'
|
||||
previewModelVisible.value = true
|
||||
@@ -634,7 +637,7 @@ const previewProcessXML = () => {
|
||||
}
|
||||
const previewProcessJson = () => {
|
||||
bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
|
||||
console.log(xml, 'xml')
|
||||
// console.log(xml, 'xml')
|
||||
|
||||
// const rootNode = parseXmlString(xml)
|
||||
// console.log(rootNode, 'rootNoderootNode')
|
||||
@@ -644,9 +647,9 @@ const previewProcessJson = () => {
|
||||
// console.log(JSON.stringify(rootNodes.parent.toJsObject()), 'rootNodes.toJSON()')
|
||||
// console.log(JSON.stringify(rootNodes.parent.toJSON()), 'rootNodes.toJSON()')
|
||||
|
||||
const parser = new xml2js.XMLParser()
|
||||
let jObj = parser.parse(xml)
|
||||
console.log(jObj, 'jObjjObjjObjjObjjObj')
|
||||
// const parser = new xml2js.XMLParser()
|
||||
// let jObj = parser.parse(xml)
|
||||
// console.log(jObj, 'jObjjObjjObjjObjjObj')
|
||||
// const builder = new xml2js.XMLBuilder(xml)
|
||||
// const xmlContent = builder
|
||||
// console.log(xmlContent, 'xmlContent')
|
||||
|
@@ -1,37 +1,11 @@
|
||||
import { App } from 'vue'
|
||||
import MyProcessDesigner from './designer'
|
||||
import MyProcessPenal from './penal'
|
||||
import MyProcessViewer from './designer/index2'
|
||||
|
||||
const components = [MyProcessDesigner, MyProcessPenal, MyProcessViewer]
|
||||
import './theme/index.scss'
|
||||
import 'bpmn-js/dist/assets/diagram-js.css'
|
||||
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
|
||||
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
|
||||
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
|
||||
|
||||
// const install = function (Vue) {
|
||||
// components.forEach(component => {
|
||||
// Vue.component(component.name, component)
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (typeof window !== "undefined" && window.Vue) {
|
||||
// install(window.Vue)
|
||||
// }
|
||||
// components.forEach(component => {
|
||||
// Vue.component(component.name, component)
|
||||
// })
|
||||
const componentss = {
|
||||
install: (Vue: App): void => {
|
||||
components.forEach((component) => {
|
||||
Vue.component(component.name, component)
|
||||
})
|
||||
}
|
||||
}
|
||||
// let version = "0.0.1"
|
||||
export const MyPD = (app) => {
|
||||
// export default {
|
||||
// app.use(version)
|
||||
// app.use(install)
|
||||
// app.use(MyProcessDesigner)
|
||||
// app.use(MyProcessPenal)
|
||||
// app.use(MyProcessViewer)
|
||||
// app.use(components)
|
||||
app.use(componentss)
|
||||
}
|
||||
export { MyProcessDesigner, MyProcessPenal, MyProcessViewer }
|
||||
|
@@ -111,7 +111,8 @@
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="text"
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'enum')"
|
||||
>移除</el-button
|
||||
@@ -143,7 +144,8 @@
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="text"
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'constraint')"
|
||||
>移除</el-button
|
||||
@@ -174,7 +176,8 @@
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="text"
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'property')"
|
||||
>移除</el-button
|
||||
|
@@ -1,25 +1,6 @@
|
||||
import type { App } from 'vue'
|
||||
import { Icon } from './Icon'
|
||||
import { Form } from '@/components/Form'
|
||||
import { Table } from '@/components/Table'
|
||||
import { Search } from '@/components/Search'
|
||||
import { XModal } from '@/components/XModal'
|
||||
import { XTable } from '@/components/XTable'
|
||||
import { XButton, XTextButton } from '@/components/XButton'
|
||||
import { DictTag } from '@/components/DictTag'
|
||||
import { ContentWrap } from '@/components/ContentWrap'
|
||||
import { Descriptions } from '@/components/Descriptions'
|
||||
|
||||
export const setupGlobCom = (app: App<Element>): void => {
|
||||
app.component('Icon', Icon)
|
||||
app.component('Form', Form)
|
||||
app.component('Table', Table)
|
||||
app.component('Search', Search)
|
||||
app.component('XModal', XModal)
|
||||
app.component('XTable', XTable)
|
||||
app.component('XButton', XButton)
|
||||
app.component('XTextButton', XTextButton)
|
||||
app.component('DictTag', DictTag)
|
||||
app.component('ContentWrap', ContentWrap)
|
||||
app.component('Descriptions', Descriptions)
|
||||
}
|
||||
|
@@ -29,6 +29,8 @@ type CrudSearchParams = {
|
||||
show?: boolean
|
||||
// 接口
|
||||
api?: () => Promise<any>
|
||||
// 搜索字段
|
||||
field?: string
|
||||
} & Omit<FormSchema, 'field'>
|
||||
|
||||
type CrudTableParams = {
|
||||
|
@@ -1,354 +0,0 @@
|
||||
import {
|
||||
FormItemRenderOptions,
|
||||
VxeColumnPropTypes,
|
||||
VxeFormItemProps,
|
||||
VxeGridPropTypes,
|
||||
VxeTableDefines
|
||||
} from 'vxe-table'
|
||||
import { eachTree } from 'xe-utils'
|
||||
|
||||
import { getBoolDictOptions, getDictOptions, getIntDictOptions } from '@/utils/dict'
|
||||
import { FormSchema } from '@/types/form'
|
||||
import { VxeTableColumn } from '@/types/table'
|
||||
import { ComponentOptions } from '@/types/components'
|
||||
import { DescriptionsSchema } from '@/types/descriptions'
|
||||
|
||||
export type VxeCrudSchema = {
|
||||
primaryKey?: string // 主键ID
|
||||
primaryTitle?: string // 主键标题 默认为序号
|
||||
primaryType?: VxeColumnPropTypes.Type | 'id' // 还支持 "id" | "seq" | "radio" | "checkbox" | "expand" | "html" | null
|
||||
firstColumn?: VxeColumnPropTypes.Type // 第一列显示类型
|
||||
action?: boolean // 是否开启表格内右侧操作栏插槽
|
||||
actionTitle?: string // 操作栏标题 默认为操作
|
||||
actionWidth?: string // 操作栏插槽宽度,一般2个字带图标 text 类型按钮 50-70
|
||||
columns: VxeCrudColumns[]
|
||||
searchSpan?: number
|
||||
}
|
||||
type VxeCrudColumns = Omit<VxeTableColumn, 'children'> & {
|
||||
field: string // 字段名
|
||||
title?: string // 标题名
|
||||
formatter?: VxeColumnPropTypes.Formatter // vxe formatter格式化
|
||||
isSearch?: boolean // 是否在查询显示
|
||||
search?: CrudSearchParams // 查询的详细配置
|
||||
isTable?: boolean // 是否在列表显示
|
||||
table?: CrudTableParams // 列表的详细配置
|
||||
isForm?: boolean // 是否在表单显示
|
||||
form?: CrudFormParams // 表单的详细配置
|
||||
isDetail?: boolean // 是否在详情显示
|
||||
detail?: CrudDescriptionsParams // 详情的详细配置
|
||||
print?: CrudPrintParams // vxe 打印的字段
|
||||
children?: VxeCrudColumns[] // 子级
|
||||
dictType?: string // 字典类型
|
||||
dictClass?: 'string' | 'number' | 'boolean' // 字典数据类型 string | number | boolean
|
||||
}
|
||||
|
||||
type CrudSearchParams = {
|
||||
// 是否显示在查询项
|
||||
show?: boolean
|
||||
} & Omit<VxeFormItemProps, 'field'>
|
||||
|
||||
type CrudTableParams = {
|
||||
// 是否显示表头
|
||||
show?: boolean
|
||||
} & Omit<VxeTableDefines.ColumnOptions, 'field'>
|
||||
|
||||
type CrudFormParams = {
|
||||
// 是否显示表单项
|
||||
show?: boolean
|
||||
} & Omit<FormSchema, 'field'>
|
||||
|
||||
type CrudDescriptionsParams = {
|
||||
// 是否显示表单项
|
||||
show?: boolean
|
||||
} & Omit<DescriptionsSchema, 'field'>
|
||||
|
||||
type CrudPrintParams = {
|
||||
// 是否显示打印项
|
||||
show?: boolean
|
||||
} & Omit<VxeTableDefines.ColumnInfo[], 'field'>
|
||||
|
||||
export type VxeAllSchemas = {
|
||||
searchSchema: VxeFormItemProps[]
|
||||
tableSchema: VxeGridPropTypes.Columns
|
||||
formSchema: FormSchema[]
|
||||
detailSchema: DescriptionsSchema[]
|
||||
printSchema: VxeTableDefines.ColumnInfo[]
|
||||
}
|
||||
|
||||
// 过滤所有结构
|
||||
export const useVxeCrudSchemas = (
|
||||
crudSchema: VxeCrudSchema
|
||||
): {
|
||||
allSchemas: VxeAllSchemas
|
||||
} => {
|
||||
// 所有结构数据
|
||||
const allSchemas = reactive<VxeAllSchemas>({
|
||||
searchSchema: [],
|
||||
tableSchema: [],
|
||||
formSchema: [],
|
||||
detailSchema: [],
|
||||
printSchema: []
|
||||
})
|
||||
|
||||
const searchSchema = filterSearchSchema(crudSchema)
|
||||
allSchemas.searchSchema = searchSchema || []
|
||||
|
||||
const tableSchema = filterTableSchema(crudSchema)
|
||||
allSchemas.tableSchema = tableSchema || []
|
||||
|
||||
const formSchema = filterFormSchema(crudSchema)
|
||||
allSchemas.formSchema = formSchema
|
||||
|
||||
const detailSchema = filterDescriptionsSchema(crudSchema)
|
||||
allSchemas.detailSchema = detailSchema
|
||||
|
||||
const printSchema = filterPrintSchema(crudSchema)
|
||||
allSchemas.printSchema = printSchema
|
||||
|
||||
return {
|
||||
allSchemas
|
||||
}
|
||||
}
|
||||
|
||||
// 过滤 Search 结构
|
||||
const filterSearchSchema = (crudSchema: VxeCrudSchema): VxeFormItemProps[] => {
|
||||
const { t } = useI18n()
|
||||
const span = crudSchema.searchSpan ? crudSchema.searchSpan : 6
|
||||
const spanLength = 24 / span
|
||||
const searchSchema: VxeFormItemProps[] = []
|
||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
||||
// 判断是否显示
|
||||
if (schemaItem?.isSearch || schemaItem.search?.show) {
|
||||
let itemRenderName = schemaItem?.search?.itemRender?.name || '$input'
|
||||
const options: any[] = []
|
||||
let itemRender: FormItemRenderOptions = {}
|
||||
|
||||
if (schemaItem.dictType) {
|
||||
const allOptions = { label: '全部', value: '' }
|
||||
options.push(allOptions)
|
||||
getDictOptions(schemaItem.dictType).forEach((dict) => {
|
||||
options.push(dict)
|
||||
})
|
||||
itemRender.options = options
|
||||
if (!schemaItem?.search?.itemRender?.name) itemRenderName = '$select'
|
||||
itemRender = {
|
||||
name: itemRenderName,
|
||||
options: options,
|
||||
props: { placeholder: t('common.selectText') }
|
||||
}
|
||||
} else {
|
||||
if (schemaItem.search?.itemRender) {
|
||||
itemRender = schemaItem.search.itemRender
|
||||
} else {
|
||||
itemRender = {
|
||||
name: itemRenderName,
|
||||
props:
|
||||
itemRenderName == '$input'
|
||||
? { placeholder: t('common.inputText') }
|
||||
: { placeholder: t('common.selectText') }
|
||||
}
|
||||
}
|
||||
}
|
||||
const searchSchemaItem = {
|
||||
// 默认为 input
|
||||
folding: searchSchema.length > spanLength - 1,
|
||||
itemRender: schemaItem.itemRender ? schemaItem.itemRender : itemRender,
|
||||
field: schemaItem.field,
|
||||
title: schemaItem.search?.title || schemaItem.title,
|
||||
slots: schemaItem.search?.slots,
|
||||
span: span
|
||||
}
|
||||
searchSchema.push(searchSchemaItem)
|
||||
}
|
||||
})
|
||||
if (searchSchema.length > 0) {
|
||||
// 添加搜索按钮
|
||||
const buttons: VxeFormItemProps = {
|
||||
span: 24,
|
||||
align: 'right',
|
||||
collapseNode: searchSchema.length > spanLength,
|
||||
itemRender: {
|
||||
name: '$buttons',
|
||||
children: [
|
||||
{ props: { type: 'submit', content: t('common.query'), status: 'primary' } },
|
||||
{ props: { type: 'reset', content: t('common.reset') } }
|
||||
]
|
||||
}
|
||||
}
|
||||
searchSchema.push(buttons)
|
||||
}
|
||||
return searchSchema
|
||||
}
|
||||
|
||||
// 过滤 table 结构
|
||||
const filterTableSchema = (crudSchema: VxeCrudSchema): VxeGridPropTypes.Columns => {
|
||||
const { t } = useI18n()
|
||||
const tableSchema: VxeGridPropTypes.Columns = []
|
||||
// 第一列
|
||||
if (crudSchema.firstColumn) {
|
||||
const tableSchemaItem = {
|
||||
type: crudSchema.firstColumn,
|
||||
width: '50px'
|
||||
}
|
||||
tableSchema.push(tableSchemaItem)
|
||||
}
|
||||
// 主键ID
|
||||
if (crudSchema.primaryKey && crudSchema.primaryType) {
|
||||
const primaryTitle = crudSchema.primaryTitle ? crudSchema.primaryTitle : t('common.index')
|
||||
const primaryWidth = primaryTitle.length * 30 + 'px'
|
||||
|
||||
let tableSchemaItem: { [x: string]: any } = {
|
||||
title: primaryTitle,
|
||||
field: crudSchema.primaryKey,
|
||||
width: primaryWidth
|
||||
}
|
||||
if (crudSchema.primaryType != 'id') {
|
||||
tableSchemaItem = {
|
||||
...tableSchemaItem,
|
||||
type: crudSchema.primaryType
|
||||
}
|
||||
}
|
||||
tableSchema.push(tableSchemaItem)
|
||||
}
|
||||
|
||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
||||
// 判断是否显示
|
||||
if (schemaItem?.isTable !== false && schemaItem?.table?.show !== false) {
|
||||
const tableSchemaItem = {
|
||||
...schemaItem.table,
|
||||
field: schemaItem.field,
|
||||
title: schemaItem.table?.title || schemaItem.title,
|
||||
minWidth: '80px'
|
||||
}
|
||||
tableSchemaItem.showOverflow = 'tooltip'
|
||||
if (schemaItem?.formatter) {
|
||||
tableSchemaItem.formatter = schemaItem.formatter
|
||||
tableSchemaItem.width = tableSchemaItem.width ? tableSchemaItem.width : 160
|
||||
}
|
||||
if (schemaItem?.dictType) {
|
||||
tableSchemaItem.cellRender = {
|
||||
name: 'XDict',
|
||||
content: schemaItem.dictType
|
||||
}
|
||||
tableSchemaItem.width = tableSchemaItem.width ? tableSchemaItem.width : 160
|
||||
}
|
||||
|
||||
tableSchema.push(tableSchemaItem)
|
||||
}
|
||||
})
|
||||
// 操作栏插槽
|
||||
if (crudSchema.action && crudSchema.action == true) {
|
||||
const tableSchemaItem = {
|
||||
title: crudSchema.actionTitle ? crudSchema.actionTitle : t('table.action'),
|
||||
field: 'actionbtns',
|
||||
fixed: 'right' as unknown as VxeColumnPropTypes.Fixed,
|
||||
width: crudSchema.actionWidth ? crudSchema.actionWidth : '200px',
|
||||
slots: {
|
||||
default: 'actionbtns_default'
|
||||
}
|
||||
}
|
||||
tableSchema.push(tableSchemaItem)
|
||||
}
|
||||
return tableSchema
|
||||
}
|
||||
|
||||
// 过滤 form 结构
|
||||
const filterFormSchema = (crudSchema: VxeCrudSchema): FormSchema[] => {
|
||||
const formSchema: FormSchema[] = []
|
||||
|
||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
||||
// 判断是否显示
|
||||
if (schemaItem?.isForm !== false && schemaItem?.form?.show !== false) {
|
||||
// 默认为 input
|
||||
let component = schemaItem?.form?.component || 'Input'
|
||||
let defaultValue: any = ''
|
||||
if (schemaItem.form?.value) {
|
||||
defaultValue = schemaItem.form?.value
|
||||
} else {
|
||||
if (component === 'InputNumber') {
|
||||
defaultValue = 0
|
||||
}
|
||||
}
|
||||
let comonentProps = {}
|
||||
if (schemaItem.dictType) {
|
||||
const options: ComponentOptions[] = []
|
||||
if (schemaItem.dictClass && schemaItem.dictClass === 'number') {
|
||||
getIntDictOptions(schemaItem.dictType).forEach((dict) => {
|
||||
options.push(dict)
|
||||
})
|
||||
} else if (schemaItem.dictClass && schemaItem.dictClass === 'boolean') {
|
||||
getBoolDictOptions(schemaItem.dictType).forEach((dict) => {
|
||||
options.push(dict)
|
||||
})
|
||||
} else {
|
||||
getDictOptions(schemaItem.dictType).forEach((dict) => {
|
||||
options.push(dict)
|
||||
})
|
||||
}
|
||||
comonentProps = {
|
||||
options: options
|
||||
}
|
||||
if (!(schemaItem.form && schemaItem.form.component)) component = 'Select'
|
||||
}
|
||||
const formSchemaItem = {
|
||||
component: component,
|
||||
componentProps: comonentProps,
|
||||
value: defaultValue,
|
||||
...schemaItem.form,
|
||||
field: schemaItem.field,
|
||||
label: schemaItem.form?.label || schemaItem.title
|
||||
}
|
||||
|
||||
formSchema.push(formSchemaItem)
|
||||
}
|
||||
})
|
||||
|
||||
return formSchema
|
||||
}
|
||||
|
||||
// 过滤 descriptions 结构
|
||||
const filterDescriptionsSchema = (crudSchema: VxeCrudSchema): DescriptionsSchema[] => {
|
||||
const descriptionsSchema: DescriptionsSchema[] = []
|
||||
|
||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
||||
// 判断是否显示
|
||||
if (schemaItem?.isDetail !== false && schemaItem.detail?.show !== false) {
|
||||
const descriptionsSchemaItem = {
|
||||
...schemaItem.detail,
|
||||
field: schemaItem.field,
|
||||
label: schemaItem.detail?.label || schemaItem.title
|
||||
}
|
||||
if (schemaItem.dictType) {
|
||||
descriptionsSchemaItem.dictType = schemaItem.dictType
|
||||
}
|
||||
if (schemaItem.detail?.dateFormat || schemaItem.formatter == 'formatDate') {
|
||||
// 优先使用 detail 下的配置,如果没有默认为 YYYY-MM-DD HH:mm:ss
|
||||
descriptionsSchemaItem.dateFormat = schemaItem?.detail?.dateFormat
|
||||
? schemaItem?.detail?.dateFormat
|
||||
: 'YYYY-MM-DD HH:mm:ss'
|
||||
}
|
||||
|
||||
descriptionsSchema.push(descriptionsSchemaItem)
|
||||
}
|
||||
})
|
||||
|
||||
return descriptionsSchema
|
||||
}
|
||||
|
||||
// 过滤 打印 结构
|
||||
const filterPrintSchema = (crudSchema: VxeCrudSchema): any[] => {
|
||||
const printSchema: any[] = []
|
||||
|
||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
||||
// 判断是否显示
|
||||
if (schemaItem?.print?.show !== false) {
|
||||
const printSchemaItem = {
|
||||
field: schemaItem.field
|
||||
}
|
||||
|
||||
printSchema.push(printSchemaItem)
|
||||
}
|
||||
})
|
||||
|
||||
return printSchema
|
||||
}
|
@@ -1,264 +0,0 @@
|
||||
import { computed, nextTick, reactive } from 'vue'
|
||||
import { SizeType, VxeGridProps, VxeTablePropTypes } from 'vxe-table'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { VxeAllSchemas } from './useVxeCrudSchemas'
|
||||
|
||||
import download from '@/utils/download'
|
||||
|
||||
const { t } = useI18n()
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
interface UseVxeGridConfig<T = any> {
|
||||
allSchemas: VxeAllSchemas
|
||||
height?: number // 高度 默认730
|
||||
topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽
|
||||
treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置
|
||||
isList?: boolean // 是否不带分页的list
|
||||
getListApi: (option: any) => Promise<T> // 获取列表接口
|
||||
getAllListApi?: (option: any) => Promise<T> // 获取全部数据接口 用于VXE导出
|
||||
deleteApi?: (option: any) => Promise<T> // 删除接口
|
||||
exportListApi?: (option: any) => Promise<T> // 导出接口
|
||||
exportName?: string // 导出文件夹名称
|
||||
queryParams?: any // 其他查询参数
|
||||
}
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const currentSize = computed(() => {
|
||||
let resSize: SizeType = 'small'
|
||||
const appsize = appStore.getCurrentSize
|
||||
switch (appsize) {
|
||||
case 'large':
|
||||
resSize = 'medium'
|
||||
break
|
||||
case 'default':
|
||||
resSize = 'small'
|
||||
break
|
||||
case 'small':
|
||||
resSize = 'mini'
|
||||
break
|
||||
}
|
||||
return resSize
|
||||
})
|
||||
|
||||
export const useVxeGrid = <T = any>(config?: UseVxeGridConfig<T>) => {
|
||||
/**
|
||||
* grid options 初始化
|
||||
*/
|
||||
const gridOptions = reactive<VxeGridProps<any>>({
|
||||
loading: true,
|
||||
size: currentSize as any,
|
||||
height: config?.height ? config.height : 730,
|
||||
rowConfig: {
|
||||
isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
|
||||
isHover: true // 当鼠标移到行时,是否要高亮当前行
|
||||
},
|
||||
toolbarConfig: {
|
||||
slots:
|
||||
!config?.topActionSlots && config?.topActionSlots != false
|
||||
? { buttons: 'toolbar_buttons' }
|
||||
: {}
|
||||
},
|
||||
printConfig: {
|
||||
columns: config?.allSchemas.printSchema
|
||||
},
|
||||
formConfig: {
|
||||
enabled: true,
|
||||
titleWidth: 100,
|
||||
titleAlign: 'right',
|
||||
items: config?.allSchemas.searchSchema
|
||||
},
|
||||
columns: config?.allSchemas.tableSchema,
|
||||
proxyConfig: {
|
||||
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
||||
form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
||||
props: { result: 'list', total: 'total' },
|
||||
ajax: {
|
||||
query: ({ page, form }) => {
|
||||
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
||||
if (config?.queryParams) {
|
||||
queryParams = Object.assign(queryParams, config.queryParams)
|
||||
}
|
||||
if (!config?.treeConfig) {
|
||||
queryParams.pageSize = page.pageSize
|
||||
queryParams.pageNo = page.currentPage
|
||||
}
|
||||
gridOptions.loading = false
|
||||
return new Promise(async (resolve) => {
|
||||
resolve(await config?.getListApi(queryParams))
|
||||
})
|
||||
},
|
||||
delete: ({ body }) => {
|
||||
return new Promise(async (resolve) => {
|
||||
if (config?.deleteApi) {
|
||||
resolve(await config?.deleteApi(JSON.stringify(body)))
|
||||
} else {
|
||||
Promise.reject('未设置deleteApi')
|
||||
}
|
||||
})
|
||||
},
|
||||
queryAll: ({ form }) => {
|
||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
||||
return new Promise(async (resolve) => {
|
||||
if (config?.getAllListApi) {
|
||||
resolve(await config?.getAllListApi(queryParams))
|
||||
} else {
|
||||
resolve(await config?.getListApi(queryParams))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
exportConfig: {
|
||||
filename: config?.exportName,
|
||||
// 默认选中类型
|
||||
type: 'csv',
|
||||
// 自定义数据量列表
|
||||
modes: config?.getAllListApi ? ['current', 'all'] : ['current'],
|
||||
columns: config?.allSchemas.printSchema
|
||||
}
|
||||
})
|
||||
|
||||
if (config?.treeConfig) {
|
||||
gridOptions.treeConfig = config.treeConfig
|
||||
} else if (config?.isList) {
|
||||
gridOptions.proxyConfig = {
|
||||
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
||||
form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
||||
props: { result: 'data' },
|
||||
ajax: {
|
||||
query: ({ form }) => {
|
||||
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
||||
if (config?.queryParams) {
|
||||
queryParams = Object.assign(queryParams, config.queryParams)
|
||||
}
|
||||
gridOptions.loading = false
|
||||
return new Promise(async (resolve) => {
|
||||
resolve(await config?.getListApi(queryParams))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gridOptions.pagerConfig = {
|
||||
border: false, // 带边框
|
||||
background: true, // 带背景颜色
|
||||
perfect: false, // 配套的样式
|
||||
pageSize: 10, // 每页大小
|
||||
pagerCount: 7, // 显示页码按钮的数量
|
||||
autoHidden: false, // 当只有一页时自动隐藏
|
||||
pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
|
||||
layouts: [
|
||||
'PrevJump',
|
||||
'PrevPage',
|
||||
'JumpNumber',
|
||||
'NextPage',
|
||||
'NextJump',
|
||||
'Sizes',
|
||||
'FullJump',
|
||||
'Total'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
* @param ref
|
||||
* @returns
|
||||
*/
|
||||
const getList = async (ref) => {
|
||||
if (!ref) {
|
||||
console.error('未传入gridRef')
|
||||
return
|
||||
}
|
||||
await nextTick()
|
||||
ref.value.commitProxy('query')
|
||||
}
|
||||
|
||||
// 获取查询参数
|
||||
const getSearchData = async (ref) => {
|
||||
if (!ref) {
|
||||
console.error('未传入gridRef')
|
||||
return
|
||||
}
|
||||
await nextTick()
|
||||
const queryParams = Object.assign(
|
||||
{},
|
||||
JSON.parse(JSON.stringify(ref.value.getProxyInfo()?.form))
|
||||
)
|
||||
return queryParams
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param ref
|
||||
* @param ids rowid
|
||||
* @returns
|
||||
*/
|
||||
const deleteData = async (ref, ids: string | number) => {
|
||||
if (!ref) {
|
||||
console.error('未传入gridRef')
|
||||
return
|
||||
}
|
||||
if (!config?.deleteApi) {
|
||||
console.error('未传入delListApi')
|
||||
return
|
||||
}
|
||||
await nextTick()
|
||||
return new Promise(async () => {
|
||||
message.delConfirm().then(async () => {
|
||||
await (config?.deleteApi && config?.deleteApi(ids))
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
ref.value.commitProxy('query')
|
||||
})
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 导出
|
||||
* @param ref
|
||||
* @param fileName 文件名,默认excel.xls
|
||||
* @returns
|
||||
*/
|
||||
const exportList = async (ref, fileName?: string) => {
|
||||
if (!ref) {
|
||||
console.error('未传入gridRef')
|
||||
return
|
||||
}
|
||||
if (!config?.exportListApi) {
|
||||
console.error('未传入exportListApi')
|
||||
return
|
||||
}
|
||||
await nextTick()
|
||||
const queryParams = Object.assign(
|
||||
{},
|
||||
JSON.parse(JSON.stringify(ref.value?.getProxyInfo()?.form))
|
||||
)
|
||||
message.exportConfirm().then(async () => {
|
||||
const res = await (config?.exportListApi && config?.exportListApi(queryParams))
|
||||
download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls')
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 表格最大/最小化
|
||||
* @param ref
|
||||
* @returns
|
||||
*/
|
||||
const zoom = async (ref) => {
|
||||
if (!ref) {
|
||||
console.error('未传入gridRef')
|
||||
return
|
||||
}
|
||||
await nextTick()
|
||||
ref.value.zoom(!ref.value.isMaximized())
|
||||
}
|
||||
|
||||
return {
|
||||
gridOptions,
|
||||
getList,
|
||||
getSearchData,
|
||||
deleteData,
|
||||
exportList,
|
||||
zoom
|
||||
}
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
import { XTableProps } from '@/components/XTable/src/type'
|
||||
|
||||
export interface tableMethod {
|
||||
reload: () => void // 刷新表格
|
||||
setProps: (props: XTableProps) => void
|
||||
deleteData: (id: string | number) => void // 删除数据
|
||||
deleteBatch: () => void // 批量删除
|
||||
exportList: (fileName?: string) => void // 导出列表
|
||||
getCurrentColumn: () => void // 获取当前列
|
||||
getRadioRecord: () => void // 获取当前选中列,radio
|
||||
getCheckboxRecords: () => void //获取当前选中列, checkbox
|
||||
}
|
||||
|
||||
export const useXTable = (props: XTableProps): [Function, tableMethod] => {
|
||||
const tableRef = ref<Nullable<tableMethod>>(null)
|
||||
|
||||
const register = (instance) => {
|
||||
tableRef.value = instance
|
||||
props && instance.setProps(props)
|
||||
}
|
||||
const getInstance = (): tableMethod => {
|
||||
const table = unref(tableRef)
|
||||
if (!table) {
|
||||
console.error('表格实例不存在')
|
||||
}
|
||||
return table as tableMethod
|
||||
}
|
||||
const methods: tableMethod = {
|
||||
reload: () => getInstance().reload(),
|
||||
setProps: (props) => getInstance().setProps(props),
|
||||
deleteData: (id: string | number) => getInstance().deleteData(id),
|
||||
deleteBatch: () => getInstance().deleteBatch(),
|
||||
exportList: (fileName?: string) => getInstance().exportList(fileName),
|
||||
getCurrentColumn: () => getInstance().getCheckboxRecords(),
|
||||
getRadioRecord: () => getInstance().getRadioRecord(),
|
||||
getCheckboxRecords: () => getInstance().getCheckboxRecords()
|
||||
}
|
||||
return [register, methods]
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="AppView" setup>
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { Footer } from '@/layout/components/Footer'
|
||||
@@ -21,16 +21,17 @@ const getCaches = computed((): string[] => {
|
||||
<template>
|
||||
<section
|
||||
:class="[
|
||||
'p-[var(--app-content-padding)] w-[100%] bg-[var(--app-contnet-bg-color)] dark:bg-[var(--el-bg-color)]',
|
||||
'p-[var(--app-content-padding)] w-[100%] bg-[var(--app-content-bg-color)] dark:bg-[var(--el-bg-color)]',
|
||||
{
|
||||
'!min-h-[calc(100%-var(--app-footer-height))]':
|
||||
fixedHeader && (layout === 'classic' || layout === 'topLeft') && footer,
|
||||
((fixedHeader && (layout === 'classic' || layout === 'topLeft')) || layout === 'top') &&
|
||||
footer,
|
||||
|
||||
'!min-h-[calc(100%-var(--tags-view-height)-var(--top-tool-height)-var(--app-footer-height))]':
|
||||
((!fixedHeader && layout === 'classic') || layout === 'top') && footer,
|
||||
!fixedHeader && layout === 'classic' && footer,
|
||||
|
||||
'!min-h-[calc(100%-var(--tags-view-height)-var(--app-footer-height))]':
|
||||
!fixedHeader && layout === 'topLeft' && footer,
|
||||
!fixedHeader && (layout === 'topLeft' || layout === 'top') && footer,
|
||||
|
||||
'!min-h-[calc(100%-var(--top-tool-height))]': fixedHeader && layout === 'cutMenu' && footer,
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Collapse" setup>
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -24,9 +24,9 @@ const toggleCollapse = () => {
|
||||
<template>
|
||||
<div :class="prefixCls">
|
||||
<Icon
|
||||
:size="18"
|
||||
:icon="collapse ? 'ep:expand' : 'ep:fold'"
|
||||
:color="color"
|
||||
:icon="collapse ? 'ep:expand' : 'ep:fold'"
|
||||
:size="18"
|
||||
class="cursor-pointer"
|
||||
@click="toggleCollapse"
|
||||
/>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ContextMenu" setup>
|
||||
import { PropType } from 'vue'
|
||||
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -51,9 +51,9 @@ defineExpose({
|
||||
:class="prefixCls"
|
||||
:trigger="trigger"
|
||||
placement="bottom-start"
|
||||
popper-class="v-context-menu-popper"
|
||||
@command="command"
|
||||
@visible-change="visibleChange"
|
||||
popper-class="v-context-menu-popper"
|
||||
>
|
||||
<slot></slot>
|
||||
<template #dropdown>
|
||||
@@ -61,11 +61,12 @@ defineExpose({
|
||||
<ElDropdownItem
|
||||
v-for="(item, index) in schema"
|
||||
:key="`dropdown${index}`"
|
||||
:divided="item.divided"
|
||||
:disabled="item.disabled"
|
||||
:command="item"
|
||||
:disabled="item.disabled"
|
||||
:divided="item.divided"
|
||||
>
|
||||
<Icon :icon="item.icon" /> {{ t(item.label) }}
|
||||
<Icon :icon="item.icon" />
|
||||
{{ t(item.label) }}
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Footer" setup>
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="LocaleDropdown" setup>
|
||||
import { useLocaleStore } from '@/store/modules/locale'
|
||||
import { useLocale } from '@/hooks/web/useLocale'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
@@ -33,11 +33,11 @@ const setLang = (lang: LocaleType) => {
|
||||
<template>
|
||||
<ElDropdown :class="prefixCls" trigger="click" @command="setLang">
|
||||
<Icon
|
||||
:size="18"
|
||||
icon="ion:language-sharp"
|
||||
class="cursor-pointer"
|
||||
:class="$attrs.class"
|
||||
:color="color"
|
||||
:size="18"
|
||||
class="cursor-pointer"
|
||||
icon="ion:language-sharp"
|
||||
/>
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, computed, onMounted, unref } from 'vue'
|
||||
<script lang="ts" name="Logo" setup>
|
||||
import { computed, onMounted, ref, unref, watch } from 'vue'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
@@ -66,8 +66,8 @@ watch(
|
||||
to="/"
|
||||
>
|
||||
<img
|
||||
src="@/assets/imgs/logo.png"
|
||||
class="w-[calc(var(--logo-height)-10px)] h-[calc(var(--logo-height)-10px)]"
|
||||
src="@/assets/imgs/logo.png"
|
||||
/>
|
||||
<div
|
||||
v-if="show"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Message" setup>
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import * as NotifyMessageApi from '@/api/system/notify/message'
|
||||
|
||||
@@ -40,10 +40,10 @@ onMounted(() => {
|
||||
</script>
|
||||
<template>
|
||||
<div class="message">
|
||||
<ElPopover placement="bottom" :width="400" trigger="click">
|
||||
<ElPopover :width="400" placement="bottom" trigger="click">
|
||||
<template #reference>
|
||||
<ElBadge :is-dot="unreadCount > 0" class="item">
|
||||
<Icon icon="ep:bell" :size="18" class="cursor-pointer" @click="getList" />
|
||||
<Icon :size="18" class="cursor-pointer" icon="ep:bell" @click="getList" />
|
||||
</ElBadge>
|
||||
</template>
|
||||
<ElTabs v-model="activeName">
|
||||
@@ -51,7 +51,7 @@ onMounted(() => {
|
||||
<div class="message-list">
|
||||
<template v-for="item in list" :key="item.id">
|
||||
<div class="message-item">
|
||||
<img src="@/assets/imgs/avatar.gif" alt="" class="message-icon" />
|
||||
<img alt="" class="message-icon" src="@/assets/imgs/avatar.gif" />
|
||||
<div class="message-content">
|
||||
<span class="message-title">
|
||||
{{ item.templateNickname }}:{{ item.templateContent }}
|
||||
@@ -67,12 +67,12 @@ onMounted(() => {
|
||||
</ElTabs>
|
||||
<!-- 更多 -->
|
||||
<div style="text-align: right; margin-top: 10px">
|
||||
<XButton type="primary" preIcon="ep:view" title="查看全部" @click="goMyList" />
|
||||
<XButton preIcon="ep:view" title="查看全部" type="primary" @click="goMyList" />
|
||||
</div>
|
||||
</ElPopover>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.message-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -81,28 +81,35 @@ onMounted(() => {
|
||||
height: 260px;
|
||||
line-height: 45px;
|
||||
}
|
||||
|
||||
.message-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px 0;
|
||||
border-bottom: 1px solid var(--el-border-color-light);
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.message-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 20px 0 5px;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.message-title {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.message-date {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ScreenFull" setup>
|
||||
import { Icon } from '@/components/Icon'
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
@@ -22,9 +22,9 @@ const toggleFullscreen = () => {
|
||||
<template>
|
||||
<div :class="prefixCls" @click="toggleFullscreen">
|
||||
<Icon
|
||||
:size="18"
|
||||
:icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'"
|
||||
:color="color"
|
||||
:icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'"
|
||||
:size="18"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Setting" setup>
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useCssVar, useClipboard } from '@vueuse/core'
|
||||
import { useClipboard, useCssVar } from '@vueuse/core'
|
||||
|
||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
import { trim, setCssVar } from '@/utils'
|
||||
import { colorIsDark, lighten, hexToRGB } from '@/utils/color'
|
||||
import { setCssVar, trim } from '@/utils'
|
||||
import { colorIsDark, hexToRGB, lighten } from '@/utils/color'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { ThemeSwitch } from '@/layout/components/ThemeSwitch'
|
||||
import ColorRadioPicker from './components/ColorRadioPicker.vue'
|
||||
@@ -202,10 +202,10 @@ const clear = () => {
|
||||
class="fixed top-[45%] right-0 w-40px h-40px text-center leading-40px bg-[var(--el-color-primary)] cursor-pointer"
|
||||
@click="drawer = true"
|
||||
>
|
||||
<Icon icon="ep:setting" color="#fff" />
|
||||
<Icon color="#fff" icon="ep:setting" />
|
||||
</div>
|
||||
|
||||
<ElDrawer v-model="drawer" direction="rtl" size="350px" :z-index="4000">
|
||||
<ElDrawer v-model="drawer" :z-index="4000" direction="rtl" size="350px">
|
||||
<template #header>
|
||||
<span class="text-16px font-700">{{ t('setting.projectSetting') }}</span>
|
||||
</template>
|
||||
@@ -279,10 +279,10 @@ const clear = () => {
|
||||
|
||||
<ElDivider />
|
||||
<div>
|
||||
<ElButton type="primary" class="w-full" @click="copyConfig">{{ t('setting.copy') }}</ElButton>
|
||||
<ElButton class="w-full" type="primary" @click="copyConfig">{{ t('setting.copy') }}</ElButton>
|
||||
</div>
|
||||
<div class="mt-5px">
|
||||
<ElButton type="danger" class="w-full" @click="clear">
|
||||
<ElButton class="w-full" type="danger" @click="clear">
|
||||
{{ t('setting.clearAndReset') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ColorRadioPicker" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -42,14 +42,14 @@ watch(
|
||||
<span
|
||||
v-for="(item, i) in schema"
|
||||
:key="`radio-${i}`"
|
||||
class="w-20px h-20px cursor-pointer rounded-2px border-solid border-gray-300 border-2px text-center leading-20px mb-5px"
|
||||
:class="{ 'is-active': colorVal === item }"
|
||||
:style="{
|
||||
background: item
|
||||
}"
|
||||
class="w-20px h-20px cursor-pointer rounded-2px border-solid border-gray-300 border-2px text-center leading-20px mb-5px"
|
||||
@click="colorVal = item"
|
||||
>
|
||||
<Icon v-if="colorVal === item" color="#fff" icon="ep:check" :size="16" />
|
||||
<Icon v-if="colorVal === item" :size="16" color="#fff" icon="ep:check" />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="InterfaceDisplay" setup>
|
||||
import { setCssVar } from '@/utils'
|
||||
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="LayoutRadioPicker" setup>
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="SizeDropdown" setup>
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
@@ -26,7 +26,7 @@ const setCurrentSize = (size: ElementPlusSize) => {
|
||||
|
||||
<template>
|
||||
<ElDropdown :class="prefixCls" trigger="click" @command="setCurrentSize">
|
||||
<Icon :size="18" icon="mdi:format-size" :color="color" class="cursor-pointer" />
|
||||
<Icon :color="color" :size="18" class="cursor-pointer" icon="mdi:format-size" />
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
<ElDropdownItem v-for="item in sizeMap" :key="item" :command="item">
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="TagsView" setup>
|
||||
import type { RouteLocationNormalizedLoaded, RouterLinkProps } from 'vue-router'
|
||||
import { usePermissionStore } from '@/store/modules/permission'
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||
@@ -266,15 +266,24 @@ watch(
|
||||
@click="move(-200)"
|
||||
>
|
||||
<Icon
|
||||
icon="ep:d-arrow-left"
|
||||
:color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
|
||||
icon="ep:d-arrow-left"
|
||||
/>
|
||||
</span>
|
||||
<div class="overflow-hidden flex-1">
|
||||
<ElScrollbar ref="scrollbarRef" class="h-full" @scroll="scroll">
|
||||
<div class="flex h-full">
|
||||
<ContextMenu
|
||||
v-for="item in visitedViews"
|
||||
:key="item.fullPath"
|
||||
:ref="itemRefs.set"
|
||||
:class="[
|
||||
`${prefixCls}__item`,
|
||||
item?.meta?.affix ? `${prefixCls}__item--affix` : '',
|
||||
{
|
||||
'is-active': isActive(item)
|
||||
}
|
||||
]"
|
||||
:schema="[
|
||||
{
|
||||
icon: 'ep:refresh',
|
||||
@@ -332,23 +341,14 @@ watch(
|
||||
}
|
||||
}
|
||||
]"
|
||||
v-for="item in visitedViews"
|
||||
:key="item.fullPath"
|
||||
:tag-item="item"
|
||||
:class="[
|
||||
`${prefixCls}__item`,
|
||||
item?.meta?.affix ? `${prefixCls}__item--affix` : '',
|
||||
{
|
||||
'is-active': isActive(item)
|
||||
}
|
||||
]"
|
||||
@visible-change="visibleChange"
|
||||
>
|
||||
<div>
|
||||
<router-link :ref="tagLinksRefs.set" :to="{ ...item }" custom v-slot="{ navigate }">
|
||||
<router-link :ref="tagLinksRefs.set" v-slot="{ navigate }" :to="{ ...item }" custom>
|
||||
<div
|
||||
@click="navigate"
|
||||
class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
|
||||
@click="navigate"
|
||||
>
|
||||
<Icon
|
||||
v-if="
|
||||
@@ -364,9 +364,9 @@ watch(
|
||||
{{ t(item?.meta?.title as string) }}
|
||||
<Icon
|
||||
:class="`${prefixCls}__item--close`"
|
||||
:size="12"
|
||||
color="#333"
|
||||
icon="ep:close"
|
||||
:size="12"
|
||||
@click.prevent.stop="closeSelectedTag(item)"
|
||||
/>
|
||||
</div>
|
||||
@@ -382,8 +382,8 @@ watch(
|
||||
@click="move(200)"
|
||||
>
|
||||
<Icon
|
||||
icon="ep:d-arrow-right"
|
||||
:color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
|
||||
icon="ep:d-arrow-right"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
@@ -392,12 +392,11 @@ watch(
|
||||
@click="refreshSelectedTag(selectedTag)"
|
||||
>
|
||||
<Icon
|
||||
icon="ep:refresh-right"
|
||||
:color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
|
||||
icon="ep:refresh-right"
|
||||
/>
|
||||
</span>
|
||||
<ContextMenu
|
||||
trigger="click"
|
||||
:schema="[
|
||||
{
|
||||
icon: 'ep:refresh',
|
||||
@@ -449,14 +448,15 @@ watch(
|
||||
}
|
||||
}
|
||||
]"
|
||||
trigger="click"
|
||||
>
|
||||
<span
|
||||
:class="`${prefixCls}__tool`"
|
||||
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer block"
|
||||
>
|
||||
<Icon
|
||||
icon="ep:menu"
|
||||
:color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
|
||||
icon="ep:menu"
|
||||
/>
|
||||
</span>
|
||||
</ContextMenu>
|
||||
@@ -513,6 +513,7 @@ $prefix-cls: #{$namespace}-tags-view;
|
||||
display: none;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
|
||||
&:not(.#{$prefix-cls}__item--affix):hover {
|
||||
.#{$prefix-cls}__item--close {
|
||||
display: block;
|
||||
@@ -530,6 +531,7 @@ $prefix-cls: #{$namespace}-tags-view;
|
||||
color: var(--el-color-white);
|
||||
background-color: var(--el-color-primary);
|
||||
border: 1px solid var(--el-color-primary);
|
||||
|
||||
.#{$prefix-cls}__item--close {
|
||||
:deep(span) {
|
||||
color: var(--el-color-white) !important;
|
||||
@@ -573,6 +575,7 @@ $prefix-cls: #{$namespace}-tags-view;
|
||||
&__item.is-active {
|
||||
color: var(--el-color-white);
|
||||
background-color: var(--el-color-primary);
|
||||
|
||||
.#{$prefix-cls}__item--close {
|
||||
:deep(span) {
|
||||
color: var(--el-color-white) !important;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="ThemeSwitch" setup>
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useIcon } from '@/hooks/web/useIcon'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
@@ -26,14 +26,14 @@ const themeChange = (val: boolean) => {
|
||||
|
||||
<template>
|
||||
<ElSwitch
|
||||
:class="prefixCls"
|
||||
v-model="isDark"
|
||||
inline-prompt
|
||||
:border-color="blackColor"
|
||||
:inactive-color="blackColor"
|
||||
:active-color="blackColor"
|
||||
:active-icon="Sun"
|
||||
:border-color="blackColor"
|
||||
:class="prefixCls"
|
||||
:inactive-color="blackColor"
|
||||
:inactive-icon="CrescentMoon"
|
||||
inline-prompt
|
||||
@change="themeChange"
|
||||
/>
|
||||
</template>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="UserInfo" setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
|
||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
||||
|
@@ -177,7 +177,9 @@ export const useRenderLayout = () => {
|
||||
class={[
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
'mt-[var(--tags-view-height)]': fixedHeader.value
|
||||
'mt-[var(--tags-view-height)] !pb-[calc(var(--tags-view-height)+var(--app-footer-height))]':
|
||||
fixedHeader.value,
|
||||
'pb-[var(--app-footer-height)]': !fixedHeader.value
|
||||
}
|
||||
]}
|
||||
>
|
||||
|
32
src/main.ts
32
src/main.ts
@@ -16,9 +16,6 @@ import { setupGlobCom } from '@/components'
|
||||
// 引入 element-plus
|
||||
import { setupElementPlus } from '@/plugins/elementPlus'
|
||||
|
||||
// 引入 vxe-table
|
||||
import { setupVxeTable } from '@/plugins/vxeTable'
|
||||
|
||||
// 引入 form-create
|
||||
import { setupFormCreate } from '@/plugins/formCreate'
|
||||
|
||||
@@ -40,51 +37,22 @@ import App from './App.vue'
|
||||
|
||||
import './permission'
|
||||
|
||||
import { isDevMode } from '@/utils/env'
|
||||
|
||||
import { MyPD } from '@/components/bpmnProcessDesigner/package/index.js'
|
||||
import '@/components/bpmnProcessDesigner/package/theme/index.scss'
|
||||
import 'bpmn-js/dist/assets/diagram-js.css'
|
||||
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
|
||||
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
|
||||
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
|
||||
|
||||
import hljs from 'highlight.js' //导入代码高亮文件
|
||||
import 'highlight.js/styles/github.css' //导入代码高亮样式 新版
|
||||
|
||||
import '@/plugins/tongji' // 百度统计
|
||||
|
||||
import Logger from '@/utils/Logger'
|
||||
|
||||
// 本地开发模式 全局引入 element-plus 样式,加快第一次进入速度
|
||||
if (isDevMode()) {
|
||||
import('element-plus/dist/index.css')
|
||||
}
|
||||
|
||||
// 创建实例
|
||||
const setupAll = async () => {
|
||||
const app = createApp(App)
|
||||
|
||||
//自定义一个代码高亮指令
|
||||
app.directive('highlight', function (el) {
|
||||
const blocks = el.querySelectorAll('code')
|
||||
blocks.forEach((block: any) => {
|
||||
hljs.highlightElement(block)
|
||||
})
|
||||
})
|
||||
|
||||
await setupI18n(app)
|
||||
|
||||
MyPD(app)
|
||||
|
||||
setupStore(app)
|
||||
|
||||
setupGlobCom(app)
|
||||
|
||||
setupElementPlus(app)
|
||||
|
||||
setupVxeTable(app)
|
||||
|
||||
setupFormCreate(app)
|
||||
|
||||
setupRouter(app)
|
||||
|
@@ -17,7 +17,6 @@ import {
|
||||
|
||||
import formCreate from '@form-create/element-ui'
|
||||
import install from '@form-create/element-ui/auto-import'
|
||||
import FcDesigner from '@form-create/designer'
|
||||
|
||||
const components = [
|
||||
ElAside,
|
||||
@@ -34,14 +33,11 @@ const components = [
|
||||
ElTabPane
|
||||
]
|
||||
|
||||
// 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档
|
||||
export const setupFormCreate = (app: App<Element>) => {
|
||||
components.forEach((component) => {
|
||||
app.component(component.name, component)
|
||||
})
|
||||
|
||||
formCreate.use(install)
|
||||
|
||||
app.use(formCreate)
|
||||
|
||||
app.use(FcDesigner)
|
||||
}
|
||||
|
@@ -1,223 +0,0 @@
|
||||
import { App } from 'vue'
|
||||
import XEUtils from 'xe-utils'
|
||||
import './renderer'
|
||||
import 'vxe-table/lib/style.css'
|
||||
import { i18n } from '@/plugins/vueI18n'
|
||||
import zhCN from 'vxe-table/lib/locale/lang/zh-CN'
|
||||
import enUS from 'vxe-table/lib/locale/lang/en-US'
|
||||
import {
|
||||
// 全局对象
|
||||
VXETable,
|
||||
// 表格功能
|
||||
Filter,
|
||||
Edit,
|
||||
Menu,
|
||||
Export,
|
||||
Keyboard,
|
||||
Validator,
|
||||
// 可选组件
|
||||
Icon,
|
||||
Column,
|
||||
Colgroup,
|
||||
Grid,
|
||||
Tooltip,
|
||||
Toolbar,
|
||||
Pager,
|
||||
Form,
|
||||
FormItem,
|
||||
FormGather,
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
RadioButton,
|
||||
Switch,
|
||||
Input,
|
||||
Select,
|
||||
Optgroup,
|
||||
Option,
|
||||
Textarea,
|
||||
Button,
|
||||
Modal,
|
||||
List,
|
||||
Pulldown,
|
||||
// 表格
|
||||
Table
|
||||
} from 'vxe-table'
|
||||
|
||||
// 全局默认参数
|
||||
VXETable.setup({
|
||||
size: 'medium', // 全局尺寸
|
||||
version: 0, // 版本号,对于某些带数据缓存的功能有用到,上升版本号可以用于重置数据
|
||||
zIndex: 1008, // 全局 zIndex 起始值,如果项目的的 z-index 样式值过大时就需要跟随设置更大,避免被遮挡
|
||||
loadingText: '加载中...', // 全局loading提示内容,如果为null则不显示文本
|
||||
height: 600,
|
||||
table: {
|
||||
border: 'inner', // default(默认), full(完整边框), outer(外边框), inner(内边框), none(无边框)
|
||||
align: 'center', // eft(左对齐), center(居中对齐), right(右对齐)
|
||||
autoResize: true, // 自动监听父元素的变化去重新计算表格
|
||||
resizable: true, // 列是否允许拖动列宽调整大小
|
||||
emptyText: '暂无数据', // 空表单
|
||||
highlightHoverRow: true, // 自动监听父元素的变化去重新计算表格
|
||||
treeConfig: {
|
||||
rowField: 'id',
|
||||
parentField: 'parentId',
|
||||
children: 'children',
|
||||
indent: 20,
|
||||
showIcon: true
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
toolbarConfig: {
|
||||
refresh: true,
|
||||
export: true,
|
||||
print: true,
|
||||
zoom: true,
|
||||
custom: true
|
||||
},
|
||||
pagerConfig: {
|
||||
border: false,
|
||||
background: false,
|
||||
autoHidden: true,
|
||||
perfect: true,
|
||||
pageSize: 10,
|
||||
pagerCount: 7,
|
||||
pageSizes: [5, 10, 15, 20, 50, 100, 200, 500],
|
||||
layouts: [
|
||||
'Sizes',
|
||||
'PrevJump',
|
||||
'PrevPage',
|
||||
'Number',
|
||||
'NextPage',
|
||||
'NextJump',
|
||||
'FullJump',
|
||||
'Total'
|
||||
]
|
||||
}
|
||||
},
|
||||
pager: {
|
||||
background: false,
|
||||
autoHidden: false,
|
||||
perfect: true,
|
||||
pageSize: 10,
|
||||
pagerCount: 7,
|
||||
pageSizes: [10, 15, 20, 50, 100],
|
||||
layouts: ['PrevJump', 'PrevPage', 'Jump', 'PageCount', 'NextPage', 'NextJump', 'Sizes', 'Total']
|
||||
},
|
||||
input: {
|
||||
clearable: true
|
||||
},
|
||||
form: {
|
||||
titleColon: true // 是否显示标题冒号
|
||||
},
|
||||
modal: {
|
||||
width: 800, // 窗口的宽度
|
||||
height: 600, // 窗口的高度
|
||||
minWidth: 460,
|
||||
minHeight: 320,
|
||||
showZoom: true, // 标题是否标显示最大化与还原按钮
|
||||
resize: true, // 是否允许窗口边缘拖动调整窗口大小
|
||||
marginSize: 0, // 只对 resize 启用后有效,用于设置可拖动界限范围,如果为负数则允许拖动超出屏幕边界
|
||||
remember: false, // 记忆功能,会记住最后操作状态,再次打开窗口时还原窗口状态
|
||||
destroyOnClose: true, // 在窗口关闭时销毁内容
|
||||
storage: false, // 是否启用 localStorage 本地保存,会将窗口拖动的状态保存到本地
|
||||
transfer: true, // 是否将弹框容器插入于 body 内
|
||||
showFooter: true, // 是否显示底部
|
||||
mask: true, // 是否显示遮罩层
|
||||
maskClosable: true, // 是否允许点击遮罩层关闭窗口
|
||||
escClosable: true // 是否允许按 Esc 键关闭窗口
|
||||
},
|
||||
i18n: (key, args) => {
|
||||
return unref(i18n.global.locale) === 'zh-CN'
|
||||
? XEUtils.toFormatString(XEUtils.get(zhCN, key), args)
|
||||
: XEUtils.toFormatString(XEUtils.get(enUS, key), args)
|
||||
}
|
||||
})
|
||||
// 自定义全局的格式化处理函数
|
||||
VXETable.formats.mixin({
|
||||
// 格式精简日期,默认 yyyy-MM-dd HH:mm:ss
|
||||
formatDay({ cellValue }, format) {
|
||||
if (cellValue != null) {
|
||||
return XEUtils.toDateString(cellValue, format || 'yyyy-MM-dd')
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// 格式完整日期,默认 yyyy-MM-dd HH:mm:ss
|
||||
formatDate({ cellValue }, format) {
|
||||
if (cellValue != null) {
|
||||
return XEUtils.toDateString(cellValue, format || 'yyyy-MM-dd HH:mm:ss')
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// 四舍五入金额,每隔3位逗号分隔,默认2位数
|
||||
formatAmount({ cellValue }, digits = 2) {
|
||||
return XEUtils.commafy(Number(cellValue), { digits })
|
||||
},
|
||||
// 格式化银行卡,默认每4位空格隔开
|
||||
formatBankcard({ cellValue }) {
|
||||
return XEUtils.commafy(XEUtils.toValueString(cellValue), { spaceNumber: 4, separator: ' ' })
|
||||
},
|
||||
// 四舍五入,默认两位数
|
||||
formatFixedNumber({ cellValue }, digits = 2) {
|
||||
return XEUtils.toFixed(XEUtils.round(cellValue, digits), digits)
|
||||
},
|
||||
// 向下舍入,默认两位数
|
||||
formatCutNumber({ cellValue }, digits = 2) {
|
||||
return XEUtils.toFixed(XEUtils.floor(cellValue, digits), digits)
|
||||
},
|
||||
// 格式化图片,将图片链接转换为html标签
|
||||
formatImg({ cellValue }) {
|
||||
return '<img height="40" src="' + cellValue + '"> '
|
||||
},
|
||||
// 格式化文件大小
|
||||
formatSize({ cellValue }, digits = 0) {
|
||||
const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
const srcSize = parseFloat(cellValue)
|
||||
const index = Math.floor(Math.log(srcSize) / Math.log(1024))
|
||||
const size = srcSize / Math.pow(1024, index)
|
||||
return XEUtils.toFixed(XEUtils.floor(size, 2), 2) + ' ' + unitArr[digits]
|
||||
}
|
||||
})
|
||||
export const setupVxeTable = (app: App<Element>) => {
|
||||
// 表格功能
|
||||
app.use(Filter).use(Edit).use(Menu).use(Export).use(Keyboard).use(Validator)
|
||||
|
||||
// 可选组件
|
||||
app
|
||||
.use(Icon)
|
||||
.use(Column)
|
||||
.use(Colgroup)
|
||||
.use(Grid)
|
||||
.use(Tooltip)
|
||||
.use(Toolbar)
|
||||
.use(Pager)
|
||||
.use(Form)
|
||||
.use(FormItem)
|
||||
.use(FormGather)
|
||||
.use(Checkbox)
|
||||
.use(CheckboxGroup)
|
||||
.use(Radio)
|
||||
.use(RadioGroup)
|
||||
.use(RadioButton)
|
||||
.use(Switch)
|
||||
.use(Input)
|
||||
.use(Select)
|
||||
.use(Optgroup)
|
||||
.use(Option)
|
||||
.use(Textarea)
|
||||
.use(Button)
|
||||
.use(Modal)
|
||||
.use(List)
|
||||
.use(Pulldown)
|
||||
|
||||
// 安装表格
|
||||
.use(Table)
|
||||
|
||||
// 给 vue 实例挂载内部对象,例如:
|
||||
// app.config.globalProperties.$XModal = VXETable.modal
|
||||
// app.config.globalProperties.$XPrint = VXETable.print
|
||||
// app.config.globalProperties.$XSaveFile = VXETable.saveFile
|
||||
// app.config.globalProperties.$XReadFile = VXETable.readFile
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
import { ElDatePicker } from 'element-plus'
|
||||
import { VXETable } from 'vxe-table'
|
||||
|
||||
// 日期区间选择渲染
|
||||
VXETable.renderer.add('XDataPicker', {
|
||||
// 默认显示模板
|
||||
renderItemContent(renderOpts, params) {
|
||||
const { data, field } = params
|
||||
const { content } = renderOpts
|
||||
return (
|
||||
<ElDatePicker
|
||||
v-model={data[field]}
|
||||
style="width: 100%"
|
||||
type={content ? (content as any) : 'datetime'}
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
clearable
|
||||
></ElDatePicker>
|
||||
)
|
||||
}
|
||||
})
|
@@ -1,23 +0,0 @@
|
||||
import { ElDatePicker } from 'element-plus'
|
||||
import { VXETable } from 'vxe-table'
|
||||
|
||||
// 日期区间选择渲染
|
||||
VXETable.renderer.add('XDataTimePicker', {
|
||||
// 默认显示模板
|
||||
renderItemContent(renderOpts, params) {
|
||||
const { t } = useI18n()
|
||||
const { data, field } = params
|
||||
const { content } = renderOpts
|
||||
return (
|
||||
<ElDatePicker
|
||||
v-model={data[field]}
|
||||
style="width: 100%"
|
||||
type={content ? (content as any) : 'datetimerange'}
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
range-separator="-"
|
||||
start-placeholder={t('common.startTimeText')}
|
||||
end-placeholder={t('common.endTimeText')}
|
||||
></ElDatePicker>
|
||||
)
|
||||
}
|
||||
})
|
@@ -1,12 +0,0 @@
|
||||
import { DictTag } from '@/components/DictTag'
|
||||
import { VXETable } from 'vxe-table'
|
||||
|
||||
// 字典渲染
|
||||
VXETable.renderer.add('XDict', {
|
||||
// 默认显示模板
|
||||
renderDefault(renderOpts, params) {
|
||||
const { row, column } = params
|
||||
const { content } = renderOpts
|
||||
return <DictTag type={content as unknown as string} value={row[column.field]}></DictTag>
|
||||
}
|
||||
})
|
@@ -1,10 +0,0 @@
|
||||
import { VXETable } from 'vxe-table'
|
||||
|
||||
// 图片渲染
|
||||
VXETable.renderer.add('XHtml', {
|
||||
// 默认显示模板
|
||||
renderDefault(_renderOpts, params) {
|
||||
const { row, column } = params
|
||||
return <span v-html={row[column.field]}></span>
|
||||
}
|
||||
})
|
@@ -1,20 +0,0 @@
|
||||
import { VXETable } from 'vxe-table'
|
||||
import { ElImage } from 'element-plus'
|
||||
|
||||
// 图片渲染
|
||||
VXETable.renderer.add('XImg', {
|
||||
// 默认显示模板
|
||||
renderDefault(_renderOpts, params) {
|
||||
const { row, column } = params
|
||||
return (
|
||||
<ElImage
|
||||
style="width: 80px; height: 50px"
|
||||
src={row[column.field]}
|
||||
key={row[column.field]}
|
||||
preview-src-list={[row[column.field]]}
|
||||
fit="contain"
|
||||
lazy
|
||||
></ElImage>
|
||||
)
|
||||
}
|
||||
})
|
@@ -1,7 +0,0 @@
|
||||
import './dataPicker'
|
||||
import './dataTimeRangePicker'
|
||||
import './dict'
|
||||
import './html'
|
||||
import './link'
|
||||
import './img'
|
||||
import './preview'
|
@@ -1,15 +0,0 @@
|
||||
import { VXETable } from 'vxe-table'
|
||||
|
||||
// 超链接渲染
|
||||
VXETable.renderer.add('XLink', {
|
||||
// 默认显示模板
|
||||
renderDefault(renderOpts, params) {
|
||||
const { row, column } = params
|
||||
const { events = {} } = renderOpts
|
||||
return (
|
||||
<a class="link" onClick={() => events.click(params)}>
|
||||
{row[column.field]}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
})
|
@@ -1,35 +0,0 @@
|
||||
import { VXETable } from 'vxe-table'
|
||||
import { ElImage, ElLink } from 'element-plus'
|
||||
|
||||
// 图片渲染
|
||||
VXETable.renderer.add('XPreview', {
|
||||
// 默认显示模板
|
||||
renderDefault(_renderOpts, params) {
|
||||
const { row, column } = params
|
||||
if (row.type.indexOf('image/') === 0) {
|
||||
return (
|
||||
<ElImage
|
||||
style="width: 80px; height: 50px"
|
||||
src={row[column.field]}
|
||||
key={row[column.field]}
|
||||
preview-src-list={[row[column.field]]}
|
||||
fit="contain"
|
||||
lazy
|
||||
></ElImage>
|
||||
)
|
||||
} else if (row.type.indexOf('video/') === 0) {
|
||||
return (
|
||||
<video>
|
||||
<source src={row[column.field]}></source>
|
||||
</video>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
// @ts-ignore
|
||||
<ElLink href={row[column.field]} target="_blank">
|
||||
{row[column.field]}
|
||||
</ElLink>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
@@ -2,9 +2,9 @@ import { Layout } from '@/utils/routerHelper'
|
||||
|
||||
const { t } = useI18n()
|
||||
/**
|
||||
* redirect: noredirect 当设置 noredirect 的时候该路由在面包屑导航中不可被点击
|
||||
* name:'router-name' 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
|
||||
* meta : {
|
||||
* redirect: noredirect 当设置 noredirect 的时候该路由在面包屑导航中不可被点击
|
||||
* name:'router-name' 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
|
||||
* meta : {
|
||||
hidden: true 当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false)
|
||||
|
||||
alwaysShow: true 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式,
|
||||
@@ -31,7 +31,7 @@ const { t } = useI18n()
|
||||
|
||||
canTo: true 设置为true即使hidden为true,也依然可以进行路由跳转(默认 false)
|
||||
}
|
||||
**/
|
||||
**/
|
||||
const remainingRouter: AppRouteRecordRaw[] = [
|
||||
{
|
||||
path: '/redirect',
|
||||
@@ -272,7 +272,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
{
|
||||
path: '/manager/task-assign-rule',
|
||||
component: () => import('@/views/bpm/taskAssignRule/index.vue'),
|
||||
name: 'BpmTaskAssignRule',
|
||||
name: 'BpmTaskAssignRuleList',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
@@ -313,7 +313,19 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '发起 OA 请假',
|
||||
activeMenu: 'bpm/oa/leave/create'
|
||||
activeMenu: '/bpm/oa/leave'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/bpm/oa/leave/detail',
|
||||
component: () => import('@/views/bpm/oa/leave/detail.vue'),
|
||||
name: 'OALeaveDetail',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '查看 OA 请假',
|
||||
activeMenu: '/bpm/oa/leave'
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -355,6 +367,29 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
meta: { title: '商品属性值', icon: '', activeMenu: '/product/property' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/product',
|
||||
component: Layout,
|
||||
name: 'ProductManagementEdit',
|
||||
meta: {
|
||||
hidden: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'productManagementAdd', // TODO @puhui999:最好拆成 add 和 edit 两个路由;添加商品;修改商品
|
||||
component: () => import('@/views/mall/product/spu/addForm.vue'),
|
||||
name: 'ProductManagementAdd',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
icon: 'ep:edit',
|
||||
title: '添加商品',
|
||||
activeMenu: '/product/product-management'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
@import './var.css';
|
||||
@import './vxe.css';
|
||||
@import 'element-plus/theme-chalk/dark/css-vars.css';
|
||||
|
||||
.reset-margin [class*='el-icon'] + span {
|
||||
@@ -11,6 +10,12 @@
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
// 解决表格内容超过表格总宽度后,横向滚动条前端顶不到表格边缘的问题
|
||||
.el-scrollbar__bar {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* nprogress 适配 element-plus 的主题色 */
|
||||
#nprogress {
|
||||
& .bar {
|
||||
|
@@ -2,5 +2,3 @@
|
||||
$namespace: v;
|
||||
// el命名空间
|
||||
$elNamespace: el;
|
||||
// vxe命名空间
|
||||
$vxeNamespace: vxe;
|
||||
|
@@ -1,30 +0,0 @@
|
||||
/*滚动条整体部分*/
|
||||
.xtable-scrollbar ::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
/*滚动条的轨道*/
|
||||
.xtable-scrollbar ::-webkit-scrollbar-track {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
/*滚动条里面的小方块,能向上向下移动*/
|
||||
.xtable-scrollbar ::-webkit-scrollbar-thumb {
|
||||
background-color: #bfbfbf;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #f1f1f1;
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.xtable-scrollbar ::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #a8a8a8;
|
||||
}
|
||||
.xtable-scrollbar ::-webkit-scrollbar-thumb:active {
|
||||
background-color: #787878;
|
||||
}
|
||||
/*边角,即两个滚动条的交汇处*/
|
||||
.xtable-scrollbar ::-webkit-scrollbar-corner {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
/*移除 vxe-grid 右侧外框*/
|
||||
.vxe-button.size--medium.type--button.is--circle {
|
||||
border: 0;
|
||||
}
|
130
src/types/auto-components.d.ts
vendored
130
src/types/auto-components.d.ts
vendored
@@ -1,130 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
Backtop: typeof import('./../components/Backtop/src/Backtop.vue')['default']
|
||||
ConfigGlobal: typeof import('./../components/ConfigGlobal/src/ConfigGlobal.vue')['default']
|
||||
ContentDetailWrap: typeof import('./../components/ContentDetailWrap/src/ContentDetailWrap.vue')['default']
|
||||
ContentWrap: typeof import('./../components/ContentWrap/src/ContentWrap.vue')['default']
|
||||
CopperModal: typeof import('./../components/Cropper/src/CopperModal.vue')['default']
|
||||
CountTo: typeof import('./../components/CountTo/src/CountTo.vue')['default']
|
||||
Crontab: typeof import('./../components/Crontab/src/Crontab.vue')['default']
|
||||
Cropper: typeof import('./../components/Cropper/src/Cropper.vue')['default']
|
||||
CropperAvatar: typeof import('./../components/Cropper/src/CropperAvatar.vue')['default']
|
||||
Descriptions: typeof import('./../components/Descriptions/src/Descriptions.vue')['default']
|
||||
Dialog: typeof import('./../components/Dialog/src/Dialog.vue')['default']
|
||||
DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default']
|
||||
DocAlert: typeof import('./../components/DocAlert/index.vue')['default']
|
||||
Echart: typeof import('./../components/Echart/src/Echart.vue')['default']
|
||||
Editor: typeof import('./../components/Editor/src/Editor.vue')['default']
|
||||
ElAlert: typeof import('element-plus/es')['ElAlert']
|
||||
ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer']
|
||||
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
||||
ElBadge: typeof import('element-plus/es')['ElBadge']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
|
||||
ElCard: typeof import('element-plus/es')['ElCard']
|
||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||
ElCollapseTransition: typeof import('element-plus/es')['ElCollapseTransition']
|
||||
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
||||
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
|
||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||
ElDivider: typeof import('element-plus/es')['ElDivider']
|
||||
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||
ElementBaseInfo: typeof import('./../components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue')['default']
|
||||
ElementForm: typeof import('./../components/bpmnProcessDesigner/package/penal/form/ElementForm.vue')['default']
|
||||
ElementListeners: typeof import('./../components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue')['default']
|
||||
ElementMultiInstance: typeof import('./../components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue')['default']
|
||||
ElementOtherConfig: typeof import('./../components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue')['default']
|
||||
ElementProperties: typeof import('./../components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue')['default']
|
||||
ElementTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/ElementTask.vue')['default']
|
||||
ElForm: typeof import('element-plus/es')['ElForm']
|
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||
ElImage: typeof import('element-plus/es')['ElImage']
|
||||
ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
||||
ElLink: typeof import('element-plus/es')['ElLink']
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
|
||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
|
||||
ElSpace: typeof import('element-plus/es')['ElSpace']
|
||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||
ElTable: typeof import('element-plus/es')['ElTable']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
ElTableV2: typeof import('element-plus/es')['ElTableV2']
|
||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||
ElTag: typeof import('element-plus/es')['ElTag']
|
||||
ElTimeline: typeof import('element-plus/es')['ElTimeline']
|
||||
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
ElTree: typeof import('element-plus/es')['ElTree']
|
||||
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
|
||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||
Error: typeof import('./../components/Error/src/Error.vue')['default']
|
||||
FlowCondition: typeof import('./../components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue')['default']
|
||||
Form: typeof import('./../components/Form/src/Form.vue')['default']
|
||||
Highlight: typeof import('./../components/Highlight/src/Highlight.vue')['default']
|
||||
Icon: typeof import('./../components/Icon/src/Icon.vue')['default']
|
||||
IconSelect: typeof import('./../components/Icon/src/IconSelect.vue')['default']
|
||||
IFrame: typeof import('./../components/IFrame/src/IFrame.vue')['default']
|
||||
ImageViewer: typeof import('./../components/ImageViewer/src/ImageViewer.vue')['default']
|
||||
Infotip: typeof import('./../components/Infotip/src/Infotip.vue')['default']
|
||||
InputPassword: typeof import('./../components/InputPassword/src/InputPassword.vue')['default']
|
||||
Pagination: typeof import('./../components/Pagination/index.vue')['default']
|
||||
ProcessDesigner: typeof import('./../components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue')['default']
|
||||
ProcessPalette: typeof import('./../components/bpmnProcessDesigner/package/palette/ProcessPalette.vue')['default']
|
||||
ProcessViewer: typeof import('./../components/bpmnProcessDesigner/package/designer/ProcessViewer.vue')['default']
|
||||
PropertiesPanel: typeof import('./../components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue')['default']
|
||||
Qrcode: typeof import('./../components/Qrcode/src/Qrcode.vue')['default']
|
||||
ReceiveTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
ScriptTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue')['default']
|
||||
Search: typeof import('./../components/Search/src/Search.vue')['default']
|
||||
SignalAndMessage: typeof import('./../components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue')['default']
|
||||
Sticky: typeof import('./../components/Sticky/src/Sticky.vue')['default']
|
||||
Table: typeof import('./../components/Table/src/Table.vue')['default']
|
||||
Tooltip: typeof import('./../components/Tooltip/src/Tooltip.vue')['default']
|
||||
UploadFile: typeof import('./../components/UploadFile/src/UploadFile.vue')['default']
|
||||
UploadImg: typeof import('./../components/UploadFile/src/UploadImg.vue')['default']
|
||||
UploadImgs: typeof import('./../components/UploadFile/src/UploadImgs.vue')['default']
|
||||
UserTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue')['default']
|
||||
UserTaskListeners: typeof import('./../components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue')['default']
|
||||
Verify: typeof import('./../components/Verifition/src/Verify.vue')['default']
|
||||
VerifyPoints: typeof import('./../components/Verifition/src/Verify/VerifyPoints.vue')['default']
|
||||
VerifySlide: typeof import('./../components/Verifition/src/Verify/VerifySlide.vue')['default']
|
||||
XButton: typeof import('./../components/XButton/src/XButton.vue')['default']
|
||||
XModal: typeof import('./../components/XModal/src/XModal.vue')['default']
|
||||
XTable: typeof import('./../components/XTable/src/XTable.vue')['default']
|
||||
XTextButton: typeof import('./../components/XButton/src/XTextButton.vue')['default']
|
||||
}
|
||||
export interface ComponentCustomProperties {
|
||||
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
||||
}
|
||||
}
|
77
src/types/auto-imports.d.ts
vendored
77
src/types/auto-imports.d.ts
vendored
@@ -1,77 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
const DICT_TYPE: typeof import('@/utils/dict')['DICT_TYPE']
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const required: typeof import('@/utils/formRules')['required']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCrudSchemas: typeof import('@/hooks/web/useCrudSchemas')['useCrudSchemas']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useI18n: typeof import('@/hooks/web/useI18n')['useI18n']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useMessage: typeof import('@/hooks/web/useMessage')['useMessage']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useTable: typeof import('@/hooks/web/useTable')['useTable']
|
||||
const useVxeCrudSchemas: typeof import('@/hooks/web/useVxeCrudSchemas')['useVxeCrudSchemas']
|
||||
const useXTable: typeof import('@/hooks/web/useXTable')['useXTable']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
|
||||
}
|
@@ -114,6 +114,10 @@ export const PayChannelEnum = {
|
||||
ALIPAY_QR: {
|
||||
code: 'alipay_qr',
|
||||
name: '支付宝扫码支付'
|
||||
},
|
||||
ALIPAY_BAR: {
|
||||
code: 'alipay_bar',
|
||||
name: '支付宝条码支付'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,3 +220,21 @@ export const PayRefundStatusEnum = {
|
||||
name: '退款关闭'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品SPU枚举类
|
||||
*/
|
||||
export const ProductSpuStatusEnum = {
|
||||
RECYCLE: {
|
||||
status: -1,
|
||||
name: '回收站'
|
||||
},
|
||||
DISABLE: {
|
||||
status: 0,
|
||||
name: '下架'
|
||||
},
|
||||
ENABLE: {
|
||||
status: 1,
|
||||
name: '上架'
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ export interface DictDataType {
|
||||
}
|
||||
|
||||
export const getDictOptions = (dictType: string) => {
|
||||
return dictStore.getDictByType(dictType)
|
||||
return dictStore.getDictByType(dictType) || []
|
||||
}
|
||||
|
||||
export const getIntDictOptions = (dictType: string) => {
|
||||
@@ -117,6 +117,7 @@ export enum DICT_TYPE {
|
||||
INFRA_API_ERROR_LOG_PROCESS_STATUS = 'infra_api_error_log_process_status',
|
||||
INFRA_CONFIG_TYPE = 'infra_config_type',
|
||||
INFRA_CODEGEN_TEMPLATE_TYPE = 'infra_codegen_template_type',
|
||||
INFRA_CODEGEN_FRONT_TYPE = 'infra_codegen_front_type',
|
||||
INFRA_CODEGEN_SCENE = 'infra_codegen_scene',
|
||||
INFRA_FILE_STORAGE = 'infra_file_storage',
|
||||
|
||||
@@ -143,5 +144,9 @@ export enum DICT_TYPE {
|
||||
|
||||
// ========== MP 模块 ==========
|
||||
MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型
|
||||
MP_MESSAGE_TYPE = 'mp_message_type' // 消息类型
|
||||
MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型
|
||||
|
||||
// ========== MALL 模块 ==========
|
||||
PRODUCT_UNIT = 'product_unit', // 商品单位
|
||||
PRODUCT_SPU_STATUS = 'product_spu_status' //商品状态
|
||||
}
|
||||
|
@@ -1,8 +0,0 @@
|
||||
export const isDevMode = () => {
|
||||
const dev = import.meta.env.VITE_DEV
|
||||
if (dev && dev === 'true') {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
18
src/utils/object.ts
Normal file
18
src/utils/object.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// TODO @puhui999:这个方法,可以考虑放到 index.js
|
||||
/**
|
||||
* 将值复制到目标对象,且以目标对象属性为准,例:target: {a:1} source:{a:2,b:3} 结果为:{a:2}
|
||||
* @param target 目标对象
|
||||
* @param source 源对象
|
||||
*/
|
||||
export const copyValueToTarget = (target, source) => {
|
||||
const newObj = Object.assign({}, target, source)
|
||||
// 删除多余属性
|
||||
Object.keys(newObj).forEach((key) => {
|
||||
// 如果不是target中的属性则删除
|
||||
if (Object.keys(target).indexOf(key) === -1) {
|
||||
delete newObj[key]
|
||||
}
|
||||
})
|
||||
// 更新目标对象值
|
||||
Object.assign(target, newObj)
|
||||
}
|
@@ -1,10 +1,22 @@
|
||||
import type { RouteLocationNormalized, Router, RouteRecordNormalized } from 'vue-router'
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
||||
import type { Router, RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'
|
||||
import { isUrl } from '@/utils/is'
|
||||
import { omit, cloneDeep } from 'lodash-es'
|
||||
import { cloneDeep, omit } from 'lodash-es'
|
||||
|
||||
const modules = import.meta.glob('../views/**/*.{vue,tsx}')
|
||||
|
||||
/**
|
||||
* 注册一个异步组件
|
||||
* @param componentPath 例:/bpm/oa/leave/detail
|
||||
*/
|
||||
export const registerComponent = (componentPath: string) => {
|
||||
for (const item in modules) {
|
||||
if (item.includes(componentPath)) {
|
||||
// 使用异步组件的方式来动态加载组件
|
||||
// @ts-ignore
|
||||
return defineAsyncComponent(modules[item])
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Layout */
|
||||
export const Layout = () => import('@/layout/Layout.vue')
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<Error type="403" @error-click="push('/')" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Error403" setup>
|
||||
const { push } = useRouter()
|
||||
</script>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<Error @error-click="push('/')" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Error404" setup>
|
||||
const { push } = useRouter()
|
||||
</script>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<Error type="500" @error-click="push('/')" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" name="Error500" setup>
|
||||
const { push } = useRouter()
|
||||
</script>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user