jeecgboot-vue 1.1.0-beta版本源码发布

pull/50/head
zhangdaiscott 2022-04-27 19:19:39 +08:00
parent 3aa84883ce
commit 40c2fc9f64
96 changed files with 2562 additions and 838 deletions

2
.env
View File

@ -8,7 +8,7 @@ VITE_GLOB_APP_TITLE = JeecgBoot 企业级低代码平台
VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin
# 单点登录服务端地址
VITE_GLOBE_APP_CAS_BASE_URL=http://cas.test.com:8443/cas
VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas
# 是否开启单点登录
VITE_GLOB_APP_OPEN_SSO = false

2
.gitignore vendored
View File

@ -1,5 +1,6 @@
node_modules
.DS_Store
.github
dist
.npmrc
.cache
@ -27,3 +28,4 @@ pnpm-debug.log*
*.njsproj
*.sln
*.sw?
/os_del.cmd

View File

@ -1,13 +1,13 @@
JEECG BOOT 低代码平台Vue3前端
===============
当前最新版本: 1.0.020220321
当前最新版本: 1.1.0-beta预计发布时间20220516
## 简介
JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue、TypeScript 等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。
是在 Vben-Admin 基础上研发的适合于JeecgBoot的新版前端VUE3框架。
> 全新的VUE3技术栈不只是追赶技术潮流用了之后才能体会到Vue3的好处的确比2更加适合大型项目。
@ -37,7 +37,7 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue、TypeScript 等新技术
## 安装与使用
- Get the project code
```bash
@ -224,6 +224,3 @@ yarn build

View File

@ -15,6 +15,8 @@ import { configThemePlugin } from './theme';
import { configImageminPlugin } from './imagemin';
import { configSvgIconsPlugin } from './svgSprite';
import { configHmrPlugin } from './hmr';
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const {
@ -78,5 +80,9 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
vitePlugins.push(configPwaConfig(viteEnv));
}
//vite-plugin-theme【解决vite首次打开界面加载慢问题】
vitePlugins.push(PkgConfig());
vitePlugins.push(OptimizationPersist());
return vitePlugins;
}

View File

@ -10,7 +10,7 @@
"bootstrap": "yarn install",
"serve": "npm run dev",
"dev": "vite",
"build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
"build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 vite build && esno ./build/script/postBuild.ts",
"build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
"build:no-cache": "yarn clean:cache && npm run build",
"report": "cross-env REPORT=true npm run build",
@ -35,11 +35,11 @@
},
"dependencies": {
"@iconify/iconify": "^2.0.4",
"@fullcalendar/core": "^5.8.0",
"@fullcalendar/daygrid": "^5.8.0",
"@fullcalendar/interaction": "^5.8.0",
"@fullcalendar/timegrid": "^5.8.0",
"@fullcalendar/vue3": "^5.8.0",
"@fullcalendar/core": "^5.10.1",
"@fullcalendar/daygrid": "^5.10.1",
"@fullcalendar/interaction": "^5.10.1",
"@fullcalendar/timegrid": "^5.10.1",
"@fullcalendar/vue3": "^5.10.1",
"@vueuse/core": "^6.6.2",
"@zxcvbn-ts/core": "^1.0.0-beta.0",
"ant-design-vue": "2.2.8",
@ -152,6 +152,8 @@
"vite-plugin-html": "^2.1.0",
"vite-plugin-imagemin": "^0.4.6",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-optimize-persist": "^0.1.2",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.7.0",
"vite-plugin-pwa": "^0.11.3",
"vite-plugin-style-import": "^1.2.1",
@ -178,5 +180,121 @@
"homepage": "https://github.com/jeecgboot/jeecgboot-vue3",
"engines": {
"node": "^12 || >=14"
},
"vite": {
"optimizeDeps": {
"include": [
"@ant-design/colors",
"@ant-design/icons-vue",
"@fullcalendar/core/vdom",
"@fullcalendar/daygrid",
"@fullcalendar/interaction",
"@fullcalendar/timegrid",
"@fullcalendar/vue3",
"@vueuse/core",
"@vueuse/shared",
"@zxcvbn-ts/core",
"ant-design-vue",
"axios",
"china-area-data",
"clipboard",
"codemirror",
"codemirror/addon/fold/brace-fold.js",
"codemirror/addon/fold/comment-fold.js",
"codemirror/addon/fold/foldcode.js",
"codemirror/addon/fold/foldgutter.js",
"codemirror/addon/fold/indent-fold.js",
"codemirror/addon/hint/anyword-hint.js",
"codemirror/addon/hint/show-hint.js",
"codemirror/addon/selection/active-line.js",
"codemirror/mode/clike/clike.js",
"codemirror/mode/css/css.js",
"codemirror/mode/javascript/javascript.js",
"codemirror/mode/markdown/markdown.js",
"codemirror/mode/python/python.js",
"codemirror/mode/r/r.js",
"codemirror/mode/shell/shell.js",
"codemirror/mode/sql/sql.js",
"codemirror/mode/swift/swift.js",
"codemirror/mode/vue/vue.js",
"codemirror/mode/xml/xml.js",
"cron-parser",
"cropperjs",
"crypto-js/aes",
"crypto-js/enc-base64",
"crypto-js/enc-utf8",
"crypto-js/md5",
"crypto-js/mode-ecb",
"crypto-js/pad-pkcs7",
"dom-align",
"echarts",
"echarts/charts",
"echarts/components",
"echarts/core",
"echarts/renderers",
"intro.js",
"lodash-es",
"md5",
"moment",
"nprogress",
"path-to-regexp",
"pinia",
"print-js",
"qiankun",
"qrcode",
"qs",
"resize-observer-polyfill",
"showdown",
"sortablejs",
"tinymce/icons/default/icons",
"tinymce/plugins/advlist",
"tinymce/plugins/anchor",
"tinymce/plugins/autolink",
"tinymce/plugins/autosave",
"tinymce/plugins/code",
"tinymce/plugins/codesample",
"tinymce/plugins/contextmenu",
"tinymce/plugins/directionality",
"tinymce/plugins/fullscreen",
"tinymce/plugins/hr",
"tinymce/plugins/image",
"tinymce/plugins/insertdatetime",
"tinymce/plugins/link",
"tinymce/plugins/lists",
"tinymce/plugins/media",
"tinymce/plugins/nonbreaking",
"tinymce/plugins/noneditable",
"tinymce/plugins/pagebreak",
"tinymce/plugins/paste",
"tinymce/plugins/preview",
"tinymce/plugins/print",
"tinymce/plugins/save",
"tinymce/plugins/searchreplace",
"tinymce/plugins/spellchecker",
"tinymce/plugins/tabfocus",
"tinymce/plugins/table",
"tinymce/plugins/template",
"tinymce/plugins/textcolor",
"tinymce/plugins/textpattern",
"tinymce/plugins/visualblocks",
"tinymce/plugins/visualchars",
"tinymce/plugins/wordcount",
"tinymce/themes/silver",
"tinymce/tinymce",
"vditor",
"vite-plugin-theme/es/client",
"vite-plugin-theme/es/colorUtils",
"vue",
"vue-i18n",
"vue-print-nb-jeecg/src/printarea",
"vue-router",
"vue-types",
"vue3-drag-test4",
"vxe-table",
"vxe-table-plugin-antd",
"xe-utils",
"xlsx"
]
}
}
}

View File

@ -1,10 +1,10 @@
module.exports = {
printWidth: 100,
printWidth: 200,
tabWidth: 2,
useTabs: false,
semi: true,
semi: true, //语句末尾使用分号
vueIndentScriptAndStyle: true,
singleQuote: true,
singleQuote: true, // 使用单引号
quoteProps: 'as-needed',
bracketSpacing: true,
trailingComma: 'es5',

View File

@ -3,8 +3,13 @@ import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userMod
import { ErrorMessageMode } from '/#/axios';
import {useMessage} from "/@/hooks/web/useMessage";
import {useUserStoreWithOut} from "/@/store/modules/user";
import {setAuthCache} from "/@/utils/auth";
import {TOKEN_KEY} from "/@/enums/cacheEnum";
import {router} from "/@/router";
import {PageEnum} from "/@/enums/pageEnum";
const { createMessage, createErrorModal } = useMessage();
const { createErrorModal } = useMessage();
enum Api {
Login = '/sys/login',
@ -73,8 +78,18 @@ export function phoneLoginApi(params: LoginParams, mode: ErrorMessageMode = 'mod
/**
* @description: getUserInfo
*/
export function getUserInfo() {
return defHttp.get<GetUserInfoModel>({ url: Api.GetUserInfo }, { errorMessageMode: 'none' });
export function getUserInfo() {
return defHttp.get<GetUserInfoModel>({ url: Api.GetUserInfo }, { errorMessageMode: 'none' }).catch((e)=>{
// update-begin--author:zyf---date:20220425---for:【VUEN-76】捕获接口超时异常,跳转到登录界面
if (e && e.message.includes('timeout')) {
//接口不通时跳转到登录界面
const userStore = useUserStoreWithOut();
userStore.setToken('');
setAuthCache(TOKEN_KEY, null);
router.push(PageEnum.BASE_LOGIN);
}
// update-end--author:zyf---date:20220425---for:【VUEN-76】捕获接口超时异常,跳转到登录界面
});
}
export function getPermCode() {

View File

@ -55,6 +55,10 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
}
const reg = createSearchReg(unref(keyword));
const filterMenu = filter(menuList, (item) => {
// 【issues/33】包含子菜单时不添加到搜索队列
if (Array.isArray(item.children)) {
return false
}
return reg.test(item.name) && !item.hideMenu;
});
searchResult.value = handlerSearchResult(filterMenu, reg);

View File

@ -1,15 +1,16 @@
<template>
<a-dropdown :trigger="trigger" v-bind="$attrs">
<a-dropdown :class="[prefixCls]" :trigger="trigger" v-bind="$attrs">
<span>
<slot></slot>
</span>
<template #overlay>
<a-menu :selectedKeys="selectedKeys">
<a-menu :class="[`${prefixCls}-menu`]" :selectedKeys="selectedKeys">
<template v-for="item in dropMenuList" :key="`${item.event}`">
<a-menu-item
v-bind="getAttr(item.event)"
@click="handleClickMenu(item)"
:disabled="item.disabled"
:class="[{'is-pop-confirm': item.popConfirm}]"
>
<a-popconfirm
v-if="popconfirm && item.popConfirm"
@ -18,7 +19,7 @@
<template #icon v-if="item.popConfirm.icon">
<Icon :icon="item.popConfirm.icon" />
</template>
<div>
<div class="dropdown-event-area">
<Icon :icon="item.icon" v-if="item.icon" />
<span class="ml-1">{{ item.text }}</span>
</div>
@ -42,6 +43,7 @@
import { Icon } from '/@/components/Icon';
import { omit } from 'lodash-es';
import { isFunction } from '/@/utils/is';
import {useDesign} from '/@/hooks/web/useDesign'
const ADropdown = Dropdown;
const AMenu = Menu;
@ -49,6 +51,7 @@
const AMenuDivider = Menu.Divider;
const APopconfirm = Popconfirm;
const { prefixCls } = useDesign('basic-dropdown');
const props = defineProps({
popconfirm: Boolean,
/**
@ -94,3 +97,21 @@
const getAttr = (key: string | number) => ({ key });
</script>
<style lang="less">
@prefix-cls: ~'@{namespace}-basic-dropdown';
.@{prefix-cls} {
// update-begin--author:sunjianlei---date:20220322---for: VUEN-180
&-menu .ant-dropdown-menu-item.is-pop-confirm {
padding: 0;
.dropdown-event-area {
padding: 5px 12px;
}
}
// update-end--author:sunjianlei---date:20220322---for: VUEN-180
}
</style>

View File

@ -56,9 +56,12 @@ import JSelectUserByDept from './jeecg/components/JSelectUserByDept.vue';
import JUpload from './jeecg/components/JUpload/JUpload.vue'
import JSearchSelect from './jeecg/components/JSearchSelect.vue'
import JAddInput from './jeecg/components/JAddInput.vue'
import {Time} from '/@/components/Time';
import JOnlineSelectCascade from './jeecg/components/JOnlineSelectCascade.vue'
const componentMap = new Map<ComponentType, Component>();
componentMap.set('Time', Time);
componentMap.set('Input', Input);
componentMap.set('InputGroup', Input.Group);
componentMap.set('InputPassword', Input.Password);
@ -121,6 +124,7 @@ componentMap.set('JSelectUserByDept', JSelectUserByDept);
componentMap.set('JUpload', JUpload);
componentMap.set('JSearchSelect', JSearchSelect);
componentMap.set('JAddInput', JAddInput);
componentMap.set('JOnlineSelectCascade', JOnlineSelectCascade)
export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component);

View File

@ -346,7 +346,8 @@
wrapperCol={wrapperCol}
>
<div style="display:flex">
<div style="flex:1;">{getContent()}</div>
{/* author: sunjianlei for: 【VUEN-744】此处加上 width: 100%; 因为要防止组件宽度超出 FormItem */ }
<div style="flex:1; width: 100%;">{getContent()}</div>
{showSuffix && <span class="suffix">{getSuffix}</span>}
</div>
</Form.Item>

View File

@ -4,7 +4,7 @@
<script lang="ts">
import {defineComponent, PropType, ref,reactive, watchEffect, computed, unref, watch, onMounted} from 'vue';
import {Cascader} from 'ant-design-vue';
import {provinceAndCityData, regionData, provinceAndCityDataPlus, regionDataPlus, CodeToText, TextToCode} from "../../utils/areaDataUtil";
import {provinceAndCityData, regionData, provinceAndCityDataPlus, regionDataPlus} from "../../utils/areaDataUtil";
import {useRuleFormItem} from "/@/hooks/component/useFormItem";
import {propTypes} from "/@/utils/propTypes";
import {useAttrs} from "/@/hooks/core/useAttrs";

View File

@ -30,6 +30,11 @@
*/
watchEffect(() => {
props.value && (checkboxArray.value = props.value ? props.value.split(",") : []);
//update-begin-author:taoyan date:20220401 for: resetFields
if(props.value === '' || props.value === undefined){
checkboxArray.value = []
}
//update-end-author:taoyan date:20220401 for: resetFields
});
/**
* 监听字典code

View File

@ -44,6 +44,7 @@
import "codemirror/addon/hint/anyword-hint.js";
import { useAttrs } from '/@/hooks/core/useAttrs';
import {useDesign} from '/@/hooks/web/useDesign'
import {isJsonObjectString} from '/@/utils/is.ts'
export default defineComponent({
name: 'JCodeEditor',
@ -86,6 +87,14 @@
// :
//
styleActiveLine: true,
//
extraKeys:{
Tab: function autoFormat(editor) {
//var totalLines = editor.lineCount();
//editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
setValue(innerValue,false)
}
}
});
let innerValue = ''
//
@ -125,6 +134,9 @@
* @param trigger 是否触发 change 事件
*/
function setValue(value: string, trigger = true) {
if(value && isJsonObjectString(value)){
value = JSON.stringify(JSON.parse(value),null,2);
}
coder?.setValue(value ?? '')
innerValue = value
trigger && emitChange(innerValue)
@ -132,7 +144,8 @@
//
function onChange(obj) {
innerValue = obj.getValue() ?? '';
let value = obj.getValue();
innerValue = value || '';
if (props.value != innerValue) {
emitChange(innerValue)
}

View File

@ -15,7 +15,14 @@
</template>
</a-radio-group>
<a-select v-else-if="compType===CompTypeEnum.Select" :placeholder="placeholder" v-bind="attrs" v-model:value="state" @change="handleChange">
<template v-else-if="compType===CompTypeEnum.Select">
<!-- 显示加载效果 -->
<a-input v-if="loadingEcho" readOnly placeholder="加载中…">
<template #prefix>
<LoadingOutlined/>
</template>
</a-input>
<a-select v-else :placeholder="placeholder" v-bind="attrs" v-model:value="state" :filterOption="handleFilterOption" :getPopupContainer="getPopupContainer" @change="handleChange">
<a-select-option v-if="showChooseOption" :value="undefined"></a-select-option>
<template v-for="item in dictOptions" :key="`${item.value}`">
<a-select-option :value="item.value">
@ -25,6 +32,7 @@
</a-select-option>
</template>
</a-select>
</template>
</template>
<script lang="ts">
import {defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted} from 'vue';
@ -34,9 +42,12 @@
import {get, omit} from 'lodash-es';
import {useRuleFormItem} from '/@/hooks/component/useFormItem';
import {CompTypeEnum} from '/@/enums/CompTypeEnum.ts';
import {LoadingOutlined} from '@ant-design/icons-vue'
export default defineComponent({
name: 'JDictSelectTag',
inheritAttrs: false,
components: {LoadingOutlined},
props: {
value: propTypes.oneOfType([
propTypes.string,
@ -51,8 +62,14 @@
type: Function,
default: (node) => node.parentNode
},
//
showChooseOption: propTypes.bool.def(true),
//
showChooseOption: propTypes.bool.def(true),
// -online使
options: {
type: Array,
default: [],
required: false
},
},
emits: ['options-change', 'change'],
setup(props, {emit, refs}) {
@ -61,6 +78,11 @@
const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
const getBindValue = Object.assign({}, unref(props), unref(attrs));
//
const loadingEcho = ref<boolean>(false)
// loading
let isFirstLoadEcho = true
//
const compType = computed(() => {
return (!props.type || props.type === "list") ? 'select' : props.type;
@ -69,8 +91,30 @@
* 监听字典code
*/
watchEffect(() => {
props.dictCode && initDictData();
if (props.dictCode) {
loadingEcho.value = isFirstLoadEcho
isFirstLoadEcho = false
initDictData().finally(() => {
loadingEcho.value = isFirstLoadEcho
})
}
//update-begin-author:taoyan date: dictCode options--
if(!props.dictCode){
dictOptions.value = props.options
}
//update-end-author:taoyan date: dictCode options--
});
//update-begin-author:taoyan date:20220404 for: 使useRuleFormItemvaluechange
// change,value''change
watch(()=>props.value, ()=>{
if(props.value===''){
emit('change', '')
}
});
//update-end-author:taoyan date:20220404 for: 使useRuleFormItemvaluechange
async function initDictData() {
let {dictCode, stringToNumber} = props;
@ -93,14 +137,27 @@
emitData.value = [e?.target?.value || e];
}
/** 用于搜索下拉框中的内容 */
function handleFilterOption(input, option) {
// label
let labelIf = option?.children[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
if (labelIf) {
return true
}
// value
return (option.value || '').toString().toLowerCase().indexOf(input.toLowerCase()) >= 0
}
return {
state,
compType,
attrs,
loadingEcho,
getBindValue,
dictOptions,
CompTypeEnum,
handleChange
handleChange,
handleFilterOption,
};
},
});

View File

@ -3,6 +3,7 @@
trigger="contextmenu"
v-model:visible="visible"
:overlayClassName="`${prefixCls}-popover`"
:getPopupContainer="getPopupContainer"
:placement="position">
<template #title>
<span>{{ title }}</span>

View File

@ -0,0 +1,213 @@
<template>
<!-- 级联下拉框 form组件 暂且只在online使用 不对外提供api -->
<a-select :placeholder="placeholder" :value="selectedValue" @change="handleChange" allowClear style="width:100%">
<a-select-option v-for="(item, index) in dictOptions" :key="index" :value="item.store">
<span style="display: inline-block;width: 100%" :title=" item.label ">{{ item.label }}</span>
</a-select-option>
</a-select>
</template>
<script lang="ts">
import { defineComponent, watch, ref } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
/**获取下拉选项*/
const SELECT_OPTIONS_URL = '/online/cgform/api/querySelectOptions';
export default defineComponent({
name: "JOnlineSelectCascade",
props:{
table:{ type: String, default: '' },
txt: { type: String, default: '' },
store: { type: String, default: '' },
idField: { type: String, default: '' },
pidField: { type: String, default: '' },
pidValue: { type: String, default: '-1' },
origin: { type: Boolean, default: false },
condition: { type: String, default: '' },
value:{ type: String, default: '' },
isNumber:{ type: Boolean, default: false },
placeholder: { type: String, default: '请选择' },
},
emits: [ 'change', 'next'],
setup(props, { emit }){
const { createMessage: $message } = useMessage()
//
const selectedValue = ref<any>('');
//
const dictOptions = ref<any[]>([])
const optionsLoad = ref(true)
//
function handleChange(value) {
console.log('handleChange', value)
// value id
let temp = value || ''
emit('change', temp)
valueChangeThenEmitNext(temp)
}
// condition
watch(()=>props.condition, (val)=>{
optionsLoad.value = true;
if(val){
loadOptions();
}
}, {immediate:true});
// pidValue
watch(()=>props.pidValue, (val)=>{
if(val === '-1'){
dictOptions.value = []
}else{
loadOptions();
}
});
//
watch(()=>props.value, (newVal, oldVal)=>{
console.log('值改变事件', newVal, oldVal)
if(!newVal){
// value--
selectedValue.value = []
if(oldVal){
// oldVal
emit('change', '')
emit('next', '-1')
}
}else{
// value
selectedValue.value = newVal
}
if(newVal && !oldVal){
// options
handleFirstValueSetting(newVal)
}
}, {immediate:true});
/**
* 第一次加载赋值
*/
async function handleFirstValueSetting(value){
if(props.idField === props.store){
// id
emit('next', value)
}else{
if(props.origin===true){
// optionsoptions
await getSelfOptions()
valueChangeThenEmitNext(value)
}else{
// value
let arr = await loadValueText();
valueChangeThenEmitNext(value, arr)
}
}
}
function loadOptions() {
let params = getQueryParams();
if(props.origin===true){
params['condition'] = props.condition
}else{
params['pidValue'] = props.pidValue
}
console.log("请求参数", params)
dictOptions.value = []
defHttp.get({ url: SELECT_OPTIONS_URL, params},{ isTransformResponse: false }).then(res=>{
if(res.success){
dictOptions.value = [...res.result]
console.log("请求结果", res.result, dictOptions)
}else{
$message.warning('联动组件数据加载失败,请检查配置!')
}
})
}
function getQueryParams(){
let params = {
table: props.table,
txt: props.txt,
key: props.store,
idField: props.idField,
pidField: props.pidField
}
return params;
}
function loadValueText() {
return new Promise(resolve => {
if(!props.value){
selectedValue.value = []
resolve([])
}else{
let params = getQueryParams();
if(props.isNumber === true){
params['condition'] = `${props.store} = ${props.value}`
}else{
params['condition'] = `${props.store} = '${props.value}'`
}
defHttp.get({ url: SELECT_OPTIONS_URL, params},{ isTransformResponse: false }).then(res=>{
if(res.success){
resolve(res.result)
}else{
$message.warning('联动组件数据加载失败,请检查配置!')
resolve([])
}
})
}
})
}
/**
* 获取下拉选项
*/
function getSelfOptions() {
return new Promise((resolve) => {
let index = 0;
(function next(index) {
if(index>10){
resolve([])
}
let arr = dictOptions.value
if (arr && arr.length>0) {
resolve(arr)
} else {
setTimeout(() => {
next(index++)
}, 300)
}
})(index)
})
}
/**
* 值改变后 需要往外抛事件 触发下级节点的选项改变
*/
function valueChangeThenEmitNext(value, arr:any=[]){
if(value && value.length>0){
if(!arr || arr.length==0){
arr = dictOptions.value
}
let selected = arr.filter(item=>item.store===value)
if(selected && selected.length>0){
let id = selected[0].id
emit('next', id)
}
}
}
return {
selectedValue,
dictOptions,
handleChange
}
}
})
</script>
<style scoped>
</style>

View File

@ -76,6 +76,8 @@
const selectedValue = ref([]);
const selectedAsyncValue = ref([]);
const lastLoad = ref(0);
// valuetext
const loadSelectText = ref(true);
/**
* 监听字典code
*/
@ -88,7 +90,7 @@
watch(
() => props.value,
(val) => {
if (val || val == 0) {
if (val || val === 0) {
initSelectValue()
} else {
selectedValue.value = []
@ -132,6 +134,12 @@
* 初始化value
*/
function initSelectValue() {
//update-begin-author:taoyan date:2022-4-24 for: value
if(loadSelectText.value===false){
loadSelectText.value = true
return
}
//update-end-author:taoyan date:2022-4-24 for: value
let {async, value, dict} = props;
if (async) {
if (!selectedAsyncValue || !selectedAsyncValue.key || selectedAsyncValue.key !== value) {
@ -216,6 +224,7 @@
*回调方法
* */
function callback(){
loadSelectText.value = false;
emit('change', unref(selectedValue));
emit('update:value', unref(selectedValue));
}
@ -227,13 +236,17 @@
}
function getParentContainer(node){
// update-begin-author:taoyan date:20220407 for: getPopupContainer popContainer
if(props.popContainer){
return document.querySelector(props.popContainer)
}else{
if(typeof props.getPopupContainer === 'function'){
return props.getPopupContainer(node)
} else if(!props.popContainer){
return node.parentNode
}else{
return document.querySelector(props.popContainer)
return props.getPopupContainer(node)
} else {
return node.parentNode
}
}
// update-end-author:taoyan date:20220407 for: getPopupContainer popContainer
}
return {
attrs,

View File

@ -1,7 +1,7 @@
<!--部门选择组件-->
<template>
<div>
<JSelectBiz @handleOpen="handleOpen" v-bind="attrs"/>
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"/>
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" />
</div>
</template>
@ -24,6 +24,8 @@
inheritAttrs: false,
props: {
value: propTypes.oneOfType([propTypes.string, propTypes.array]),
// true
multiple: propTypes.bool.def(true),
},
emits: ['options-change', 'change','select','update:value'],
setup(props, { emit, refs }) {
@ -38,10 +40,14 @@
let selectValues = reactive<object>({
value: []
});
//
const loadingEcho = ref<boolean>(false)
// selectOptions,xxxBiz
provide('selectOptions', selectOptions);
// selectValues,xxxBiz
provide('selectValues', selectValues);
// loadingEcho,xxxBiz
provide('loadingEcho', loadingEcho);
const tag = ref(false);
const attrs = useAttrs();
@ -51,6 +57,12 @@
*/
watchEffect(() => {
props.value && initValue();
// update-begin-author:taoyan date:20220401 for: resetFields
if(props.value==='' || props.value===undefined){
state.value = []
selectValues.value = []
}
// update-end-author:taoyan date:20220401 for: resetFields
});
/**
@ -89,6 +101,7 @@
state.value = value.split(',');
selectValues.value = value.split(',');
}
}
/**
@ -107,6 +120,7 @@
attrs,
selectOptions,
selectValues,
loadingEcho,
getBindValue,
tag,
regModal,

View File

@ -6,7 +6,7 @@
import { propTypes } from '/@/utils/propTypes'
import { defineComponent, ref, watch, computed } from 'vue'
//
//
export default defineComponent({
name: 'JSelectInput',
props: {
@ -50,11 +50,11 @@ export default defineComponent({
}
//
function deleteSearchAdd(value) {
function deleteSearchAdd(value = '') {
let indexes: any[] = []
options.value.forEach((option, index) => {
if (option.searchAdd) {
if (option.value.toLocaleString() !== value.toLocaleString()) {
if ((option.value ?? '').toString() !== value.toString()) {
indexes.push(index)
}
}

View File

@ -1,6 +1,6 @@
<!--字典下拉多选-->
<template>
<a-select :value="arrayValue" @change="onChange" mode="multiple" :placeholder="placeholder">
<a-select :value="arrayValue" @change="onChange" mode="multiple" :placeholder="placeholder" allowClear :getPopupContainer="getParentContainer">
<a-select-option v-for="(item,index) in dictOptions" :key="index" :getPopupContainer="getParentContainer" :value="item.value">
{{ item.text || item.label }}
</a-select-option>
@ -61,7 +61,7 @@
},
emits: ['options-change', 'change', 'input', 'update:value'],
setup(props, { emit, refs }) {
console.info(props);
//console.info(props);
const emitData = ref<any[]>([]);
const arrayValue = ref<any[]>(!props.value ? [] : props.value.split(props.spliter));
const dictOptions = ref<any[]>([]);
@ -109,7 +109,7 @@
getDictItems(props.dictCode).then(res => {
if (res) {
dictOptions.value = res.map(item => ({ value: item.value, label: item.text }));
console.info('res', dictOptions.value);
//console.info('res', dictOptions.value);
} else {
console.error('getDictItems error: : ', res);
dictOptions.value = [];

View File

@ -1,7 +1,7 @@
<!--职务选择组件-->
<template>
<div>
<JSelectBiz @handleOpen="handleOpen" v-bind="attrs"></JSelectBiz>
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<PositionSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></PositionSelectModal>
</div>
</template>
@ -54,10 +54,14 @@
value: [],
change: false
});
//
const loadingEcho = ref<boolean>(false)
// selectOptions,xxxBiz
provide('selectOptions', selectOptions);
// selectValues,xxxBiz
provide('selectValues', selectValues);
// loadingEcho,xxxBiz
provide('loadingEcho', loadingEcho);
const tag = ref(false);
const attrs = useAttrs();
@ -117,6 +121,7 @@
attrs,
selectOptions,
selectValues,
loadingEcho,
tag,
regModal,
setValue,

View File

@ -1,7 +1,7 @@
<!--角色选择组件-->
<template>
<div>
<JSelectBiz @handleOpen="handleOpen" v-bind="attrs"></JSelectBiz>
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<RoleSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></RoleSelectModal>
</div>
</template>
@ -54,10 +54,14 @@
value: [],
change: false
});
//
const loadingEcho = ref<boolean>(false)
// selectOptions,xxxBiz
provide('selectOptions', selectOptions);
// selectValues,xxxBiz
provide('selectValues', selectValues);
// loadingEcho,xxxBiz
provide('loadingEcho', loadingEcho);
const tag = ref(false);
const attrs = useAttrs();
@ -116,6 +120,7 @@
getBindValue,
selectOptions,
selectValues,
loadingEcho,
tag,
regModal,
setValue,

View File

@ -1,7 +1,7 @@
<!--用户选择组件-->
<template>
<div>
<JSelectBiz @handleOpen="handleOpen" v-bind="attrs"></JSelectBiz>
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<UserSelectModal :rowKey="rowKey" @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></UserSelectModal>
</div>
</template>
@ -15,7 +15,7 @@
import {useRuleFormItem} from "/@/hooks/component/useFormItem";
import {useAttrs} from "/@/hooks/core/useAttrs";
import {SelectTypes} from 'ant-design-vue/es/select';
import {unref} from 'vue';
export default defineComponent({
name: 'JSelectUser',
components: {
@ -55,10 +55,14 @@
value: [],
change: false
});
//
const loadingEcho = ref<boolean>(false)
// selectOptions,xxxBiz
provide('selectOptions', selectOptions);
// selectValues,xxxBiz
provide('selectValues', selectValues);
// loadingEcho,xxxBiz
provide('loadingEcho', loadingEcho);
const tag = ref(false);
const attrs = useAttrs();
@ -122,6 +126,7 @@
selectOptions,
getBindValue,
selectValues,
loadingEcho,
tag,
regModal,
setValue,

View File

@ -1,7 +1,7 @@
<!--用户选择组件-->
<template>
<div>
<JSelectBiz @change="handleChange" @handleOpen="handleOpen" v-bind="attrs"></JSelectBiz>
<JSelectBiz @change="handleChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<UserSelectByDepModal :rowKey="rowKey" @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></UserSelectByDepModal>
</div>
</template>
@ -49,10 +49,14 @@
value: [],
change: false
});
//
const loadingEcho = ref<boolean>(false)
// selectOptions,xxxBiz
provide('selectOptions', selectOptions);
// selectValues,xxxBiz
provide('selectValues', selectValues);
// loadingEcho,xxxBiz
provide('loadingEcho', loadingEcho);
const tag = ref(false);
const attrs = useAttrs();
@ -118,6 +122,7 @@
selectOptions,
getBindValue,
selectValues,
loadingEcho,
tag,
regModal,
setValue,

View File

@ -38,7 +38,7 @@
dict: propTypes.string.def('id'),
parentCode: propTypes.string.def(''),
pidField: propTypes.string.def('pid'),
pidValue: propTypes.string.def(''),
pidValue: propTypes.string.def('0'),
hasChildField: propTypes.string.def(''),
condition: propTypes.string.def(''),
multiple: propTypes.bool.def(false),

View File

@ -6,7 +6,6 @@
:action="uploadUrl"
:fileList="fileList"
:disabled="disabled"
:beforeUpload="onBeforeUpload"
:remove="onRemove"
v-bind="bindProps"
@change="onFileChange"
@ -87,7 +86,15 @@ const bindProps = computed(() => {
bind.listType = isImageMode.value ? 'picture-card' : 'text'
bind.class = [bind.class, { 'upload-disabled': props.disabled }]
bind.data = { 'biz': props.bizPath, ...(bind.data) }
bind.beforeUpload = onBeforeUpload
//update-begin-author:taoyan date:20220407 for: beforeUpload return false
if(!bind.beforeUpload){
bind.beforeUpload = onBeforeUpload
}
//update-end-author:taoyan date:20220407 for: beforeUpload return false
//
if (isImageMode.value && !bind.accept) {
bind.accept = 'image/*'
}
return bind
})
@ -150,8 +157,8 @@ function onAddActionsButton(event) {
createApp(UploadItemActions, {
element: uploadItem,
fileList: fileList,
mover: true,
download: true,
mover: props.mover,
download: props.download,
emitValue: emitValue,
}).mount(div)
actions[0].appendChild(div)

View File

@ -2,7 +2,13 @@
<div>
<a-row class="j-select-row" type="flex" :gutter="8">
<a-col class="left" :class="{'full': !showButton}">
<a-select ref="select" v-model:value="selectValues.value" :placeholder="placeholder" :mode="multiple" :open="false" :disabled="disabled" :options="options" @change="handleChange" style="width: 100%;" @click="openModal(false)"></a-select>
<!-- 显示加载效果 -->
<a-input v-if="loading" readOnly placeholder="加载中…">
<template #prefix>
<LoadingOutlined/>
</template>
</a-input>
<a-select v-else ref="select" v-model:value="selectValues.value" :placeholder="placeholder" :mode="multiple" :open="false" :disabled="disabled" :options="options" @change="handleChange" style="width: 100%;" @click="!disabled && openModal(false)"></a-select>
</a-col>
<a-col v-if="showButton" class="right">
<a-button type="primary" @click="openModal(true)" :disabled="disabled">选择</a-button>
@ -14,10 +20,11 @@
import {defineComponent, ref, inject, reactive} from 'vue';
import {propTypes} from "/@/utils/propTypes";
import {useAttrs} from "/@/hooks/core/useAttrs";
import {LoadingOutlined} from '@ant-design/icons-vue'
export default defineComponent({
name: 'JSelectBiz',
components: {},
components: {LoadingOutlined},
inheritAttrs: false,
props: {
showButton: propTypes.bool.def(true),
@ -30,7 +37,9 @@
multiple: {
type: String,
default: 'multiple',
}
},
//
loading: propTypes.bool.def(false),
},
emits: ['handleOpen','change'],
setup(props, {emit, refs}) {

View File

@ -2,14 +2,14 @@
<template>
<div>
<BasicModal v-bind="$attrs" @register="register" title="部门选择" width="500px" @ok="handleOk" destroyOnClose @visible-change="visibleChange">
<BasicTree ref="treeRef" :treeData="treeData" :load-data="sync==false?null:onLoadData" v-bind="getBindValue" @select="onSelect" @check="onCheck" :replaceFields="replaceFields" :checkedKeys="checkedKeys"/>
<BasicTree ref="treeRef" :treeData="treeData" :load-data="sync==false?null:onLoadData" v-bind="getBindValue" @select="onSelect" @check="onCheck" :replaceFields="replaceFields" :checkedKeys="checkedKeys" :checkStrictly="getCheckStrictly"/>
<!--树操作部分-->
<template #insertFooter>
<a-dropdown placement="topCenter">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="checkALL(true)"></a-menu-item>
<a-menu-item key="2" @click="checkALL(false)"></a-menu-item>
<a-menu-item v-if="multiple" key="1" @click="checkALL(true)"></a-menu-item>
<a-menu-item v-if="multiple" key="2" @click="checkALL(false)"></a-menu-item>
<a-menu-item key="3" @click="expandAll(true)"></a-menu-item>
<a-menu-item key="4" @click="expandAll(false)"></a-menu-item>
</a-menu>
@ -48,7 +48,7 @@
const treeRef = ref<Nullable<TreeActionType>>(null);
const getBindValue = Object.assign({}, unref(props), unref(attrs));
const queryUrl=props.sync?queryDepartTreeSync:queryTreeList;
const [{ visibleChange,checkedKeys, getSelectTreeData,onCheck,onLoadData,treeData,checkALL,expandAll,onSelect }] = useTreeBiz(treeRef,queryUrl, getBindValue);
const [{ visibleChange,checkedKeys, getCheckStrictly, getSelectTreeData,onCheck,onLoadData,treeData,checkALL,expandAll,onSelect }] = useTreeBiz(treeRef,queryUrl, getBindValue);
const searchInfo = ref(props.params);
const tree = ref([]);
//treeNodekeytreeData
@ -81,6 +81,7 @@
checkedKeys,
register,
getBindValue,
getCheckStrictly,
visibleChange,
onLoadData,
};

View File

@ -1,4 +1,4 @@
import {inject, reactive, ref, watch,unref} from "vue";
import {inject, reactive, ref, watch, unref, Ref} from 'vue'
import {useMessage} from "/@/hooks/web/useMessage";
export function useSelectBiz(getList,props) {
@ -6,6 +6,8 @@ export function useSelectBiz(getList,props) {
const selectOptions = inject('selectOptions', ref<Array<object>>([]));
//接收已选择的值
const selectValues = <object>inject('selectValues', reactive({}));
// 是否正在加载回显
const loadingEcho = inject<Ref<boolean>>('loadingEcho', ref(false))
//数据集
const dataSource = ref<Array<object>>([]);
//已选择的值
@ -14,19 +16,27 @@ export function useSelectBiz(getList,props) {
const selectRows = ref<Array<object>>([]);
//提示弹窗
const $message = useMessage()
// 是否是首次加载回显,只有首次加载,才会显示 loading
let isFirstLoadEcho = true
/**
* selectValues
*/
watch(selectValues, () => {
if (selectValues["change"] == false) {
let params={
code: selectValues["value"].join(",")
};
getDataSource(params, true).then();
//update-begin---author:wangshuai ---date:20220412 for[VUEN-672]发文草稿箱编辑时拟稿人显示用户名------------
let params={};
params[props.rowKey] = selectValues["value"].join(",")
//update-end---author:wangshuai ---date:20220412 for[VUEN-672]发文草稿箱编辑时拟稿人显示用户名--------------
loadingEcho.value = isFirstLoadEcho
isFirstLoadEcho = false
getDataSource(params, true).then().finally(()=>{
loadingEcho.value = isFirstLoadEcho
});
}
//设置列表默认选中
checkedKeys["value"] = selectValues["value"]
})
}, {immediate: true})
async function onSelectChange(selectedRowKeys: (string | number)[], selectRow) {
checkedKeys.value = selectedRowKeys;

View File

@ -1,4 +1,5 @@
import { inject, reactive, ref, unref, watch, nextTick } from 'vue';
import type {Ref} from 'vue'
import { inject, reactive, ref, computed, unref, watch, nextTick } from 'vue';
import { TreeActionType } from '/@/components/Tree';
import { listToTree } from '/@/utils/common/compUtils';
@ -7,6 +8,8 @@ export function useTreeBiz(treeRef, getList, props) {
const selectOptions = inject('selectOptions', ref<Array<object>>([]));
//接收已选择的值
const selectValues = <object>inject('selectValues', reactive({}));
// 是否正在加载回显
const loadingEcho = inject<Ref<boolean>>('loadingEcho', ref(false))
//数据集
const treeData = ref<Array<object>>([]);
//已选择的值
@ -15,15 +18,23 @@ export function useTreeBiz(treeRef, getList, props) {
const selectRows = ref<Array<object>>([]);
//是否是打开弹框模式
const openModal = ref(false);
// 是否开启父子关联,如果不可以多选,就始终取消父子关联
const getCheckStrictly = computed(() => props.multiple ? props.checkStrictly : true)
// 是否是首次加载回显,只有首次加载,才会显示 loading
let isFirstLoadEcho = true
/**
* selectValues
*/
watch(selectValues, () => {
if (openModal.value == false) {
onLoadData(null, selectValues['value'].join(',')).then();
watch(selectValues, ({value: values}: Recordable) => {
if (openModal.value == false && values.length > 0) {
loadingEcho.value = isFirstLoadEcho
isFirstLoadEcho = false
onLoadData(null, values.join(',')).finally(() => {
loadingEcho.value = false
})
}
});
}, {immediate: true});
/**
@ -72,6 +83,20 @@ export function useTreeBiz(treeRef, getList, props) {
*/
function onCheck(keys, info) {
if(props.checkable==true) {
// 如果不能多选,就只保留最后一个选中的
if (!props.multiple) {
if (info.checked) {
//update-begin-author:taoyan date:20220408 for: 单选模式下设定rowKey无法选中数据-
checkedKeys.value = [info.node.eventKey]
let temp = info.checkedNodes.find(n => n.key === info.node.eventKey)
selectRows.value = [temp.props.node]
//update-end-author:taoyan date:20220408 for: 单选模式下设定rowKey无法选中数据-
} else {
checkedKeys.value = []
selectRows.value = []
}
return
}
checkedKeys.value = props.checkStrictly?keys.checked:keys;
const { checkedNodes } = info;
let rows = <any[]>[];
@ -105,7 +130,9 @@ export function useTreeBiz(treeRef, getList, props) {
let startPid=''
if (treeNode) {
startPid=treeNode.eventKey;
params['pid'] = treeNode.eventKey;
//update-begin---author:wangshuai ---date:20220407 forrowkey不设置成idsync开启异步的时候点击上级下级不显示------------
params['pid'] = treeNode.value;
//update-end---author:wangshuai ---date:20220407 forrowkey不设置成idsync开启异步的时候点击上级下级不显示------------
}
if (ids) {
startPid='';
@ -215,6 +242,7 @@ export function useTreeBiz(treeRef, getList, props) {
checkedKeys,
selectRows,
treeData,
getCheckStrictly,
getSelectTreeData,
},
];

View File

@ -75,5 +75,7 @@ export const treeProps = {
//是否显示复选框
checkable: propTypes.bool.def(true),
//checkable 状态下节点选择完全受控(父子节点选中状态不再关联)
checkStrictly: propTypes.bool.def(false)
checkStrictly: propTypes.bool.def(false),
// 是否允许多选,默认 true
multiple: propTypes.bool.def(true),
};

View File

@ -140,4 +140,6 @@ export type ComponentType =
| 'JUpload'
| 'JSearchSelect'
| 'JAddInput'
| 'Time'
| 'JOnlineSelectCascade'
;

View File

@ -0,0 +1,108 @@
import REGION_DATA from 'china-area-data'
/**
* Area all
*/
interface PlainPca {
id:string,
text:string,
pid:string,
index:Number
}
/**
* -
*/
class Area {
all: PlainPca[];
/**
*
* @param express
*/
constructor(pcaa?) {
if(!pcaa){
pcaa = REGION_DATA;
}
let arr:PlainPca[] = []
const province = pcaa['86']
Object.keys(province).map(key=>{
arr.push({id:key, text:province[key], pid:'86', index:1});
const city = pcaa[key];
Object.keys(city).map(key2=>{
arr.push({id:key2, text:city[key2], pid:key, index:2});
const qu = pcaa[key2];
if(qu){
Object.keys(qu).map(key3=>{
arr.push({id:key3, text:qu[key3], pid:key2, index:3});
})
}
})
})
this.all = arr;
}
get pca(){
return this.all;
}
getCode(text){
if(!text || text.length==0){
return ''
}
for(let item of this.all){
if(item.text === text){
return item.id;
}
}
}
getText(code){
if(!code || code.length==0){
return ''
}
let arr = []
this.getAreaBycode(code, arr, 3);
return arr.join('/')
}
getRealCode(code){
let arr = []
this.getPcode(code, arr, 3)
return arr;
}
getPcode(id, arr, index){
for(let item of this.all){
if(item.id === id && item.index == index){
arr.unshift(id)
if(item.pid != '86'){
this.getPcode(item.pid, arr, --index)
}
}
}
}
getAreaBycode(code, arr, index){
for(let item of this.all){
if(item.id === code && item.index == index){
arr.unshift(item.text);
if(item.pid != '86'){
this.getAreaBycode(item.pid, arr, --index)
}
}
}
}
}
const jeecgAreaData = new Area();
// 根据code找文本
const getAreaTextByCode = function(code) {
return jeecgAreaData.getText(code)
}
export {
getAreaTextByCode
}

View File

@ -190,4 +190,4 @@ function getPcode(id, arr, index){
}
}
//--end--@updateBy:liusq----date:20210922---for:省市区三级联动需求方法-----
export {provinceAndCityData, regionData, provinceAndCityDataPlus, regionDataPlus, CodeToText, TextToCode,getDataByCode,provinceOptions,getRealCode}
export {provinceAndCityData, regionData, provinceAndCityDataPlus, regionDataPlus,getDataByCode,provinceOptions,getRealCode}

View File

@ -29,7 +29,13 @@ export function handleRangeTimeValue(props, values) {
if (!field || !startTimeKey || !endTimeKey || !values[field]) {
continue;
}
const [startTime, endTime]: string[] = values[field];
// 【issues/I53G9Y】 日期区间组件有可能是字符串
let timeValue = values[field]
if (!Array.isArray(timeValue)) {
timeValue = timeValue.split(',')
}
const [startTime, endTime]: string[] = timeValue;
values[startTimeKey] = dateUtil(startTime).format(format);
values[endTimeKey] = dateUtil(endTime).format(format);
Reflect.deleteProperty(values, field);

View File

@ -75,7 +75,7 @@
</template>
</a-input>
</template>
<script lang="ts" setup>
<script lang="ts" setup name="icon-picker">
import { ref, watchEffect, watch, unref } from 'vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { ScrollContainer } from '/@/components/Container';

View File

@ -33,6 +33,8 @@
import { openWindow } from '/@/utils';
import { useOpenKeys } from './useOpenKeys';
import {URL_HASH_TAB} from '/@/utils'
export default defineComponent({
name: 'SimpleMenu',
components: {
@ -129,7 +131,11 @@
async function handleSelect(key: string) {
if (isUrl(key)) {
openWindow(key);
// update-begin--author:sunjianlei---date:20220408---for: VUEN-656#
let url = key.replace(URL_HASH_TAB, '#')
openWindow(url)
// openWindow(key);
// update-begin--author:sunjianlei---date:20220408---for: VUEN-656#
return;
}
const { beforeClickFn } = props;

View File

@ -142,7 +142,7 @@
getPaginationInfo,
setLoading,
setPagination,
getFieldsValue: formActions.getFieldsValue,
validate: formActions.validate,
clearSelectedRowKeys,
},
emit

View File

@ -21,7 +21,9 @@ interface ActionType {
getPaginationInfo: ComputedRef<boolean | PaginationProps>;
setPagination: (info: Partial<PaginationProps>) => void;
setLoading: (loading: boolean) => void;
getFieldsValue: () => Recordable;
// update-begin--author:sunjianlei---date:220220419---for由于 getFieldsValue 返回的不是逗号分割的数据,所以改用 validate
validate: () => Recordable;
// update-end--author:sunjianlei---date:220220419---for由于 getFieldsValue 返回的不是逗号分割的数据,所以改用 validate
clearSelectedRowKeys: () => void;
tableData: Ref<Recordable[]>;
}
@ -36,7 +38,7 @@ export function useDataSource(
getPaginationInfo,
setPagination,
setLoading,
getFieldsValue,
validate,
clearSelectedRowKeys,
tableData,
}: ActionType,
@ -264,7 +266,8 @@ export function useDataSource(
let params: Recordable = {
...pageParams,
...(useSearchForm ? getFieldsValue() : {}),
// 由于 getFieldsValue 返回的不是逗号分割的数据,所以改用 validate
...(useSearchForm ? (await validate()) : {}),
...searchInfo,
...defSort,
...(opt?.searchInfo ?? {}),

View File

@ -205,9 +205,14 @@
const { options } = props;
const getdDisabled = options && Reflect.get(options, 'readonly');
const editor = unref(editorRef);
// update-begin-author:taoyan date:20220407 for: disabled
if (editor) {
editor.setMode(getdDisabled ? 'readonly' : 'design');
editor.setMode(getdDisabled||(attrs.disabled === true) ? 'readonly' : 'design');
}
if(attrs.disabled === true){
return true;
}
// update-end-author:taoyan date:20220407 for: disabled
return getdDisabled ?? false;
});

View File

@ -2,7 +2,7 @@
<div ref="chartRef" :style="{ height, width }"></div>
</template>
<script lang="ts">
import { defineComponent, PropType, ref, Ref,watchEffect,reactive } from 'vue';
import { defineComponent, PropType, ref, Ref,watchEffect,reactive,watch } from 'vue';
import { useECharts } from '/@/hooks/web/useECharts';
export default defineComponent({
@ -12,6 +12,10 @@
type: Array,
default: () => ([]),
},
size: {
type: Object,
default: ()=>{}
},
option:{
type: Object,
default: () => ({}),
@ -28,7 +32,7 @@
emits: ['click'],
setup(props, {emit}) {
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>);
const { setOptions, getInstance,resize } = useECharts(chartRef as Ref<HTMLDivElement>);
const option = reactive({
tooltip: {
formatter: '{b} ({c})',
@ -52,13 +56,25 @@
watchEffect(() => {
props.chartData && initCharts();
});
/**
* 监听拖拽大小变化
*/
watch(
() => props.size,
() => {
resize();
},
{
immediate: true,
}
);
function initCharts(){
if(props.option){
Object.assign(option,props.option);
}
option.series[0].data = props.chartData;
setOptions(option);
resize();
getInstance()?.off('click', onClick)
getInstance()?.on('click', onClick)
}

View File

@ -2,7 +2,7 @@
<div ref="chartRef" :style="{ height, width }"></div>
</template>
<script lang="ts">
import {defineComponent, PropType, ref, Ref, reactive, watchEffect} from 'vue';
import {defineComponent, PropType, ref, Ref, reactive, watchEffect,watch} from 'vue';
import {useECharts} from '/@/hooks/web/useECharts';
export default defineComponent({
@ -13,6 +13,10 @@
default: () => ([]),
required: true
},
size: {
type: Object,
default: ()=>{}
},
option: {
type: Object,
default: () => ({}),
@ -32,7 +36,7 @@
},
setup(props) {
const chartRef = ref<HTMLDivElement | null>(null);
const {setOptions, echarts} = useECharts(chartRef as Ref<HTMLDivElement>);
const {setOptions, echarts,resize} = useECharts(chartRef as Ref<HTMLDivElement>);
const option = reactive({
tooltip: {
trigger: 'axis',
@ -63,7 +67,19 @@
watchEffect(() => {
props.chartData && initCharts();
});
/**
* 监听拖拽大小变化
*/
watch(
() => props.size,
() => {
console.log("props.size",props.size)
resize();
},
{
immediate: true,
}
);
function initCharts() {
if (props.option) {
Object.assign(option, props.option);

View File

@ -58,10 +58,12 @@ export default defineComponent({
// JVxeComponent.Enhanced
enhanced: {
aopEvents: {
editActived({ $event }) {
editActived({$event, row, column}) {
dispatchEvent({
$event,
row, column,
props: this.props,
instance: this,
className: '.ant-calendar-picker',
isClick: false,
handler: (el) => el.children[0].click(),

View File

@ -175,10 +175,12 @@ export default defineComponent({
// JVxeComponent.Enhanced
enhanced: {
aopEvents: {
editActived({ $event }) {
editActived({$event, row, column}) {
dispatchEvent({
$event,
row, column,
props: this.props,
instance: this,
className: '.ant-select .ant-select-selection-search-input',
isClick: false,
handler: (el) => el.focus(),

View File

@ -31,12 +31,14 @@ export default defineComponent({
autofocus: '.ant-input',
},
aopEvents: {
editActived({$event, column}) {
editActived({$event, row, column}) {
//
if ((column.params.defaultOpen ?? false)) {
dispatchEvent({
$event,
row, column,
props: this.props,
instance: this,
className: '.ant-input-suffix .app-iconify',
isClick: true,
})

View File

@ -57,10 +57,12 @@ export default defineComponent({
// JVxeComponent.Enhanced
enhanced: {
aopEvents: {
editActived({ $event }) {
editActived({ $event, row, column }) {
dispatchEvent({
$event,
row, column,
props: this.props,
instance: this,
className: '.ant-time-picker-input',
isClick: true,
})

View File

@ -41,6 +41,23 @@ export function useData(props: JVxeTableProps): JVxeDataProps {
// },
radioConfig: { highlight: true },
checkboxConfig: { highlight: true },
mouseConfig: {selected: false},
keyboardConfig: {
// 删除键功能
isDel: false,
// Esc键关闭编辑功能
isEsc: true,
// Tab 键功能
isTab: true,
// 任意键进入编辑(功能键除外)
isEdit: true,
// 方向键功能
isArrow: true,
// 回车键功能
isEnter: true,
// 如果功能被支持,用于 column.type=checkbox|radio开启空格键切换复选框或单选框状态功能
isChecked: true,
},
}),
selectedRows: ref<any[]>([]),
selectedRowIds: ref<string[]>([]),

View File

@ -2,10 +2,13 @@ import { unref, computed } from 'vue'
import { merge } from 'lodash-es'
import { isArray } from '/@/utils/is'
import { useAttrs } from '/@/hooks/core/useAttrs'
import {useKeyboardEdit} from '../hooks/useKeyboardEdit'
import { JVxeDataProps, JVxeTableMethods, JVxeTableProps } from '../types'
export function useFinallyProps(props: JVxeTableProps, data: JVxeDataProps, methods: JVxeTableMethods) {
const attrs = useAttrs()
// vxe 键盘操作配置
const {keyboardEditConfig} = useKeyboardEdit(props)
// vxe 最终 editRules
const vxeEditRules = computed(() => merge({}, props.editRules, data.innerEditRules))
// vxe 最终 events
@ -63,7 +66,7 @@ export function useFinallyProps(props: JVxeTableProps, data: JVxeDataProps, meth
checkboxConfig: {
checkMethod: methods.handleCheckMethod,
},
}, unref(vxeEvents))
}, unref(vxeEvents), unref(keyboardEditConfig))
})
return {
vxeProps,

View File

@ -0,0 +1,37 @@
/*
* JVxeTable
*/
import type {VxeTablePropTypes} from 'vxe-table'
import type {JVxeTableProps} from '../types'
import {computed} from 'vue'
/**
* JVxeTable
*
* @param props
*/
export function useKeyboardEdit(props: JVxeTableProps) {
// 是否开启了键盘操作
const enabledKeyboard = computed(() => props.keyboardEdit ?? false)
// 重写 keyboardConfig
const keyboardConfig: VxeTablePropTypes.KeyboardConfig = {
editMethod({row, column, $table}) {
// 重写默认的覆盖式,改为追加式
$table.setActiveCell(row, column)
return true
},
}
// 键盘操作配置
const keyboardEditConfig = computed(() => {
return {
mouseConfig: {
selected: enabledKeyboard.value,
},
keyboardConfig,
}
})
return {
keyboardEditConfig,
}
}

View File

@ -4,6 +4,7 @@ import { useGlobSetting } from '/@/hooks/setting'
import { useUserStore } from '/@/store/modules/user'
import { JVxeDataProps, JVxeTableMethods, JVxeTableProps } from '../types'
import { isArray } from '/@/utils/is'
import { getToken } from '/@/utils/auth';
// vxe socket
const vs = {
@ -55,7 +56,10 @@ const vs = {
const domainURL = useGlobSetting().uploadUrl!
const domain = domainURL.replace('https://', 'wss://').replace('http://', 'ws://')
const url = `${domain}/vxeSocket/${userId}/${this.pageId}`
this.ws = new WebSocket(url)
//update-begin-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
let token = (getToken() || '') as string
this.ws = new WebSocket(url, [token])
//update-end-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
this.ws.onopen = this.on.open.bind(this)
this.ws.onerror = this.on.error.bind(this)
this.ws.onmessage = this.on.message.bind(this)

View File

@ -5,7 +5,7 @@ import type { VxeGridInstance, VxeTablePropTypes } from 'vxe-table'
import { JVxeTypes } from './JVxeTypes'
import { vxeProps } from '../vxe.data'
import { useMethods } from '../hooks/useMethods'
import { getJVxeAuths } from '/@/utils/auth/authFilter'
import { getJVxeAuths } from '../utils/authUtils'
export type JVxeTableProps = Partial<ExtractPropTypes<ReturnType<typeof vxeProps>>>;
export type JVxeTableMethods = ReturnType<typeof useMethods>['methods']

View File

@ -1,4 +1,5 @@
import { unref, isRef, Ref } from 'vue'
import type {Ref, ComponentInternalInstance} from 'vue'
import {unref, isRef} from 'vue'
import { useDefaultEnhanced } from '../hooks/useJVxeComponent'
import { isFunction, isObject, isString } from '/@/utils/is'
import { JVxeTypes } from '../types'
@ -53,12 +54,27 @@ export function replaceProps(col, value) {
return value
}
type dispatchEventOptions = { props, $event, className: string, handler?: Fn, isClick?: boolean }
type dispatchEventOptions = {
// JVxeTable 的 props
props,
// 触发的 event 事件对象
$event,
// 行、列
row?, column?,
// JVxeTable的vue3实例
instance?: ComponentInternalInstance,
// 要寻找的className
className: string,
// 重写找到dom后的处理方法
handler?: Fn,
// 是否直接执行click方法而不是模拟click事件
isClick?: boolean,
}
/** 模拟触发事件 */
export function dispatchEvent(options: dispatchEventOptions) {
const { props, $event, className, handler, isClick } = options
if (!$event || !$event.path) {
const {props, $event, row, column, instance, className, handler, isClick} = options
if ((!$event || !$event.path) && !instance) {
return
}
// alwaysEdit 下不模拟触发事件,否者会导致触发两次
@ -66,9 +82,18 @@ export function dispatchEvent(options: dispatchEventOptions) {
return
}
let getCell = () => {
for (const el of $event.path) {
if (el.classList.contains('vxe-body--column')) {
return el as HTMLElement
let paths: HTMLElement[] = [...($event?.path ?? [])]
// 通过 instance 获取 cell dom对象
if (row && column) {
let selector = `table.vxe-table--body tbody tr[rowid='${row.id}'] td[colid='${column.id}']`
let cellDom = instance!.vnode?.el?.querySelector(selector)
if (cellDom) {
paths.unshift(cellDom)
}
}
for (const el of paths) {
if (el.classList?.contains('vxe-body--column')) {
return el
}
}
return null

View File

@ -89,6 +89,8 @@ export const vxeProps = () => ({
socketKey: propTypes.string.def('vxe-default'),
// 新增行时切换行的激活状态
addSetActive: propTypes.bool.def(true),
// 是否开启键盘编辑
keyboardEdit: propTypes.bool.def(false),
})
export const vxeEmits = ['save', 'added', 'removed', 'inserted', 'dragged', 'selectRowChange', 'pageChange', 'valueChange']

View File

@ -42,7 +42,11 @@ import {
Spin,
Space,
Layout,
Collapse
Collapse,
Slider,
InputNumber,
Carousel,
Popconfirm,
} from 'ant-design-vue';
const compList = [AntButton.Group, Icon, AIcon,UploadButton];
@ -91,4 +95,8 @@ export function registerGlobComp(app: App) {
.use(Space)
.use(Layout)
.use(Collapse)
.use(Slider)
.use(InputNumber)
.use(Carousel)
.use(Popconfirm)
}

View File

@ -43,4 +43,6 @@ export enum ConfigEnum {
Sign = 'X-Sign',
// 租户id
TENANT_ID = 'tenant-id',
// 版本
VERSION = 'X-Version',
}

View File

@ -8,6 +8,14 @@ export enum JInputTypeEnum {
JINPUT_QUERY_NE = 'ne',
//大于等于
JINPUT_QUERY_GE = 'ge',
//小等于
//小等于
JINPUT_QUERY_LE = 'le',
}
/**
*
*/
export enum JDragConfigEnum {
//baseURL
DRAG_BASE_URL = 'drag-base-url',
}

View File

@ -0,0 +1,85 @@
/**
*
*
* @time 2022-4-8
* @author sunjianlei
*/
import {ref} from 'vue'
import {useDebounceFn, tryOnUnmounted} from '@vueuse/core'
import {useEventListener} from '/@/hooks/event/useEventListener'
// key = js运算符+数字
const defWidthConfig: configType = {
'<=565': '100%',
'<=1366': '800px',
'<=1600': '600px',
'<=1920': '600px',
'>1920': '500px',
}
type configType = Record<string, string | number>
/**
*
*
* @param widthConfig defWidthConfig
* @param assign
* @param debounce
*/
export function useAdaptiveWidth(widthConfig = defWidthConfig, assign = true, debounce = 50) {
const widthConfigAssign = assign ? Object.assign({}, defWidthConfig, widthConfig) : widthConfig
const configKeys = Object.keys(widthConfigAssign)
const adaptiveWidth = ref<string | number>()
/**
*
* @param innerWidth
*/
function calcWidth(innerWidth) {
let width
for (const key of configKeys) {
try {
// 通过js运算
let flag = new Function(`return ${innerWidth} ${key}`)()
if (flag) {
width = widthConfigAssign[key]
break
}
} catch (e) {
console.error(e)
}
}
if (width) {
adaptiveWidth.value = width
} else {
console.warn('没有找到匹配的自适应宽度')
}
}
// 初始计算
calcWidth(window.innerWidth)
// 监听 resize 事件
const {removeEvent} = useEventListener({
el: window,
name: 'resize',
listener: useDebounceFn(() => calcWidth(window.innerWidth), debounce),
})
// 卸载组件时取消监听事件
tryOnUnmounted(() => removeEvent())
return {adaptiveWidth}
}
/**
*
*/
export function useDrawerAdaptiveWidth() {
return useAdaptiveWidth({
'<=620': '100%',
'<=1600': 600,
'<=1920': 650,
'>1920': 700,
}, false)
}

View File

@ -8,7 +8,7 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
VITE_GLOB_API_URL,
VITE_GLOB_APP_SHORT_NAME,
VITE_GLOB_API_URL_PREFIX,
VITE_GLOBE_APP_CAS_BASE_URL,
VITE_GLOB_APP_CAS_BASE_URL,
VITE_GLOB_APP_OPEN_SSO,
VITE_GLOB_APP_OPEN_QIANKUN,
VITE_GLOB_DOMAIN_URL,
@ -29,7 +29,7 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
shortName: VITE_GLOB_APP_SHORT_NAME,
openSso:VITE_GLOB_APP_OPEN_SSO,
openQianKun:VITE_GLOB_APP_OPEN_QIANKUN,
casBaseUrl:VITE_GLOBE_APP_CAS_BASE_URL,
casBaseUrl:VITE_GLOB_APP_CAS_BASE_URL,
urlPrefix: VITE_GLOB_API_URL_PREFIX,
uploadUrl: VITE_GLOB_DOMAIN_URL,
viewUrl: VITE_GLOB_ONLINE_VIEW_URL,

View File

@ -23,6 +23,8 @@ interface ListPageOptions {
url: string,
// 导出文件名
name?: string | (() => string),
//导出参数
params?: object,
}
// 导入配置
importConfig?: {
@ -59,14 +61,20 @@ export function useListPage(options: ListPageOptions) {
// 导出 excel
async function onExportXls() {
let { url, name } = options?.exportConfig ?? {}
//update-begin---author:wangshuai ---date:20220411 for导出新增自定义参数------------
let { url, name,params } = options?.exportConfig ?? {}
if (url) {
let title = typeof name === 'function' ? name() : name
const params = await getForm().validate()
if(selectedRowKeys.value && selectedRowKeys.value.length>0){
params['selections'] = selectedRowKeys.value.join(",")
let paramsForm = await getForm().validate()
//如果参数不为空,则整合到一起
if(params){
paramsForm = Object.assign({},paramsForm,params);
}
return handleExportXls(title as string, url,filterObj(params))
if(selectedRowKeys.value && selectedRowKeys.value.length>0){
paramsForm['selections'] = selectedRowKeys.value.join(",")
}
return handleExportXls(title as string, url,filterObj(paramsForm))
//update-end---author:wangshuai ---date:20220411 for导出新增自定义参数--------------
} else {
$message.createMessage.warn('没有传递 exportConfig.url 参数')
return Promise.reject()

View File

@ -5,13 +5,22 @@ import {useGlobSetting} from '/@/hooks/setting';
const {createMessage, createWarningModal} = useMessage();
const glob = useGlobSetting();
/**
* xlsxmime-type
*/
export const XLSX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
/**
* xlsx
*/
export const XLSX_FILE_SUFFIX = ".xlsx";
export function useMethods() {
/**
* xls
* @param name
* @param url
*/
async function exportXls(name,url,params) {
async function exportXls(name,url,params, isXlsx=false) {
const data = await defHttp.get({url: url, params:params,responseType: 'blob'}, {isTransformResponse: false})
if (!data) {
createMessage.warning("文件下载失败")
@ -20,14 +29,20 @@ export function useMethods() {
if(!name || typeof name != "string"){
name = "导出文件"
}
let blobOptions = { type: 'application/vnd.ms-excel' }
let fileSuffix = '.xls'
if(isXlsx===true){
blobOptions['type'] = XLSX_MIME_TYPE
fileSuffix = XLSX_FILE_SUFFIX
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(new Blob([data], {type: 'application/vnd.ms-excel'}), name + '.xls')
window.navigator.msSaveBlob(new Blob([data], blobOptions), name + fileSuffix)
} else {
let url = window.URL.createObjectURL(new Blob([data], {type: 'application/vnd.ms-excel'}))
let url = window.URL.createObjectURL(new Blob([data], blobOptions))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', name + '.xls')
link.setAttribute('download', name + fileSuffix)
document.body.appendChild(link)
link.click()
document.body.removeChild(link); //下载完成移除元素
@ -70,7 +85,8 @@ export function useMethods() {
}
return {
handleExportXls: (name: string, url: string,params:object) => exportXls(name, url,params),
handleExportXls: (name: string, url: string,params?:object) => exportXls(name, url,params),
handleImportXls: (data, url, success) => importXls(data, url, success),
handleExportXlsx: (name: string, url: string, params?:object) => exportXls(name, url,params, true),
};
}

View File

@ -2,6 +2,7 @@
import { computed, reactive, ref, unref } from 'vue'
import { useWebSocket as $useWebSocket, WebSocketResult } from '@vueuse/core'
import { getToken } from '/@/utils/auth';
const state = reactive({
server: '',
@ -20,12 +21,16 @@ const listeners = new Map()
export function connectWebSocket(url: string) {
if (!unref(getIsOpen)) {
state.server = url
//update-begin-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
let token = (getToken() || '') as string
result.value = $useWebSocket(state.server, {
// 自动重连
autoReconnect: true,
// 心跳检测
heartbeat: false,
protocols: [token],
})
//update-end-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
result.value.open()
const ws = unref(result.value.ws)
if (ws) {

View File

@ -1,7 +1,7 @@
<template>
<Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`">
<span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex">
<img :class="`${prefixCls}__header`" :src="getUserInfo.avatar" />
<img :class="`${prefixCls}__header`" :src="getAvatarUrl" />
<span :class="`${prefixCls}__info hidden md:block`">
<span :class="`${prefixCls}__name `" class="truncate">
{{ getUserInfo.realname }}
@ -80,6 +80,8 @@
import {refreshCache,queryAllDictItems} from '/@/views/system/dict/dict.api';
import { DB_DICT_DATA_KEY } from '/src/enums/cacheEnum';
import { removeAuthCache,setAuthCache } from '/src/utils/auth';
import {getFileAccessHttpUrl} from '/@/utils/common/compUtils'
type MenuEvent = 'logout' | 'doc' | 'lock'|'cache' | 'depart';
const {createMessage} = useMessage();
export default defineComponent({
@ -108,6 +110,8 @@
return { realname, avatar: avatar || headerImg, desc };
});
const getAvatarUrl = computed(() => getFileAccessHttpUrl(getUserInfo.value?.avatar))
const [register, { openModal }] = useModal();
/**
* 多部门弹窗逻辑
@ -179,6 +183,7 @@
prefixCls,
t,
getUserInfo,
getAvatarUrl,
handleMenuClick,
getShowDoc,
register,

View File

@ -6,6 +6,8 @@ import { cloneDeep, omit } from 'lodash-es';
import { warn } from '/@/utils/log';
import { createRouter, createWebHashHistory } from 'vue-router';
import { getToken } from '/@/utils/auth';
import {URL_HASH_TAB} from '/@/utils'
export type LayoutMapKey = 'LAYOUT';
const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
const LayoutContent = () => import('/@/layouts/default/content/index.vue');
@ -49,6 +51,9 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
if (item.meta?.internalOrExternal) {
// @ts-ignore 外部打开
item.path = item.component
// update-begin--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开原因是带了#号,需要替换一下
item.path = item.path.replace('#', URL_HASH_TAB)
// update-end--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开原因是带了#号,需要替换一下
} else {
// @ts-ignore 内部打开
item.meta.frameSrc = item.component

View File

@ -0,0 +1,30 @@
/*
*
*
* Online使
* 使 export
*
* export const name = '张三'; // const 是常量
* export let age = 17; // 看情况 export const 还是 let ,两者都可正常使用
* export function content(arg) { // export 方法可传参数使用时要加括号值一定要return回去可以返回Promise
* return 'content' + arg;
* }
* export const address = (arg) => content(arg) + ' | 北京市'; // export 箭头函数也可以
*
*/
/** 字段默认值官方示例:获取地址 */
export function demoFieldDefVal_getAddress(arg) {
if (!arg) {
arg = '朝阳区'
}
return `北京市 ${arg}`
}
/** 自定义JS函数示例 */
export function sayHi(name) {
if (!name) {
name = '张三'
}
return `您好,我叫: ${name}`
}

View File

@ -103,23 +103,31 @@ export default class signMd5Utils {
return paramStr;
};
static getDateTimeToString() {
const date_ = new Date()
const year = date_.getFullYear()
let month = date_.getMonth() + 1
let day = date_.getDate()
if (month < 10) month = '0' + month
if (day < 10) day = '0' + day
let hours = date_.getHours()
let mins = date_.getMinutes()
let secs = date_.getSeconds()
const msecs = date_.getMilliseconds()
if (hours < 10) hours = '0' + hours
if (mins < 10) mins = '0' + mins
if (secs < 10) secs = '0' + secs
if (msecs < 10) secs = '0' + msecs
return year + '' + month + '' + day + '' + hours + '' + mins + '' + secs
/**
* 接口签名用 生成header中的时间戳
* @returns {number}
*/
static getTimestamp(){
return new Date().getTime()
}
// static getDateTimeToString() {
// const date_ = new Date()
// const year = date_.getFullYear()
// let month = date_.getMonth() + 1
// let day = date_.getDate()
// if (month < 10) month = '0' + month
// if (day < 10) day = '0' + day
// let hours = date_.getHours()
// let mins = date_.getMinutes()
// let secs = date_.getSeconds()
// const msecs = date_.getMilliseconds()
// if (hours < 10) hours = '0' + hours
// if (mins < 10) mins = '0' + mins
// if (secs < 10) secs = '0' + secs
// if (msecs < 10) secs = '0' + msecs
// return year + '' + month + '' + day + '' + hours + '' + mins + '' + secs
// }
// true:数值型的false非数值型
static myIsNaN(value) {
return typeof value === 'number' && !isNaN(value);

View File

@ -30,7 +30,7 @@ export function getAppEnvConfig() {
VITE_GLOB_API_URL_PREFIX,
VITE_GLOB_APP_OPEN_SSO,
VITE_GLOB_APP_OPEN_QIANKUN,
VITE_GLOBE_APP_CAS_BASE_URL,
VITE_GLOB_APP_CAS_BASE_URL,
VITE_GLOB_DOMAIN_URL,
VITE_GLOB_ONLINE_VIEW_URL,
} = ENV;
@ -49,7 +49,7 @@ export function getAppEnvConfig() {
VITE_GLOB_API_URL_PREFIX,
VITE_GLOB_APP_OPEN_SSO,
VITE_GLOB_APP_OPEN_QIANKUN,
VITE_GLOBE_APP_CAS_BASE_URL,
VITE_GLOB_APP_CAS_BASE_URL,
VITE_GLOB_DOMAIN_URL,
VITE_GLOB_ONLINE_VIEW_URL,
};

View File

@ -138,7 +138,7 @@ const transform: AxiosTransform = {
/**
* @description:
*/
requestInterceptors: (config, options) => {
requestInterceptors: (config:Recordable, options) => {
// 请求之前处理config
const token = getToken();
let tenantid = getTenantId();
@ -147,7 +147,11 @@ const transform: AxiosTransform = {
config.headers.Authorization = options.authenticationScheme ? `${options.authenticationScheme} ${token}` : token;
config.headers[ConfigEnum.TOKEN] = token
//--update-begin--author:liusq---date:20210831---for:将签名和时间戳,添加在请求接口 Header
config.headers[ConfigEnum.TIMESTAMP] = signMd5Utils.getDateTimeToString();
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
config.headers[ConfigEnum.TIMESTAMP] = signMd5Utils.getTimestamp();
// update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
config.headers[ConfigEnum.Sign] = signMd5Utils.getSign(config.url, config.params);
//--update-end--author:liusq---date:20210831---for:将签名和时间戳,添加在请求接口 Header
//--update-begin--author:liusq---date:20211105---for: for:将多租户id添加在请求接口 Header
@ -155,6 +159,9 @@ const transform: AxiosTransform = {
tenantid = 0;
}
config.headers[ConfigEnum.TENANT_ID ] = tenantid
//--update-begin--author:liusq---date:20220325---for: 增加vue3标记
config.headers[ConfigEnum.VERSION] = "v3"
//--update-end--author:liusq---date:20220325---for:增加vue3标记
//--update-end--author:liusq---date:20211105---for:将多租户id添加在请求接口 Header
}
@ -177,7 +184,9 @@ const transform: AxiosTransform = {
errorLogStore.addAjaxErrorInfo(error);
const { response, code, message, config } = error || {};
const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
const msg: string = response?.data?.error?.message ?? '';
//scott 20211022 token失效提示信息
//const msg: string = response?.data?.error?.message ?? '';
const msg: string = response?.data?.message ?? '';
const err: string = error?.toString?.() ?? '';
let errMessage = '';

View File

@ -4,6 +4,10 @@ import type { App, Plugin } from 'vue';
import { unref } from 'vue';
import { isObject } from '/@/utils/is';
// update-begin--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开原因是带了#号,需要替换一下
export const URL_HASH_TAB = `__AGWE4H__HASH__TAG__PWHRG__`
// update-end--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开原因是带了#号,需要替换一下
export const noop = () => {};
/**
@ -71,7 +75,7 @@ export function getDynamicProps<T, U>(props: T): Partial<U> {
* @updateBy:zyf
*/
export function getValueType(props,field){
let formSchema = unref(props.schemas);
let formSchema = unref(unref(props)?.schemas)
let valueType = "string";
if (formSchema) {
let schema = formSchema.filter((item) => item.field === field)[0];
@ -151,3 +155,19 @@ export function sleep(ms: number, fn?: Fn) {
resolve()
}, ms))
}
/**
*
* @param text
* @param checker
* @param replacer
* @returns {String}
*/
export function replaceAll(text, checker, replacer) {
let lastText = text
text = text.replace(checker, replacer)
if (lastText !== text) {
return replaceAll(text, checker, replacer)
}
return text
}

View File

@ -26,7 +26,9 @@ import {
GraphicComponent,
} from 'echarts/components';
import { SVGRenderer } from 'echarts/renderers';
// TODO 如果想换成SVG渲染就导出SVGRenderer
// 并且放到 echarts.use 里,注释掉 CanvasRenderer
import { /*SVGRenderer*/ CanvasRenderer } from 'echarts/renderers';
echarts.use([
LegendComponent,
@ -41,7 +43,8 @@ echarts.use([
PieChart,
MapChart,
RadarChart,
SVGRenderer,
// TODO 因为要兼容Online图表自适应打印所以改成 CanvasRenderer可能会模糊
CanvasRenderer,
PictorialBarChart,
RadarComponent,
ToolboxComponent,

View File

@ -0,0 +1,143 @@
<template>
<div>
<b>键盘操作快捷键</b>
<div style="border: 1px solid #cccccc; padding: 8px; width: 740px;">
<pre>
F2 | 如果存在激活单元格为编辑状态
Esc | 如果存在取消单元格编辑状态
| 如果存在则移动到上面的单元格
| 如果存在则移动到下面的单元格
| 如果存在则移动到左边的单元格
| 如果存在则移动到右边的单元格
Tab | 如果存在则移动到右边单元格如果移动到最后一列则从下一行开始移到以此循环
Shift + Tab | 如果存在则移动到左边单元格如果移动到第一列则从上一行开始移到以此循环
Enter | 如果存在取消单元格编辑并移动到下面的单元格
Shift + Enter | 如果存在取消单元格编辑并移动到上面的单元格</pre>
</div>
<JVxeTable
ref="tableRef"
stripe
toolbar
rowNumber
rowSelection
keyboardEdit
:columns="columns"
:dataSource="dataSource"
>
</JVxeTable>
</div>
</template>
<script lang="ts">
import {ref, onMounted, nextTick, defineComponent} from 'vue'
import {Popconfirm} from 'ant-design-vue'
import {JVxeTypes, JVxeColumn, JVxeTableInstance} from '/@/components/jeecg/JVxeTable/types'
export default defineComponent({
name: 'JVxeDemo5',
components: {[Popconfirm.name]: Popconfirm},
setup() {
const tableRef = ref<JVxeTableInstance>()
const columns = ref<JVxeColumn[]>([
{
title: '单行文本',
key: 'input',
type: JVxeTypes.input,
width: 220,
defaultValue: '',
placeholder: '请输入${title}',
},
{
title: '多行文本',
key: 'textarea',
type: JVxeTypes.textarea,
width: 240,
},
{
title: '数字',
key: 'number',
type: JVxeTypes.inputNumber,
width: 120,
defaultValue: 32,
},
{
title: '日期时间',
key: 'datetime',
type: JVxeTypes.datetime,
width: 240,
defaultValue: '2019-4-30 14:52:22',
placeholder: '请选择',
},
{
title: '时间',
key: 'time',
type: JVxeTypes.time,
width: 220,
defaultValue: '14:52:22',
placeholder: '请选择',
},
{
title: '下拉框',
key: 'select',
type: JVxeTypes.select,
width: 220,
//
options: [
{title: 'String', value: 'string'},
{title: 'Integer', value: 'int'},
{title: 'Double', value: 'double'},
{title: 'Boolean', value: 'boolean'},
],
// allowInput: true,
allowSearch: true,
placeholder: '请选择',
},
{
title: '复选框',
key: 'checkbox',
type: JVxeTypes.checkbox,
// width: 100,
customValue: ['Y', 'N'], // true ,false
defaultChecked: false,
},
])
const dataSource = ref([])
function handleView(props) {
//
// props.value
// props.row
// props.rowId ID
// props.rowIndex
// props.column
// props.columnIndex
// props.$table vxe-tablevxe-table
// props.scrolling
// props.reloadEffect
// props.triggerChange changeslot
console.log('props: ', props)
}
function handleDelete({row}) {
// 使
tableRef.value?.removeRows(row)
}
onMounted(async () => {
console.log(tableRef.value)
await nextTick()
//
tableRef.value!.addRows([
{input: 'input_1'},
{input: 'input_2'},
{input: 'input_3'},
{input: 'input_4'},
{input: 'input_5'},
], {setActive: false})
})
return {tableRef, columns, dataSource, handleView, handleDelete}
},
})
</script>

View File

@ -14,6 +14,9 @@
<a-tab-pane tab="联动示例" key="4">
<JVxeDemo4/>
</a-tab-pane>
<a-tab-pane tab="键盘操作" key="5">
<JVxeDemo5/>
</a-tab-pane>
</a-tabs>
</a-card>
</PageWrapper>
@ -26,4 +29,5 @@ import JVxeDemo1 from './JVxeDemo1.vue'
import JVxeDemo2 from './JVxeDemo2.vue'
import JVxeDemo3 from './JVxeDemo3.vue'
import JVxeDemo4 from './JVxeDemo4.vue'
import JVxeDemo5 from './JVxeDemo5.vue'
</script>

View File

@ -1,60 +1,72 @@
<template>
<BasicForm ref="formElRef" :labelCol="{span: 5}" :wrapperCol="{ span: 15}" :showResetButton="false" :showSubmitButton="false" :schemas="schemas" :actionColOptions="{ span: 24 }" @submit="handleSubmit" @reset="handleReset" style="height: 100%">
<template #jAreaLinkage="{model, field }">
<JAreaLinkage v-model:value="model[field]" :showArea="true" :showAll="false"/>
</template>
<template #jAreaLinkage1="{model, field }">
<JAreaLinkage :disabled="isDisabledAuth(['demo.dbarray'])" v-model:value="model[field]" :showArea="true" :showAll="false"/>
</template>
<template #JPopup="{model, field }">
<JPopup v-model:value="model[field]" :formElRef="formElRef" code="report_user" :fieldConfig="[{source:'username',target:'pop1'}]"/>
</template>
<template #JAreaSelect="{model, field }">
<JAreaSelect v-model:value="model[field]"/>
</template>
<template #JCheckbox="{model, field }">
<JCheckbox v-model:value="model[field]" dictCode="remindMode"/>
</template>
<template #JInput="{model, field }">
<JInput v-model:value="model[field]" :type="model['jinputtype']"/>
</template>
<template #dargVerify="{model, field }">
<BasicDragVerify v-model:value="model[field]"/>
</template>
</BasicForm>
<BasicForm
ref="formElRef"
:class="'jee-select-demo-form'"
:labelCol="{ span: 5 }"
:wrapperCol="{ span: 15 }"
:showResetButton="false"
:showSubmitButton="false"
:schemas="schemas"
:actionColOptions="{ span: 24 }"
@submit="handleSubmit"
@reset="handleReset"
style="height: 100%"
>
<template #jAreaLinkage="{ model, field }">
<JAreaLinkage v-model:value="model[field]" :showArea="true" :showAll="false" />
</template>
<template #jAreaLinkage1="{ model, field }">
<JAreaLinkage :disabled="isDisabledAuth(['demo.dbarray'])" v-model:value="model[field]" :showArea="true" :showAll="false" />
</template>
<template #JPopup="{ model, field }">
<JPopup v-model:value="model[field]" :formElRef="formElRef" code="report_user" :fieldConfig="[{ source: 'username', target: 'pop1' }]" />
</template>
<template #JAreaSelect="{ model, field }">
<JAreaSelect v-model:value="model[field]" />
</template>
<template #JCheckbox="{ model, field }">
<JCheckbox v-model:value="model[field]" dictCode="remindMode" />
</template>
<template #JInput="{ model, field }">
<JInput v-model:value="model[field]" :type="model['jinputtype']" />
</template>
<template #dargVerify="{ model, field }">
<BasicDragVerify v-model:value="model[field]" />
</template>
</BasicForm>
</template>
<script lang="ts">
import { computed, defineComponent, unref, ref } from 'vue';
import {
BasicForm,
ApiSelect,
JAreaLinkage,
JPopup,
JAreaSelect,
FormActionType,
JCheckbox,
JInput,
JEllipsis
} from '/@/components/Form'
import { BasicForm, ApiSelect, JAreaLinkage, JPopup, JAreaSelect, FormActionType, JCheckbox, JInput, JEllipsis } from '/@/components/Form';
import { useMessage } from '/@/hooks/web/useMessage';
import { optionsListApi } from '/@/api/demo/select';
import { useDebounceFn } from '@vueuse/core';
import { schemas } from './jeecgComponents.data.ts';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicDragVerify } from '/@/components/Verify/index';
export default defineComponent({
components: { BasicForm, ApiSelect, JAreaLinkage ,JPopup,JAreaSelect,JCheckbox,JInput,JEllipsis,BasicDragVerify },
name:'JeecgComponents',
components: {
BasicForm,
ApiSelect,
JAreaLinkage,
JPopup,
JAreaSelect,
JCheckbox,
JInput,
JEllipsis,
BasicDragVerify,
},
name: 'JeecgComponents',
setup() {
const { isDisabledAuth } = usePermission();
const check = ref(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const { createMessage } = useMessage();
const keyword = ref<string>('');
const submitButtonOptions=ref({
text:"确定"
})
const submitButtonOptions = ref({
text: '确定',
});
const searchParams = computed<Recordable>(() => {
return { keyword: unref(keyword) };
});
@ -75,7 +87,7 @@
keyword.value = '';
},
handleSubmit: (values: any) => {
console.log("values:",values)
console.log('values:', values);
createMessage.success('click search,values:' + JSON.stringify(values));
},
check,
@ -83,3 +95,11 @@
},
});
</script>
<style lang="less" scoped>
/**update-begin-author:taoyan date:20220324 for: VUEN-351【vue3】展示不全*/
.jee-select-demo-form .ant-col-5 {
flex: 0 0 159px;
max-width: 159px;
}
/**update-end-author:taoyan date:20220324 for: VUEN-351【vue3】展示不全*/
</style>

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@
import { baseSetschemas } from './data';
import { useUserStore } from '/@/store/modules/user';
import { uploadImg } from '/@/api/sys/upload';
import {getFileAccessHttpUrl} from '/@/utils/common/compUtils'
export default defineComponent({
components: {
@ -63,7 +64,7 @@
const avatar = computed(() => {
const { avatar } = userStore.getUserInfo;
return avatar || headerImg;
return getFileAccessHttpUrl(avatar) || headerImg;
});
function updateAvatar(src: string, data:string) {

View File

@ -15,33 +15,57 @@
</a-form-item>
<a-form-item name="predicates" label="路由条件">
<div v-for="(item,index) in router.predicates">
<div v-for="(item,index) in router.predicates" >
<!--当name在noKeyRouter时不需要指定key-->
<template v-if="noKeyRouter.includes(item.name)">
<a-divider>{{item.name}}
<DeleteOutlined size="22" @click="removePredicate(router,index)"/>
</a-divider>
<div>
<template v-for="(tag, tagIndx) in item.args">
<a-input ref="inputRef2" v-if="tagIndx==currentTagIndex&&index==currentNameIndex" type="text" size="small" :style="{ width: '190px' }" v-model:value="state.inputValue" @change="handleInputChange" @blur="handleInputEditConfirm(item,tag,tagIndx)" @keyup.enter="handleInputEditConfirm(item,tag,tagIndx)"/>
<a-tag v-else :key="tag" style="margin-bottom:2px" :closable="true" @close="() => removeTag(item,tag)" @click="editTag(item,tag,tagIndx,index)">
{{ tag }}
</a-tag>
</template>
<a-input ref="inputRef" v-if="state.inputVisible&&index==currentNameIndex" type="text" size="small" :style="{ width: '100px' }" v-model:value="state.inputValue" @change="handleInputChange" @blur="handleInputConfirm(item)" @keyup.enter="handleInputConfirm(item)"/>
<a-tag v-else style="background: #fff; borderStyle: dashed;margin-bottom:2px" @click="showInput(item,index)">
<PlusOutlined size="22" />
新建{{item.name}}
</a-tag>
</div>
</template>
<!--当name不在noKeyRouter时需要指定key-->
<template v-if="!noKeyRouter.includes(item.name)">
<a-divider>{{item.name}}
<Icon preIcon="mdi:access-point-remove" size="22" @click="removePredicate(router,index)"/>
<DeleteOutlined size="22" @click="removePredicate(router,index)"/>
</a-divider>
<div>
<template v-for="(tag, tagIndx) in item.args">
<a-input ref="inputRef2" v-if="tagIndx==currentTagIndex" type="text" size="small" :style="{ width: '190px' }" v-model:value="state.inputValue" @change="handleInputChange" @blur="handleInputEditConfirm(item,tag,tagIndx)" @keyup.enter="handleInputEditConfirm(item,tag,tagIndx)"/>
<a-tag v-else :key="tag" style="margin-bottom:2px" :closable="true" @close="() => removeTag(item,tag)" @click="editTag(tag,tagIndx)">
{{ tag }}
</a-tag>
<template v-for="(value, key) in item.args">
<a-row>
<a-col :span="5" style="margin-top: 8px">
<span v-if="key=='header'" >Header名称</span>
<span v-if="key=='regexp'"></span>
<span v-if="key=='param'"></span>
<span v-if="key=='name'"></span>
</a-col>
<a-col :span="18">
<a-input :defaultValue="value" placeholder="参数值" style="width: 70%; margin-right: 8px;margin-top: 3px" @change="(e)=>valueChange(e,item.args,key)"/>
</a-col>
</a-row>
</template>
<a-input ref="inputRef" v-if="state.inputVisible&&index==currentNameIndex" type="text" size="small" :style="{ width: '100px' }" v-model:value="state.inputValue" @change="handleInputChange" @blur="handleInputConfirm(item)" @keyup.enter="handleInputConfirm(item)"/>
<a-tag v-else style="background: #fff; borderStyle: dashed;margin-bottom:2px" @click="showInput(item,index)">
<Icon type="plus"/>
新建{{item.name}}
</a-tag>
</div>
</template>
</div>
<p class="btn" style="padding-top: 10px">
<a-dropdown>
<template #overlay>
<a-menu @click="predicatesHandleMenuClick">
<a-menu-item :key="item" v-for="item in tagArray">{{item}}</a-menu-item>
<a-menu >
<a-menu-item :key="item.name" v-for="item in tagArray" @click="predicatesHandleMenuClick(item)">{{item.name}}</a-menu-item>
</a-menu>
</template>
<a-button type="dashed" style="margin-left: 8px;width:100%"> 添加路由条件
<Icon type="down"/>
<DownOutlined :size="22"/>
</a-button>
</a-dropdown>
</p>
@ -49,15 +73,15 @@
<a-form-item name="predicates" label="过滤器">
<div v-for="(item,index) in router.filters">
<a-divider>{{item.name}}
<Icon type="delete" size="22" @click="removeFilter(router,index)"/>
<DeleteOutlined size="22" @click="removeFilter(router,index)"/>
</a-divider>
<div v-for="(tag, index) in item.args" :key="tag.key">
<a-input v-model:value="tag.key" placeholder="参数键" style="width: 45%; margin-right: 8px"/>
<a-input v-model:value="tag.value" placeholder="参数值" style="width: 40%; margin-right: 8px;margin-top: 3px"/>
<Icon class="dynamic-delete-button" type="minus-circle-o" @click="removeFilterParams(item,index)"/>
<CloseOutlined :size="22" @click="removeFilterParams(item,index)"/>
</div>
<a-button type="dashed" style="margin-left:28%;width: 37%;margin-top:5px" size="small" @click="addFilterParams(item)">
<Icon type="plus"/>
<DownOutlined :size="22"/>
添加参数
</a-button>
</div>
@ -69,7 +93,7 @@
</a-menu>
</template>
<a-button type="dashed" style="margin-left: 8px;width:100%"> 添加过滤器
<Icon type="down"/>
<DownOutlined />
</a-button>
</a-dropdown>
</p>
@ -80,9 +104,12 @@
</template>
<script lang="ts" setup>
import { ref, computed, unref, useAttrs, reactive,nextTick } from 'vue';
import { BasicDrawer, useDrawerInner } from '/src/components/Drawer';
import {BasicDrawer, useDrawerInner} from '/@/components/Drawer';
import { saveOrUpdateRoute } from './route.api';
import { saveOrUpdateTenant } from '../../system/tenant/tenant.api';
import {DeleteOutlined} from '@ant-design/icons-vue';
import {PlusOutlined} from '@ant-design/icons-vue';
import {CloseOutlined} from '@ant-design/icons-vue';
import {DownOutlined} from '@ant-design/icons-vue';
// Emits
const emit = defineEmits(['register', 'success']);
const labelCol = reactive({
@ -114,8 +141,55 @@
{ required: true, message: 'uri不能为空', trigger: 'blur' },
],
};
const filterArray = [{ key: 0, name: '熔断器' }, { key: 1, name: '限流过滤器' }];
const tagArray = ref(['Path', 'Host', 'Cookie', 'Header', 'Method', 'Query', 'After', 'Before', 'Between', 'RemoteAddr']);
const noKeyRouter=["Path","Host","Method","After","Before","Between","RemoteAddr"];
const filterArray = [/*{ key: 0, name: '熔断器' },*/ { key: 1, name: '限流过滤器' }];
const tagArray = ref([
{
name:'Header',
args:{
header:'',
regexp:''
}
},
{
name:'Query',
args:{
param:'',
regexp:''
}
},
{
name:'Method',
args:[]
},
{
name:'Host',
args:[]
},
{
name:'Cookie',
args:{
name:'',
regexp:''
}
},
{
name:'After',
args:[]
},
{
name:'Before',
args:[]
},
{
name:'Between',
args:[]
},
{
name:'RemoteAddr',
args:[]
}
]);
const formRef = ref();
let router = reactive({});
@ -155,13 +229,24 @@
//
function predicatesHandleMenuClick(e) {
router.predicates.push({
args: [],
name: e.key,
args: e.args,
name: e.name,
});
}
function editTag(tag, index) {
currentTagIndex.value = index;
/**
* 值修改事件
* @param e
* @param item
* @param key
*/
function valueChange(e,item,key){
item[key]=e.target.value
}
function editTag(item,tag, tagIndex,index) {
currentNameIndex.value = index;
currentTagIndex.value = tagIndex;
state.inputValue=tag;
nextTick(() => {
inputRef2.value.focus();
@ -239,7 +324,7 @@
value: 20,
}],
name: 'RequestRateLimiter',
title: filterArray[1].name,
title: filterArray[0].name,
});
}
}
@ -280,14 +365,16 @@
await formRef.value.validate().then(() => {
try {
setDrawerProps({ confirmLoading: true });
console.log('formData', JSON.stringify(router));
router.predicates = JSON.stringify(router.predicates);
router.filters = JSON.stringify(router.filters);
//,router
let params=Object.assign({},router,{
predicates:JSON.stringify(router.predicates),
filters:JSON.stringify(router.filters),
})
//
saveOrUpdateRoute({ router: router }).then(() => {
saveOrUpdateRoute({ router: params }).then(() => {
closeDrawer();
//
emit('success');
closeDrawer();
});
} finally {

View File

@ -3,6 +3,7 @@
<template v-if="treeData.length > 0">
<BasicTree
ref="basicTree"
class="depart-rule-tree"
checkable
:treeData="treeData"
:checkedKeys="checkedKeys"
@ -158,4 +159,12 @@ async function toggleCheckALL(flag) {
await nextTick()
checkedKeys.value = basicTree.value.getCheckedKeys()
}
</script>
</script>
<style lang="less" scoped>
// VUEN-188
.depart-rule-tree ::v-deep(.scrollbar__bar) {
pointer-events: none;
}
</style>

View File

@ -6,6 +6,8 @@ import {duplicateCheck} from "../user/user.api";
import {ajaxGetDictItems} from "./menu.api";
import {render} from "/@/utils/common/renderUtils";
import { Select } from 'ant-design-vue';
import {rules} from '/@/utils/helper/validator'
const isDir = (type) => type === 0;
const isMenu = (type) => type === 1;
const isButton = (type) => type === 2;
@ -131,7 +133,10 @@ export const formSchema: FormSchema[] = [
label: '访问路径',
component: 'Input',
required: true,
ifShow: ({ values }) => !(values.component === ComponentTypes.IFrame && values.internalOrExternal),
ifShow: ({ values }) => !(values.component === ComponentTypes.IFrame && values.internalOrExternal) && values.menuType !== 2,
dynamicRules: ({model, schema}) => {
return rules.duplicateCheckRule('sys_permission', 'url', model, schema, true)
},
},
{
field: 'component',

View File

@ -1,5 +1,5 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="查看详情" :showCancelBtn="false" :showOkBtn="false">
<BasicModal v-bind="$attrs" @register="registerModal" title="查看详情" :showCancelBtn="false" :showOkBtn="false" :height="500">
<iframe :src="frameSrc" class="detail-iframe"/>
</BasicModal>
</template>

View File

@ -153,7 +153,10 @@
{
label: '撤销',
ifShow: record.sendStatus == 1,
onClick: handleReovke.bind(null, record.id),
popConfirm: {
title: '确定要撤销吗?',
confirm: handleReovke.bind(null, record.id),
},
},
{
label: '查看',

View File

@ -32,7 +32,7 @@
import {BasicTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal';
import {getPositionList, deletePosition, batchDeletePosition,customUpload,getExportUrl,getImportUrl} from './position.api';
import {columns, searchFormSchema} from './Position.data';
import {columns, searchFormSchema} from './position.data';
import PositionModal from './PositionModal.vue';
import {useMessage} from "/@/hooks/web/useMessage";
import { useListPage } from '/@/hooks/system/useListPage'

View File

@ -1,4 +1,5 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
import {rules} from '/@/utils/helper/validator'
export const columns: BasicColumn[] = [
{
@ -61,5 +62,8 @@ export const formSchema: FormSchema[] = [
dynamicDisabled: ({values}) => {
return !!values.id;
},
dynamicRules: ({model, schema}) => {
return rules.duplicateCheckRule('sys_position', 'code', model, schema, true)
},
}
];

View File

@ -0,0 +1,57 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="首页配置" @ok="handleSubmit" width="40%">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import {roleIndexFormSchema} from '../role.data';
import {saveOrUpdateRoleIndex, queryIndexByCode} from '../role.api';
// Emits
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
//
const [registerForm, {resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: roleIndexFormSchema,
showActionButtonGroup: false,
});
//
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//
await resetFields();
setModalProps({confirmLoading: false});
setFieldsValue({roleCode: data.roleCode});
let res = await queryIndexByCode({roleCode: data.roleCode});
isUpdate.value = !!res.result?.id;
if (unref(isUpdate)) {
//
await setFieldsValue({
...res.result,
});
}
});
//
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//
await saveOrUpdateRoleIndex(values, isUpdate.value);
//
closeModal();
//
emit('success', {isUpdate: isUpdate.value, values});
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>

View File

@ -9,8 +9,8 @@
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
<Icon icon="bx:bx-unlink"></Icon>
取消关联
</a-menu-item>
</a-menu>
</template>
@ -72,7 +72,7 @@
canResize: false,
rowKey: 'id',
actionColumn: {
width: 50,
width: 180,
title: '操作',
dataIndex: 'action',
slots: {customRender: 'action'},
@ -172,9 +172,9 @@
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
label: '取消关联',
popConfirm: {
title: '是否确认删除',
title: '是否确认取消关联',
confirm: handleDelete.bind(null, record),
}
}

View File

@ -31,6 +31,8 @@
<RolePermissionDrawer @register="rolePermissionDrawer"/>
<!--角色工单授权-->
<RoleDesignModal @register="registerModal"/>
<!--角色工单授权-->
<RoleIndexModal @register="registerIndexModal"/>
</template>
<script lang="ts" name="system-role" setup>
import {ref} from 'vue'
@ -41,6 +43,7 @@
import RoleDesc from './components/RoleDesc.vue';
import RolePermissionDrawer from './components/RolePermissionDrawer.vue';
import RoleDesignModal from './components/RoleDesignModal.vue';
import RoleIndexModal from './components/RoleIndexModal.vue';
import RoleUserTable from './components/RoleUserTable.vue';
import {columns, searchFormSchema} from './role.data';
import {list, deleteRole, batchDeleteRole, getExportUrl,getImportUrl} from './role.api';
@ -49,6 +52,7 @@
const [roleUserDrawer, {openDrawer:openRoleUserDrawer}] = useDrawer();
const [registerDrawer, {openDrawer}] = useDrawer();
const [registerModal, {openModal}] = useModal();
const [registerIndexModal, {openModal:openIndexModal}] = useModal();
const [rolePermissionDrawer, {openDrawer: openRolePermissionDrawer}] = useDrawer();
const [registerDesc, {openDrawer: openRoleDesc}] = useDrawer();
@ -130,6 +134,12 @@
function handleDesign(id) {
openModal(true, {roleId: id});
}
/**
* 首页配置弹窗
*/
function handleIndexConfig(roleCode) {
openIndexModal(true, {roleCode});
}
/**
* 角色用户
*/
@ -171,6 +181,9 @@
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
},
},{
label: '首页配置',
onClick: handleIndexConfig.bind(null, record.roleCode),
}, {
label: '工单?',
onClick: handleDesign.bind(null, record.id),

View File

@ -21,6 +21,9 @@ enum Api {
deleteUserRole = '/sys/user/deleteUserRole',
batchDeleteUserRole = '/sys/user/deleteUserRoleBatch',
addUserRole = '/sys/user/addSysUserRole',
saveRoleIndex='/sys/sysRoleIndex/add',
editRoleIndex='/sys/sysRoleIndex/edit',
queryIndexByCode='/sys/sysRoleIndex/queryByCode',
}
/**
* api
@ -157,3 +160,18 @@ export const addUserRole = (params, handleSuccess) => {
handleSuccess();
});
}
/**
*
* @param params
* @param isUpdate
*/
export const saveOrUpdateRoleIndex = (params, isUpdate) => {
let url = isUpdate ? Api.editRoleIndex : Api.saveRoleIndex;
return defHttp.post({url: url, params});
}
/**
* code
* @param params
*/
export const queryIndexByCode = (params) =>
defHttp.get({url: Api.queryIndexByCode, params}, {isTransformResponse: false});

View File

@ -24,12 +24,10 @@ export const userColumns = [
{
title: '用户账号',
dataIndex: 'username',
width: 100,
},
{
title: '用户姓名',
dataIndex: 'realname',
width: 100,
},
{
title: '状态',
@ -125,4 +123,36 @@ export const formDescSchema = [
}
];
export const roleIndexFormSchema: FormSchema[] = [
{
field: 'id',
label: '',
component: 'Input',
show:false
},
{
label: '角色编码',
field: 'roleCode',
component: 'Input',
dynamicDisabled: true
},
{
label: '首页路由',
field: 'url',
component: 'Input',
required:true
},
{
label: '优先级',
field: 'priority',
component: 'InputNumber'
},
{
label: '是否开启',
field: 'status',
component: 'JSwitch',
componentProps:{
options : ['1', '0'],
}
}
];

View File

@ -13,7 +13,7 @@
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
//
const [registerForm, {resetFields, setFieldsValue, validate}] = useForm({
const [registerForm, {resetFields, setFieldsValue, validate, updateSchema}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
@ -25,12 +25,16 @@
setModalProps({confirmLoading: false});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
// id
updateSchema({field: 'id', dynamicDisabled: true})
//
data.record = await getTenantById({id: data.record.id});
//
await setFieldsValue({
...data.record,
});
} else {
updateSchema({field: 'id', dynamicDisabled: false})
}
});
//

View File

@ -67,6 +67,7 @@
label: '删除',
popConfirm: {
title: '是否确认删除',
placement: 'left',
confirm: handleDelete.bind(null, record),
},
},

View File

@ -50,8 +50,8 @@ export const searchFormSchema: FormSchema[] = [
component: 'Select',
componentProps: {
options: [
{ label: '启用', value: 1 },
{ label: '停用', value: 0 },
{ label: '正常', value: 1 },
{ label: '冻结', value: 0 },
],
},
colProps: { span: 8 },
@ -77,9 +77,6 @@ export const formSchema: FormSchema[] = [
field: 'id',
label: '租户编号',
component: 'InputNumber',
dynamicDisabled: ({values}) => {
return !!values.id;
},
required: true
},
{

View File

@ -1,5 +1,5 @@
<template>
<BasicDrawer v-bind="$attrs" @register="registerDrawer" :title="getTitle" width="600" @ok="handleSubmit" destroyOnClose>
<BasicDrawer v-bind="$attrs" @register="registerDrawer" :title="getTitle" :width="adaptiveWidth" @ok="handleSubmit" :showFooter="showFooter" destroyOnClose>
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
@ -9,6 +9,7 @@
import {formSchema} from './user.data';
import {BasicDrawer, useDrawerInner} from '/@/components/Drawer';
import {saveOrUpdateUser,getUserRoles,getUserDepartList} from './user.api';
import {useDrawerAdaptiveWidth} from '/@/hooks/jeecg/useAdaptiveWidth'
// Emits
const emit = defineEmits(['success', 'register']);
const attrs = useAttrs()
@ -21,11 +22,13 @@
schemas: formSchema,
showActionButtonGroup: false,
});
// TODO [VUEN-527] https://www.teambition.com/task/6239beb894b358003fe93626
const showFooter = ref(true)
//
const [registerDrawer, {setDrawerProps, closeDrawer}] = useDrawerInner(async (data) => {
await resetFields();
let showFooter = data?.showFooter ?? true
setDrawerProps({ confirmLoading: false, showFooter })
showFooter.value = data?.showFooter ?? true
setDrawerProps({ confirmLoading: false, showFooter: showFooter.value })
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
rowId.value = data.record.id;
@ -96,6 +99,7 @@
});
//
const getTitle = computed(() => (!unref(isUpdate) ? '新增用户' : '编辑用户'));
const {adaptiveWidth} = useDrawerAdaptiveWidth()
//
async function handleSubmit() {

View File

@ -34,6 +34,9 @@
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import {recycleColumns} from './user.data';
import {getRecycleBinList, putRecycleBin, deleteRecycleBin} from './user.api';
import {useMessage} from '/@/hooks/web/useMessage'
const {createConfirm} = useMessage()
// Emits
const emit = defineEmits(['success', 'register']);
const checkedKeys = ref<Array<string | number>>([]);
@ -100,7 +103,14 @@
* 批量删除事件
*/
function batchHandleDelete() {
handleDelete({id:toRaw(unref(checkedKeys)).join(",")})
createConfirm({
iconType: 'warning',
title: '删除',
content: '确定要永久删除吗?删除后将不可恢复!',
onOk: () => handleDelete({id: toRaw(unref(checkedKeys)).join(',')}),
onCancel() {
},
})
}
//
function getTableAction(record) {

View File

@ -176,7 +176,7 @@ export const formSchema: FormSchema[] = [
{
label: '职务',
field: 'post',
required: true,
required: false,
component: 'JSelectPosition',
componentProps: {
rowKey:'code',

2
types/config.d.ts vendored
View File

@ -169,7 +169,7 @@ export interface GlobEnvConfig {
//是否开启微应用模式
VITE_GLOB_APP_OPEN_QIANKUN: string;
//单点服务端地址
VITE_GLOBE_APP_CAS_BASE_URL: string;
VITE_GLOB_APP_CAS_BASE_URL: string;
VITE_GLOB_DOMAIN_URL: string;
// Upload url
VITE_GLOB_UPLOAD_URL?: string;

1
types/store.d.ts vendored
View File

@ -40,6 +40,7 @@ export interface UserInfo {
homePath?: string;
tenantid?: string | number;
roles: RoleInfo[];
orgCode?: string;
}
export interface LoginInfo {

350
yarn.lock
View File

@ -920,9 +920,9 @@
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.7.2":
version "7.17.2"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
version "7.17.9"
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
dependencies:
regenerator-runtime "^0.13.4"
@ -1206,53 +1206,53 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@fullcalendar/common@~5.10.1":
version "5.10.1"
resolved "https://registry.npmmirror.com/@fullcalendar/common/download/@fullcalendar/common-5.10.1.tgz#a019951743852277a4095e536fd7716f6f85b9aa"
integrity sha1-oBmVF0OFInekCV5Tb9dxb2+Fuao=
"@fullcalendar/common@~5.11.0":
version "5.11.0"
resolved "https://registry.npmmirror.com/@fullcalendar/common/-/common-5.11.0.tgz#d7e47b4272ba6824f95581fb7fb630c5880f4212"
integrity sha512-gWjbMAnN1u73Oqlgjbyky7i+3bY0hvFSnGT0YBPx44n874AkQa9e9OU12PMLTMOPy0tXPb8DEwRelFQ7CJNbcw==
dependencies:
tslib "^2.1.0"
"@fullcalendar/core@^5.8.0", "@fullcalendar/core@~5.10.1":
version "5.10.1"
resolved "https://registry.npmmirror.com/@fullcalendar/core/download/@fullcalendar/core-5.10.1.tgz#05c7653e5004149a63bcb03e9dc8b049186ca50b"
integrity sha1-BcdlPlAEFJpjvLA+nciwSRhspQs=
"@fullcalendar/core@^5.10.1", "@fullcalendar/core@~5.11.0":
version "5.11.0"
resolved "https://registry.npmmirror.com/@fullcalendar/core/-/core-5.11.0.tgz#336fcfb9799cf0c2d1ee15c110dce26a9e14881c"
integrity sha512-cF/d9LuJb/6xw14ms0urv1H4BiA70c4jrufe/EuVzLR6qTDpK92IZ3JK7GVtZtzptfTYZ/NQgDV9YCzIaO9Blw==
dependencies:
"@fullcalendar/common" "~5.10.1"
"@fullcalendar/common" "~5.11.0"
preact "^10.0.5"
tslib "^2.1.0"
"@fullcalendar/daygrid@^5.8.0", "@fullcalendar/daygrid@~5.10.1":
version "5.10.1"
resolved "https://registry.npmmirror.com/@fullcalendar/daygrid/download/@fullcalendar/daygrid-5.10.1.tgz#bdee4f58364fdab631b2abf8b56094ab5776f203"
integrity sha1-ve5PWDZP2rYxsqv4tWCUq1d28gM=
"@fullcalendar/daygrid@^5.10.1", "@fullcalendar/daygrid@~5.11.0":
version "5.11.0"
resolved "https://registry.npmmirror.com/@fullcalendar/daygrid/-/daygrid-5.11.0.tgz#fd10391dfc2b6caa3538e0826f8d8f3e83e0e22a"
integrity sha512-Ybh/dfHn/VL0qOVIRVyJc9I8oYiqqHl6xQONk8xXCe456QbPzAQLsAxpLLJLH+3smWNCfoQgvDKzR9e9XTzLMQ==
dependencies:
"@fullcalendar/common" "~5.10.1"
"@fullcalendar/common" "~5.11.0"
tslib "^2.1.0"
"@fullcalendar/interaction@^5.8.0":
version "5.10.1"
resolved "https://registry.npmmirror.com/@fullcalendar/interaction/download/@fullcalendar/interaction-5.10.1.tgz#dfa74b5c50bbd5608eb50aeab6e579c8d20cb367"
integrity sha1-36dLXFC71WCOtQrqtuV5yNIMs2c=
"@fullcalendar/interaction@^5.10.1":
version "5.11.0"
resolved "https://registry.npmmirror.com/@fullcalendar/interaction/-/interaction-5.11.0.tgz#9cfb46cc5f75690394ef553d2c5cf4955782ff05"
integrity sha512-9XTI5+ydqrSX+IL3iWgKBURXfnPewn57Tmsv9mJZhiqrUEF7/+qtftLoKEAc8ZdWk/+01aBe67PFL16uPXj2Jg==
dependencies:
"@fullcalendar/common" "~5.10.1"
"@fullcalendar/common" "~5.11.0"
tslib "^2.1.0"
"@fullcalendar/timegrid@^5.8.0":
version "5.10.1"
resolved "https://registry.npmmirror.com/@fullcalendar/timegrid/download/@fullcalendar/timegrid-5.10.1.tgz#fa7feb909bf599eac1466b9e70c0d56ce0d1aefc"
integrity sha1-+n/rkJv1merBRmuecMDVbODRrvw=
"@fullcalendar/timegrid@^5.10.1":
version "5.11.0"
resolved "https://registry.npmmirror.com/@fullcalendar/timegrid/-/timegrid-5.11.0.tgz#b41153ef301f21f8c1e19a65023493c48c8bacf5"
integrity sha512-GNy+/PwAj510PS4Fu18Mf/CytNBVftFU7M8XwsUXOCJ6ouyroHZje0a7k5cH/nE5IQ6NJZfH2eAPBlxGath1MQ==
dependencies:
"@fullcalendar/common" "~5.10.1"
"@fullcalendar/daygrid" "~5.10.1"
"@fullcalendar/common" "~5.11.0"
"@fullcalendar/daygrid" "~5.11.0"
tslib "^2.1.0"
"@fullcalendar/vue3@^5.8.0":
version "5.10.1"
resolved "https://registry.npmmirror.com/@fullcalendar/vue3/download/@fullcalendar/vue3-5.10.1.tgz#b34adcaf7837256a5aa9240592a0d97b55eb675d"
integrity sha1-s0rcr3g3JWpaqSQFkqDZe1XrZ10=
"@fullcalendar/vue3@^5.10.1":
version "5.11.0"
resolved "https://registry.npmmirror.com/@fullcalendar/vue3/-/vue3-5.11.0.tgz#51b737e91aadab53a03162a8ade9f017429ba1cf"
integrity sha512-vqRJRItEdIdtO+6B3/jNppF9dU1zkZVuEL+YiXmuqH3bwqrOH0xK5ALm7YfPJvZJq9TnrVI2HPaVl9D49Mxr7g==
dependencies:
"@fullcalendar/core" "~5.10.1"
"@fullcalendar/core" "~5.11.0"
tslib "^2.1.0"
"@humanwhocodes/config-array@^0.6.0":
@ -1293,6 +1293,122 @@
resolved "https://registry.npmmirror.com/@iconify/json/download/@iconify/json-1.1.423.tgz#3507db88e10a58b63f78e817200f07eacb1a2c1e"
integrity sha1-NQfbiOEKWLY/eOgXIA8H6ssaLB4=
"@interactjs/actions@1.10.11", "@interactjs/actions@^1.10.2":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/actions/-/actions-1.10.11.tgz#ec68fd60bee751f80c650964b5ba299eb6afe78c"
integrity sha512-P39zeefr4hkmKx+5nZ+mrH1s0l2YJ3gIHrthXmE81n6MlMa42m0WtHcTms4C5JTTNBP2EEDY+KGgGxSnmJKvUw==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/auto-scroll@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/auto-scroll/-/auto-scroll-1.10.11.tgz#0c0ac7dbb55aa7d7df6c0a04c77ebb3148cbdf54"
integrity sha512-feHNjhi0EMNLV2nQcEgjYPz2mI54aeSW2RiaoNtFLyBvtXKp0b4DmluwDv6DvuXmUpDwD5g/Hk1gGM2rgl7iqQ==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/auto-start@1.10.11", "@interactjs/auto-start@^1.10.2":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/auto-start/-/auto-start-1.10.11.tgz#5ce045740f35be36640ebad053db7b5652e18e70"
integrity sha512-cIg5CcalCPtC6AiGq6j/0hKUtL2MweEpvw12FuB19sz2Q9Dye0J4GliHKhOYvtumNinnvfVAZ4FZMqZEuX7YZA==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/core@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/core/-/core-1.10.11.tgz#8b0203492c1ba6f8432f20b718ae53707fcfc724"
integrity sha512-aJ50ccVeszpJt7wPH7Yfqm7f1aG1SA94qd90P0NaESh5/QUXn4CESO6igobo4DFHQ5z+1Rfdl8aphP4JxlH4gw==
"@interactjs/dev-tools@1.10.11", "@interactjs/dev-tools@^1.10.2":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/dev-tools/-/dev-tools-1.10.11.tgz#8d4b5b650cf74e800909f52962008700143a4304"
integrity sha512-BP2FNfMbF7zLuOAUGMkDhCo1e1B0fnqyb9ih/Y8yAIJuoLrZxP/9htbsS1vZOIVZ4UgtrId4cYOwfcAZBMQtmw==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/inertia@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/inertia/-/inertia-1.10.11.tgz#58864173310985b8247d84e347148ea6cd7b88a8"
integrity sha512-h+sknCzRqBSyHy4ctPNsq56mxkAMMdwHWD6en7rDEw899gdGKYaXVDVdv1jMfiwNRw0eRFBNoCiol8r3a/a3Jw==
dependencies:
"@interactjs/offset" "1.10.11"
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/interact@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/interact/-/interact-1.10.11.tgz#d96e3f949ee4001a6a34dc363a232646f9dd2b1b"
integrity sha512-0iZJ9l547JuBA/lKxK4ARGYVmMqRSsAdA8gXL1zWe51qEIQq8PyWmMipoi8JbDaL7exC2THKwkXu5uq5ndT+iA==
dependencies:
"@interactjs/core" "1.10.11"
"@interactjs/types" "1.10.11"
"@interactjs/utils" "1.10.11"
"@interactjs/interactjs@^1.10.2":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/interactjs/-/interactjs-1.10.11.tgz#d0fdd6b03c1c855043b1f608a10b2f5ccac4b4b7"
integrity sha512-cGOxf6rp3Y8/sk88LhIT0XDn4gCiCzAnUG5Kkj9SAqiUO6BK/9+Wbp1IBkNaPgl/8uG8gNHh/dXBrlBBNcqJAg==
dependencies:
"@interactjs/actions" "1.10.11"
"@interactjs/auto-scroll" "1.10.11"
"@interactjs/auto-start" "1.10.11"
"@interactjs/core" "1.10.11"
"@interactjs/dev-tools" "1.10.11"
"@interactjs/inertia" "1.10.11"
"@interactjs/interact" "1.10.11"
"@interactjs/modifiers" "1.10.11"
"@interactjs/offset" "1.10.11"
"@interactjs/pointer-events" "1.10.11"
"@interactjs/reflow" "1.10.11"
"@interactjs/utils" "1.10.11"
"@interactjs/modifiers@1.10.11", "@interactjs/modifiers@^1.10.2":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/modifiers/-/modifiers-1.10.11.tgz#f40962a97fd3e110e66b79664796c24f3c4e6cd6"
integrity sha512-ltqX1RSqeAIikixlQBlyEUdclT5+rbfIGi3sIdLLYaIZQnltYkWqL9MHKx/w5b+hV+Mc0p5MLUFWJbTdkSCZ9g==
dependencies:
"@interactjs/snappers" "1.10.11"
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/offset@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/offset/-/offset-1.10.11.tgz#512242f330dc80cdbda4feda8fb34c0491f50496"
integrity sha512-mBT7eIfy5ivofECiv+VwtEwwIMLV54fT9ujSMWJPduxdSYIHepUWgEf/3zjJknFh6jQc7pqz9dtjvVvyzRCLlQ==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/pointer-events@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/pointer-events/-/pointer-events-1.10.11.tgz#ff4c74a75d7711fc1006ebf32ea344e35bffe938"
integrity sha512-yBT8JJVMZ+MgBay5l1WAHnL8ch/mZsRfaFahti+QFYeQyRloDtsWmEMDSYI/Onyy9+hS3gN/ge77ArGciZZ0Ow==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/reflow@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/reflow/-/reflow-1.10.11.tgz#43d2ad8ca002bf98091273d179fd70b1cabfb9e2"
integrity sha512-NSCtcCkjImOYSbxzzv2kFqR9t49J8KlhEr9UoePc7GyLbNXsiv3WQ3n0ehZd7CgZXQDiVXnP2UnmIOv5Zd4HQg==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/snappers@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/snappers/-/snappers-1.10.11.tgz#3eb6e45ab8319c0dd4b60b284c55c87561aaadb1"
integrity sha512-yYtOMUZ7aFUZ1IYheq9Tj5hZ4J1r5dnaXhLF44WsI/awQ5L0DjZf07GPWof0B+7rZHEVudxyQNbPfFmb+1K94Q==
optionalDependencies:
"@interactjs/interact" "1.10.11"
"@interactjs/types@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/types/-/types-1.10.11.tgz#29be25d503f9c7842df062fa3cda5b044a47cf2a"
integrity sha512-YRsVFWjL8Gkkvlx3qnjeaxW4fnibSJ9791g8BA7Pv5ANByI64WmtR1vU7A2rXcrOn8XvyCEfY0ss1s8NhZP+MA==
"@interactjs/utils@1.10.11":
version "1.10.11"
resolved "https://registry.npmmirror.com/@interactjs/utils/-/utils-1.10.11.tgz#939d0f128dfa96c673276cca3eb7f313d92daabf"
integrity sha512-410ZoxKF+r1roeSelL+WHXfdryUMg5iykC1XwQ3l6XqNw43IMACzyvTH6k6Pwxj7w7x42nce0Qdn1GQ3Y8xyCw==
"@intlify/core-base@9.1.9":
version "9.1.9"
resolved "https://registry.npmmirror.com/@intlify/core-base/download/@intlify/core-base-9.1.9.tgz#e4e8c951010728e4af3a0d13d74cf3f9e7add7f6"
@ -1755,6 +1871,13 @@
resolved "https://registry.nlark.com/@types/crypto-js/download/@types/crypto-js-4.0.2.tgz?cache=0&sync_timestamp=1629707090206&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fcrypto-js%2Fdownload%2F%40types%2Fcrypto-js-4.0.2.tgz#4524325a175bf819fec6e42560c389ce1fb92c97"
integrity sha1-RSQyWhdb+Bn+xuQlYMOJzh+5LJc=
"@types/echarts@^4.9.12":
version "4.9.14"
resolved "https://registry.npmmirror.com/@types/echarts/-/echarts-4.9.14.tgz#41fd4aa286078fa3346bbd92144a704aec5e2b78"
integrity sha512-hg2EFjTmiatztvxIFNIQ7tTIdSsbRZJXfBwJlaucvnQKqv4t2AKmpbPXU9rLtrgD/KCpyi1SX7T+WH6uVybmqA==
dependencies:
"@types/zrender" "*"
"@types/estree@*":
version "0.0.50"
resolved "https://registry.nlark.com/@types/estree/download/@types/estree-0.0.50.tgz?cache=0&sync_timestamp=1629707592205&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Festree%2Fdownload%2F%40types%2Festree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83"
@ -2045,6 +2168,11 @@
dependencies:
"@types/yargs-parser" "*"
"@types/zrender@*":
version "4.0.1"
resolved "https://registry.npmmirror.com/@types/zrender/-/zrender-4.0.1.tgz#6280c40207927ce086be24b4391d668cd330e956"
integrity sha512-IyTRf30jPOXK1+1RChI/78U6aV9hyWYf/vhL96Vt66oDz9es/BDjeKpvbNZSOHVA7zAReOwJcmdZS5AGAqhygw==
"@typescript-eslint/eslint-plugin@^5.1.0":
version "5.3.0"
resolved "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/download/@typescript-eslint/eslint-plugin-5.3.0.tgz#a55ae72d28ffeb6badd817fe4566c9cced1f5e29"
@ -2579,7 +2707,7 @@ ansi-styles@^5.0.0:
resolved "https://registry.nlark.com/ansi-styles/download/ansi-styles-5.2.0.tgz?cache=0&sync_timestamp=1618995588464&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-styles%2Fdownload%2Fansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
integrity sha1-B0SWkK1Fd30ZJKwquy/IiV26g2s=
ant-design-vue@2.2.8:
ant-design-vue@2.2.8, ant-design-vue@^2.2.8:
version "2.2.8"
resolved "https://registry.npmmirror.com/ant-design-vue/download/ant-design-vue-2.2.8.tgz#fa87cf6842d8ee9a0d8af393ff4099ecc4072f2b"
integrity sha1-+ofPaELY7poNivOT/0CZ7MQHLys=
@ -2784,6 +2912,13 @@ axios@^0.23.0:
dependencies:
follow-redirects "^1.14.4"
axios@^0.24.0:
version "0.24.0"
resolved "https://registry.npmmirror.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
dependencies:
follow-redirects "^1.14.4"
babel-jest@^27.3.1:
version "27.3.1"
resolved "https://registry.npmmirror.com/babel-jest/download/babel-jest-27.3.1.tgz?cache=0&sync_timestamp=1634626713402&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fbabel-jest%2Fdownload%2Fbabel-jest-27.3.1.tgz#0636a3404c68e07001e434ac4956d82da8a80022"
@ -2938,6 +3073,11 @@ basic-auth@^2.0.1:
dependencies:
safe-buffer "5.1.2"
batch-processor@1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8"
integrity sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.nlark.com/big.js/download/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@ -3498,6 +3638,11 @@ codemirror@^5.63.3:
resolved "https://registry.npmmirror.com/codemirror/download/codemirror-5.63.3.tgz#97042a242027fe0c87c09b36bc01931d37b76527"
integrity sha1-lwQqJCAn/gyHwJs2vAGTHTe3ZSc=
codemirror@^5.65.0:
version "5.65.3"
resolved "https://registry.npmmirror.com/codemirror/-/codemirror-5.65.3.tgz#2d029930d5a293bc5fb96ceea64654803c0d4ac7"
integrity sha512-kCC0iwGZOVZXHEKW3NDTObvM7pTIyowjty4BUqeREROc/3I6bWbgZDA3fGDwlA+rbgRjvnRnfqs9SfXynel1AQ==
codepage@~1.15.0:
version "1.15.0"
resolved "https://registry.nlark.com/codepage/download/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab"
@ -3879,6 +4024,11 @@ core-js@^3.15.1, core-js@^3.18.1:
resolved "https://registry.npmmirror.com/core-js/download/core-js-3.19.1.tgz?cache=0&sync_timestamp=1635888694924&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fcore-js%2Fdownload%2Fcore-js-3.19.1.tgz#f6f173cae23e73a7d88fa23b6e9da329276c6641"
integrity sha1-9vFzyuI+c6fYj6I7bp2jKSdsZkE=
core-js@^3.6.5, core-js@^3.8.1:
version "3.22.2"
resolved "https://registry.npmmirror.com/core-js/-/core-js-3.22.2.tgz#3ea0a245b0895fa39d1faa15fe75d91ade504a01"
integrity sha512-Z5I2vzDnEIqO2YhELVMFcL1An2CIsFe9Q7byZhs8c/QxummxZlAHw33TUHbIte987LkisOgL0LwQ1P9D6VISnA==
core-util-is@~1.0.0:
version "1.0.3"
resolved "https://registry.nlark.com/core-util-is/download/core-util-is-1.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcore-util-is%2Fdownload%2Fcore-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
@ -4125,6 +4275,13 @@ debug@^3.1.1, debug@^3.2.6:
dependencies:
ms "^2.1.1"
debug@^4.3.3:
version "4.3.4"
resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
decamelize-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.nlark.com/decamelize-keys/download/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@ -4471,6 +4628,14 @@ echarts@^5.2.1:
tslib "2.3.0"
zrender "5.2.1"
echarts@^5.2.2:
version "5.3.2"
resolved "https://registry.npmmirror.com/echarts/-/echarts-5.3.2.tgz#0a7b3be8c48a48b2e7cb1b82121df0c208d42d2c"
integrity sha512-LWCt7ohOKdJqyiBJ0OGBmE9szLdfA9sGcsMEi+GGoc6+Xo75C+BkcT/6NNGRHAWtnQl2fNow05AQjznpap28TQ==
dependencies:
tslib "2.3.0"
zrender "5.3.1"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.nlark.com/ee-first/download/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@ -4493,6 +4658,13 @@ electron-to-chromium@^1.3.886:
resolved "https://registry.npmmirror.com/electron-to-chromium/download/electron-to-chromium-1.3.887.tgz?cache=0&sync_timestamp=1635879962653&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.887.tgz#b36aeed12a28aaa19460a467823f5bbe1f3c6f06"
integrity sha1-s2ru0SooqqGUYKRngj9bvh88bwY=
element-resize-detector@^1.2.1:
version "1.2.4"
resolved "https://registry.npmmirror.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz#3e6c5982dd77508b5fa7e6d5c02170e26325c9b1"
integrity sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==
dependencies:
batch-processor "1.0.0"
emittery@^0.8.1:
version "0.8.1"
resolved "https://registry.nlark.com/emittery/download/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
@ -6258,9 +6430,9 @@ import-fresh@^3.0.0, import-fresh@^3.2.1:
resolve-from "^4.0.0"
import-html-entry@^1.9.0:
version "1.11.1"
resolved "https://registry.npmjs.org/import-html-entry/-/import-html-entry-1.11.1.tgz#3d8c5977926bdd122ab8e658965c102068b4af8d"
integrity sha512-O7mCUTwKdYU49/LH6nq1adWPnUlZQpKeGWIEcDq07KTcqP/v0jBLEIVc0oE0Mtlw3CEe0eeKGMyhl6LwfXCV7A==
version "1.12.0"
resolved "https://registry.npmmirror.com/import-html-entry/-/import-html-entry-1.12.0.tgz#460dff3cd86a9774f2ae9fc44bdce3577d30a235"
integrity sha512-wloMEMwupKJ8DWvKsEzJTXhHVieEH8ylu9ebeQg7T9JUsPTo0Zwa1EkuSKgKJvOiA2MxAFkeYYvd/E2pKiFtWQ==
dependencies:
"@babel/runtime" "^7.7.2"
@ -8123,6 +8295,11 @@ minimist@1.2.5, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
resolved "https://registry.npmmirror.com/minimist/download/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=
mitt@^2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230"
integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==
mixin-deep@^1.2.0:
version "1.3.2"
resolved "https://registry.nlark.com/mixin-deep/download/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@ -9337,9 +9514,9 @@ q@^1.5.1:
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qiankun@^2.5.1:
version "2.6.3"
resolved "https://registry.npmjs.org/qiankun/-/qiankun-2.6.3.tgz#00c55a3d6655b2a78b6e0578d70c694cdb662073"
integrity sha512-h1NIokwjdt508HNPcWBdzoYFDJvhbpUUlFSa5dDkpJYVCl55iqqHgdyi1YayinmLmr/9s/zD+WQv+A2mbzkMQw==
version "2.7.0"
resolved "https://registry.npmmirror.com/qiankun/-/qiankun-2.7.0.tgz#2054e1be05ddfbf1eb7658125075bc9f04afd37e"
integrity sha512-MvsRNsu/2dql9un6qWRz/uNsyrFKa2b21Yxpb6UQpNu1pAl16xFozLDufBqiv/RbaGLI+f37VMwofi8n6WpP3w==
dependencies:
"@babel/runtime" "^7.10.5"
import-html-entry "^1.9.0"
@ -10005,7 +10182,7 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
single-spa@^5.9.2:
version "5.9.3"
resolved "https://registry.npmjs.org/single-spa/-/single-spa-5.9.3.tgz#2d151cbb3b273629a5b27b30a3b8ca847dcba4c5"
resolved "https://registry.npmmirror.com/single-spa/-/single-spa-5.9.3.tgz#2d151cbb3b273629a5b27b30a3b8ca847dcba4c5"
integrity sha512-qMGraRzIBsodV6569Fob4cQ4/yQNrcZ5Achh3SAQDljmqUtjAZ7BAA7GAyO/l5eizb7GtTmVq9Di7ORyKw82CQ==
sisteransi@^1.0.5:
@ -10940,7 +11117,7 @@ tslib@2.3.0:
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0:
@ -11351,6 +11528,21 @@ vite-plugin-mock@^2.9.6:
fast-glob "^3.2.7"
path-to-regexp "^6.2.0"
vite-plugin-optimize-persist@^0.1.2:
version "0.1.2"
resolved "https://registry.npmmirror.com/vite-plugin-optimize-persist/-/vite-plugin-optimize-persist-0.1.2.tgz#c2aa2712afa74db55f580e3d1656e8cc0b783019"
integrity sha512-H/Ebn2kZO8PvwUF08SsT5K5xMJNCWKoGX71+e9/ER3yNj7GHiFjNQlvGg5ih/zEx09MZ9m7WCxOwmEKbeIVzww==
dependencies:
debug "^4.3.2"
fs-extra "^10.0.0"
vite-plugin-package-config@^0.1.1:
version "0.1.1"
resolved "https://registry.npmmirror.com/vite-plugin-package-config/-/vite-plugin-package-config-0.1.1.tgz#6bd579f71db7582ef9dcc05e9f7920e689c498c9"
integrity sha512-w9B3I8ZnqoyhlbzimXjXNk85imrMZgvI9m8f6j3zonK5IVA5KXzpT+PZOHlDz8lqh1vqvoEI1uhy+ZDoLAiA/w==
dependencies:
debug "^4.3.3"
vite-plugin-purge-icons@^0.7.0:
version "0.7.0"
resolved "https://registry.npm.taobao.org/vite-plugin-purge-icons/download/vite-plugin-purge-icons-0.7.0.tgz#c460037438fd71372153360ccb9e7d97b030fb58"
@ -11575,6 +11767,19 @@ vscode-vue-languageservice@0.28.10:
vscode-pug-languageservice "0.28.10"
vscode-typescript-languageservice "0.28.10"
vue-count-to2@^1.0.6:
version "1.0.6"
resolved "https://registry.npmmirror.com/vue-count-to2/-/vue-count-to2-1.0.6.tgz#4685ef8d7867efc793a375d31af0155e012441e8"
integrity sha512-Mm56aA2nxgw/qTfU2XaauUh1W4bdM6lIeihhDIahQOGNUxVPVARyvLUbUFbOrynOJ5Ab26fuTguspX+xBGhVKw==
dependencies:
core-js "^3.8.1"
vue-count-to "^1.0.13"
vue-count-to@^1.0.13:
version "1.0.13"
resolved "https://registry.npmmirror.com/vue-count-to/-/vue-count-to-1.0.13.tgz#3e7573ea6e64c2b2972f64e0a2ab2e23c7590ff3"
integrity sha512-6R4OVBVNtQTlcbXu6SJ8ENR35M2/CdWt3Jmv57jOUM+1ojiFmjVGvZPH8DfHpMDSA+ITs+EW5V6qthADxeyYOQ==
vue-cropper@^0.5.6:
version "0.5.7"
resolved "https://registry.npmmirror.com/vue-cropper/download/vue-cropper-0.5.7.tgz#56103ada05996ec5dcc9f25d24eb7701fda9fe6c"
@ -11620,6 +11825,19 @@ vue-eslint-parser@^8.0.0:
lodash "^4.17.21"
semver "^7.3.5"
vue-grid-layout@^3.0.0-beta1:
version "3.0.0-beta1"
resolved "https://registry.npmmirror.com/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz#f8ce8eb7dbb1ff58f64820332afcc12c8cf873aa"
integrity sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==
dependencies:
"@interactjs/actions" "^1.10.2"
"@interactjs/auto-start" "^1.10.2"
"@interactjs/dev-tools" "^1.10.2"
"@interactjs/interactjs" "^1.10.2"
"@interactjs/modifiers" "^1.10.2"
element-resize-detector "^1.2.1"
mitt "^2.1.0"
vue-i18n@^9.1.9:
version "9.1.9"
resolved "https://registry.npmmirror.com/vue-i18n/download/vue-i18n-9.1.9.tgz?cache=0&sync_timestamp=1635872482815&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue-i18n%2Fdownload%2Fvue-i18n-9.1.9.tgz#cb53e06ab5cc5b7eed59332f151caf48d47be9bb"
@ -11641,9 +11859,9 @@ vue-json-pretty@^2.0.4:
integrity sha1-L25/WahODh70HdM2Y8Ph0alzSik=
vue-print-nb-jeecg@^1.0.10:
version "1.0.10"
resolved "https://registry.npmjs.org/vue-print-nb-jeecg/-/vue-print-nb-jeecg-1.0.10.tgz#d8d76342d053ac18c3b570ba6c4364ee9b93fa71"
integrity sha512-eP4lR7T8wNZ+/nZUOGG61+9UwNyTFQUYbcRkwgpOC8qEudepmGa+K9iGYzSrscx9G+E0YZDpIdlvAlIQoURCSA==
version "1.0.11"
resolved "https://packages.aliyun.com/60e053ce4690c27532d3dfd3/npm/npm-registry/vue-print-nb-jeecg/-/vue-print-nb-jeecg-1.0.11.tgz#63d1e0802facae02dd6482454debe998f6779d07"
integrity sha512-jp/7tnKm8A+vYsUqMY+8ODOi8WayjEYkf/r1Z7enUfMe3Rk9ytGIJonAhnwLBWMoH7mWndgMayOPMki1dFUlGA==
dependencies:
babel-plugin-transform-runtime "^6.23.0"
@ -11676,6 +11894,30 @@ vue-types@^4.1.1:
dependencies:
is-plain-object "5.0.0"
vue3-drag-test4@0.1.20:
version "0.1.20"
resolved "https://packages.aliyun.com/60e053ce4690c27532d3dfd3/npm/npm-registry/vue3-drag-test4/-/vue3-drag-test4-0.1.20.tgz#27bd632707a6428863facaed15bf9ca553fe18f5"
integrity sha512-RtAcE2jVZbsboe7sMVSmSK9PyYddiv+LeYSORnkUrAzOYxcZvzsxAKOJNkRhy5gxOKBqcKJ9K3t6Aqk6dEQxKQ==
dependencies:
"@fullcalendar/core" "^5.10.1"
"@fullcalendar/daygrid" "^5.10.1"
"@fullcalendar/interaction" "^5.10.1"
"@fullcalendar/timegrid" "^5.10.1"
"@fullcalendar/vue3" "^5.10.1"
"@types/echarts" "^4.9.12"
"@vueuse/core" "^6.6.2"
ant-design-vue "^2.2.8"
axios "^0.24.0"
codemirror "^5.65.0"
core-js "^3.6.5"
echarts "^5.2.2"
lodash-es "^4.17.21"
vue "^3.2.20"
vue-count-to2 "^1.0.6"
vue-grid-layout "^3.0.0-beta1"
xlsx "^0.17.3"
yarn "^1.22.17"
vue@^3.2.20:
version "3.2.21"
resolved "https://registry.npmmirror.com/vue/download/vue-3.2.21.tgz?cache=0&sync_timestamp=1635835999987&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue%2Fdownload%2Fvue-3.2.21.tgz#55f5665172d95cf97e806b9aad0a375180be23a1"
@ -11689,8 +11931,8 @@ vue@^3.2.20:
vuedraggable@^4.1.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz#edece68adb8a4d9e06accff9dfc9040e66852270"
integrity sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==
resolved "https://registry.nlark.com/vuedraggable/download/vuedraggable-4.1.0.tgz#edece68adb8a4d9e06accff9dfc9040e66852270"
integrity sha1-7ezmituKTZ4GrM/538kEDmaFInA=
dependencies:
sortablejs "1.14.0"
@ -11701,7 +11943,7 @@ vxe-table-plugin-antd@^3.0.3:
vxe-table@4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/vxe-table/-/vxe-table-4.1.0.tgz#6533ab768cada2e6743eaee801a5c7db54cc7581"
resolved "https://registry.npmmirror.com/vxe-table/-/vxe-table-4.1.0.tgz#6533ab768cada2e6743eaee801a5c7db54cc7581"
integrity sha512-FX4nc4ckkQGWG/W94z97KBIGrfZsbcni3pm+4uMzNQUcEgxgchnY78/4PrRC4ZRsHJIMv4mtNrzdfJDCTfA65g==
w3c-hr-time@^1.0.2:
@ -12203,6 +12445,11 @@ yargs@^17.0.0:
y18n "^5.0.5"
yargs-parser "^20.2.2"
yarn@^1.22.17:
version "1.22.18"
resolved "https://registry.npmmirror.com/yarn/-/yarn-1.22.18.tgz#05b822ade8c672987bab8858635145da0850f78a"
integrity sha512-oFffv6Jp2+BTUBItzx1Z0dpikTX+raRdqupfqzeMKnoh7WD6RuPAxcqDkMUy9vafJkrB0YaV708znpuMhEBKGQ==
yauzl@^2.4.2:
version "2.10.0"
resolved "https://registry.nlark.com/yauzl/download/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
@ -12228,6 +12475,13 @@ zrender@5.2.1:
dependencies:
tslib "2.3.0"
zrender@5.3.1:
version "5.3.1"
resolved "https://registry.npmmirror.com/zrender/-/zrender-5.3.1.tgz#fa8e63ac7e719cfd563831fe8c42a9756c5af384"
integrity sha512-7olqIjy0gWfznKr6vgfnGBk7y4UtdMvdwFmK92vVQsQeDPyzkHW1OlrLEKg6GHz1W5ePf0FeN1q2vkl/HFqhXw==
dependencies:
tslib "2.3.0"
zwitch@^1.0.0:
version "1.0.5"
resolved "https://registry.nlark.com/zwitch/download/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"