merge(sj_map_reduce): Merge branch dev_1.1.0_beta1 into dev_map_reduce
This commit is contained in:
commit
61b0d80a77
2
.env
2
.env
@ -2,7 +2,7 @@ VITE_APP_TITLE=Snail Job
|
||||
|
||||
VITE_APP_DESC=A flexible, reliable, and fast platform for distributed task retry and distributed task scheduling.
|
||||
|
||||
VITE_APP_VERSION=1.0.0
|
||||
VITE_APP_VERSION=1.1.0-beta1
|
||||
|
||||
VITE_APP_DEFAULT_TOKEN=SJ_Wyz3dmsdbDOkDujOTSSoBjGQP1BMsVnj
|
||||
|
||||
|
@ -15,7 +15,7 @@ interface Props {
|
||||
min: number;
|
||||
max: number;
|
||||
};
|
||||
locale: I18n.LocaleType;
|
||||
locale?: I18n.LocaleType;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@ -106,7 +106,9 @@ const value = computed(() => {
|
||||
return props.field.value === DATE ? type.value : `${lastDayOfWeek.value}${type.value}`;
|
||||
case TYPE.SPECIFY: {
|
||||
const specifyValue = specify.value;
|
||||
return specifyValue.length ? specifyValue.sort((a, b) => a - b).join(type.value) : `${specifyValue[0] || 0}`;
|
||||
return specifyValue.length
|
||||
? specifyValue.sort((a, b) => a - b).join(type.value)
|
||||
: `${specifyValue[0] || specifies.value[0].value}`;
|
||||
}
|
||||
default:
|
||||
return '';
|
||||
@ -144,7 +146,8 @@ watch(
|
||||
specify.value =
|
||||
data !== 'undefined' && data !== 'NaN' ? data.split(TYPE.SPECIFY).map(i => Number.parseInt(i, 10)) : [];
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
|
@ -49,7 +49,7 @@ const fields = computed(() => {
|
||||
// });
|
||||
|
||||
const previewLabel = computed(() => {
|
||||
return Locales[props.lang].preview.join(previewTime.value.toString());
|
||||
return Locales[props.lang].preview.join(previewTime.value?.toString());
|
||||
});
|
||||
|
||||
const expression = computed(() => {
|
||||
@ -81,7 +81,7 @@ const previews = computed(() => {
|
||||
try {
|
||||
previewList = parserCron(expression.value);
|
||||
} catch (error) {
|
||||
previewList = ['此表达式暂时无法解析!'];
|
||||
previewList = [Locales[props.lang].previewError];
|
||||
}
|
||||
|
||||
return previewList;
|
||||
|
@ -31,7 +31,7 @@ const value = computed({
|
||||
});
|
||||
|
||||
const formatter = (val: number) => {
|
||||
return props.fieldValue === WEEK ? formatterWeek(val.toString(), props.locale!) : null;
|
||||
return props.fieldValue === WEEK ? formatterWeek(val?.toString(), props.locale!) : null;
|
||||
};
|
||||
|
||||
const parser = (val: string) => {
|
||||
|
@ -19,7 +19,7 @@ export function generateSpecifies(
|
||||
let index = 0;
|
||||
|
||||
for (let specify = min; specify <= max; specify += 1) {
|
||||
specifies.push({ value: specify, label: labels ? labels[index] : specify.toString() });
|
||||
specifies.push({ value: specify, label: labels ? labels[index] : specify?.toString() });
|
||||
index += 1;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@ export type TableConfig<A extends ApiFn, T, C> = {
|
||||
apiFn: A;
|
||||
/** api params */
|
||||
apiParams?: Parameters<A>[0];
|
||||
/** search params */
|
||||
searchParams?: Parameters<A>[0];
|
||||
/** transform api response to table data */
|
||||
transformer: Transformer<T, Awaited<ReturnType<A>>>;
|
||||
/** columns factory */
|
||||
@ -133,6 +135,9 @@ export default function useHookTable<A extends ApiFn, T, C>(config: TableConfig<
|
||||
}
|
||||
|
||||
if (immediate) {
|
||||
if (config.searchParams) {
|
||||
updateSearchParams(config.searchParams);
|
||||
}
|
||||
getData();
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ export class Crypto<T extends object> {
|
||||
encrypt(data: T): string {
|
||||
const dataString = JSON.stringify(data);
|
||||
const encrypted = CryptoJS.AES.encrypt(dataString, this.secret);
|
||||
return encrypted.toString();
|
||||
return encrypted?.toString();
|
||||
}
|
||||
|
||||
decrypt(encrypted: string) {
|
||||
|
@ -29,6 +29,9 @@
|
||||
"warning-outlined": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M464 720a48 48 0 1 0 96 0a48 48 0 1 0-96 0m16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8m475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48m-783.5-27.9L512 239.9l339.8 588.2z\"/>"
|
||||
},
|
||||
"check-outlined": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5L207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8\"/>"
|
||||
},
|
||||
"clock-circle-outlined": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448s448-200.6 448-448S759.4 64 512 64m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372s372 166.6 372 372s-166.6 372-372 372\"/><path fill=\"currentColor\" d=\"M686.7 638.6L544.1 535.5V288c0-4.4-3.6-8-8-8H488c-4.4 0-8 3.6-8 8v275.4c0 2.6 1.2 5 3.3 6.5l165.4 120.6c3.6 2.6 8.6 1.8 11.2-1.7l28.6-39c2.6-3.7 1.8-8.7-1.8-11.2\"/>"
|
||||
},
|
||||
|
@ -8,6 +8,10 @@
|
||||
"dashboard-outline-rounded": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M13 8V4q0-.425.288-.712T14 3h6q.425 0 .713.288T21 4v4q0 .425-.288.713T20 9h-6q-.425 0-.712-.288T13 8M3 12V4q0-.425.288-.712T4 3h6q.425 0 .713.288T11 4v8q0 .425-.288.713T10 13H4q-.425 0-.712-.288T3 12m10 8v-8q0-.425.288-.712T14 11h6q.425 0 .713.288T21 12v8q0 .425-.288.713T20 21h-6q-.425 0-.712-.288T13 20M3 20v-4q0-.425.288-.712T4 15h6q.425 0 .713.288T11 16v4q0 .425-.288.713T10 21H4q-.425 0-.712-.288T3 20m2-9h4V5H5zm10 8h4v-6h-4zm0-12h4V5h-4zM5 19h4v-2H5zm4-2\"/>"
|
||||
},
|
||||
"expand-more-rounded": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M12 14.95q-.2 0-.375-.062t-.325-.213l-4.6-4.6q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l3.9 3.9l3.9-3.9q.275-.275.7-.275t.7.275t.275.7t-.275.7l-4.6 4.6q-.15.15-.325.213T12 14.95\"/>",
|
||||
"hidden": true
|
||||
},
|
||||
"group-work-outline": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M8 16q.825 0 1.413-.587T10 14t-.587-1.412T8 12t-1.412.588T6 14t.588 1.413T8 16m8 0q.825 0 1.413-.587T18 14t-.587-1.412T16 12t-1.412.588T14 14t.588 1.413T16 16m-4-6q.825 0 1.413-.587T14 8t-.587-1.412T12 6t-1.412.588T10 8t.588 1.413T12 10m0 12q-2.075 0-3.9-.788t-3.175-2.137T2.788 15.9T2 12t.788-3.9t2.137-3.175T8.1 2.788T12 2t3.9.788t3.175 2.137T21.213 8.1T22 12t-.788 3.9t-2.137 3.175t-3.175 2.138T12 22m0-2q3.35 0 5.675-2.325T20 12t-2.325-5.675T12 4T6.325 6.325T4 12t2.325 5.675T12 20m0-8\"/>"
|
||||
},
|
||||
@ -31,6 +35,12 @@
|
||||
},
|
||||
"sunny": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M11 5V1h2v4zm6.65 2.75l-1.375-1.375l2.8-2.875l1.4 1.425zM19 13v-2h4v2zm-8 10v-4h2v4zM6.35 7.7L3.5 4.925l1.425-1.4L7.75 6.35zm12.7 12.8l-2.775-2.875l1.35-1.35l2.85 2.75zM1 13v-2h4v2zm3.925 7.5l-1.4-1.425l2.8-2.8l.725.675l.725.7zM12 18q-2.5 0-4.25-1.75T6 12t1.75-4.25T12 6t4.25 1.75T18 12t-1.75 4.25T12 18\"/>"
|
||||
},
|
||||
"check-circle": {
|
||||
"body": "<path fill=\"currentColor\" d=\"m10.6 16.6l7.05-7.05l-1.4-1.4l-5.65 5.65l-2.85-2.85l-1.4 1.4zM12 22q-2.075 0-3.9-.788t-3.175-2.137T2.788 15.9T2 12t.788-3.9t2.137-3.175T8.1 2.788T12 2t3.9.788t3.175 2.137T21.213 8.1T22 12t-.788 3.9t-2.137 3.175t-3.175 2.138T12 22\"/>"
|
||||
},
|
||||
"cancel": {
|
||||
"body": "<path fill=\"currentColor\" d=\"m8.4 17l3.6-3.6l3.6 3.6l1.4-1.4l-3.6-3.6L17 8.4L15.6 7L12 10.6L8.4 7L7 8.4l3.6 3.6L7 15.6zm3.6 5q-2.075 0-3.9-.788t-3.175-2.137T2.788 15.9T2 12t.788-3.9t2.137-3.175T8.1 2.788T12 2t3.9.788t3.175 2.137T21.213 8.1T22 12t-.788 3.9t-2.137 3.175t-3.175 2.138T12 22\"/>"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="snail-job" data-name="snail-job" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 709.6845005488 690.7728719041">
|
||||
<path fill="#1366ff" d="M338.3025810878.1920476727c-24.3000003621,2.1000000313-31.0000004619,2.8000000417-41.0000006109,4.5000000671C156.7025783818,28.3920480929,44.9025767158,131.4920496292,10.4025762017,269.0920516796,2.8025760885,299.5920521341.0025760468,322.4920524753.0025760468,354.0920529462c-.1000000015,33.1000004932,2.7000000402,55.8000008315,10.400000155,86.7000012919,9.9000001475,39.4000005871,26.0000003874,76.0000011325,47.9000007138,109.1000016257,13.9000002071,20.9000003114,25.100000374,34.7000005171,42.5000006333,52.6000007838,29.8000004441,30.5000004545,62.0000009239,53.8000008017,99.2000014782,71.8000010699,8.3000001237,4.0000000596,15.7000002339,7.3000001088,16.4000002444,7.3000001088.6000000089,0,5.4000000805,1.3000000194,10.5000001565,3.0000000447,44.7000006661,14.3000002131,92.2000013739,3.7000000551,138.4000020623-30.9000004604,4.1000000611-3.1000000462,12.9000001922-10.8000001609,19.4000002891-17.1000002548,10.1000001505-9.7000001445,12.4000001848-12.6000001878,15.2000002265-18.5000002757,15.6000002325-33.9000005051,14.6000002176-69.0000010282-3.2000000477-110.9000016525-8.6000001281-20.1000002995-25.9000003859-46.1000006869-43.3000006452-65.0000009686-3.0000000447-3.4000000507-10.7000001594-9.6000001431-17.1000002548-14.0000002086-24.5000003651-16.7000002488-43.7000006512-32.1000004783-54.3000008091-43.4000006467-6.3000000939-6.8000001013-16.1000002399-21.9000003263-18.7000002787-28.9000004306-2.8000000417-7.5000001118-3.6000000536-17.5000002608-2.0000000298-24.4000003636,1.8000000268-7.8000001162,7.2000001073-18.7000002787,12.0000001788-24.2000003606,4.1000000611-4.6000000685,4.2000000626-4.8000000715,3.5000000522-10.000000149-1.6000000238-11.7000001743-17.8000002652-62.0000009239-20.600000307-63.8000009507-.6000000089-.3000000045-3.3000000492-.9000000134-6.0000000894-1.2000000179-10.5000001565-1.3000000194-18.3000002727-6.9000001028-22.7000003383-16.6000002474-2.1000000313-4.5000000671-2.4000000358-6.4000000954-2.0000000298-12.1000001803,1.1000000164-15.500000231,13.5000002012-26.0000003874,29.2000004351-24.8000003695,18.3000002727,1.5000000224,30.1000004485,19.2000002861,23.7000003532,35.8000005335-1.2000000179,3.0000000447-2.1000000313,6.5000000969-2.1000000313,7.7000001147,0,3.1000000462,8.2000001222,18.5000002757,14.2000002116,26.6000003964,13.9000002071,18.8000002801,30.000000447,27.6000004113,48.4000007212,26.4000003934,10.600000158-.6000000089,13.3000001982-2.0000000298,16.4000002444-8.2000001222,2.3000000343-4.5000000671,2.5000000373-6.2000000924,2.5000000373-17.0000002533,0-7.7000001147-.7000000104-15.0000002235-1.9000000283-20.5000003055-2.5000000373-11.6000001729-11.3000001684-38.4000005722-13.7000002041-41.4000006169-1.1000000164-1.3000000194-4.1000000611-3.2000000477-6.8000001013-4.1000000611-14.700000219-4.900000073-23.3000003472-16.7000002488-23.3000003472-32.1000004783,0-13.1000001952,7.2000001073-24.3000003621,19.5000002906-30.000000447,7.8000001162-3.6000000536,19.0000002831-3.4000000507,27.2000004053.5000000075,3.5000000522,1.6000000238,7.8000001162,4.8000000715,10.3000001535,7.5000001118,10.3000001535,11.2000001669,11.8000001758,24.4000003636,4.5000000671,39.4000005871-3.3000000492,6.7000000998-3.0000000447,8.1000001207,5.100000076,24.6000003666,18.2000002712,36.8000005484,52.2000007778,76.8000011444,101.1000015065,118.7000017688,39.2000005841,33.7000005022,64.9000009671,65.4000009745,84.9000012651,105.1000015661,15.6000002325,31.0000004619,24.1000003591,57.9000008628,30.20000045,96.300001435,1.0000000149,6.1000000909,1.8000000268,19.7000002936,2.1000000313,34.6000005156.6000000089,26.0000003874-.3000000045,39.5000005886-3.8000000566,59.3000008836-1.1000000164,6.0000000894-1.8000000268,11.0000001639-1.6000000238,11.2000001669.8000000119.8000000119,31.7000004724-31.7000004724,40.1000005975-42.1000006273,18.9000002816-23.5000003502,38.6000005752-56.6000008434,50.400000751-84.5000012591,13.0000001937-30.800000459,22.7000003383-68.9000010267,26.4000003934-104.0000015497,1.8000000268-17.3000002578,1.5000000224-54.7000008151-.6000000089-72.0000010729-13.2000001967-111.000001654-73.5000010952-206.1000030711-167.300002493-264.0000039339-13.3000001982-8.2000001222-37.4000005573-20.5000003055-52.2000007778-26.5000003949-29.7000004426-12.1000001803-67.1000009999-21.3000003174-99.1000014767-24.5000003651-11.4000001699-1.1000000164-43.8000006527-2.0000000298-51.00000076-1.4000000209Z"/>
|
||||
<path d="M338.3025810878.1920476727c-24.3000003621,2.1000000313-31.0000004619,2.8000000417-41.0000006109,4.5000000671C156.7025783818,28.3920480929,44.9025767158,131.4920496292,10.4025762017,269.0920516796,2.8025760885,299.5920521341.0025760468,322.4920524753.0025760468,354.0920529462c-.1000000015,33.1000004932,2.7000000402,55.8000008315,10.400000155,86.7000012919,9.9000001475,39.4000005871,26.0000003874,76.0000011325,47.9000007138,109.1000016257,13.9000002071,20.9000003114,25.100000374,34.7000005171,42.5000006333,52.6000007838,29.8000004441,30.5000004545,62.0000009239,53.8000008017,99.2000014782,71.8000010699,8.3000001237,4.0000000596,15.7000002339,7.3000001088,16.4000002444,7.3000001088.6000000089,0,5.4000000805,1.3000000194,10.5000001565,3.0000000447,44.7000006661,14.3000002131,92.2000013739,3.7000000551,138.4000020623-30.9000004604,4.1000000611-3.1000000462,12.9000001922-10.8000001609,19.4000002891-17.1000002548,10.1000001505-9.7000001445,12.4000001848-12.6000001878,15.2000002265-18.5000002757,15.6000002325-33.9000005051,14.6000002176-69.0000010282-3.2000000477-110.9000016525-8.6000001281-20.1000002995-25.9000003859-46.1000006869-43.3000006452-65.0000009686-3.0000000447-3.4000000507-10.7000001594-9.6000001431-17.1000002548-14.0000002086-24.5000003651-16.7000002488-43.7000006512-32.1000004783-54.3000008091-43.4000006467-6.3000000939-6.8000001013-16.1000002399-21.9000003263-18.7000002787-28.9000004306-2.8000000417-7.5000001118-3.6000000536-17.5000002608-2.0000000298-24.4000003636,1.8000000268-7.8000001162,7.2000001073-18.7000002787,12.0000001788-24.2000003606,4.1000000611-4.6000000685,4.2000000626-4.8000000715,3.5000000522-10.000000149-1.6000000238-11.7000001743-17.8000002652-62.0000009239-20.600000307-63.8000009507-.6000000089-.3000000045-3.3000000492-.9000000134-6.0000000894-1.2000000179-10.5000001565-1.3000000194-18.3000002727-6.9000001028-22.7000003383-16.6000002474-2.1000000313-4.5000000671-2.4000000358-6.4000000954-2.0000000298-12.1000001803,1.1000000164-15.500000231,13.5000002012-26.0000003874,29.2000004351-24.8000003695,18.3000002727,1.5000000224,30.1000004485,19.2000002861,23.7000003532,35.8000005335-1.2000000179,3.0000000447-2.1000000313,6.5000000969-2.1000000313,7.7000001147,0,3.1000000462,8.2000001222,18.5000002757,14.2000002116,26.6000003964,13.9000002071,18.8000002801,30.000000447,27.6000004113,48.4000007212,26.4000003934,10.600000158-.6000000089,13.3000001982-2.0000000298,16.4000002444-8.2000001222,2.3000000343-4.5000000671,2.5000000373-6.2000000924,2.5000000373-17.0000002533,0-7.7000001147-.7000000104-15.0000002235-1.9000000283-20.5000003055-2.5000000373-11.6000001729-11.3000001684-38.4000005722-13.7000002041-41.4000006169-1.1000000164-1.3000000194-4.1000000611-3.2000000477-6.8000001013-4.1000000611-14.700000219-4.900000073-23.3000003472-16.7000002488-23.3000003472-32.1000004783,0-13.1000001952,7.2000001073-24.3000003621,19.5000002906-30.000000447,7.8000001162-3.6000000536,19.0000002831-3.4000000507,27.2000004053.5000000075,3.5000000522,1.6000000238,7.8000001162,4.8000000715,10.3000001535,7.5000001118,10.3000001535,11.2000001669,11.8000001758,24.4000003636,4.5000000671,39.4000005871-3.3000000492,6.7000000998-3.0000000447,8.1000001207,5.100000076,24.6000003666,18.2000002712,36.8000005484,52.2000007778,76.8000011444,101.1000015065,118.7000017688,39.2000005841,33.7000005022,64.9000009671,65.4000009745,84.9000012651,105.1000015661,15.6000002325,31.0000004619,24.1000003591,57.9000008628,30.20000045,96.300001435,1.0000000149,6.1000000909,1.8000000268,19.7000002936,2.1000000313,34.6000005156.6000000089,26.0000003874-.3000000045,39.5000005886-3.8000000566,59.3000008836-1.1000000164,6.0000000894-1.8000000268,11.0000001639-1.6000000238,11.2000001669.8000000119.8000000119,31.7000004724-31.7000004724,40.1000005975-42.1000006273,18.9000002816-23.5000003502,38.6000005752-56.6000008434,50.400000751-84.5000012591,13.0000001937-30.800000459,22.7000003383-68.9000010267,26.4000003934-104.0000015497,1.8000000268-17.3000002578,1.5000000224-54.7000008151-.6000000089-72.0000010729-13.2000001967-111.000001654-73.5000010952-206.1000030711-167.300002493-264.0000039339-13.3000001982-8.2000001222-37.4000005573-20.5000003055-52.2000007778-26.5000003949-29.7000004426-12.1000001803-67.1000009999-21.3000003174-99.1000014767-24.5000003651-11.4000001699-1.1000000164-43.8000006527-2.0000000298-51.00000076-1.4000000209Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.4 KiB |
@ -25,7 +25,6 @@ const handleUpdate = (value: Api.Common.BlockStrategy) => {
|
||||
v-model:value="valueRef"
|
||||
:placeholder="$t('common.blockStrategy.form')"
|
||||
:options="translateOptions(blockStrategyRecordOptions)"
|
||||
clearable
|
||||
@update:value="handleUpdate"
|
||||
/>
|
||||
</template>
|
||||
|
35
src/components/common/datetime-range.vue
Normal file
35
src/components/common/datetime-range.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
import { $t } from '@/locales';
|
||||
import { monthRange } from '@/utils/common';
|
||||
|
||||
defineOptions({
|
||||
name: 'DatetimeRange'
|
||||
});
|
||||
|
||||
// 注意:格式与 day.js 大小写不一样
|
||||
const DATETIME_FORMAT_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss";
|
||||
|
||||
const modelValue = defineModel<[string, string] | null>('value');
|
||||
|
||||
const createShortcuts = () => {
|
||||
const shortcuts: any = {};
|
||||
shortcuts[$t('common.currentMonth')] = monthRange(0, 'month');
|
||||
shortcuts[$t('common.lastMonth')] = monthRange(1, 'month');
|
||||
shortcuts[$t('common.lastTwoMonth')] = monthRange(2, 'month');
|
||||
return shortcuts;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDatePicker
|
||||
v-model:formatted-value="modelValue"
|
||||
type="datetimerange"
|
||||
:value-format="DATETIME_FORMAT_ISO8601"
|
||||
clearable
|
||||
:default-time="['00:00:00', '23:56:56']"
|
||||
:shortcuts="createShortcuts()"
|
||||
:actions="['clear', 'confirm']"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@ -25,7 +25,6 @@ const handleUpdate = (value: Api.Common.TriggerType) => {
|
||||
v-model:value="valueRef"
|
||||
:placeholder="$t('common.executorType.form')"
|
||||
:options="translateOptions(executorTypeRecordOptions)"
|
||||
clearable
|
||||
@update:value="handleUpdate"
|
||||
/>
|
||||
</template>
|
||||
|
@ -78,14 +78,14 @@ const onUpdateShow = (value: boolean) => {
|
||||
};
|
||||
|
||||
function timestampToDate(timestamp: string): string {
|
||||
const date = new Date(Number.parseInt(timestamp.toString(), 10));
|
||||
const date = new Date(Number.parseInt(timestamp?.toString(), 10));
|
||||
const year = date.getFullYear();
|
||||
const month =
|
||||
(date.getMonth() + 1).toString().length === 1 ? `0${date.getMonth() + 1}` : (date.getMonth() + 1).toString();
|
||||
const day = date.getDate().toString().length === 1 ? `0${date.getDate()}` : date.getDate().toString();
|
||||
const hours = date.getHours().toString().length === 1 ? `0${date.getHours()}` : date.getHours().toString();
|
||||
const minutes = date.getMinutes().toString().length === 1 ? `0${date.getMinutes()}` : date.getMinutes().toString();
|
||||
const seconds = date.getSeconds().toString().length === 1 ? `0${date.getSeconds()}` : date.getSeconds().toString();
|
||||
(date.getMonth() + 1)?.toString().length === 1 ? `0${date.getMonth() + 1}` : (date.getMonth() + 1)?.toString();
|
||||
const day = date.getDate()?.toString().length === 1 ? `0${date.getDate()}` : date.getDate()?.toString();
|
||||
const hours = date.getHours()?.toString().length === 1 ? `0${date.getHours()}` : date.getHours()?.toString();
|
||||
const minutes = date.getMinutes()?.toString().length === 1 ? `0${date.getMinutes()}` : date.getMinutes()?.toString();
|
||||
const seconds = date.getSeconds()?.toString().length === 1 ? `0${date.getSeconds()}` : date.getSeconds()?.toString();
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${date.getMilliseconds()}`;
|
||||
}
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
import { translateOptions } from '@/utils/common';
|
||||
import { operationReasonOptions } from '@/constants/business';
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:value', value: Api.Common.OperationReason): void;
|
||||
}
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const handleUpdate = (operationReason: Api.Common.OperationReason) => {
|
||||
emit('update:value', operationReason);
|
||||
};
|
||||
|
||||
const operationReasonRef = ref<Api.Common.OperationReason>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSelect
|
||||
v-model:value="operationReasonRef"
|
||||
:placeholder="$t('common.jobOperationReason.form')"
|
||||
:options="translateOptions(operationReasonOptions)"
|
||||
clearable
|
||||
@update:value="handleUpdate"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
@ -36,12 +36,7 @@ const selectOptions = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSelect
|
||||
v-model:value="modelValue"
|
||||
:placeholder="$t('common.routeKey.routeForm')"
|
||||
:options="selectOptions"
|
||||
clearable
|
||||
/>
|
||||
<NSelect v-model:value="modelValue" :placeholder="$t('common.routeKey.routeForm')" :options="selectOptions" />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -10,6 +10,7 @@ defineOptions({
|
||||
|
||||
interface Props {
|
||||
model: Record<string, any>;
|
||||
btnSpan?: string;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
@ -40,15 +41,16 @@ async function search() {
|
||||
}
|
||||
|
||||
const btnSpan = computed(() => {
|
||||
const keyNum = Object.keys(props.model).length - 2;
|
||||
return `24 m:12 m:${(4 - (keyNum % 4)) * 6}`;
|
||||
const keyNum = Object.keys(props.model).length - 1;
|
||||
|
||||
return props.btnSpan || keyNum % 4 !== 0 ? `24 m:12 m:${(4 - ((keyNum - 1) % 4)) * 6}` : '24';
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NCard :title="title" :bordered="false" size="small" class="card-wrapper">
|
||||
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80" :show-feedback="appStore.isMobile">
|
||||
<NGrid responsive="screen" item-responsive :y-gap="5">
|
||||
<NGrid responsive="screen" item-responsive :y-gap="12">
|
||||
<slot></slot>
|
||||
<NFormItemGi :y-gap="8" :span="btnSpan" class="pr-24px lg:p-t-0 md:p-t-16px">
|
||||
<NSpace class="min-w-172px w-full" justify="end">
|
||||
|
@ -10,10 +10,12 @@ defineOptions({
|
||||
|
||||
interface Props {
|
||||
disabled?: boolean;
|
||||
clearable?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
disabled: false
|
||||
disabled: false,
|
||||
clearable: false
|
||||
});
|
||||
|
||||
const model = defineModel<string | null>();
|
||||
@ -45,6 +47,7 @@ getGroupNameList();
|
||||
:placeholder="$t('page.retryTask.form.groupName')"
|
||||
:options="translateOptions2(groupNameList)"
|
||||
:disabled="props.disabled"
|
||||
:clearable="props.clearable"
|
||||
filterable
|
||||
@update:value="handleUpdate"
|
||||
/>
|
||||
|
@ -12,9 +12,12 @@ const emit = defineEmits<Emits>();
|
||||
|
||||
interface Props {
|
||||
groupName: string | null;
|
||||
clearable?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
clearable: false
|
||||
});
|
||||
|
||||
/** 场景列表 */
|
||||
const sceneNameList = ref<string[]>([]);
|
||||
@ -55,7 +58,7 @@ watch(
|
||||
v-model:value="sceneNameRef"
|
||||
:placeholder="$t('page.retryTask.form.sceneName')"
|
||||
:options="translateOptions2(sceneNameList)"
|
||||
clearable
|
||||
:clearable="props.clearable"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
@ -1,28 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
import { translateOptions } from '@/utils/common';
|
||||
import { taskBatchStatusRecordOptions } from '@/constants/business';
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:value', value: Api.Common.TaskBatchStatus): void;
|
||||
defineOptions({
|
||||
name: 'TaskBatchStatus'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
disabled?: boolean;
|
||||
clearable?: boolean;
|
||||
}
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const taskBatchStatusRef = ref<Api.Common.TaskBatchStatus>();
|
||||
|
||||
const handleUpdate = (taskBatchStatus: Api.Common.TaskBatchStatus) => {
|
||||
emit('update:value', taskBatchStatus);
|
||||
};
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
disabled: false,
|
||||
clearable: false
|
||||
});
|
||||
const modelValue = defineModel<Api.Common.TaskBatchStatus>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSelect
|
||||
v-model:value="taskBatchStatusRef"
|
||||
v-model:value="modelValue"
|
||||
:placeholder="$t('common.taskBatchStatus.form')"
|
||||
:options="translateOptions(taskBatchStatusRecordOptions)"
|
||||
clearable
|
||||
@update:value="handleUpdate"
|
||||
:disabled="props.disabled"
|
||||
:clearable="props.clearable"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
@ -25,7 +25,6 @@ const handleUpdate = (value: Api.Common.BlockStrategy) => {
|
||||
v-model:value="valueRef"
|
||||
:placeholder="$t('common.routeKey.routeForm')"
|
||||
:options="translateOptions(taskTypeRecordRecordOptions)"
|
||||
clearable
|
||||
@update:value="handleUpdate"
|
||||
/>
|
||||
</template>
|
||||
|
@ -25,7 +25,6 @@ const handleUpdate = (value: Api.Common.TriggerType) => {
|
||||
v-model:value="valueRef"
|
||||
:placeholder="$t('common.triggerType.form')"
|
||||
:options="translateOptions(triggerTypeOptions)"
|
||||
clearable
|
||||
@update:value="handleUpdate"
|
||||
/>
|
||||
</template>
|
||||
|
@ -7,9 +7,9 @@ export const REG_PHONE =
|
||||
/**
|
||||
* Password reg
|
||||
*
|
||||
* 6-18 characters, including letters, numbers, and underscores
|
||||
* 由字母、数字、特殊字符,任意2种组成,6-20位
|
||||
*/
|
||||
export const REG_PWD = /^\w{6,18}$/;
|
||||
export const REG_PWD = /^(?![a-zA-Z]+$)(?!\d+$)(?![^\da-zA-Z\s]+$).{6,20}$/;
|
||||
|
||||
/** Email reg */
|
||||
export const REG_EMAIL = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
|
||||
|
@ -36,6 +36,7 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
|
||||
} = useHookTable<A, GetTableData<A>, TableColumn<NaiveUI.TableDataWithIndex<GetTableData<A>>>>({
|
||||
apiFn,
|
||||
apiParams,
|
||||
searchParams: config.searchParams,
|
||||
columns: config.columns,
|
||||
transformer: res => {
|
||||
const { data: records = [], page: current = 1, size = 10, total = 0 } = res.data || {};
|
||||
|
@ -34,10 +34,10 @@ const { formRef, validate } = useNaiveForm();
|
||||
type RuleRecord = Partial<Record<keyof Model, App.Global.FormRule[]>>;
|
||||
|
||||
const rules = computed<RuleRecord>(() => {
|
||||
const { formRules, createConfirmPwdRule } = useFormRules();
|
||||
const { formRules, createConfirmPwdRule, defaultRequiredRule } = useFormRules();
|
||||
|
||||
return {
|
||||
oldPassword: formRules.pwd,
|
||||
oldPassword: [defaultRequiredRule],
|
||||
newPassword: formRules.pwd,
|
||||
checkPassword: createConfirmPwdRule(model.newPassword!)
|
||||
};
|
||||
|
@ -17,7 +17,7 @@ withDefaults(defineProps<Props>(), {
|
||||
|
||||
<template>
|
||||
<RouterLink to="/" class="w-full flex-center nowrap-hidden">
|
||||
<SystemLogo class="text-36px text-primary" />
|
||||
<SystemLogo class="fill-primary text-36px" />
|
||||
<h2 v-show="showTitle" class="pl-8px text-27px text-primary font-bold transition duration-300 ease-in-out">
|
||||
{{ $t('system.title') }}
|
||||
</h2>
|
||||
|
@ -1,24 +1,60 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
<script lang="tsx" setup>
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { NEllipsis } from 'naive-ui';
|
||||
import { $t } from '@/locales';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import ButtonIcon from '@/components/custom/button-icon.vue';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'NamespaceSelect'
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const authStore = useAuthStore();
|
||||
const namespaceId = ref<string>(localStg.get('namespaceId')!);
|
||||
const userInfo = localStg.get('userInfo');
|
||||
const selectOptions = computed(() =>
|
||||
userInfo?.namespaceIds.map(item => {
|
||||
return { label: item.name, value: item.uniqueId };
|
||||
})
|
||||
const namespaceIds = ref(localStg.get('userInfo')?.namespaceIds || []);
|
||||
|
||||
watch(
|
||||
() => authStore.namespaceUniqueId,
|
||||
val => {
|
||||
namespaceId.value = val;
|
||||
authStore.setNamespaceId(val);
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => authStore.userInfo.namespaceIds,
|
||||
val => {
|
||||
namespaceIds.value = val;
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const dropOptions = computed(() =>
|
||||
userInfo?.namespaceIds.map(item => {
|
||||
return { label: item.name, key: item.uniqueId };
|
||||
namespaceIds.value.map(item => {
|
||||
return {
|
||||
label: () => {
|
||||
if (item.uniqueId === namespaceId.value) {
|
||||
return (
|
||||
<div class="max-w-130px flex items-center justify-between">
|
||||
<NEllipsis tooltip={{ placement: 'left' }}>{item.name}</NEllipsis>
|
||||
<SvgIcon class="ml-6px" icon="ant-design:check-outlined" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div class="max-w-130px flex items-center justify-between">
|
||||
<NEllipsis tooltip={{ placement: 'left' }}>{item.name}</NEllipsis>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
key: item.uniqueId
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
@ -27,31 +63,80 @@ const onChange = (value: string) => {
|
||||
authStore.setNamespaceId(value);
|
||||
router.go(0);
|
||||
};
|
||||
|
||||
const namespaceName = computed(() => {
|
||||
return namespaceIds.value.filter(item => item.uniqueId === namespaceId.value)[0]?.name || 'Default';
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDropdown v-if="appStore.isMobile" :value="namespaceId" :options="dropOptions" trigger="hover" @select="onChange">
|
||||
<div>
|
||||
<ButtonIcon :tooltip-content="$t('icon.namespace')" tooltip-placement="left">
|
||||
<SvgIcon icon="oui:app-spaces" />
|
||||
<SvgIcon icon="eos-icons:namespace" />
|
||||
</ButtonIcon>
|
||||
</div>
|
||||
</NDropdown>
|
||||
|
||||
<NDropdown v-else :value="namespaceId" :options="dropOptions" trigger="click" @select="onChange">
|
||||
<div class="namespace-select">
|
||||
<ButtonIcon class="w-full" :tooltip-content="$t('icon.namespace')" tooltip-placement="left">
|
||||
<SvgIcon icon="eos-icons:namespace" />
|
||||
<NEllipsis class="text-14px">{{ namespaceName }}</NEllipsis>
|
||||
<SvgIcon icon="material-symbols:expand-more-rounded" />
|
||||
</ButtonIcon>
|
||||
</div>
|
||||
</NDropdown>
|
||||
<NSelect
|
||||
v-else
|
||||
v-model:value="namespaceId"
|
||||
class="namespace-select"
|
||||
:options="selectOptions"
|
||||
@update:value="onChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.namespace-select {
|
||||
width: 150px;
|
||||
width: 158px;
|
||||
border: 1px solid rgb(224, 224, 230);
|
||||
border-radius: 35px;
|
||||
|
||||
:deep(.n-base-selection) {
|
||||
border-radius: 32px !important;
|
||||
:deep(.n-button):hover,
|
||||
:deep(.n-button):focus {
|
||||
background-color: var(--n-color);
|
||||
}
|
||||
|
||||
:deep(.n-ellipsis) {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
max-width: 88px;
|
||||
}
|
||||
|
||||
:deep(.n-button) {
|
||||
width: 100% !important;
|
||||
padding: 0 5px 0 10px !important;
|
||||
}
|
||||
|
||||
:deep(.n-button__content) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
:deep(.gap-8px) {
|
||||
gap: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.flex-center) {
|
||||
width: 100% !important;
|
||||
justify-content: space-between !important;
|
||||
}
|
||||
}
|
||||
|
||||
.namespace-select:hover {
|
||||
border-color: rgb(var(--nprogress-color));
|
||||
}
|
||||
|
||||
.namespace-select-option {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
:deep(.n-ellipsis) {
|
||||
width: 100%;
|
||||
max-width: 113px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -82,6 +82,8 @@ const local: App.I18n.Schema = {
|
||||
confirmRetry: 'Are you sure you want to retry?',
|
||||
idDetailTip: 'Click on ID for details',
|
||||
log: 'Log',
|
||||
generateRandomly: 'Generate randomly',
|
||||
active: 'Active',
|
||||
yesOrNo: {
|
||||
yes: 'Yes',
|
||||
no: 'No'
|
||||
@ -201,7 +203,10 @@ const local: App.I18n.Schema = {
|
||||
}
|
||||
},
|
||||
updateDt: 'Updated Time',
|
||||
createDt: 'Created Time'
|
||||
createDt: 'Created Time',
|
||||
currentMonth: 'Current Month',
|
||||
lastMonth: 'Last Month',
|
||||
lastTwoMonth: 'Last 2 Month'
|
||||
},
|
||||
request: {
|
||||
logout: 'Logout user after request failed',
|
||||
@ -309,7 +314,7 @@ const local: App.I18n.Schema = {
|
||||
namespace: 'Namespace',
|
||||
notify: 'Notify',
|
||||
notify_recipient: 'Notify Recipient',
|
||||
notify_scene: 'Notify Scene',
|
||||
notify_config: 'Notify Config',
|
||||
retry: 'Retry Task',
|
||||
retry_task: 'Retry Task',
|
||||
retry_scene: 'Retry Scene',
|
||||
@ -909,7 +914,7 @@ const local: App.I18n.Schema = {
|
||||
},
|
||||
pwd: {
|
||||
required: 'Please enter password',
|
||||
invalid: '6-18 characters, including letters, numbers, and underscores'
|
||||
invalid: 'Letters, numbers, and special characters, combination of two, 6 to 20 characters'
|
||||
},
|
||||
confirmPwd: {
|
||||
required: 'Please enter password again',
|
||||
|
@ -82,6 +82,8 @@ const local: App.I18n.Schema = {
|
||||
confirmRetry: '确认重试吗?',
|
||||
log: '日志',
|
||||
idDetailTip: '点击 ID 查看详情',
|
||||
generateRandomly: '随机生成',
|
||||
active: '活跃',
|
||||
yesOrNo: {
|
||||
yes: '是',
|
||||
no: '否'
|
||||
@ -201,7 +203,10 @@ const local: App.I18n.Schema = {
|
||||
}
|
||||
},
|
||||
updateDt: '更新时间',
|
||||
createDt: '创建时间'
|
||||
createDt: '创建时间',
|
||||
currentMonth: '当月',
|
||||
lastMonth: '最近一月',
|
||||
lastTwoMonth: '最近两月'
|
||||
},
|
||||
request: {
|
||||
logout: '请求失败后登出用户',
|
||||
@ -310,7 +315,7 @@ const local: App.I18n.Schema = {
|
||||
group: '组管理',
|
||||
notify: '告警通知',
|
||||
notify_recipient: '通知人',
|
||||
notify_scene: '通知场景',
|
||||
notify_config: '通知配置',
|
||||
retry: '重试任务',
|
||||
retry_task: '任务管理',
|
||||
'retry_dead-letter': '死信任务',
|
||||
@ -915,7 +920,7 @@ const local: App.I18n.Schema = {
|
||||
},
|
||||
pwd: {
|
||||
required: '请输入密码',
|
||||
invalid: '密码格式不正确,6-18位字符,包含字母、数字、下划线'
|
||||
invalid: '由字母、数字、特殊字符,任意2种组成,6-20位'
|
||||
},
|
||||
confirmPwd: {
|
||||
required: '请输入确认密码',
|
||||
@ -950,7 +955,7 @@ const local: App.I18n.Schema = {
|
||||
expand: '展开菜单',
|
||||
pin: '固定',
|
||||
unpin: '取消固定',
|
||||
namespace: '切换空间'
|
||||
namespace: '切换命名空间'
|
||||
},
|
||||
datatable: {
|
||||
itemCount: '共 {total} 条'
|
||||
|
@ -18,7 +18,7 @@ export function setupLoading() {
|
||||
'right-0 bottom-0 animate-delay-1500'
|
||||
];
|
||||
|
||||
const logoWithClass = systemLogo.replace('<svg', `<svg class="size-158px text-primary"`);
|
||||
const logoWithClass = systemLogo.replace('<svg', `<svg class="size-158px fill-primary"`);
|
||||
|
||||
const dot = loadingClasses
|
||||
.map(item => {
|
||||
|
@ -27,8 +27,8 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
||||
job_batch: () => import("@/views/job/batch/index.vue"),
|
||||
job_task: () => import("@/views/job/task/index.vue"),
|
||||
namespace: () => import("@/views/namespace/index.vue"),
|
||||
notify_config: () => import("@/views/notify/config/index.vue"),
|
||||
notify_recipient: () => import("@/views/notify/recipient/index.vue"),
|
||||
notify_scene: () => import("@/views/notify/scene/index.vue"),
|
||||
pods: () => import("@/views/pods/index.vue"),
|
||||
"retry_dead-letter": () => import("@/views/retry/dead-letter/index.vue"),
|
||||
retry_log: () => import("@/views/retry/log/index.vue"),
|
||||
|
@ -166,6 +166,16 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
icon: 'material-symbols:notifications-active-outline-rounded'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'notify_config',
|
||||
path: '/notify/config',
|
||||
component: 'view.notify_config',
|
||||
meta: {
|
||||
title: 'notify_config',
|
||||
i18nKey: 'route.notify_config',
|
||||
icon: 'cbi:scene-dynamic'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'notify_recipient',
|
||||
path: '/notify/recipient',
|
||||
@ -175,16 +185,6 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
i18nKey: 'route.notify_recipient',
|
||||
icon: 'fluent:people-call-20-filled'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'notify_scene',
|
||||
path: '/notify/scene',
|
||||
component: 'view.notify_scene',
|
||||
meta: {
|
||||
title: 'notify_scene',
|
||||
i18nKey: 'route.notify_scene',
|
||||
icon: 'cbi:scene-dynamic'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -18,7 +18,7 @@ export function fetchTriggerWorkflow(id: string) {
|
||||
}
|
||||
|
||||
/** get namespace list */
|
||||
export function fetchGetWorkflowNameList(params?: Api.WorkflowBatch.WorkflowBatchSearchParams) {
|
||||
export function fetchGetWorkflowNameList(params?: Api.Workflow.WorkflowNameSearchParams) {
|
||||
return request<Api.Workflow.Workflow[]>({
|
||||
url: '/workflow/workflow-name/list',
|
||||
method: 'get',
|
||||
|
@ -13,6 +13,9 @@ const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
||||
export const request = createFlatRequest<App.Service.Response, RequestInstanceState>(
|
||||
{
|
||||
baseURL,
|
||||
'axios-retry': {
|
||||
retries: 0
|
||||
},
|
||||
headers: {
|
||||
timeout: 6000
|
||||
}
|
||||
@ -52,14 +55,14 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
||||
|
||||
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
|
||||
const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
|
||||
if (logoutCodes.includes(response.data.status.toString())) {
|
||||
if (logoutCodes.includes(response.data.status?.toString())) {
|
||||
handleLogout();
|
||||
return null;
|
||||
}
|
||||
|
||||
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
|
||||
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
||||
if (modalLogoutCodes.includes(response.data.status.toString())) {
|
||||
if (modalLogoutCodes.includes(response.data.status?.toString())) {
|
||||
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.message];
|
||||
|
||||
// prevent the user from refreshing the page
|
||||
@ -116,7 +119,7 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
||||
|
||||
// get backend error message and code
|
||||
message = error.response?.data?.message || message;
|
||||
backendErrorCode = error.response?.data?.status.toString() || '';
|
||||
backendErrorCode = error.response?.data?.status?.toString() || '';
|
||||
|
||||
// the error message is displayed in the modal
|
||||
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
||||
|
@ -19,6 +19,8 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
|
||||
const token = ref(getToken());
|
||||
|
||||
const namespaceUniqueId = ref('');
|
||||
|
||||
const userInfo: Api.Auth.UserInfo = reactive({
|
||||
id: '',
|
||||
userId: '',
|
||||
@ -35,7 +37,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
const isStaticSuper = computed(() => {
|
||||
const { VITE_AUTH_ROUTE_MODE, VITE_STATIC_SUPER_ROLE } = import.meta.env;
|
||||
return (
|
||||
VITE_AUTH_ROUTE_MODE === 'static' && userInfo.roles.map(role => role.toString()).includes(VITE_STATIC_SUPER_ROLE)
|
||||
VITE_AUTH_ROUTE_MODE === 'static' && userInfo.roles.map(role => role?.toString()).includes(VITE_STATIC_SUPER_ROLE)
|
||||
);
|
||||
});
|
||||
|
||||
@ -160,6 +162,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
}
|
||||
|
||||
function setNamespaceId(namespaceId: string) {
|
||||
namespaceUniqueId.value = namespaceId;
|
||||
const userNamespace = localStg.get('userNamespace') || {};
|
||||
userNamespace[userInfo.userId] = namespaceId;
|
||||
localStg.set('userNamespace', userNamespace);
|
||||
@ -169,11 +172,13 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
return {
|
||||
token,
|
||||
userInfo,
|
||||
namespaceUniqueId,
|
||||
isStaticSuper,
|
||||
isLogin,
|
||||
loginLoading,
|
||||
resetStore,
|
||||
login,
|
||||
getUserInfo,
|
||||
initUserInfo,
|
||||
initAppVersion,
|
||||
setNamespaceId
|
||||
|
25
src/typings/api.d.ts
vendored
25
src/typings/api.d.ts
vendored
@ -287,8 +287,7 @@ declare namespace Api {
|
||||
groupName?: string;
|
||||
type: DashboardLineType;
|
||||
mode?: DashboardLineMode;
|
||||
startTime?: string;
|
||||
endTime?: string;
|
||||
datetimeRange?: [string, string] | null;
|
||||
} & CommonSearchParams;
|
||||
|
||||
/**
|
||||
@ -718,7 +717,7 @@ declare namespace Api {
|
||||
Api.RetryDeadLetter.DeadLetter,
|
||||
'id' | 'uniqueId' | 'groupName' | 'sceneName' | 'idempotentId' | 'bizNo' | 'taskType' | 'createDt'
|
||||
> &
|
||||
CommonSearchParams
|
||||
CommonSearchParams & { datetimeRange?: [string, string] }
|
||||
>;
|
||||
|
||||
/** DeadLetter list */
|
||||
@ -914,6 +913,18 @@ declare namespace Api {
|
||||
Pick<Api.Workflow.Workflow, 'workflowName' | 'groupName' | 'workflowStatus'> & CommonSearchParams
|
||||
>;
|
||||
|
||||
/** workflow name search params */
|
||||
type WorkflowNameSearchParams = CommonType.RecordNullable<
|
||||
Pick<
|
||||
Common.CommonRecord<{
|
||||
keywords: string;
|
||||
workflowId: number;
|
||||
groupName: string;
|
||||
}>,
|
||||
'keywords' | 'workflowId' | 'groupName'
|
||||
>
|
||||
>;
|
||||
|
||||
type ExportWorkflow = Common.CommonRecord<{
|
||||
workflowIds: String[];
|
||||
}> &
|
||||
@ -1113,7 +1124,8 @@ declare namespace Api {
|
||||
|
||||
/** JobBatch search params */
|
||||
type JobBatchSearchParams = CommonType.RecordNullable<
|
||||
Pick<Api.JobBatch.JobBatch, 'groupName' | 'jobName' | 'taskBatchStatus' | 'taskType'> & CommonSearchParams
|
||||
Pick<Api.JobBatch.JobBatch, 'groupName' | 'jobName' | 'taskBatchStatus' | 'jobId' | 'taskType'> &
|
||||
CommonSearchParams & { datetimeRange?: [string, string] }
|
||||
>;
|
||||
|
||||
/** JobBatch list */
|
||||
@ -1148,7 +1160,8 @@ declare namespace Api {
|
||||
|
||||
/** workflowBatch search params */
|
||||
type WorkflowBatchSearchParams = CommonType.RecordNullable<
|
||||
Pick<Api.WorkflowBatch.WorkflowBatch, 'workflowId' | 'groupName' | 'taskBatchStatus'> & CommonSearchParams
|
||||
Pick<Api.WorkflowBatch.WorkflowBatch, 'workflowId' | 'groupName' | 'workflowName' | 'taskBatchStatus'> &
|
||||
CommonSearchParams & { datetimeRange?: [string, string] }
|
||||
>;
|
||||
|
||||
/** workflowBatch list */
|
||||
@ -1198,7 +1211,7 @@ declare namespace Api {
|
||||
/** retryLog search params */
|
||||
type RetryLogSearchParams = CommonType.RecordNullable<
|
||||
Pick<Api.RetryLog.RetryLog, 'uniqueId' | 'groupName' | 'sceneName' | 'idempotentId' | 'bizNo' | 'retryStatus'> &
|
||||
CommonSearchParams
|
||||
CommonSearchParams & { datetimeRange?: [string, string] }
|
||||
>;
|
||||
|
||||
/** retryLog list */
|
||||
|
5
src/typings/app.d.ts
vendored
5
src/typings/app.d.ts
vendored
@ -332,6 +332,8 @@ declare namespace App {
|
||||
confirmPause: string;
|
||||
confirmFinish: string;
|
||||
confirmRetry: string;
|
||||
generateRandomly: string;
|
||||
active: string;
|
||||
log: string;
|
||||
idDetailTip: string;
|
||||
yesOrNo: {
|
||||
@ -454,6 +456,9 @@ declare namespace App {
|
||||
};
|
||||
updateDt: string;
|
||||
createDt: string;
|
||||
currentMonth: string;
|
||||
lastMonth: string;
|
||||
lastTwoMonth: string;
|
||||
};
|
||||
request: {
|
||||
logout: string;
|
||||
|
2
src/typings/naive-ui.d.ts
vendored
2
src/typings/naive-ui.d.ts
vendored
@ -42,7 +42,7 @@ declare namespace NaiveUI {
|
||||
|
||||
type NaiveTableConfig<A extends TableApiFn> = Pick<
|
||||
import('@sa/hooks').TableConfig<A, GetTableData<A>, TableColumn<TableDataWithIndex<GetTableData<A>>>>,
|
||||
'apiFn' | 'apiParams' | 'columns' | 'immediate'
|
||||
'apiFn' | 'apiParams' | 'columns' | 'immediate' | 'searchParams'
|
||||
> & {
|
||||
/**
|
||||
* whether to display the total items count
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Md5 } from 'ts-md5';
|
||||
import dayjs from 'dayjs';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
/**
|
||||
@ -118,6 +119,34 @@ export function toggleHtmlClass(className: string) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 `最近n个自然月` timestamp时间区间
|
||||
*
|
||||
* @param months 月数
|
||||
* @param startOf 时间的开始类型
|
||||
* @returns timestamp时间区间
|
||||
*/
|
||||
export function monthRange(months: number = 1, startOf: dayjs.OpUnitType = 'day') {
|
||||
return [dayjs().subtract(months, 'month').startOf(startOf).valueOf(), dayjs().endOf('day').valueOf()] as [
|
||||
number,
|
||||
number
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 `最近n个自然月` 字符串时间区间
|
||||
*
|
||||
* @param months 月数
|
||||
* @param startOf 时间的开始类型
|
||||
* @returns 字符串时间区间
|
||||
*/
|
||||
export function monthRangeISO8601(months: number = 1, startOf: dayjs.OpUnitType = 'day') {
|
||||
return [
|
||||
dayjs().subtract(months, 'month').startOf(startOf).format('YYYY-MM-DDTHH:mm:ss'),
|
||||
dayjs().endOf('day').format('YYYY-MM-DDTHH:mm:ss')
|
||||
] as [string, string];
|
||||
}
|
||||
|
||||
export function isNotNull(value: any) {
|
||||
return value !== undefined && value !== null && value !== '' && value !== 'undefined';
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ const href = (url: string) => {
|
||||
<NCard :bordered="false" class="relative z-4 w-auto rd-12px">
|
||||
<div class="w-400px lt-sm:w-300px">
|
||||
<header class="flex-y-center justify-between">
|
||||
<SystemLogo class="text-64px text-primary lt-sm:text-48px" />
|
||||
<SystemLogo class="fill-primary text-64px lt-sm:text-48px" />
|
||||
<h3 class="flex text-28px text-primary font-500 lt-sm:text-22px">
|
||||
{{ $t('system.title') }}
|
||||
<span class="mt-3px pl-12px text-16px color-#00000072 font-600">v{{ version }}</span>
|
||||
|
@ -37,7 +37,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64
|
||||
|
@ -28,7 +28,7 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.groupConfig.groupName')" path="groupName" class="pr-24px">
|
||||
<NInput v-model:value="model.groupName" :placeholder="$t('page.groupConfig.form.groupName')" />
|
||||
<NInput v-model:value="model.groupName" :placeholder="$t('page.groupConfig.form.groupName')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.groupConfig.groupStatus')" path="groupStatus" class="pr-24px">
|
||||
<NSelect
|
||||
|
@ -4,6 +4,7 @@ import type { DataTableColumns } from 'naive-ui';
|
||||
import { $t } from '@/locales';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { fetchAllGroupName, fetchJobLine, fetchRetryLine } from '@/service/api';
|
||||
import DatetimeRange from '@/components/common/datetime-range.vue';
|
||||
import TaskLineChart from './task-line-chart.vue';
|
||||
import TaskPieChart from './task-pie-chart.vue';
|
||||
|
||||
@ -26,12 +27,9 @@ const tabParams = ref<Api.Dashboard.DashboardLineParams>({
|
||||
type: 'WEEK',
|
||||
page: 1,
|
||||
size: 6,
|
||||
mode: 'JOB'
|
||||
mode: 'JOB',
|
||||
datetimeRange: null
|
||||
});
|
||||
const dateRange = ref<[number, number] | null>();
|
||||
const formattedValue = ref<[string, string] | null>(
|
||||
tabParams.value.startTime && tabParams.value.endTime ? [tabParams.value.startTime, tabParams.value.endTime] : null
|
||||
);
|
||||
|
||||
const getData = async () => {
|
||||
const { data: lineData, error } =
|
||||
@ -67,26 +65,19 @@ const onUpdateTab = (value: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
const onUpdateDate = (value: [string, string]) => {
|
||||
const onUpdateDate = (value: [string, string] | null) => {
|
||||
if (value) {
|
||||
tabParams.value.type = 'OTHERS';
|
||||
tabParams.value.startTime = value[0];
|
||||
tabParams.value.endTime = value[1];
|
||||
}
|
||||
};
|
||||
|
||||
const onClearDate = () => {
|
||||
tabParams.value.type = 'WEEK';
|
||||
tabParams.value.startTime = undefined;
|
||||
tabParams.value.endTime = undefined;
|
||||
};
|
||||
|
||||
const onUpdateType = (value: string) => {
|
||||
if (value !== 'OTHERS') {
|
||||
dateRange.value = null;
|
||||
formattedValue.value = null;
|
||||
tabParams.value.startTime = undefined;
|
||||
tabParams.value.endTime = undefined;
|
||||
tabParams.value.datetimeRange = null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -213,16 +204,7 @@ getGroupNames();
|
||||
<NRadioButton value="MONTH" :label="$t('page.home.retryTab.params.month')" />
|
||||
<NRadioButton value="YEAR" :label="$t('page.home.retryTab.params.year')" />
|
||||
</NRadioGroup>
|
||||
<NDatePicker
|
||||
v-model:value="dateRange"
|
||||
v-model:formatted-value="formattedValue"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="daterange"
|
||||
class="w-300px lg:w-230px md:w-270px"
|
||||
clearable
|
||||
@update:formatted-value="onUpdateDate"
|
||||
@clear="onClearDate"
|
||||
/>
|
||||
<DatetimeRange v-model:value="tabParams.datetimeRange" @update:value="onUpdateDate" @clear="onClearDate" />
|
||||
<NSelect v-model:value="tabParams.groupName" :options="groupOptions" class="w-200px lg:w-150px md:w-170px" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,26 +1,26 @@
|
||||
<script setup lang="tsx">
|
||||
import { NButton, NPopconfirm, NTag, NTooltip } from 'naive-ui';
|
||||
import { useBoolean } from '@sa/hooks';
|
||||
import { ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { fetchGetJobBatchList, fetchGetJobNameList, fetchJobBatchRetry, fetchJobBatchStop } from '@/service/api';
|
||||
import { ref } from 'vue';
|
||||
import { fetchGetJobBatchList, fetchJobBatchRetry, fetchJobBatchStop } from '@/service/api';
|
||||
import { $t } from '@/locales';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTable } from '@/hooks/common/table';
|
||||
import { operationReasonRecord, taskBatchStatusRecord, taskTypeRecord } from '@/constants/business';
|
||||
import { tagColor } from '@/utils/common';
|
||||
import { monthRangeISO8601, tagColor } from '@/utils/common';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
import JobBatchSearch from './modules/job-batch-search.vue';
|
||||
import JobBatchDetailDrawer from './modules/job-batch-detail-drawer.vue';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const route = useRoute();
|
||||
|
||||
/** 详情页属性数据 */
|
||||
const detailData = ref<Api.JobBatch.JobBatch | null>();
|
||||
/** 详情页可见状态 */
|
||||
const { bool: detailVisible, setTrue: openDetail } = useBoolean(false);
|
||||
const { bool: detailLog, setBool: setDetailLog } = useBoolean(false);
|
||||
const jobName = history.state.jobName;
|
||||
const jobId = history.state.jobId;
|
||||
const taskBatchStatus = history.state.taskBatchStatus;
|
||||
|
||||
const { columnChecks, columns, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
|
||||
apiFn: fetchGetJobBatchList,
|
||||
@ -29,7 +29,14 @@ const { columnChecks, columns, data, getData, loading, mobilePagination, searchP
|
||||
size: 10,
|
||||
groupName: null,
|
||||
jobName: null,
|
||||
taskBatchStatus: null
|
||||
taskBatchStatus: null,
|
||||
jobId: null,
|
||||
datetimeRange: monthRangeISO8601()
|
||||
},
|
||||
searchParams: {
|
||||
jobId,
|
||||
jobName,
|
||||
taskBatchStatus
|
||||
},
|
||||
columns: () => [
|
||||
{
|
||||
@ -211,41 +218,6 @@ async function handleStopJob(id: string) {
|
||||
getData();
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理路由 query 参数变化 */
|
||||
async function handleQueryChanged(jobId: number) {
|
||||
if (!jobId) {
|
||||
searchParams.jobName = null;
|
||||
} else {
|
||||
const { data: jobList, error } = await fetchGetJobNameList({ jobId });
|
||||
if (!error && jobList.length > 0) {
|
||||
const jobName = jobList[0].jobName;
|
||||
searchParams.jobName = jobName;
|
||||
}
|
||||
}
|
||||
getData();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => route.query,
|
||||
() => {
|
||||
if (route.name === 'job_batch' && route.query.jobId) {
|
||||
const jobId = Number(route.query.jobId);
|
||||
handleQueryChanged(jobId);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
function initParams() {
|
||||
const taskBatchStatus = history.state.taskBatchStatus;
|
||||
if (taskBatchStatus) {
|
||||
searchParams.taskBatchStatus = taskBatchStatus;
|
||||
getData();
|
||||
}
|
||||
}
|
||||
|
||||
initParams();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,7 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import type { SelectOption } from 'naive-ui';
|
||||
import SelectGroup from '@/components/common/select-group.vue';
|
||||
import TaskBatchStatus from '@/components/common/task-batch-status.vue';
|
||||
import DatetimeRange from '@/components/common/datetime-range.vue';
|
||||
import { $t } from '@/locales';
|
||||
import { fetchGetJobNameList } from '@/service/api';
|
||||
|
||||
defineOptions({
|
||||
name: 'JobBatchSearch'
|
||||
@ -12,29 +16,84 @@ interface Emits {
|
||||
(e: 'search'): void;
|
||||
}
|
||||
|
||||
const noSearchFlag = ref(false);
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
/** 定时任务列表 */
|
||||
const jobList = ref<Api.Job.Job[]>([]);
|
||||
|
||||
const model = defineModel<Api.JobBatch.JobBatchSearchParams>('model', { required: true });
|
||||
const keywords = ref<string>(model.value.jobName as string);
|
||||
|
||||
function reset() {
|
||||
keywords.value = '';
|
||||
emit('reset');
|
||||
}
|
||||
|
||||
function search() {
|
||||
emit('search');
|
||||
}
|
||||
|
||||
async function keywordsUpdate() {
|
||||
const res = await fetchGetJobNameList({ keywords: keywords.value, groupName: model.value.groupName });
|
||||
jobList.value = res.data as Api.Job.Job[];
|
||||
}
|
||||
|
||||
function handleSelect(value: string) {
|
||||
model.value.jobId = value;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => keywords.value,
|
||||
(value: string) => {
|
||||
if (value.length !== 0) {
|
||||
keywordsUpdate();
|
||||
} else {
|
||||
noSearchFlag.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function translateOptions(options: Api.Job.Job[]) {
|
||||
return options.map(option => ({
|
||||
value: option.id,
|
||||
label: option.jobName
|
||||
}));
|
||||
}
|
||||
|
||||
function renderLabel(option: SelectOption) {
|
||||
return [option.label as string, `(${option.value})`];
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<SearchForm btn-span="24 s:24 m:9 l:12 xl:15" :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobBatch.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobBatch.jobName')" path="jobName" class="pr-24px">
|
||||
<NInput v-model:value="model.jobName" :placeholder="$t('page.jobBatch.form.jobName')" />
|
||||
<NAutoComplete
|
||||
v-model:value="keywords"
|
||||
:placeholder="$t('page.jobBatch.form.jobName')"
|
||||
:options="translateOptions(jobList)"
|
||||
:empty-visible="noSearchFlag"
|
||||
clearable
|
||||
filterable
|
||||
:render-label="renderLabel"
|
||||
@select="handleSelect"
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobBatch.taskBatchStatus')" path="taskBatchStatus" class="pr-24px">
|
||||
<TaskBatchStatus v-model:value="model.taskBatchStatus" />
|
||||
<TaskBatchStatus v-model:value="model.taskBatchStatus" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi
|
||||
span="24 s:24 m:15 l:12 xl:9"
|
||||
:label="$t('page.common.createTime')"
|
||||
path="datetimeRange"
|
||||
class="pr-24px"
|
||||
>
|
||||
<DatetimeRange v-model:value="model.datetimeRange!" />
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
||||
|
@ -41,7 +41,7 @@ const { columnChecks, columns, data, getData, loading, mobilePagination, searchP
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 48
|
||||
@ -252,7 +252,8 @@ async function handleTriggerJob(id: string) {
|
||||
}
|
||||
|
||||
function goToBatch(jobId: string) {
|
||||
routerPushByKey('job_batch', { query: { jobId } });
|
||||
const findItem = data.value.find(item => item.id === jobId)!;
|
||||
routerPushByKey('job_batch', { state: { jobId, jobName: findItem.jobName } });
|
||||
}
|
||||
|
||||
function body(): Api.Job.ExportJob {
|
||||
|
@ -162,6 +162,7 @@ async function handleSubmit() {
|
||||
groupName,
|
||||
jobName,
|
||||
argsType,
|
||||
argsStr,
|
||||
jobStatus,
|
||||
routeKey,
|
||||
executorType,
|
||||
@ -179,7 +180,7 @@ async function handleSubmit() {
|
||||
const { error } = await fetchAddJob({
|
||||
groupName,
|
||||
jobName,
|
||||
argsStr: parseArgsStr(),
|
||||
argsStr,
|
||||
argsType,
|
||||
jobStatus,
|
||||
routeKey,
|
||||
@ -204,6 +205,7 @@ async function handleSubmit() {
|
||||
id,
|
||||
groupName,
|
||||
jobName,
|
||||
argsStr,
|
||||
argsType,
|
||||
jobStatus,
|
||||
routeKey,
|
||||
@ -223,7 +225,7 @@ async function handleSubmit() {
|
||||
id,
|
||||
groupName,
|
||||
jobName,
|
||||
argsStr: parseArgsStr(),
|
||||
argsStr,
|
||||
argsType,
|
||||
jobStatus,
|
||||
routeKey,
|
||||
@ -249,7 +251,8 @@ async function handleSubmit() {
|
||||
|
||||
function parseArgsStr() {
|
||||
if (model.taskType === 3 && dynamicForm.args) {
|
||||
return JSON.stringify(dynamicForm.args.map(item => item.arg));
|
||||
const slices = dynamicForm.args.map(item => item.arg.trim()).filter(item => Boolean(item));
|
||||
model.argsStr = slices.length > 0 ? JSON.stringify(slices) : '';
|
||||
}
|
||||
return model.argsStr;
|
||||
}
|
||||
@ -268,6 +271,26 @@ watch(visible, () => {
|
||||
restoreValidation();
|
||||
}
|
||||
});
|
||||
|
||||
/** 分片参数变化, 解析并序列化到model.argsStr */
|
||||
watch(dynamicForm, () => {
|
||||
if (visible.value && model.taskType === 3) {
|
||||
parseArgsStr();
|
||||
}
|
||||
});
|
||||
|
||||
/** 任务类型变化, 清理分片参数/方法参数 */
|
||||
watch(
|
||||
() => model.taskType,
|
||||
taskType => {
|
||||
if (visible.value) {
|
||||
if (taskType !== 3) {
|
||||
dynamicForm.args = [];
|
||||
}
|
||||
model.argsStr = '';
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -29,16 +29,17 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobTask.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobTask.jobName')" path="jobName" class="pr-24px">
|
||||
<NInput v-model:value="model.jobName" :placeholder="$t('page.jobTask.form.jobName')" />
|
||||
<NInput v-model:value="model.jobName" :placeholder="$t('page.jobTask.form.jobName')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.jobTask.jobStatus')" path="jobStatus" class="pr-24px">
|
||||
<NSelect
|
||||
v-model:value="model.jobStatus"
|
||||
:placeholder="$t('page.jobTask.form.jobStatus')"
|
||||
:options="translateOptions(enableStatusNumberOptions)"
|
||||
clearable
|
||||
/>
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
|
@ -1,13 +1,24 @@
|
||||
<script setup lang="tsx">
|
||||
import { NButton } from 'naive-ui';
|
||||
import { ref } from 'vue';
|
||||
import { fetchGetNamespaceList } from '@/service/api';
|
||||
import { $t } from '@/locales';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
import NamespaceOperateDrawer from './modules/namespace-operate-drawer.vue';
|
||||
import NamespaceSearch from './modules/namespace-search.vue';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const authStore = useAuthStore();
|
||||
const namespaceId = ref<string>(localStg.get('namespaceId')!);
|
||||
|
||||
const handleChange = (uniqueId: string) => {
|
||||
namespaceId.value = uniqueId;
|
||||
authStore.setNamespaceId(uniqueId);
|
||||
};
|
||||
|
||||
const { columns, columnChecks, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
|
||||
apiFn: fetchGetNamespaceList,
|
||||
@ -18,7 +29,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
},
|
||||
columns: () => [
|
||||
// {
|
||||
// key: 'index',
|
||||
// key: 'id',
|
||||
// title: $t('common.index'),
|
||||
// align: 'center',
|
||||
// width: 64
|
||||
@ -29,6 +40,21 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
align: 'left',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
title: $t('common.active'),
|
||||
align: 'center',
|
||||
width: 40,
|
||||
render: row => (
|
||||
<div class="flex justify-center">
|
||||
{namespaceId.value === row.uniqueId! ? (
|
||||
<SvgIcon icon="material-symbols:check-circle" class="text-20px color-success" />
|
||||
) : (
|
||||
<SvgIcon icon="material-symbols:cancel" class="text-20px color-gray400" />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'uniqueId',
|
||||
title: $t('page.namespace.uniqueId'),
|
||||
@ -57,6 +83,16 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
<NButton type="primary" text ghost size="small" onClick={() => edit(row.id!)}>
|
||||
{$t('common.edit')}
|
||||
</NButton>
|
||||
{namespaceId.value !== row.uniqueId! ? (
|
||||
<>
|
||||
<n-divider vertical />
|
||||
<NButton type="warning" text ghost size="small" onClick={() => handleChange(row.uniqueId!)}>
|
||||
{$t('common.switch')}
|
||||
</NButton>
|
||||
</>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { nanoid } from '@sa/utils';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
import OperateDrawer from '@/components/common/operate-drawer.vue';
|
||||
import { $t } from '@/locales';
|
||||
import { fetchAddNamespace, fetchEditNamespace } from '@/service/api';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
|
||||
defineOptions({
|
||||
name: 'NamespaceOperateDrawer'
|
||||
@ -24,6 +26,7 @@ interface Emits {
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
@ -61,6 +64,10 @@ const rules: Record<RuleKey, App.Global.FormRule> = {
|
||||
}
|
||||
};
|
||||
|
||||
function setUniqueId() {
|
||||
model.uniqueId = nanoid(32);
|
||||
}
|
||||
|
||||
function handleUpdateModelWhenEdit() {
|
||||
if (props.operateType === 'add') {
|
||||
Object.assign(model, createDefaultModel());
|
||||
@ -93,6 +100,7 @@ async function handleSubmit() {
|
||||
window.$message?.success($t('common.updateSuccess'));
|
||||
}
|
||||
|
||||
await authStore.getUserInfo();
|
||||
closeDrawer();
|
||||
emit('submitted');
|
||||
}
|
||||
@ -109,11 +117,21 @@ watch(visible, () => {
|
||||
<OperateDrawer v-model="visible" :title="title" @submitted="handleSubmit">
|
||||
<NForm ref="formRef" :model="model" :rules="rules">
|
||||
<NFormItem :label="$t('page.namespace.uniqueId')" path="uniqueId">
|
||||
<NInput
|
||||
v-model:value="model.uniqueId"
|
||||
:disabled="props.operateType === 'edit'"
|
||||
:placeholder="$t('page.namespace.form.uniqueId')"
|
||||
/>
|
||||
<NInputGroup>
|
||||
<NInput
|
||||
v-model:value="model.uniqueId"
|
||||
:disabled="props.operateType === 'edit'"
|
||||
:placeholder="$t('page.namespace.form.uniqueId')"
|
||||
/>
|
||||
<NTooltip trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton type="default" ghost :disabled="props.operateType === 'edit'" @click="setUniqueId">
|
||||
<icon-ic-round-refresh class="text-icon" />
|
||||
</NButton>
|
||||
</template>
|
||||
{{ $t('common.generateRandomly') }}
|
||||
</NTooltip>
|
||||
</NInputGroup>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.namespace.name')" path="name">
|
||||
<NInput v-model:value="model.name" :placeholder="$t('page.namespace.form.name')" />
|
||||
|
@ -26,7 +26,7 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.namespace.keyword')" path="keyword" class="pr-24px">
|
||||
<NInput v-model:value="model.keyword" :placeholder="$t('page.namespace.form.keyword')" />
|
||||
<NInput v-model:value="model.keyword" :placeholder="$t('page.namespace.form.keyword')" clearable />
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
||||
|
@ -6,9 +6,9 @@ import { fetchBatchDeleteNotify, fetchGetNotifyConfigList, fetchUpdateNotifyStat
|
||||
import { $t } from '@/locales';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||
import NotifyConfigOperateDrawer from '@/views/notify/scene/modules/notify-config-operate-drawer.vue';
|
||||
import NotifyConfigSearch from '@/views/notify/scene/modules/notify-config-search.vue';
|
||||
import NotifyConfigDetailDrawer from '@/views/notify/scene/modules/notify-config-detail-drawer.vue';
|
||||
import NotifyConfigOperateDrawer from '@/views/notify/config/modules/notify-config-operate-drawer.vue';
|
||||
import NotifyConfigSearch from '@/views/notify/config/modules/notify-config-search.vue';
|
||||
import NotifyConfigDetailDrawer from '@/views/notify/config/modules/notify-config-detail-drawer.vue';
|
||||
import StatusSwitch from '@/components/common/status-switch.vue';
|
||||
import { jobNotifyScene, retryNotifyScene, systemTaskType, workflowNotifyScene } from '@/constants/business';
|
||||
import { tagColor } from '@/utils/common';
|
||||
@ -40,7 +40,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64
|
@ -115,12 +115,20 @@ function createDefaultModel(): Model {
|
||||
|
||||
type RuleKey = Extract<
|
||||
keyof Model,
|
||||
'groupName' | 'businessId' | 'recipientIds' | 'notifyStatus' | 'notifyScene' | 'rateLimiterStatus' | 'notifyThreshold'
|
||||
| 'groupName'
|
||||
| 'businessId'
|
||||
| 'systemTaskType'
|
||||
| 'recipientIds'
|
||||
| 'notifyStatus'
|
||||
| 'notifyScene'
|
||||
| 'rateLimiterStatus'
|
||||
| 'notifyThreshold'
|
||||
>;
|
||||
|
||||
const rules: Record<RuleKey, App.Global.FormRule> = {
|
||||
groupName: defaultRequiredRule,
|
||||
businessId: defaultRequiredRule,
|
||||
systemTaskType: defaultRequiredRule,
|
||||
notifyStatus: defaultRequiredRule,
|
||||
notifyScene: defaultRequiredRule,
|
||||
recipientIds: defaultRequiredRule,
|
||||
@ -277,7 +285,6 @@ watch(visible, () => {
|
||||
v-model:value="model.systemTaskType"
|
||||
:placeholder="$t('page.notifyConfig.form.systemTaskType')"
|
||||
:options="translateOptions(systemTaskTypeOptions)"
|
||||
clearable
|
||||
@update:value="systemTaskTypeChange"
|
||||
/>
|
||||
</NFormItem>
|
||||
@ -288,7 +295,6 @@ watch(visible, () => {
|
||||
:options="retryScenes"
|
||||
label-field="sceneName"
|
||||
value-field="sceneName"
|
||||
clearable
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem v-if="model.systemTaskType === 3" :label="$t('page.notifyConfig.job')" path="businessId">
|
||||
@ -298,7 +304,6 @@ watch(visible, () => {
|
||||
:options="jobs"
|
||||
label-field="jobName"
|
||||
value-field="id"
|
||||
clearable
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem v-if="model.systemTaskType === 4" :label="$t('page.notifyConfig.workflow')" path="businessId">
|
||||
@ -308,7 +313,6 @@ watch(visible, () => {
|
||||
:options="workflows"
|
||||
label-field="workflowName"
|
||||
value-field="id"
|
||||
clearable
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.notifyConfig.notifyScene')" path="notifyScene">
|
||||
@ -316,7 +320,6 @@ watch(visible, () => {
|
||||
v-model:value="model.notifyScene"
|
||||
:placeholder="$t('page.notifyConfig.form.notifyScene')"
|
||||
:options="notifySceneOptions"
|
||||
clearable
|
||||
@update:value="retrySceneChange"
|
||||
/>
|
||||
</NFormItem>
|
@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { $t } from '@/locales';
|
||||
import { translateOptions } from '@/utils/common';
|
||||
import { enableStatusNumberOptions } from '@/constants/business';
|
||||
|
||||
defineOptions({
|
||||
name: 'NotifyConfigSearch'
|
||||
@ -26,13 +28,18 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.notifyConfig.groupName')" path="groupName" class="pr-24px">
|
||||
<NSelect v-model:value="model.groupName" :placeholder="$t('page.notifyConfig.groupName')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.notifyConfig.notifyStatus')" path="notifyStatus" class="pr-24px">
|
||||
<NSelect v-model:value="model.notifyStatus" :placeholder="$t('page.notifyConfig.notifyStatus')" clearable />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.notifyConfig.notifyScene')" path="notifyScene" class="pr-24px">
|
||||
<NSelect v-model:value="model.notifyScene" :placeholder="$t('page.notifyConfig.notifyScene')" clearable />
|
||||
<SelectScene v-model:value="model.notifyScene" :group-name="model.groupName as string" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.notifyConfig.notifyStatus')" path="notifyStatus" class="pr-24px">
|
||||
<NSelect
|
||||
v-model:value="model.notifyStatus"
|
||||
:placeholder="$t('page.notifyConfig.notifyStatus')"
|
||||
:options="translateOptions(enableStatusNumberOptions)"
|
||||
clearable
|
||||
/>
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
@ -39,7 +39,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64
|
||||
|
@ -35,7 +35,11 @@ function search() {
|
||||
path="recipientName"
|
||||
class="pr-24px"
|
||||
>
|
||||
<NInput v-model:value="model.recipientName" :placeholder="$t('page.notifyRecipient.form.recipientName')" />
|
||||
<NInput
|
||||
v-model:value="model.recipientName"
|
||||
:placeholder="$t('page.notifyRecipient.form.recipientName')"
|
||||
clearable
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.notifyRecipient.notifyType')" path="notifyType" class="pr-24px">
|
||||
<NSelect
|
||||
|
@ -27,7 +27,7 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.pods.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" :placeholder="$t('page.pods.form.groupName')" />
|
||||
<SelectGroup v-model:value="model.groupName" :placeholder="$t('page.pods.form.groupName')" clearable />
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
||||
|
@ -13,7 +13,7 @@ import { $t } from '@/locales';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||
import { retryTaskTypeRecord } from '@/constants/business';
|
||||
import { tagColor } from '@/utils/common';
|
||||
import { monthRangeISO8601, tagColor } from '@/utils/common';
|
||||
import RetryDeadLetterSearch from './modules/dead-letter-search.vue';
|
||||
import RetryDeadLetterDetailDrawer from './modules/retry-letter-detail-drawer.vue';
|
||||
|
||||
@ -30,7 +30,8 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
page: 1,
|
||||
size: 10,
|
||||
groupName: null,
|
||||
sceneName: null
|
||||
sceneName: null,
|
||||
datetimeRange: monthRangeISO8601()
|
||||
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
|
||||
// the value can not be undefined, otherwise the property in Form will not be reactive
|
||||
},
|
||||
@ -41,7 +42,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { $t } from '@/locales';
|
||||
import SelectGroup from '@/components/common/select-group.vue';
|
||||
import SelectScene from '@/components/common/select-scene.vue';
|
||||
import DatetimeRange from '@/components/common/datetime-range.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'RetryDeadLetterSearch'
|
||||
@ -28,10 +29,18 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.sceneName')" path="sceneName" class="pr-24px">
|
||||
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" />
|
||||
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi
|
||||
span="24 s:24 m:15 l:12 xl:9"
|
||||
:label="$t('page.common.createTime')"
|
||||
path="datetimeRange"
|
||||
class="pr-24px"
|
||||
>
|
||||
<DatetimeRange v-model:value="model.datetimeRange!" />
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
||||
|
@ -7,7 +7,7 @@ import { $t } from '@/locales';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||
import { retryTaskStatusTypeRecord, retryTaskTypeRecord } from '@/constants/business';
|
||||
import { tagColor } from '@/utils/common';
|
||||
import { monthRangeISO8601, tagColor } from '@/utils/common';
|
||||
import RetryLogSearch from './modules/retry-log-search.vue';
|
||||
import RetryLogDetailDrawer from './modules/retry-log-detail-drawer.vue';
|
||||
|
||||
@ -17,6 +17,7 @@ const appStore = useAppStore();
|
||||
const detailData = ref<Api.RetryLog.RetryLog | null>();
|
||||
/** 详情页可见状态 */
|
||||
const { bool: detailVisible, setTrue: openDetail } = useBoolean(false);
|
||||
const retryStatus = history.state.retryStatus;
|
||||
|
||||
const { columns, columnChecks, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
|
||||
apiFn: fetchRetryLogPageList,
|
||||
@ -30,7 +31,11 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
sceneName: null,
|
||||
idempotentId: null,
|
||||
bizNo: null,
|
||||
retryStatus: null
|
||||
retryStatus: null,
|
||||
datetimeRange: monthRangeISO8601()
|
||||
},
|
||||
searchParams: {
|
||||
retryStatus
|
||||
},
|
||||
columns: () => [
|
||||
{
|
||||
@ -40,7 +45,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
disabled: row => row.retryStatus !== 1
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64
|
||||
@ -168,16 +173,6 @@ async function loadRetryInfo(row: Api.RetryLog.RetryLog) {
|
||||
const res = await fetchRetryLogById(row.id!);
|
||||
detailData.value = (res.data as Api.RetryLog.RetryLog) || null;
|
||||
}
|
||||
|
||||
function initParams() {
|
||||
const retryStatus = history.state.retryStatus;
|
||||
if (retryStatus) {
|
||||
searchParams.retryStatus = retryStatus;
|
||||
getData();
|
||||
}
|
||||
}
|
||||
|
||||
initParams();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -4,6 +4,7 @@ import { translateOptions } from '@/utils/common';
|
||||
import { retryTaskStatusTypeOptions } from '@/constants/business';
|
||||
import SelectGroup from '@/components/common/select-group.vue';
|
||||
import SelectScene from '@/components/common/select-scene.vue';
|
||||
import DatetimeRange from '@/components/common/datetime-range.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'RetryLogSearch'
|
||||
@ -30,19 +31,19 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.sceneName')" path="sceneName" class="pr-24px">
|
||||
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" />
|
||||
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.UniqueId')" path="UniqueId" class="pr-24px">
|
||||
<NInput v-model:value="model.uniqueId" :placeholder="$t('page.retryLog.form.UniqueId')" />
|
||||
<NInput v-model:value="model.uniqueId" :placeholder="$t('page.retryLog.form.UniqueId')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.idempotentId')" path="idempotentId" class="pr-24px">
|
||||
<NInput v-model:value="model.idempotentId" :placeholder="$t('page.retryLog.form.idempotentId')" />
|
||||
<NInput v-model:value="model.idempotentId" :placeholder="$t('page.retryLog.form.idempotentId')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.bizNo')" path="bizNo" class="pr-24px">
|
||||
<NInput v-model:value="model.bizNo" :placeholder="$t('page.retryLog.form.bizNo')" />
|
||||
<NInput v-model:value="model.bizNo" :placeholder="$t('page.retryLog.form.bizNo')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryLog.retryStatus')" path="taskBatchStatus" class="pr-24px">
|
||||
<NSelect
|
||||
@ -52,6 +53,14 @@ function search() {
|
||||
clearable
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi
|
||||
span="24 s:24 m:15 l:12 xl:9"
|
||||
:label="$t('page.common.createTime')"
|
||||
path="datetimeRange"
|
||||
class="pr-24px"
|
||||
>
|
||||
<DatetimeRange v-model:value="model.datetimeRange!" />
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
||||
|
||||
|
@ -39,6 +39,12 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
align: 'center',
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
key: 'sceneName',
|
||||
title: $t('page.retryScene.sceneName'),
|
||||
|
@ -29,10 +29,10 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryScene.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryScene.sceneName')" path="sceneName" class="pr-24px">
|
||||
<NInput v-model:value="model.sceneName" :placeholder="$t('page.retryScene.form.sceneName')" />
|
||||
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryScene.sceneStatus')" path="sceneStatus" class="pr-24px">
|
||||
<NSelect
|
||||
|
@ -45,6 +45,12 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
align: 'center',
|
||||
width: 48
|
||||
},
|
||||
{
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
key: 'uniqueId',
|
||||
title: $t('page.retryTask.uniqueId'),
|
||||
|
@ -30,25 +30,26 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.sceneName')" path="sceneName" class="pr-24px">
|
||||
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" />
|
||||
<SelectScene v-model:value="model.sceneName" :group-name="model.groupName as string" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.uniqueId')" path="uniqueId" class="pr-24px">
|
||||
<NInput v-model:value="model.uniqueId" :placeholder="$t('page.retryTask.form.uniqueId')" />
|
||||
<NInput v-model:value="model.uniqueId" :placeholder="$t('page.retryTask.form.uniqueId')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.idempotentId')" path="idempotentId" class="pr-24px">
|
||||
<NInput v-model:value="model.idempotentId" :placeholder="$t('page.retryTask.form.idempotentId')" />
|
||||
<NInput v-model:value="model.idempotentId" :placeholder="$t('page.retryTask.form.idempotentId')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.bizNo')" path="bizNo" class="pr-24px">
|
||||
<NInput v-model:value="model.bizNo" :placeholder="$t('page.retryTask.form.bizNo')" />
|
||||
<NInput v-model:value="model.bizNo" :placeholder="$t('page.retryTask.form.bizNo')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.retryTask.retryStatus')" path="retryStatus" class="pr-24px">
|
||||
<NSelect
|
||||
v-model:value="model.retryStatus"
|
||||
:placeholder="$t('page.retryTask.form.retryStatus')"
|
||||
:options="translateOptions(retryTaskStatusTypeOptions)"
|
||||
clearable
|
||||
/>
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
|
@ -57,6 +57,12 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'id',
|
||||
title: $t('common.index'),
|
||||
align: 'left',
|
||||
minWidth: 50
|
||||
},
|
||||
{
|
||||
key: 'username',
|
||||
title: $t('page.userManager.username'),
|
||||
@ -93,6 +99,12 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
return <NTag type={tagMap[row.role!]}>{label}</NTag>;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'createDt',
|
||||
title: $t('common.createDt'),
|
||||
align: 'left',
|
||||
minWidth: 50
|
||||
},
|
||||
{
|
||||
key: 'updateDt',
|
||||
title: $t('common.updateDt'),
|
||||
|
@ -26,7 +26,7 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.userManager.username')" path="username" class="pr-24px">
|
||||
<NInput v-model:value="model.username" :placeholder="$t('page.userManager.form.username')" />
|
||||
<NInput v-model:value="model.username" :placeholder="$t('page.userManager.form.username')" clearable />
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
||||
|
@ -1,20 +1,20 @@
|
||||
<script setup lang="tsx">
|
||||
import { NButton, NPopconfirm, NTag } from 'naive-ui';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { fetchGetWorkflowBatchList, fetchStopWorkflowBatch } from '@/service/api';
|
||||
import { $t } from '@/locales';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||
import { operationReasonRecord, taskBatchStatusRecord } from '@/constants/business';
|
||||
import { monthRangeISO8601 } from '@/utils/common';
|
||||
import WorkflowBatchSearch from './modules/workflow-batch-search.vue';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
// 此处可能有问题
|
||||
const workflowId =
|
||||
route.query?.workflowId === undefined ? null : Number.parseInt(route.query?.workflowId as string, 10);
|
||||
const router = useRouter();
|
||||
|
||||
const appStore = useAppStore();
|
||||
const workflowId = history.state.workflowId;
|
||||
const workflowName = history.state.workflowName;
|
||||
const taskBatchStatus = history.state.taskBatchStatus;
|
||||
|
||||
const { columns, columnChecks, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
|
||||
apiFn: fetchGetWorkflowBatchList,
|
||||
@ -23,9 +23,16 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
size: 10,
|
||||
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
|
||||
// the value can not be undefined, otherwise the property in Form will not be reactive
|
||||
workflowId,
|
||||
workflowId: null,
|
||||
workflowName: null,
|
||||
groupName: null,
|
||||
taskBatchStatus: null
|
||||
taskBatchStatus: null,
|
||||
datetimeRange: monthRangeISO8601()
|
||||
},
|
||||
searchParams: {
|
||||
workflowId,
|
||||
workflowName,
|
||||
taskBatchStatus
|
||||
},
|
||||
columns: () => [
|
||||
{
|
||||
@ -155,16 +162,6 @@ async function handleStop(id: string) {
|
||||
function detail(id: string) {
|
||||
router.push({ path: '/workflow/form/batch', query: { id } });
|
||||
}
|
||||
|
||||
function initParams() {
|
||||
const taskBatchStatus = history.state.taskBatchStatus;
|
||||
if (taskBatchStatus) {
|
||||
searchParams.taskBatchStatus = taskBatchStatus;
|
||||
getData();
|
||||
}
|
||||
}
|
||||
|
||||
initParams();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,8 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import type { SelectOption } from 'naive-ui';
|
||||
import { $t } from '@/locales';
|
||||
import SelectGroup from '@/components/common/select-group.vue';
|
||||
import TaskBatchStatus from '@/components/common/task-batch-status.vue';
|
||||
import DatetimeRange from '@/components/common/datetime-range.vue';
|
||||
|
||||
import { fetchGetWorkflowNameList } from '@/service/api';
|
||||
|
||||
@ -14,14 +16,17 @@ interface Emits {
|
||||
(e: 'reset'): void;
|
||||
(e: 'search'): void;
|
||||
}
|
||||
const noSearchFlag = ref(false);
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
/** 组列表 */
|
||||
/** 工作流列表 */
|
||||
const workflowList = ref<Api.Workflow.Workflow[]>([]);
|
||||
|
||||
const model = defineModel<Api.WorkflowBatch.WorkflowBatchSearchParams>('model', { required: true });
|
||||
const keywords = ref<string>(model.value.workflowName as any);
|
||||
|
||||
function reset() {
|
||||
keywords.value = '';
|
||||
emit('reset');
|
||||
}
|
||||
|
||||
@ -29,18 +34,42 @@ function search() {
|
||||
emit('search');
|
||||
}
|
||||
|
||||
async function groupNameUpdate(groupName: string) {
|
||||
const res = await fetchGetWorkflowNameList({ groupName });
|
||||
async function keywordsUpdate() {
|
||||
const res = await fetchGetWorkflowNameList({ keywords: keywords.value, groupName: model.value.groupName });
|
||||
workflowList.value = res.data as Api.Workflow.Workflow[];
|
||||
}
|
||||
|
||||
groupNameUpdate('');
|
||||
function handleSelect(value: number) {
|
||||
model.value.workflowId = value;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => keywords.value,
|
||||
(value: string) => {
|
||||
if (value.length !== 0) {
|
||||
keywordsUpdate();
|
||||
} else {
|
||||
noSearchFlag.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function translateOptions(options: Api.Workflow.Workflow[]) {
|
||||
return options.map(option => ({
|
||||
value: option.id,
|
||||
label: option.workflowName
|
||||
}));
|
||||
}
|
||||
|
||||
function renderLabel(option: SelectOption) {
|
||||
return [option.label as string, `(${option.value})`];
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<SearchForm btn-span="24 s:24 m:9 l:12 xl:15" :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflowBatch.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" @update:value="groupNameUpdate" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi
|
||||
span="24 s:12 m:6"
|
||||
@ -49,14 +78,15 @@ groupNameUpdate('');
|
||||
path="workflowName"
|
||||
class="pr-24px"
|
||||
>
|
||||
<NSelect
|
||||
v-model:value="model.workflowId"
|
||||
<NAutoComplete
|
||||
v-model:value="keywords"
|
||||
:placeholder="$t('page.workflowBatch.form.workflowName')"
|
||||
value-field="id"
|
||||
label-field="workflowName"
|
||||
:options="workflowList"
|
||||
:options="translateOptions(workflowList)"
|
||||
:empty-visible="noSearchFlag"
|
||||
clearable
|
||||
filterable
|
||||
:render-label="renderLabel"
|
||||
@select="handleSelect"
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi
|
||||
@ -65,7 +95,15 @@ groupNameUpdate('');
|
||||
path="taskBatchStatus"
|
||||
class="pr-24px"
|
||||
>
|
||||
<TaskBatchStatus v-model:value="model.taskBatchStatus" />
|
||||
<TaskBatchStatus v-model:value="model.taskBatchStatus" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi
|
||||
span="24 s:24 m:15 l:12 xl:9"
|
||||
:label="$t('page.common.createTime')"
|
||||
path="datetimeRange"
|
||||
class="pr-24px"
|
||||
>
|
||||
<DatetimeRange v-model:value="model.datetimeRange!" />
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
</template>
|
||||
|
@ -15,11 +15,13 @@ import StatusSwitch from '@/components/common/status-switch.vue';
|
||||
import { tagColor } from '@/utils/common';
|
||||
import { useAuth } from '@/hooks/business/auth';
|
||||
import { downloadFetch } from '@/utils/download';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import WorkflowSearch from './modules/workflow-search.vue';
|
||||
const { hasAuth } = useAuth();
|
||||
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const { routerPushByKey } = useRouterPush();
|
||||
|
||||
const { columns, columnChecks, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
|
||||
apiFn: fetchGetWorkflowPageList,
|
||||
@ -143,7 +145,7 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
|
||||
{
|
||||
label: $t('common.batchList'),
|
||||
key: 'batchList',
|
||||
click: () => batch(row.id!)
|
||||
click: () => goToBatch(row.id!)
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
@ -241,9 +243,9 @@ function copy(id: string) {
|
||||
router.push({ path: '/workflow/form/copy', query: { id } });
|
||||
}
|
||||
|
||||
function batch(id: string) {
|
||||
router.push({ path: '/workflow/batch', query: { workflowId: id } });
|
||||
}
|
||||
// function batch(id: string) {
|
||||
// router.push({ path: '/workflow/batch', state: { workflowId: id } });
|
||||
// }
|
||||
|
||||
async function execute(id: string) {
|
||||
const { error } = await fetchTriggerWorkflow(id);
|
||||
@ -265,6 +267,10 @@ function body(): Api.Workflow.ExportWorkflow {
|
||||
function handleExport() {
|
||||
downloadFetch('/workflow/export', body(), $t('page.workflow.title'));
|
||||
}
|
||||
function goToBatch(workflowId: string) {
|
||||
const findItem = data.value.find(item => item.id === workflowId)!;
|
||||
routerPushByKey('workflow_batch', { state: { workflowId, workflowName: findItem.workflowName } });
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -324,3 +330,5 @@ function handleExport() {
|
||||
</NCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -29,7 +29,7 @@ function search() {
|
||||
<template>
|
||||
<SearchForm :model="model" @search="search" @reset="reset">
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflow.groupName')" path="groupName" class="pr-24px">
|
||||
<SelectGroup v-model:value="model.groupName" />
|
||||
<SelectGroup v-model:value="model.groupName" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi
|
||||
span="24 s:12 m:6"
|
||||
@ -38,13 +38,14 @@ function search() {
|
||||
class="pr-24px"
|
||||
:label-width="100"
|
||||
>
|
||||
<NInput v-model:value="model.workflowName" :placeholder="$t('page.workflow.form.workflowName')" />
|
||||
<NInput v-model:value="model.workflowName" :placeholder="$t('page.workflow.form.workflowName')" clearable />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24 s:12 m:6" :label="$t('page.workflow.workflowStatus')" path="workflowStatus" class="pr-24px">
|
||||
<NSelect
|
||||
v-model:value="model.workflowStatus"
|
||||
:placeholder="$t('page.workflow.form.workflowStatus')"
|
||||
:options="translateOptions(enableStatusNumberOptions)"
|
||||
clearable
|
||||
/>
|
||||
</NFormItemGi>
|
||||
</SearchForm>
|
||||
|
Loading…
Reference in New Issue
Block a user