Browse Source

Merge pull request #823 from colinin/fix-lost-changes

fix: restore lost changes
pull/830/head
yx lin 3 years ago
committed by GitHub
parent
commit
af44c36a25
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 73
      apps/vue/src/components/Excel/src/Export2Excel.ts
  2. 14
      apps/vue/src/components/Excel/src/typing.ts
  3. 4
      apps/vue/src/components/Form/src/components/ApiSelect.vue
  4. 3
      apps/vue/src/components/Form/src/components/ApiTransfer.vue
  5. 88
      apps/vue/src/components/Form/src/hooks/useFormEvents.ts
  6. 2
      apps/vue/src/components/Form/src/types/form.ts
  7. 63
      apps/vue/src/components/FormDesign/src/components/VFormDesign/modules/CollapseItem.vue
  8. 1
      apps/vue/src/components/Modal/src/BasicModal.vue
  9. 8
      apps/vue/src/components/Table/src/BasicTable.vue
  10. 41
      apps/vue/src/components/Table/src/components/AdvancedSearch.vue
  11. 4
      apps/vue/src/components/Table/src/components/settings/ColumnSetting.vue
  12. 2
      apps/vue/src/components/Table/src/hooks/useTableForm.ts
  13. 8
      apps/vue/src/components/Tree/src/hooks/useTree.ts
  14. 2
      apps/vue/src/components/Upload/src/helper.ts
  15. 33
      apps/vue/src/hooks/web/useECharts.ts
  16. 6
      apps/vue/src/hooks/web/useWatermark.ts
  17. 2
      apps/vue/src/layouts/default/setting/components/SettingFooter.vue
  18. 16
      apps/vue/src/store/modules/app.ts
  19. 8
      apps/vue/src/store/modules/errorLog.ts
  20. 8
      apps/vue/src/store/modules/locale.ts
  21. 4
      apps/vue/src/store/modules/lock.ts
  22. 12
      apps/vue/src/store/modules/multipleTab.ts
  23. 20
      apps/vue/src/store/modules/permission.ts
  24. 24
      apps/vue/src/store/modules/user.ts
  25. 68
      apps/vue/src/views/webhooks/send-attempts/components/SendAttemptModal.vue
  26. 14
      apps/vue/src/views/webhooks/send-attempts/components/SendAttemptTable.vue
  27. 19
      apps/vue/src/views/webhooks/subscriptions/components/SubscriptionModal.vue
  28. 17
      apps/vue/src/views/webhooks/subscriptions/components/SubscriptionTable.vue

73
apps/vue/src/components/Excel/src/Export2Excel.ts

@ -1,17 +1,19 @@
import * as xlsx from 'xlsx';
import type { WorkBook } from 'xlsx';
import type { JsonToSheet, AoAToSheet } from './typing';
import { AoaToMultipleSheet, JsonToMultipleSheet } from './typing';
const { utils, writeFile } = xlsx;
const DEF_FILE_NAME = 'excel-list.xlsx';
const DEF_SHEET_NAME = 'sheet';
/**
* @param data source data
* @param worksheet worksheet object
* @param min min width
*/
function setColumnWidth(data, worksheet, min = 3) {
function setColumnWidth(data, worksheet, min = 3) {
const obj = {};
worksheet['!cols'] = [];
data.forEach((item) => {
@ -32,6 +34,7 @@ export function jsonToSheetXlsx<T = any>({
data,
header,
filename = DEF_FILE_NAME,
sheetName = DEF_SHEET_NAME,
json2sheetOpts = {},
write2excelOpts = { bookType: 'xlsx' },
}: JsonToSheet<T>) {
@ -45,9 +48,9 @@ export function jsonToSheetXlsx<T = any>({
setColumnWidth(arrData, worksheet);
/* add worksheet to workbook */
const workbook: WorkBook = {
SheetNames: [filename],
SheetNames: [sheetName],
Sheets: {
[filename]: worksheet,
[sheetName]: worksheet,
},
};
/* output format determined by filename */
@ -79,3 +82,67 @@ export function aoaToSheetXlsx<T = any>({
writeFile(workbook, filename, write2excelOpts);
/* at this point, out.xlsb will have been downloaded */
}
/**
* json导出多Sheet的Xlsx
* @param sheetList sheet配置
* @param filename ()
* @param write2excelOpts
*/
export function jsonToMultipleSheetXlsx<T = any>({
sheetList,
filename = DEF_FILE_NAME,
write2excelOpts = { bookType: 'xlsx' },
}: JsonToMultipleSheet<T>) {
const workbook: WorkBook = {
SheetNames: [],
Sheets: {},
};
sheetList.forEach((p, index) => {
const arrData = [...p.data];
if (p.header) {
arrData.unshift(p.header);
p.json2sheetOpts = p.json2sheetOpts || {};
p.json2sheetOpts.skipHeader = true;
}
const worksheet = utils.json_to_sheet(arrData, p.json2sheetOpts);
setColumnWidth(arrData, worksheet);
p.sheetName = p.sheetName || `${DEF_SHEET_NAME}${index}`;
workbook.SheetNames.push(p.sheetName);
workbook.Sheets[p.sheetName] = worksheet;
});
writeFile(workbook, filename, write2excelOpts);
}
/**
* aoa导出多Sheet的Xlsx
* @param sheetList sheet配置
* @param filename ()
* @param write2excelOpts
*/
export function aoaToMultipleSheetXlsx<T = any>({
sheetList,
filename = DEF_FILE_NAME,
write2excelOpts = { bookType: 'xlsx' },
}: AoaToMultipleSheet<T>) {
const workbook: WorkBook = {
SheetNames: [],
Sheets: {},
};
sheetList.forEach((p, index) => {
const arrData = [...p.data];
if (p.header) {
arrData.unshift(p.header);
}
const worksheet = utils.aoa_to_sheet(arrData);
p.sheetName = p.sheetName || `${DEF_SHEET_NAME}${index}`;
workbook.SheetNames.push(p.sheetName);
workbook.Sheets[p.sheetName] = worksheet;
});
/* output format determined by filename */
writeFile(workbook, filename, write2excelOpts);
/* at this point, out.xlsb will have been downloaded */
}

14
apps/vue/src/components/Excel/src/typing.ts

@ -10,6 +10,7 @@ export interface JsonToSheet<T = any> {
data: T[];
header?: T;
filename?: string;
sheetName?: string;
json2sheetOpts?: JSON2SheetOpts;
write2excelOpts?: WritingOptions;
}
@ -18,6 +19,7 @@ export interface AoAToSheet<T = any> {
data: T[][];
header?: T[];
filename?: string;
sheetName?: string;
write2excelOpts?: WritingOptions;
}
@ -25,3 +27,15 @@ export interface ExportModalResult {
filename: string;
bookType: BookType;
}
export interface JsonToMultipleSheet<T = any> {
sheetList: JsonToSheet<T>[];
filename?: string;
write2excelOpts?: WritingOptions;
}
export interface AoaToMultipleSheet<T = any> {
sheetList: AoAToSheet<T>[];
filename?: string;
write2excelOpts?: WritingOptions;
}

4
apps/vue/src/components/Form/src/components/ApiSelect.vue

@ -76,10 +76,10 @@
return unref(options).reduce((prev, next: Recordable) => {
if (next) {
const value = next[valueField];
const value = get(next, valueField);
prev.push({
...omit(next, [labelField, valueField]),
label: next[labelField],
label: get(next, labelField),
value: numberToString ? `${value}` : value,
});
}

3
apps/vue/src/components/Form/src/components/ApiTransfer.vue

@ -76,6 +76,9 @@
if (Array.isArray(props.value)) {
return props.value;
}
if (Array.isArray(props.targetKeys)){
return props.targetKeys;
}
return [];
});
function handleChange(keys: string[], direction: TransferDirection, moveKeys: string[]) {

88
apps/vue/src/components/Form/src/hooks/useFormEvents.ts

@ -14,7 +14,7 @@ import {
import { deepMerge } from '/@/utils';
import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper';
import { dateUtil } from '/@/utils/dateUtil';
import { cloneDeep, uniqBy } from 'lodash-es';
import { cloneDeep, set, uniqBy } from 'lodash-es';
import { error } from '/@/utils/log';
interface UseFormActionContext {
@ -27,6 +27,47 @@ interface UseFormActionContext {
schemaRef: Ref<FormSchema[]>;
handleFormValues: Fn;
}
function tryConstructArray(field: string, values: Recordable = {}): any[] | undefined {
const pattern = /^\[(.+)\]$/;
if (pattern.test(field)) {
const match = field.match(pattern);
if (match && match[1]) {
const keys = match[1].split(',');
if (!keys.length) {
return undefined;
}
const result = [];
keys.forEach((k, index) => {
set(result, index, values[k.trim()]);
});
return result.length ? result : undefined;
}
}
}
function tryConstructObject(field: string, values: Recordable = {}): Recordable | undefined {
const pattern = /^\{(.+)\}$/;
if (pattern.test(field)) {
const match = field.match(pattern);
if (match && match[1]) {
const keys = match[1].split(',');
if (!keys.length) {
return;
}
const result = {};
keys.forEach((k) => {
set(result, k.trim(), values[k.trim()]);
});
return Object.values(result).filter(Boolean).length ? result : undefined;
}
}
}
export function useFormEvents({
emit,
getProps,
@ -67,51 +108,61 @@ export function useFormEvents({
// key 支持 a.b.c 的嵌套写法
const delimiter = '.';
const nestKeyArray = fields.filter((item) => item.indexOf(delimiter) >= 0);
const nestKeyArray = fields.filter((item) => String(item).indexOf(delimiter) >= 0);
const validKeys: string[] = [];
Object.keys(values).forEach((key) => {
fields.forEach((key) => {
const schema = unref(getSchema).find((item) => item.field === key);
let value = values[key];
const hasKey = Reflect.has(values, key);
value = handleInputNumberValue(schema?.component, value);
const { componentProps } = schema || {};
let _props = componentProps as any;
if (typeof componentProps === 'function') {
_props = _props({ formModel: unref(formModel) });
}
const constructValue = tryConstructArray(key, values) || tryConstructObject(key, values);
// 0| '' is allow
if (hasKey && fields.includes(key)) {
if (hasKey || !!constructValue) {
const fieldValue = constructValue || value;
// time type
if (itemIsDateType(key)) {
if (Array.isArray(value)) {
if (Array.isArray(fieldValue)) {
const arr: any[] = [];
for (const ele of value) {
for (const ele of fieldValue) {
arr.push(ele ? dateUtil(ele) : null);
}
formModel[key] = arr;
unref(formModel)[key] = arr;
} else {
const { componentProps } = schema || {};
let _props = componentProps as any;
if (typeof componentProps === 'function') {
_props = _props({ formModel });
}
formModel[key] = value ? (_props?.valueFormat ? value : dateUtil(value)) : null;
unref(formModel)[key] = fieldValue
? _props?.valueFormat
? fieldValue
: dateUtil(fieldValue)
: null;
}
} else {
formModel[key] = value;
unref(formModel)[key] = fieldValue;
}
// if (_props?.onChange) {
// _props?.onChange(fieldValue);
// }
validKeys.push(key);
} else {
nestKeyArray.forEach((nestKey: string) => {
try {
const value = nestKey.split('.').reduce((out, item) => out[item], values);
if (isDef(value)) {
formModel[nestKey] = value;
unref(formModel)[nestKey] = unref(value);
validKeys.push(nestKey);
}
} catch (e) {
// key not exist
if (isDef(defaultValueRef.value[nestKey])) {
//formModel[nestKey] = defaultValueRef.value[nestKey];
formModel[nestKey] = cloneDeep(defaultValueRef.value[nestKey]);
unref(formModel)[nestKey] = cloneDeep(unref(defaultValueRef.value[nestKey]));
}
}
});
@ -313,6 +364,9 @@ export function useFormEvents({
const res = handleFormValues(values);
emit('submit', res);
} catch (error: any) {
if (error?.outOfDate === false && error?.errorFields) {
return;
}
throw new Error(error);
}
}

2
apps/vue/src/components/Form/src/types/form.ts

@ -26,7 +26,7 @@ export interface ButtonProps extends AntdButtonProps {
export interface FormActionType {
submit: () => Promise<void>;
setFieldsValue: <T>(values: T) => Promise<void>;
setFieldsValue: (values: Recordable) => Promise<void>;
resetFields: () => Promise<void>;
getFieldsValue: () => Recordable;
clearValidate: (name?: string | string[]) => Promise<void>;

63
apps/vue/src/components/FormDesign/src/components/VFormDesign/modules/CollapseItem.vue

@ -1,5 +1,5 @@
<template>
<div>
<div :class="prefixCls">
<draggable
tag="ul"
:model-value="list"
@ -36,6 +36,7 @@
import draggable from 'vuedraggable';
// import { toRefs } from '@vueuse/core';
import { Icon } from '/@/components/Icon';
import { useDesign } from '/@/hooks/web/useDesign';
export default defineComponent({
name: 'CollapseItem',
components: { draggable, Icon },
@ -50,6 +51,7 @@
},
},
setup(props, { emit }) {
const { prefixCls } = useDesign('form-design-collapse-item');
const state = reactive({});
const handleStart = (e: any, list1: IVFormComponent[]) => {
emit('start', list1[e.oldIndex].component);
@ -62,40 +64,45 @@
const cloneItem = (one) => {
return props.handleListPush(one);
};
return { state, handleStart, handleAdd, cloneItem };
return { prefixCls, state, handleStart, handleAdd, cloneItem };
},
});
</script>
<style lang="less" scoped>
@prefix-cls: ~'@{namespace}-form-design-collapse-item';
@import url(../styles/variable.less);
ul {
padding: 5px;
list-style: none;
display: flex;
margin-bottom: 0;
flex-wrap: wrap;
// background: #efefef;
li {
padding: 8px 12px;
transition: all 0.3s;
width: calc(50% - 6px);
margin: 2.7px;
height: 36px;
line-height: 20px;
cursor: move;
border: 1px solid @border-color;
border-radius: 3px;
&:hover {
color: @primary-color;
border: 1px solid @primary-color;
position: relative;
// z-index: 1;
box-shadow: 0 2px 6px @primary-color;
.@{prefix-cls} {
ul {
padding: 5px;
list-style: none;
display: flex;
margin-bottom: 0;
flex-wrap: wrap;
// background: #efefef;
li {
padding: 8px 12px;
transition: all 0.3s;
width: calc(50% - 6px);
margin: 2.7px;
height: 36px;
line-height: 20px;
cursor: move;
border: 1px solid @border-color;
border-radius: 3px;
&:hover {
color: @primary-color;
border: 1px solid @primary-color;
position: relative;
// z-index: 1;
box-shadow: 0 2px 6px @primary-color;
}
}
}
}
svg {
display: inline !important;
svg {
display: inline !important;
}
}
</style>

1
apps/vue/src/components/Modal/src/BasicModal.vue

@ -141,6 +141,7 @@
visible: unref(visibleRef),
wrapClassName: unref(getWrapClassName),
};
attr['wrapClassName'] = `${attr?.['wrapClassName'] || ''} ${unref(getWrapClassName)}`;
if (unref(fullScreenRef)) {
return omit(attr, ['height', 'title']);
}

8
apps/vue/src/components/Table/src/BasicTable.vue

@ -97,7 +97,7 @@
import { warn } from '/@/utils/log';
export default defineComponent({
name:'BasicTable',
name: 'BasicTable',
components: {
Table,
BasicForm,
@ -454,8 +454,10 @@
margin-bottom: 16px;
}
.ant-tag {
margin-right: 0;
.ant-table-cell {
.ant-tag {
margin-right: 0;
}
}
.ant-table-wrapper {

41
apps/vue/src/components/Table/src/components/AdvancedSearch.vue

@ -24,9 +24,8 @@
style="width: 100%;"
show-search
v-model:value="record.field"
:options="getAvailableParams"
:options="getAvailableOptions"
:filter-option="filterOption"
:field-names="{ label: 'description', value: 'name' }"
@change="(field) => handleFieldChange(field, record)"
/>
</template>
@ -43,13 +42,13 @@
v-else-if="record.javaScriptType==='number' && record.options && record.options.length > 0"
style="width: 100%;"
v-model:value="record.value"
:options="getAvailableOptions"
/>
<InputNumber
v-else-if="record.javaScriptType==='number'"
style="width: 100%;"
v-model:value="record.value"
:options="record.options"
:field-names="{
label: 'key',
value: 'value'
}"
/>
<InputNumber v-else-if="record.javaScriptType==='number'" style="width: 100%;" v-model:value="record.value" />
<Switch v-else-if="record.javaScriptType==='boolean'" v-model:checked="record.value" />
<DatePicker
v-else-if="record.javaScriptType==='Date'"
@ -250,6 +249,19 @@
return defineParams.filter(dp => !formMdel.paramters.some(fp => fp.field === dp.name));
});
const getAvailableOptions = computed(() => {
const availableParams = unref(getAvailableParams);
if (!availableParams.length) return[];
return availableParams
.map((item) => {
return {
label: item.description,
value: item.name,
children: [],
}
});
});
const getAvailableComparisonOptions = computed(() => {
return (paramter: DynamicParamter) => {
const defineParams = unref(defineParamsRef);
@ -266,18 +278,6 @@
.filter(c => availableComparator.includes(c.value));
}
});
const getAvailableOptions = computed(() => {
const availableParams = unref(getAvailableParams);
if (!availableParams.length) return[];
return availableParams
.map((item) => {
return {
label: item.description,
value: item.name,
children: [],
}
});
});
const filterOption = (input: string, option: any) => {
return option.description.toLowerCase().indexOf(input.toLowerCase()) >= 0;
@ -300,6 +300,7 @@
const isArrayResult = Array.isArray(res);
resultItems = isArrayResult ? res : get(res, listField || 'items');
}
console.log(resultItems);
defineParamsRef.value = resultItems;
}).finally(() => {
setLoading(false);

4
apps/vue/src/components/Table/src/components/settings/ColumnSetting.vue

@ -350,7 +350,9 @@
function handleColumnFixed(item: BasicColumn, fixed?: 'left' | 'right') {
if (!state.checkedList.includes(item.dataIndex as string)) return;
const columns = getColumns() as BasicColumn[];
const columns = getColumns().filter((c: BasicColumn) =>
state.checkedList.includes(c.dataIndex as string),
) as BasicColumn[];
const isFixed = item.fixed === fixed ? false : fixed;
const index = columns.findIndex((col) => col.dataIndex === item.dataIndex);
if (index !== -1) {

2
apps/vue/src/components/Table/src/hooks/useTableForm.ts

@ -11,7 +11,7 @@ export function useTableForm(
slots: Slots,
fetch: (opt?: FetchParams | undefined) => Promise<void>,
getLoading: ComputedRef<boolean | undefined>,
setFieldsValue: <T>(values: T) => Promise<void>,
setFieldsValue: (values: Recordable) => Promise<void>,
) {
const getFormProps = computed((): Partial<FormProps> => {
const { formConfig, advancedSearchConfig } = unref(propsRef);

8
apps/vue/src/components/Tree/src/hooks/useTree.ts

@ -181,14 +181,16 @@ export function useTree(treeDataRef: Ref<TreeDataItem[]>, getFieldNames: Compute
function getSelectedNode(key: KeyType, list?: TreeItem[], selectedNode?: TreeItem | null) {
if (!key && key !== 0) return null;
const treeData = list || unref(treeDataRef);
const { key: keyField, children: childrenField } = unref(getFieldNames);
if (!keyField) return;
treeData.forEach((item) => {
if (selectedNode?.key || selectedNode?.key === 0) return selectedNode;
if (item.key === key) {
if (item[keyField] === key) {
selectedNode = item;
return;
}
if (item.children && item.children.length) {
selectedNode = getSelectedNode(key, item.children, selectedNode);
if (item[childrenField!] && item[childrenField!].length) {
selectedNode = getSelectedNode(key, item[childrenField!], selectedNode);
}
});
return selectedNode || null;

2
apps/vue/src/components/Upload/src/helper.ts

@ -11,7 +11,7 @@ export function checkImgType(file: File) {
}
export function isImgTypeByName(name: string) {
return /\.(jpg|jpeg|png|gif)$/i.test(name);
return /\.(jpg|jpeg|png|gif|webp)$/i.test(name);
}
export function getBase64WithFile(file: File) {

33
apps/vue/src/hooks/web/useECharts.ts

@ -60,23 +60,26 @@ export function useECharts(
function setOptions(options: EChartsOption, clear = true) {
cacheOptions.value = options;
if (unref(elRef)?.offsetHeight === 0) {
useTimeoutFn(() => {
setOptions(unref(getOptions));
}, 30);
return;
}
nextTick(() => {
useTimeoutFn(() => {
if (!chartInstance) {
initCharts(getDarkMode.value as 'default');
return new Promise((resolve) => {
if (unref(elRef)?.offsetHeight === 0) {
useTimeoutFn(() => {
setOptions(unref(getOptions));
resolve(null);
}, 30);
}
nextTick(() => {
useTimeoutFn(() => {
if (!chartInstance) {
initCharts(getDarkMode.value as 'default');
if (!chartInstance) return;
}
clear && chartInstance?.clear();
if (!chartInstance) return;
}
clear && chartInstance?.clear();
chartInstance?.setOption(unref(getOptions));
}, 30);
chartInstance?.setOption(unref(getOptions));
resolve(null);
}, 30);
});
});
}

6
apps/vue/src/hooks/web/useWatermark.ts

@ -4,10 +4,15 @@ import { addResizeListener, removeResizeListener } from '/@/utils/event';
import { isDef } from '/@/utils/is';
const domSymbol = Symbol('watermark-dom');
const sourceMap = new WeakMap<HTMLElement, {}>();
export function useWatermark(
appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement>,
) {
const appendElRaw = unref(appendEl);
if (appendElRaw && sourceMap.has(appendElRaw)) {
return sourceMap.get(appendElRaw);
}
const func = useRafThrottle(function () {
const el = unref(appendEl);
if (!el) return;
@ -82,6 +87,7 @@ export function useWatermark(
const { clientHeight: height, clientWidth: width } = el;
updateWatermark({ str, width, height });
el.appendChild(div);
sourceMap.set(el, { setWatermark, clear });
return id;
};

2
apps/vue/src/layouts/default/setting/components/SettingFooter.vue

@ -38,6 +38,7 @@
import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
import { updateSidebarBgColor } from '/@/logics/theme/updateBackground';
import { changeTheme } from '/@/logics/theme';
import defaultSetting from '/@/settings/projectSetting';
@ -72,6 +73,7 @@
appStore.setProjectConfig(defaultSetting);
const { colorWeak, grayMode, themeColor } = defaultSetting;
changeTheme(themeColor);
updateSidebarBgColor();
updateColorWeak(colorWeak);
updateGrayMode(grayMode);
createMessage.success(t('layout.setting.resetSuccess'));

16
apps/vue/src/store/modules/app.ts

@ -38,19 +38,19 @@ export const useAppStore = defineStore({
beforeMiniInfo: {},
}),
getters: {
getPageLoading(): boolean {
return this.pageLoading;
getPageLoading(state): boolean {
return state.pageLoading;
},
getDarkMode(): 'light' | 'dark' | string {
return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
getDarkMode(state): 'light' | 'dark' | string {
return state.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
},
getBeforeMiniInfo(): BeforeMiniState {
return this.beforeMiniInfo;
getBeforeMiniInfo(state): BeforeMiniState {
return state.beforeMiniInfo;
},
getProjectConfig(): ProjectConfig {
return this.projectConfig || ({} as ProjectConfig);
getProjectConfig(state): ProjectConfig {
return state.projectConfig || ({} as ProjectConfig);
},
getHeaderSetting(): HeaderSetting {

8
apps/vue/src/store/modules/errorLog.ts

@ -20,11 +20,11 @@ export const useErrorLogStore = defineStore({
errorLogListCount: 0,
}),
getters: {
getErrorLogInfoList(): ErrorLogInfo[] {
return this.errorLogInfoList || [];
getErrorLogInfoList(state): ErrorLogInfo[] {
return state.errorLogInfoList || [];
},
getErrorLogListCount(): number {
return this.errorLogListCount;
getErrorLogListCount(state): number {
return state.errorLogListCount;
},
},
actions: {

8
apps/vue/src/store/modules/locale.ts

@ -21,11 +21,11 @@ export const useLocaleStore = defineStore({
localInfo: lsLocaleSetting,
}),
getters: {
getShowPicker(): boolean {
return !!this.localInfo?.showPicker;
getShowPicker(state): boolean {
return !!state.localInfo?.showPicker;
},
getLocale(): LocaleType {
return this.localInfo?.locale ?? 'zh_CN';
getLocale(state): LocaleType {
return state.localInfo?.locale ?? 'zh_CN';
},
},
actions: {

4
apps/vue/src/store/modules/lock.ts

@ -16,8 +16,8 @@ export const useLockStore = defineStore({
lockInfo: Persistent.getLocal(LOCK_INFO_KEY),
}),
getters: {
getLockInfo(): Nullable<LockInfo> {
return this.lockInfo;
getLockInfo(state): Nullable<LockInfo> {
return state.lockInfo;
},
},
actions: {

12
apps/vue/src/store/modules/multipleTab.ts

@ -48,14 +48,14 @@ export const useMultipleTabStore = defineStore({
lastDragEndIndex: 0,
}),
getters: {
getTabList(): RouteLocationNormalized[] {
return this.tabList;
getTabList(state): RouteLocationNormalized[] {
return state.tabList;
},
getCachedTabList(): string[] {
return Array.from(this.cacheTabList);
getCachedTabList(state): string[] {
return Array.from(state.cacheTabList);
},
getLastDragEndIndex(): number {
return this.lastDragEndIndex;
getLastDragEndIndex(state): number {
return state.lastDragEndIndex;
},
},
actions: {

20
apps/vue/src/store/modules/permission.ts

@ -50,20 +50,20 @@ export const usePermissionStore = defineStore({
frontMenuList: [],
}),
getters: {
getPermCodeList(): string[] | number[] {
return this.permCodeList;
getPermCodeList(state): string[] | number[] {
return state.permCodeList;
},
getBackMenuList(): Menu[] {
return this.backMenuList;
getBackMenuList(state): Menu[] {
return state.backMenuList;
},
getFrontMenuList(): Menu[] {
return this.frontMenuList;
getFrontMenuList(state): Menu[] {
return state.frontMenuList;
},
getLastBuildMenuTime(): number {
return this.lastBuildMenuTime;
getLastBuildMenuTime(state): number {
return state.lastBuildMenuTime;
},
getIsDynamicAddedRoute(): boolean {
return this.isDynamicAddedRoute;
getIsDynamicAddedRoute(state): boolean {
return state.isDynamicAddedRoute;
},
},
actions: {

24
apps/vue/src/store/modules/user.ts

@ -46,23 +46,23 @@ export const useUserStore = defineStore({
lastUpdateTime: 0,
}),
getters: {
getSso(): boolean {
return this.sso === true;
getSso(state): boolean {
return state.sso === true;
},
getUserInfo(): GetUserInfoModel {
return this.userInfo || getAuthCache<GetUserInfoModel>(USER_INFO_KEY) || {};
getUserInfo(state): GetUserInfoModel {
return state.userInfo || getAuthCache<GetUserInfoModel>(USER_INFO_KEY) || {};
},
getToken(): string {
return this.token || getAuthCache<string>(TOKEN_KEY);
getToken(state): string {
return state.token || getAuthCache<string>(TOKEN_KEY);
},
getRoleList(): RoleEnum[] {
return this.roleList.length > 0 ? this.roleList : getAuthCache<RoleEnum[]>(ROLES_KEY);
getRoleList(state): RoleEnum[] {
return state.roleList.length > 0 ? state.roleList : getAuthCache<RoleEnum[]>(ROLES_KEY);
},
getSessionTimeout(): boolean {
return !!this.sessionTimeout;
getSessionTimeout(state): boolean {
return !!state.sessionTimeout;
},
getLastUpdateTime(): number {
return this.lastUpdateTime;
getLastUpdateTime(state): number {
return state.lastUpdateTime;
},
},
actions: {

68
apps/vue/src/views/webhooks/send-attempts/components/SendAttemptModal.vue

@ -30,7 +30,7 @@
<Input readonly :value="getDateTime(modelRef.creationTime)" />
</FormItem>
<FormItem :label="L('DisplayName:RequestHeaders')">
<CodeEditorX readonly :mode="MODE.JSON" v-model="modelRef.requestHeaders" />
<CodeEditor readonly :mode="MODE.JSON" :value="getJsonValue(modelRef.requestHeaders)" />
</FormItem>
<FormItem :label="L('DisplayName:ResponseStatusCode')">
<Tag
@ -40,10 +40,10 @@
>
</FormItem>
<FormItem :label="L('DisplayName:ResponseHeaders')">
<CodeEditorX readonly :mode="MODE.JSON" v-model="modelRef.responseHeaders" />
<CodeEditor readonly :mode="MODE.JSON" :value="getJsonValue(modelRef.responseHeaders)" />
</FormItem>
<FormItem :label="L('DisplayName:Response')">
<CodeEditorX readonly v-model="modelRef.response" />
<CodeEditor readonly :value="getJsonValue(modelRef.response)" />
</FormItem>
</TabPane>
@ -51,17 +51,17 @@
<FormItem :label="L('DisplayName:TenantId')">
<Input readonly :value="getTenant" />
</FormItem>
<FormItem :label="L('DisplayName:WebhookEventId')">
<FormItem name="webhookEventId" :label="L('DisplayName:WebhookEventId')">
<Input readonly :value="modelRef.webhookEventId" />
</FormItem>
<FormItem :label="L('DisplayName:WebhookName')">
<FormItem :name="['webhookEvent', 'webhookName']" :label="L('DisplayName:WebhookName')">
<Input readonly :value="modelRef.webhookEvent.webhookName" />
</FormItem>
<FormItem :label="L('DisplayName:CreationTime')">
<FormItem :name="['webhookEvent', 'creationTime']" :label="L('DisplayName:CreationTime')">
<Input readonly :value="getDateTime(modelRef.webhookEvent.creationTime)" />
</FormItem>
<FormItem :label="L('DisplayName:Data')">
<CodeEditorX readonly :mode="MODE.JSON" v-model="modelRef.webhookEvent.data" />
<FormItem :name="['webhookEvent', 'data']" :label="L('DisplayName:Data')">
<CodeEditor readonly :mode="MODE.JSON" :value="modelRef.webhookEvent.data" />
</FormItem>
</TabPane>
@ -100,7 +100,7 @@
</template>
</FormItem>
<FormItem name="headers" :label="L('DisplayName:Headers')">
<CodeEditorX readonly :mode="MODE.JSON" v-model="subscriptionRef.headers" />
<CodeEditor readonly :mode="MODE.JSON" :value="getJsonValue(subscriptionRef.headers)" />
</FormItem>
</TabPane>
</Tabs>
@ -113,7 +113,7 @@
import { useTabsStyle } from '/@/hooks/component/useStyles';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Checkbox, Form, Tabs, Tag, Input, InputPassword, Textarea } from 'ant-design-vue';
import { CodeEditorX, MODE } from '/@/components/CodeEditor';
import { CodeEditor, MODE } from '/@/components/CodeEditor';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { findTenantById } from '/@/api/multi-tenancy/tenants';
import { getById } from '/@/api/webhooks/send-attempts';
@ -122,6 +122,7 @@
import { WebhookSubscription } from '/@/api/webhooks/model/subscriptionsModel';
import { httpStatusCodeMap, getHttpStatusColor } from '../../typing';
import { formatToDateTime } from '/@/utils/dateUtil';
import { isString } from '/@/utils/is';
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
@ -131,10 +132,12 @@
const activeKey = ref('basic');
const tenantName = ref('');
const tabsStyle = useTabsStyle();
const modelRef = ref<WebhookSendAttempt>(getDefaultModel());
const subscriptionRef = ref<WebhookSubscription>(getDefaultSubscription());
const modelRef = ref<WebhookSendAttempt>({} as WebhookSendAttempt);
const subscriptionRef = ref<WebhookSubscription>({} as WebhookSubscription);
const [registerModal] = useModalInner((model) => {
activeKey.value = 'basic';
modelRef.value = {} as WebhookSendAttempt;
subscriptionRef.value = {} as WebhookSubscription;
fetchModel(model.id);
});
const getDateTime = computed(() => {
@ -145,6 +148,13 @@
const getTenant = computed(() => {
return tenantName.value ?? modelRef.value.tenantId;
});
const getJsonValue = computed(() => {
return (value?: Recordable | string) => {
if (!value) return '{}';
if (isString(value)) return value;
return JSON.stringify(value);
};
});
watch(
() => modelRef.value.tenantId,
@ -173,38 +183,4 @@
subscriptionRef.value = res;
});
}
function getDefaultModel(): WebhookSendAttempt {
return {
id: '',
webhookEventId: '',
webhookSubscriptionId: '',
webhookEvent: {
tenantId: undefined,
webhookName: '',
data: '{}',
creationTime: new Date(),
},
response: '',
responseStatusCode: undefined,
creationTime: new Date(),
lastModificationTime: undefined,
requestHeaders: {},
responseHeaders: {},
sendExactSameData: false,
};
}
function getDefaultSubscription(): WebhookSubscription {
return {
id: '',
webhooks: [],
webhookUri: '',
headers: {},
secret: '',
isActive: true,
creatorId: '',
creationTime: new Date(),
};
}
</script>

14
apps/vue/src/views/webhooks/send-attempts/components/SendAttemptTable.vue

@ -109,15 +109,16 @@
openModal(true, record);
}
function handleDelete(record) {
function handleDeleteMany() {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
content: L('ItemWillBeDeletedMessageWithFormat', { 0: L('SelectedItems') }),
okCancel: true,
onOk: () => {
const selectKeys = getSelectRowKeys();
setLoading(true);
return deleteById(record.id).then(() => {
return deleteMany(selectKeys).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
clearSelectedRowKeys();
reload();
@ -128,16 +129,15 @@
});
}
function handleDeleteMany() {
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', { 0: L('SelectedItems') }),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
const selectKeys = getSelectRowKeys();
setLoading(true);
return deleteMany(selectKeys).then(() => {
return deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
clearSelectedRowKeys();
reload();

19
apps/vue/src/views/webhooks/subscriptions/components/SubscriptionModal.vue

@ -57,7 +57,7 @@
</Select>
</FormItem>
<FormItem name="headers" :label="L('DisplayName:Headers')">
<CodeEditorX style="height: 300px" :mode="MODE.JSON" v-model="modelRef.headers" />
<CodeEditor style="height: 300px" :mode="MODE.JSON" v-model:value="modelRef.headers" />
</FormItem>
</Form>
</BasicModal>
@ -70,7 +70,7 @@
import { useMessage } from '/@/hooks/web/useMessage';
import { Checkbox, Form, Select, Tooltip, Input, InputPassword, Textarea } from 'ant-design-vue';
import { isString } from '/@/utils/is';
import { CodeEditorX, MODE } from '/@/components/CodeEditor';
import { CodeEditor, MODE } from '/@/components/CodeEditor';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { TenantDto } from '/@/api/saas/tenant/model';
import { GetListAsyncByInput as getTenants } from '/@/api/saas/tenant';
@ -133,6 +133,19 @@
length: 128,
type: 'string',
}),
// headers: ruleCreator.defineValidator({
// trigger: 'change',
// validator: (_, value: any) => {
// console.log(String(value));
// if (!value) {
// return Promise.resolve();
// }
// if (isJson(value)) {
// return Promise.resolve();
// }
// return Promise.reject(L('InvalidHeaders'));
// },
// }),
});
onMounted(() => {
@ -169,11 +182,11 @@
function handleSubmit() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
changeOkLoading(true);
const model = unref(modelRef);
if (isString(model.headers)) {
model.headers = JSON.parse(model.headers);
}
changeOkLoading(true);
const api = isEditModal.value
? update(model.id, Object.assign(model))
: create(Object.assign(model));

17
apps/vue/src/views/webhooks/subscriptions/components/SubscriptionTable.vue

@ -69,7 +69,7 @@
const { createConfirm, createMessage } = useMessage();
const { L } = useLocalization(['WebhooksManagement', 'AbpUi']);
const [registerModal, { openModal }] = useModal();
const [registerTable, { reload, setLoading, clearSelectedRowKeys, getSelectRowKeys }] = useTable({
const [registerTable, { reload, setLoading, getSelectRowKeys, clearSelectedRowKeys }] = useTable({
rowKey: 'id',
title: L('Subscriptions'),
columns: getDataColumns(),
@ -107,15 +107,16 @@
openModal(true, record);
}
function handleDelete(record) {
function handleDeleteMany() {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
content: L('ItemWillBeDeletedMessageWithFormat', { 0: L('SelectedItems') }),
okCancel: true,
onOk: () => {
const selectKeys = getSelectRowKeys();
setLoading(true);
return deleteById(record.id).then(() => {
return deleteMany(selectKeys).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
clearSelectedRowKeys();
reload();
@ -126,19 +127,19 @@
});
}
function handleDeleteMany() {
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', { 0: L('SelectedItems') }),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
const selectKeys = getSelectRowKeys();
setLoading(true);
return deleteMany(selectKeys).then(() => {
return deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
clearSelectedRowKeys();
reload();
reload();
}).finally(() => {
setLoading(false);
});

Loading…
Cancel
Save