3.7.0大版本发布

pull/186/merge
JEECG 2024-06-12 00:01:27 +08:00
parent a9247d28a6
commit 894778a152
240 changed files with 11391 additions and 17305 deletions

4
.env
View File

@ -4,8 +4,8 @@ VITE_PORT = 3100
# 网站标题
VITE_GLOB_APP_TITLE = JeecgBoot 企业级低代码平台
# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符
VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin
# 简称,此变量只能是字符/下划线
VITE_GLOB_APP_SHORT_NAME = JeecgBoot_Pro
# 单点登录服务端地址
VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas

View File

@ -1,11 +1,11 @@
JEECG BOOT 低代码开发平台Vue3前端
===============
当前最新版本: 3.6.3发布时间2024-03-11
当前最新版本: 3.7.0发布时间2024-06-17
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://jeecg.com/aboutusIndex)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.6.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-3.7.0-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)

View File

@ -30,6 +30,8 @@ const demoList = (() => {
avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()),
imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1),
imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1),
age: Math.ceil(Math.random() * 30) + 1,
score: Math.ceil(Math.random() * 80) + 1,
date: `@date('yyyy-MM-dd')`,
time: `@time('HH:mm')`,
'no|100000-10000000': 100000,

View File

@ -1,6 +1,6 @@
{
"name": "jeecgboot-vue3",
"version": "3.6.3",
"version": "3.7.0",
"author": {
"name": "北京国炬信息技术有限公司",
"email": "jeecgos@163.com",
@ -25,12 +25,12 @@
"@iconify/iconify": "^3.1.1",
"@ant-design/colors": "^7.0.2",
"@ant-design/icons-vue": "^7.0.1",
"@vue/shared": "^3.3.4",
"@vueuse/core": "^10.7.1",
"@tinymce/tinymce-vue": "^4.0.7",
"@vue/shared": "^3.4.19",
"@vueuse/core": "^10.8.0",
"@tinymce/tinymce-vue": "4.0.7",
"@zxcvbn-ts/core": "^3.0.4",
"ant-design-vue": "^4.1.2",
"axios": "^1.6.4",
"axios": "^1.6.7",
"china-area-data": "^5.0.1",
"clipboard": "^2.0.11",
"codemirror": "^5.65.3",
@ -40,16 +40,16 @@
"dayjs": "^1.11.10",
"dom-align": "^1.12.4",
"echarts": "^5.4.3",
"emoji-mart-vue-fast": "^15.0.0",
"emoji-mart-vue-fast": "^15.0.1",
"enquire.js": "^2.1.6",
"intro.js": "^7.2.0",
"lodash-es": "^4.17.21",
"lodash.get": "^4.4.2",
"markdown-it": "^14.0.0",
"markdown-it-link-attributes": "^4.0.1",
"@traptitech/markdown-it-katex": "^3.6.0",
"event-source-polyfill": "^1.0.31",
"highlight.js": "^11.9.0",
"@traptitech/markdown-it-katex": "^3.6.0",
"md5": "^2.3.0",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
@ -60,49 +60,49 @@
"qrcode": "^1.5.3",
"resize-observer-polyfill": "^1.5.1",
"showdown": "^2.1.0",
"sortablejs": "^1.15.1",
"tinymce": "^6.6.2",
"vditor": "^3.9.8",
"vue": "^3.4.15",
"sortablejs": "^1.15.2",
"tinymce": "6.6.2",
"vditor": "^3.9.9",
"vue": "^3.4.19",
"vue-cropper": "^0.6.4",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.8.0",
"vue-i18n": "^9.9.1",
"vue-infinite-scroll": "^2.0.2",
"vue-print-nb-jeecg": "^1.0.12",
"vue-router": "^4.2.5",
"vue-router": "^4.3.0",
"vue-types": "^5.1.1",
"vuedraggable": "^4.1.0",
"vxe-table": "4.5.17",
"vxe-table-plugin-antd": "3.1.0",
"xe-utils": "3.5.14",
"vxe-table": "4.6.14",
"vxe-table-plugin-antd": "4.0.5",
"xe-utils": "3.5.26",
"xss": "^1.0.14"
},
"devDependencies": {
"@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^18.4.3",
"@iconify/json": "^2.2.164",
"@commitlint/cli": "^18.6.1",
"@commitlint/config-conventional": "^18.6.2",
"@iconify/json": "^2.2.185",
"@purge-icons/generated": "^0.10.0",
"@types/codemirror": "^5.60.15",
"@types/crypto-js": "^4.2.1",
"@types/crypto-js": "^4.2.2",
"@types/fs-extra": "^11.0.4",
"@types/inquirer": "^9.0.7",
"@types/intro.js": "^5.1.5",
"@types/jest": "^29.5.11",
"@types/jest": "^29.5.12",
"@types/lodash-es": "^4.17.12",
"@types/mockjs": "^1.0.10",
"@types/node": "^20.10.6",
"@types/node": "^20.11.19",
"@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.11",
"@types/showdown": "^2.0.6",
"@types/sortablejs": "^1.15.7",
"@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"@vitejs/plugin-vue": "^4.3.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.4.4",
"@vue/test-utils": "^2.4.3",
"autoprefixer": "^10.4.16",
"@vue/test-utils": "^2.4.4",
"autoprefixer": "^10.4.17",
"commitizen": "^4.3.0",
"conventional-changelog-cli": "^4.1.0",
"cross-env": "^7.0.3",
@ -112,48 +112,50 @@
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^2.1.0",
"eslint-plugin-jest": "^27.6.1",
"eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-vue": "^9.19.2",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-vue": "^9.21.1",
"esno": "^4.0.0",
"fs-extra": "^11.2.0",
"http-server": "^14.1.1",
"husky": "^8.0.3",
"inquirer": "^9.2.12",
"inquirer": "^9.2.15",
"is-ci": "^3.0.1",
"jest": "^29.7.0",
"less": "^4.2.0",
"lint-staged": "15.2.0",
"lint-staged": "15.2.2",
"npm-run-all": "^4.1.5",
"picocolors": "^1.0.0",
"postcss": "^8.4.32",
"postcss-html": "^1.5.0",
"postcss": "^8.4.35",
"postcss-html": "^1.6.0",
"postcss-less": "^6.0.0",
"prettier": "^3.1.1",
"pretty-quick": "^3.1.3",
"prettier": "^3.2.5",
"pretty-quick": "^4.0.0",
"rimraf": "^5.0.5",
"rollup": "^4.9.2",
"rollup": "^4.12.0",
"rollup-plugin-visualizer": "^5.12.0",
"stylelint": "^16.1.0",
"stylelint": "^16.2.1",
"stylelint-config-prettier": "^9.0.5",
"stylelint-config-recommended": "^14.0.0",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^36.0.0",
"stylelint-order": "^6.0.4",
"ts-jest": "^29.1.1",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^4.9.5",
"vite": "^4.4.9",
"vite": "^5.2.11",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.1",
"vite-plugin-mkcert": "^1.17.1",
"vite-plugin-html": "^3.2.2",
"vite-plugin-mkcert": "^1.17.3",
"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.10.0",
"vite-plugin-svg-icons": "^2.0.1",
"@rys-fe/vite-plugin-theme": "^0.8.6",
"vite-plugin-vue-setup-extend-plus": "^0.1.0",
"unocss": "^0.58.3",
"vue-eslint-parser": "^9.3.2",
"unocss": "^0.58.5",
"vue-eslint-parser": "^9.4.2",
"vue-tsc": "^1.8.27"
},
"repository": {

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,20 @@
const { getAntdLocale } = useLocale();
useTitle();
/**
* 2024-04-07
* liaozhiyang
* 暗黑模式下默认文字白色白天模式默认文字 #333
* */
const modeAction = (data) => {
if (data.token) {
if (getDarkMode.value === ThemeEnum.DARK) {
Object.assign(data.token, { colorTextBase: 'fff' });
} else {
Object.assign(data.token, { colorTextBase: '#333' });
}
}
};
// update-begin--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
const appTheme: any = ref({});
const { getDarkMode } = useRootSetting();
@ -40,6 +54,7 @@
changeTheme(appStore.getProjectConfig.themeColor);
}
// update-end--author:liaozhiyang---date:20240322---forQQYUN-8570
modeAction(appTheme.value);
appTheme.value = {
...appTheme.value,
};
@ -50,23 +65,28 @@
appStore.getProjectConfig,
(newValue) => {
const primary = newValue.themeColor;
appTheme.value = {
const result = {
...appTheme.value,
...{
token: {
colorPrimary: primary,
wireframe: true,
fontSize: 14,
colorTextBase: '#333',
colorSuccess: '#55D187',
colorInfo: primary,
borderRadius: 2,
borderRadius: 4,
sizeStep: 4,
sizeUnit: 4,
colorWarning: '#EFBD47',
colorError: '#ED6F6F',
fontFamily:
'-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol',
},
},
};
appTheme.value = result;
modeAction(result);
},
{ immediate: true }
);
@ -74,6 +94,7 @@
appStore.getProjectConfig?.themeColor && changeTheme(appStore.getProjectConfig.themeColor);
}, 300);
// update-end--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
</script>
<style lang="less">
// update-begin--author:liaozhiyang---date:20230803---forQQYUN-5839windihtml2canvas

View File

@ -8,6 +8,7 @@ import { setAuthCache } from '/@/utils/auth';
import { TOKEN_KEY } from '/@/enums/cacheEnum';
import { router } from '/@/router';
import { PageEnum } from '/@/enums/pageEnum';
import { ExceptionEnum } from "@/enums/exceptionEnum";
const { createErrorModal } = useMessage();
enum Api {
@ -123,8 +124,13 @@ export function getCaptcha(params) {
if (res.success) {
resolve(true);
} else {
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject();
//update-begin---author:wangshuai---date:2024-04-18---for:【QQYUN-9005】同一个IP1分钟超过5次短信则提示需要验证码---
if(res.code != ExceptionEnum.PHONE_SMS_FAIL_CODE){
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject();
}
reject(res);
//update-end---author:wangshuai---date:2024-04-18---for:【QQYUN-9005】同一个IP1分钟超过5次短信则提示需要验证码---
}
}).catch((res)=>{
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1713356465646" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5683" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M320.067666 286.437731c53.150524-53.15564 126.532835-86.077447 207.455889-86.077447 89.598644 0 172.483376 40.805358 227.39501 108.063181l-101.596909 101.603049 251.597225 0L904.918881 158.424172l-90.333378 90.361007C743.985562 166.207439 639.765919 116.493178 527.524578 116.493178c-104.055914 0-198.409862 42.322921-266.757506 110.670565-49.444109 49.455365-84.98865 112.251573-100.999298 182.862771l86.263689 0C260.052804 362.352725 285.750069 320.744072 320.067666 286.437731L320.067666 286.437731z" fill="#272636" p-id="5684"></path><path d="M734.974327 701.344393c-53.151547 53.15564-126.533858 86.083587-207.450772 86.083587-89.599667 0-172.488493-40.810474-227.402173-108.069321l101.603049-101.596909L150.122089 577.76175 150.122089 829.358975l90.333378-90.333378c70.601988 82.555228 174.820608 132.270513 287.067065 132.270513 104.055914 0 198.402699-42.306548 266.750343-110.650099 49.360198-49.397037 84.866876-112.477724 100.920504-182.883237L808.689213 577.762773C794.560424 624.99654 768.983909 667.338904 734.974327 701.344393L734.974327 701.344393z" fill="#272636" p-id="5685"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -6,7 +6,7 @@
<div class="anticon" :class="getAppLogoClass" @click="goHome">
<img src="../../../assets/images/logo.png" />
<div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
{{ title }}
{{ shortTitle }}
</div>
</div>
</template>
@ -37,7 +37,8 @@
const { prefixCls } = useDesign('app-logo');
const { getCollapsedShowTitle } = useMenuSetting();
const userStore = useUserStore();
const { title } = useGlobSetting();
const { title, shortTitle } = useGlobSetting();
const go = useGo();
const getAppLogoClass = computed(() => [prefixCls, props.theme, { 'collapsed-show-title': unref(getCollapsedShowTitle) }]);
@ -83,8 +84,8 @@
}
&__title {
font-size: 16px;
font-weight: 700;
font-size: 18px;
font-weight: 600;
transition: all 0.5s;
line-height: normal;
}

View File

@ -7,6 +7,7 @@ import { useGo } from '/@/hooks/web/usePage';
import { useScrollTo } from '/@/hooks/event/useScrollTo';
import { onKeyStroke, useDebounceFn } from '@vueuse/core';
import { useI18n } from '/@/hooks/web/useI18n';
import { URL_HASH_TAB } from '/@/utils';
export interface SearchResult {
name: string;
@ -154,7 +155,10 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
// update-begin--author:liaozhiyang---date:20230803---for【QQYUN-8369】搜索区分大小写外部链接新页打开
if (to.internalOrExternal) {
window.open(to.path, '_blank');
// update-begin--author:liaozhiyang---date:20240402---for:【QQYUN-8773】配置外部网址在顶部菜单模式和搜索打不开
const path = to.path.replace(URL_HASH_TAB, '#');
window.open(path, '_blank');
// update-end--author:liaozhiyang---date:20240402---for:【QQYUN-8773】配置外部网址在顶部菜单模式和搜索打不开
} else {
go(to.path);
}

View File

@ -2,6 +2,8 @@
<Button v-bind="$attrs" :disabled="isStart" @click="handleStart" :loading="loading">
{{ getButtonText }}
</Button>
<!-- 图片验证码弹窗 -->
<CaptchaModal @register="captchaRegisterModal" @ok="handleStart" />
</template>
<script lang="ts">
import { defineComponent, ref, watchEffect, computed, unref } from 'vue';
@ -9,6 +11,11 @@
import { useCountdown } from './useCountdown';
import { isFunction } from '/@/utils/is';
import { useI18n } from '/@/hooks/web/useI18n';
import { useModal } from "@/components/Modal";
import { createAsyncComponent } from "@/utils/factory/createAsyncComponent";
import { ExceptionEnum } from "@/enums/exceptionEnum";
const CaptchaModal = createAsyncComponent(() => import('/@/components/jeecg/captcha/CaptchaModal.vue'));
const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
const props = {
value: { type: [Object, Number, String, Array] },
@ -21,7 +28,7 @@
export default defineComponent({
name: 'CountButton',
components: { Button },
components: { Button, CaptchaModal },
props,
setup(props) {
const loading = ref(false);
@ -45,7 +52,13 @@
if (beforeStartFunc && isFunction(beforeStartFunc)) {
loading.value = true;
try {
const canStart = await beforeStartFunc();
//update-begin---author:wangshuai---date:2024-04-18---for:QQYUN-9005IP15---
const canStart = await beforeStartFunc().catch((res) =>{
if(res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE){
openCaptchaModal(true, {});
}
});
//update-end---author:wangshuai---date:2024-04-18---for:QQYUN-9005IP15---
canStart && start();
} finally {
loading.value = false;
@ -54,7 +67,7 @@
start();
}
}
return { handleStart, currentCount, loading, getButtonText, isStart };
return { handleStart, currentCount, loading, getButtonText, isStart, captchaRegisterModal };
},
});
</script>

View File

@ -35,6 +35,7 @@
import { basicProps } from './props';
import { useDesign } from '/@/hooks/web/useDesign';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { cloneDeep } from 'lodash-es';
export default defineComponent({
components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader },
@ -59,9 +60,9 @@
instance && emit('register', drawerInstance, instance.uid);
const getMergeProps = computed((): DrawerProps => {
// update-begin--author:liaozhiyang---date:20240320---forQQYUN-8389vue3.4footertoRow,propscomputed
return { ...deepMerge(props, unref(propsRef)) };
// update-end--author:liaozhiyang---date:20240320---forQQYUN-8389vue3.4footertoRow,propscomputed
// update-begin--author:liaozhiyang---date:20240320---forQQYUN-8389vue3.4footertoRawcloneDeeppropscomputed
return { ...deepMerge(cloneDeep(props), unref(propsRef)) };
// update-end--author:liaozhiyang---date:20240320---forQQYUN-8389vue3.4footertoRawcloneDeeppropscomputed
});
const getProps = computed((): DrawerProps => {
@ -88,6 +89,7 @@
opt.getContainer = `.${prefixVar}-layout-content` as any;
}
}
console.log('getProps:opt',opt);
return opt as DrawerProps;
});

View File

@ -12,6 +12,8 @@
:formModel="formModel"
:setFormModel="setFormModel"
:validateFields="validateFields"
:clearValidate="clearValidate"
v-auth="schema.auth"
>
<template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data || {}"></slot>
@ -109,6 +111,7 @@
prefixCls,
{
[`${prefixCls}--compact`]: unref(getProps).compact,
'jeecg-form-detail-effect': unref(getProps).disabled
},
];
});
@ -142,7 +145,10 @@
if (!Array.isArray(defaultValue)) {
//update-begin---author:wangshuai ---date:20221124 for[issues/215]------------
if(valueFormat){
schema.defaultValue = dateUtil(defaultValue).format(valueFormat);
// schema.defaultValue = dateUtil(defaultValue).format(valueFormat);
// update-begin--author:liaozhiyang---date:20240529---forTV360X-346
schema.defaultValue = dateUtil(defaultValue, valueFormat).format(valueFormat);
// update-end--author:liaozhiyang---date:20240529---forTV360X-346
}else{
schema.defaultValue = dateUtil(defaultValue);
}
@ -152,7 +158,9 @@
defaultValue.forEach((item) => {
//update-begin---author:wangshuai ---date:20221124 for[issues/215]------------
if(valueFormat){
def.push(dateUtil(item).format(valueFormat));
// update-begin--author:liaozhiyang---date:20240529---forTV360X-346
def.push(dateUtil(item, valueFormat).format(valueFormat));
// update-end--author:liaozhiyang---date:20240529---forTV360X-346
}else{
def.push(dateUtil(item));
}
@ -346,10 +354,11 @@
&-with-help {
margin-bottom: 0;
}
&:not(.ant-form-item-with-help) {
margin-bottom: 20px;
}
// update-begin--author:liaozhiyang---date:20240514---forQQYUN-9241form
//&:not(.ant-form-item-with-help) {
// margin-bottom: 24px;
//}
// update-begin--author:liaozhiyang---date:20240514---forQQYUN-9241form
&.suffix-item {
.ant-form-item-children {
@ -370,7 +379,7 @@
}
}
/*【美化表单】form的字体改小一号*/
.ant-form-item-label > label{
/* .ant-form-item-label > label{
font-size: 13px;
}
.ant-form-item .ant-select {
@ -384,7 +393,7 @@
}
.ant-input {
font-size: 13px;
}
}*/
/*【美化表单】form的字体改小一号*/
.ant-form-explain {

View File

@ -45,7 +45,7 @@ import JImageUpload from './jeecg/components/JImageUpload.vue';
import JDictSelectTag from './jeecg/components/JDictSelectTag.vue';
import JSelectDept from './jeecg/components/JSelectDept.vue';
import JAreaSelect from './jeecg/components/JAreaSelect.vue';
// import JEditor from './jeecg/components/JEditor.vue';
import JEditor from './jeecg/components/JEditor.vue';
// import JMarkdownEditor from './jeecg/components/JMarkdownEditor.vue';
import JSelectInput from './jeecg/components/JSelectInput.vue';
// import JCodeEditor from './jeecg/components/JCodeEditor.vue';
@ -72,7 +72,9 @@ import JRangeNumber from './jeecg/components/JRangeNumber.vue';
import UserSelect from './jeecg/components/userSelect/index.vue';
import JRangeDate from './jeecg/components/JRangeDate.vue'
import JRangeTime from './jeecg/components/JRangeTime.vue'
import JInputSelect from './jeecg/components/JInputSelect.vue'
import RoleSelectInput from './jeecg/components/roleSelect/RoleSelectInput.vue';
import {DatePickerInFilter, CascaderPcaInFilter} from "@/components/InFilter";
const componentMap = new Map<ComponentType, Component>();
@ -104,6 +106,7 @@ componentMap.set('MonthPicker', DatePicker.MonthPicker);
componentMap.set('RangePicker', DatePicker.RangePicker);
componentMap.set('WeekPicker', DatePicker.WeekPicker);
componentMap.set('TimePicker', TimePicker);
componentMap.set('DatePickerInFilter', DatePickerInFilter);
componentMap.set('StrengthMeter', StrengthMeter);
componentMap.set('IconPicker', IconPicker);
componentMap.set('InputCountDown', CountdownInput);
@ -112,6 +115,7 @@ componentMap.set('Upload', BasicUpload);
componentMap.set('Divider', Divider);
//注册自定义组件
componentMap.set(
'JAreaLinkage',
createAsyncComponent(() => import('./jeecg/components/JAreaLinkage.vue'))
@ -123,10 +127,11 @@ componentMap.set('JImageUpload', JImageUpload);
componentMap.set('JDictSelectTag', JDictSelectTag);
componentMap.set('JSelectDept', JSelectDept);
componentMap.set('JAreaSelect', JAreaSelect);
componentMap.set(
'JEditor',
createAsyncComponent(() => import('./jeecg/components/JEditor.vue'))
);
// componentMap.set(
// 'JEditor',
// createAsyncComponent(() => import('./jeecg/components/JEditor.vue'))
// );
componentMap.set('JEditor', JEditor);
componentMap.set(
'JMarkdownEditor',
createAsyncComponent(() => import('./jeecg/components/JMarkdownEditor.vue'))
@ -158,10 +163,12 @@ componentMap.set('JUpload', JUpload);
componentMap.set('JSearchSelect', JSearchSelect);
componentMap.set('JAddInput', JAddInput);
componentMap.set('JRangeNumber', JRangeNumber);
componentMap.set('CascaderPcaInFilter', CascaderPcaInFilter);
componentMap.set('UserSelect', UserSelect);
componentMap.set('RangeDate', JRangeDate);
componentMap.set('RangeTime', JRangeTime);
componentMap.set('RoleSelect', RoleSelectInput);
componentMap.set('JInputSelect', JInputSelect);

View File

@ -16,7 +16,8 @@
import { useItemLabelWidth } from '../hooks/useLabelWidth';
import { useI18n } from '/@/hooks/web/useI18n';
import { useAppInject } from '/@/hooks/web/useAppInject';
import { usePermission } from '/@/hooks/web/usePermission';
import Middleware from './Middleware.vue';
export default defineComponent({
name: 'BasicFormItem',
inheritAttrs: false,
@ -51,6 +52,12 @@
formActionType: {
type: Object as PropType<FormActionType>,
},
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857
clearValidate: {
type: Function,
default: null,
},
// update-end-author:liaozhiyang---date:20240605---forTV360X-857
},
setup(props, { slots }) {
const { t } = useI18n();
@ -93,6 +100,11 @@
const getDisable = computed(() => {
const { disabled: globDisabled } = props.formProps;
// update-begin--author:liaozhiyang---date:20240530---forTV360X-594dynamicDisabled
if (!!globDisabled) {
return globDisabled;
}
// update-end--author:liaozhiyang---date:20240530---forTV360X-594dynamicDisabled
const { dynamicDisabled } = props.schema;
const { disabled: itemDisabled = false } = unref(getComponentsProps);
let disabled = !!globDisabled || itemDisabled;
@ -144,12 +156,62 @@
isShow = isShow && itemIsAdvanced;
return { isShow, isIfShow };
}
// update-begin--author:liaozhiyang---date:20240530---forTV360X-434validator
let vSwitchArr: any = [],
prevValidatorArr: any = [];
const hijackValidator = (rules) => {
vSwitchArr = [];
prevValidatorArr = [];
rules.forEach((item, index) => {
const fn = item.validator;
vSwitchArr.push(true);
prevValidatorArr.push(null);
if (isFunction(fn)) {
item.validator = (rule, value, callback) => {
if (vSwitchArr[index]) {
vSwitchArr[index] = false;
setTimeout(() => {
vSwitchArr[index] = true;
}, 100);
const result = fn(rule, value, callback);
prevValidatorArr[index] = result;
return result;
} else {
return prevValidatorArr[index];
}
};
}
});
};
// update-end--author:liaozhiyang---date:20240530---forTV360X-434validator
function handleRules(): ValidationRule[] {
const { rules: defRules = [], component, rulesMessageJoinLabel, label, dynamicRules, required } = props.schema;
const { rules: defRules = [], component, rulesMessageJoinLabel, label, dynamicRules, required, auth, field } = props.schema;
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857
const { disabled: globDisabled } = props.formProps;
const { disabled: itemDisabled = false } = unref(getComponentsProps);
if (!!globDisabled || !!itemDisabled) {
props.clearValidate(field);
return [];
}
// update-end--author:liaozhiyang---date:20240605---forTV360X-857
// update-begin--author:liaozhiyang---date:20240531---forTV360X-842v-authshow
const { hasPermission } = usePermission();
const { isShow } = getShow();
if ((auth && !hasPermission(auth)) || !isShow) {
return [];
}
// update-end--author:liaozhiyang---date:20240531---forTV360X-842v-authshow
if (isFunction(dynamicRules)) {
return dynamicRules(unref(getValues)) as ValidationRule[];
// update-begin--author:liaozhiyang---date:20240514---forissues/1244
const ruleArr = dynamicRules(unref(getValues)) as ValidationRule[];
if (required) {
ruleArr.unshift({ required: true });
}
// update-begin--author:liaozhiyang---date:20240530---forTV360X-434validator
hijackValidator(ruleArr);
// update-end--author:liaozhiyang---date:20240530---forTV360X-434validator
return ruleArr;
// update-end--author:liaozhiyang---date:20240514---forissues/1244
}
let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
@ -237,11 +299,14 @@
}
});
// update-end--author:liaozhiyang---date:20231226---forQQYUN-7495patternantd使InputNumber
// update-begin--author:liaozhiyang---date:20240530---forTV360X-434validator
hijackValidator(rules);
// update-end--author:liaozhiyang---date:20240530---forTV360X-434validator
return rules;
}
function renderComponent() {
const { renderComponentContent, component, field, changeEvent = 'change', valueField, componentProps } = props.schema;
const { renderComponentContent, component, field, changeEvent = 'change', valueField, componentProps, dynamicRules } = props.schema;
const isCheck = component && ['Switch', 'Checkbox'].includes(component);
// update-begin--author:liaozhiyang---date:20231013---forQQYUN-6679input
@ -272,7 +337,9 @@
}
// update-end--author:liaozhiyang---date:20231013---forQQYUN-6679input
props.setFormModel(field, value);
//props.validateFields([field], { triggerName: 'change' }).catch((_) => {});
// update-begin--author:liaozhiyang---date:20240522---forTV360X-341
props.validateFields([field]).catch((_) => {});
// update-end--author:liaozhiyang---date:20240522--forTV360X-341
},
// onBlur: () => {
// props.validateFields([field], { triggerName: 'blur' }).catch((_) => {});
@ -338,9 +405,11 @@
//label
const { label, helpMessage, helpComponentProps, subLabel, labelLength } = props.schema;
let showLabel: string = label + '';
if (labelLength && showLabel.length > 4) {
// update-begin--author:liaozhiyang---date:20240517---forTV360X-98labellabelLength
if (labelLength) {
showLabel = showLabel.substr(0, labelLength);
}
// update-end--author:liaozhiyang---date:20240517---forTV360X-98labellabelLength
const titleObj = { title: label };
const renderLabel = subLabel ? (
<span>
@ -391,12 +460,17 @@
{...(itemProps as Recordable)}
label={renderLabelHelpMessage()}
rules={handleRules()}
// update-begin--author:liaozhiyang---date:20240514---forissues/1244
validateFirst = { true }
// update-end--author:liaozhiyang---date:20240514---forissues/1244
labelCol={labelCol}
wrapperCol={wrapperCol}
>
<div style="display:flex">
{/* author: sunjianlei for: 【VUEN-744】此处加上 width: 100%; 因为要防止组件宽度超出 FormItem */}
<div style="flex:1; width: 100%;">{getContent()}</div>
{/* update-begin--author:liaozhiyang---date:20240510---for【TV360X-719】表单校验不通过项滚动到可视区内 */}
<Middleware>{getContent()}</Middleware>
{/* update-end--author:liaozhiyang---date:20240510---for【TV360X-719】表单校验不通过项滚动到可视区内 */}
{showSuffix && <span class="suffix">{getSuffix}</span>}
</div>
</Form.Item>

View File

@ -0,0 +1,16 @@
<template>
<div :id="formItemId" style="flex: 1; width: 100%">
<slot></slot>
</div>
</template>
<script setup>
import { Form } from 'ant-design-vue';
import { computed } from 'vue';
const formItemContext = Form.useInjectFormItemContext();
const formItemId = computed(() => {
return formItemContext.id.value;
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,204 @@
<template>
<div :class="formDisabled ? 'jeecg-form-container-disabled jeecg-form-detail-effect' : ''">
<fieldset :disabled="formDisabled">
<slot name="detail"></slot>
</fieldset>
<slot name="edit"> </slot>
<fieldset disabled>
<slot></slot>
</fieldset>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
export default defineComponent({
name: 'JForm',
props: {
disabled: {
type: Boolean,
default: false,
required: false,
},
},
setup(props, { emit }) {
const formDisabled = ref<boolean>(props.disabled);
watch(
() => props.disabled,
(value) => {
formDisabled.value = value;
}
);
return {
formDisabled,
};
},
});
</script>
<style scoped lang="less">
.jeecg-form-container-disabled {
cursor: not-allowed;
}
.jeecg-form-container-disabled fieldset[disabled] {
-ms-pointer-events: none;
pointer-events: none;
}
.jeecg-form-container-disabled :deep(.ant-select) {
-ms-pointer-events: none;
pointer-events: none;
}
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857online
// begin antdv
// .jeecg-form-container-disabled :deep(.ant-input-number),
// .jeecg-form-container-disabled :deep(.ant-input),
// .jeecg-form-container-disabled :deep(.ant-input-password),
// .jeecg-form-container-disabled :deep(.ant-select-single .ant-select-selector),
// .jeecg-form-container-disabled :deep(.ant-radio-wrapper .ant-radio-checked .ant-radio-inner),
// .jeecg-form-container-disabled :deep(.ant-switch),
// .jeecg-form-container-disabled :deep(.ant-picker),
// .jeecg-form-container-disabled :deep(.ant-select:not(.ant-select-customize-input) .ant-select-selector),
// .jeecg-form-container-disabled :deep(.ant-input-affix-wrapper),
// .jeecg-form-container-disabled :deep(.tox .tox-toolbar__group),
// .jeecg-form-container-disabled :deep(.tox .tox-edit-area__iframe),
// .jeecg-form-container-disabled :deep(.vditor-toolbar),
// .jeecg-form-container-disabled :deep(.vditor-preview),
// .jeecg-form-container-disabled :deep(.jeecg-tinymce-img-upload) {
// background: rgba(51, 51, 51, 0.04);
// }
// .jeecg-form-container-disabled :deep(.ant-radio-wrapper),
// .jeecg-form-container-disabled :deep(.ant-checkbox-wrapper),
// .jeecg-form-container-disabled :deep(.ant-btn) {
// color: rgba(0, 0, 0, 0.65);
// }
// .jeecg-form-container-disabled :deep(.ant-radio-wrapper .ant-radio-inner:after),
// .jeecg-form-container-disabled :deep(.ant-checkbox-checked .ant-checkbox-inner) {
// background-color: rgba(51, 51, 51, 0.25);
// }
// .jeecg-form-container-disabled :deep(.ant-radio-inner),
// .jeecg-form-container-disabled :deep(.ant-checkbox-inner) {
// border-color: rgba(51, 51, 51, 0.25) !important;
// }
// .jeecg-form-container-disabled :deep(.ant-input-password > .ant-input),
// .jeecg-form-container-disabled :deep(.ant-input-affix-wrapper .ant-input) {
// background: none;
// }
html[data-theme='light'] {
.jeecg-form-detail-effect {
:deep(.ant-select-selector),
:deep(.ant-btn),
:deep(.ant-input),
:deep(.ant-input-affix-wrapper),
:deep(.ant-picker),
:deep(.ant-input-number) {
color: rgba(51, 51, 51, 0.25) !important;
}
:deep(.ant-select) {
color: rgba(51, 51, 51, 0.25) !important;
}
:deep(.ant-select-selection-item-content),:deep(.ant-select-selection-item),:deep(input) {
color: rgba(51, 51, 51, 0.25) !important;
}
:deep(.ant-radio-wrapper),
:deep(.ant-checkbox-wrapper),
:deep(.ant-btn) {
color: rgba(0, 0, 0, 0.65);
}
:deep(.ant-radio-wrapper .ant-radio-inner:after),
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
background-color: rgba(51, 51, 51, 0.25);
}
:deep(.ant-radio-inner),
:deep(.ant-checkbox-inner) {
border-color: rgba(51, 51, 51, 0.25) !important;
background-color: rgba(51, 51, 51, 0.04) !important;
}
:deep(.ant-checkbox-checked .ant-checkbox-inner::after), :deep(.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after){
border-color: rgba(51, 51, 51, 0.25) !important;
}
:deep(.ant-switch) {
background-color: rgba(51, 51, 51, 0.25);
}
:deep(.tox .tox-toolbar__group),
:deep(.tox .tox-edit-area__iframe),
:deep(.vditor-toolbar),
:deep(.vditor-preview),
:deep(.jeecg-tinymce-img-upload) {
background: rgba(51, 51, 51, 0.04);
}
}
}
html[data-theme='dark'] {
.jeecg-form-detail-effect {
:deep(.ant-select-selector),
:deep(.ant-btn),
:deep(.ant-input),
:deep(.ant-input-affix-wrapper),
:deep(.ant-picker),
:deep(.ant-input-number) {
color: rgba(255, 255, 255, 0.25) !important;
background-color: rgba(255, 255, 255, 0.08) !important;
}
:deep(.ant-select) {
color: rgba(255, 255, 255, 0.25) !important;
}
:deep(.ant-select-selection-item-content),:deep(.ant-select-selection-item),:deep(input) {
color: rgba(255, 255, 255, 0.25) !important;
}
:deep(.ant-radio-wrapper),
:deep(.ant-checkbox-wrapper){
color: rgba(255, 255, 255, 0.25);
}
:deep(.ant-radio-wrapper .ant-radio-inner:after),
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
background-color: rgba(255, 255, 255, 0.08);
}
:deep(.ant-radio-inner),
:deep(.ant-checkbox-inner) {
border-color: #424242 !important;
background-color: rgba(255, 255, 255, 0.08);
}
:deep(.ant-switch) {
background-color: rgba(51, 51, 51, 0.25);
opacity: 0.65;
}
:deep(.tox .tox-toolbar__group),
:deep(.tox .tox-edit-area__iframe),
:deep(.vditor-toolbar),
:deep(.vditor-preview),
:deep(.jeecg-tinymce-img-upload) {
background: rgba(51, 51, 51, 0.04);
}
}
}
// end antdv
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857online
.jeecg-form-container-disabled :deep(.ant-upload-select) {
cursor: grabbing;
}
.jeecg-form-container-disabled :deep(.ant-upload-list) {
cursor: grabbing;
}
.jeecg-form-container-disabled fieldset[disabled] :deep(.ant-upload-list){
// -ms-pointer-events: auto !important;
// pointer-events: auto !important;
}
.jeecg-form-container-disabled fieldset[disabled] iframe {
-ms-pointer-events: auto !important;
pointer-events: auto !important;
}
.jeecg-form-container-disabled :deep(.ant-upload-list-item-actions .anticon-delete),
.jeecg-form-container-disabled :deep(.ant-upload-list-item .anticon-close) {
display: none;
}
.jeecg-form-container-disabled :deep(.vditor-sv) {
display: none !important;
background: rgba(51, 51, 51, 0.04);
}
</style>

View File

@ -74,9 +74,11 @@ export function handleInputNumberValue(component?: ComponentType, val?: any) {
*/
export function handleInputStringValue(component?: ComponentType, val?: any) {
if (!component) return val;
if (['InputNumber'].includes(component) && typeof val === 'string') {
// update-begin--author:liaozhiyang---date:20240517---for【TV360X-13】InputNumber设置精确3位小数传入''变成了0.00
if (['InputNumber'].includes(component) && typeof val === 'string' && val != '') {
return Number(val);
}
// update-end--author:liaozhiyang---date:20240517---for【TV360X-13】InputNumber设置精确3位小数传入''变成了0.00
return val;
}

View File

@ -1,5 +1,5 @@
<template>
<Cascader v-bind="attrs" :value="state" :options="getOptions" @change="handleChange" />
<Cascader v-bind="attrs" :value="cascaderValue" :options="getOptions" @change="handleChange" />
</template>
<script lang="ts">
import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted } from 'vue';
@ -8,6 +8,8 @@
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { isArray } from '/@/utils/is';
export default defineComponent({
name: 'JAreaLinkage',
components: {
@ -20,12 +22,15 @@
showArea: propTypes.bool.def(true),
//
showAll: propTypes.bool.def(false),
//
saveCode: propTypes.oneOf(['province', 'city', 'region', 'all']).def('all'),
},
emits: ['options-change', 'change'],
setup(props, { emit, refs }) {
const emitData = ref<any[]>([]);
const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
// const [state] = useRuleFormItem(props, 'value', 'change', emitData);
const cascaderValue = ref([]);
const getOptions = computed(() => {
if (props.showArea && props.showAll) {
return regionDataPlus;
@ -52,20 +57,59 @@
*/
function initValue() {
let value = props.value ? props.value : [];
// update-begin--author:liaozhiyang---date:20240607---forTV360X-501
if (value && typeof value === 'string' && value != 'null' && value != 'undefined') {
state.value = value.split(',');
const arr = value.split(',');
cascaderValue.value = transform(arr);
} else if (isArray(value)) {
cascaderValue.value = transform(value);
}
// update-end--author:liaozhiyang---date:20240607---forTV360X-501
}
function handleChange(array, ...args) {
function transform(arr) {
let result: any = [];
if (props.saveCode === 'region') {
// 81 82
const regionCode = arr[0];
if (['82', '81'].includes(regionCode.substring(0, 2))) {
result = [`${regionCode.substring(0, 2)}0000`, regionCode];
} else {
result = [`${regionCode.substring(0, 2)}0000`, `${regionCode.substring(0, 2)}${regionCode.substring(2, 4)}00`, regionCode];
}
} else if (props.saveCode === 'city') {
const cityCode = arr[0];
result = [`${cityCode.substring(0, 2)}0000`, cityCode];
} else if (props.saveCode === 'province') {
const provinceCode = arr[0];
result = [provinceCode];
} else {
result = arr;
}
return result;
}
function handleChange(arr, ...args) {
// update-begin--author:liaozhiyang---date:20240607---forTV360X-501
let result: any = [];
if (props.saveCode === 'region') {
//
result = [arr[arr.length - 1]];
} else if (props.saveCode === 'city') {
result = [arr[1]];
} else if (props.saveCode === 'province') {
result = [arr[0]];
} else {
result = arr;
}
emit('change', result);
// update-end--author:liaozhiyang---date:20240607---forTV360X-501
// emitData.value = args;
//update-begin-author:taoyan date:2022-6-27 for: VUEN-1424vue3jvxeerp
// v-model:value
state.value = array;
// state.value = result;
//update-end-author:taoyan date:2022-6-27 for: VUEN-1424vue3jvxeerp
}
return {
state,
cascaderValue,
attrs,
regionData,
getOptions,

View File

@ -16,7 +16,7 @@
</a-tree-select>
</template>
<script lang="ts">
import { defineComponent, ref, unref, watch } from 'vue';
import { defineComponent, ref, unref, watch, nextTick } from 'vue';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
@ -78,7 +78,7 @@
const treeData = ref<any[]>([]);
const treeValue = ref();
const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
const [state, , , formItemContext] = useRuleFormItem(props, 'value', 'change', emitData);
watch(
() => props.value,
() => {
@ -218,6 +218,11 @@
backValue(value.value, value.label);
treeValue.value = value;
}
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
}
function getCurrTreeData() {

View File

@ -42,12 +42,16 @@
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/show-hint.js';
import 'codemirror/addon/hint/anyword-hint.js';
//
import 'codemirror/addon/edit/matchbrackets';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useDesign } from '/@/hooks/web/useDesign';
import { isJsonObjectString } from '/@/utils/is.ts';
//
import { useCodeHinting } from '../hooks/useCodeHinting';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { ThemeEnum } from '/@/enums/appEnum';
export default defineComponent({
name: 'JCodeEditor',
// attrs html
@ -68,6 +72,7 @@
},
emits: ['change', 'update:value'],
setup(props, { emit }) {
const { getDarkMode } = useRootSetting();
const containerRef = ref(null);
const { prefixCls } = useDesign('code-editer');
const CodeMirror = window.CodeMirror || _CodeMirror;
@ -82,7 +87,9 @@
//
tabSize: 2,
// JS
theme: props.theme,
// update-begin--author:liaozhiyang---date:20240327---forQQYUN-8639
theme: getDarkMode.value == ThemeEnum.DARK ? 'monokai' : props.theme,
// update-end--author:liaozhiyang---date:20240327---forQQYUN-8639
smartIndent: true, //
//
lineNumbers: true,
@ -97,13 +104,19 @@
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
mode: props.language,
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
//
// update-begin--author:liaozhiyang---date:20240603---forTV360X-898
readOnly: props.disabled,
// update-end--author:liaozhiyang---date:20240603---forTV360X-898
//
matchBrackets: true,
extraKeys: {
Tab: function autoFormat(editor) {
//var totalLines = editor.lineCount();
//editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
setValue(innerValue, false);
},
// Tab: function autoFormat(editor) {
// //var totalLines = editor.lineCount();
// //editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
// setValue(innerValue, false);
// },
'Cmd-/': (cm) => comment(cm),
'Ctrl-/': (cm) => comment(cm),
},
});
// props.value
@ -146,6 +159,11 @@
);
onMounted(() => {
initialize();
// update-begin--author:liaozhiyang---date:20240318---forQQYUN-8473
setTimeout(() => {
refresh();
}, 150);
// update-end--author:liaozhiyang---date:20240318---forQQYUN-8473
});
/**
@ -160,6 +178,15 @@
coder?.setValue(value ?? '');
innerValue = value;
trigger && emitChange(innerValue);
// update-begin--author:liaozhiyang---date:20240510---forQQYUN-9231
setTimeout(() => {
refresh();
//
setTimeout(() => {
refresh();
}, 600);
}, 400);
// update-end--author:liaozhiyang---date:20240510---forQQYUN-9231
}
//
@ -221,6 +248,24 @@
}
//update-end-author:taoyan date:2022-10-18 for: VUEN-2480bugonline vue3 8online js
/**
* 2024-04-01
* liaozhiyang
* 代码批量注释
*/
function comment(cm) {
var selection = cm.getSelection();
var start = cm.getCursor('start');
var end = cm.getCursor('end');
var isCommented = selection.startsWith('//');
if (isCommented) {
//
cm.replaceRange(selection.replace(/\n\/\/\s/g, '\n').replace(/^\/\/\s/, ''), start, end);
} else {
//
cm.replaceRange('// ' + selection.replace(/\n(?=.)/g, '\n// '), start, end);
}
}
return {
state,
@ -312,9 +357,19 @@
border: 1px solid #ddd;
}
}
.CodeMirror-hints.idea {
.CodeMirror-hints.idea,
.CodeMirror-hints.monokai {
z-index: 1001;
max-width: 600px;
max-height: 300px;
}
// update-begin--author:liaozhiyang---date:20240327---forQQYUN-8639
html[data-theme='dark'] {
.@{prefix-cls} {
.CodeMirror {
border: 1px solid #3a3a3a;
}
}
}
// update-end--author:liaozhiyang---date:20240327---forQQYUN-8639
</style>

View File

@ -3,10 +3,11 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
import { computed, defineComponent, nextTick } from 'vue';
import { Tinymce } from '/@/components/Tinymce';
import { propTypes } from '/@/utils/propTypes';
import { Form } from 'ant-design-vue';
export default defineComponent({
name: 'JEditor',
@ -21,11 +22,16 @@
setup(props, { emit, attrs }) {
// props attrs
const bindProps = computed(() => Object.assign({}, props, attrs));
const formItemContext = Form.useInjectFormItemContext();
// value change
function onChange(value) {
emit('change', value);
emit('update:value', value);
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
}
return {

View File

@ -30,6 +30,7 @@
import { defHttp } from '/@/utils/http/axios';
import { useGlobSetting } from '/@/hooks/setting';
import { useMessage } from '/@/hooks/web/useMessage';
import { isObject } from '/@/utils/is';
export default defineComponent({
name: 'JImportModal',
@ -116,6 +117,11 @@
if (unref(foreignKeys) && unref(foreignKeys).length > 0) {
formData.append('foreignKeys', unref(foreignKeys));
}
// update-begin--author:liaozhiyang---date:20240429---forissues/6124Online
if (isObject(foreignKeys.value)) {
formData.append('foreignKeys', JSON.stringify(foreignKeys.value));
}
// update-end--author:liaozhiyang---date:20240429---forissues/6124Online
if (!!online) {
formData.append('validateStatus', unref(validateStatus));
}

View File

@ -7,7 +7,7 @@
:placement="position"
>
<template #title>
<span>{{ title }}</span>
<span :class="title ? 'title' : 'emptyTitle'">{{ title }}</span>
<span style="float: right" title="关闭">
<Icon icon="ant-design:close-outlined" @click="visible = false" />
</span>
@ -100,6 +100,11 @@
.@{prefix-cls} {
&-popover {
// update-begin--author:liaozhiyang---date:20240520---forTV360X-144jVxetabletitle线
.ant-popover-title:has(.emptyTitle) {
border-bottom: none;
}
// update-end--author:liaozhiyang---date:20240520---forTV360X-144jVxetabletitle线
}
&-input {

View File

@ -0,0 +1,75 @@
<template>
<div class="JInputSelect">
<a-input-group compact>
<a-select
v-bind="$attrs"
:placeholder="selectPlaceholder"
v-if="selectLocation === 'left'"
v-model:value="selectVal"
@change="handleSelectChange"
>
<a-select-option v-for="item in options" :key="item.value">{{ item.label }}</a-select-option>
</a-select>
<a-input v-bind="$attrs" :placeholder="inputPlaceholder" v-model:value="inputVal" @change="handleInputChange" />
<a-select
v-bind="$attrs"
:placeholder="selectPlaceholder"
v-if="selectLocation === 'right'"
v-model:value="selectVal"
@change="handleSelectChange"
>
<a-select-option v-for="item in options" :key="item.value">{{ item.label }}</a-select-option>
</a-select>
</a-input-group>
</div>
</template>
<script setup name="JInputSelect" lang="ts">
import { ref, watchEffect } from 'vue';
import { propTypes } from '/@/utils/propTypes';
const props = defineProps({
value: propTypes.string.def(''),
options: propTypes.array.def([]),
selectLocation: propTypes.oneOf(['left', 'right']).def('right'),
selectPlaceholder: propTypes.string.def(''),
inputPlaceholder: propTypes.string.def(''),
});
const emit = defineEmits(['update:value', 'change']);
const selectVal = ref<string>();
const inputVal = ref<string>();
const handleInputChange = (e) => {
const val = e.target.value;
setSelectValByInputVal(val);
emits(val);
};
const handleSelectChange = (val) => {
inputVal.value = val;
emits(val);
};
const setSelectValByInputVal = (val) => {
const findItem = props.options.find((item) => item.value === val);
if (findItem) {
selectVal.value = val;
} else {
selectVal.value = undefined;
}
}
watchEffect(() => {
inputVal.value = props.value;
setSelectValByInputVal(props.value);
});
const emits = (val) => {
emit('update:value', val);
emit('change', val);
};
</script>
<style lang="less" scoped>
.JInputSelect {
.ant-input-group {
display: flex;
}
}
</style>

View File

@ -3,10 +3,10 @@
</template>
<script lang="ts">
import { computed, defineComponent, watch } from 'vue';
import { computed, defineComponent, watch, nextTick } from 'vue';
import { MarkDown } from '/@/components/Markdown';
import { propTypes } from '/@/utils/propTypes';
import { Form } from 'ant-design-vue';
export default defineComponent({
name: 'JMarkdownEditor',
// attrs html
@ -24,7 +24,7 @@
let vditorRef: any = null;
// props attrs
const bindProps = computed(() => Object.assign({}, props, attrs));
const formItemContext = Form.useInjectFormItemContext();
// onMounted
function onGetVditor(instance) {
mdRef = instance;
@ -42,6 +42,11 @@
function onChange(value) {
emit('change', value);
emit('update:value', value);
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
}
return {

View File

@ -1,6 +1,6 @@
<!--popup组件-->
<template>
<div class="components-input-demo-presuffix" v-if="avalid">
<div class="JPopup components-input-demo-presuffix" v-if="avalid">
<!--输入框-->
<a-input @click="handleOpen" v-model:value="showText" :placeholder="placeholder" readOnly v-bind="attrs">
<template #prefix>
@ -12,17 +12,22 @@
</template>-->
<!-- update-begin-author:taoyan date:2022-5-31 for: VUEN-1157 popup 选中后有两个清除图标后边这个清除只是把输入框中数据清除实际值并没有清除 -->
</a-input>
<!--popup弹窗-->
<JPopupOnlReportModal
@register="regModal"
:code="code"
:multi="multi"
:sorter="sorter"
:groupId="uniqGroupId"
:param="param"
@ok="callBack"
:getContainer="getContainer"
></JPopupOnlReportModal>
<!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<!--popup弹窗-->
<JPopupOnlReportModal
@register="regModal"
:code="code"
:multi="multi"
:sorter="sorter"
:groupId="uniqGroupId"
:param="param"
:showAdvancedButton="showAdvancedButton"
@ok="callBack"
:getContainer="getContainer"
></JPopupOnlReportModal>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div>
</template>
<script lang="ts">
@ -56,6 +61,7 @@
type: Array,
default: () => [],
},
showAdvancedButton: propTypes.bool.def(true),
},
emits: ['update:value', 'register', 'popUpChange', 'focus'],
setup(props, { emit, refs }) {
@ -97,7 +103,9 @@
*/
function handleOpen() {
emit('focus');
!props.disabled && openModal(true);
// update-begin--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
!attrs.value.disabled && openModal(true);
// update-end--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
}
/**
@ -148,6 +156,13 @@
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JPopup {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.components-input-demo-presuffix .anticon-close-circle {
cursor: pointer;
color: #ccc;

View File

@ -1,21 +1,26 @@
<!--popup组件-->
<template>
<div class="components-input-demo-presuffix">
<div class="JPopupDict components-input-demo-presuffix">
<!--输入框-->
<a-select v-model:value="showText" v-bind="attrs" :mode="multi ? 'multiple' : ''" @click="handleOpen" readOnly :loading="loading">
<a-select-option v-for="item in options" :value="item.value">{{ item.text }}</a-select-option>
</a-select>
<!--popup弹窗-->
<JPopupOnlReportModal
@register="regModal"
:code="code"
:multi="multi"
:sorter="sorter"
:groupId="''"
:param="param"
@ok="callBack"
:getContainer="getContainer"
/>
<!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<!--popup弹窗-->
<JPopupOnlReportModal
@register="regModal"
:code="code"
:multi="multi"
:sorter="sorter"
:groupId="''"
:param="param"
@ok="callBack"
:getContainer="getContainer"
:showAdvancedButton="showAdvancedButton"
/>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div>
</template>
<script lang="ts">
@ -52,6 +57,7 @@
param: propTypes.object.def({}),
spliter: propTypes.string.def(','),
getContainer: propTypes.func,
showAdvancedButton: propTypes.bool.def(true),
},
emits: ['update:value', 'register', 'change'],
setup(props, { emit }) {
@ -74,7 +80,9 @@
* 打开pop弹出框
*/
function handleOpen() {
!props.disabled && openModal(true);
// update-begin--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
!attrs.value.disabled && openModal(true);
// update-end--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
}
/**
* 监听value数值
@ -195,6 +203,13 @@
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JPopupDict {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.components-input-demo-presuffix {
:deep(.ant-select-dropdown) {
display: none !important;

View File

@ -1,8 +1,8 @@
<template>
<a-input-group>
<a-input :value="beginValue" style="width: calc(50% - 15px)" placeholder="最小值" @change="handleChangeBegin" />
<a-input-number v-bind="attrs" :value="beginValue" style="width: calc(50% - 15px)" placeholder="最小值" @change="handleChangeBegin" />
<a-input style="width: 30px; border-left: 0; pointer-events: none; background-color: #fff" placeholder="~" disabled />
<a-input :value="endValue" style="width: calc(50% - 15px); border-left: 0" placeholder="最大值" @change="handleChangeEnd" />
<a-input-number v-bind="attrs" :value="endValue" style="width: calc(50% - 15px); border-left: 0" placeholder="最大值" @change="handleChangeEnd" />
</a-input-group>
</template>
@ -13,25 +13,27 @@
import { ref, watch } from 'vue';
import { Form } from 'ant-design-vue';
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
export default {
name: 'JRangeNumber',
props: {
value: propTypes.oneOfType([propTypes.string, propTypes.array]),
},
emits: ['change', 'update:value'],
emits: ['change', 'update:value', 'blur'],
setup(props, { emit }) {
const beginValue = ref('');
const endValue = ref('');
const attrs = useAttrs();
const formItemContext = Form.useInjectFormItemContext();
function handleChangeBegin(e) {
beginValue.value = e.target.value;
beginValue.value = e;
emitArray();
}
function handleChangeEnd(e) {
endValue.value = e.target.value;
endValue.value = e;
emitArray();
}
@ -58,15 +60,32 @@
}
}, {immediate: true}
);
return {
beginValue,
endValue,
handleChangeBegin,
handleChangeEnd,
attrs,
};
},
};
</script>
<style scoped></style>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240607---forTV360X-214
.ant-input-group {
display: flex;
.ant-input-number {
&:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
&:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
}
// update-end--author:liaozhiyang---date:20240607---forTV360X-214
</style>

View File

@ -11,6 +11,7 @@
:placeholder="placeholder"
:filterOption="isDictTable ? false : filterOption"
:notFoundContent="loading ? undefined : null"
@focus="handleAsyncFocus"
@search="loadData"
@change="handleAsyncChange"
>
@ -46,6 +47,8 @@
import { useAttrs } from '/@/hooks/core/useAttrs';
import { initDictOptions } from '/@/utils/dict/index';
import { defHttp } from '/@/utils/http/axios';
import { debounce } from 'lodash-es';
import { setPopContainer } from '/@/utils';
export default defineComponent({
name: 'JSearchSelect',
@ -144,7 +147,7 @@
/**
* 异步查询数据
*/
async function loadData(value) {
const loadData = debounce(async function loadData(value) {
if (!isDictTable.value) {
return;
}
@ -153,6 +156,9 @@
options.value = [];
loading.value = true;
let keywordInfo = getKeywordParam(value);
//update-begin---author:chenrui ---date:2024/4/7 for[QQYUN-8800]JSearchSelectsearchSQL #6049------------
keywordInfo = keywordInfo.replaceAll("'", '');
//update-end---author:chenrui ---date:2024/4/7 for[QQYUN-8800]JSearchSelectsearchSQL #6049------------
// codetable,text,code
defHttp
.get({
@ -168,7 +174,7 @@
options.value = res;
}
});
}
}, 300);
/**
* 初始化value
*/
@ -282,6 +288,10 @@
loadData('');
}
callback();
// update-begin--author:liaozhiyang---date:20240524---forTV360X-426
// xloadSelectTexttrue
selectedObj ?? (loadSelectText.value = true);
// update-end--author:liaozhiyang---date:20240524---forTV360X-426
}
/**
*回调方法
@ -311,7 +321,9 @@
function getParentContainer(node) {
// update-begin-author:taoyan date:20220407 for: getPopupContainer popContainer
if (props.popContainer) {
return document.querySelector(props.popContainer);
// update-begin--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
return setPopContainer(node, props.popContainer);
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
} else {
if (typeof props.getPopupContainer === 'function') {
return props.getPopupContainer(node);
@ -339,7 +351,12 @@
}
}
//update-end-author:taoyan date:2022-8-15 for: VUEN-1971 online 1
// update-begin--author:liaozhiyang---date:20240523---forTV360X-26
const handleAsyncFocus = () => {
options.value.length && initDictCodeData();
attrs.onFocus?.();
};
// update-end--author:liaozhiyang---date:20240523---forTV360X-26
return {
attrs,
options,
@ -352,6 +369,7 @@
filterOption,
handleChange,
handleAsyncChange,
handleAsyncFocus,
};
},
});

View File

@ -1,8 +1,12 @@
<!--部门选择组件-->
<template>
<div>
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" @change="handleChange"/>
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :multiple="multiple" />
<div class="JSelectDept">
<JSelectBiz @change="handleSelectChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"/>
<!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :multiple="multiple" @close="handleClose"/>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div>
</template>
<script lang="ts">
@ -14,6 +18,7 @@
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { SelectValue } from 'ant-design-vue/es/select';
import { cloneDeep } from 'lodash-es';
export default defineComponent({
name: 'JSelectDept',
@ -33,13 +38,15 @@
//model
const [regModal, { openModal }] = useModal();
//
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
// const [state] = useRuleFormItem(props, 'value', 'change', emitData);
//
const selectOptions = ref<SelectValue>([]);
//
let selectValues = reactive<Recordable>({
value: [],
});
let tempSave: any = [];
//
const loadingEcho = ref<boolean>(false);
// selectOptions,xxxBiz
@ -70,11 +77,13 @@
/**
* 监听selectValues变化
*/
watch(selectValues, () => {
if (selectValues) {
state.value = selectValues.value;
}
});
// update-begin--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
// watch(selectValues, () => {
// if (selectValues) {
// state.value = selectValues.value;
// }
// });
// update-end--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
/**
* 监听selectOptions变化
*/
@ -100,11 +109,13 @@
function initValue() {
let value = props.value ? props.value : [];
if (value && typeof value === 'string') {
state.value = value.split(',');
// state.value = value.split(',');
selectValues.value = value.split(',');
tempSave = value.split(',');
} else {
// VUEN-857
selectValues.value = value;
tempSave = cloneDeep(value);
}
}
@ -114,24 +125,33 @@
function setValue(options, values) {
selectOptions.value = options;
//emitData.value = values.join(",");
state.value = values;
// state.value = values;
selectValues.value = values;
emit('update:value', values.join(','));
send(values);
}
const getBindValue = Object.assign({}, unref(props), unref(attrs));
//update-begin---author:wangshuai ---date:20230406 forissues/397使v-model:valueJSelectDept------------
/**
* 值改变事件更新value值
* @param values
*/
function handleChange(values) {
emit('update:value', values);
}
//update-end---author:wangshuai ---date:20230406 forissues/397使v-model:valueJSelectDept------------
// update-begin--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
const handleClose = () => {
if (tempSave.length) {
selectValues.value = cloneDeep(tempSave);
} else {
send(tempSave);
}
};
const handleSelectChange = (values) => {
tempSave = cloneDeep(values);
send(tempSave);
};
const send = (values) => {
let result = typeof props.value == 'string' ? values.join(',') : values;
emit('update:value', result);
emit('change', result);
};
// update-end--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
return {
state,
// state,
attrs,
selectOptions,
selectValues,
@ -141,12 +161,20 @@
regModal,
setValue,
handleOpen,
handleChange
handleClose,
handleSelectChange,
};
},
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JSelectDept {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.j-select-row {
@width: 82px;

View File

@ -22,6 +22,7 @@
import { useAttrs } from '/@/hooks/core/useAttrs';
import { getDictItems } from '/@/api/common/api';
import { useMessage } from '/@/hooks/web/useMessage';
import { setPopContainer } from '/@/utils';
const { createMessage, createErrorModal } = useMessage();
export default defineComponent({
@ -80,7 +81,7 @@
const arrayValue = ref<any[]>(!props.value ? [] : props.value.split(props.spliter));
const dictOptions = ref<any[]>([]);
const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
const [state, , , formItemContext] = useRuleFormItem(props, 'value', 'change', emitData);
onMounted(() => {
if (props.dictCode) {
@ -118,13 +119,20 @@
emit('input', selectedValue.join(props.spliter));
emit('update:value', selectedValue.join(props.spliter));
}
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
}
function getParentContainer(node) {
if (!props.popContainer) {
return node?.parentNode;
} else {
return document.querySelector(props.popContainer);
// update-begin--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
return setPopContainer(node, props.popContainer);
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
}
}
@ -177,4 +185,4 @@
color: #fff;
font-size: 12px;
}
</style>
</style>

View File

@ -1,8 +1,12 @@
<!--职务选择组件-->
<template>
<div>
<div class="JSelectPosition">
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<PositionSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></PositionSelectModal>
<!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<PositionSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></PositionSelectModal>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div>
</template>
<script lang="ts">
@ -131,6 +135,13 @@
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JSelectPosition {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.j-select-row {
@width: 82px;

View File

@ -1,8 +1,12 @@
<!--角色选择组件-->
<template>
<div>
<div class="JSelectRole">
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<RoleSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></RoleSelectModal>
<!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<RoleSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></RoleSelectModal>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div>
</template>
<script lang="ts">
@ -132,6 +136,13 @@
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JSelectRole {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.j-select-row {
@width: 82px;

View File

@ -1,7 +1,7 @@
<!--用户选择组件-->
<template>
<div class="JselectUser">
<JSelectBiz @change="handleChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<JSelectBiz @change="handleSelectChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<UserSelectModal
@ -10,6 +10,7 @@
@getSelectResult="setValue"
v-bind="getBindValue"
:excludeUserIdList="excludeUserIdList"
@close="handleClose"
/>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
@ -25,7 +26,7 @@
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { SelectValue } from 'ant-design-vue/es/select';
import { cloneDeep } from 'lodash-es';
export default defineComponent({
name: 'JSelectUser',
components: {
@ -61,7 +62,7 @@
//model
const [regModal, { openModal }] = useModal();
//
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
// const [state] = useRuleFormItem(props, 'value', 'change', emitData);
//
const selectOptions = ref<SelectValue>([]);
//
@ -69,6 +70,7 @@
value: [],
change: false,
});
let tempSave: any = [];
//
const loadingEcho = ref<boolean>(false);
// selectOptions,xxxBiz
@ -95,11 +97,11 @@
/**
* 监听selectValues变化
*/
watch(selectValues, () => {
if (selectValues) {
state.value = selectValues.value;
}
});
// watch(selectValues, () => {
// if (selectValues) {
// state.value = selectValues.value;
// }
// });
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
const excludeUserIdList = ref<any>([]);
@ -117,6 +119,9 @@
*/
function handleOpen() {
tag.value = true;
//update-begin-author:liusq---date:2024-06-03--for: [TV360X-840]
tempSave = [];
//update-end-author:liusq---date:2024-06-03--for:[TV360X-840]
openModal(true, {
isUpdate: false,
});
@ -128,11 +133,13 @@
function initValue() {
let value = props.value ? props.value : [];
if (value && typeof value === 'string' && value != 'null' && value != 'undefined') {
state.value = value.split(',');
// state.value = value.split(',');
selectValues.value = value.split(',');
tempSave = value.split(',');
} else {
// VUEN-857
selectValues.value = value;
tempSave = cloneDeep(value);
}
}
@ -142,27 +149,31 @@
function setValue(options, values) {
selectOptions.value = options;
//emitData.value = values.join(",");
state.value = values;
// state.value = values;
selectValues.value = values;
emit('update:value', values.join(','));
send(values);
}
const getBindValue = Object.assign({}, unref(props), unref(attrs));
//update-begin---author:wangshuai ---date:20230711 for------------
/**
* 下拉框值改变回调事件
* @param values
*/
function handleChange(values) {
emit('update:value', values);
// update-begin--author:liaozhiyang---date:20240417---for:QQYUN-8933
emit('change', values);
// update-end--author:liaozhiyang---date:20240417---for:QQYUN-8933
}
//update-end---author:wangshuai ---date:20230711 for------------
// update-begin--author:liaozhiyang---date:20240517---forQQYUN-9366
const handleClose = () => {
if (tempSave.length) {
selectValues.value = cloneDeep(tempSave);
} else {
send(tempSave);
}
};
const handleSelectChange = (values) => {
tempSave = cloneDeep(values);
send(tempSave);
};
const send = (values) => {
let result = typeof props.value == "string" ? values.join(',') : values;
emit('update:value', result);
emit('change', result);
};
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9366
return {
state,
// state,
attrs,
selectOptions,
getBindValue,
@ -173,7 +184,8 @@
setValue,
handleOpen,
excludeUserIdList,
handleChange,
handleClose,
handleSelectChange,
};
},
});

View File

@ -1,5 +1,6 @@
<template>
<a-tree-select
v-if="show"
allowClear
labelInValue
style="width: 100%"
@ -22,7 +23,7 @@
* 异步树加载组件 通过传入表名 显示字段 存储字段 加载一个树控件
* <j-tree-select dict="aa_tree_test,aad,id" pid-field="pid" ></j-tree-select>
* */
import { ref, watch, unref } from 'vue';
import { ref, watch, unref, nextTick } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
@ -57,6 +58,7 @@
//
treeCheckAble: propTypes.bool.def(false),
//update-end---author:wangshuai date: 20230202 for:
hiddenNodeKey: propTypes.string.def(''),
});
const attrs = useAttrs();
const emit = defineEmits(['change', 'update:value']);
@ -68,6 +70,7 @@
const tableName = ref<any>('');
const text = ref<any>('');
const code = ref<any>('');
const show = ref<boolean>(true);
/**
* 监听value数据并初始化
*/
@ -87,12 +90,29 @@
},
{ deep: true, immediate: true }
);
// update-begin--author:liaozhiyang---date:20240529---forTV360X-87
watch(
() => props.hiddenNodeKey,
() => {
if (treeData.value?.length && props.hiddenNodeKey) {
handleHiddenNode(treeData.value);
treeData.value = [...treeData.value];
}
}
);
// update-end--author:liaozhiyang---date:20240529---forTV360X-87
//update-begin-author:taoyan date:2022-5-25 for: VUEN-1056 15online
watch(
() => props.reload,
async () => {
treeData.value = [];
// update-begin--author:liaozhiyang---date:20240524---forTV360X-88online
show.value = false;
nextTick(() => {
show.value = true;
});
// update-end--author:liaozhiyang---date:20240524---forTV360X-88online
await loadRoot();
},
{
@ -175,6 +195,9 @@
i.value = i.key;
i.isLeaf = !!i.leaf;
}
// update-begin--author:liaozhiyang---date:20240523---forTV360X-87
handleHiddenNode(res.result);
// update-end--author:liaozhiyang---date:20240523---forTV360X-87
treeData.value = [...res.result];
} else {
console.log('数根节点查询结果异常', res);
@ -208,6 +231,9 @@
i.value = i.key;
i.isLeaf = !!i.leaf;
}
// update-begin--author:liaozhiyang---date:20240523---forTV360X-87
handleHiddenNode(res.result);
// update-end--author:liaozhiyang---date:20240523---forTV360X-87
//
addChildren(pid, res.result, treeData.value);
treeData.value = [...treeData.value];
@ -305,6 +331,9 @@
i.key = i.value;
i.isLeaf = !!i.leaf;
}
// update-begin--author:liaozhiyang---date:20240523---forTV360X-87
handleHiddenNode(res.result);
// update-end--author:liaozhiyang---date:20240523---forTV360X-87
treeData.value = [...res.result];
} else {
console.log('数根节点查询结果异常', res);
@ -347,6 +376,24 @@
}
//update-end-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelectchangeOptions
/**
* 2024-05-23
* liaozhiyang
* 过滤掉指定节点(包含其子孙节点)
*/
function handleHiddenNode(data) {
if (props.hiddenNodeKey && data?.length) {
for (let i = 0, len = data.length; i < len; i++) {
const item = data[i];
if (item.key == props.hiddenNodeKey) {
data.splice(i, 1);
i--;
len--;
return;
}
}
}
}
// onCreated
validateProp().then(() => {
initDictInfo();

View File

@ -408,7 +408,9 @@
}
/* update-end-author:taoyan date:2022-5-24 for:VUEN-1093详情界面 图片下载按钮显示不全*/
}
.ant-upload-text-icon {
color: @primary-color;
}
.ant-upload-list-item {
.upload-actions-container {
position: absolute;

View File

@ -63,7 +63,7 @@
// update-end--author:liaozhiyang---date:20231220---forQQYUN-7678
value: propTypes.oneOfType([propTypes.string, propTypes.array])
},
emits: ['register', 'getSelectResult'],
emits: ['register', 'getSelectResult', 'close'],
setup(props, { emit, refs }) {
//
const [register, { closeModal }] = useModalInner();

View File

@ -28,7 +28,7 @@
</template>
</template>
<a-col :md="8" :sm="8">
<a-col :md="8" :sm="8" v-if="showAdvancedButton">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset"></a-button>
@ -82,7 +82,7 @@
loading: true,
}),
},
props: ['multi', 'code', 'sorter', 'groupId', 'param'],
props: ['multi', 'code', 'sorter', 'groupId', 'param','showAdvancedButton'],
emits: ['ok', 'register'],
setup(props, { emit, refs }) {
const { createMessage } = useMessage();

View File

@ -8,8 +8,12 @@
:width="showSelected ? '1200px' : '900px'"
wrapClassName="j-user-select-modal"
@ok="handleOk"
@cancel="handleCancel"
:maxHeight="maxHeight"
:centered="true"
destroyOnClose
@visible-change="visibleChange"
>
<a-row>
<a-col :span="showSelected ? 18 : 24">
@ -81,11 +85,13 @@
},
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
},
emits: ['register', 'getSelectResult'],
emits: ['register', 'getSelectResult', 'close'],
setup(props, { emit, refs }) {
// update-begin-author:taoyan date:2022-5-24 for: VUEN-1086
const tableScroll = ref<any>({ x: false });
const tableRef = ref();
const maxHeight = ref(600);
//
const [register, { closeModal }] = useModalInner(() => {
if (window.innerWidth < 900) {
@ -112,7 +118,8 @@
const getBindValue = Object.assign({}, unref(props), unref(attrs), config);
const [{ rowSelection, visibleChange, selectValues, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz(
getUserList,
getBindValue
getBindValue,
emit
);
const searchInfo = ref(props.params);
// update-begin--author:liaozhiyang---date:20230811---forissues/657
@ -248,8 +255,18 @@
}
return record;
}
// update-begin--author:liaozhiyang---date:20240517---forQQYUN-9366
const handleCancel = () => {
emit('close');
};
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9366
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
// update-begin--author:liaozhiyang---date:20240607---forTV360X-30510
const clientHeight = document.documentElement.clientHeight * 200;
maxHeight.value = clientHeight > 600 ? 600 : clientHeight;
// update-end--author:liaozhiyang---date:20240607---forTV360X-30510
return {
//config,
handleOk,
@ -268,6 +285,8 @@
tableScroll,
tableRef,
afterFetch,
handleCancel,
maxHeight,
};
},
});

View File

@ -190,12 +190,17 @@
e && prevent(e);
searchInputStatus.value = true;
}
//
function onSearchUser() {
console.log('onSearchUser');
pageNo.value = 1;
loadUserList();
}
//
function clearSearch(e) {
e && prevent(e);
pageNo.value = 1;
searchText.value = '';
searchInputStatus.value = false;
loadUserList();

View File

@ -13,7 +13,16 @@ export const useCodeHinting = (CodeMirror, keywords, language) => {
}, 1e3);
}
};
const codeHintingRegistry = () => {
// 自定义关键词(.的上一级)
const customKeywords: string[] = [];
currentKeywords.forEach((item) => {
if (item.superiors) {
customKeywords.push(item.superiors);
}
});
const funcsHint = (cm, callback) => {
// 获取光标位置
const cur = cm.getCursor();
@ -22,38 +31,93 @@ export const useCodeHinting = (CodeMirror, keywords, language) => {
const start = token.start;
const end = cur.ch;
const str = token.string;
let recordKeyword = null;
console.log('光标位置:', cur, '单词信息:', token, `start:${start},end:${end},str:${str}`);
if (str.length) {
const findIdx = (a, b) => a.toLowerCase().indexOf(b.toLowerCase());
let list = currentKeywords
.filter((item) => {
const index = findIdx(item, str);
return (index === 0 || index === 1) && (item.length != str.length || item.length - 1 != str.length);
})
.sort((a, b) => {
if (findIdx(a, str) < findIdx(b, str)) {
return -1;
} else {
return 1;
if (str === '.') {
// 查找.前面是否有定义的关键词
const curLineCode = cm.getLine(cur.line);
for (let i = 0, len = customKeywords.length; i < len; i++) {
const k = curLineCode.substring(-1, customKeywords[i].length);
if (customKeywords.includes(k)) {
recordKeyword = k;
break;
}
});
}
}
const findIdx = (a, b) => a.toLowerCase().indexOf(b.toLowerCase());
let list = currentKeywords.filter((item) => {
if (recordKeyword) {
// 查特定对象下的属性or方法
return item.superiors === recordKeyword;
} else {
// 查全局属性或者方法
return item.superiors == undefined;
}
});
if (str === '.') {
if (recordKeyword == null) {
list = [];
}
} else {
list = list
.filter((item) => {
const { text } = item;
const index = findIdx(text, str);
let result = text.startsWith('.') ? index === 1 : index === 0;
return result;
})
.sort((a, b) => {
if (findIdx(a.text, str) < findIdx(b.text, str)) {
return -1;
} else {
return 1;
}
});
}
// 有点去掉点
// list = list.map(item => {
// if(item.indexOf(".") === 0){
// return item.substring(1);
// }
// return item;
// });
if (list.length === 1 && (list[0] === str || list[0].substring(1) === str)) {
list = [];
if (list.length === 1) {
// 只有一个时可能是自己输入,输到最后需要去掉提示。
const item = list[0];
if (item.text === str || item.text.substring(1) === str) {
list = [];
}
}
if (list.length) {
// 当str不是点时去掉点
if (str != '.') {
list = list.map((item) => {
if (item.text.indexOf('.') === 0) {
return { ...item, text: item.text.substring(1) };
}
return item;
});
}
callback({
list: list,
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end),
});
// update-begin--author:liaozhiyang---date:20240429---for【QQYUN-8865】js增强加上鼠标移入提示
const item = currentKeywords[0];
if (item?.desc) {
setTimeout(() => {
const elem: HTMLUListElement = document.querySelector('.CodeMirror-hints')!;
if (elem) {
const childElems = elem.children;
Array.from(childElems).forEach((item) => {
const displayText = item.textContent;
const findItem = currentKeywords.find((item) => item.displayText === displayText);
if (findItem) {
item.setAttribute('title', findItem.desc);
}
});
}
}, 0);
}
// update-end--author:liaozhiyang---date:20240429---for【QQYUN-8865】js增强加上鼠标移入提示
} else {
}
}
};

View File

@ -2,7 +2,7 @@ import { inject, reactive, ref, watch, unref, Ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { isEmpty } from '@/utils/is';
export function useSelectBiz(getList, props) {
export function useSelectBiz(getList, props, emit) {
//接收下拉框选项
const selectOptions = inject('selectOptions', ref<Array<object>>([]));
//接收已选择的值
@ -118,6 +118,10 @@ export function useSelectBiz(getList, props) {
if (visible) {
//设置列表默认选中
props.showSelected && initSelectRows();
} else {
// update-begin--author:liaozhiyang---date:20240517---for【QQYUN-9366】用户选择组件取消和关闭会把选择数据带入
emit('close');
// update-end--author:liaozhiyang---date:20240517---for【QQYUN-9366】用户选择组件取消和关闭会把选择数据带入
}
}

View File

@ -3,7 +3,7 @@ import { inject, reactive, ref, computed, unref, watch, nextTick } from 'vue';
import { TreeActionType } from '/@/components/Tree';
import { listToTree } from '/@/utils/common/compUtils';
export function useTreeBiz(treeRef, getList, props, realProps) {
export function useTreeBiz(treeRef, getList, props, realProps, emit) {
//接收下拉框选项
const selectOptions = inject('selectOptions', ref<Array<object>>([]));
//接收已选择的值
@ -252,6 +252,9 @@ export function useTreeBiz(treeRef, getList, props, realProps) {
await onLoadData(null, null);
} else {
openModal.value = false;
// update-begin--author:liaozhiyang---date:20240527---for【TV360X-414】部门设置了默认值查询重置变成空了(同步JSelectUser组件改法)
emit?.('close');
// update-end--author:liaozhiyang---date:20240527---for【TV360X-414】部门设置了默认值查询重置变成空了(同步JSelectUser组件改法)
}
}

View File

@ -202,7 +202,10 @@ export interface FormSchema {
buss?: any;
//label字数控制label宽度
labelLength?: number
labelLength?: number;
// update-begin--author:liaozhiyang---date:20240529---for【TV360X-460】basicForm支持v-auth指令(权限控制显隐)
auth?: string;
// update-end--author:liaozhiyang---date:20240529---for【TV360X-460】basicForm支持v-auth指令(权限控制显隐)
}
export interface HelpComponentProps {
maxWidth: string;

View File

@ -105,6 +105,7 @@ export type ComponentType =
| 'RangePicker'
| 'WeekPicker'
| 'TimePicker'
| 'DatePickerInFilter'
| 'Switch'
| 'StrengthMeter'
| 'Upload'
@ -147,10 +148,13 @@ export type ComponentType =
| 'LinkTableSelect'
| 'LinkTableForQuery'
| 'CascaderPcaForQuery'
| 'CascaderPcaInFilter'
| 'UserSelect'
| 'RoleSelect'
| 'RangeDate'
| 'RangeNumber'
| 'linkRecordSelect'
| 'RangeTime'
| 'JRangeNumber';
| 'JRangeNumber'
| 'JInputSelect';

View File

@ -0,0 +1,198 @@
<template>
<div class="flex justify-between ml-4 mr-5 mb-1" v-if="isSearch">
<a-input :placeholder="t('component.icon.search')" v-model:value="searchIconValue" @change="debounceHandleSearchChange" allowClear />
</div>
<div v-if="getPaginationList.length > 0">
<ScrollContainer>
<ul class="px-2 icon-list" style="padding-right: 0">
<li
v-for="icon in getPaginationList"
:key="icon"
:class="currentSelect === icon ? 'icon-border' : ''"
class="p-2 w-1/8 cursor-pointer mr-1 mt-1 flex justify-center items-center border border-solid hover:border-primary"
@click="handleClick(icon)"
:title="icon"
>
<SvgIcon v-if="isSvgMode" :name="icon" />
<Icon :icon="icon" v-else />
</li>
</ul>
</ScrollContainer>
<div class="flex py-2 items-center justify-content-right mr-10 mt-5" v-if="getTotal >= pageSize && isPage">
<Pagination
showLessItems
v-model:current="current"
:page-size-options="pageSizeOptions"
size="small"
v-model:pageSize="pageSize"
v-model:total="getTotal"
@change="handlePageChange"
/>
</div>
</div>
<template v-else
><div class="p-5"><empty /></div>
</template>
</template>
<script lang="ts" name="icon-list">
import { ScrollContainer } from '@/components/Container';
import SvgIcon from '@/components/Icon/src/SvgIcon.vue';
import Icon from '@/components/Icon/src/Icon.vue';
import { defineComponent, ref, unref, watchEffect} from 'vue';
import { useDebounceFn } from '@vueuse/core';
import { usePagination } from '@/hooks/web/usePagination';
import { propTypes } from '@/utils/propTypes';
import { useCopyToClipboard } from '@/hooks/web/useCopyToClipboard';
import { useI18n } from '@/hooks/web/useI18n';
import { useMessage } from '@/hooks/web/useMessage';
import { Empty, Pagination } from 'ant-design-vue';
export default defineComponent({
components: {
ScrollContainer,
SvgIcon,
Icon,
Empty,
Pagination,
},
props: {
currentList: propTypes.any.def([]),
clearSelect: propTypes.bool.def(false),
copy: propTypes.bool.def(false),
isSvgMode: propTypes.bool.def(false),
isPage: propTypes.bool.def(false),
isSearch: propTypes.bool.def(false),
value: propTypes.string.def(''),
},
setup(props, { emit }) {
//
const currentSelect = ref('');
//
const current = ref<number>(1);
//
const pageSize = ref<number>(140);
//
const pageSizeOptions = ref<any>(['10', '20', '50', '100', '140']);
//
const searchIconValue = ref<string>('');
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
const currentList = ref<any>(props.currentList);
const { getPaginationList, getTotal, setCurrentPage, setPageSize } = usePagination(currentList, pageSize.value);
const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
const { t } = useI18n();
const { createMessage } = useMessage();
/**
* 搜索
* @param e
*/
function handleSearchChange(e: ChangeEvent) {
const value = e.target.value;
console.log("value::::",value)
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
setCurrentPage(1);
current.value = 1;
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
if (!value) {
currentList.value = props.currentList;
return;
}
currentList.value = props.currentList.filter((item) => item.includes(value));
}
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
/**
* 图标点击重置页数
*/
function currentSelectClick() {
setCurrentPage(1);
setPageSize(140);
current.value = 1;
pageSize.value = 140;
currentList.value = props.currentList;
searchIconValue.value = '';
}
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
function handlePageChange(page: number, size: number) {
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
current.value = page;
pageSize.value = size;
setPageSize(size);
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
setCurrentPage(page);
}
/**
* 图标点击事件
* @param icon
*/
function handleClick(icon: string) {
if (props.clearSelect === true) {
if (currentSelect.value === icon) {
currentSelect.value = '';
} else {
currentSelect.value = icon;
}
} else {
currentSelect.value = icon;
if (props.copy) {
clipboardRef.value = icon;
if (unref(isSuccessRef)) {
createMessage.success(t('component.icon.copy'));
}
}
}
}
/**
* 获取图标
*/
function getIcon() {
return currentSelect.value;
}
watchEffect(() => {
currentSelect.value = props.value;
});
return {
searchIconValue,
debounceHandleSearchChange,
getTotal,
getPaginationList,
handlePageChange,
handleClick,
currentSelect,
t,
pageSize,
pageSizeOptions,
current,
getIcon,
currentSelectClick,
};
},
});
</script>
<style scoped lang="less">
ul li {
width: 32px;
height: 32px;
float: left;
display: flex;
margin: 6px;
}
ul span {
font-size: 1.5rem !important;
border: 1px solid #f1f1f1;
padding: 0.2rem;
margin: 0.3rem;
}
.icon-border span {
border: 1px solid rgba(24, 144, 255) !important;
}
.justify-content-right {
justify-content: right;
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,39 @@
<!-- 省市县选择组件在筛选中的用法 -->
<template>
<a-space :class="[prefixCls]" direction="vertical">
</a-space>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
name: 'CascaderPcaInFilter',
inheritAttrs: false,
})
</script>
<script lang="ts" setup>
</script>
<style lang="less">
//noinspection LessUnresolvedVariable
@prefix-cls: ~'@{namespace}-j-cascader-pca-in-filter';
.@{prefix-cls} {
width: 100%;
}
.@{prefix-cls}-menu-item-icon {
width: 16px;
height: 16px;
display: inline-block;
margin-right: 6px;
&, & + span {
vertical-align: middle;
}
}
</style>

View File

@ -0,0 +1,142 @@
<!-- 在筛选中使用的日期选择器可选择今天本周等范围 -->
<template>
<a-space :id="formItemId" :class="[prefixCls]" direction="vertical">
<a-space-compact block>
<!-- 日期范围下拉 -->
<a-select v-if="isRange" v-model:value="innerValue">
<a-select-option v-for="opt of RANGE_OPTIONS" :key="opt.key" :value="opt.key">
{{ opt.label }}
</a-select-option>
<a-select-option key="custom" value="custom">
自定义日期
</a-select-option>
</a-select>
<!-- 自定义日期选择器 -->
<DatePicker v-else v-model:value="innerValue" v-model:open="datePickerIsOpen" v-bind="attrs"/>
<!-- 右侧下拉菜单 -->
<a-dropdown v-if="allowSelectRange" :trigger="['click']">
<a-button preIcon="ant-design:menu-unfold"/>
<template #overlay>
<a-menu @click="onMenuClick">
<a-menu-item v-for="opt of RANGE_OPTIONS" :key="opt.key">
{{ opt.label }}
</a-menu-item>
<a-menu-item key="custom">
自定义日期
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</a-space-compact>
</a-space>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
name: 'DatePickerInFilter',
inheritAttrs: false,
})
</script>
<script lang="ts" setup>
import {ref, watch, computed, nextTick, useAttrs, defineProps} from 'vue'
import {DatePicker} from 'ant-design-vue'
import {useDesign} from '/@/hooks/web/useDesign';
import { Form } from 'ant-design-vue';
const formItemContext = Form.useInjectFormItemContext();
//
const RANGE_OPTIONS = [
{key: 'TODAY', label: '今天'},
{key: 'YESTERDAY', label: '昨天'},
{key: 'TOMORROW', label: '明天'},
{key: 'THIS_WEEK', label: '本周'},
{key: 'LAST_WEEK', label: '上周'},
{key: 'NEXT_WEEK', label: '下周'},
{key: 'LAST_7_DAYS', label: '过去七天'},
{key: 'THIS_MONTH', label: '本月'},
{key: 'LAST_MONTH', label: '上月'},
{key: 'NEXT_MONTH', label: '下月'},
];
const RANGE_OPTION_KEYS = RANGE_OPTIONS.map(item => item.key)
const {prefixCls} = useDesign('j-data-picker-in-filter');
const props = defineProps({
value: {
type: [String],
default: ''
},
//
allowSelectRange: {
type: Boolean,
default: true,
}
})
const emit = defineEmits(['change', 'update:value'])
const attrs = useAttrs()
// id
const formItemId = computed(() => formItemContext.id.value)
const innerValue = ref(props.value)
//
const datePickerIsOpen = ref(false)
//
const isRange = computed(() => RANGE_OPTION_KEYS.includes(innerValue.value));
// value
watch(() => props.value, (val) => {
innerValue.value = val
})
// emit
watch(innerValue, (val) => {
if (val === 'custom') {
val = ''
openDatePicker()
}
emit('change', val)
emit('update:value', val)
// update-begin--author:liaozhiyang---date:20240509---forQQYUN-9227
formItemContext?.onFieldChange();
// update-end--author:liaozhiyang---date:20240509---forQQYUN-9227
})
watch(() => props.allowSelectRange, (allow) => {
//
if (!allow && isRange.value) {
innerValue.value = ''
}
}, {immediate: true});
//
function onMenuClick(event: Recordable) {
if (event.key === 'custom') {
if (isRange.value) {
innerValue.value = '';
}
openDatePicker()
} else {
innerValue.value = event.key
}
}
//
async function openDatePicker() {
await nextTick()
datePickerIsOpen.value = true
}
</script>
<style lang="less">
//noinspection LessUnresolvedVariable
@prefix-cls: ~'@{namespace}-j-data-picker-in-filter';
.@{prefix-cls} {
width: 100%;
}
</style>

View File

@ -0,0 +1,2 @@
export {default as DatePickerInFilter} from './DatePickerInFilter.vue';
export {default as CascaderPcaInFilter} from './CascaderPcaInFilter.vue';

View File

@ -2,7 +2,6 @@ import { registerComponent, registerAsyncComponent, registerASyncComponentReal }
import { JVxeTypes } from '/@/components/jeecg/JVxeTable/types';
import { DictSearchSpanCell, DictSearchInputCell } from './src/components/JVxeSelectDictSearchCell';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export async function registerJVxeCustom() {
// ----------------- ⚠ 注意事项 ⚠ -----------------
// 当组件内包含 BasicModal 时,必须使用异步引入!
@ -24,8 +23,11 @@ export async function registerJVxeCustom() {
// 注册【部门选择】组件
await registerAsyncComponent(JVxeTypes.departSelect, import('./src/components/JVxeDepartSelectCell.vue'));
// 注册【省市区选择】组件
// await registerAsyncComponent(JVxeTypes.pca, import('./src/components/JVxePcaCell.vue'));
// update-begin--author:liaozhiyang---date:20240308---for【QQYUN-8241】为避免首次加载china-area-dataJVxePcaCell组件需异步加载
registerASyncComponentReal(
JVxeTypes.pca,
createAsyncComponent(() => import('./src/components/JVxePcaCell.vue'))
);
// update-end--author:liaozhiyang---date:20240308---for【QQYUN-8241】为避免首次加载china-area-dataJVxePcaCell组件需异步加载
}

View File

@ -17,7 +17,7 @@
<span style="margin-left: 5px">{{ ellipsisFileName }}</span>
</a-tooltip>
<Dropdown :trigger="['click']" placement="bottomRight" style="margin-left: 10px" :disabled="cellProps.disabled">
<Dropdown :trigger="['click']" placement="bottomRight" style="margin-left: 10px">
<a-tooltip title="操作">
<Icon v-if="file.status !== 'uploading'" icon="ant-design:setting" style="cursor: pointer" />
</a-tooltip>
@ -26,10 +26,10 @@
<a-menu-item v-if="originColumn.allowDownload !== false" @click="handleClickDownloadFile">
<span><Icon icon="ant-design:download" />&nbsp;下载</span>
</a-menu-item>
<a-menu-item v-if="originColumn.allowRemove !== false" @click="handleClickDeleteFile">
<a-menu-item :disabled="cellProps.disabled" v-if="originColumn.allowRemove !== false" @click="handleClickDeleteFile">
<span><Icon icon="ant-design:delete" />&nbsp;删除</span>
</a-menu-item>
<a-menu-item @click="handleMoreOperation">
<a-menu-item :disabled="cellProps.disabled" @click="handleMoreOperation">
<span><Icon icon="ant-design:bars" />&nbsp;更多</span>
</a-menu-item>
</a-menu>
@ -39,6 +39,7 @@
</template>
<a-upload
v-if="cellProps.allDisable"
v-show="!hasFile"
name="file"
:data="{ isup: 1 }"

View File

@ -9,7 +9,7 @@
</template>
<template v-else-if="file['path']">
<template v-for="src of imgList">
<img class="j-vxe-image" :src="src" alt="图片错误" @[clickEvent]="handleMoreOperation" />
<img class="j-vxe-image" :src="src" alt="图片错误" @[clickEvent]="handleMoreOperation" @click="handlePreview" />
</template>
</template>
<a-tooltip v-else :title="file.message || '上传失败'" @[clickEvent]="handleClickShowImageError">
@ -17,8 +17,9 @@
</a-tooltip>
</div>
</template>
<div class="j-vxe-image-upload">
<div class="j-vxe-image-upload" v-if="cellProps.allDisable">
<a-upload
:accept="acceptFileType"
name="file"
:data="{ isup: 1 }"
:multiple="false"
@ -45,6 +46,7 @@
import { UploadTypeEnum } from '/@/components/Form/src/jeecg/components/JUpload';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { components, enhanced, useFileCell } from '../hooks/useFileCell';
import { createImgPreview } from '/@/components/Preview/index';
export default defineComponent({
name: 'JVxeImageCell',
@ -54,6 +56,9 @@
const { createErrorModal } = useMessage();
const setup = useFileCell(props, UploadTypeEnum.image, { multiple: true });
// update-begin--author:liaozhiyang---date:20240604---forTV360X-470jVxetable
const acceptFileType = 'image/*';
// update-end--author:liaozhiyang---date:20240604---forTV360X-470jVxetable
// update-begin--author:liaozhiyang---date:20240105---forissues/953onlinevxe-table
const clickEvent = computed(() => {
return unref(setup.cellProps).disabled ? null : 'click';
@ -84,13 +89,21 @@
});
}
}
// update-begin--author:liaozhiyang---date:20240523---forTV360X-121jvxetable()
const handlePreview = () => {
if (unref(setup.cellProps).disabled) {
createImgPreview({ imageList: imgList.value });
}
};
// update-end--author:liaozhiyang---date:20240523---forTV360X-121jvxetable()
return {
...setup,
imgList,
maxCount,
handleClickShowImageError,
clickEvent
clickEvent,
handlePreview,
acceptFileType,
};
},
// JVxeComponent.Enhanced

View File

@ -63,6 +63,11 @@ export function useFileCell(props, fileType: UploadTypeEnum, options?) {
// 更多上传回调
function onModalChange(path) {
if (path) {
// update-begin--author:liaozhiyang---date:20240524---for【TV360X-235】富文本禁用状态下图片上传按钮文字看不清
if (innerFile.value === null) {
innerFile.value = {};
}
// update-end-author:liaozhiyang---date:20240524---for【TV360X-235】富文本禁用状态下图片上传按钮文字看不清
innerFile.value.path = path;
handleChangeCommon(innerFile.value);
} else {

View File

@ -112,8 +112,46 @@
const insEditor = new Vditor(wrapEl, {
theme: getDarkMode.value === 'dark' ? 'dark' : 'classic',
lang: unref(getCurrentLang),
// update-begin--author:liaozhiyang---date:20240520---forTV360X-146Markdown
toolbar: [
'emoji',
'headings',
'bold',
'italic',
'strike',
'link',
'|',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'|',
'quote',
'line',
'code',
'inline-code',
'insert-before',
'insert-after',
'|',
'upload',
// 'record',
'table',
'|',
'undo',
'redo',
'|',
'fullscreen',
'edit-mode',
{
name: 'more',
toolbar: ['both', 'code-theme', 'content-theme', 'export', 'outline', 'preview', 'devtools', 'info', 'help'],
},
],
// update-end--author:liaozhiyang---date:20240520---forTV360X-146Markdown
mode: 'sv',
cdn: 'https://cdn.jsdelivr.net/npm/vditor@3.9.6',
// cdn: 'https://cdn.jsdelivr.net/npm/vditor@3.9.6',
cdn: 'https://unpkg.com/vditor@3.10.1',
fullscreen: {
index: 520,
},
@ -186,3 +224,10 @@
},
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240527---forTV360X-318markdown
:deep(.vditor-menu--disabled) {
pointer-events: none;
}
// update-end--author:liaozhiyang---date:20240527---forTV360X-318markdown
</style>

View File

@ -25,7 +25,7 @@
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { useOpenKeys } from './useOpenKeys';
import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
import { isFunction } from '/@/utils/is';
import { isFunction, isUrl } from '/@/utils/is';
import { basicProps } from './props';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { REDIRECT_NAME } from '/@/router/constant';
@ -33,6 +33,9 @@
import { getCurrentParentPath } from '/@/router/menus';
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
import { getAllParentPath } from '/@/router/helper/menuHelper';
import { createBasicRootMenuContext } from './useBasicMenuContext';
import { URL_HASH_TAB } from '/@/utils';
import { getMenus } from '/@/router/menus';
export default defineComponent({
name: 'BasicMenu',
@ -52,7 +55,9 @@
selectedKeys: [],
collapsedOpenKeys: [],
});
// update-begin--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
createBasicRootMenuContext({ menuState: menuState });
// update-end--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
const { prefixCls } = useDesign('basic-menu');
const { items, mode, accordion } = toRefs(props);
@ -112,11 +117,43 @@
//update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online
async function handleMenuClick({ item, key }: { item: any; key: string; keyPath: string[] }) {
const { beforeClickFn } = props;
// update-begin--author:liaozhiyang---date:20240402---for:QQYUN-8773
if (isUrl(key)) {
key = key.replace(URL_HASH_TAB, '#');
window.open(key);
return;
}
// update-end--author:liaozhiyang---date:20240402---for:QQYUN-8773
if (beforeClickFn && isFunction(beforeClickFn)) {
const flag = await beforeClickFn(key);
if (!flag) return;
}
emit('menuClick', key, item);
// update-begin--author:liaozhiyang---date:20240418---for:QQYUN-8773()redirect
if (props.type === MenuTypeEnum.MIX) {
const menus = await getMenus();
const menuItem = getMatchingPath(menus, key);
if (menuItem && !menuItem.redirect && menuItem.children?.length) {
const subMenuItem = getSubMenu(menuItem.children);
if (subMenuItem?.path) {
const path = subMenuItem.redirect ?? subMenuItem.path;
let _key = path;
if (isUrl(path)) {
window.open(path);
// emitkeyurl
_key = key;
}
emit('menuClick', _key, { title: subMenuItem.title });
} else {
emit('menuClick', key, item);
}
} else {
emit('menuClick', key, item);
}
} else {
emit('menuClick', key, item);
}
// emit('menuClick', key, item);
// update-begin--author:liaozhiyang---date:20240418---for:QQYUN-8773()redirect
//update-end-author:taoyan date:2022-6-1 for: VUEN-1144 online
isClickGo.value = true;
@ -142,6 +179,45 @@
menuState.selectedKeys = parentPaths;
}
}
/**
* liaozhiyang
* 2024-05-18
* 获取指定菜单下的第一个菜单
*/
function getSubMenu(menus) {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path && !item.children?.length) {
return item;
} else if (item.children?.length) {
const result = getSubMenu(item.children);
if (result) {
return result;
}
}
}
return null;
}
/**
* liaozhiyang
* 2024-05-18
* 获取匹配path的菜单
*/
function getMatchingPath(menus, path) {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path === path) {
return item;
} else if (item.children?.length) {
const result = getMatchingPath(item.children, path);
if (result) {
return result;
}
}
}
return null;
}
return {
handleMenuClick,

View File

@ -1,6 +1,6 @@
<template>
<BasicMenuItem v-if="!menuHasChildren(item) && getShowMenu" v-bind="$props" />
<SubMenu v-if="menuHasChildren(item) && getShowMenu" :class="[theme]" :key="`submenu-${item.path}`" popupClassName="app-top-menu-popup">
<SubMenu v-if="menuHasChildren(item) && getShowMenu" :class="[theme]" :key="`submenu-${item.path}`" :popupClassName="prefixCls">
<template #title>
<MenuItemContent v-bind="$props" :item="item" />
</template>
@ -12,14 +12,17 @@
</template>
<script lang="ts">
import type { Menu as MenuType } from '/@/router/types';
import { defineComponent, computed } from 'vue';
import { defineComponent, computed, watch } from 'vue';
import { Menu } from 'ant-design-vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { checkChildrenHidden } from '/@/utils/common/compUtils';
import { itemProps } from '../props';
import BasicMenuItem from './BasicMenuItem.vue';
import MenuItemContent from './MenuItemContent.vue';
import { useBasicRootMenuContext } from '../useBasicMenuContext';
import { useLocaleStore } from '/@/store/modules/locale';
import { getMenus } from '/@/router/menus';
export default defineComponent({
name: 'BasicSubMenuItem',
isSubMenu: true,
@ -30,8 +33,10 @@
},
props: itemProps,
setup(props) {
const { prefixCls } = useDesign('basic-menu-item');
const { prefixCls } = useDesign('basic-subMenu');
const { menuState } = useBasicRootMenuContext();
const localeStore = useLocaleStore();
const getShowMenu = computed(() => !props.item.meta?.hideMenu);
function menuHasChildren(menuTreeItem: MenuType): boolean {
return (
@ -42,6 +47,34 @@
&&checkChildrenHidden(menuTreeItem)
);
}
// update-begin--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
const getMatchingRouterName = (menus, path) => {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path === path && !item.redirect && !item.paramPath) {
return item.meta?.title;
} else if (item.children?.length) {
const result = getMatchingRouterName(item.children, path);
if (result) {
return result;
}
}
}
return '';
};
watch(
() => menuState.selectedKeys,
async (value) => {
if (value.length && value.includes(props.item.path)) {
const menus = await getMenus();
const getTitle = getMatchingRouterName(menus, props.item.path);
localeStore.setPathTitle(props.item.path, getTitle ? getTitle : props.item.name);
}
},
{ immediate: true }
);
// update-end--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
return {
prefixCls,
menuHasChildren,
@ -51,3 +84,51 @@
},
});
</script>
<style lang="less">
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762
@prefix-cls: ~'@{namespace}-basic-subMenu';
html[data-theme='light'] {
.@{prefix-cls}.ant-menu-dark {
background-color: var(--header-bg-color);
color: rgba(255, 255, 255, 0.9);
&.ant-menu-submenu {
> .ant-menu {
background-color: var(--header-bg-color);
}
}
.ant-menu-item-selected {
background-color: var(--header-active-menu-bg-color);
}
}
//QQYUN-8922
.ant-menu-submenu-placement-bottomLeft.ant-menu-dark.ant-menu-submenu-popup {
background-color: var(--header-bg-color);
&.ant-menu-dark.ant-menu-submenu > .ant-menu {
background-color: var(--header-bg-color);
color: rgba(255, 255, 255, 0.9);
}
}
}
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9128
html[data-theme='dark'] {
@bgcolor:#212121;
.@{prefix-cls}.ant-menu-dark {
background-color: @bgcolor;
&.ant-menu-submenu {
> .ant-menu {
background-color: @bgcolor;
}
}
}
//QQYUN-8922
.ant-menu-submenu-placement-bottomLeft.ant-menu-dark.ant-menu-submenu-popup {
background-color: @bgcolor;
&.ant-menu-dark.ant-menu-submenu > .ant-menu {
background-color: @bgcolor;
color: rgba(255, 255, 255, 0.9);
}
}
}
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9128
</style>

View File

@ -18,7 +18,9 @@
&.ant-menu-dark {
background-color: transparent;
// update-begin--author:liaozhiyang---date:20240407---for【QQYUN-8762】顶部菜单模式文字调整
color: rgba(255 ,255 ,255, 1);
// update-end--author:liaozhiyang---date:20240407---for【QQYUN-8762】顶部菜单模式文字调整
.ant-menu-submenu:hover,
.ant-menu-item-open,
.ant-menu-submenu-open,

View File

@ -0,0 +1,16 @@
import type { InjectionKey, Ref } from 'vue';
import { createContext, useContext } from '/@/hooks/core/useContext';
export interface BasicRootMenuContextProps {
menuState: any;
}
const key: InjectionKey<BasicRootMenuContextProps> = Symbol();
export function createBasicRootMenuContext(context: BasicRootMenuContextProps) {
return createContext<BasicRootMenuContextProps>(context, key, { readonly: false, native: true });
}
export function useBasicRootMenuContext() {
return useContext<BasicRootMenuContextProps>(key);
}

View File

@ -73,7 +73,7 @@
components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
inheritAttrs: false,
props: basicProps,
emits: ['visible-change', 'open-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible', 'update:open', 'fullScreen'],
emits: ['visible-change', 'open-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible', 'update:open', 'fullScreen','comment-open'],
setup(props, { emit, attrs , slots}) {
const visibleRef = ref(false);
const propsRef = ref<Partial<ModalProps> | null>(null);
@ -183,6 +183,7 @@
() => unref(visibleRef),
(v) => {
emit('visible-change', v);
emit('open-change', v);
emit('update:visible', v);
emit('update:open', v);
instance && modalMethods.emitVisible?.(v, instance.uid);
@ -263,6 +264,9 @@
}else{
commentSpan.value = 0
}
// update-begin--author:liaozhiyang---date:20240528---forTV360X-485
emit('comment-open', commentSpan.value === 0, commentSpan.value);
// update-end--author:liaozhiyang---date:20240528---forTV360X-485
}
//update-end-author:taoyan date:2022-7-18 for: modal slot

View File

@ -0,0 +1,327 @@
<template>
<a-modal v-bind="getBindValue" @cancel="handleCancel" :body-style="!fullScreenRef ? bodyStyle : {}">
<slot></slot>
<template #closeIcon v-if="!$slots.closeIcon">
<div class="jeecg-basic-modal-close" v-if="canFullscreen">
<Tooltip :title="t('component.modal.restore')" placement="bottom" v-if="fullScreenRef">
<FullscreenExitOutlined role="full" @click="handleFullScreen" />
</Tooltip>
<Tooltip :title="t('component.modal.maximize')" placement="bottom" v-else>
<FullscreenOutlined role="close" @click="handleFullScreen" />
</Tooltip>
<Tooltip :title="t('component.modal.close')" placement="bottom">
<CloseOutlined @click="handleCancel" />
</Tooltip>
</div>
</template>
<template #title v-if="!isNoTitle">
<ModalHeader :helpMessage="getProps.helpMessage" :title="getMergeProps.title" @dblclick="handleTitleDbClick" />
</template>
<template #footer v-if="!$slots.footer">
<ModalFooter v-bind="getBindValue" @ok="handleOk" @cancel="handleCancel">
<template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data || {}"></slot>
</template>
</ModalFooter>
</template>
<template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
<slot :name="item" v-bind="data || {}"></slot>
</template>
</a-modal>
</template>
<script lang="ts" name="j-modal">
import { computed, defineComponent, getCurrentInstance, ref, toRef, unref, watch, watchEffect } from 'vue';
import ModalFooter from '@/components/Modal/src/components/ModalFooter.vue';
import ModalClose from '@/components/Modal/src/components/ModalClose.vue';
import ModalHeader from '@/components/Modal/src/components/ModalHeader.vue';
import { omit } from 'lodash-es';
import { useAppInject } from '@/hooks/web/useAppInject';
import type { ModalMethods, ModalProps } from '@/components/Modal';
import { CloseOutlined, FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons-vue';
import { Tooltip } from 'ant-design-vue';
import { useI18n } from '@/hooks/web/useI18n';
import { deepMerge } from '@/utils';
import { basicProps } from '@/components/Modal/src/props';
import Modal from '/@/components/Modal/src/components/Modal';
import { isFunction } from '@/utils/is';
export default defineComponent({
name: 'JModal',
methods: { omit },
components: {
CloseOutlined,
Tooltip,
FullscreenExitOutlined,
FullscreenOutlined,
ModalHeader,
ModalClose,
ModalFooter,
Modal,
},
props: {
//
fullscreen: {
type: Boolean,
default: false,
},
...basicProps,
},
emits: ['visible-change', 'open-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible', 'update:open', 'fullScreen'],
setup(props, { emit, attrs, slots }) {
const { getIsMobile } = useAppInject();
const visibleRef = ref(false);
const propsRef = ref<Partial<ModalProps> | null>(null);
const fullScreenRef = ref<any>(props.fullscreen);
const fullScreen = ref<boolean>(false);
const { t } = useI18n();
const bodyStyle = ref<any>({
height: props.maxHeight ? props.maxHeight : '600px',
'overflow-y': 'auto',
});
const modalMethods: ModalMethods = {
setModalProps,
emitVisible: undefined,
};
const getMergeProps = computed((): Recordable => {
const result = {
...props,
...(unref(propsRef) as any),
};
if (getIsMobile.value) {
result.fullscreen = false;
}
return result;
});
const getBindValue = computed((): Recordable => {
const attr = {
...attrs,
...unref(getMergeProps),
open: unref(visibleRef),
wrapClassName: unref(getWrapClassName),
};
if (unref(fullScreenRef)) {
return omit(attr, ['height', 'visible']);
}
return omit(attr, ['visible']);
});
//warpClassName
const getWrapClassName = computed(() => {
const clsName = toRef(getMergeProps.value, 'wrapClassName').value || '';
return unref(fullScreenRef) ? `jeecg-full-screen-modal-code-generate ${clsName} ` : unref(clsName);
});
//props
const getProps = computed((): Recordable => {
const opt = {
...unref(getMergeProps),
visible: unref(visibleRef),
okButtonProps: undefined,
cancelButtonProps: undefined,
title: undefined,
};
return {
...opt,
wrapClassName: unref(getWrapClassName),
};
});
//model,instance.uid model
const instance = getCurrentInstance();
if (instance) {
emit('register', modalMethods, instance.uid);
}
/**
* 是否含有标题
*/
function isNoTitle() {
//
return !unref(getMergeProps).title && !slots.title;
}
/**
* 放大缩小事件
* @param e
*/
function handleFullScreen(e: Event) {
e?.stopPropagation();
e?.preventDefault();
fullScreenRef.value = !unref(fullScreenRef);
}
//
async function handleCancel(e: Event) {
e?.stopPropagation();
//
if (props.closeFunc && isFunction(props.closeFunc)) {
const isClose: boolean = await props.closeFunc();
visibleRef.value = !isClose;
return;
}
visibleRef.value = false;
emit('cancel', e);
}
/**
* 确定事件
* @param e
*/
function handleOk(e: Event) {
emit('ok', e);
}
function handleTitleDbClick(e) {
if (!props.fullscreen) return;
e.stopPropagation();
handleFullScreen(e);
}
/**
* 设置modal参数
*/
function setModalProps(props: Partial<ModalProps>): void {
// Keep the last setModalProps
propsRef.value = deepMerge(unref(propsRef) || ({} as any), props);
if (Reflect.has(props, 'visible')) {
visibleRef.value = !!props.visible;
}
if (Reflect.has(props, 'open')) {
visibleRef.value = !!props.open;
}
if (Reflect.has(props, 'defaultFullscreen')) {
fullScreenRef.value = !!props.defaultFullscreen;
if (getIsMobile.value) {
fullScreenRef.value = true;
}
}
}
/**
* 监听放大缩小
*/
watchEffect(() => {
fullScreenRef.value = props.fullscreen;
if (getIsMobile.value) {
fullScreenRef.value = true;
}
});
/**
* 监听model的显示隐藏
*/
watchEffect(() => {
visibleRef.value = !!props.visible;
});
/**
* 监听model的显示隐藏
*/
watchEffect(() => {
visibleRef.value = !!props.open;
});
watch(
() => unref(visibleRef),
(v) => {
emit('visible-change', v);
emit('open-change', v);
emit('update:visible', v);
emit('update:open', v);
instance && modalMethods.emitVisible?.(v, instance.uid);
},
{
immediate: false,
}
);
return {
isNoTitle,
getBindValue,
fullScreenRef,
handleFullScreen,
fullScreen,
t,
handleCancel,
handleOk,
getProps,
getMergeProps,
handleTitleDbClick,
bodyStyle,
};
},
});
</script>
<style lang="less" scoped>
/*begin 放大关闭按钮样式*/
.jeecg-basic-modal-close {
display: flex;
height: 95%;
align-items: center;
> span {
margin-left: 10px;
font-size: 16px;
}
&--can-full {
> span {
margin-left: 12px;
}
}
&:not(&--can-full) {
> span:nth-child(1) {
&:hover {
font-weight: 700;
}
}
}
& span:nth-child(1) {
display: inline-block;
padding: 10px;
&:hover {
color: @primary-color;
}
}
& span:last-child {
padding: 10px 10px 10px 0;
&:hover {
color: @error-color;
}
}
}
/*end 放大关闭按钮样式*/
</style>
<style lang="less">
/*begin 全屏弹窗modal样式*/
.jeecg-full-screen-modal-code-generate {
.ant-modal {
max-width: 100%;
top: 0 !important;
padding-bottom: 0 !important;
margin: 0 !important;
width: 100% !important;
overflow-y: auto;
}
.ant-modal-content {
display: flex;
flex-direction: column;
height: calc(100vh);
}
.ant-modal-body {
flex: 1;
overflow-y: auto;
}
}
/*end 全屏弹窗modal样式*/
</style>

View File

@ -46,34 +46,50 @@
useWindowSizeFn(setModalHeight.bind(null, false));
// update-begin--author:liaozhiyang---date:2024-04-18---forQQYUN-9035basicModalmaxHeightheightsetModalHeight使MutationObserver
// update-begin--author:liaozhiyang---date:2024-05-30---forTV360X-145
let observer,
recordCount: any = {};
if (!(props.maxHeight || props.height)) {
observer = useMutationObserver(
spinRef,
() => {
setModalHeight({
source: 'muob',
callBack: (height) => {
const count = recordCount[height];
if (count) {
recordCount[height] = ++recordCount[height];
if (count > 5) {
observer.stop();
recordCount = null;
}
} else {
recordCount[height] = 1;
}
watch(
() => props.visible,
() => {
if (props.visible && !observer && !(props.maxHeight || props.height)) {
recordCount = {};
observer = useMutationObserver(
spinRef,
() => {
setModalHeight({
source: 'muob',
callBack: (height) => {
const count = recordCount[height];
if (count) {
recordCount[height] = ++recordCount[height];
if (count > 10) {
observer.stop();
recordCount = {};
observer = null;
}
} else {
recordCount = {};
recordCount[height] = 1;
}
},
});
},
});
},
{
attributes: true,
subtree: true,
{
attributes: true,
subtree: true,
}
);
} else {
if (observer) {
observer.stop();
observer = null;
}
}
);
}
},
{ immediate: true }
);
// update-end--author:liaozhiyang---date:2024-05-30---forTV360X-145
// update-end--author:liaozhiyang---date:2024-04-18---forQQYUN-9035basicModalmaxHeightheightsetModalHeight使MutationObserver
createModalContext({

View File

@ -3,12 +3,12 @@
v-bind="getBindValues"
:activeName="activeName"
:openNames="getOpenKeys"
:class="prefixCls"
:class="`${prefixCls} ${isThemeBright ? 'bright' : ''}`"
:activeSubMenuNames="activeSubMenuNames"
@select="handleSelect"
>
<template v-for="item in items" :key="item.path">
<SimpleSubMenu :item="item" :parent="true" :collapsedShowTitle="collapsedShowTitle" :collapse="collapse" />
<SimpleSubMenu :isThemeBright="isThemeBright" :item="item" :parent="true" :collapsedShowTitle="collapsedShowTitle" :collapse="collapse" />
</template>
</Menu>
</template>
@ -29,6 +29,7 @@
import { useOpenKeys } from './useOpenKeys';
import { URL_HASH_TAB } from '/@/utils';
import { useAppStore } from '/@/store/modules/app';
export default defineComponent({
name: 'SimpleMenu',
@ -56,6 +57,8 @@
setup(props, { attrs, emit }) {
const currentActiveMenu = ref('');
const isClickGo = ref(false);
const appStore = useAppStore();
const isThemeBright = ref(false);
const menuState = reactive<MenuState>({
activeName: '',
@ -93,7 +96,15 @@
},
{ flush: 'post' }
);
// update-begin--author:liaozhiyang---date:20240408---forQQYUN-8922
watch(
() => appStore.getProjectConfig.menuSetting,
(menuSetting) => {
isThemeBright.value = !!menuSetting?.isThemeBright;
},
{ immediate: true, deep: true }
);
// update-end--author:liaozhiyang---date:20240408---forQQYUN-8922
listenerRouteChange((route) => {
if (route.name === REDIRECT_NAME) return;
@ -174,6 +185,7 @@
handleSelect,
getOpenKeys,
...toRefs(menuState),
isThemeBright,
};
},
});

View File

@ -11,7 +11,13 @@
<SimpleMenuTag :item="item" :collapseParent="getIsCollapseParent" />
</template>
</MenuItem>
<SubMenu :name="item.path" v-if="menuHasChildren(item) && getShowMenu" :class="[getLevelClass, theme]" :collapsedShowTitle="collapsedShowTitle">
<SubMenu
:isThemeBright="isThemeBright"
:name="item.path"
v-if="menuHasChildren(item) && getShowMenu"
:class="[getLevelClass, theme]"
:collapsedShowTitle="collapsedShowTitle"
>
<template #title>
<Icon v-if="getIcon" :icon="getIcon" :size="16" />
@ -25,7 +31,7 @@
<SimpleMenuTag :item="item" :collapseParent="!!collapse && !!parent" />
</template>
<template v-for="childrenItem in item.children || []" :key="childrenItem.path">
<SimpleSubMenu v-bind="$props" :item="childrenItem" :parent="false" />
<SimpleSubMenu v-bind="$props" :isThemeBright="isThemeBright" :item="childrenItem" :parent="false" />
</template>
</SubMenu>
</template>
@ -60,6 +66,12 @@
collapsedShowTitle: propTypes.bool,
collapse: propTypes.bool,
theme: propTypes.oneOf(['dark', 'light']),
// update-begin--author:liaozhiyang---date:20240417---for:QQYUN-8927
isThemeBright: {
type: Boolean,
default: false,
},
// update-end--author:liaozhiyang---date:20240417---for:QQYUN-8927
},
setup(props) {
const { t } = useI18n();

View File

@ -37,7 +37,7 @@
<!-- eslint-disable-next-line -->
<template #content v-show="opened">
<div v-bind="getEvents(true)">
<ul :class="[prefixCls, `${prefixCls}-${getTheme}`, `${prefixCls}-popup`]">
<ul :class="[prefixCls, `${prefixCls}-${getTheme}`, `${prefixCls}-popup`, `${isThemeBright && 'bright'}`]">
<slot></slot>
</ul>
</div>
@ -75,6 +75,12 @@
},
disabled: propTypes.bool,
collapsedShowTitle: propTypes.bool,
// update-begin--author:liaozhiyang---date:20240417---for:QQYUN-8927
isThemeBright: {
type: Boolean,
default: false,
},
// update-end--author:liaozhiyang---date:20240417---for:QQYUN-8927
},
setup(props) {
const instance = getCurrentInstance();
@ -128,9 +134,11 @@
const getTheme = computed(() => rootProps.theme);
const getOverlayStyle = computed((): CSSProperties => {
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8774
return {
minWidth: '200px',
minWidth: '150px',
};
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8774
});
const getIsOpend = computed(() => {

View File

@ -36,7 +36,7 @@
&-submenu-title {
position: relative;
z-index: 1;
padding: 12px 20px;
padding: 10px 14px;
color: @menu-dark-subsidiary-color;
cursor: pointer;
transition: all @transition-time @ease-in-out;
@ -65,6 +65,16 @@
background-color: @primary-color !important;
}
}
// 彩色模式(绿色,橘红等)
&.bright {
.@{menu-prefix-cls}-item,
.@{menu-prefix-cls}-submenu-title {
color: #fff;
&:hover {
color: rgba(255, 255, 255, 0.8);
}
}
}
}
&-light {
@ -108,7 +118,15 @@
&-light {
background-color: #fff;
color: rgba(0, 0, 0, 0.65);
.@{menu-prefix-cls} {
color: rgba(0, 0, 0, 0.65);
}
.@{namespace}-menu-submenu:not(.@{namespace}-menu-item-active) .@{namespace}-menu-submenu-title {
.anticon {
color: rgba(0, 0, 0, 0.9);
}
}
.@{menu-prefix-cls}-submenu-active {
color: @primary-color !important;
@ -129,7 +147,6 @@
z-index: 1;
display: flex;
font-size: @font-size-base;
color: inherit;
list-style: none;
cursor: pointer;
outline: none;
@ -262,6 +279,20 @@
color: #fff;
}
}
// update-begin--author:liaozhiyang---date:20240408---for【QQYUN-8922】左侧导航栏文字颜色调整区分彩色和暗黑
&-dark&-vertical&.bright &-item,
&-dark&-vertical.bright &-submenu-title {
color: rgba(255, 255, 255, 1);
&-active:not(.@{menu-prefix-cls}-submenu) {
color: #fff !important;
background-color: @primary-color !important;
}
&:hover {
color: rgba(255, 255, 255, 0.8);
}
}
// update-end--author:liaozhiyang---date:20240408---for【QQYUN-8922】左侧导航栏文字颜色调整区分彩色和暗黑
&-dark&-vertical&-collapse {
> li.@{menu-prefix-cls}-item-active,

View File

@ -3,7 +3,7 @@
<BasicForm
submitOnReset
v-bind="getFormProps"
v-if="getBindValues.useSearchForm"
v-if="getBindValues.useSearchForm && getBindValues.formConfig?.schemas?.length"
:tableAction="tableAction"
@register="registerForm"
@submit="handleSearchInfoChange"
@ -17,37 +17,47 @@
<!-- antd v3 升级兼容阻止数据的收集防止控制台报错 -->
<!-- https://antdv.com/docs/vue/migration-v3-cn -->
<a-form-item-rest>
<Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable" @resizeColumn="handleResizeColumn" @change="handleTableChange">
<!-- antd的原生插槽直接传递 -->
<template #[item]="data" v-for="item in slotNamesGroup.native" :key="item">
<!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
<template v-if="item === 'headerCell'">
<CustomSelectHeader v-if="isCustomSelection(data.column)" v-bind="selectHeaderProps" />
<!-- TV360X-377关联记录必填影响到了table的输入框和页码样式 -->
<a-form-item>
<Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable" @resizeColumn="handleResizeColumn" @change="handleTableChange">
<!-- antd的原生插槽直接传递 -->
<template #[item]="data" v-for="item in slotNamesGroup.native" :key="item">
<!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
<template v-if="item === 'headerCell'">
<CustomSelectHeader v-if="isCustomSelection(data.column)" v-bind="selectHeaderProps" />
<slot v-else :name="item" v-bind="data || {}"></slot>
</template>
<slot v-else :name="item" v-bind="data || {}"></slot>
<!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
</template>
<slot v-else :name="item" v-bind="data || {}"></slot>
<!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
</template>
<template #headerCell="{ column }">
<!-- update-begin--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 -->
<CustomSelectHeader v-if="isCustomSelection(column)" v-bind="selectHeaderProps"/>
<HeaderCell v-else :column="column" />
<!-- update-end--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 -->
</template>
<!-- 增加对antdv3.x兼容 -->
<template #bodyCell="data">
<!-- update-begin--author:liaozhiyang---date:220230717---forissues-179antd3 一些警告以及报错(针对表格) -->
<!-- update-begin--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<template v-if="data.column?.slotsBak?.customRender">
<!-- update-end--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot>
<template #headerCell="{ column }">
<!-- update-begin--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 -->
<CustomSelectHeader v-if="isCustomSelection(column)" v-bind="selectHeaderProps"/>
<HeaderCell v-else :column="column" />
<!-- update-end--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 -->
</template>
<template v-else>
<slot name="bodyCell" v-bind="data || {}"></slot>
<!-- 增加对antdv3.x兼容 -->
<template #bodyCell="data">
<!-- update-begin--author:liaozhiyang---date:220230717---forissues-179antd3 一些警告以及报错(针对表格) -->
<!-- update-begin--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<template v-if="data.column?.slotsBak?.customRender">
<!-- update-end--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot>
</template>
<template v-else>
<slot name="bodyCell" v-bind="data || {}"></slot>
</template>
<!-- update-begin--author:liaozhiyang---date:22030717---forissues-179antd3 一些警告以及报错(针对表格) -->
</template>
<!-- update-begin--author:liaozhiyang---date:22030717---forissues-179antd3 一些警告以及报错(针对表格) -->
</template>
</Table>
<!-- update-begin--author:liaozhiyang---date:20240425---forpull/1201添加antd的TableSummary功能兼容老的summary表尾合计 -->
<template v-if="showSummaryRef && !getBindValues.showSummary" #summary="data">
<slot name="summary" v-bind="data || {}">
<TableSummary :data="data || {}" v-bind="getSummaryProps" />
</slot>
</template>
<!-- update-end--author:liaozhiyang---date:20240425---forpull/1201添加antd的TableSummary功能兼容老的summary表尾合计 -->
</Table>
</a-form-item>
</a-form-item-rest>
</div>
</template>
@ -61,6 +71,7 @@
import CustomSelectHeader from './components/CustomSelectHeader.vue'
import expandIcon from './components/ExpandIcon';
import HeaderCell from './components/HeaderCell.vue';
import TableSummary from './components/TableSummary';
import { InnerHandlers } from './types/table';
import { usePagination } from './hooks/usePagination';
import { useColumns } from './hooks/useColumns';
@ -78,7 +89,7 @@
import { useDesign } from '/@/hooks/web/useDesign';
import { useCustomSelection } from "./hooks/useCustomSelection";
import { omit } from 'lodash-es';
import { omit, pick } from 'lodash-es';
import { basicProps } from './props';
import { isFunction } from '/@/utils/is';
import { warn } from '/@/utils/log';
@ -88,6 +99,7 @@
Table,
BasicForm,
HeaderCell,
TableSummary,
CustomSelectHeader,
},
props: basicProps,
@ -232,6 +244,18 @@
};
const { getHeaderProps } = useTableHeader(getProps, slots, handlers);
// update-begin--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
const getSummaryProps = computed(() => {
return pick(unref(getProps), ['summaryFunc', 'summaryData', 'hasExpandedRow', 'rowKey']);
});
const getIsEmptyData = computed(() => {
return (unref(getDataSourceRef) || []).length === 0;
});
const showSummaryRef = computed(() => {
const summaryProps = unref(getSummaryProps);
return (summaryProps.summaryFunc || summaryProps.summaryData) && !unref(getIsEmptyData);
});
// update-end--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
const { getFooterProps } = useTableFooter(getProps, slots, getScrollRef, tableElRef, getDataSourceRef);
@ -266,7 +290,7 @@
/*if (slots.expandedRowRender) {
propsData = omit(propsData, 'scroll');
}*/
//update-end---author:wangshuai ---date:20230214 for[QQYUN-4237] ------------
//update-end---author:wangshuai ---date:20230214 for[QQYUN-4237] ------------
// update-begin--author:sunjianlei---date:220230630---forQQYUN-5571
//
@ -414,6 +438,10 @@
isCustomSelection,
// update-end--author:sunjianlei---date:220230630---forQQYUN-5571
slotNamesGroup,
// update-begin--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
getSummaryProps,
showSummaryRef,
// update-end--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
};
},
});
@ -563,5 +591,10 @@
}
}
// update-end--author:sunjianlei---date:220230718---forissues/622
// update-begin--author:liaozhiyang---date:20240604---forTV360X-377table
> .ant-form-item {
margin-bottom: 0;
}
// update-end--author:liaozhiyang---date:20240604---forTV360X-377table
}
</style>

View File

@ -19,7 +19,13 @@
<Divider type="vertical" class="action-divider" v-if="divider && index < getActions.length - 1" />
</template>
<Dropdown :trigger="['hover']" :dropMenuList="getDropdownList" popconfirm v-if="dropDownActions && getDropdownList.length > 0">
<Dropdown
:overlayClassName="dropdownCls"
:trigger="['hover']"
:dropMenuList="getDropdownList"
popconfirm
v-if="dropDownActions && getDropdownList.length > 0"
>
<slot name="more"></slot>
<!-- 设置插槽 -->
<template v-slot:[item.slot] v-for="(item, index) in getDropdownSlotList" :key="`${index}-${item.label}`">
@ -63,6 +69,7 @@
},
setup(props) {
const { prefixCls } = useDesign('basic-table-action');
const dropdownCls = `${prefixCls}-dropdown`;
let table: Partial<TableActionType> = {};
if (!props.outside) {
table = useTableContext();
@ -189,8 +196,8 @@
});
isInButton && e.stopPropagation();
}
return { prefixCls, getActions, getDropdownList, getDropdownSlotList, getAlign, onCellClick, getTooltip };
return { prefixCls, getActions, getDropdownList, getDropdownSlotList, getAlign, onCellClick, getTooltip, dropdownCls };
},
});
</script>
@ -258,5 +265,19 @@
// update-end--author:liaozhiyang---date:20240124---forissues/1019popConfirm
}
}
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762tableant-dropdown
&-dropdown {
.ant-dropdown-menu .ant-dropdown-menu-item-divider {
margin: 2px 0;
}
.ant-dropdown-menu .ant-dropdown-menu-item {
padding: 3px 8px;
font-size: 13.6px;
}
.dropdown-event-area {
padding: 0 !important;
}
}
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762tableant-dropdown
}
</style>

View File

@ -0,0 +1,163 @@
import type { PropType, VNode } from 'vue';
import { defineComponent, unref, computed, isVNode } from 'vue';
import { cloneDeep, pick } from 'lodash-es';
import { isFunction } from '/@/utils/is';
import type { BasicColumn } from '../types/table';
import { INDEX_COLUMN_FLAG } from '../const';
import { propTypes } from '/@/utils/propTypes';
import { useTableContext } from '../hooks/useTableContext';
import { TableSummary, TableSummaryRow, TableSummaryCell } from 'ant-design-vue';
const SUMMARY_ROW_KEY = '_row';
const SUMMARY_INDEX_KEY = '_index';
export default defineComponent({
name: 'BasicTableSummary',
components: { TableSummary, TableSummaryRow, TableSummaryCell },
props: {
summaryFunc: {
type: Function as PropType<Fn>,
},
summaryData: {
type: Array as PropType<Recordable[]>,
},
rowKey: propTypes.string.def('key'),
// 是否有展开列
hasExpandedRow: propTypes.bool,
data: {
type: Object as PropType<Recordable>,
default: () => {},
},
},
setup(props) {
const table = useTableContext();
const getDataSource = computed((): Recordable[] => {
const {
summaryFunc,
summaryData,
data: { pageData },
} = props;
if (summaryData?.length) {
summaryData.forEach((item, i) => (item[props.rowKey] = `${i}`));
return summaryData;
}
if (!isFunction(summaryFunc)) {
return [];
}
let dataSource = cloneDeep(unref(pageData));
dataSource = summaryFunc(dataSource);
dataSource.forEach((item, i) => {
item[props.rowKey] = `${i}`;
});
return dataSource;
});
const getColumns = computed(() => {
const dataSource = unref(getDataSource);
let columns: BasicColumn[] = cloneDeep(table.getColumns({ sort: true }));
columns = columns.filter((item) => !item.defaultHidden);
const index = columns.findIndex((item) => item.flag === INDEX_COLUMN_FLAG);
const hasRowSummary = dataSource.some((item) => Reflect.has(item, SUMMARY_ROW_KEY));
const hasIndexSummary = dataSource.some((item) => Reflect.has(item, SUMMARY_INDEX_KEY));
// 是否有序号列
let hasIndexCol = false;
// 是否有选择列
const hasSelection = table.getRowSelection() && hasRowSummary;
if (index !== -1) {
if (hasIndexSummary) {
hasIndexCol = true;
columns[index].customSummaryRender = ({ record }) => record[SUMMARY_INDEX_KEY];
columns[index].ellipsis = false;
} else {
Reflect.deleteProperty(columns[index], 'customSummaryRender');
}
}
if (hasSelection) {
const isFixed = columns.some((col) => col.fixed === 'left' || col.fixed === true);
columns.unshift({
width: 60,
title: 'selection',
key: 'selectionKey',
align: 'center',
...(isFixed ? { fixed: 'left' } : {}),
customSummaryRender: ({ record }) => (hasIndexCol ? '' : record[SUMMARY_ROW_KEY]),
});
}
if (props.hasExpandedRow) {
const isFixed = columns.some((col) => col.fixed === 'left');
columns.unshift({
width: 50,
title: 'expandedRow',
key: 'expandedRowKey',
align: 'center',
...(isFixed ? { fixed: 'left' } : {}),
customSummaryRender: () => '',
});
}
return columns;
});
function isRenderCell(data: any) {
return data && typeof data === 'object' && !Array.isArray(data) && !isVNode(data);
}
const getValues = (row: Recordable, col: BasicColumn, index: number) => {
const value = row[col.dataIndex as string];
let childNode: VNode | JSX.Element | string | number | undefined | null;
childNode = value;
if (col.customSummaryRender) {
const renderData = col.customSummaryRender({
text: value,
value,
record: row,
index,
column: cloneDeep(col),
});
if (isRenderCell(renderData)) {
childNode = renderData.children;
} else {
childNode = renderData;
}
if (typeof childNode === 'object' && !Array.isArray(childNode) && !isVNode(childNode)) {
childNode = null;
}
if (Array.isArray(childNode) && childNode.length === 1) {
childNode = childNode[0];
}
return childNode;
}
return childNode;
};
const getCellProps = (col: BasicColumn) => {
const cellProps = pick(col, ['colSpan', 'rowSpan', 'align']);
return {
...cellProps,
};
};
return () => {
return (
<TableSummary fixed>
{(unref(getDataSource) || []).map((row) => {
return (
<TableSummaryRow key={row[props.rowKey]}>
{unref(getColumns).map((col, index) => {
return (
<TableSummaryCell {...getCellProps(col)} index={index} key={`${row[props.rowKey]}_${col.dataIndex}_${index}`}>
{getValues(row, col, index)}
</TableSummaryCell>
);
})}
</TableSummaryRow>
);
})}
</TableSummary>
);
};
},
});

View File

@ -142,9 +142,9 @@
setup(props, { emit, attrs }) {
const { t } = useI18n();
const table = useTableContext();
const popoverVisible = ref(true);
const popoverVisible = ref(false);
// update-begin--author:sunjianlei---date:20221101---for:
nextTick(() => popoverVisible.value = false);
// nextTick(() => popoverVisible.value = false);
// update-end--author:sunjianlei---date:20221101---for:
const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys');
let inited = false;
@ -311,7 +311,9 @@
// Open the pop-up window for drag and drop initialization
function handleVisibleChange() {
if (inited) return;
nextTick(() => {
// update-begin--author:liaozhiyang---date:20240529---forTV360X-254
setTimeout(() => {
// update-begin--author:liaozhiyang---date:20240529---forTV360X-254
const columnListEl = unref(columnListRef);
if (!columnListEl) return;
const el = columnListEl.$el as any;
@ -340,14 +342,14 @@
plainSortOptions.value = columns;
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-6424table
if(state.checkedList.length != columns.length){
const cols = columns.map(item => item.value);
const arr = cols.filter((cItem) => state.checkedList.find((lItem) => lItem === cItem));
setColumns(arr);
} else {
setColumns(columns);
}
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-6424table
// update-begin--author:liaozhiyang---date:20240522---forTV360X-108
const cols = columns.map((item) => item.value);
const arr = cols.filter((cItem) => state.checkedList.find((lItem) => lItem === cItem));
setColumns(arr);
//
// setColumns(columns);
// update-end--author:liaozhiyang---date:20240522---forTV360X-108
// update-end--author:liaozhiyang---date:20230904---forQQYUN-6424table
},
});
// order
@ -355,7 +357,7 @@
sortableOrder.value = sortable.toArray();
}
inited = true;
});
}, 2000);
}
// Control whether the serial number column is displayed
@ -516,6 +518,16 @@
// flex-wrap: wrap;
}
// update-begin--author:liaozhiyang---date:20240529---forTV360X-254
&.ant-popover,
.ant-popover-content,
.ant-popover-inner,
.ant-popover-inner-content,
.scroll-container,
.scrollbar__wrap {
max-width: min-content;
}
// update-end--author:liaozhiyang---date:20240529---forTV360X-254
.scrollbar {
height: 220px;
}

View File

@ -8,8 +8,8 @@
<ColumnHeightOutlined />
<template #overlay>
<Menu @click="handleTitleClick" selectable v-model:selectedKeys="selectedKeysRef">
<MenuItem key="default">
<span>{{ t('component.table.settingDensDefault') }}</span>
<MenuItem key="large">
<span>{{ t('component.table.settingDensLarge') }}</span>
</MenuItem>
<MenuItem key="middle">
<span>{{ t('component.table.settingDensMiddle') }}</span>
@ -30,6 +30,8 @@
import { useI18n } from '/@/hooks/web/useI18n';
import { useTableContext } from '../../hooks/useTableContext';
import { getPopupContainer } from '/@/utils';
import { useRoute } from 'vue-router';
import { createLocalStorage } from '/@/utils/cache';
export default defineComponent({
name: 'SizeSetting',
@ -46,6 +48,8 @@
setup(props) {
const table = useTableContext();
const { t } = useI18n();
const $ls = createLocalStorage();
const route = useRoute();
const selectedKeysRef = ref<SizeType[]>([table.getSize()]);
const getBindProps = computed(() => {
@ -60,7 +64,28 @@
table.setProps({
size: key,
});
// update-begin--author:liaozhiyang---date:20240604---forTV360X-100
$ls.set(cacheKey.value, key);
// update-end--author:liaozhiyang---date:20240604---forTV360X-100
}
// update-begin--author:liaozhiyang---date:20240604---forTV360X-100
const cacheKey = computed(() => {
const path = route.path;
let key = path.replace(/[\/\\]/g, '_');
let cacheKey = table.getBindValues.value.tableSetting?.cacheKey;
if (cacheKey) {
key += ':' + cacheKey;
}
return 'tableSizeCache:' + key;
});
const local: SizeType | null = $ls.get(cacheKey.value);
if (local) {
selectedKeysRef.value = [local];
table.setProps({
size: local,
});
}
// update-end--author:liaozhiyang---date:20240604---forTV360X-100
return {
getBindProps,

View File

@ -75,6 +75,11 @@ export function useCustomRow(
}
setSelectedRowKeys([key]);
return;
} else {
// update-begin--author:liaozhiyang---date:20240527---for【TV360X-359】erp主表点击已选中的选到了最后一个
// 点击已经选中的直接return不在做操作
return;
// update-end--author:liaozhiyang---date:20240527---for【TV360X-359】erp主表点击已选中的选到了最后一个
}
clearSelectedRowKeys();
}

View File

@ -120,7 +120,10 @@ export function useCustomSelection(
onSelectAll,
isRadio: isRadio.value,
selectedLength: flattedData.value.filter((data) => selectedKeys.value.includes(getRecordKey(data))).length,
pageSize: currentPageSize.value,
// update-begin--author:liaozhiyang---date:20240511---for【QQYUN-9289】解决表格条数不足pageSize数量时行数全部勾选但是全选框不勾选
// 【TV360X-53】为空时会报错加强判断
pageSize: tableData.value?.length ?? 0,
// update-end--author:liaozhiyang---date:20240511---for【QQYUN-9289】解决表格条数不足pageSize数量时行数全部勾选但是全选框不勾选
// 【QQYUN-6774】解决checkbox禁用后全选仍能勾选问题
disabled: flattedData.value.length == 0,
hideSelectAll: unref(propsRef)?.rowSelection?.hideSelectAll,
@ -225,9 +228,14 @@ export function useCustomSelection(
// update-end--author:liaozhiyang---date:20231122---for【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件
// 取消全选
if (!checked) {
selectedKeys.value = [];
selectedRows.value = [];
emitChange('all');
// update-begin--author:liaozhiyang---date:20240510---for【issues/1173】取消全选只是当前页面取消
// selectedKeys.value = [];
// selectedRows.value = [];
// emitChange('all');
flattedData.value.forEach((item) => {
updateSelected(item, false);
});
// update-end--author:liaozhiyang---date:20240510---for【issues/1173】取消全选只是当前页面取消
return;
}
let modal: Nullable<ReturnType<ModalFunc>> = null;
@ -625,3 +633,4 @@ function flattenData<RecordType>(data: RecordType[] | undefined, childrenColumnN
return list;
}

View File

@ -133,6 +133,10 @@ export function useTableScroll(
}
let height = bottomIncludeBody - (resizeHeightOffset || 0) - paddingHeight - paginationHeight - footerHeight - headerHeight;
// update-begin--author:liaozhiyang---date:20240603---for【TV360X-861】列表查询区域不可往上滚动
// 10+6(外层边距padding:10 + 内层padding-bottom:6)
height -= 16;
// update-end--author:liaozhiyang---date:20240603---for【TV360X-861】列表查询区域不可往上滚动
height = (height < minHeight! ? (minHeight as number) : height) ?? height;
height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;

View File

@ -173,6 +173,9 @@ export interface ColumnProps<T> {
* @type object
*/
customHeaderCell?: (column: ColumnProps<T>) => object;
// update-begin--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
customSummaryRender?: CustomRenderFunction<T> | VNodeChild | JSX.Element;
// update-end--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
/**
* Callback executed when the confirm filter button is clicked, Use as a filter event when using template or jsx

View File

@ -81,7 +81,7 @@ export interface GetColumnsParams {
sort?: boolean;
}
export type SizeType = 'default' | 'middle' | 'small' | 'large';
export type SizeType = 'middle' | 'small' | 'large';
export interface TableActionType {
reload: (opt?: FetchParams) => Promise<void>;
@ -455,6 +455,16 @@ export interface BasicColumn extends ColumnProps<Recordable> {
ifShow?: boolean | ((column: BasicColumn) => boolean);
//compType-用于记录类型
compType?: string;
// update-begin--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
customSummaryRender?: (opt: {
value: any;
text: any;
record: Recordable;
index: number;
renderIndex?: number;
column: BasicColumn;
}) => any | VNodeChild | JSX.Element;
// update-end--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
}
export type ColumnChangeParam = {

View File

@ -1,13 +1,16 @@
<template>
<div :class="prefixCls" :style="{ width: containerWidth }">
<ImgUpload
:fullscreen="fullscreen"
@uploading="handleImageUploading"
@done="handleDone"
v-if="showImageUpload"
v-show="editorRef"
:disabled="disabled"
/>
<div ref="editorRootRef" :class="prefixCls" :style="{ width: containerWidth }">
<!-- update-begin--author:liaozhiyang---date:20240517---forTV360X-35富文本图片上传遮挡其他按钮 -->
<Teleport v-if="imgUploadShow" :to="targetElem">
<ImgUpload
:fullscreen="fullscreen"
@uploading="handleImageUploading"
@done="handleDone"
v-show="editorRef"
:disabled="disabled"
/>
</Teleport>
<!-- update-end--author:liaozhiyang---date:20240517---forTV360X-35富文本图片上传遮挡其他按钮 -->
<Editor :id="tinymceId" ref="elRef" :disabled="disabled" :init="initOptions" :style="{ visibility: 'hidden' }" v-if="!initOptions.inline"></Editor>
<slot v-else></slot>
</div>
@ -27,7 +30,7 @@
import 'tinymce/plugins/lists';
import 'tinymce/plugins/preview';
import 'tinymce/plugins/image';
import { defineComponent, computed, nextTick, ref, unref, watch, onDeactivated, onBeforeUnmount } from 'vue';
import { defineComponent, computed, nextTick, ref, unref, watch, onDeactivated, onBeforeUnmount, onMounted } from 'vue';
import ImgUpload from './ImgUpload.vue';
import {simpleToolbar, menubar, simplePlugins} from './tinymce';
import { buildShortUUID } from '/@/utils/uuid';
@ -39,6 +42,7 @@
import { useAppStore } from '/@/store/modules/app';
import { uploadFile } from '/@/api/common/api';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { ThemeEnum } from '/@/enums/appEnum';
const tinymceProps = {
options: {
type: Object as PropType<Partial<RawEditorSettings>>,
@ -92,6 +96,9 @@
const fullscreen = ref(false);
const tinymceId = ref<string>(buildShortUUID('tiny-vue'));
const elRef = ref<Nullable<HTMLElement>>(null);
const editorRootRef = ref<Nullable<HTMLElement>>(null);
const imgUploadShow = ref(false);
const targetElem = ref<null | HTMLDivElement>(null);
const { prefixCls } = useDesign('tinymce-container');
@ -231,6 +238,7 @@
tinymce
.init(unref(initOptions))
.then((editor) => {
changeColor();
emit('inited', editor);
})
.catch((err) => {
@ -311,7 +319,60 @@
function getUploadingImgName(name: string) {
return `[uploading:${name}]`;
}
// update-begin--author:liaozhiyang---date:20240517---forTV360X-35
let executeCount = 0;
watch(
() => props.showImageUpload,
() => {
mountElem();
}
);
onMounted(() => {
mountElem();
});
const mountElem = () => {
if (executeCount > 20) return;
setTimeout(() => {
if (targetElem.value) {
imgUploadShow.value = props.showImageUpload;
} else {
const toxToolbar = editorRootRef.value?.querySelector('.tox-toolbar__group');
if (toxToolbar) {
const divElem = document.createElement('div');
divElem.setAttribute('style', `width:64px;height:39px;display:flex;align-items:center;`);
toxToolbar!.appendChild(divElem);
targetElem.value = divElem;
imgUploadShow.value = props.showImageUpload;
executeCount = 0;
} else {
mountElem();
}
}
executeCount++;
}, 100);
};
// update-end--author:liaozhiyang---date:20240517---forTV360X-35
// update-begin--author:liaozhiyang---date:20240327---forQQYUN-8639
function changeColor() {
setTimeout(() => {
const iframe = editorRootRef.value?.querySelector('iframe');
const body = iframe?.contentDocument?.querySelector('body');
if (body) {
if (appStore.getDarkMode == ThemeEnum.DARK) {
body.style.color = '#fff';
} else {
body.style.color = '#000';
}
}
}, 300);
}
watch(
() => appStore.getDarkMode,
() => {
changeColor();
}
);
// update-end--author:liaozhiyang---date:20240327---forQQYUN-8639
return {
prefixCls,
containerWidth,
@ -324,6 +385,9 @@
editorRef,
fullscreen,
disabled,
editorRootRef,
imgUploadShow,
targetElem,
};
},
});
@ -342,5 +406,22 @@
z-index: -1;
visibility: hidden;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header {
padding:0;
}
// update-begin--author:liaozhiyang---date:20240527---forTV360X-329
.tox .tox-tbtn--disabled,
.tox .tox-tbtn--disabled:hover,
.tox .tox-tbtn:disabled,
.tox .tox-tbtn:disabled:hover {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23d9d9d9'/%3E%3C/svg%3E");
background-position: left 0;
}
// update-end--author:liaozhiyang---date:20240527---forTV360X-329
}
html[data-theme='dark'] {
.@{prefix-cls} {
.tox .tox-edit-area__iframe {background-color: #141414;}
}
}
</style>

View File

@ -105,11 +105,8 @@
@prefix-cls: ~'@{namespace}-tinymce-img-upload';
.@{prefix-cls} {
position: absolute;
top: 8px;
right: 10px;
z-index: 20;
background-color: @primary-color;
margin: 0 3px;
&.fullscreen {
position: fixed;
z-index: 10000;
@ -119,6 +116,11 @@
padding: 2px 4px;
font-size: 12px;
height: 24px;
// update-begin--author:liaozhiyang---date:20240524---forTV360X-235
&.is-disabled {
color: rgba(255, 255, 255, 0.5);
}
// update-end--author:liaozhiyang---date:20240524---forTV360X-235
}
// update-end--author:liaozhiyang---date:20230326---forQQYUN-8647online tinymce
}

View File

@ -13,7 +13,7 @@ export const toolbar =
export const simplePlugins = 'lists image link fullscreen';
export const simpleToolbar = [
'undo redo formatselect bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent lists image link fullscreen',
'undo redo styles bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent lists image link fullscreen',
];
export const menubar = 'file edit insert view format table';

View File

@ -24,6 +24,12 @@
type: String as PropType<string>,
default: 'calc(100vh - 78px)',
},
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
seriesColor: {
type: String,
default: '#1890ff',
},
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
},
setup(props) {
const chartRef = ref<HTMLDivElement | null>(null);
@ -51,6 +57,7 @@
name: 'bar',
type: 'bar',
data: [],
color: props.seriesColor,
},
],
});
@ -70,6 +77,9 @@
return item.name;
});
option.series[0].data = seriesData;
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
option.series[0].color = props.seriesColor;
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
option.xAxis.data = xAxisData;
setOptions(option);
}

View File

@ -29,6 +29,12 @@
type: String as PropType<string>,
default: 'calc(100vh - 78px)',
},
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
seriesColor: {
type: Array,
default: () => [],
},
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
},
emits: ['click'],
setup(props, { emit }) {
@ -89,6 +95,14 @@
// update-end-author:liusq date:2023-7-12 for: [issues/613] LineMulti
//data
obj['data'] = data;
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
if (props.seriesColor?.length) {
const findItem = props.seriesColor.find((item: any) => item.type === type);
if (findItem?.color) {
obj['color'] = findItem.color;
}
}
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
seriesData.push(obj);
});
option.series = seriesData;

View File

@ -100,7 +100,6 @@
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
color: #000;
margin-top: 4px;
margin-bottom: 0;
font-size: 30px;

View File

@ -25,6 +25,12 @@
type: String as PropType<string>,
default: 'calc(100vh - 78px)',
},
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
seriesColor: {
type: String,
default: '#1890ff',
},
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
},
setup(props) {
const chartRef = ref<HTMLDivElement | null>(null);
@ -93,6 +99,9 @@
}
option.series[0].data[0].name = props.chartData.name;
option.series[0].data[0].value = props.chartData.value;
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
option.series[0].color = props.seriesColor;
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
setOptions(option);
}
return { chartRef };

View File

@ -1,7 +1,7 @@
<template>
<div class="head-info" :class="center && 'center'">
<span>{{ title }}</span>
<p>{{ content }} <a-icon :type="icon" style="font-size: 24px; color: #2b99ff" /></p>
<p :style="{ color: `${$props.iconColor}` }">{{ content }} <a-icon :type="icon" :style="{ fontSize: `24px`, color: `${$props.iconColor}` }" /></p>
<em v-if="bordered" />
</div>
</template>
@ -32,6 +32,12 @@
type: String,
default: false,
},
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
iconColor: {
type: String,
default: '#2b99ff',
},
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
},
});
</script>
@ -49,7 +55,6 @@
}
span {
color: rgba(0, 0, 0, 0.45);
display: inline-block;
font-size: 14px;
line-height: 22px;
@ -57,7 +62,6 @@
}
p {
color: rgba(0, 0, 0, 0.85);
font-size: 24px;
line-height: 32px;
margin: 0;

View File

@ -77,6 +77,12 @@
let seriesData = [];
typeArr.forEach((type) => {
let obj: any = { name: type, type: props.type };
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
const findItem: any = props.chartData.find((item: any) => item.type == type);
if (findItem && findItem.color) {
obj.color = findItem.color;
}
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
// update-begin-author:liusq date:2023-7-12 for: [issues/613] LineMulti
let data = [];
xAxisData.forEach((x) => {

View File

@ -45,12 +45,12 @@
margin-top: 16px;
span {
color: rgba(0, 0, 0, 0.65);
font-size: 14px;
line-height: 22px;
&:first-child {
background-color: #f5f5f5;
color: rgba(0, 0, 0, 0.65);
border-radius: 20px;
display: inline-block;
font-size: 12px;

View File

@ -24,6 +24,12 @@
type: String as PropType<string>,
default: 'calc(100vh - 78px)',
},
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
seriesColor: {
type: String,
default: '#1890ff',
},
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
},
setup(props) {
const chartRef = ref<HTMLDivElement | null>(null);
@ -53,6 +59,7 @@
smooth: true,
areaStyle: {},
data: [],
color: props.seriesColor,
},
],
});
@ -60,7 +67,7 @@
watchEffect(() => {
props.chartData && initCharts();
});
function initCharts() {
if (props.option) {
Object.assign(option, cloneDeep(props.option));
@ -72,6 +79,9 @@
return item.name;
});
option.series[0].data = seriesData;
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762echars
option.series[0].color = props.seriesColor;
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762echars
option.xAxis.data = xAxisData;
setOptions(option);
}

View File

@ -61,76 +61,81 @@
</div>
</div>
<div class="footer">
<a-button type="text" class="delBtn" @click="handleDelSession">
<svg
t="1706504908534"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1584"
width="18"
height="18"
<div class="topArea">
<presetQuestion @outQuestion="handleOutQuestion"></presetQuestion>
</div>
<div class="bottomArea">
<a-button type="text" class="delBtn" @click="handleDelSession">
<svg
t="1706504908534"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1584"
width="18"
height="18"
>
<path
d="M816.872727 158.254545h-181.527272V139.636364c0-39.563636-30.254545-69.818182-69.818182-69.818182h-107.054546c-39.563636 0-69.818182 30.254545-69.818182 69.818182v18.618181H207.127273c-48.872727 0-90.763636 41.890909-90.763637 93.09091s41.890909 90.763636 90.763637 90.763636h609.745454c51.2 0 90.763636-41.890909 90.763637-90.763636 0-51.2-41.890909-93.090909-90.763637-93.09091zM435.2 139.636364c0-13.963636 9.309091-23.272727 23.272727-23.272728h107.054546c13.963636 0 23.272727 9.309091 23.272727 23.272728v18.618181h-153.6V139.636364z m381.672727 155.927272H207.127273c-25.6 0-44.218182-20.945455-44.218182-44.218181 0-25.6 20.945455-44.218182 44.218182-44.218182h609.745454c25.6 0 44.218182 20.945455 44.218182 44.218182 0 23.272727-20.945455 44.218182-44.218182 44.218181zM835.490909 407.272727h-121.018182c-13.963636 0-23.272727 9.309091-23.272727 23.272728s9.309091 23.272727 23.272727 23.272727h97.745455V837.818182c0 39.563636-30.254545 69.818182-69.818182 69.818182h-37.236364V602.763636c0-13.963636-9.309091-23.272727-23.272727-23.272727s-23.272727 9.309091-23.272727 23.272727V907.636364h-118.690909V602.763636c0-13.963636-9.309091-23.272727-23.272728-23.272727s-23.272727 9.309091-23.272727 23.272727V907.636364H372.363636V602.763636c0-13.963636-9.309091-23.272727-23.272727-23.272727s-23.272727 9.309091-23.272727 23.272727V907.636364h-34.909091c-39.563636 0-69.818182-30.254545-69.818182-69.818182V453.818182H558.545455c13.963636 0 23.272727-9.309091 23.272727-23.272727s-9.309091-23.272727-23.272727-23.272728H197.818182c-13.963636 0-23.272727 9.309091-23.272727 23.272728V837.818182c0 65.163636 51.2 116.363636 116.363636 116.363636h451.490909c65.163636 0 116.363636-51.2 116.363636-116.363636V430.545455c0-13.963636-11.636364-23.272727-23.272727-23.272728z"
fill="currentColor"
p-id="1585"
></path>
</svg>
</a-button>
<a-button type="text" class="contextBtn" :class="[usingContext && 'enabled']" @click="handleUsingContext">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--ri"
width="20"
height="20"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10a9.956 9.956 0 0 1-4.708-1.175L2 22l1.176-5.29A9.956 9.956 0 0 1 2 12C2 6.477 6.477 2 12 2m0 2a8 8 0 0 0-8 8c0 1.335.326 2.618.94 3.766l.35.654l-.656 2.946l2.948-.654l.653.349A7.955 7.955 0 0 0 12 20a8 8 0 1 0 0-16m1 3v5h4v2h-6V7z"
></path>
</svg>
</a-button>
<a-textarea
ref="inputRef"
v-model:value="prompt"
:autoSize="{ minRows: 1, maxRows: 6 }"
:placeholder="placeholder"
@pressEnter="handleEnter"
autofocus
></a-textarea>
<a-button
@click="
() => {
handleSubmit();
}
"
:disabled="loading"
type="primary"
class="sendBtn"
>
<path
d="M816.872727 158.254545h-181.527272V139.636364c0-39.563636-30.254545-69.818182-69.818182-69.818182h-107.054546c-39.563636 0-69.818182 30.254545-69.818182 69.818182v18.618181H207.127273c-48.872727 0-90.763636 41.890909-90.763637 93.09091s41.890909 90.763636 90.763637 90.763636h609.745454c51.2 0 90.763636-41.890909 90.763637-90.763636 0-51.2-41.890909-93.090909-90.763637-93.09091zM435.2 139.636364c0-13.963636 9.309091-23.272727 23.272727-23.272728h107.054546c13.963636 0 23.272727 9.309091 23.272727 23.272728v18.618181h-153.6V139.636364z m381.672727 155.927272H207.127273c-25.6 0-44.218182-20.945455-44.218182-44.218181 0-25.6 20.945455-44.218182 44.218182-44.218182h609.745454c25.6 0 44.218182 20.945455 44.218182 44.218182 0 23.272727-20.945455 44.218182-44.218182 44.218181zM835.490909 407.272727h-121.018182c-13.963636 0-23.272727 9.309091-23.272727 23.272728s9.309091 23.272727 23.272727 23.272727h97.745455V837.818182c0 39.563636-30.254545 69.818182-69.818182 69.818182h-37.236364V602.763636c0-13.963636-9.309091-23.272727-23.272727-23.272727s-23.272727 9.309091-23.272727 23.272727V907.636364h-118.690909V602.763636c0-13.963636-9.309091-23.272727-23.272728-23.272727s-23.272727 9.309091-23.272727 23.272727V907.636364H372.363636V602.763636c0-13.963636-9.309091-23.272727-23.272727-23.272727s-23.272727 9.309091-23.272727 23.272727V907.636364h-34.909091c-39.563636 0-69.818182-30.254545-69.818182-69.818182V453.818182H558.545455c13.963636 0 23.272727-9.309091 23.272727-23.272727s-9.309091-23.272727-23.272727-23.272728H197.818182c-13.963636 0-23.272727 9.309091-23.272727 23.272728V837.818182c0 65.163636 51.2 116.363636 116.363636 116.363636h451.490909c65.163636 0 116.363636-51.2 116.363636-116.363636V430.545455c0-13.963636-11.636364-23.272727-23.272727-23.272728z"
fill="currentColor"
p-id="1585"
></path>
</svg>
</a-button>
<a-button type="text" class="contextBtn" :class="[usingContext && 'enabled']" @click="handleUsingContext">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--ri"
width="20"
height="20"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10a9.956 9.956 0 0 1-4.708-1.175L2 22l1.176-5.29A9.956 9.956 0 0 1 2 12C2 6.477 6.477 2 12 2m0 2a8 8 0 0 0-8 8c0 1.335.326 2.618.94 3.766l.35.654l-.656 2.946l2.948-.654l.653.349A7.955 7.955 0 0 0 12 20a8 8 0 1 0 0-16m1 3v5h4v2h-6V7z"
></path>
</svg>
</a-button>
<a-textarea
ref="inputRef"
v-model:value="prompt"
:autoSize="{ minRows: 1, maxRows: 6 }"
:placeholder="placeholder"
@pressEnter="handleEnter"
autofocus
></a-textarea>
<a-button
@click="
() => {
handleSubmit();
}
"
:disabled="loading"
type="primary"
class="sendBtn"
>
<svg
t="1706147858151"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4237"
width="1em"
height="1em"
>
<path
d="M865.28 202.5472c-17.1008-15.2576-41.0624-19.6608-62.5664-11.5712L177.7664 427.1104c-23.2448 8.8064-38.5024 29.696-39.6288 54.5792-1.1264 24.8832 11.9808 47.104 34.4064 58.0608l97.5872 47.7184c4.5056 2.2528 8.0896 6.0416 9.9328 10.6496l65.4336 161.1776c7.7824 19.1488 24.4736 32.9728 44.7488 37.0688 20.2752 4.096 41.0624-2.1504 55.6032-16.7936l36.352-36.352c6.4512-6.4512 16.5888-7.8848 24.576-3.3792l156.5696 88.8832c9.4208 5.3248 19.8656 8.0896 30.3104 8.0896 8.192 0 16.4864-1.6384 24.2688-5.0176 17.8176-7.68 30.72-22.8352 35.4304-41.6768l130.7648-527.1552c5.5296-22.016-1.7408-45.2608-18.8416-60.416z m-20.8896 50.7904L713.5232 780.4928c-1.536 6.2464-5.8368 11.3664-11.776 13.9264s-12.5952 2.1504-18.2272-1.024L526.9504 704.512c-9.4208-5.3248-19.8656-7.9872-30.208-7.9872-15.9744 0-31.744 6.144-43.52 17.92l-36.352 36.352c-3.8912 3.8912-8.9088 5.9392-14.2336 6.0416l55.6032-152.1664c0.512-1.3312 1.2288-2.56 2.2528-3.6864l240.3328-246.1696c8.2944-8.4992-2.048-21.9136-12.3904-16.0768L301.6704 559.8208c-4.096-3.584-8.704-6.656-13.6192-9.1136L190.464 502.9888c-11.264-5.5296-11.5712-16.1792-11.4688-19.3536 0.1024-3.1744 1.536-13.824 13.2096-18.2272L817.152 229.2736c10.4448-3.9936 18.0224 1.3312 20.8896 3.8912 2.8672 2.4576 9.0112 9.3184 6.3488 20.1728z"
p-id="4238"
fill="currentColor"
></path>
</svg>
</a-button>
<svg
t="1706147858151"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4237"
width="1em"
height="1em"
>
<path
d="M865.28 202.5472c-17.1008-15.2576-41.0624-19.6608-62.5664-11.5712L177.7664 427.1104c-23.2448 8.8064-38.5024 29.696-39.6288 54.5792-1.1264 24.8832 11.9808 47.104 34.4064 58.0608l97.5872 47.7184c4.5056 2.2528 8.0896 6.0416 9.9328 10.6496l65.4336 161.1776c7.7824 19.1488 24.4736 32.9728 44.7488 37.0688 20.2752 4.096 41.0624-2.1504 55.6032-16.7936l36.352-36.352c6.4512-6.4512 16.5888-7.8848 24.576-3.3792l156.5696 88.8832c9.4208 5.3248 19.8656 8.0896 30.3104 8.0896 8.192 0 16.4864-1.6384 24.2688-5.0176 17.8176-7.68 30.72-22.8352 35.4304-41.6768l130.7648-527.1552c5.5296-22.016-1.7408-45.2608-18.8416-60.416z m-20.8896 50.7904L713.5232 780.4928c-1.536 6.2464-5.8368 11.3664-11.776 13.9264s-12.5952 2.1504-18.2272-1.024L526.9504 704.512c-9.4208-5.3248-19.8656-7.9872-30.208-7.9872-15.9744 0-31.744 6.144-43.52 17.92l-36.352 36.352c-3.8912 3.8912-8.9088 5.9392-14.2336 6.0416l55.6032-152.1664c0.512-1.3312 1.2288-2.56 2.2528-3.6864l240.3328-246.1696c8.2944-8.4992-2.048-21.9136-12.3904-16.0768L301.6704 559.8208c-4.096-3.584-8.704-6.656-13.6192-9.1136L190.464 502.9888c-11.264-5.5296-11.5712-16.1792-11.4688-19.3536 0.1024-3.1744 1.536-13.824 13.2096-18.2272L817.152 229.2736c10.4448-3.9936 18.0224 1.3312 20.8896 3.8912 2.8672 2.4576 9.0112 9.3184 6.3488 20.1728z"
p-id="4238"
fill="currentColor"
></path>
</svg>
</a-button>
</div>
</div>
</div>
</div>
@ -145,8 +150,9 @@
import { getToken } from '/@/utils/auth';
import { getAppEnvConfig } from '/@/utils/env';
import chatMessage from './chatMessage.vue';
import presetQuestion from './presetQuestion.vue';
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { message, Modal } from 'ant-design-vue';
import { message, Modal, Tabs } from 'ant-design-vue';
import '../style/github-markdown.less';
import '../style/highlight.less';
import '../style/style.less';
@ -165,6 +171,7 @@
return props.uuid;
});
let evtSource: any = null;
// const presetQuestion = ref(['', '', '稿']);
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const conversationList = computed(() => props.chatData.filter((item) => !item.inversion && !!item.conversationOptions));
@ -179,15 +186,17 @@
}
}
function handleSubmit() {
onConversation();
}
async function onConversation() {
let message = prompt.value;
if (loading.value) return;
if (!message || message.trim() === '') return;
loading.value = true;
prompt.value = '';
onConversation(message);
}
const handleOutQuestion = (message) => {
onConversation(message);
};
async function onConversation(message) {
if (loading.value) return;
loading.value = true;
if (props.chatData.length == 0) {
const findItem = props.dataSource.history.find((item) => item.uuid === uuid.value);
@ -225,7 +234,7 @@
if (typeof EventSource !== 'undefined') {
const token = getToken();
evtSource = new EventSourcePolyfill(
`${VITE_GLOB_API_URL}/ai/chat/send?message=${message}${options.parentMessageId ? '&topicId=' + options.parentMessageId : ''}`,
`${VITE_GLOB_API_URL}/test/ai/chat/send?message=${message}${options.parentMessageId ? '&topicId=' + options.parentMessageId : ''}`,
{
withCredentials: true,
headers: {
@ -403,43 +412,52 @@
}
.footer {
display: flex;
align-items: center;
flex-direction: column;
padding: 6px 16px;
.ant-input {
margin: 0 16px;
.topArea {
padding-left: 94px;
margin-bottom: 6px;
}
.ant-input,
.ant-btn {
height: 36px;
}
textarea.ant-input {
padding-top: 6px;
padding-bottom: 6px;
}
.contextBtn,
.delBtn {
padding: 0;
width: 40px;
border-radius: 50%;
.bottomArea {
display: flex;
align-items: center;
justify-content: center;
}
.delBtn {
margin-right: 8px;
}
.contextBtn {
color: #a8071a;
&.enabled {
color: @primary-color;
.ant-input {
margin: 0 16px;
}
.ant-input,
.ant-btn {
height: 36px;
}
textarea.ant-input {
padding-top: 6px;
padding-bottom: 6px;
}
.contextBtn,
.delBtn {
padding: 0;
width: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.delBtn {
margin-right: 8px;
}
.contextBtn {
color: #a8071a;
&.enabled {
color: @primary-color;
}
font-size: 18px;
}
.sendBtn {
padding: 0 10px;
font-size: 22px;
display: flex;
align-items: center;
}
font-size: 18px;
}
.sendBtn {
padding: 0 10px;
font-size: 22px;
display: flex;
align-items: center;
}
}
</style>

View File

@ -23,9 +23,10 @@
import defaultAvatar from '../assets/avatar.jpg';
import { useUserStore } from '/@/store/modules/user';
const props = defineProps(['dateTime', 'text', 'inversion', 'error', 'loading']);
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
const { userInfo } = useUserStore();
const avatar = () => {
return userInfo?.avatar || defaultAvatar;
return getFileAccessHttpUrl(userInfo?.avatar)|| defaultAvatar;
};
</script>

View File

@ -0,0 +1,151 @@
<template>
<div class="presetQuestion-wrap">
<svg
v-if="btnShow"
class="leftBtn"
:class="leftBtnStatus"
t="1710296339017"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="5070"
@click="onScroll('prev')"
>
<path
d="M970.496 543.829333l30.165333-30.165333-415.829333-415.914667a42.837333 42.837333 0 0 0-60.288 0 42.538667 42.538667 0 0 0 0 60.330667l355.413333 355.498667-355.413333 355.285333a42.496 42.496 0 0 0 0 60.288c16.64 16.64 43.861333 16.469333 60.288 0.042667l383.914667-383.701334 1.749333-1.664z"
fill="currentColor"
p-id="5071"
></path>
</svg>
<div class="content">
<ul ref="ulElemRef">
<li v-for="(item, index) in data" :key="index" class="item" @click="handleQuestion(item)">{{ item }}</li>
</ul>
</div>
<svg
v-if="btnShow"
class="rightBtn"
:class="rightBtnStatus"
t="1710296339017"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="5070"
@click="onScroll('next')"
>
<path
d="M970.496 543.829333l30.165333-30.165333-415.829333-415.914667a42.837333 42.837333 0 0 0-60.288 0 42.538667 42.538667 0 0 0 0 60.330667l355.413333 355.498667-355.413333 355.285333a42.496 42.496 0 0 0 0 60.288c16.64 16.64 43.861333 16.469333 60.288 0.042667l383.914667-383.701334 1.749333-1.664z"
fill="currentColor"
p-id="5071"
></path>
</svg>
</div>
</template>
<script name="presetQuestion" setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';
const emit = defineEmits(['outQuestion']);
const data = ref(['请介绍一下JeecgBoot', 'JEECG有哪些优势', 'JEECG可以做哪些事情']);
const leftBtnStatus = ref('');
const rightBtnStatus = ref('');
const rightBtn = ref('');
const ulElemRef = ref(null);
const btnShow = ref(false);
let timer = null;
const handleScroll = (e) => {
clearTimeout(timer);
timer = setTimeout(() => {
const scrollLeft = e.target.scrollLeft;
const offsetWidth = e.target.offsetWidth;
const scrollWidth = e.target.scrollWidth;
if (scrollWidth > offsetWidth) {
btnShow.value = true;
} else {
btnShow.value = false;
}
if (scrollLeft <= 0) {
leftBtnStatus.value = 'disabled';
} else if (scrollWidth - offsetWidth == scrollLeft) {
rightBtnStatus.value = 'disabled';
} else {
leftBtnStatus.value = '';
rightBtnStatus.value = '';
}
}, 100);
};
const onScroll = (flag) => {
const offsetWidth = ulElemRef.value.offsetWidth;
if (flag == 'prev') {
ulElemRef.value.scrollLeft = ulElemRef.value.scrollLeft - offsetWidth;
} else if (flag == 'next') {
ulElemRef.value.scrollLeft = ulElemRef.value.scrollLeft + offsetWidth;
}
};
const handleQuestion = (item) => {
emit('outQuestion', item);
};
onMounted(() => {
ulElemRef.value.addEventListener('scroll', handleScroll, false);
handleScroll({ target: ulElemRef.value });
});
onBeforeUnmount(() => {
ulElemRef.value.removeEventListener('scroll', handleScroll);
});
</script>
<style lang="less" scoped>
.presetQuestion-wrap {
display: flex;
align-items: center;
svg {
width: 14px;
height: 14px;
flex: none;
cursor: pointer;
color: #333;
&.leftBtn {
transform: rotate(180deg);
}
&.disabled {
opacity: 0.5;
pointer-events: none;
cursor: default;
}
}
.content {
flex: 1;
min-width: 0;
overflow: hidden;
}
ul {
display: flex;
margin-bottom: 0;
width: 100%;
overflow-y: auto;
/* 隐藏所有滚动条 */
&::-webkit-scrollbar {
display: none;
height: 0;
width: 0;
}
}
.item {
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 16px;
cursor: pointer;
font-size: 14px;
padding: 2px 10px;
width: max-content;
margin-right: 6px;
white-space: nowrap;
transition: all 300ms ease;
&:last-child {
margin-right: 0;
}
&:hover {
color: @primary-color;
border-color: @primary-color;
}
}
}
</style>

View File

@ -67,6 +67,7 @@
width="1em"
height="1em"
viewBox="0 0 24 24"
@click.stop=""
>
<path
fill="currentColor"
@ -212,6 +213,11 @@
height: 8px;
}
}
.historyArea ul li:hover{
.del{
display: block;
}
}
.createArea {
padding: 20px;
padding-bottom: 0;

View File

@ -33,8 +33,8 @@
import { JEECG_CHAT_KEY } from '/@/enums/cacheEnum';
import { defHttp } from '/@/utils/http/axios';
const configUrl = {
get: '/ai/chat/history/get',
save: '/ai/chat/history/save',
get: '/test/ai/chat/history/get',
save: '/test/ai/chat/history/save',
};
const userId = useUserStore().getUserInfo?.id;
const localKey = JEECG_CHAT_KEY + userId;
@ -199,5 +199,6 @@
margin-left: 0;
}
flex: 1;
min-width: 0;
}
</style>

View File

@ -1,7 +1,8 @@
import { defineComponent, h, ref, useSlots } from 'vue';
import { defineComponent, h, nextTick, ref, useSlots } from 'vue';
import { vxeEmits, vxeProps } from './vxe.data';
import { useData, useRefs, useResolveComponent as rc } from './hooks/useData';
import { useColumns } from './hooks/useColumns';
import { useColumnsCache } from './hooks/useColumnsCache';
import { useMethods } from './hooks/useMethods';
import { useDataSource } from './hooks/useDataSource';
import { useDragSort } from './hooks/useDragSort';
@ -25,6 +26,10 @@ export default defineComponent({
useColumns(props, data, methods, slots);
useDataSource(props, data, methods, refs);
useDragSort(props, methods);
// update-begin--author:liaozhiyang---date:20240321---for【QQYUN-8566】JVXETable无法记住列设置
const { initSetting } = useColumnsCache({ cacheColumnsKey: props.cacheColumnsKey });
initSetting(props);
// update-end--author:liaozhiyang---date:20240321---for【QQYUN-8566】JVXETable无法记住列设置
// 最终传入到 template 里的 props
const finallyProps = useFinallyProps(props, data, methods);
// 渲染子组件

View File

@ -1,6 +1,6 @@
<template>
<div :class="boxClass">
<vxe-toolbar ref="xToolbarRef" custom>
<vxe-toolbar ref="xToolbarRef" :custom="custom">
<!-- 工具按钮 -->
<template #buttons>
<div :class="`${prefixCls}-button div`" :size="btnSize">
@ -41,6 +41,7 @@
const props = defineProps({
size: propTypes.string,
disabled: propTypes.bool.def(false),
custom: propTypes.bool.def(false),
toolbarConfig: propTypes.object,
disabledRows: propTypes.object,
hasBtnAuth: propTypes.func,

View File

@ -1,5 +1,5 @@
<template>
<div :class="boxClass" :style="boxStyle">
<div :class="boxClass" :style="boxStyle" title="">
<a-checkbox :checked="innerValue" v-bind="cellProps" @change="handleChange" />
</div>
</template>

View File

@ -2,12 +2,14 @@
<a-date-picker
:value="innerDateValue"
allowClear
:format="dateFormat"
:format="picker ? null : dateFormat"
:showTime="isDatetime"
:valueFormat="picker ? dateFormat : null"
popupClassName="j-vxe-date-picker"
style="min-width: 0"
v-model:open="openPicker"
v-bind="cellProps"
:picker="picker"
@change="handleChange"
/>
</template>
@ -18,6 +20,7 @@
import { JVxeComponent, JVxeTypes } from '/@/components/jeecg/JVxeTable/types';
import { useJVxeComponent, useJVxeCompProps } from '/@/components/jeecg/JVxeTable/hooks';
import { isEmpty } from '/@/utils/is';
import { getWeekMonthQuarterYear } from '/@/utils';
export default defineComponent({
name: 'JVxeDateCell',
@ -31,6 +34,12 @@
return format ? format : isDatetime.value ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
});
const openPicker = ref(true);
// update-begin--author:liaozhiyang---date:20240509---forQQYUN-9205(jVxetabledate)
const picker = computed(() => {
const picker = originColumn.value.picker;
return picker ? picker : null;
});
// update-end--author:liaozhiyang---date:20240509---forQQYUN-9205(jVxetabledate)
watch(
innerValue,
(val) => {
@ -44,7 +53,13 @@
);
function handleChange(_mom, dateStr) {
handleChangeCommon(dateStr);
// update-begin--author:liaozhiyang---date:20240509---forQQYUN-9205(jVxetabledate)
if (picker.value) {
handleChangeCommon(_mom);
} else {
handleChangeCommon(dateStr);
}
// update-begin--author:liaozhiyang---date:20240509---forQQYUN-9205(jVxetabledate)
}
return {
@ -54,12 +69,26 @@
innerDateValue,
openPicker,
handleChange,
picker,
};
},
// JVxeComponent.Enhanced
enhanced: {
aopEvents: {
},
// update-begin--author:liaozhiyang---date:20240509---forQQYUN-9205(jVxetabledate)
translate: {
enabled: true,
handler(value, ctx) {
let { props, context } = ctx!;
let { row, originColumn } = context;
if (originColumn.value.picker && value) {
return getWeekMonthQuarterYear(value)[originColumn.value.picker];
}
return value;
},
},
// update-end--author:liaozhiyang---date:20240509---forQQYUN-9205(jVxetabledate)
} as JVxeComponent.EnhancedPartial,
});
</script>

View File

@ -1,10 +1,12 @@
<template>
<div class="j-vxe-drag-box">
<a-dropdown :trigger="['click']">
<span v-if="!isAllowDrag"><span class="not-drag-btn"> <Icon icon="mi:drag" /> </span
></span>
<a-dropdown v-else :trigger="['click']" >
<span
><span class="drag-btn"> <Icon icon="mi:drag" /> </span
></span>
<template #overlay>
<template #overlay >
<a-menu>
<a-menu-item key="0" :disabled="disabledMoveUp" @click="handleRowMoveUp"></a-menu-item>
<a-menu-item key="1" :disabled="disabledMoveDown" @click="handleRowMoveDown"></a-menu-item>
@ -27,8 +29,22 @@
components: { Icon },
props: useJVxeCompProps(),
setup(props: JVxeComponent.Props) {
const { rowIndex, fullDataLength, trigger } = useJVxeComponent(props);
const { rowIndex, originColumn, fullDataLength, trigger } = useJVxeComponent(props);
// update-begin--author:liaozhiyang---date:20240417---for:QQYUN-8785onlineidid
const isAllowDrag = computed(() => {
const notAllowDrag = originColumn.value.notAllowDrag;
if (notAllowDrag.length) {
const row = props.params.row;
const find = notAllowDrag.find((item: any) => {
const { key, value } = item;
return row[key] == value;
});
return !find;
} else {
return true;
}
});
// update-end--author:liaozhiyang---date:20240417---for:QQYUN-8785onlineidid
const disabledMoveUp = computed(() => rowIndex.value === 0);
const disabledMoveDown = computed(() => rowIndex.value === fullDataLength.value - 1);
@ -63,6 +79,7 @@
handleRowMoveUp,
handleRowMoveDown,
handleRowInsertDown,
isAllowDrag
};
},
// JVxeComponent.Enhanced
@ -90,3 +107,11 @@
}
}
</style>
<style scoped>
.not-drag-btn {
opacity: 0.5;
.app-iconify {
cursor: not-allowed;
}
}
</style>

View File

@ -26,7 +26,7 @@
components: { LoadingOutlined },
props: useJVxeCompProps(),
setup(props: JVxeComponent.Props) {
const { innerValue, cellProps, row, originColumn, handleChangeCommon, handleBlurCommon } = useJVxeComponent(props);
const { innerValue, cellProps, row, originColumn, scrolling, handleChangeCommon, handleBlurCommon } = useJVxeComponent(props);
const loading = ref(false);
// options
const asyncOptions = ref<any[] | null>(null);
@ -36,7 +36,7 @@
...cellProps.value,
allowClear: true,
autofocus: true,
defaultOpen: true,
defaultOpen: !scrolling.value,
style: { width: '100%' },
filterOption: handleSelectFilterOption,
onBlur: handleBlur,
@ -136,6 +136,9 @@
let { allowSearch, allowInput } = originColumn.value;
if (allowSearch === true || allowInput === true) {
// update-begin--author:liaozhiyang---date:20240321---forQQYUN-5806jsoptions (option.titlenull)
if (option.title == null) return false;
// update-begin--author:liaozhiyang---date:20240321---forQQYUN-5806jsoptions (option.titlenull)
// update-begin--author:liaozhiyang---date:20230904---forissues/5305JVxeTypes.select
return option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0;
// update-begin--author:liaozhiyang---date:20230904---forissues/5305JVxeTypes.select

Some files were not shown because too many files have changed in this diff Show More