Browse Source

Merge pull request #655 from colinin/Switch-Ui-Setup-Syntax

feat: components switch to setup syntax
pull/712/head
yx lin 3 years ago
committed by GitHub
parent
commit
22fd445b6e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      apps/vue/src/api/auditing/auditLog.ts
  2. 8
      apps/vue/src/api/identity/securityLog.ts
  3. 58
      apps/vue/src/components/MultiTenancyBox/src/MultiTenancyBox.vue
  4. 119
      apps/vue/src/components/MultiTenancyBox/src/MultiTenancyModal.vue
  5. 180
      apps/vue/src/components/SettingManagement/src/SettingForm.vue
  6. 9
      apps/vue/src/utils/cache/persistent.ts
  7. 4
      apps/vue/src/utils/dateUtil.ts
  8. 194
      apps/vue/src/views/account/center/Cloud.vue
  9. 1
      apps/vue/src/views/account/center/FileList.vue
  10. 100
      apps/vue/src/views/account/center/index.vue
  11. 37
      apps/vue/src/views/account/setting/AccountBind.vue
  12. 171
      apps/vue/src/views/account/setting/BaseSetting.vue
  13. 75
      apps/vue/src/views/account/setting/MsgNotify.vue
  14. 122
      apps/vue/src/views/account/setting/SecureSetting.vue
  15. 63
      apps/vue/src/views/account/setting/index.vue
  16. 164
      apps/vue/src/views/auditing/components/AuditLogModal.vue
  17. 105
      apps/vue/src/views/auditing/components/AuditLogTable.vue
  18. 2
      apps/vue/src/views/caching-management/cache/datas/ModalData.ts
  19. 78
      apps/vue/src/views/feature/src/FeatureModal.vue
  20. 159
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceModal.vue
  21. 65
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceScope.vue
  22. 89
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceSecret.vue
  23. 122
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceTable.vue
  24. 4
      apps/vue/src/views/identity-server/api-resources/datas/TableData.ts
  25. 17
      apps/vue/src/views/identity-server/api-resources/hooks/useModal.ts
  26. 135
      apps/vue/src/views/identity-server/api-scopes/components/ApiScopeModal.vue
  27. 128
      apps/vue/src/views/identity-server/api-scopes/components/ApiScopeTable.vue
  28. 32
      apps/vue/src/views/identity-server/api-scopes/datas/TableData.ts
  29. 17
      apps/vue/src/views/identity-server/api-scopes/hooks/useModal.ts
  30. 81
      apps/vue/src/views/identity-server/clients/components/ClientApiResource.vue
  31. 79
      apps/vue/src/views/identity-server/clients/components/ClientCallback.vue
  32. 130
      apps/vue/src/views/identity-server/clients/components/ClientClaim.vue
  33. 278
      apps/vue/src/views/identity-server/clients/components/ClientClone.vue
  34. 77
      apps/vue/src/views/identity-server/clients/components/ClientCorsOrigins.vue
  35. 87
      apps/vue/src/views/identity-server/clients/components/ClientGrantType.vue
  36. 90
      apps/vue/src/views/identity-server/clients/components/ClientIdentityProvider.vue
  37. 83
      apps/vue/src/views/identity-server/clients/components/ClientIdentityResource.vue
  38. 79
      apps/vue/src/views/identity-server/clients/components/ClientLogoutRedirectUris.vue
  39. 203
      apps/vue/src/views/identity-server/clients/components/ClientModal.vue
  40. 113
      apps/vue/src/views/identity-server/clients/components/ClientProperties.vue
  41. 206
      apps/vue/src/views/identity-server/clients/components/ClientSecret.vue
  42. 155
      apps/vue/src/views/identity-server/clients/components/ClientTable.vue
  43. 181
      apps/vue/src/views/identity-server/clients/components/DynamicForm.vue
  44. 59
      apps/vue/src/views/identity-server/clients/components/Resources.vue
  45. 32
      apps/vue/src/views/identity-server/clients/hooks/useModal.ts
  46. 86
      apps/vue/src/views/identity-server/components/Properties.vue
  47. 87
      apps/vue/src/views/identity-server/components/UserClaim.vue
  48. 140
      apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceModal.vue
  49. 128
      apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceTable.vue
  50. 28
      apps/vue/src/views/identity-server/identity-resources/datas/TableData.ts
  51. 32
      apps/vue/src/views/identity-server/identity-resources/hooks/useModal.ts
  52. 20
      apps/vue/src/views/identity-server/persisted-grants/components/ModalData.ts
  53. 72
      apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantModal.vue
  54. 98
      apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantTable.vue
  55. 66
      apps/vue/src/views/identity/claim-types/components/ClaimModal.vue
  56. 48
      apps/vue/src/views/identity/claim-types/components/ClaimTable.vue
  57. 9
      apps/vue/src/views/identity/claim-types/hooks/useClaimTable.ts
  58. 2
      apps/vue/src/views/identity/components/ClaimModal.vue
  59. 209
      apps/vue/src/views/identity/components/MenuModal.vue
  60. 188
      apps/vue/src/views/identity/organization-units/components/MemberModal.vue
  61. 63
      apps/vue/src/views/identity/organization-units/components/MemberTable.vue
  62. 38
      apps/vue/src/views/identity/organization-units/components/OrganizationUnitPage.vue
  63. 47
      apps/vue/src/views/identity/organization-units/components/OrganizationUnitTree.vue
  64. 174
      apps/vue/src/views/identity/organization-units/components/RoleModal.vue
  65. 63
      apps/vue/src/views/identity/organization-units/components/RoleTable.vue
  66. 14
      apps/vue/src/views/identity/organization-units/hooks/useMemberTable.ts
  67. 6
      apps/vue/src/views/identity/organization-units/hooks/useOuTree.ts
  68. 12
      apps/vue/src/views/identity/organization-units/hooks/useRoleTable.ts
  69. 1
      apps/vue/src/views/identity/organization-units/index.vue
  70. 61
      apps/vue/src/views/identity/role/components/ClaimModal.vue
  71. 66
      apps/vue/src/views/identity/role/components/RoleModal.vue
  72. 115
      apps/vue/src/views/identity/role/components/RoleTable.vue
  73. 15
      apps/vue/src/views/identity/role/hooks/useClaim.ts
  74. 7
      apps/vue/src/views/identity/role/hooks/useRoleTable.ts
  75. 90
      apps/vue/src/views/identity/security-logs/components/SecurityLogTable.vue
  76. 45
      apps/vue/src/views/identity/user/components/LockModal.vue
  77. 75
      apps/vue/src/views/identity/user/components/PasswordModal.vue
  78. 91
      apps/vue/src/views/identity/user/components/UserModal.vue
  79. 141
      apps/vue/src/views/identity/user/components/UserTable.vue
  80. 14
      apps/vue/src/views/identity/user/hooks/useUserForm.ts
  81. 14
      apps/vue/src/views/identity/user/hooks/useUserTable.ts
  82. 97
      apps/vue/src/views/localization/languages/components/LanguageTable.vue
  83. 95
      apps/vue/src/views/localization/resources/components/ResourceTable.vue
  84. 261
      apps/vue/src/views/localization/texts/components/TextModal.vue
  85. 112
      apps/vue/src/views/localization/texts/components/TextTable.vue
  86. 156
      apps/vue/src/views/oss-management/containers/components/ContainerTable.vue
  87. 4
      apps/vue/src/views/oss-management/objects/components/FileList.vue
  88. 81
      apps/vue/src/views/oss-management/objects/components/OssFolderModal.vue
  89. 75
      apps/vue/src/views/oss-management/objects/components/OssManagePage.vue
  90. 47
      apps/vue/src/views/oss-management/objects/components/OssPreviewModal.vue
  91. 303
      apps/vue/src/views/oss-management/objects/components/OssUploadModal.vue
  92. 119
      apps/vue/src/views/platform/dataDic/components/DataItemModal.vue
  93. 176
      apps/vue/src/views/platform/dataDic/components/DataItemTable.vue
  94. 108
      apps/vue/src/views/platform/dataDic/components/DataModal.vue
  95. 162
      apps/vue/src/views/platform/dataDic/components/DataTree.vue
  96. 36
      apps/vue/src/views/platform/dataDic/index.vue
  97. 94
      apps/vue/src/views/platform/layout/components/LayoutModal.vue
  98. 105
      apps/vue/src/views/platform/layout/components/LayoutTable.vue
  99. 77
      apps/vue/src/views/platform/menu/components/MenuDrawer.vue
  100. 140
      apps/vue/src/views/platform/menu/components/MenuTable.vue

4
apps/vue/src/api/auditing/auditLog.ts

@ -12,9 +12,7 @@ export const deleteById = (id: string) => {
controller: Api.Controller, controller: Api.Controller,
action: 'DeleteAsync', action: 'DeleteAsync',
params: { params: {
input: { id: id,
id: id,
},
}, },
}); });
}; };

8
apps/vue/src/api/identity/securityLog.ts

@ -12,9 +12,7 @@ export const deleteById = (id: string) => {
controller: Api.Controller, controller: Api.Controller,
action: 'DeleteAsync', action: 'DeleteAsync',
params: { params: {
input: { id: id,
id: id,
},
}, },
}); });
}; };
@ -25,9 +23,7 @@ export const getById = (id: string) => {
controller: Api.Controller, controller: Api.Controller,
action: 'GetAsync', action: 'GetAsync',
params: { params: {
input: { id: id,
id: id,
},
}, },
}); });
}; };

58
apps/vue/src/components/MultiTenancyBox/src/MultiTenancyBox.vue

@ -16,50 +16,28 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent } from 'vue'; import { computed } from 'vue';
import { Button, Form, Input } from 'ant-design-vue'; import { Button, Input } from 'ant-design-vue';
import { Input as BInput } from '/@/components/Input'; import { useModal } from '/@/components/Modal';
import { BasicModal, useModal } from '/@/components/Modal';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useAbpStoreWithOut } from '/@/store/modules/abp'; import { useAbpStoreWithOut } from '/@/store/modules/abp';
import MultiTenancyModal from './MultiTenancyModal.vue'; import MultiTenancyModal from './MultiTenancyModal.vue';
export default defineComponent({ const InputSearch = Input.Search;
name: 'MultiTenancyBox',
components: {
BasicModal,
Button,
Form,
FormItem: Form.Item,
BInput,
InputSearch: Input.Search,
MultiTenancyModal,
},
setup() {
const { L } = useLocalization('AbpUiMultiTenancy');
const [registerModal, { openModal }] = useModal();
const multiTenancyEnabled = computed(() => {
const abpStore = useAbpStoreWithOut();
return abpStore.getApplication.multiTenancy.isEnabled;
});
const currentTenant = computed(() => {
const abpStore = useAbpStoreWithOut();
return abpStore.getApplication.currentTenant;
});
function handleSwitchTenant() {
openModal(true, currentTenant.value.name);
}
return { const { L } = useLocalization('AbpUiMultiTenancy');
L, const [registerModal, { openModal }] = useModal();
multiTenancyEnabled, const multiTenancyEnabled = computed(() => {
currentTenant, const abpStore = useAbpStoreWithOut();
registerModal, return abpStore.getApplication.multiTenancy.isEnabled;
handleSwitchTenant,
};
},
}); });
const currentTenant = computed(() => {
const abpStore = useAbpStoreWithOut();
return abpStore.getApplication.currentTenant;
});
function handleSwitchTenant() {
openModal(true, currentTenant.value.name);
}
</script> </script>

119
apps/vue/src/components/MultiTenancyBox/src/MultiTenancyModal.vue

@ -14,8 +14,8 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, nextTick } from 'vue'; import { nextTick, inject } from 'vue';
import { BasicForm, useForm } from '/@/components/Form'; import { BasicForm, useForm } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { findTenantByName } from '/@/api/multi-tenancy/tenants'; import { findTenantByName } from '/@/api/multi-tenancy/tenants';
@ -24,74 +24,57 @@
import { useAbpStoreWithOut } from '/@/store/modules/abp'; import { useAbpStoreWithOut } from '/@/store/modules/abp';
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
export default defineComponent({ const cookies = inject<any>('$cookies');
name: 'MultiTenancyModal', const globSetting = useGlobSetting();
components: { BasicForm, BasicModal }, const { L } = useLocalization('AbpUiMultiTenancy');
setup() { const { createMessage } = useMessage();
const globSetting = useGlobSetting(); const [registerForm, { validate, setFieldsValue }] = useForm({
const { L } = useLocalization('AbpUiMultiTenancy'); showActionButtonGroup: false,
const { createMessage } = useMessage(); layout: 'vertical',
const [registerForm, { validate, setFieldsValue }] = useForm({ schemas: [
showActionButtonGroup: false, {
layout: 'vertical', field: 'name',
schemas: [ label: L('SwitchTenantHint'),
{ component: 'Input',
field: 'name', colProps: { span: 24 },
label: L('SwitchTenantHint'), },
component: 'Input', ],
colProps: { span: 24 }, });
}, const [registerModal, { closeModal, changeLoading }] = useModalInner((name) => {
], nextTick(() => {
}); setFieldsValue({
const [registerModal, { closeModal, changeLoading }] = useModalInner((name) => { name: name,
nextTick(() => {
setFieldsValue({
name: name,
});
});
}); });
});
});
return { function switchToTenant() {
L, validate().then((input) => {
registerForm, changeLoading(true);
registerModal, const abpStore = useAbpStoreWithOut();
validate, if (!input.name) {
createMessage, cookies?.remove(globSetting.multiTenantKey);
closeModal, } else {
globSetting, findTenantByName(input.name).then((result) => {
changeLoading, if (!result.success || !result.tenantId) {
}; createMessage.warn(L('GivenTenantIsNotExist', [input.name]));
}, return;
methods: { }
switchToTenant() {
this.validate().then((input) => {
this.changeLoading(true);
const abpStore = useAbpStoreWithOut();
if (!input.name) {
this.$cookies.remove(this.globSetting.multiTenantKey);
} else {
findTenantByName(input.name).then((result) => {
if (!result.success || !result.tenantId) {
this.createMessage.warn(this.L('GivenTenantIsNotExist', [input.name]));
return;
}
if (!result.isActive) {
this.createMessage.warn(this.L('GivenTenantIsNotAvailable', [input.name]));
return;
}
this.$cookies.set(this.globSetting.multiTenantKey, result.tenantId); if (!result.isActive) {
}).finally(() => this.changeLoading(false)); createMessage.warn(L('GivenTenantIsNotAvailable', [input.name]));
return;
} }
//
setTimeout(() => { cookies?.set(globSetting.multiTenantKey, result.tenantId);
abpStore.initlizeAbpApplication() }).finally(() => changeLoading(false));
.then(this.closeModal) }
.finally(() => this.changeLoading(false)); //
}, 100); setTimeout(() => {
}); abpStore.initlizeAbpApplication()
}, .then(closeModal)
} .finally(() => changeLoading(false));
}) }, 100);
});
}
</script> </script>

180
apps/vue/src/components/SettingManagement/src/SettingForm.vue

@ -81,7 +81,7 @@
</TabPane> </TabPane>
</Tabs> </Tabs>
<FormItem style="margin-top: 20px"> <FormItem style="margin-top: 20px">
<a-button <Button
v-if="updateSetting.settings.length > 0" v-if="updateSetting.settings.length > 0"
type="primary" type="primary"
style="width: 150px" style="width: 150px"
@ -90,19 +90,20 @@
@click="handleSubmit" @click="handleSubmit"
> >
{{ sumbitButtonTitle }} {{ sumbitButtonTitle }}
</a-button> </Button>
</FormItem> </FormItem>
</Form> </Form>
</Card> </Card>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { computed, defineComponent, ref, toRaw } from 'vue'; import { computed, ref, toRaw } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { useTabsStyle } from '/@/hooks/component/useStyles'; import { useTabsStyle } from '/@/hooks/component/useStyles';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { import {
Button,
Card, Card,
Checkbox, Checkbox,
Tabs, Tabs,
@ -110,15 +111,20 @@
Form, Form,
Input, Input,
Select, Select,
Row,
Col,
DatePicker, DatePicker,
} from 'ant-design-vue'; } from 'ant-design-vue';
import { Input as BInput } from '/@/components/Input'; import { Input as BInput } from '/@/components/Input';
import { formatToDate } from '/@/utils/dateUtil'; import { formatToDate } from '/@/utils/dateUtil';
import { SettingGroup, SettingsUpdate } from '/@/api/settings/model/settingModel'; import { SettingGroup, SettingsUpdate } from '/@/api/settings/model/settingModel';
const props = { const CollapsePanel = Collapse.Panel;
const FormItem = Form.Item;
const SelectOption = Select.Option;
const TabPane = Tabs.TabPane;
const Password = Input.Password;
const emits = defineEmits(['change']);
const props = defineProps({
settingGroups: { settingGroups: {
type: Array as PropType<Array<SettingGroup>>, type: Array as PropType<Array<SettingGroup>>,
required: true, required: true,
@ -131,110 +137,72 @@
type: String as PropType<'left' | 'right' | 'top' | 'bottom'>, type: String as PropType<'left' | 'right' | 'top' | 'bottom'>,
default: 'top', default: 'top',
}, },
} as const; // props see: https://blog.csdn.net/q535999731/article/details/109578885 });
export default defineComponent({ const { L } = useLocalization('AbpSettingManagement');
components: { const activeTabKey = ref(0);
Card, const saving = ref(false);
Checkbox, const updateSetting = ref(new SettingsUpdate());
Collapse: Collapse, const { createMessage } = useMessage();
CollapsePanel: Collapse.Panel, const { success } = createMessage;
DatePicker,
Form: Form,
FormItem: Form.Item,
BInput,
Select,
SelectOption: Select.Option,
Tabs: Tabs,
TabPane: Tabs.TabPane,
Password: Input.Password,
Row,
Col,
},
props,
emits: ['change'],
setup(props, { emit }) {
const { L } = useLocalization('AbpSettingManagement');
const activeTabKey = ref(0);
const saving = ref(false);
const updateSetting = ref(new SettingsUpdate());
const { createMessage } = useMessage();
const { success } = createMessage;
const tabsStyle = useTabsStyle( const tabsStyle = useTabsStyle(
props.tabPosition, props.tabPosition,
{}, {},
{ {
top: props.tabPosition === 'top' ? '80px' : '0' top: props.tabPosition === 'top' ? '80px' : '0'
}); });
const sumbitButtonTitle = computed(() => { const sumbitButtonTitle = computed(() => {
if (saving.value) { if (saving.value) {
return L('Save'); return L('Save');
} }
return L('Save'); return L('Save');
}); });
const expandedCollapseKeys = computed(() => { const expandedCollapseKeys = computed(() => {
return (group) => { return (group) => {
const keys = group.settings.map((s) => { const keys = group.settings.map((s) => {
return s.displayName; return s.displayName;
});
return keys;
};
}); });
return keys;
};
});
function handleCheckChange(setting) { function handleCheckChange(setting) {
if (setting.value === 'true') { if (setting.value === 'true') {
setting.value = 'false'; setting.value = 'false';
} else { } else {
setting.value = 'true'; setting.value = 'true';
} }
handleValueChange(setting); handleValueChange(setting);
} }
function handleDateChange(e, setting) {
setting.value = dayjs.isDayjs(e) ? formatToDate(e) : '';
handleValueChange(setting);
}
function handleValueChange(setting) { function handleDateChange(e, setting) {
const index = updateSetting.value.settings.findIndex((s) => s.name === setting.name); setting.value = dayjs.isDayjs(e) ? formatToDate(e) : '';
if (index >= 0) { handleValueChange(setting);
updateSetting.value.settings[index].value = setting.value; }
} else {
updateSetting.value.settings.push({
name: setting.name,
value: setting.value,
});
}
}
function handleSubmit() { function handleValueChange(setting) {
saving.value = true; const index = updateSetting.value.settings.findIndex((s) => s.name === setting.name);
props if (index >= 0) {
.saveApi(toRaw(updateSetting.value)) updateSetting.value.settings[index].value = setting.value;
.then(() => { } else {
success(L('SuccessfullySaved')); updateSetting.value.settings.push({
emit('change', toRaw(updateSetting.value)); name: setting.name,
}) value: setting.value,
.finally(() => { });
saving.value = false; }
}); }
}
return { function handleSubmit() {
L, saving.value = true;
dayjs, props
saving, .saveApi(toRaw(updateSetting.value))
tabsStyle, .then(() => {
activeTabKey, success(L('SuccessfullySaved'));
updateSetting, emits('change', toRaw(updateSetting.value));
sumbitButtonTitle, })
expandedCollapseKeys, .finally(() => {
handleCheckChange, saving.value = false;
handleDateChange, });
handleValueChange, }
handleSubmit,
};
},
});
</script> </script>

9
apps/vue/src/utils/cache/persistent.ts

@ -6,7 +6,6 @@ import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
import { Memory } from './memory'; import { Memory } from './memory';
import { import {
TOKEN_KEY, TOKEN_KEY,
ABP_TENANT_KEY,
USER_INFO_KEY, USER_INFO_KEY,
ROLES_KEY, ROLES_KEY,
LOCK_INFO_KEY, LOCK_INFO_KEY,
@ -21,7 +20,6 @@ import { pick, omit } from 'lodash-es';
interface BasicStore { interface BasicStore {
[TOKEN_KEY]: string | number | null | undefined; [TOKEN_KEY]: string | number | null | undefined;
[ABP_TENANT_KEY]: string;
[USER_INFO_KEY]: UserInfo; [USER_INFO_KEY]: UserInfo;
[ROLES_KEY]: string[]; [ROLES_KEY]: string[];
[LOCK_INFO_KEY]: LockInfo; [LOCK_INFO_KEY]: LockInfo;
@ -51,13 +49,6 @@ function initPersistentMemory() {
} }
export class Persistent { export class Persistent {
static setTenant(value: any) {
ls.set(ABP_TENANT_KEY, value);
}
static getTenant() {
return ls.get(ABP_TENANT_KEY);
}
static getLocal<T>(key: LocalKeys) { static getLocal<T>(key: LocalKeys) {
return localMemory.get(key)?.value as Nullable<T>; return localMemory.get(key)?.value as Nullable<T>;

4
apps/vue/src/utils/dateUtil.ts

@ -7,14 +7,14 @@ const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
const DATE_FORMAT = 'YYYY-MM-DD'; const DATE_FORMAT = 'YYYY-MM-DD';
export function formatToDateTime( export function formatToDateTime(
date: string | dayjs.Dayjs | undefined = undefined, date: string | Date | dayjs.Dayjs | undefined = undefined,
format = DATE_TIME_FORMAT, format = DATE_TIME_FORMAT,
): string { ): string {
return dayjs(date).format(format); return dayjs(date).format(format);
} }
export function formatToDate( export function formatToDate(
date: string | dayjs.Dayjs | undefined = undefined, date: string | Date | dayjs.Dayjs | undefined = undefined,
format = DATE_FORMAT, format = DATE_FORMAT,
): string { ): string {
return dayjs(date).format(format); return dayjs(date).format(format);

194
apps/vue/src/views/account/center/Cloud.vue

@ -15,7 +15,7 @@
</CardGrid> </CardGrid>
<CardGrid style="width: 75%"> <CardGrid style="width: 75%">
<component <component
:is="switchComponent.name" :is="componentsRef[switchComponent.name]"
:select-group="switchComponent.group" :select-group="switchComponent.group"
:select-path="switchComponent.path" :select-path="switchComponent.path"
:delete-enabled="deleteEnabled" :delete-enabled="deleteEnabled"
@ -26,8 +26,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref } from 'vue'; import { computed, ref, shallowRef } from 'vue';
import { Card, Tree } from 'ant-design-vue'; import { Card, Tree } from 'ant-design-vue';
import { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; import { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
@ -36,6 +36,15 @@
import FileList from './FileList.vue'; import FileList from './FileList.vue';
import ShareList from './ShareList.vue'; import ShareList from './ShareList.vue';
const componentsRef = shallowRef({
'FileList': FileList,
'ShareList': ShareList,
});
const CardGrid = Card.Grid;
const CardMeta = Card.Meta;
const DirectoryTree = Tree.DirectoryTree;
interface IComponent { interface IComponent {
name: string; name: string;
group: string; group: string;
@ -43,111 +52,88 @@
dataRef: any; dataRef: any;
} }
export default defineComponent({ const { hasPermission } = usePermission();
components: { const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
Card, const folderTreeRef = ref<{ [key: string]: TreeDataItem }>({
CardGrid: Card.Grid, private: {
CardMeta: Card.Meta, key: 'private',
DirectoryTree: Tree.DirectoryTree, group: 'private',
FileList, title: L('MyDocument'),
ShareList, path: '/',
children: [],
}, },
setup() { public: {
const { hasPermission } = usePermission(); key: 'public',
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']); group: 'public',
const folderTreeRef = ref<{ [key: string]: TreeDataItem }>({ title: L('PublicDocument'),
private: { path: '/',
key: 'private', children: [],
group: 'private', },
title: L('MyDocument'), share: {
path: '/', key: 'share',
children: [], group: 'share',
}, title: L('MyShare'),
public: { path: '/',
key: 'public', children: [],
group: 'public', },
title: L('PublicDocument'), });
path: '/', const folderTree = computed(() => {
children: [], return Object.keys(folderTreeRef.value).map((key) => folderTreeRef.value[key]);
}, });
share: { const switchComponent = ref<IComponent>({
key: 'share', name: 'FileList',
group: 'share', group: '',
title: L('MyShare'), path: '/',
path: '/', dataRef: {},
children: [], });
}, const deleteEnabled = computed(() => {
}); switch (switchComponent.value.group) {
const folderTree = computed(() => { case 'private':
return Object.keys(folderTreeRef.value).map((key) => folderTreeRef.value[key]); case 'share':
}); return true;
const switchComponent = ref<IComponent>({ case 'public':
name: 'FileList', return hasPermission('AbpOssManagement.OssObject.Delete');
group: '', default:
path: '/', return false;
dataRef: {}, }
}); });
const deleteEnabled = computed(() => { const expandedKeys = ref<string[]>([]);
switch (switchComponent.value.group) {
case 'private':
case 'share':
return true;
case 'public':
return hasPermission('AbpOssManagement.OssObject.Delete');
default:
return false;
}
});
const expandedKeys = ref<string[]>([]);
function fetchFolders(keys) {
expandedKeys.value = keys;
}
function handleSelectFolder(_, e) { function fetchFolders(keys) {
switch (e.node.dataRef.group) { expandedKeys.value = keys;
case 'private': }
case 'public':
switchComponent.value = {
name: 'FileList',
group: e.node.dataRef.group,
path: e.node.dataRef.path,
dataRef: e.node.dataRef,
};
break;
case 'share':
switchComponent.value = {
name: 'ShareList',
group: e.node.dataRef.group,
path: e.node.dataRef.path,
dataRef: e.node.dataRef,
};
break;
}
}
function handleAppendFolder(folders: OssObject[]) { function handleSelectFolder(_, e) {
switchComponent.value.dataRef.children = folders.map((obj) => { switch (e.node.dataRef.group) {
return { case 'private':
key: obj.name, case 'public':
group: switchComponent.value.group, switchComponent.value = {
title: obj.name, name: 'FileList',
path: obj.name, group: e.node.dataRef.group,
children: [], path: e.node.dataRef.path,
}; dataRef: e.node.dataRef,
}); };
} break;
case 'share':
switchComponent.value = {
name: 'ShareList',
group: e.node.dataRef.group,
path: e.node.dataRef.path,
dataRef: e.node.dataRef,
};
break;
}
}
function handleAppendFolder(folders: OssObject[]) {
switchComponent.value.dataRef.children = folders.map((obj) => {
return { return {
L, key: obj.name,
switchComponent, group: switchComponent.value.group,
folderTree, title: obj.name,
deleteEnabled, path: obj.name,
expandedKeys, children: [],
fetchFolders,
handleSelectFolder,
handleAppendFolder,
}; };
}, });
}); }
</script> </script>

1
apps/vue/src/views/account/center/FileList.vue

@ -155,6 +155,7 @@
path: record.path, path: record.path,
object: record.name, object: record.name,
}).then(() => { }).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
deleteTableDataRecord(record.name); deleteTableDataRecord(record.name);
props.selectGroup === 'private' && emit('delete:file:private', record); props.selectGroup === 'private' && emit('delete:file:private', record);
props.selectGroup === 'public' && emit('delete:file:public', record); props.selectGroup === 'public' && emit('delete:file:public', record);

100
apps/vue/src/views/account/center/index.vue

@ -1,18 +1,18 @@
<template> <template>
<div :class="prefixCls"> <div :class="prefixCls">
<a-row :class="`${prefixCls}-top`"> <Row :class="`${prefixCls}-top`">
<a-col :span="9" :class="`${prefixCls}-col`"> <Col :span="9" :class="`${prefixCls}-col`">
<a-row> <Row>
<a-col :span="8"> <Col :span="8">
<div :class="`${prefixCls}-top__avatar`"> <div :class="`${prefixCls}-top__avatar`">
<img width="70" :src="userInfo.avatar ?? headerImg" /> <img width="70" :src="userInfo.avatar ?? headerImg" />
<span>{{ userInfo.realName ?? userInfo.username }}</span> <span>{{ userInfo.realName ?? userInfo.username }}</span>
<div>{{ userInfo.description }}</div> <div>{{ userInfo.description }}</div>
</div> </div>
</a-col> </Col>
</a-row> </Row>
</a-col> </Col>
</a-row> </Row>
<div :class="`${prefixCls}-bottom`"> <div :class="`${prefixCls}-bottom`">
<Tabs <Tabs
v-model:activeKey="activeTabKey" v-model:activeKey="activeTabKey"
@ -21,7 +21,7 @@
> >
<template v-for="item in components" :key="item.key"> <template v-for="item in components" :key="item.key">
<TabPane :tab="item.name"> <TabPane :tab="item.name">
<component :is="item.component" /> <component :is="componentsRef[item.component]" />
</TabPane> </TabPane>
</template> </template>
</Tabs> </Tabs>
@ -29,63 +29,47 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { Tag, Tabs, Row, Col } from 'ant-design-vue'; import { Tabs, Row, Col } from 'ant-design-vue';
import { defineComponent, computed, ref } from 'vue'; import { computed, ref, shallowRef } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import Icon from '/@/components/Icon/index';
import headerImg from '/@/assets/images/header.jpg'; import headerImg from '/@/assets/images/header.jpg';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useTabsStyle } from '/@/hooks/component/useStyles'; import { useTabsStyle } from '/@/hooks/component/useStyles';
import Cloud from './Cloud.vue'; import Cloud from './Cloud.vue';
import Setting from './Setting.vue'; import Setting from './Setting.vue';
export default defineComponent({
components: { const TabPane = Tabs.TabPane;
Cloud,
CollapseContainer, const componentsRef = shallowRef({
Icon, 'Cloud': Cloud,
Tag, 'Setting': Setting,
Tabs, });
TabPane: Tabs.TabPane,
Setting, const prefixCls = 'account-center';
[Row.name]: Row, const userStore = useUserStore();
[Col.name]: Col, const activeTabKey = ref('Cloud');
const { L } = useLocalization(['AbpOssManagement', 'AbpSettingManagement']);
const components = [
{
key: 'Cloud',
name: L('MyCloud'),
component: 'Cloud',
}, },
setup() { {
const userStore = useUserStore(); key: 'Setting',
const activeTabKey = ref('cloud'); name: L('DisplayName:UserSetting'),
const { L } = useLocalization(['AbpOssManagement', 'AbpSettingManagement']); component: 'Setting',
const components = [
{
key: 'cloud',
name: L('MyCloud'),
component: 'cloud',
},
{
key: 'setting',
name: L('DisplayName:UserSetting'),
component: 'setting',
},
];
const tabsStyle = useTabsStyle(
'top',
{},
{
top: '80px',
}
);
const userInfo = computed(() => userStore.getUserInfo);
return {
activeTabKey,
tabsStyle,
prefixCls: 'account-center',
userInfo,
headerImg,
components,
};
}, },
}); ];
const tabsStyle = useTabsStyle(
'top',
{},
{
top: '80px',
}
);
const userInfo = computed(() => userStore.getUserInfo);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.account-center { .account-center {

37
apps/vue/src/views/account/setting/AccountBind.vue

@ -1,7 +1,7 @@
<template> <template>
<CollapseContainer :title="L('Binding')" :canExpan="false"> <CollapseContainer :title="L('Binding')" :canExpan="false">
<List> <List>
<template v-for="item in list" :key="item.key"> <template v-for="item in getAccountBindList()" :key="item.key">
<ListItem> <ListItem>
<ListItemMeta> <ListItemMeta>
<template #avatar> <template #avatar>
@ -25,38 +25,25 @@
</List> </List>
</CollapseContainer> </CollapseContainer>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { List, Tag } from 'ant-design-vue'; import { List, Tag } from 'ant-design-vue';
import { defineComponent } from 'vue';
import { CollapseContainer } from '/@/components/Container/index'; import { CollapseContainer } from '/@/components/Container/index';
import { useProfile } from './useProfile'; import { useProfile } from './useProfile';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { MyProfile } from '/@/api/account/model/profilesModel'; import { MyProfile } from '/@/api/account/model/profilesModel';
import Icon from '/@/components/Icon/index'; import Icon from '/@/components/Icon/index';
export default defineComponent({ const ListItem = List.Item;
components: { const ListItemMeta = List.Item.Meta;
CollapseContainer,
List, const props = defineProps({
ListItem: List.Item, profile: {
ListItemMeta: List.Item.Meta, type: Object as PropType<MyProfile>,
Icon, }
Tag,
},
props: {
profile: {
type: Object as PropType<MyProfile>,
}
},
setup(props) {
const { L } = useLocalization('AbpAccount');
const { getAccountBindList } = useProfile({ profile: props.profile });
return {
L,
list: getAccountBindList(),
};
},
}); });
const { L } = useLocalization('AbpAccount');
const { getAccountBindList } = useProfile({ profile: props.profile });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.avatar { .avatar {

171
apps/vue/src/views/account/setting/BaseSetting.vue

@ -1,10 +1,10 @@
<template> <template>
<CollapseContainer :title="L('BasicSettings')" :canExpan="false"> <CollapseContainer :title="L('BasicSettings')" :canExpan="false">
<a-row :gutter="24"> <Row :gutter="24">
<a-col :span="14"> <Col :span="14">
<BasicForm @register="register" /> <BasicForm @register="register" />
</a-col> </Col>
<a-col :span="10"> <Col :span="10">
<div class="change-avatar"> <div class="change-avatar">
<div class="mb-2">{{ L('Avatar') }}</div> <div class="mb-2">{{ L('Avatar') }}</div>
<CropperAvatar <CropperAvatar
@ -16,8 +16,8 @@
@change="updateAvatar" @change="updateAvatar"
/> />
</div> </div>
</a-col> </Col>
</a-row> </Row>
<Button <Button
type="primary" type="primary"
:loading="confirmButton.loading" :loading="confirmButton.loading"
@ -27,117 +27,96 @@
> >
</CollapseContainer> </CollapseContainer>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { Button, Row, Col } from 'ant-design-vue'; import { Button, Row, Col } from 'ant-design-vue';
import { computed, defineComponent, reactive, watch } from 'vue'; import { computed, reactive, watch } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index'; import { BasicForm, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container'; import { CollapseContainer } from '/@/components/Container';
import { CropperAvatar } from '/@/components/Cropper'; import { CropperAvatar } from '/@/components/Cropper';
import { useMessage } from '/@/hooks/web/useMessage';
import headerImg from '/@/assets/icons/64x64/color-user.png'; import headerImg from '/@/assets/icons/64x64/color-user.png';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
import { upload } from '/@/api/oss-management/private'; import { upload } from '/@/api/oss-management/private';
import { changeAvatar } from '/@/api/account/claims'; import { changeAvatar } from '/@/api/account/claims';
import { update as updateProfile } from '/@/api/account/profiles'; import { update as updateProfile } from '/@/api/account/profiles';
import { MyProfile, UpdateMyProfile } from '/@/api/account/model/profilesModel'; import { MyProfile, UpdateMyProfile } from '/@/api/account/model/profilesModel';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useProfile } from './useProfile'; import { useProfile } from './useProfile';
export default defineComponent({ const emits = defineEmits(['profile-change']);
components: { const props = defineProps({
BasicForm, profile: {
CollapseContainer, type: Object as PropType<MyProfile>,
Button, }
ARow: Row, });
ACol: Col,
CropperAvatar, const { getBaseSetschemas } = useProfile({ profile: props.profile });
}, const userStore = useUserStore();
emits: ['profile-change'], const { createMessage } = useMessage();
props: { const { L } = useLocalization('AbpAccount');
profile: { const [register, { getFieldsValue, setFieldsValue, validate }] = useForm({
type: Object as PropType<MyProfile>, labelWidth: 120,
schemas: getBaseSetschemas(),
showActionButtonGroup: false,
});
const confirmButton = reactive({
title: L('Submit'),
loading: false,
});
const avatar = computed(() => {
const { avatar } = userStore.getUserInfo;
return avatar ?? headerImg;
});
watch(
() => props.profile,
(profile) => {
if (profile) {
setFieldsValue(profile);
} }
}, },
setup(props, { emit }) { {
const { createMessage } = useMessage(); immediate: true,
const { getBaseSetschemas } = useProfile({ profile: props.profile }); },
const userStore = useUserStore(); )
const { L } = useLocalization('AbpAccount');
const [register, { getFieldsValue, setFieldsValue, validate }] = useForm({
labelWidth: 120,
schemas: getBaseSetschemas(),
showActionButtonGroup: false,
});
const confirmButton = reactive({
title: L('Submit'),
loading: false,
});
const avatar = computed(() => {
const { avatar } = userStore.getUserInfo;
return avatar ?? headerImg;
});
watch(
() => props.profile,
(profile) => {
if (profile) {
setFieldsValue(profile);
}
},
{
immediate: true,
},
)
function handleUploadAvatar(params: { file: Blob; name: string; filename: string }) { function handleUploadAvatar(params: { file: Blob; name: string; filename: string }) {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
upload(params.file, 'avatar', params.filename) upload(params.file, 'avatar', params.filename)
.then((res) => { .then((res) => {
const path = encodeURIComponent(res.data.path.substring(0, res.data.path.length - 1)); const path = encodeURIComponent(res.data.path.substring(0, res.data.path.length - 1));
changeAvatar({ avatarUrl: `${path}/${res.data.name}` }) changeAvatar({ avatarUrl: `${path}/${res.data.name}` })
.then(() => { .then(() => {
emit('profile-change'); createMessage.success(L('Successful'));
resolve({} as unknown as void); emits('profile-change');
}) resolve({} as unknown as void);
.catch((err) => reject(err));
}) })
.catch((err) => reject(err)); .catch((err) => reject(err));
}); })
} .catch((err) => reject(err));
});
}
function updateAvatar(src: string) { function updateAvatar(src: string) {
const userinfo = userStore.getUserInfo; const userinfo = userStore.getUserInfo;
userinfo.avatar = src; userinfo.avatar = src;
userStore.setUserInfo(userinfo); userStore.setUserInfo(userinfo);
} }
function handleSubmit() { function handleSubmit() {
validate().then(() => { validate().then(() => {
confirmButton.loading = true; confirmButton.loading = true;
confirmButton.title = L('SavingWithThreeDot'); confirmButton.title = L('SavingWithThreeDot');
updateProfile(getFieldsValue() as UpdateMyProfile) updateProfile(getFieldsValue() as UpdateMyProfile)
.then(() => { .then(() => {
createMessage.success(L('PersonalSettingsSaved')); createMessage.success(L('PersonalSettingsSaved'));
emit('profile-change'); emits('profile-change');
}) }).finally(() => {
.finally(() => { confirmButton.loading = false;
confirmButton.loading = false; confirmButton.title = L('Submit');
confirmButton.title = L('Submit');
});
}); });
} });
}
return {
L,
avatar,
register,
updateAvatar,
confirmButton,
handleUploadAvatar,
handleSubmit,
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

75
apps/vue/src/views/account/setting/MsgNotify.vue

@ -30,56 +30,47 @@
</template> </template>
</Collapse> </Collapse>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { Card, List, Switch, Collapse } from 'ant-design-vue'; import { Card, List, Switch, Collapse } from 'ant-design-vue';
import { defineComponent, ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { ListItem, useProfile } from './useProfile'; import { ListItem as ProfileItem, useProfile } from './useProfile';
import { subscribe, unSubscribe } from '/@/api/messages/subscribes'; import { subscribe, unSubscribe } from '/@/api/messages/subscribes';
import { MyProfile } from '/@/api/account/model/profilesModel'; import { MyProfile } from '/@/api/account/model/profilesModel';
export default defineComponent({
components: {
Card,
Collapse,
CollapsePanel: Collapse.Panel,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Switch,
},
props: {
profile: {
type: Object as PropType<MyProfile>,
}
},
setup(props) {
const { L } = useLocalization('AbpAccount');
const notifyGroup = ref<{[key: string]: ListItem[]}>({});
const { getMsgNotifyList } = useProfile({ profile: props.profile });
function _fetchNotifies() { const CollapsePanel = Collapse.Panel;
getMsgNotifyList().then((res) => { const ListItem = List.Item;
notifyGroup.value = res; const ListItemMeta = List.Item.Meta;
});
}
onMounted(_fetchNotifies); const props = defineProps({
profile: {
type: Object as PropType<MyProfile>,
}
});
function handleChange(item: ListItem, checked) { const { createMessage } = useMessage();
item.loading = true; const { L } = useLocalization('AbpAccount');
const api = checked ? subscribe(item.key) : unSubscribe(item.key); const notifyGroup = ref<{[key: string]: ProfileItem[]}>({});
api.finally(() => { const { getMsgNotifyList } = useProfile({ profile: props.profile });
item.loading = false;
});
}
return { function _fetchNotifies() {
L, getMsgNotifyList().then((res) => {
notifyGroup, notifyGroup.value = res;
handleChange, });
}; }
},
}); onMounted(_fetchNotifies);
function handleChange(item: ProfileItem, checked) {
item.loading = true;
const api = checked ? subscribe(item.key) : unSubscribe(item.key);
api.then(() => {
createMessage.success(L('Successful'));
}).finally(() => {
item.loading = false;
});
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.extra { .extra {

122
apps/vue/src/views/account/setting/SecureSetting.vue

@ -33,10 +33,10 @@
<SettingFormModal @register="registerModal" /> <SettingFormModal @register="registerModal" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { ListItem } from './useProfile'; import type { ListItem as ProfileItem } from './useProfile';
import { Button, List, Switch, Tag } from 'ant-design-vue'; import { Button, List, Switch, Tag } from 'ant-design-vue';
import { defineComponent, ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { CollapseContainer } from '/@/components/Container'; import { CollapseContainer } from '/@/components/Container';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import { useProfile } from './useProfile'; import { useProfile } from './useProfile';
@ -46,77 +46,59 @@
import { MyProfile } from '/@/api/account/model/profilesModel'; import { MyProfile } from '/@/api/account/model/profilesModel';
import SettingFormModal from './SettingFormModal.vue'; import SettingFormModal from './SettingFormModal.vue';
export default defineComponent({ const ListItem = List.Item;
components: { const ListItemMeta = List.Item.Meta;
Button,
CollapseContainer,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Switch,
Tag,
SettingFormModal,
},
props: {
profile: {
type: Object as PropType<MyProfile>,
}
},
setup(props) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpAccount');
const { getSecureSettingList } = useProfile({ profile: props.profile });
const secureSettingList = ref<ListItem[]>([]);
const [registerModal, { openModal }] = useModal();
onMounted(() => { const props = defineProps({
getSecureSettingList().then((res) => { profile: {
secureSettingList.value = res; type: Object as PropType<MyProfile>,
}); }
}); });
function toggleCommand(item: ListItem) {
item.loading = true;
switch (item.key) {
case 'password':
case 'phoneNumber':
openModal(true, item);
item.loading = false;
break;
case 'email':
sendEmailConfirmLink({
email: item.description,
appName: 'STS',
returnUrl: window.location.href,
}).finally(() => {
item.loading = false;
});
break;
}
}
function handleChange(item: ListItem, checked) { const { createMessage } = useMessage();
item.loading = true; const { L } = useLocalization('AbpAccount');
switch (item.key) { const { getSecureSettingList } = useProfile({ profile: props.profile });
case 'twofactor': const secureSettingList = ref<ProfileItem[]>([]);
changeTwoFactorEnabled(checked).then(() => { const [registerModal, { openModal }] = useModal();
createMessage.success(L('Successful'));
}).finally(() => {
item.loading = false;
});
break;
}
}
return { onMounted(() => {
L, getSecureSettingList().then((res) => {
secureSettingList, secureSettingList.value = res;
handleChange, });
toggleCommand,
registerModal,
};
},
}); });
function toggleCommand(item: ProfileItem) {
item.loading = true;
switch (item.key) {
case 'password':
case 'phoneNumber':
openModal(true, item);
item.loading = false;
break;
case 'email':
sendEmailConfirmLink({
email: item.description,
appName: 'STS',
returnUrl: window.location.href,
}).finally(() => {
item.loading = false;
});
break;
}
}
function handleChange(item: ProfileItem, checked) {
item.loading = true;
switch (item.key) {
case 'twofactor':
changeTwoFactorEnabled(checked).then(() => {
createMessage.success(L('Successful'));
}).finally(() => {
item.loading = false;
});
break;
}
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.extra { .extra {

63
apps/vue/src/views/account/setting/index.vue

@ -1,10 +1,10 @@
<template> <template>
<ScrollContainer> <ScrollContainer>
<div ref="wrapperRef" :class="prefixCls"> <div ref="wrapperRef" class="account-setting">
<Tabs tab-position="left" :tabBarStyle="tabBarStyle"> <Tabs tab-position="left" :tabBarStyle="{ width: '220px' }">
<template v-for="item in getSettingList()" :key="item.key"> <template v-for="item in getSettingList()" :key="item.key">
<TabPane :tab="item.name"> <TabPane :tab="item.name">
<component :is="item.component" :profile="profileRef" @profile-change="initUserInfo" /> <component :is="componentsRef[item.component]" :profile="profileRef" @profile-change="initUserInfo" />
</TabPane> </TabPane>
</template> </template>
</Tabs> </Tabs>
@ -12,8 +12,8 @@
</ScrollContainer> </ScrollContainer>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, onMounted } from 'vue'; import { ref, shallowRef, onMounted } from 'vue';
import { Tabs } from 'ant-design-vue'; import { Tabs } from 'ant-design-vue';
import { ScrollContainer } from '/@/components/Container/index'; import { ScrollContainer } from '/@/components/Container/index';
import { getSettingList } from './data'; import { getSettingList } from './data';
@ -24,42 +24,29 @@
import SecureSetting from './SecureSetting.vue'; import SecureSetting from './SecureSetting.vue';
import AccountBind from './AccountBind.vue'; import AccountBind from './AccountBind.vue';
import MsgNotify from './MsgNotify.vue'; import MsgNotify from './MsgNotify.vue';
export default defineComponent({
components: {
ScrollContainer,
Tabs,
TabPane: Tabs.TabPane,
BaseSetting,
SecureSetting,
AccountBind,
MsgNotify,
},
setup() {
const profileRef = ref<MyProfile>();
onMounted(fetchProfile);
async function fetchProfile() { const TabPane = Tabs.TabPane;
const profile = await getProfile();
profileRef.value = profile;
}
async function initUserInfo() { const componentsRef = shallowRef({
const abpStore = useAbpStoreWithOut(); 'BaseSetting': BaseSetting,
await abpStore.initlizeAbpApplication(); 'SecureSetting': SecureSetting,
await fetchProfile(); 'AccountBind': AccountBind,
} 'MsgNotify': MsgNotify,
return {
prefixCls: 'account-setting',
profileRef,
initUserInfo,
getSettingList,
tabBarStyle: {
width: '220px',
},
};
},
}); });
const profileRef = ref<MyProfile>();
onMounted(fetchProfile);
async function fetchProfile() {
const profile = await getProfile();
profileRef.value = profile;
}
async function initUserInfo() {
const abpStore = useAbpStoreWithOut();
await abpStore.initlizeAbpApplication();
await fetchProfile();
}
</script> </script>
<style lang="less"> <style lang="less">
.account-setting { .account-setting {

164
apps/vue/src/views/auditing/components/AuditLogModal.vue

@ -1,6 +1,7 @@
<template> <template>
<BasicModal @register="registerModal" :width="800" :height="400" :title="L('AuditLog')"> <BasicModal @register="registerModal" :width="800" :height="400" :title="L('AuditLog')">
<Form <Form
ref="formElRef"
:colon="false" :colon="false"
:labelCol="{ span: 6 }" :labelCol="{ span: 6 }"
:wrapperCol="{ span: 18 }" :wrapperCol="{ span: 18 }"
@ -145,8 +146,8 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, watch, unref } from 'vue'; import { computed, nextTick, ref, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useTabsStyle } from '/@/hooks/component/useStyles'; import { useTabsStyle } from '/@/hooks/component/useStyles';
import { Collapse, Form, Tabs, Tag } from 'ant-design-vue'; import { Collapse, Form, Tabs, Tag } from 'ant-design-vue';
@ -158,101 +159,74 @@
import { AuditLog } from '/@/api/auditing/model/auditLogModel'; import { AuditLog } from '/@/api/auditing/model/auditLogModel';
import { formatToDateTime } from '/@/utils/dateUtil'; import { formatToDateTime } from '/@/utils/dateUtil';
import { tryToJson } from '/@/utils/strings'; import { tryToJson } from '/@/utils/strings';
export default defineComponent({
name: 'AuditLogModal',
components: {
BasicModal,
BasicTable,
CodeEditor,
Collapse,
CollapsePanel: Collapse.Panel,
Form,
FormItem: Form.Item,
Tag,
Tabs,
TabPane: Tabs.TabPane,
},
setup() {
const { L } = useLocalization('AbpAuditLogging');
const activeKey = ref('basic');
const auditLogIdRef = ref('');
const tabsStyle = useTabsStyle();
const modelRef = ref<AuditLog>({} as AuditLog);
const [registerModal] = useModalInner((model) => {
auditLogIdRef.value = model.id;
activeKey.value = 'basic';
});
const columns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('PropertyName'),
dataIndex: 'propertyName',
align: 'left',
width: 120,
sorter: true,
},
{
title: L('NewValue'),
dataIndex: 'newValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('OriginalValue'),
dataIndex: 'originalValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('PropertyTypeFullName'),
dataIndex: 'propertyTypeFullName',
align: 'left',
width: 300,
sorter: true,
},
];
const { entityChangeTypeColor, entityChangeType, httpMethodColor, httpStatusCodeColor } =
useAuditLog();
const formatJsonVal = computed(() => {
return (jsonString: string) => tryToJson(jsonString);
});
const formatDateVal = computed(() => {
return (dateVal) => formatToDateTime(dateVal, 'YYYY-MM-DD HH:mm:ss');
});
watch( const CollapsePanel = Collapse.Panel;
() => unref(auditLogIdRef), const FormItem = Form.Item;
(id) => { const TabPane = Tabs.TabPane;
if (id) {
getById(id).then((res) => {
modelRef.value = res;
});
}
},
);
return { const { L } = useLocalization('AbpAuditLogging');
L, const formElRef = ref<any>();
MODE, const activeKey = ref('basic');
columns, const tabsStyle = useTabsStyle();
modelRef, const modelRef = ref<AuditLog>({} as AuditLog);
activeKey, const [registerModal] = useModalInner((model) => {
tabsStyle, activeKey.value = 'basic';
entityChangeType, nextTick(() => {
entityChangeTypeColor, fetchAuditLog(model.id);
httpMethodColor, });
httpStatusCodeColor, });
registerModal, const columns: BasicColumn[] = [
formatJsonVal, {
formatDateVal, title: 'id',
}; dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('PropertyName'),
dataIndex: 'propertyName',
align: 'left',
width: 120,
sorter: true,
}, },
{
title: L('NewValue'),
dataIndex: 'newValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('OriginalValue'),
dataIndex: 'originalValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('PropertyTypeFullName'),
dataIndex: 'propertyTypeFullName',
align: 'left',
width: 300,
sorter: true,
},
];
const { entityChangeTypeColor, entityChangeType, httpMethodColor, httpStatusCodeColor } =
useAuditLog();
const formatJsonVal = computed(() => {
return (jsonString: string) => tryToJson(jsonString);
}); });
const formatDateVal = computed(() => {
return (dateVal) => formatToDateTime(dateVal, 'YYYY-MM-DD HH:mm:ss');
});
function fetchAuditLog(id?: string) {
const formEl = unref(formElRef);
formEl?.resetFields();
if (id) {
getById(id).then((res) => {
modelRef.value = res;
});
}
}
</script> </script>

105
apps/vue/src/views/auditing/components/AuditLogTable.vue

@ -35,75 +35,62 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { Tag } from 'ant-design-vue';
import { Modal, Tag } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table'; import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
import { getSearchFormSchemas } from './ModalData'; import { getSearchFormSchemas } from './ModalData';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import AuditLogModal from './AuditLogModal.vue';
import { useAuditLog } from '../hooks/useAuditLog'; import { useAuditLog } from '../hooks/useAuditLog';
import { useMessage } from '/@/hooks/web/useMessage';
import { deleteById, getList } from '/@/api/auditing/auditLog'; import { deleteById, getList } from '/@/api/auditing/auditLog';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import AuditLogModal from './AuditLogModal.vue';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'AuditLogTable', const { L } = useLocalization('AbpAuditLogging');
components: { AuditLogModal, BasicTable, Tag, TableAction }, const [registerTable, { reload }] = useTable({
setup() { rowKey: 'id',
const { L } = useLocalization('AbpAuditLogging'); title: L('AuditLog'),
const [registerTable, { reload }] = useTable({ columns: getDataColumns(),
rowKey: 'id', api: getList,
title: L('AuditLog'), beforeFetch: formatPagedRequest,
columns: getDataColumns(), pagination: true,
api: getList, striped: false,
beforeFetch: formatPagedRequest, useSearchForm: true,
pagination: true, showTableSetting: true,
striped: false, bordered: true,
useSearchForm: true, showIndexColumn: false,
showTableSetting: true, canResize: false,
bordered: true, immediate: true,
showIndexColumn: false, formConfig: getSearchFormSchemas(),
canResize: false, scroll: { x: 'max-content', y: '100%' },
immediate: true, actionColumn: {
formConfig: getSearchFormSchemas(), width: 180,
scroll: { x: 'max-content', y: '100%' }, title: L('Actions'),
actionColumn: { dataIndex: 'action',
width: 180, },
title: L('Actions'), });
dataIndex: 'action', const [registerModal, { openModal }] = useModal();
}, const { httpMethodColor, httpStatusCodeColor } = useAuditLog();
});
const [registerModal, { openModal }] = useModal();
const { httpMethodColor, httpStatusCodeColor } = useAuditLog();
function handleShow(record) { function handleShow(record) {
openModal(true, record, true); openModal(true, record, true);
} }
function handleDelete(record) { function handleDelete(record) {
Modal.warning({ createConfirm({
title: L('AreYouSure'), iconType: 'warning',
content: L('ItemWillBeDeletedMessage'), title: L('AreYouSure'),
okCancel: true, content: L('ItemWillBeDeletedMessage'),
onOk: () => { okCancel: true,
deleteById(record.id).then(() => { onOk: () => {
reload(); deleteById(record.id).then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
}, reload();
}); });
} },
});
return { }
L,
httpMethodColor,
httpStatusCodeColor,
registerTable,
registerModal,
handleShow,
handleDelete,
};
},
});
</script> </script>

2
apps/vue/src/views/caching-management/cache/datas/ModalData.ts

@ -69,7 +69,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('DisplayName:Values'), label: L('DisplayName:Values'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ values }) => { render: ({ values }) => {
return createVNode(JsonPreview, { return createVNode(JsonPreview!, {
data: values.values, data: values.values,
}); });
}, },

78
apps/vue/src/views/feature/src/FeatureModal.vue

@ -31,7 +31,7 @@
style="width: 100%" style="width: 100%"
v-model:value="feature.value" v-model:value="feature.value"
/> />
<Input v-else v-model:value="feature.value" /> <BInput v-else v-model:value="feature.value" />
</div> </div>
<Select <Select
v-else-if="feature.valueType.name === 'SelectionStringValueType'" v-else-if="feature.valueType.name === 'SelectionStringValueType'"
@ -52,60 +52,38 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref } from 'vue'; import { computed, ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Checkbox, Form, InputNumber, Select, Tabs } from 'ant-design-vue'; import { Checkbox, Form, InputNumber, Select, Tabs } from 'ant-design-vue';
import { Input } from '/@/components/Input'; import { Input } from '/@/components/Input';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { useFeature } from '../hooks/useFeature'; import { useFeature } from '../hooks/useFeature';
export default defineComponent({
components: {
BasicModal,
Checkbox,
Form,
FormItem: Form.Item,
Input,
InputNumber,
Select,
Option: Select.Option,
Tabs,
TabPane: Tabs.TabPane,
},
setup() {
const { L } = useLocalization('AbpFeatureManagement');
// TODO: ?
const localizer = computed(() => {
return (resourceName: string, key: string) => {
const { L: RL } = useLocalization(resourceName);
return RL(key);
};
});
const formRel = ref(null);
const providerName = ref('');
const providerKey = ref(null);
const [registerModal, modalMethods] = useModalInner((data) => {
providerName.value = data.providerName;
providerKey.value = data.providerKey;
});
const { featureGroup, featureGroupKey, validator, handleSubmit, onGroupChange } = useFeature({
providerName,
providerKey,
formRel,
modalMethods,
});
return { const FormItem = Form.Item;
L, const Option = Select.Option;
localizer, const TabPane = Tabs.TabPane;
formRel, const BInput = Input!;
registerModal,
featureGroup, const { L } = useLocalization('AbpFeatureManagement');
featureGroupKey, // TODO: ?
validator, const localizer = computed(() => {
handleSubmit, return (resourceName: string, key: string) => {
onGroupChange, const { L: RL } = useLocalization(resourceName);
}; return RL(key);
}, };
});
const formRel = ref(null);
const providerName = ref('');
const providerKey = ref(null);
const [registerModal, modalMethods] = useModalInner((data) => {
providerName.value = data.providerName;
providerKey.value = data.providerKey;
});
const { featureGroup, featureGroupKey, validator, handleSubmit, onGroupChange } = useFeature({
providerName,
providerKey,
formRel,
modalMethods,
}); });
</script> </script>

159
apps/vue/src/views/identity-server/api-resources/components/ApiResourceModal.vue

@ -13,8 +13,8 @@
ref="formElRef" ref="formElRef"
:model="resourceRef" :model="resourceRef"
:rules="formRules" :rules="formRules"
:label-col="labelCol" :label-col="{ span: 6 }"
:wrapper-col="wrapperCol" :wrapper-col="{ span: 18 }"
> >
<Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab"> <Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab">
<!-- Api 资源基本信息 --> <!-- Api 资源基本信息 -->
@ -28,19 +28,19 @@
}}</Checkbox> }}</Checkbox>
</FormItem> </FormItem>
<FormItem name="name" required :label="L('Name')"> <FormItem name="name" required :label="L('Name')">
<Input v-model:value="resourceRef.name" :disabled="isEdit" /> <BInput v-model:value="resourceRef.name" :disabled="isEdit" />
</FormItem> </FormItem>
<FormItem name="displayName" :label="L('DisplayName')"> <FormItem name="displayName" :label="L('DisplayName')">
<Input v-model:value="resourceRef.displayName" /> <BInput v-model:value="resourceRef.displayName" />
</FormItem> </FormItem>
<FormItem name="description" :label="L('Description')"> <FormItem name="description" :label="L('Description')">
<Input v-model:value="resourceRef.description" /> <BInput v-model:value="resourceRef.description" />
</FormItem> </FormItem>
<FormItem <FormItem
name="allowedAccessTokenSigningAlgorithms" name="allowedAccessTokenSigningAlgorithms"
:label="L('AllowedAccessTokenSigningAlgorithms')" :label="L('AllowedAccessTokenSigningAlgorithms')"
> >
<Input v-model:value="resourceRef.allowedAccessTokenSigningAlgorithms" /> <BInput v-model:value="resourceRef.allowedAccessTokenSigningAlgorithms" />
</FormItem> </FormItem>
</TabPane> </TabPane>
@ -64,14 +64,14 @@
</span> </span>
<template #overlay> <template #overlay>
<Menu @click="handleClickMenu"> <Menu @click="handleClickMenu">
<MenuItem key="api-resource-secret">{{ L('Secret') }}</MenuItem> <MenuItem key="ApiResourceSecret">{{ L('Secret') }}</MenuItem>
<MenuItem key="properties">{{ L('Propertites') }}</MenuItem> <MenuItem key="Properties">{{ L('Propertites') }}</MenuItem>
</Menu> </Menu>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
<component <component
:is="advancedComponent" :is="componentsRef[advancedComponent]"
:secrets="resourceRef.secrets" :secrets="resourceRef.secrets"
:properties="resourceRef.properties" :properties="resourceRef.properties"
@secrets-new="handleNewSecret" @secrets-new="handleNewSecret"
@ -85,8 +85,9 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref, shallowRef } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue'; import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue'; import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue';
@ -101,94 +102,58 @@
import ApiResourceSecret from './ApiResourceSecret.vue'; import ApiResourceSecret from './ApiResourceSecret.vue';
import UserClaim from '../../components/UserClaim.vue'; import UserClaim from '../../components/UserClaim.vue';
import Properties from '../../components/Properties.vue'; import Properties from '../../components/Properties.vue';
export default defineComponent({
name: 'ApiResourceModal',
components: {
UserClaim,
Properties,
ApiResourceScope,
ApiResourceSecret,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
Input,
Checkbox,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const resourceIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('api-resource-secret');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
resourceIdRef.value = val.id;
});
const {
isEdit,
resourceRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
resourceIdRef,
formElRef,
tabActivedKey,
});
const { handleNewSecret, handleDeleteSecret } = useSecret({ resourceRef });
const { handleNewProperty, handleDeleteProperty } = useProperty({ resourceRef });
const { targetClaims, handleClaimChange } = useClaim({ resourceRef });
const { targetScopes, handleScopeChange } = useScope({ resourceRef });
function handleClickMenu(e) { const FormItem = Form.Item;
tabActivedKey.value = 'advanced'; const MenuItem = Menu.Item;
advancedComponent.value = e.key; const TabPane = Tabs.TabPane;
} const BInput = Input!;
function handleOk() { const componentsRef = shallowRef({
changeOkLoading(true); 'ApiResourceSecret': ApiResourceSecret,
handleSubmit() 'Properties': Properties,
.then(() => { });
emit('change');
}) const emits = defineEmits(['change', 'register']);
.finally(() => {
changeOkLoading(false);
});
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization('AbpIdentityServer');
isEdit, const formElRef = ref<any>(null);
formElRef, const resourceIdRef = ref('');
formRules, const tabActivedKey = ref('basic');
formTitle, const advancedComponent = ref('ApiResourceSecret');
tabActivedKey, const [registerModal, { changeOkLoading }] = useModalInner((val) => {
registerModal, resourceIdRef.value = val.id;
resourceRef, });
advancedComponent, const {
labelCol: { span: 6 }, isEdit,
wrapperCol: { span: 18 }, resourceRef,
handleClickMenu, formRules,
handleNewSecret, formTitle,
handleDeleteSecret, handleChangeTab,
handleNewProperty, handleVisibleModal,
handleDeleteProperty, handleSubmit,
handleChangeTab, } = useModal({
handleVisibleModal, resourceIdRef,
handleOk, formElRef,
targetScopes, tabActivedKey,
handleScopeChange,
targetClaims,
handleClaimChange,
};
},
}); });
const { handleNewSecret, handleDeleteSecret } = useSecret({ resourceRef });
const { handleNewProperty, handleDeleteProperty } = useProperty({ resourceRef });
const { targetClaims, handleClaimChange } = useClaim({ resourceRef });
const { targetScopes, handleScopeChange } = useScope({ resourceRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleOk() {
changeOkLoading(true);
handleSubmit().then(() => {
createMessage.success(L('Successful'));
emits('change');
}).finally(() => {
changeOkLoading(false);
});
}
</script> </script>

65
apps/vue/src/views/identity-server/api-resources/components/ApiResourceScope.vue

@ -12,48 +12,41 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Transfer } from 'ant-design-vue'; import { Transfer } from 'ant-design-vue';
import { discovery } from '/@/api/identity-server/identityServer'; import { discovery } from '/@/api/identity-server/identityServer';
export default defineComponent({ const emits = defineEmits(['change']);
name: 'ApiResourceScope',
components: { Transfer },
props: {
targetScopes: { type: Object as PropType<string[]>, required: true },
},
emits: ['change'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const supportedScopes = ref<
{
key: string;
title: string;
}[]
>([]);
onMounted(() => { defineProps({
discovery().then((res) => { targetScopes: {
supportedScopes.value = res.scopes_supported.map((scope) => { type: Object as PropType<string[]>,
return { required: true,
key: scope, },
title: scope, });
};
});
});
});
function handleChange(targetKeys, direction, moveKeys) { const { L } = useLocalization('AbpIdentityServer');
emit('change', targetKeys, direction, moveKeys); const supportedScopes = ref<
} {
key: string;
title: string;
}[]
>([]);
return { onMounted(() => {
L, discovery().then((res) => {
supportedScopes, supportedScopes.value = res.scopes_supported.map((scope) => {
handleChange, return {
}; key: scope,
}, title: scope,
};
});
});
}); });
function handleChange(targetKeys, direction, moveKeys) {
emits('change', targetKeys, direction, moveKeys);
}
</script> </script>

89
apps/vue/src/views/identity-server/api-resources/components/ApiResourceSecret.vue

@ -2,7 +2,7 @@
<div> <div>
<BasicTable <BasicTable
rowKey="type" rowKey="type"
:columns="columns" :columns="getSecretColumns()"
:dataSource="secrets" :dataSource="secrets"
:pagination="false" :pagination="false"
:showTableSetting="true" :showTableSetting="true"
@ -38,8 +38,9 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Button } from 'ant-design-vue'; import { Button } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form'; import { BasicForm, useForm } from '/@/components/Form';
@ -49,60 +50,40 @@
import { getSecretColumns } from '../datas/TableData'; import { getSecretColumns } from '../datas/TableData';
import { getSecretFormSchemas } from '../datas/ModalData'; import { getSecretFormSchemas } from '../datas/ModalData';
export default defineComponent({ const emits = defineEmits(['register', 'secrets-new', 'secrets-delete']);
name: 'ApiResourceSecret', defineProps({
components: { secrets: {
BasicForm, type: [Array] as PropType<ApiResourceSecret[]>,
BasicModal, required: true,
BasicTable, default: () => [],
Button,
TableAction,
}, },
props: { });
secrets: {
type: [Array] as PropType<ApiResourceSecret[]>,
required: true,
default: () => [],
},
},
emits: ['register', 'secrets-new', 'secrets-delete'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const title = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: getSecretFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
function handleAddNew() { const { createMessage } = useMessage();
title.value = L('Secret:New'); const { L } = useLocalization('AbpIdentityServer');
openModal(true); const title = ref('');
} const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: getSecretFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
function handleDelete(record) { function handleAddNew() {
emit('secrets-delete', record); title.value = L('Secret:New');
} openModal(true);
}
function handleSubmit() { function handleDelete(record) {
validate().then((input) => { emits('secrets-delete', record);
emit('secrets-new', input); }
resetFields();
closeModal();
});
}
return { function handleSubmit() {
L, validate().then((input) => {
title, createMessage.success(L('Successful'));
handleAddNew, emits('secrets-new', input);
handleDelete, resetFields();
handleSubmit, closeModal();
columns: getSecretColumns(), });
registerForm, }
registerModal,
};
},
});
</script> </script>

122
apps/vue/src/views/identity-server/api-resources/components/ApiResourceTable.vue

@ -6,10 +6,12 @@
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'enabled'"> <template v-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly /> <CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-if="column.key === 'showInDiscoveryDocument'"> <template v-if="column.key === 'showInDiscoveryDocument'">
<Switch :checked="record.showInDiscoveryDocument" readonly /> <CheckOutlined v-if="record.showInDiscoveryDocument" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'action'"> <template v-else-if="column.key === 'action'">
<TableAction <TableAction
@ -36,9 +38,10 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { Button } from 'ant-design-vue';
import { Button, Modal, Switch } from 'ant-design-vue'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table'; import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
@ -48,70 +51,57 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import ApiResourceModal from './ApiResourceModal.vue'; import ApiResourceModal from './ApiResourceModal.vue';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'ApiResourceTable', const { L } = useLocalization('AbpIdentityServer');
components: { ApiResourceModal, BasicTable, Button, Switch, TableAction }, const [registerModal, { openModal, closeModal }] = useModal();
setup() { const [registerTable, { reload }] = useTable({
const { L } = useLocalization('AbpIdentityServer'); rowKey: 'id',
const [registerModal, { openModal, closeModal }] = useModal(); title: L('DisplayName:ApiResources'),
const [registerTable, { reload }] = useTable({ columns: getDataColumns(),
rowKey: 'id', api: getList,
title: L('DisplayName:ApiResources'), beforeFetch: formatPagedRequest,
columns: getDataColumns(), pagination: true,
api: getList, striped: false,
beforeFetch: formatPagedRequest, useSearchForm: true,
pagination: true, showTableSetting: true,
striped: false, bordered: true,
useSearchForm: true, showIndexColumn: false,
showTableSetting: true, canResize: true,
bordered: true, immediate: true,
showIndexColumn: false, canColDrag: true,
canResize: true, formConfig: getSearchFormSchemas(),
immediate: true, actionColumn: {
canColDrag: true, width: 200,
formConfig: getSearchFormSchemas(), title: L('Actions'),
actionColumn: { dataIndex: 'action',
width: 200, },
title: L('Actions'), });
dataIndex: 'action',
},
});
function handleAddNew() { function handleAddNew() {
openModal(true, {}); openModal(true, {});
} }
function handleEdit(record) { function handleEdit(record) {
openModal(true, record); openModal(true, record);
} }
function handleChange() { function handleChange() {
closeModal(); closeModal();
reload(); reload();
} }
function handleDelete(record) { function handleDelete(record) {
Modal.warning({ createConfirm({
title: L('AreYouSure'), iconType: 'warning',
content: L('ItemWillBeDeletedMessage'), title: L('AreYouSure'),
okCancel: true, content: L('ItemWillBeDeletedMessage'),
onOk: () => { okCancel: true,
deleteById(record.id).then(() => { onOk: () => {
reload(); deleteById(record.id).then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
}, reload();
}); });
} },
});
return { }
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
};
},
});
</script> </script>

4
apps/vue/src/views/identity-server/api-resources/datas/TableData.ts

@ -36,14 +36,14 @@ export function getDataColumns(): BasicColumn[] {
{ {
title: L('Resource:Enabled'), title: L('Resource:Enabled'),
dataIndex: 'enabled', dataIndex: 'enabled',
align: 'left', align: 'center',
width: 200, width: 200,
sorter: true, sorter: true,
}, },
{ {
title: L('ShowInDiscoveryDocument'), title: L('ShowInDiscoveryDocument'),
dataIndex: 'showInDiscoveryDocument', dataIndex: 'showInDiscoveryDocument',
align: 'left', align: 'center',
width: 200, width: 200,
sorter: true, sorter: true,
}, },

17
apps/vue/src/views/identity-server/api-resources/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue'; import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation'; import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
} }
export function useModal({ resourceIdRef, formElRef, tabActivedKey }: UseModal) { export function useModal({ resourceIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer'); const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation(); const { ruleCreator } = useValidation();
const resourceRef = ref<ApiResource>({} as ApiResource); const resourceRef = ref<ApiResource>({} as ApiResource);
@ -80,14 +81,12 @@ export function useModal({ resourceIdRef, formElRef, tabActivedKey }: UseModal)
const api = isEdit.value const api = isEdit.value
? update(input.id, Object.assign(input)) ? update(input.id, Object.assign(input))
: create(Object.assign(input)); : create(Object.assign(input));
api api.then((res) => {
.then((res) => { createMessage.success(L('Successful'));
message.success(L('Successful')); resolve(res);
resolve(res); }).catch((error) => {
}) reject(error);
.catch((error) => { });
reject(error);
});
}) })
.catch((error) => { .catch((error) => {
reject(error); reject(error);

135
apps/vue/src/views/identity-server/api-scopes/components/ApiScopeModal.vue

@ -13,8 +13,8 @@
ref="formElRef" ref="formElRef"
:model="modelRef" :model="modelRef"
:rules="formRules" :rules="formRules"
:label-col="labelCol" :label-col="{ span: 6 }"
:wrapper-col="wrapperCol" :wrapper-col="{ span: 18 }"
> >
<Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab"> <Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab">
<!-- Api 资源基本信息 --> <!-- Api 资源基本信息 -->
@ -65,7 +65,7 @@
</Dropdown> </Dropdown>
</template> </template>
<component <component
:is="advancedComponent" :is="componentsRef[advancedComponent]"
:properties="modelRef.properties" :properties="modelRef.properties"
@props-new="handleNewProperty" @props-new="handleNewProperty"
@props-delete="handleDeleteProperty" @props-delete="handleDeleteProperty"
@ -76,8 +76,9 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref, shallowRef } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue'; import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue'; import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue';
@ -88,86 +89,54 @@
import { useProperty } from '../hooks/useProperty'; import { useProperty } from '../hooks/useProperty';
import UserClaim from '../../components/UserClaim.vue'; import UserClaim from '../../components/UserClaim.vue';
import Properties from '../../components/Properties.vue'; import Properties from '../../components/Properties.vue';
export default defineComponent({
name: 'ApiScopeModal',
components: {
UserClaim,
Properties,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
Input,
Checkbox,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('properties');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) { const FormItem = Form.Item;
tabActivedKey.value = 'advanced'; const MenuItem = Menu.Item;
advancedComponent.value = e.key; const TabPane = Tabs.TabPane;
}
function handleOk() { const componentsRef = shallowRef({
changeOkLoading(true); 'properties': Properties,
handleSubmit() });
.then(() => {
emit('change'); const emits = defineEmits(['change', 'register']);
})
.finally(() => {
changeOkLoading(false);
});
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization('AbpIdentityServer');
isEdit, const formElRef = ref<any>(null);
formElRef, const modelIdRef = ref('');
formRules, const tabActivedKey = ref('basic');
formTitle, const advancedComponent = ref('properties');
tabActivedKey, const [registerModal, { changeOkLoading }] = useModalInner((val) => {
registerModal, modelIdRef.value = val.id;
modelRef, });
advancedComponent, const {
labelCol: { span: 6 }, isEdit,
wrapperCol: { span: 18 }, modelRef,
handleClickMenu, formRules,
handleNewProperty, formTitle,
handleDeleteProperty, handleChangeTab,
handleChangeTab, handleVisibleModal,
handleVisibleModal, handleSubmit,
handleOk, } = useModal({
targetClaims, modelIdRef,
handleClaimChange, formElRef,
}; tabActivedKey,
},
}); });
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleOk() {
changeOkLoading(true);
handleSubmit() .then(() => {
createMessage.success(L('Successful'));
emits('change');
}) .finally(() => {
changeOkLoading(false);
});
}
</script> </script>

128
apps/vue/src/views/identity-server/api-scopes/components/ApiScopeTable.vue

@ -6,16 +6,20 @@
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'required'"> <template v-if="column.key === 'required'">
<Switch :checked="record.required" readonly /> <CheckOutlined v-if="record.required" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'enabled'"> <template v-else-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly /> <CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'emphasize'"> <template v-else-if="column.key === 'emphasize'">
<Switch :checked="record.emphasize" readonly /> <CheckOutlined v-if="record.emphasize" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'showInDiscoveryDocument'"> <template v-else-if="column.key === 'showInDiscoveryDocument'">
<Switch :checked="record.showInDiscoveryDocument" readonly /> <CheckOutlined v-if="record.showInDiscoveryDocument" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'action'"> <template v-else-if="column.key === 'action'">
<TableAction <TableAction
@ -42,9 +46,10 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { Button } from 'ant-design-vue';
import { Button, Modal, Switch } from 'ant-design-vue'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table'; import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
@ -54,70 +59,57 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import ApiScopeModal from './ApiScopeModal.vue'; import ApiScopeModal from './ApiScopeModal.vue';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'ApiScopeTable', const { L } = useLocalization('AbpIdentityServer');
components: { ApiScopeModal, BasicTable, Button, Switch, TableAction }, const [registerModal, { openModal, closeModal }] = useModal();
setup() { const [registerTable, { reload }] = useTable({
const { L } = useLocalization('AbpIdentityServer'); rowKey: 'id',
const [registerModal, { openModal, closeModal }] = useModal(); title: L('DisplayName:ApiScopes'),
const [registerTable, { reload }] = useTable({ columns: getDataColumns(),
rowKey: 'id', api: getList,
title: L('DisplayName:ApiScopes'), beforeFetch: formatPagedRequest,
columns: getDataColumns(), pagination: true,
api: getList, striped: false,
beforeFetch: formatPagedRequest, useSearchForm: true,
pagination: true, showTableSetting: true,
striped: false, bordered: true,
useSearchForm: true, showIndexColumn: false,
showTableSetting: true, canResize: true,
bordered: true, immediate: true,
showIndexColumn: false, canColDrag: true,
canResize: true, formConfig: getSearchFormSchemas(),
immediate: true, actionColumn: {
canColDrag: true, width: 200,
formConfig: getSearchFormSchemas(), title: L('Actions'),
actionColumn: { dataIndex: 'action',
width: 200, },
title: L('Actions'), });
dataIndex: 'action',
},
});
function handleAddNew() { function handleAddNew() {
openModal(true, {}); openModal(true, {});
} }
function handleEdit(record) { function handleEdit(record) {
openModal(true, record); openModal(true, record);
} }
function handleChange() { function handleChange() {
closeModal(); closeModal();
reload(); reload();
} }
function handleDelete(record) { function handleDelete(record) {
Modal.warning({ createConfirm({
title: L('AreYouSure'), iconType: 'warning',
content: L('ItemWillBeDeletedMessage'), title: L('AreYouSure'),
okCancel: true, content: L('ItemWillBeDeletedMessage'),
onOk: () => { okCancel: true,
deleteById(record.id).then(() => { onOk: () => {
reload(); deleteById(record.id).then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
}, reload();
}); });
} },
});
return { }
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
};
},
});
</script> </script>

32
apps/vue/src/views/identity-server/api-scopes/datas/TableData.ts

@ -11,6 +11,20 @@ export function getDataColumns(): BasicColumn[] {
width: 1, width: 1,
ifShow: false, ifShow: false,
}, },
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'center',
width: 150,
sorter: true,
},
{
title: L('Required'),
dataIndex: 'required',
align: 'center',
width: 150,
sorter: true,
},
{ {
title: L('Name'), title: L('Name'),
dataIndex: 'name', dataIndex: 'name',
@ -32,31 +46,17 @@ export function getDataColumns(): BasicColumn[] {
width: 180, width: 180,
sorter: true, sorter: true,
}, },
{
title: L('Required'),
dataIndex: 'required',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'left',
width: 200,
sorter: true,
},
{ {
title: L('Emphasize'), title: L('Emphasize'),
dataIndex: 'emphasize', dataIndex: 'emphasize',
align: 'left', align: 'center',
width: 200, width: 200,
sorter: true, sorter: true,
}, },
{ {
title: L('ShowInDiscoveryDocument'), title: L('ShowInDiscoveryDocument'),
dataIndex: 'showInDiscoveryDocument', dataIndex: 'showInDiscoveryDocument',
align: 'left', align: 'center',
width: 200, width: 200,
sorter: true, sorter: true,
}, },

17
apps/vue/src/views/identity-server/api-scopes/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue'; import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation'; import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
} }
export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) { export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer'); const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation(); const { ruleCreator } = useValidation();
const modelRef = ref<ApiScope>({} as ApiScope); const modelRef = ref<ApiScope>({} as ApiScope);
@ -76,14 +77,12 @@ export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const api = isEdit.value const api = isEdit.value
? update(input.id, Object.assign(input)) ? update(input.id, Object.assign(input))
: create(Object.assign(input)); : create(Object.assign(input));
api api.then((res) => {
.then((res) => { createMessage.success(L('Successful'));
message.success(L('Successful')); resolve(res);
resolve(res); }).catch((error) => {
}) reject(error);
.catch((error) => { });
reject(error);
});
}) })
.catch((error) => { .catch((error) => {
reject(error); reject(error);

81
apps/vue/src/views/identity-server/clients/components/ClientApiResource.vue

@ -2,60 +2,49 @@
<Resources :resources="resources" :targetResources="targetResources" @change="handleChange" /> <Resources :resources="resources" :targetResources="targetResources" @change="handleChange" />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, onMounted, toRefs } from 'vue'; import { computed, ref, onMounted, toRefs } from 'vue';
import Resources from './Resources.vue'; import Resources from './Resources.vue';
import { getAssignableApiResources } from '/@/api/identity-server/clients'; import { getAssignableApiResources } from '/@/api/identity-server/clients';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import { useResource } from '../hooks/useResource'; import { useResource } from '../hooks/useResource';
export default defineComponent({ const props = defineProps({
name: 'ClientApiResource', modelRef: {
components: { Resources }, type: Object as PropType<Client>,
props: { required: true,
modelRef: {
type: Object as PropType<Client>,
required: true,
},
}, },
setup(props) { });
const resources = ref<{ key: string; title: string }[]>([]);
const targetResources = computed(() => {
const targetScopes = resources.value.filter((item) =>
props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
);
return targetScopes.map((item) => item.key);
});
onMounted(() => { const resources = ref<{ key: string; title: string }[]>([]);
getAssignableApiResources().then((res) => { const targetResources = computed(() => {
resources.value = res.items.map((item) => { const targetScopes = resources.value.filter((item) =>
return { props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
key: item, );
title: item,
};
});
});
});
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
function handleChange(_, direction, moveKeys: string[]) { return targetScopes.map((item) => item.key);
switch (direction) { });
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
return { onMounted(() => {
resources, getAssignableApiResources().then((res) => {
targetResources, resources.value = res.items.map((item) => {
handleChange, return {
}; key: item,
}, title: item,
};
});
});
}); });
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
function handleChange(_, direction, moveKeys: string[]) {
switch (direction) {
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
</script> </script>

79
apps/vue/src/views/identity-server/clients/components/ClientCallback.vue

@ -10,60 +10,47 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
import { useUrl } from '../hooks/useUrl'; import { useUrl } from '../hooks/useUrl';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({ const props = defineProps({
name: 'ClientCallback', modelRef: {
components: { DynamicForm }, type: Object as PropType<Client>,
props: { required: true,
modelRef: {
type: Object as PropType<Client>,
required: true,
},
}, },
setup(props) { });
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'redirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'redirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleRedirectUriChange } = useUrl({ modelRef: toRefs(props).modelRef });
function handleAddNew(record) { const { L } = useLocalization('AbpIdentityServer');
handleRedirectUriChange('add', record.redirectUri); const schemas: FormSchema[] = [
} {
field: 'redirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'redirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleRedirectUriChange } = useUrl({ modelRef: toRefs(props).modelRef });
function handleDelete(record) { function handleAddNew(record) {
handleRedirectUriChange('delete', record.redirectUri); handleRedirectUriChange('add', record.redirectUri);
} }
return { function handleDelete(record) {
L, handleRedirectUriChange('delete', record.redirectUri);
schemas, }
columns,
handleAddNew,
handleDelete,
};
},
});
</script> </script>

130
apps/vue/src/views/identity-server/clients/components/ClientClaim.vue

@ -26,87 +26,75 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { Checkbox, Form } from 'ant-design-vue'; import { Checkbox, Form } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
import DynamicForm from './DynamicForm.vue';
import { useClaim } from '../hooks/useClaim'; import { useClaim } from '../hooks/useClaim';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import { getActivedList } from '/@/api/identity/claim'; import { getActivedList } from '/@/api/identity/claim';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({ const FormItem = Form.Item;
name: 'ClientClaim',
components: { Checkbox, DynamicForm, FormItem: Form.Item },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'ApiSelect',
label: L('Claims:Type'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getActivedList(),
resultField: 'items',
labelField: 'name',
valueField: 'name',
},
},
{
field: 'value',
component: 'Input',
label: L('Claims:Value'),
colProps: { span: 24 },
required: true,
// TODO: type ValueType
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Claims:Type'),
align: 'left',
width: '150',
sorter: true,
},
{
dataIndex: 'value',
title: L('Claims:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleClaimChange, handleCheckedChange } = useClaim({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleClaimChange('add', record);
}
function handleDelete(record) { const props = defineProps({
handleClaimChange('delete', record); modelRef: {
} type: Object as PropType<Client>,
required: true,
},
});
return { const { L } = useLocalization('AbpIdentityServer');
L, const schemas: FormSchema[] = [
schemas, {
columns, field: 'type',
handleAddNew, component: 'ApiSelect',
handleDelete, label: L('Claims:Type'),
handleCheckedChange, colProps: { span: 24 },
}; required: true,
componentProps: {
api: () => getActivedList(),
resultField: 'items',
labelField: 'name',
valueField: 'name',
},
},
{
field: 'value',
component: 'Input',
label: L('Claims:Value'),
colProps: { span: 24 },
required: true,
// TODO: type ValueType
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Claims:Type'),
align: 'left',
width: '150',
sorter: true,
}, },
{
dataIndex: 'value',
title: L('Claims:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleClaimChange, handleCheckedChange } = useClaim({
modelRef: toRefs(props).modelRef,
}); });
function handleAddNew(record) {
handleClaimChange('add', record);
}
function handleDelete(record) {
handleClaimChange('delete', record);
}
</script> </script>

278
apps/vue/src/views/identity-server/clients/components/ClientClone.vue

@ -12,157 +12,145 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref } from 'vue'; import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { message } from 'ant-design-vue';
import { BasicForm, useForm, FormActionType, FormSchema } from '/@/components/Form'; import { BasicForm, useForm, FormActionType, FormSchema } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { clone } from '/@/api/identity-server/clients'; import { clone } from '/@/api/identity-server/clients';
export default defineComponent({ const emits = defineEmits(['change', 'register']);
name: 'ClientClone',
components: { BasicForm, BasicModal },
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const clientIdRef = ref('');
const formElRef = ref<Nullable<FormActionType>>(null);
const formSchemas: FormSchema[] = [
{
field: 'clientId',
component: 'Input',
label: L('Client:Id'),
colProps: { span: 24 },
required: true,
},
{
field: 'clientName',
component: 'Input',
label: L('Name'),
colProps: { span: 24 },
required: true,
},
{
field: 'description',
component: 'InputTextArea',
label: L('Description'),
colProps: { span: 24 },
},
{
field: 'copyAllowedGrantType',
component: 'Checkbox',
label: L('Clone:CopyAllowedGrantType'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedGrantType'),
},
{
field: 'copyRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyRedirectUri'),
},
{
field: 'copyAllowedScope',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyAllowedScope'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyAllowedScope'),
},
{
field: 'copyClaim',
component: 'Checkbox',
label: L('Clone:CopyClaim'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyClaim'),
},
{
field: 'copySecret',
component: 'Checkbox',
label: L('Clone:CopySecret'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopySecret'),
},
{
field: 'copyAllowedCorsOrigin',
component: 'Checkbox',
label: L('Clone:CopyAllowedCorsOrigin'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedCorsOrigin'),
},
{
field: 'copyPostLogoutRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyPostLogoutRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyPostLogoutRedirectUri'),
},
{
field: 'copyProperties',
component: 'Checkbox',
label: L('Clone:CopyProperties'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyProperties'),
},
{
field: 'copyIdentityProviderRestriction',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyIdentityProviderRestriction'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyIdentityProviderRestriction'),
},
];
const [registerForm] = useForm({
labelWidth: 120,
schemas: formSchemas,
showActionButtonGroup: false,
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((data) => {
clientIdRef.value = data.id;
});
function handleSubmit() { const { createMessage } = useMessage();
const formEl = unref(formElRef); const { L } = useLocalization('AbpIdentityServer');
formEl?.validate().then((input) => { const clientIdRef = ref('');
changeOkLoading(true); const formElRef = ref<Nullable<FormActionType>>(null);
clone(unref(clientIdRef), input) const formSchemas: FormSchema[] = [
.then(() => { {
message.success(L('Successful')); field: 'clientId',
emit('change'); component: 'Input',
closeModal(); label: L('Client:Id'),
}) colProps: { span: 24 },
.finally(() => { required: true,
changeOkLoading(false); },
}); {
}); field: 'clientName',
} component: 'Input',
label: L('Name'),
return { colProps: { span: 24 },
L, required: true,
formElRef, },
registerModal, {
registerForm, field: 'description',
handleSubmit, component: 'InputTextArea',
}; label: L('Description'),
colProps: { span: 24 },
},
{
field: 'copyAllowedGrantType',
component: 'Checkbox',
label: L('Clone:CopyAllowedGrantType'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedGrantType'),
},
{
field: 'copyRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyRedirectUri'),
},
{
field: 'copyAllowedScope',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyAllowedScope'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyAllowedScope'),
},
{
field: 'copyClaim',
component: 'Checkbox',
label: L('Clone:CopyClaim'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyClaim'),
}, },
{
field: 'copySecret',
component: 'Checkbox',
label: L('Clone:CopySecret'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopySecret'),
},
{
field: 'copyAllowedCorsOrigin',
component: 'Checkbox',
label: L('Clone:CopyAllowedCorsOrigin'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedCorsOrigin'),
},
{
field: 'copyPostLogoutRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyPostLogoutRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyPostLogoutRedirectUri'),
},
{
field: 'copyProperties',
component: 'Checkbox',
label: L('Clone:CopyProperties'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyProperties'),
},
{
field: 'copyIdentityProviderRestriction',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyIdentityProviderRestriction'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyIdentityProviderRestriction'),
},
];
const [registerForm] = useForm({
labelWidth: 120,
schemas: formSchemas,
showActionButtonGroup: false,
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((data) => {
clientIdRef.value = data.id;
}); });
function handleSubmit() {
const formEl = unref(formElRef);
formEl?.validate().then((input) => {
changeOkLoading(true);
clone(unref(clientIdRef), input)
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
changeOkLoading(false);
});
});
}
</script> </script>

77
apps/vue/src/views/identity-server/clients/components/ClientCorsOrigins.vue

@ -10,8 +10,8 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
@ -19,51 +19,38 @@
import DynamicForm from './DynamicForm.vue'; import DynamicForm from './DynamicForm.vue';
import { useUrl } from '../hooks/useUrl'; import { useUrl } from '../hooks/useUrl';
export default defineComponent({ const props = defineProps({
name: 'ClientCorsOrigins', modelRef: {
components: { DynamicForm }, type: Object as PropType<Client>,
props: { required: true,
modelRef: {
type: Object as PropType<Client>,
required: true,
},
}, },
setup(props) { });
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'origin',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'origin',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleCorsOriginsChange } = useUrl({ modelRef: toRefs(props).modelRef });
function handleAddNew(record) { const { L } = useLocalization('AbpIdentityServer');
handleCorsOriginsChange('add', record.origin); const schemas: FormSchema[] = [
} {
field: 'origin',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'origin',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleCorsOriginsChange } = useUrl({ modelRef: toRefs(props).modelRef });
function handleDelete(record) { function handleAddNew(record) {
handleCorsOriginsChange('delete', record.origin); handleCorsOriginsChange('add', record.origin);
} }
return { function handleDelete(record) {
L, handleCorsOriginsChange('delete', record.origin);
schemas, }
columns,
handleAddNew,
handleDelete,
};
},
});
</script> </script>

87
apps/vue/src/views/identity-server/clients/components/ClientGrantType.vue

@ -10,8 +10,8 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
@ -19,56 +19,43 @@
import { useGrantType } from '../hooks/useGrantType'; import { useGrantType } from '../hooks/useGrantType';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
export default defineComponent({ const props = defineProps({
name: 'ClientGrantType', modelRef: {
components: { DynamicForm }, type: Object as PropType<Client>,
props: { required: true,
modelRef: {
type: Object as PropType<Client>,
required: true,
},
}, },
setup(props) { });
const { L } = useLocalization('AbpIdentityServer');
const { grantTypeOptions, handleGrantTypeChanged } = useGrantType({
modelRef: toRefs(props).modelRef,
});
const schemas: FormSchema[] = [
{
field: 'grantType',
component: 'Select',
label: L('Client:AllowedGrantTypes'),
colProps: { span: 24 },
required: true,
componentProps: {
options: grantTypeOptions,
},
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'grantType',
align: 'left',
width: 'auto',
sorter: true,
},
];
function handleAddNew(record) { const { L } = useLocalization('AbpIdentityServer');
handleGrantTypeChanged('add', record); const { grantTypeOptions, handleGrantTypeChanged } = useGrantType({
} modelRef: toRefs(props).modelRef,
});
const schemas: FormSchema[] = [
{
field: 'grantType',
component: 'Select',
label: L('Client:AllowedGrantTypes'),
colProps: { span: 24 },
required: true,
componentProps: {
options: grantTypeOptions,
},
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'grantType',
align: 'left',
width: 'auto',
sorter: true,
},
];
function handleDelete(record) { function handleAddNew(record) {
handleGrantTypeChanged('delete', record); handleGrantTypeChanged('add', record);
} }
return { function handleDelete(record) {
L, handleGrantTypeChanged('delete', record);
schemas, }
columns,
handleAddNew,
handleDelete,
};
},
});
</script> </script>

90
apps/vue/src/views/identity-server/clients/components/ClientIdentityProvider.vue

@ -16,67 +16,53 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { Checkbox, Form } from 'ant-design-vue'; import { Checkbox, Form } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
import DynamicForm from './DynamicForm.vue';
import { useIdentityProvider } from '../hooks/useIdentityProvider'; import { useIdentityProvider } from '../hooks/useIdentityProvider';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({ const FormItem = Form.Item;
name: 'ClientIdentityProvider',
components: { Checkbox, DynamicForm, FormItem: Form.Item },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'provider',
component: 'Input',
label: L('Client:IdentityProviderRestrictions'),
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'provider',
title: L('Client:IdentityProviderRestrictions'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleIdpChange, handleCheckedChange } = useIdentityProvider({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
console.log(record);
handleIdpChange('add', record);
}
function handleDelete(record) { const props = defineProps({
console.log(record); modelRef: {
handleIdpChange('delete', record); type: Object as PropType<Client>,
} required: true,
},
});
return { const { L } = useLocalization('AbpIdentityServer');
L, const schemas: FormSchema[] = [
schemas, {
columns, field: 'provider',
handleAddNew, component: 'Input',
handleDelete, label: L('Client:IdentityProviderRestrictions'),
handleCheckedChange, colProps: { span: 24 },
}; required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'provider',
title: L('Client:IdentityProviderRestrictions'),
align: 'left',
width: 'auto',
sorter: true,
}, },
];
const { handleIdpChange, handleCheckedChange } = useIdentityProvider({
modelRef: toRefs(props).modelRef,
}); });
function handleAddNew(record) {
handleIdpChange('add', record);
}
function handleDelete(record) {
handleIdpChange('delete', record);
}
</script> </script>

83
apps/vue/src/views/identity-server/clients/components/ClientIdentityResource.vue

@ -2,60 +2,49 @@
<Resources :resources="resources" :targetResources="targetResources" @change="handleChange" /> <Resources :resources="resources" :targetResources="targetResources" @change="handleChange" />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, onMounted, toRefs } from 'vue'; import { computed, ref, onMounted, toRefs } from 'vue';
import Resources from './Resources.vue';
import { getAssignableIdentityResources } from '/@/api/identity-server/clients'; import { getAssignableIdentityResources } from '/@/api/identity-server/clients';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import { useResource } from '../hooks/useResource'; import { useResource } from '../hooks/useResource';
import Resources from './Resources.vue';
export default defineComponent({ const props = defineProps({
name: 'ClientIdentityResource', modelRef: {
components: { Resources }, type: Object as PropType<Client>,
props: { required: true,
modelRef: {
type: Object as PropType<Client>,
required: true,
},
}, },
setup(props) { });
const resources = ref<{ key: string; title: string }[]>([]);
const targetResources = computed(() => {
const targetScopes = resources.value.filter((item) =>
props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
);
return targetScopes.map((item) => item.key);
});
onMounted(() => { const resources = ref<{ key: string; title: string }[]>([]);
getAssignableIdentityResources().then((res) => { const targetResources = computed(() => {
resources.value = res.items.map((item) => { const targetScopes = resources.value.filter((item) =>
return { props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
key: item, );
title: item,
};
});
});
});
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
function handleChange(_, direction, moveKeys: string[]) { return targetScopes.map((item) => item.key);
switch (direction) { });
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
return { onMounted(() => {
resources, getAssignableIdentityResources().then((res) => {
targetResources, resources.value = res.items.map((item) => {
handleChange, return {
}; key: item,
}, title: item,
};
});
});
}); });
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
function handleChange(_, direction, moveKeys: string[]) {
switch (direction) {
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
</script> </script>

79
apps/vue/src/views/identity-server/clients/components/ClientLogoutRedirectUris.vue

@ -10,60 +10,47 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
import { useUrl } from '../hooks/useUrl'; import { useUrl } from '../hooks/useUrl';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({ const props = defineProps({
name: 'ClientLogoutRedirectUris', modelRef: {
components: { DynamicForm }, type: Object as PropType<Client>,
props: { required: true,
modelRef: {
type: Object as PropType<Client>,
required: true,
},
}, },
setup(props) { });
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'postLogoutRedirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'postLogoutRedirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleLogoutRedirectUris } = useUrl({ modelRef: toRefs(props).modelRef });
function handleAddNew(record) { const { L } = useLocalization('AbpIdentityServer');
handleLogoutRedirectUris('add', record.postLogoutRedirectUri); const schemas: FormSchema[] = [
} {
field: 'postLogoutRedirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'postLogoutRedirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleLogoutRedirectUris } = useUrl({ modelRef: toRefs(props).modelRef });
function handleDelete(record) { function handleAddNew(record) {
handleLogoutRedirectUris('delete', record.postLogoutRedirectUri); handleLogoutRedirectUris('add', record.postLogoutRedirectUri);
} }
return { function handleDelete(record) {
L, handleLogoutRedirectUris('delete', record.postLogoutRedirectUri);
schemas, }
columns,
handleAddNew,
handleDelete,
};
},
});
</script> </script>

203
apps/vue/src/views/identity-server/clients/components/ClientModal.vue

@ -13,8 +13,8 @@
ref="formElRef" ref="formElRef"
:model="modelRef" :model="modelRef"
:rules="formRules" :rules="formRules"
:label-col="labelCol" :label-col="{ span: 6 }"
:wrapper-col="wrapperCol" :wrapper-col="{ span: 18 }"
> >
<Tabs <Tabs
v-model:activeKey="tabActivedKey" v-model:activeKey="tabActivedKey"
@ -74,18 +74,18 @@
</span> </span>
<template #overlay> <template #overlay>
<Menu @click="handleClickUrlsMenu"> <Menu @click="handleClickUrlsMenu">
<MenuItem key="client-callback">{{ L('Client:CallbackUrl') }}</MenuItem> <MenuItem key="ClientCallback">{{ L('Client:CallbackUrl') }}</MenuItem>
<MenuItem key="client-cors-origins">{{ <MenuItem key="ClientCorsOrigins">{{
L('Client:AllowedCorsOrigins') L('Client:AllowedCorsOrigins')
}}</MenuItem> }}</MenuItem>
<MenuItem key="client-logout-redirect-uris">{{ <MenuItem key="ClientLogoutRedirectUris">{{
L('Client:PostLogoutRedirectUri') L('Client:PostLogoutRedirectUri')
}}</MenuItem> }}</MenuItem>
</Menu> </Menu>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
<component :is="urlsComponent" :modelRef="modelRef" /> <component :is="componentsRef[urlsComponent]" :modelRef="modelRef" />
</TabPane> </TabPane>
<!-- 资源 --> <!-- 资源 -->
@ -98,13 +98,13 @@
</span> </span>
<template #overlay> <template #overlay>
<Menu @click="handleClickResourcesMenu"> <Menu @click="handleClickResourcesMenu">
<MenuItem key="client-api-resource">{{ L('Resource:Api') }}</MenuItem> <MenuItem key="ClientApiResource">{{ L('Resource:Api') }}</MenuItem>
<MenuItem key="client-identity-resource">{{ L('Resource:Identity') }}</MenuItem> <MenuItem key="ClientIdentityResource">{{ L('Resource:Identity') }}</MenuItem>
</Menu> </Menu>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
<component :is="resourcesComponent" :modelRef="modelRef" /> <component :is="componentsRef[resourcesComponent]" :modelRef="modelRef" />
</TabPane> </TabPane>
<!-- 认证/注销 --> <!-- 认证/注销 -->
@ -256,27 +256,28 @@
</span> </span>
<template #overlay> <template #overlay>
<Menu @click="handleClickAdvancedMenu"> <Menu @click="handleClickAdvancedMenu">
<MenuItem key="client-secret">{{ L('Secret') }}</MenuItem> <MenuItem key="ClientSecret">{{ L('Secret') }}</MenuItem>
<MenuItem key="client-claim">{{ L('Claims') }}</MenuItem> <MenuItem key="ClientClaim">{{ L('Claims') }}</MenuItem>
<MenuItem key="client-properties">{{ L('Propertites') }}</MenuItem> <MenuItem key="ClientProperties">{{ L('Propertites') }}</MenuItem>
<MenuItem key="client-grant-type">{{ L('Client:AllowedGrantTypes') }}</MenuItem> <MenuItem key="ClientGrantType">{{ L('Client:AllowedGrantTypes') }}</MenuItem>
<MenuItem key="client-identity-provider">{{ <MenuItem key="ClientIdentityProvider">{{
L('Client:IdentityProviderRestrictions') L('Client:IdentityProviderRestrictions')
}}</MenuItem> }}</MenuItem>
</Menu> </Menu>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
<component :is="advancedComponent" :modelRef="modelRef" /> <component :is="componentsRef[advancedComponent]" :modelRef="modelRef" />
</TabPane> </TabPane>
</Tabs> </Tabs>
</Form> </Form>
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref, shallowRef } from 'vue';
import { useTabsStyle } from '/@/hooks/component/useStyles'; import { useTabsStyle } from '/@/hooks/component/useStyles';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue'; import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form, Input, InputNumber, Select } from 'ant-design-vue'; import { Checkbox, Dropdown, Menu, Tabs, Form, Input, InputNumber, Select } from 'ant-design-vue';
@ -293,112 +294,78 @@
import ClientProperties from './ClientProperties.vue'; import ClientProperties from './ClientProperties.vue';
import ClientGrantType from './ClientGrantType.vue'; import ClientGrantType from './ClientGrantType.vue';
import ClientIdentityProvider from './ClientIdentityProvider.vue'; import ClientIdentityProvider from './ClientIdentityProvider.vue';
export default defineComponent({
name: 'ClientModal',
components: {
ClientCallback,
ClientCorsOrigins,
ClientLogoutRedirectUris,
ClientApiResource,
ClientIdentityResource,
ClientSecret,
ClientClaim,
ClientProperties,
ClientGrantType,
ClientIdentityProvider,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
BInput,
InputNumber,
TextArea: Input.TextArea,
Checkbox,
Select,
Option: Select.Option,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('client-secret');
const urlsComponent = ref('client-callback');
const resourcesComponent = ref('client-api-resource');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const tabsStyle = useTabsStyle();
function handleClickAdvancedMenu(e) { const FormItem = Form.Item;
tabActivedKey.value = 'advanced'; const MenuItem = Menu.Item;
advancedComponent.value = e.key; const TabPane = Tabs.TabPane;
} const TextArea = Input.TextArea;
const Option = Select.Option;
function handleClickUrlsMenu(e) { const componentsRef = shallowRef({
tabActivedKey.value = 'urls'; 'ClientCallback': ClientCallback,
urlsComponent.value = e.key; 'ClientCorsOrigins': ClientCorsOrigins,
} 'ClientLogoutRedirectUris': ClientLogoutRedirectUris,
'ClientApiResource': ClientApiResource,
function handleClickResourcesMenu(e) { 'ClientIdentityResource': ClientIdentityResource,
tabActivedKey.value = 'resources'; 'ClientSecret': ClientSecret,
resourcesComponent.value = e.key; 'ClientClaim': ClientClaim,
} 'ClientProperties': ClientProperties,
'ClientGrantType': ClientGrantType,
'ClientIdentityProvider': ClientIdentityProvider,
});
function handleOk() { const emits = defineEmits(['change', 'register']);
changeOkLoading(true);
handleSubmit()
.then(() => {
emit('change');
})
.finally(() => {
changeOkLoading(false);
});
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization('AbpIdentityServer');
isEdit, const formElRef = ref<any>(null);
formElRef, const modelIdRef = ref('');
formRules, const tabActivedKey = ref('basic');
formTitle, const advancedComponent = ref('ClientSecret');
tabsStyle, const urlsComponent = ref('ClientCallback');
tabActivedKey, const resourcesComponent = ref('ClientApiResource');
registerModal, const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelRef, modelIdRef.value = val.id;
labelCol: { span: 6 }, });
wrapperCol: { span: 18 }, const {
advancedComponent, isEdit,
urlsComponent, modelRef,
resourcesComponent, formRules,
handleClickUrlsMenu, formTitle,
handleClickResourcesMenu, handleChangeTab,
handleClickAdvancedMenu, handleVisibleModal,
handleChangeTab, handleSubmit,
handleVisibleModal, } = useModal({
handleOk, modelIdRef,
}; formElRef,
}, tabActivedKey,
}); });
const tabsStyle = useTabsStyle();
function handleClickAdvancedMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleClickUrlsMenu(e) {
tabActivedKey.value = 'urls';
urlsComponent.value = e.key;
}
function handleClickResourcesMenu(e) {
tabActivedKey.value = 'resources';
resourcesComponent.value = e.key;
}
function handleOk() {
changeOkLoading(true);
handleSubmit().then(() => {
createMessage.success(L('Successful'));
emits('change');
}).finally(() => {
changeOkLoading(false);
});
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

113
apps/vue/src/views/identity-server/clients/components/ClientProperties.vue

@ -11,77 +11,64 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
import DynamicForm from './DynamicForm.vue';
import { useProperty } from '../hooks/useProperty'; import { useProperty } from '../hooks/useProperty';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({ const props = defineProps({
name: 'ClientProperties', modelRef: {
components: { DynamicForm }, type: Object as PropType<Client>,
props: { required: true,
modelRef: {
type: Object as PropType<Client>,
required: true,
},
}, },
setup(props) { });
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'Input',
label: L('Propertites:Key'),
colProps: { span: 24 },
required: true,
},
{
field: 'value',
component: 'Input',
label: L('Propertites:Value'),
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Propertites:Key'),
align: 'left',
width: '150',
sorter: true,
},
{
dataIndex: 'value',
title: L('Propertites:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleNewProperty, handleDeleteProperty } = useProperty({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleNewProperty(record);
}
function handleDelete(record) {
handleDeleteProperty(record);
}
return { const { L } = useLocalization('AbpIdentityServer');
L, const schemas: FormSchema[] = [
schemas, {
columns, field: 'type',
handleAddNew, component: 'Input',
handleDelete, label: L('Propertites:Key'),
}; colProps: { span: 24 },
required: true,
}, },
{
field: 'value',
component: 'Input',
label: L('Propertites:Value'),
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Propertites:Key'),
align: 'left',
width: '150',
sorter: true,
},
{
dataIndex: 'value',
title: L('Propertites:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleNewProperty, handleDeleteProperty } = useProperty({
modelRef: toRefs(props).modelRef,
}); });
function handleAddNew(record) {
handleNewProperty(record);
}
function handleDelete(record) {
handleDeleteProperty(record);
}
</script> </script>

206
apps/vue/src/views/identity-server/clients/components/ClientSecret.vue

@ -16,126 +16,114 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, toRefs } from 'vue'; import { toRefs } from 'vue';
import { Checkbox, Form } from 'ant-design-vue'; import { Checkbox, Form } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
import { formatToDateTime } from '/@/utils/dateUtil'; import { formatToDateTime } from '/@/utils/dateUtil';
import { Client } from '/@/api/identity-server/model/clientsModel'; import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
import { useSecret } from '../hooks/useSecret'; import { useSecret } from '../hooks/useSecret';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({ const FormItem = Form.Item;
name: 'ClientSecret',
components: { Checkbox, DynamicForm, FormItem: Form.Item }, const props = defineProps({
props: { modelRef: {
modelRef: { type: Object as PropType<Client>,
type: Object as PropType<Client>, required: true,
required: true, },
});
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'Select',
label: L('Secret:Type'),
colProps: { span: 24 },
required: true,
componentProps: {
options: [
{ label: 'JsonWebKey', value: 'JWK' },
{ label: 'SharedSecret', value: 'SharedSecret' },
{ label: 'X509CertificateName', value: 'X509Name' },
{ label: 'X509CertificateBase64', value: 'X509CertificateBase64' },
{ label: 'X509CertificateThumbprint', value: 'X509Thumbprint' },
],
}, },
}, },
setup(props) { {
const { L } = useLocalization('AbpIdentityServer'); field: 'value',
const schemas: FormSchema[] = [ component: 'Input',
{ label: L('Secret:Value'),
field: 'type', colProps: { span: 24 },
component: 'Select', required: true,
label: L('Secret:Type'), },
colProps: { span: 24 }, {
required: true, field: 'description',
componentProps: { component: 'InputTextArea',
options: [ label: L('Description'),
{ label: 'JsonWebKey', value: 'JWK' }, colProps: { span: 24 },
{ label: 'SharedSecret', value: 'SharedSecret' }, },
{ label: 'X509CertificateName', value: 'X509Name' }, {
{ label: 'X509CertificateBase64', value: 'X509CertificateBase64' }, field: 'expiration',
{ label: 'X509CertificateThumbprint', value: 'X509Thumbprint' }, component: 'DatePicker',
], label: L('Expiration'),
}, colProps: { span: 24 },
}, componentProps: {
{ style: {
field: 'value', width: '100%',
component: 'Input',
label: L('Secret:Value'),
colProps: { span: 24 },
required: true,
},
{
field: 'description',
component: 'InputTextArea',
label: L('Description'),
colProps: { span: 24 },
},
{
field: 'expiration',
component: 'DatePicker',
label: L('Expiration'),
colProps: { span: 24 },
componentProps: {
style: {
width: '100%',
},
},
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Secret:Type'),
align: 'left',
width: '120',
sorter: true,
},
{
dataIndex: 'value',
title: L('Secret:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
{
dataIndex: 'description',
title: L('Description'),
align: 'left',
width: '100',
sorter: true,
},
{
dataIndex: 'expiration',
title: L('Expiration'),
align: 'left',
width: '100',
sorter: true,
format: (text) => {
if (text) {
return formatToDateTime(text);
}
return '';
},
}, },
]; },
const { handleSecretChange, handleRequiredChange } = useSecret({ },
modelRef: toRefs(props).modelRef, ];
}); const columns: BasicColumn[] = [
{
function handleAddNew(record) { dataIndex: 'type',
handleSecretChange('add', record); title: L('Secret:Type'),
} align: 'left',
width: '120',
function handleDelete(record) { sorter: true,
handleSecretChange('delete', record);
}
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
handleRequiredChange,
};
}, },
{
dataIndex: 'value',
title: L('Secret:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
{
dataIndex: 'description',
title: L('Description'),
align: 'left',
width: '100',
sorter: true,
},
{
dataIndex: 'expiration',
title: L('Expiration'),
align: 'left',
width: '100',
sorter: true,
format: (text) => {
if (text) {
return formatToDateTime(text);
}
return '';
},
},
];
const { handleSecretChange, handleRequiredChange } = useSecret({
modelRef: toRefs(props).modelRef,
}); });
function handleAddNew(record) {
handleSecretChange('add', record);
}
function handleDelete(record) {
handleSecretChange('delete', record);
}
</script> </script>

155
apps/vue/src/views/identity-server/clients/components/ClientTable.vue

@ -6,7 +6,8 @@
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'enabled'"> <template v-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly /> <CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'actions'"> <template v-else-if="column.key === 'actions'">
<TableAction <TableAction
@ -47,9 +48,10 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { Button } from 'ant-design-vue';
import { Button, Modal, Switch } from 'ant-design-vue'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table'; import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
@ -57,100 +59,75 @@
import { getSearchFormSchemas } from '../datas/ModalData'; import { getSearchFormSchemas } from '../datas/ModalData';
import { deleteById, getList } from '/@/api/identity-server/clients'; import { deleteById, getList } from '/@/api/identity-server/clients';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { PermissionModal } from '/@/components/Permission';
import ClientModal from './ClientModal.vue'; import ClientModal from './ClientModal.vue';
import ClientClone from './ClientClone.vue'; import ClientClone from './ClientClone.vue';
import { PermissionModal } from '/@/components/Permission';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'ApiScopeTable', const { L } = useLocalization('AbpIdentityServer');
components: { const [registerModal, { openModal, closeModal }] = useModal();
ClientModal, const [registerCloneModal, { openModal: openCloneModal }] = useModal();
ClientClone, const [registerPermissionModal, { openModal: openPermissionModal }] = useModal();
BasicTable, const [registerTable, { reload }] = useTable({
Button, rowKey: 'id',
Switch, title: L('DisplayName:ApiScopes'),
TableAction, columns: getDataColumns(),
PermissionModal, api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'actions',
}, },
setup() { });
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerCloneModal, { openModal: openCloneModal }] = useModal();
const [registerPermissionModal, { openModal: openPermissionModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:ApiScopes'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'actions',
},
});
function handleAddNew() { function handleAddNew() {
openModal(true, {}); openModal(true, {});
} }
function handleEdit(record) { function handleEdit(record) {
openModal(true, record); openModal(true, record);
} }
function handleChange() { function handleChange() {
closeModal(); closeModal();
reload(); reload();
} }
function handleClone(record) { function handleClone(record) {
openCloneModal(true, record); openCloneModal(true, record);
} }
function handlePermission(record) { function handlePermission(record) {
const props = { const props = {
providerName: 'C', providerName: 'C',
providerKey: record.clientId, providerKey: record.clientId,
}; };
openPermissionModal(true, props, true); openPermissionModal(true, props, true);
} }
function handleDelete(record) { function handleDelete(record) {
Modal.warning({ createConfirm({
title: L('AreYouSure'), iconType: 'warning',
content: L('ItemWillBeDeletedMessage'), title: L('AreYouSure'),
okCancel: true, content: L('ItemWillBeDeletedMessage'),
onOk: () => { okCancel: true,
deleteById(record.id).then(() => { onOk: () => {
reload(); deleteById(record.id).then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
}, reload();
}); });
} },
});
return { }
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
handleClone,
registerCloneModal,
handlePermission,
registerPermissionModal,
};
},
});
</script> </script>

181
apps/vue/src/views/identity-server/clients/components/DynamicForm.vue

@ -21,113 +21,100 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { BasicTitle } from '/@/components/Basic'; import { BasicTitle } from '/@/components/Basic';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, FormSchema, useForm } from '/@/components/Form'; import { BasicForm, FormSchema, useForm } from '/@/components/Form';
import { BasicTable, BasicColumn, TableAction, useTable } from '/@/components/Table'; import { BasicTable, BasicColumn, TableAction, useTable } from '/@/components/Table';
export default defineComponent({ const emits = defineEmits(['new', 'delete']);
name: 'DynamicForm', const props = defineProps({
components: { BasicForm, BasicTitle, BasicTable, TableAction }, schemas: {
props: { type: [Array] as PropType<FormSchema[]>,
schemas: { required: true,
type: [Array] as PropType<FormSchema[]>, default: () => [],
required: true,
default: () => [],
},
labelWidth: {
type: Number,
},
columns: {
type: [Array] as PropType<BasicColumn[]>,
required: true,
default: () => [],
},
dataSource: {
type: [Array] as PropType<Recordable[]>,
required: true,
default: () => [],
},
rowKey: {
type: String,
default: () => 'id',
},
showHeader: {
type: Boolean,
default: () => false,
},
title: {
type: String,
default: () => '',
},
tableTitle: {
type: String,
default: () => '',
},
}, },
emits: ['new', 'delete'], labelWidth: {
setup(props, { emit }) { type: Number,
const { L } = useLocalization('AbpIdentityServer'); },
const modelRef = ref({}); columns: {
const [registerForm, { resetFields }] = useForm({ type: [Array] as PropType<BasicColumn[]>,
model: modelRef, required: true,
labelWidth: props.labelWidth, default: () => [],
schemas: props.schemas, },
showResetButton: false, dataSource: {
submitButtonOptions: { type: [Array] as PropType<Recordable[]>,
text: L('AddNew'), required: true,
// icon: 'ant-design:plus-outlined', default: () => [],
}, },
}); rowKey: {
const [registerTable, { setTableData }] = useTable({ type: String,
rowKey: props.rowKey, default: () => 'id',
showHeader: props.showHeader, },
title: props.tableTitle, showHeader: {
columns: props.columns, type: Boolean,
dataSource: props.dataSource, default: () => false,
pagination: false, },
striped: false, title: {
useSearchForm: false, type: String,
showTableSetting: false, default: () => '',
showIndexColumn: false, },
bordered: false, tableTitle: {
actionColumn: { type: String,
width: 200, default: () => '',
title: L('Actions'), },
dataIndex: 'action', });
},
});
watch( const { L } = useLocalization('AbpIdentityServer');
() => props.dataSource, const modelRef = ref({});
(data) => { const [registerForm, { resetFields }] = useForm({
setTableData(data); model: modelRef,
}, labelWidth: props.labelWidth,
{ schemas: props.schemas,
deep: true, showResetButton: false,
}, submitButtonOptions: {
); text: L('AddNew'),
// icon: 'ant-design:plus-outlined',
},
});
const [registerTable, { setTableData }] = useTable({
rowKey: props.rowKey,
showHeader: props.showHeader,
title: props.tableTitle,
columns: props.columns,
dataSource: props.dataSource,
pagination: false,
striped: false,
useSearchForm: false,
showTableSetting: false,
showIndexColumn: false,
bordered: false,
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleSubmit(input) { watch(
emit('new', input); () => props.dataSource,
resetFields(); (data) => {
} setTableData(data);
},
{
deep: true,
},
);
function handleDelete(record) { function handleSubmit(input) {
emit('delete', record); emits('new', input);
} resetFields();
}
return { function handleDelete(record) {
L, emits('delete', record);
registerForm, }
registerTable,
handleSubmit,
handleDelete,
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

59
apps/vue/src/views/identity-server/clients/components/Resources.vue

@ -9,46 +9,33 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent } from 'vue'; import { computed } from 'vue';
import { Transfer } from 'ant-design-vue'; import { Transfer } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
export default defineComponent({ const emits = defineEmits(['change']);
name: 'Resources', const props = defineProps({
components: { Transfer }, resources: {
props: { type: [Array] as PropType<{ key: string; title: string }[]>,
resources: { required: true,
type: [Array] as PropType<{ key: string; title: string }[]>, default: () => [],
required: true,
default: () => [],
},
targetResources: { type: [Array] as PropType<string[]>, required: true, default: () => [] },
listStyle: { type: Object, required: false },
}, },
emits: ['change'], targetResources: { type: [Array] as PropType<string[]>, required: true, default: () => [] },
setup(props, { emit }) { listStyle: { type: Object, required: false },
const { L } = useLocalization('AbpIdentityServer'); });
const defaultListStyle = {
width: '48%',
height: '500px',
minHeight: '500px',
};
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
});
function handleChange(targetKeys, direction, moveKeys) {
emit('change', targetKeys, direction, moveKeys);
}
return { const { L } = useLocalization('AbpIdentityServer');
L, const defaultListStyle = {
getListStyle, width: '48%',
handleChange, height: '500px',
}; minHeight: '500px',
}, };
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
}); });
function handleChange(targetKeys, direction, moveKeys) {
emits('change', targetKeys, direction, moveKeys);
}
</script> </script>

32
apps/vue/src/views/identity-server/clients/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue'; import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation'; import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
} }
export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) { export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer'); const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation(); const { ruleCreator } = useValidation();
const modelRef = ref<Client>({} as Client); const modelRef = ref<Client>({} as Client);
@ -89,25 +90,20 @@ export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
function handleSubmit() { function handleSubmit() {
return new Promise<any>((resolve, reject) => { return new Promise<any>((resolve, reject) => {
const formEl = unref(formElRef); const formEl = unref(formElRef);
formEl formEl.validate().then(() => {
.validate() const input = cloneDeep(unref(modelRef));
.then(() => { const api = isEdit.value
const input = cloneDeep(unref(modelRef)); ? update(input.id, Object.assign(input))
const api = isEdit.value : create(Object.assign(input));
? update(input.id, Object.assign(input)) api.then((res) => {
: create(Object.assign(input)); createMessage.success(L('Successful'));
api resolve(res);
.then((res) => { }).catch((error) => {
message.success(L('Successful'));
resolve(res);
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error); reject(error);
}); });
}).catch((error) => {
reject(error);
});
}); });
} }

86
apps/vue/src/views/identity-server/components/Properties.vue

@ -2,7 +2,7 @@
<div> <div>
<BasicTable <BasicTable
rowKey="key" rowKey="key"
:columns="columns" :columns="getDataColumns()"
:dataSource="properties" :dataSource="properties"
:pagination="false" :pagination="false"
:showTableSetting="true" :showTableSetting="true"
@ -38,8 +38,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { Button } from 'ant-design-vue'; import { Button } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form'; import { BasicForm, useForm } from '/@/components/Form';
import { BasicModal, useModal } from '/@/components/Modal'; import { BasicModal, useModal } from '/@/components/Modal';
@ -49,60 +49,38 @@
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
import { getFormSchemas } from './ModalData'; import { getFormSchemas } from './ModalData';
export default defineComponent({ const emits = defineEmits(['new', 'props-new', 'props-delete']);
name: 'Properties', defineProps({
components: { properties: {
BasicForm, type: [Array] as PropType<Property[]>,
BasicModal, required: true,
BasicTable, default: () => [],
Button,
TableAction,
}, },
props: { });
properties: {
type: [Array] as PropType<Property[]>,
required: true,
default: () => [],
},
},
emits: ['new', 'props-new', 'props-delete'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const title = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: getFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
function handleAddNew() { const { L } = useLocalization('AbpIdentityServer');
title.value = L('Propertites:New'); const title = ref('');
openModal(true); const [registerForm, { validate, resetFields }] = useForm({
} labelWidth: 120,
showActionButtonGroup: false,
schemas: getFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
function handleDelete(record) { function handleAddNew() {
emit('props-delete', record); title.value = L('Propertites:New');
} openModal(true);
}
function handleSubmit() { function handleDelete(record) {
validate().then((input) => { emits('props-delete', record);
emit('props-new', input); }
resetFields();
closeModal();
});
}
return { function handleSubmit() {
L, validate().then((input) => {
title, emits('props-new', input);
handleAddNew, resetFields();
handleDelete, closeModal();
handleSubmit, });
columns: getDataColumns(), }
registerForm,
registerModal,
};
},
});
</script> </script>

87
apps/vue/src/views/identity-server/components/UserClaim.vue

@ -9,59 +9,54 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { Transfer } from 'ant-design-vue'; import { Transfer } from 'ant-design-vue';
import { getActivedList } from '/@/api/identity/claim'; import { getActivedList } from '/@/api/identity/claim';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
export default defineComponent({ const emits = defineEmits(['change']);
name: 'UserClaim', const props = defineProps({
components: { Transfer }, targetClaims: {
props: { type: [Array] as PropType<string[]>,
targetClaims: { type: [Array] as PropType<string[]>, required: true, default: () => [] }, required: true,
listStyle: { type: Object, required: false }, default: () => [],
}, },
emits: ['change'], listStyle: {
setup(props, { emit }) { type: Object,
const { L } = useLocalization('AbpIdentityServer'); required: false,
const userClaims = ref< },
{ });
key: string;
title: string;
}[]
>([]);
const defaultListStyle = {
width: '48%',
height: '500px',
minHeight: '500px',
};
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
});
onMounted(() => { const { L } = useLocalization('AbpIdentityServer');
getActivedList().then((res) => { const userClaims = ref<
userClaims.value = res.items.map((item) => { {
return { key: string;
key: item.name, title: string;
title: item.name, }[]
}; >([]);
}); const defaultListStyle = {
}); width: '48%',
}); height: '500px',
minHeight: '500px',
};
function handleChange(targetKeys, direction, moveKeys) { const getListStyle = computed(() => {
emit('change', targetKeys, direction, moveKeys); return {...defaultListStyle, ...props.listStyle}
} });
return { onMounted(() => {
L, getActivedList().then((res) => {
getListStyle, userClaims.value = res.items.map((item) => {
userClaims, return {
handleChange, key: item.name,
}; title: item.name,
}, };
});
});
}); });
function handleChange(targetKeys, direction, moveKeys) {
emits('change', targetKeys, direction, moveKeys);
}
</script> </script>

140
apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceModal.vue

@ -13,8 +13,8 @@
ref="formElRef" ref="formElRef"
:model="modelRef" :model="modelRef"
:rules="formRules" :rules="formRules"
:label-col="labelCol" :label-col="{ span: 6 }"
:wrapper-col="wrapperCol" :wrapper-col="{ span: 18 }"
> >
<Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab"> <Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab">
<!-- Api 资源基本信息 --> <!-- Api 资源基本信息 -->
@ -59,13 +59,13 @@
</span> </span>
<template #overlay> <template #overlay>
<Menu @click="handleClickMenu"> <Menu @click="handleClickMenu">
<MenuItem key="properties">{{ L('Propertites') }}</MenuItem> <MenuItem key="Properties">{{ L('Propertites') }}</MenuItem>
</Menu> </Menu>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
<component <component
:is="advancedComponent" :is="componentsRef[advancedComponent]"
:properties="modelRef.properties" :properties="modelRef.properties"
@props-new="handleNewProperty" @props-new="handleNewProperty"
@props-delete="handleDeleteProperty" @props-delete="handleDeleteProperty"
@ -76,8 +76,9 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref, unref, shallowRef } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue'; import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue'; import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue';
@ -88,86 +89,57 @@
import { useProperty } from '../hooks/useProperty'; import { useProperty } from '../hooks/useProperty';
import UserClaim from '../../components/UserClaim.vue'; import UserClaim from '../../components/UserClaim.vue';
import Properties from '../../components/Properties.vue'; import Properties from '../../components/Properties.vue';
export default defineComponent({
name: 'IdentityResourceModal',
components: {
UserClaim,
Properties,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
Input,
Checkbox,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('properties');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) { const FormItem = Form.Item;
tabActivedKey.value = 'advanced'; const MenuItem = Menu.Item;
advancedComponent.value = e.key; const TabPane = Tabs.TabPane;
}
function handleOk() { const emits = defineEmits(['change', 'register']);
changeOkLoading(true);
handleSubmit() const componentsRef = shallowRef({
.then(() => { 'Properties': Properties,
emit('change'); });
})
.finally(() => {
changeOkLoading(false);
});
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization('AbpIdentityServer');
isEdit, const formElRef = ref<any>(null);
formElRef, const modelIdRef = ref('');
formRules, const tabActivedKey = ref('basic');
formTitle, const advancedComponent = ref('Properties');
tabActivedKey, const [registerModal, { changeOkLoading }] = useModalInner((val) => {
registerModal, modelIdRef.value = val.id;
modelRef,
advancedComponent,
labelCol: { span: 6 },
wrapperCol: { span: 18 },
handleClickMenu,
handleNewProperty,
handleDeleteProperty,
handleChangeTab,
handleVisibleModal,
handleOk,
targetClaims,
handleClaimChange,
};
},
}); });
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleOk() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
changeOkLoading(true);
handleSubmit().then(() => {
createMessage.success(L('Successful'));
emits('change');
}).finally(() => {
changeOkLoading(false);
});
});
}
</script> </script>

128
apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceTable.vue

@ -6,16 +6,20 @@
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'enabled'"> <template v-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly /> <CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'required'"> <template v-else-if="column.key === 'required'">
<Switch :checked="record.required" readonly /> <CheckOutlined v-if="record.required" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'emphasize'"> <template v-else-if="column.key === 'emphasize'">
<Switch :checked="record.emphasize" readonly /> <CheckOutlined v-if="record.emphasize" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'showInDiscoveryDocument'"> <template v-else-if="column.key === 'showInDiscoveryDocument'">
<Switch :checked="record.showInDiscoveryDocument" readonly /> <CheckOutlined v-if="record.showInDiscoveryDocument" class="enable" />
<CloseOutlined v-else class="disable" />
</template> </template>
<template v-else-if="column.key === 'actions'"> <template v-else-if="column.key === 'actions'">
<TableAction <TableAction
@ -42,9 +46,10 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { Button } from 'ant-design-vue';
import { Button, Modal, Switch } from 'ant-design-vue'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table'; import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
@ -54,70 +59,57 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import IdentityResourceModal from './IdentityResourceModal.vue'; import IdentityResourceModal from './IdentityResourceModal.vue';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'IdentityResourceTable', const { L } = useLocalization('AbpIdentityServer');
components: { IdentityResourceModal, BasicTable, Button, Switch, TableAction }, const [registerModal, { openModal, closeModal }] = useModal();
setup() { const [registerTable, { reload }] = useTable({
const { L } = useLocalization('AbpIdentityServer'); rowKey: 'id',
const [registerModal, { openModal, closeModal }] = useModal(); title: L('DisplayName:IdentityResources'),
const [registerTable, { reload }] = useTable({ columns: getDataColumns(),
rowKey: 'id', api: getList,
title: L('DisplayName:IdentityResources'), beforeFetch: formatPagedRequest,
columns: getDataColumns(), pagination: true,
api: getList, striped: false,
beforeFetch: formatPagedRequest, useSearchForm: true,
pagination: true, showTableSetting: true,
striped: false, bordered: true,
useSearchForm: true, showIndexColumn: false,
showTableSetting: true, canResize: true,
bordered: true, immediate: true,
showIndexColumn: false, canColDrag: true,
canResize: true, formConfig: getSearchFormSchemas(),
immediate: true, actionColumn: {
canColDrag: true, width: 200,
formConfig: getSearchFormSchemas(), title: L('Actions'),
actionColumn: { dataIndex: 'actions',
width: 200, },
title: L('Actions'), });
dataIndex: 'actions',
},
});
function handleAddNew() { function handleAddNew() {
openModal(true, {}); openModal(true, {});
} }
function handleEdit(record) { function handleEdit(record) {
openModal(true, record); openModal(true, record);
} }
function handleChange() { function handleChange() {
closeModal(); closeModal();
reload(); reload();
} }
function handleDelete(record) { function handleDelete(record) {
Modal.warning({ createConfirm({
title: L('AreYouSure'), iconType: 'warning',
content: L('ItemWillBeDeletedMessage'), title: L('AreYouSure'),
okCancel: true, content: L('ItemWillBeDeletedMessage'),
onOk: () => { okCancel: true,
deleteById(record.id).then(() => { onOk: () => {
reload(); deleteById(record.id).then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
}, reload();
}); });
} },
});
return { }
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
};
},
});
</script> </script>

28
apps/vue/src/views/identity-server/identity-resources/datas/TableData.ts

@ -11,6 +11,20 @@ export function getDataColumns(): BasicColumn[] {
width: 1, width: 1,
ifShow: false, ifShow: false,
}, },
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'center',
width: 150,
sorter: true,
},
{
title: L('Required'),
dataIndex: 'required',
align: 'center',
width: 150,
sorter: true,
},
{ {
title: L('Name'), title: L('Name'),
dataIndex: 'name', dataIndex: 'name',
@ -32,20 +46,6 @@ export function getDataColumns(): BasicColumn[] {
width: 180, width: 180,
sorter: true, sorter: true,
}, },
{
title: L('Required'),
dataIndex: 'required',
align: 'center',
width: 200,
sorter: true,
},
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'center',
width: 200,
sorter: true,
},
{ {
title: L('Emphasize'), title: L('Emphasize'),
dataIndex: 'emphasize', dataIndex: 'emphasize',

32
apps/vue/src/views/identity-server/identity-resources/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue'; import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation'; import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
} }
export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) { export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer'); const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation(); const { ruleCreator } = useValidation();
const modelRef = ref<IdentityResource>({} as IdentityResource); const modelRef = ref<IdentityResource>({} as IdentityResource);
@ -69,25 +70,20 @@ export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
function handleSubmit() { function handleSubmit() {
return new Promise<any>((resolve, reject) => { return new Promise<any>((resolve, reject) => {
const formEl = unref(formElRef); const formEl = unref(formElRef);
formEl formEl.validate().then(() => {
.validate() const input = cloneDeep(unref(modelRef));
.then(() => { const api = isEdit.value
const input = cloneDeep(unref(modelRef)); ? update(input.id, Object.assign(input))
const api = isEdit.value : create(Object.assign(input));
? update(input.id, Object.assign(input)) api.then((res) => {
: create(Object.assign(input)); createMessage.success(L('Successful'));
api resolve(res);
.then((res) => { }).catch((error) => {
message.success(L('Successful'));
resolve(res);
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error); reject(error);
}); });
}).catch((error) => {
reject(error);
});
}); });
} }

20
apps/vue/src/views/identity-server/persisted-grants/components/ModalData.ts

@ -1,4 +1,4 @@
import { h } from 'vue'; import { createVNode } from 'vue';
import { Input } from 'ant-design-vue'; import { Input } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { JsonPreview } from '/@/components/CodeEditor'; import { JsonPreview } from '/@/components/CodeEditor';
@ -35,7 +35,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:Key'), label: L('Grants:Key'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field], value: model[field],
readonly: true, readonly: true,
placeholder: '', placeholder: '',
@ -48,7 +48,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:Type'), label: L('Grants:Type'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field], value: model[field],
readonly: true, readonly: true,
placeholder: '', placeholder: '',
@ -61,7 +61,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:SubjectId'), label: L('Grants:SubjectId'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field], value: model[field],
readonly: true, readonly: true,
placeholder: '', placeholder: '',
@ -74,7 +74,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:SessionId'), label: L('Grants:SessionId'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field], value: model[field],
readonly: true, readonly: true,
placeholder: '', placeholder: '',
@ -87,7 +87,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Description'), label: L('Description'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field], value: model[field],
readonly: true, readonly: true,
placeholder: '', placeholder: '',
@ -100,7 +100,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('CreationTime'), label: L('CreationTime'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field] value: model[field]
? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss') ? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss')
: model[field], : model[field],
@ -115,7 +115,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Expiration'), label: L('Expiration'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field] value: model[field]
? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss') ? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss')
: model[field], : model[field],
@ -130,7 +130,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:ConsumedTime'), label: L('Grants:ConsumedTime'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(Input, { return createVNode(Input, {
value: model[field] value: model[field]
? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss') ? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss')
: model[field], : model[field],
@ -145,7 +145,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:Data'), label: L('Grants:Data'),
colProps: { span: 24 }, colProps: { span: 24 },
render: ({ model, field }) => { render: ({ model, field }) => {
return h(JsonPreview, { return createVNode(JsonPreview!, {
data: model[field] ? JSON.parse(model[field]) : {}, data: model[field] ? JSON.parse(model[field]) : {},
}); });
}, },

72
apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantModal.vue

@ -6,60 +6,42 @@
:width="660" :width="660"
:min-height="400" :min-height="400"
> >
<BasicForm <BasicForm @register="registerForm" />
ref="formElRef"
:model="persistedGrantRef"
:colon="true"
:schemas="formSchemas"
:label-width="120"
:show-action-button-group="false"
:action-col-options="{
span: 24,
}"
/>
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, watch, unref } from 'vue'; import { nextTick } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, FormActionType } from '/@/components/Form'; import { BasicForm, useForm } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { getModalFormSchemas } from './ModalData'; import { getModalFormSchemas } from './ModalData';
import { get } from '/@/api/identity-server/persistedGrants'; import { get } from '/@/api/identity-server/persistedGrants';
import { PersistedGrant } from '/@/api/identity-server/model/persistedGrantsModel';
export default defineComponent({
name: 'PersistedGrantModal',
components: { BasicForm, BasicModal },
emits: ['register'],
setup() {
const { L } = useLocalization('AbpIdentityServer');
const persistedGrantIdRef = ref('');
const persistedGrantRef = ref<PersistedGrant | null>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerModal] = useModalInner((val) => {
persistedGrantIdRef.value = val.id;
});
const formSchemas = getModalFormSchemas();
watch( defineEmits(['register']);
() => unref(persistedGrantIdRef),
(id) => {
const formEl = unref(formElRef);
formEl?.resetFields();
get(id).then((res) => {
persistedGrantRef.value = res;
});
},
);
return { const { L } = useLocalization('AbpIdentityServer');
L, const [registerForm, { resetFields, setFieldsValue }] = useForm({
formElRef, colon: true,
formSchemas, labelWidth: 120,
registerModal, showActionButtonGroup: false,
persistedGrantRef, actionColOptions: {
}; span: 24,
}, },
schemas: getModalFormSchemas(),
});
const [registerModal] = useModalInner((val) => {
nextTick(() => {
fetchPersistedGrant(val.id);
});
}); });
function fetchPersistedGrant(id?: string) {
resetFields();
if (id) {
get(id).then((res) => {
setFieldsValue(res);
});
}
}
</script> </script>

98
apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantTable.vue

@ -27,9 +27,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { useMessage } from '/@/hooks/web/useMessage';
import { Modal } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table'; import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
@ -39,59 +38,48 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import PersistedGrantModal from './PersistedGrantModal.vue'; import PersistedGrantModal from './PersistedGrantModal.vue';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'PersistedGrantTable', const { L } = useLocalization('AbpIdentityServer');
components: { BasicTable, TableAction, PersistedGrantModal }, const [registerModal, { openModal }] = useModal();
setup() { const [registerTable, { reload }] = useTable({
const { L } = useLocalization('AbpIdentityServer'); rowKey: 'id',
const [registerModal, { openModal }] = useModal(); title: L('DisplayName:PersistedGrants'),
const [registerTable, { reload }] = useTable({ columns: getDataColumns(),
rowKey: 'id', api: getList,
title: L('DisplayName:PersistedGrants'), beforeFetch: formatPagedRequest,
columns: getDataColumns(), pagination: true,
api: getList, striped: false,
beforeFetch: formatPagedRequest, useSearchForm: true,
pagination: true, showTableSetting: true,
striped: false, bordered: true,
useSearchForm: true, showIndexColumn: false,
showTableSetting: true, canResize: true,
bordered: true, immediate: true,
showIndexColumn: false, canColDrag: true,
canResize: true, formConfig: getSearchFormSchemas(),
immediate: true, actionColumn: {
canColDrag: true, width: 160,
formConfig: getSearchFormSchemas(), title: L('Actions'),
actionColumn: { dataIndex: 'actions',
width: 160, },
title: L('Actions'), });
dataIndex: 'actions',
},
});
function handleShow(record) { function handleShow(record) {
openModal(true, record); openModal(true, record);
} }
function handleDelete(record) { function handleDelete(record) {
Modal.warning({ createConfirm({
title: L('AreYouSure'), iconType: 'warning',
content: L('ItemWillBeDeletedMessage'), title: L('AreYouSure'),
okCancel: true, content: L('ItemWillBeDeletedMessage'),
onOk: () => { okCancel: true,
deleteById(record.id).then(() => { onOk: () => {
reload(); deleteById(record.id).then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
}, reload();
}); });
} },
});
return { }
L,
registerModal,
registerTable,
handleDelete,
handleShow,
};
},
});
</script> </script>

66
apps/vue/src/views/identity/claim-types/components/ClaimModal.vue

@ -21,48 +21,40 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref } from 'vue'; import { ref, unref } from 'vue';
import { BasicForm, FormActionType } from '/@/components/Form'; import { BasicForm, FormActionType } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { useClaimModal } from '../hooks/useClaimModal'; import { useClaimModal } from '../hooks/useClaimModal';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { IdentityClaimType } from '/@/api/identity/model/claimModel'; import { IdentityClaimType } from '/@/api/identity/model/claimModel';
export default defineComponent({
name: 'ClaimModal',
components: { BasicForm, BasicModal },
emits: ['change', 'register'],
setup(_props, { emit }) {
const submiting = ref(false);
const claimRef = ref<Nullable<IdentityClaimType>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerModal, { closeModal }] = useModalInner((val) => {
claimRef.value = val;
});
const { formTitle, formSchemas, handleSubmit } = useClaimModal({ claimRef, formElRef });
function handleSaveChanges() { const emits = defineEmits(['change', 'register']);
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
return { const { createMessage } = useMessage();
submiting, const { L } = useLocalization('AbpIdentity');
formElRef, const submiting = ref(false);
formTitle, const claimRef = ref<Nullable<IdentityClaimType>>(null);
formSchemas, const formElRef = ref<Nullable<FormActionType>>(null);
registerModal, const [registerModal, { closeModal }] = useModalInner((val) => {
handleSaveChanges, claimRef.value = val;
};
},
}); });
const { formTitle, formSchemas, handleSubmit } = useClaimModal({ claimRef, formElRef });
function handleSaveChanges() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
</script> </script>

48
apps/vue/src/views/identity/claim-types/components/ClaimTable.vue

@ -49,8 +49,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
@ -59,39 +58,16 @@
import { useClaimTable } from '../hooks/useClaimTable'; import { useClaimTable } from '../hooks/useClaimTable';
import ClaimModal from './ClaimModal.vue'; import ClaimModal from './ClaimModal.vue';
export default defineComponent({ const { L } = useLocalization('AbpIdentity');
name: 'ClaimTable', const { hasPermission } = usePermission();
components: { const [registerModal, { openModal }] = useModal();
BasicTable, const { valueTypeMap, registerTable, reloadTable, handleDelete } = useClaimTable();
ClaimModal,
CheckOutlined,
CloseOutlined,
TableAction,
},
setup() {
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const { valueTypeMap, registerTable, reloadTable, handleDelete } = useClaimTable();
return { function handleAddNew() {
L, openModal(true, {});
hasPermission, }
valueTypeMap,
registerTable, function handleEdit(record) {
reloadTable, openModal(true, record);
registerModal, }
openModal,
handleDelete,
};
},
methods: {
handleAddNew() {
this.openModal(true, {}, true);
},
handleEdit(record) {
this.openModal(true, record, true);
},
},
});
</script> </script>

9
apps/vue/src/views/identity/claim-types/hooks/useClaimTable.ts

@ -1,14 +1,15 @@
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useMessage } from '/@/hooks/web/useMessage';
import { useTable } from '/@/components/Table'; import { useTable } from '/@/components/Table';
import { deleteById, getList } from '/@/api/identity/claim'; import { deleteById, getList } from '/@/api/identity/claim';
import { ValueType } from '/@/api/identity/model/claimModel'; import { ValueType } from '/@/api/identity/model/claimModel';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getDataColumns } from '../datas/TableData'; import { getDataColumns } from '../datas/TableData';
import { getSearchFormSchemas } from '../datas/ModalData'; import { getSearchFormSchemas } from '../datas/ModalData';
import { Modal } from 'ant-design-vue';
export function useClaimTable() { export function useClaimTable() {
const { L } = useLocalization('AbpIdentity'); const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const valueTypeMap = { const valueTypeMap = {
[ValueType.String]: 'String', [ValueType.String]: 'String',
[ValueType.Int]: 'Int', [ValueType.Int]: 'Int',
@ -39,12 +40,14 @@ export function useClaimTable() {
}); });
function handleDelete(role) { function handleDelete(role) {
Modal.warning({ createConfirm({
iconType: 'warning',
title: L('AreYouSure'), title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [role.name] as Recordable), content: L('ItemWillBeDeletedMessageWithFormat', [role.name]),
okCancel: true, okCancel: true,
onOk: () => { onOk: () => {
deleteById(role.id).then(() => { deleteById(role.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadTable(); reloadTable();
}); });
}, },

2
apps/vue/src/views/identity/components/ClaimModal.vue

@ -151,7 +151,7 @@
onOk: () => { onOk: () => {
if (isFunction(props.deleteApi)) { if (isFunction(props.deleteApi)) {
props.deleteApi(identityRef.value, claim).then(() => { props.deleteApi(identityRef.value, claim).then(() => {
createMessage.success(L('Successful')); createMessage.success(L('SuccessfullyDeleted'));
reload(); reload();
}); });
} }

209
apps/vue/src/views/identity/components/MenuModal.vue

@ -41,8 +41,8 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref, watch } from 'vue'; import { ref, unref, watch } from 'vue';
import { Card, Form, Select, TreeSelect } from 'ant-design-vue'; import { Card, Form, Select, TreeSelect } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
@ -51,128 +51,103 @@
import { MenuListResult } from '/@/api/platform/model/menuModel'; import { MenuListResult } from '/@/api/platform/model/menuModel';
import { getAll } from '/@/api/platform/menu'; import { getAll } from '/@/api/platform/menu';
import { listToTree } from '/@/utils/helper/treeHelper'; import { listToTree } from '/@/utils/helper/treeHelper';
export default defineComponent({
name: 'MenuModal', const FormItem = Form.Item;
components: {
BasicModal, const emits = defineEmits(['change', 'change:startup', 'register']);
BasicTree, const props = defineProps({
Card, loading: {
Form, type: Boolean,
FormItem: Form.Item, default: false,
Select,
TreeSelect,
}, },
props: { getMenuApi: {
loading: { type: Function as PropType<(...args) => Promise<MenuListResult>>,
type: Boolean, required: true,
default: false, default: new Promise<MenuListResult>((resolve) => {
}, return resolve({
getMenuApi: { items: [],
type: Function as PropType<(...args) => Promise<MenuListResult>>, });
required: true, }),
default: new Promise<MenuListResult>((resolve) => {
return resolve({
items: [],
});
}),
},
}, },
emits: ['change', 'register', 'change:startup'], });
setup(props, { emit }) {
const { L } = useLocalization('AppPlatform');
const identityRef = ref('');
const frameworkRef = ref('');
const startupMenuRef = ref('');
const menuTreeRef = ref<any[]>([]);
const defaultCheckedRef = ref<any[]>([]);
const checkedRef = ref<string[]>([]);
const replaceFields = {
key: 'id',
title: 'displayName',
children: 'children',
value: 'id',
};
const optionsRef = ref<
{
key: string;
label: string;
value: string;
}[]
>([]);
const [registerModal, { changeOkLoading }] = useModalInner((record) => {
identityRef.value = record.identity;
optionsRef.value = [];
frameworkRef.value = '';
startupMenuRef.value = '';
checkedRef.value = [];
defaultCheckedRef.value = [];
menuTreeRef.value = [];
});
watch( const { L } = useLocalization('AppPlatform');
() => unref(props).loading, const identityRef = ref('');
(busy) => { const frameworkRef = ref('');
changeOkLoading(busy); const startupMenuRef = ref('');
}, const menuTreeRef = ref<any[]>([]);
); const defaultCheckedRef = ref<any[]>([]);
const checkedRef = ref<string[]>([]);
const replaceFields = {
key: 'id',
title: 'displayName',
children: 'children',
value: 'id',
};
const optionsRef = ref<
{
key: string;
label: string;
value: string;
}[]
>([]);
const [registerModal, { changeOkLoading }] = useModalInner((record) => {
identityRef.value = record.identity;
optionsRef.value = [];
frameworkRef.value = '';
startupMenuRef.value = '';
checkedRef.value = [];
defaultCheckedRef.value = [];
menuTreeRef.value = [];
});
function handleSelect(value) { watch(
getAll({ () => unref(props).loading,
filter: '', (busy) => {
sorting: '', changeOkLoading(busy);
framework: value, },
}).then((res) => { );
menuTreeRef.value = listToTree(res.items, { id: 'id', pid: 'parentId' });
});
props.getMenuApi(unref(identityRef), value).then((res) => {
checkedRef.value = res.items.map((item) => item.id);
defaultCheckedRef.value = checkedRef.value;
const startupMenu = res.items.find((item) => item.startup);
if (startupMenu) {
startupMenuRef.value = startupMenu.id;
}
});
}
function handleVisibleChange(visible) { function handleSelect(value) {
if (visible) { getAll({
getByName('UI Framework').then((res) => { filter: '',
optionsRef.value = res.items.map((item) => { sorting: '',
return { framework: value,
key: item.id, }).then((res) => {
label: item.displayName, menuTreeRef.value = listToTree(res.items, { id: 'id', pid: 'parentId' });
value: item.name, });
}; props.getMenuApi(unref(identityRef), value).then((res) => {
}); checkedRef.value = res.items.map((item) => item.id);
}); defaultCheckedRef.value = checkedRef.value;
} const startupMenu = res.items.find((item) => item.startup);
if (startupMenu) {
startupMenuRef.value = startupMenu.id;
} }
});
}
function handleCheck(checkedKeys) { function handleVisibleChange(visible) {
checkedRef.value = checkedKeys.checked; if (visible) {
} getByName('UI Framework').then((res) => {
optionsRef.value = res.items.map((item) => {
return {
key: item.id,
label: item.displayName,
value: item.name,
};
});
});
}
}
function handleSubmit() { function handleCheck(checkedKeys) {
emit('change', unref(identityRef), unref(checkedRef)); checkedRef.value = checkedKeys.checked;
if (unref(startupMenuRef)) { }
emit('change:startup', unref(identityRef), unref(startupMenuRef));
}
}
return { function handleSubmit() {
L, emits('change', unref(identityRef), unref(checkedRef));
menuTreeRef, if (unref(startupMenuRef)) {
defaultCheckedRef, emits('change:startup', unref(identityRef), unref(startupMenuRef));
replaceFields, }
frameworkRef, }
startupMenuRef,
optionsRef,
registerModal,
handleSelect,
handleVisibleChange,
handleCheck,
handleSubmit,
};
},
});
</script> </script>

188
apps/vue/src/views/identity/organization-units/components/MemberModal.vue

@ -18,8 +18,9 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, unref } from 'vue'; import { computed, ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Input } from 'ant-design-vue'; import { Input } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
@ -27,106 +28,93 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { addMembers, getUnaddedMemberList } from '/@/api/identity/organization-units'; import { addMembers, getUnaddedMemberList } from '/@/api/identity/organization-units';
export default defineComponent({ const InputSearch = Input.Search;
name: 'MemberModal',
components: { BasicModal, BasicTable, InputSearch: Input.Search },
props: {
ouId: { type: String },
},
emits: ['change', 'register'],
setup(props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const loading = ref(false);
const filter = ref('');
const tableRef = ref<Nullable<TableActionType>>(null);
const [registerModal, { closeModal }] = useModalInner();
const dataColumns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('DisplayName:UserName'),
dataIndex: 'userName',
align: 'left',
width: 280,
sorter: true,
},
{
title: L('EmailAddress'),
dataIndex: 'email',
align: 'left',
width: 'auto',
sorter: true,
},
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
});
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedMemberList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
});
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
function handleSubmit() { const emits = defineEmits(['change', 'register']);
const tableEl = unref(tableRef); const props = defineProps({
const selectRows = tableEl?.getSelectRows(); ouId: { type: String },
if (selectRows) { });
loading.value = true;
addMembers(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization('AbpIdentity');
filter, const loading = ref(false);
loading, const filter = ref('');
tableRef, const tableRef = ref<Nullable<TableActionType>>(null);
registerModal, const [registerModal, { closeModal }] = useModalInner();
registerTable, const dataColumns: BasicColumn[] = [
handleVisibleChange, {
handleSearch, title: 'id',
handleSubmit, dataIndex: 'id',
}; width: 1,
ifShow: false,
},
{
title: L('DisplayName:UserName'),
dataIndex: 'userName',
align: 'left',
width: 280,
sorter: true,
}, },
{
title: L('EmailAddress'),
dataIndex: 'email',
align: 'left',
width: 'auto',
sorter: true,
},
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
});
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedMemberList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
}); });
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
function handleSubmit() {
const tableEl = unref(tableRef);
const selectRows = tableEl?.getSelectRows();
if (selectRows) {
loading.value = true;
addMembers(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
</script> </script>

63
apps/vue/src/views/identity/organization-units/components/MemberTable.vue

@ -30,8 +30,8 @@
<MemberModal @register="registerModal" :ou-id="ouId" @change="handleChange" /> <MemberModal @register="registerModal" :ou-id="ouId" @change="handleChange" />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, unref } from 'vue'; import { computed, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, TableAction } from '/@/components/Table'; import { BasicTable, TableAction } from '/@/components/Table';
@ -40,44 +40,29 @@
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import MemberModal from './MemberModal.vue'; import MemberModal from './MemberModal.vue';
export default defineComponent({ const props = defineProps({
name: 'MemberTable', ouId: { type: String },
components: { BasicTable, MemberModal, TableAction }, });
props: {
ouId: { type: String },
},
setup(props) {
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addMemberEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageUsers');
});
const { registerTable, reloadMembers, handleDelete } = useMemberTable({ getProps });
const [registerModal, { openModal }] = useModal();
function handleAddNew() { const { L } = useLocalization('AbpIdentity');
openModal(); const { hasPermission } = usePermission();
} const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addMemberEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageUsers');
});
const { registerTable, reloadMembers, handleDelete } = useMemberTable({ getProps });
const [registerModal, { openModal }] = useModal();
function handleChange() { function handleAddNew() {
reloadMembers(); openModal();
} }
return { function handleChange() {
L, reloadMembers();
addMemberEnabled, }
registerTable,
handleChange,
handleDelete,
registerModal,
handleAddNew,
};
},
});
</script> </script>

38
apps/vue/src/views/identity/organization-units/components/OrganizationUnitPage.vue

@ -18,41 +18,21 @@
</Row> </Row>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Card, Row, Col, Tabs } from 'ant-design-vue'; import { Card, Row, Col, Tabs } from 'ant-design-vue';
import OrganizationUnitTree from './OrganizationUnitTree.vue'; import OrganizationUnitTree from './OrganizationUnitTree.vue';
import MemberTable from './MemberTable.vue'; import MemberTable from './MemberTable.vue';
import RoleTable from './RoleTable.vue'; import RoleTable from './RoleTable.vue';
export default defineComponent({ const TabPane = Tabs.TabPane;
name: 'OrganizationUnitPage',
components: {
OrganizationUnitTree,
Card,
Col,
MemberTable,
Row,
RoleTable,
Tabs,
TabPane: Tabs.TabPane,
},
setup() {
const { L } = useLocalization('AbpIdentity');
const activeKey = ref('members');
const ouIdRef = ref('');
function handleSelect(key) { const { L } = useLocalization('AbpIdentity');
ouIdRef.value = key; const activeKey = ref('members');
} const ouIdRef = ref('');
return { function handleSelect(key) {
L, ouIdRef.value = key;
activeKey, }
ouIdRef,
handleSelect,
};
},
});
</script> </script>

47
apps/vue/src/views/identity/organization-units/components/OrganizationUnitTree.vue

@ -29,8 +29,7 @@
</Card> </Card>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import { Card } from 'ant-design-vue'; import { Card } from 'ant-design-vue';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
@ -40,36 +39,18 @@
import { PermissionModal } from '/@/components/Permission'; import { PermissionModal } from '/@/components/Permission';
import OrganizationUnitModal from './OrganizationUnitModal.vue'; import OrganizationUnitModal from './OrganizationUnitModal.vue';
export default defineComponent({ const emits = defineEmits(['change', 'select']);
name: 'OrganizationUnitTree',
components: { BasicTree, Card, OrganizationUnitModal, PermissionModal },
emits: ['change', 'select'],
setup(_props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const [registerModal, modalMethods] = useModal();
const [registerPermissionModal, permissionModalMethods] = useModal();
const {
ouTree,
getContentMenus,
handleDrop,
handleAddNew,
handleSelect,
loadOuTree,
} = useOuTree({ emit, modalMethods, permissionModalMethods });
const { hasPermission } = usePermission();
return { const { L } = useLocalization('AbpIdentity');
L, const [registerModal, modalMethods] = useModal();
ouTree, const [registerPermissionModal, permissionModalMethods] = useModal();
loadOuTree, const {
registerModal, ouTree,
getContentMenus, getContentMenus,
hasPermission, handleDrop,
handleDrop, handleAddNew,
handleAddNew, handleSelect,
handleSelect, loadOuTree,
registerPermissionModal, } = useOuTree({ emit: emits, modalMethods, permissionModalMethods });
}; const { hasPermission } = usePermission();
},
});
</script> </script>

174
apps/vue/src/views/identity/organization-units/components/RoleModal.vue

@ -18,8 +18,9 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, unref } from 'vue'; import { computed, ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Input } from 'ant-design-vue'; import { Input } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
@ -27,99 +28,86 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { addRoles, getUnaddedRoleList } from '/@/api/identity/organization-units'; import { addRoles, getUnaddedRoleList } from '/@/api/identity/organization-units';
export default defineComponent({ const InputSearch = Input.Search;
name: 'RoleModal',
components: { BasicModal, BasicTable, InputSearch: Input.Search },
props: {
ouId: { type: String },
},
emits: ['change', 'register'],
setup(props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const loading = ref(false);
const filter = ref('');
const tableRef = ref<Nullable<TableActionType>>(null);
const [registerModal, { closeModal }] = useModalInner();
const dataColumns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('RoleName'),
dataIndex: 'name',
align: 'left',
width: 'auto',
sorter: true,
},
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
});
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedRoleList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
});
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
function handleSubmit() { const emits = defineEmits(['change', 'register']);
const tableEl = unref(tableRef); const props = defineProps({
const selectRows = tableEl?.getSelectRows(); ouId: { type: String },
if (selectRows) { });
loading.value = true;
addRoles(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization('AbpIdentity');
filter, const loading = ref(false);
loading, const filter = ref('');
tableRef, const tableRef = ref<Nullable<TableActionType>>(null);
registerModal, const [registerModal, { closeModal }] = useModalInner();
registerTable, const dataColumns: BasicColumn[] = [
handleVisibleChange, {
handleSearch, title: 'id',
handleSubmit, dataIndex: 'id',
}; width: 1,
ifShow: false,
},
{
title: L('RoleName'),
dataIndex: 'name',
align: 'left',
width: 'auto',
sorter: true,
}, },
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
}); });
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedRoleList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
});
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
function handleSubmit() {
const tableEl = unref(tableRef);
const selectRows = tableEl?.getSelectRows();
if (selectRows) {
loading.value = true;
addRoles(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
</script> </script>

63
apps/vue/src/views/identity/organization-units/components/RoleTable.vue

@ -30,8 +30,8 @@
<RoleModal @register="registerModal" :ou-id="ouId" @change="handleChange" /> <RoleModal @register="registerModal" :ou-id="ouId" @change="handleChange" />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, unref } from 'vue'; import { computed, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, TableAction } from '/@/components/Table'; import { BasicTable, TableAction } from '/@/components/Table';
@ -40,44 +40,29 @@
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import RoleModal from './RoleModal.vue'; import RoleModal from './RoleModal.vue';
export default defineComponent({ const props = defineProps({
name: 'RoleTable', ouId: { type: String },
components: { BasicTable, RoleModal, TableAction }, });
props: {
ouId: { type: String },
},
setup(props) {
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addRoleEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageRoles');
});
const { registerTable, reloadRoles, handleDelete } = useRoleTable({ getProps });
const [registerModal, { openModal }] = useModal();
function handleAddNew() { const { L } = useLocalization('AbpIdentity');
openModal(); const { hasPermission } = usePermission();
} const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addRoleEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageRoles');
});
const { registerTable, reloadRoles, handleDelete } = useRoleTable({ getProps });
const [registerModal, { openModal }] = useModal();
function handleChange() { function handleAddNew() {
reloadRoles(); openModal();
} }
return { function handleChange() {
L, reloadRoles();
addRoleEnabled, }
registerTable,
registerModal,
handleDelete,
handleAddNew,
handleChange,
};
},
});
</script> </script>

14
apps/vue/src/views/identity/organization-units/hooks/useMemberTable.ts

@ -1,6 +1,6 @@
import { ComputedRef } from 'vue'; import type { ComputedRef } from 'vue';
import { Modal } from 'ant-design-vue';
import { watch, ref, unref } from 'vue'; import { watch, ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicColumn, useTable } from '/@/components/Table'; import { BasicColumn, useTable } from '/@/components/Table';
import { User } from '/@/api/identity/model/userModel'; import { User } from '/@/api/identity/model/userModel';
@ -14,6 +14,7 @@ interface UseMemberTable {
export function useMemberTable({ getProps }: UseMemberTable) { export function useMemberTable({ getProps }: UseMemberTable) {
const { L } = useLocalization('AbpIdentity'); const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const dataSource = ref([] as User[]); const dataSource = ref([] as User[]);
const dataColumns: BasicColumn[] = [ const dataColumns: BasicColumn[] = [
{ {
@ -61,12 +62,17 @@ export function useMemberTable({ getProps }: UseMemberTable) {
}); });
function handleDelete(user) { function handleDelete(user) {
Modal.warning({ createConfirm({
iconType: 'warning',
title: L('AreYouSure'), title: L('AreYouSure'),
content: L('OrganizationUnit:AreYouSureRemoveUser', [user.userName] as Recordable), content: L('OrganizationUnit:AreYouSureRemoveUser', [user.userName] as Recordable),
okCancel: true, okCancel: true,
onOk: () => { onOk: () => {
removeOrganizationUnit(user.id, unref(getProps).ouId).then(() => reloadMembers()); removeOrganizationUnit(user.id, unref(getProps).ouId)
.then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadMembers();
});
}, },
}); });
} }

6
apps/vue/src/views/identity/organization-units/hooks/useOuTree.ts

@ -1,5 +1,4 @@
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { Modal } from 'ant-design-vue';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
@ -13,7 +12,7 @@ export function useOuTree({ emit, modalMethods, permissionModalMethods }:
modalMethods: ReturnMethods, modalMethods: ReturnMethods,
permissionModalMethods: ReturnMethods, permissionModalMethods: ReturnMethods,
}) { }) {
const { createMessage } = useMessage(); const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AbpIdentity']); const { L } = useLocalization(['AbpIdentity']);
const { hasPermission } = usePermission(); const { hasPermission } = usePermission();
const ouTree = ref<any[]>([]); const ouTree = ref<any[]>([]);
@ -38,7 +37,8 @@ export function useOuTree({ emit, modalMethods, permissionModalMethods }:
{ {
label: L('Delete'), label: L('Delete'),
handler: () => { handler: () => {
Modal.warning({ createConfirm({
iconType: 'warning',
title: L('AreYouSure'), title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'), content: L('ItemWillBeDeletedMessage'),
okCancel: true, okCancel: true,

12
apps/vue/src/views/identity/organization-units/hooks/useRoleTable.ts

@ -1,7 +1,7 @@
import { ComputedRef } from 'vue'; import { ComputedRef } from 'vue';
import { Modal } from 'ant-design-vue';
import { ref, unref, watch } from 'vue'; import { ref, unref, watch } from 'vue';
import { useTable } from '/@/components/Table'; import { useTable } from '/@/components/Table';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { getDataColumns } from '../../role/datas/TableData'; import { getDataColumns } from '../../role/datas/TableData';
import { Role } from '/@/api/identity/model/roleModel'; import { Role } from '/@/api/identity/model/roleModel';
@ -15,6 +15,7 @@ interface UseRoleTable {
export function useRoleTable({ getProps }: UseRoleTable) { export function useRoleTable({ getProps }: UseRoleTable) {
const { L } = useLocalization('AbpIdentity'); const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const dataSource = ref([] as Role[]); const dataSource = ref([] as Role[]);
const [registerTable] = useTable({ const [registerTable] = useTable({
rowKey: 'id', rowKey: 'id',
@ -40,12 +41,17 @@ export function useRoleTable({ getProps }: UseRoleTable) {
}); });
function handleDelete(role) { function handleDelete(role) {
Modal.warning({ createConfirm({
iconType: 'warning',
title: L('AreYouSure'), title: L('AreYouSure'),
content: L('OrganizationUnit:AreYouSureRemoveRole', [role.name] as Recordable), content: L('OrganizationUnit:AreYouSureRemoveRole', [role.name] as Recordable),
okCancel: true, okCancel: true,
onOk: () => { onOk: () => {
removeOrganizationUnit(role.id, unref(getProps).ouId).then(() => reloadRoles()); removeOrganizationUnit(role.id, unref(getProps).ouId)
.then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadRoles();
});
}, },
}); });
} }

1
apps/vue/src/views/identity/organization-units/index.vue

@ -7,6 +7,7 @@
import OrganizationUnitPage from './components/OrganizationUnitPage.vue'; import OrganizationUnitPage from './components/OrganizationUnitPage.vue';
export default defineComponent({ export default defineComponent({
name: 'OrganizationUnits',
components: { OrganizationUnitPage }, components: { OrganizationUnitPage },
}); });
</script> </script>

61
apps/vue/src/views/identity/role/components/ClaimModal.vue

@ -42,50 +42,33 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicTable, TableAction } from '/@/components/Table'; import { BasicTable, TableAction } from '/@/components/Table';
import { BasicModalForm } from '/@/components/ModalForm'; import { BasicModalForm } from '/@/components/ModalForm';
import { useClaim } from '../hooks/useClaim'; import { useClaim } from '../hooks/useClaim';
export default defineComponent({ const { L } = useLocalization('AbpIdentity');
name: 'RoleClaimModal', const roleIdRef = ref('');
components: { BasicModal, BasicTable, BasicModalForm, TableAction }, const [registerModal] = useModalInner((val) => {
setup() { roleIdRef.value = val.id;
const { L } = useLocalization('AbpIdentity');
const roleIdRef = ref('');
const [registerModal] = useModalInner((val) => {
roleIdRef.value = val.id;
});
const {
formSchemas,
registerClaimForm,
openClaimForm,
registerTable,
handleDelete,
handleSaveChanges,
} = useClaim({ roleIdRef });
return {
L,
formSchemas,
registerModal,
registerTable,
registerClaimForm,
openClaimForm,
handleDelete,
handleSaveChanges,
};
},
methods: {
handleAddNew() {
this.openClaimForm({});
},
handleEdit(record) {
this.openClaimForm(record);
},
},
}); });
const {
formSchemas,
registerClaimForm,
openClaimForm,
registerTable,
handleDelete,
handleSaveChanges,
} = useClaim({ roleIdRef });
function handleAddNew() {
openClaimForm({});
}
function handleEdit(record) {
openClaimForm(record);
}
</script> </script>

66
apps/vue/src/views/identity/role/components/RoleModal.vue

@ -19,48 +19,40 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref } from 'vue'; import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, FormActionType } from '/@/components/Form'; import { BasicForm, FormActionType } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { useRoleModal } from '../hooks/useRoleModal'; import { useRoleModal } from '../hooks/useRoleModal';
import { Role } from '/@/api/identity/model/roleModel'; import { Role } from '/@/api/identity/model/roleModel';
export default defineComponent({
name: '',
components: { BasicForm, BasicModal },
emits: ['change', 'register'],
setup(_props, { emit }) {
const submiting = ref(false);
const roleRef = ref<Nullable<Role>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerModal, { closeModal }] = useModalInner((val) => {
roleRef.value = val;
});
const { formTitle, formSchemas, handleSubmit } = useRoleModal({ roleRef, formElRef });
function handleSaveChanges() { const emits = defineEmits(['change', 'register']);
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
return { const submiting = ref(false);
submiting, const roleRef = ref<Nullable<Role>>(null);
formElRef, const formElRef = ref<Nullable<FormActionType>>(null);
formTitle, const { createMessage } = useMessage();
formSchemas, const { L } = useLocalization('AbpIdentity');
registerModal, const [registerModal, { closeModal }] = useModalInner((val) => {
handleSaveChanges, roleRef.value = val;
};
},
}); });
const { formTitle, formSchemas, handleSubmit } = useRoleModal({ roleRef, formElRef });
function handleSaveChanges() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
</script> </script>

115
apps/vue/src/views/identity/role/components/RoleTable.vue

@ -75,8 +75,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { Tag } from 'ant-design-vue'; import { Tag } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
@ -91,86 +91,45 @@
import MenuModal from '../../components/MenuModal.vue'; import MenuModal from '../../components/MenuModal.vue';
import ClaimModal from '../../components/ClaimModal.vue'; import ClaimModal from '../../components/ClaimModal.vue';
export default defineComponent({ const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
name: 'RoleTable', const loadMenuRef = ref(false);
components: { const { hasPermission } = usePermission();
BasicTable, const [registerModal, { openModal }] = useModal();
ClaimModal, const [registerClaimModal, { openModal: openClaimModal }] = useModal();
MenuModal, const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
RoleModal, useModal();
Tag, const { registerTable, reloadTable, handleDelete } = useRoleTable();
TableAction, const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
PermissionModal,
},
setup() {
const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
const loadMenuRef = ref(false);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
useModal();
const { registerTable, reloadTable, handleDelete } = useRoleTable();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
function handleSetMenu(record) { function handleSetMenu(record) {
openMenuModal(true, { identity: record.name }, true); openMenuModal(true, { identity: record.name }, true);
} }
function handleChangeMenu(roleName, menuIds) { function handleChangeMenu(roleName, menuIds) {
loadMenuRef.value = true; loadMenuRef.value = true;
setRoleMenu({ setRoleMenu({
roleName: roleName, roleName: roleName,
menuIds: menuIds, menuIds: menuIds,
}) }).then(() => {
.then(() => { closeMenuModal();
closeMenuModal(); }).finally(() => {
}) loadMenuRef.value = false;
.finally(() => { });
loadMenuRef.value = false; }
});
}
function handleChangeStartupMenu(roleName, meunId) { function handleChangeStartupMenu(roleName, meunId) {
setRoleStartupMenu(roleName, meunId); setRoleStartupMenu(roleName, meunId);
} }
function handleAddNew() { function handleAddNew() {
openModal(true, {}, true); openModal(true, {}, true);
} }
function handleEdit(record) { function handleEdit(record) {
openModal(true, record, true); openModal(true, record, true);
} }
function handleShowClaims(record) { function handleShowClaims(record) {
openClaimModal(true, { id: record.id }); openClaimModal(true, { id: record.id });
} }
return {
L,
loadMenuRef,
hasPermission,
registerTable,
reloadTable,
registerModal,
registerClaimModal,
handleShowClaims,
registerPermissionModal,
showPermissionModal,
registerMenuModal,
handleAddNew,
handleEdit,
handleSetMenu,
handleDelete,
handleChangeMenu,
handleChangeStartupMenu,
getListByRole,
getRoleClaims,
createClaim,
updateClaim,
deleteClaim,
};
},
});
</script> </script>

15
apps/vue/src/views/identity/role/hooks/useClaim.ts

@ -1,7 +1,6 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Modal } from 'ant-design-vue';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import { getActivedList } from '/@/api/identity/claim'; import { getActivedList } from '/@/api/identity/claim';
@ -16,6 +15,7 @@ interface UseClaim {
// TODO: 与UserClaim重复 需要分离组件 // TODO: 与UserClaim重复 需要分离组件
export function useClaim({ roleIdRef }: UseClaim) { export function useClaim({ roleIdRef }: UseClaim) {
const { L } = useLocalization('AbpIdentity'); const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const formSchemas: FormSchema[] = [ const formSchemas: FormSchema[] = [
{ {
field: 'id', field: 'id',
@ -102,14 +102,17 @@ export function useClaim({ roleIdRef }: UseClaim) {
} }
function handleDelete(claim) { function handleDelete(claim) {
Modal.warning({ createConfirm({
iconType: 'warning',
title: L('AreYouSure'), title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [claim.claimValue] as Recordable), content: L('ItemWillBeDeletedMessageWithFormat', [claim.claimValue] as Recordable),
okCancel: true, okCancel: true,
onOk: () => { onOk: () => {
deleteClaim(unref(roleIdRef), claim).then(() => { deleteClaim(unref(roleIdRef), claim)
reloadTable(); .then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
reloadTable();
});
}, },
}); });
} }

7
apps/vue/src/views/identity/role/hooks/useRoleTable.ts

@ -1,13 +1,14 @@
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useMessage } from '/@/hooks/web/useMessage';
import { useTable } from '/@/components/Table'; import { useTable } from '/@/components/Table';
import { deleteById, getList } from '/@/api/identity/role'; import { deleteById, getList } from '/@/api/identity/role';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getDataColumns } from '../datas/TableData'; import { getDataColumns } from '../datas/TableData';
import { getSearchFormSchemas } from '../datas/ModalData'; import { getSearchFormSchemas } from '../datas/ModalData';
import { Modal } from 'ant-design-vue';
export function useRoleTable() { export function useRoleTable() {
const { L } = useLocalization('AbpIdentity'); const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const [registerTable, { reload: reloadTable }] = useTable({ const [registerTable, { reload: reloadTable }] = useTable({
rowKey: 'id', rowKey: 'id',
title: L('Roles'), title: L('Roles'),
@ -32,12 +33,14 @@ export function useRoleTable() {
}); });
function handleDelete(role) { function handleDelete(role) {
Modal.warning({ createConfirm({
iconType: 'warning',
title: L('AreYouSure'), title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [role.name] as Recordable), content: L('ItemWillBeDeletedMessageWithFormat', [role.name] as Recordable),
okCancel: true, okCancel: true,
onOk: () => { onOk: () => {
deleteById(role.id).then(() => { deleteById(role.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadTable(); reloadTable();
}); });
}, },

90
apps/vue/src/views/identity/security-logs/components/SecurityLogTable.vue

@ -18,9 +18,8 @@
</BasicTable> </BasicTable>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { useMessage } from '/@/hooks/web/useMessage';
import { Modal } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table'; import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
@ -28,53 +27,44 @@
import { deleteById, getList } from '/@/api/identity/securityLog'; import { deleteById, getList } from '/@/api/identity/securityLog';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'SecurityLogTable', const { L } = useLocalization('AbpAuditLogging');
components: { BasicTable, TableAction }, const [registerTable, { reload }] = useTable({
setup() { rowKey: 'id',
const { L } = useLocalization('AbpAuditLogging'); title: L('SecurityLog'),
const [registerTable, { reload }] = useTable({ columns: getDataColumns(),
rowKey: 'id', api: getList,
title: L('SecurityLog'), beforeFetch: formatPagedRequest,
columns: getDataColumns(), pagination: true,
api: getList, striped: false,
beforeFetch: formatPagedRequest, useSearchForm: true,
pagination: true, showTableSetting: true,
striped: false, bordered: true,
useSearchForm: true, showIndexColumn: false,
showTableSetting: true, canResize: true,
bordered: true, immediate: true,
showIndexColumn: false, canColDrag: true,
canResize: true, formConfig: getSearchFormSchemas(),
immediate: true, scroll: { x: 'max-content', y: '100%' },
canColDrag: true, actionColumn: {
formConfig: getSearchFormSchemas(), width: 120,
scroll: { x: 'max-content', y: '100%' }, title: L('Actions'),
actionColumn: { dataIndex: 'actions',
width: 120,
title: L('Actions'),
dataIndex: 'actions',
},
});
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
});
}
return {
L,
registerTable,
handleDelete,
};
}, },
}); });
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
},
});
}
</script> </script>

45
apps/vue/src/views/identity/user/components/LockModal.vue

@ -7,39 +7,30 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref } from 'vue'; import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModalForm } from '/@/components/ModalForm'; import { BasicModalForm } from '/@/components/ModalForm';
import { useModalInner } from '/@/components/Modal'; import { useModalInner } from '/@/components/Modal';
import { useLock } from '../hooks/useLock'; import { useLock } from '../hooks/useLock';
export default defineComponent({ const emits = defineEmits(['change', 'register']);
name: 'LockModal',
components: { BasicModalForm },
emits: ['change', 'register'],
setup(_props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const userIdRef = ref('');
const { formSchemas, handleLock } = useLock({ emit });
const [registerModal, { closeModal }] = useModalInner((val) => {
userIdRef.value = val.userId;
});
function handleSaveChanges(input) {
return handleLock(unref(userIdRef), input).then(() => {
closeModal();
});
}
return { const { L } = useLocalization('AbpIdentity');
L, const { createMessage } = useMessage();
formSchemas, const userIdRef = ref('');
handleLock, const { formSchemas, handleLock } = useLock({ emit: emits });
handleSaveChanges, const [registerModal, { closeModal }] = useModalInner((val) => {
registerModal, userIdRef.value = val.userId;
};
},
}); });
function handleSaveChanges(input) {
return handleLock(unref(userIdRef), input)
.then(() => {
createMessage.success(L('Successful'));
closeModal();
});
}
</script> </script>

75
apps/vue/src/views/identity/user/components/PasswordModal.vue

@ -9,57 +9,42 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref } from 'vue'; import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm, FormActionType } from '/@/components/Form'; import { BasicForm, useForm, FormActionType } from '/@/components/Form';
import { usePassword } from '../hooks/usePassword'; import { usePassword } from '../hooks/usePassword';
import { changePassword } from '/@/api/identity/user'; import { changePassword } from '/@/api/identity/user';
export default defineComponent({ const { createMessage } = useMessage();
name: 'PasswordModal', const { L } = useLocalization('AbpIdentity');
components: { BasicModal, BasicForm }, const userIdRef = ref('');
setup() { const formElRef = ref<Nullable<FormActionType>>(null);
const { L } = useLocalization('AbpIdentity'); const { formSchemas } = usePassword(formElRef);
const userIdRef = ref(''); const [registerModal, { closeModal }] = useModalInner((val) => {
const formElRef = ref<Nullable<FormActionType>>(null); userIdRef.value = val;
const { formSchemas } = usePassword(formElRef); });
const [registerModal, { closeModal }] = useModalInner((val) => { const [registerForm, { validate }] = useForm({
userIdRef.value = val; schemas: formSchemas,
}); showActionButtonGroup: false,
const [registerForm, { getFieldsValue, validate }] = useForm({ actionColOptions: {
schemas: formSchemas, span: 24,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
function handleSubmit() {
const userId = unref(userIdRef);
if (userId) {
validate().then((res) => {
changePassword(userId, {
password: res.password,
}).then(() => {
closeModal();
});
});
}
}
return {
L,
formElRef,
registerModal,
closeModal,
registerForm,
getFieldsValue,
validate,
userIdRef,
handleSubmit,
};
}, },
}); });
function handleSubmit() {
const userId = unref(userIdRef);
if (userId) {
validate().then((res) => {
changePassword(userId, {
password: res.password,
}).then(() => {
createMessage.success(L('Successful'));
closeModal();
});
});
}
}
</script> </script>

91
apps/vue/src/views/identity/user/components/UserModal.vue

@ -62,72 +62,49 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { message, Checkbox, Input, Form, Tabs, Transfer } from 'ant-design-vue'; import { Checkbox, Input, Form, Tabs, Transfer } from 'ant-design-vue';
import { Input as BInput } from '/@/components/Input'; import { Input as BInput } from '/@/components/Input';
import { FormActionType } from '/@/components/Form'; import { FormActionType } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { useUserForm } from '../hooks/useUserForm'; import { useUserForm } from '../hooks/useUserForm';
export default defineComponent({ const FormItem = Form.Item;
name: 'UserModal', const TabPane = Tabs.TabPane;
components: { const InputPassword = Input.Password;
BasicModal,
Checkbox,
Form,
FormItem: Form.Item,
Tabs,
TabPane: Tabs.TabPane,
BInput,
InputPassword: Input.Password,
Transfer,
},
emits: ['register', 'change'],
setup(_, { emit }) {
const { L } = useLocalization(['AbpIdentity', 'AbpIdentityServer']);
const activedTab = ref('info');
const userRef = ref<Recordable>({});
const formElRef = ref<Nullable<FormActionType>>(null);
const { handleSubmit, getUser, userTitle, formRules, roleDataSource, handleRoleChange } =
useUserForm({
userRef,
formElRef,
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner(async (val) => {
activedTab.value = 'info';
getUser(val.id);
});
function handleOk() { const emits = defineEmits(['register', 'change']);
changeOkLoading(true);
handleSubmit()
.then((res) => {
message.success(L('Successful'));
closeModal();
emit('change', res);
})
.finally(() => {
changeOkLoading(false);
});
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization(['AbpIdentity', 'AbpIdentityServer']);
activedTab, const activedTab = ref('info');
userRef, const userRef = ref<Recordable>({});
formElRef, const formElRef = ref<Nullable<FormActionType>>(null);
formRules, const { handleSubmit, getUser, userTitle, formRules, roleDataSource, handleRoleChange } =
roleDataSource, useUserForm({
handleRoleChange, userRef,
userTitle, formElRef,
handleOk, });
registerModal, const [registerModal, { closeModal, changeOkLoading }] = useModalInner(async (val) => {
closeModal, activedTab.value = 'info';
}; getUser(val.id);
},
}); });
function handleOk() {
changeOkLoading(true);
handleSubmit()
.then((res) => {
createMessage.success(L('Successful'));
closeModal();
emits('change', res);
})
.finally(() => {
changeOkLoading(false);
});
}
</script> </script>
<style scoped> <style scoped>

141
apps/vue/src/views/identity/user/components/UserTable.vue

@ -106,8 +106,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { Tag } from 'ant-design-vue'; import { Tag } from 'ant-design-vue';
@ -126,105 +126,56 @@
import MenuModal from '../../components/MenuModal.vue'; import MenuModal from '../../components/MenuModal.vue';
import ClaimModal from '../../components/ClaimModal.vue'; import ClaimModal from '../../components/ClaimModal.vue';
export default defineComponent({ const emits = defineEmits(['change']);
name: 'UserTable',
components: {
BasicTable,
ClaimModal,
PermissionModal,
TableAction,
Tag,
UserModal,
PasswordModal,
LockModal,
MenuModal,
},
setup(_props, { emit }) {
const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
const loadMenuRef = ref(false);
const nullFormElRef = ref(null);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const { lockEnable, registerTable, reloadTable, handleDelete } = useUserTable();
const { registerLockModal, showLockModal, handleUnLock } = useLock({ emit });
const { registerPasswordModal, showPasswordModal } = usePassword(nullFormElRef);
const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
useModal();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
function handleSetMenu(record) { const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
openMenuModal(true, { identity: record.id }, true); const loadMenuRef = ref(false);
} const nullFormElRef = ref(null);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const { lockEnable, registerTable, reloadTable, handleDelete } = useUserTable();
const { registerLockModal, showLockModal, handleUnLock } = useLock({ emit: emits });
const { registerPasswordModal, showPasswordModal } = usePassword(nullFormElRef);
const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
useModal();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
function handleChangeMenu(userId, menuIds) { function handleSetMenu(record) {
loadMenuRef.value = true; openMenuModal(true, { identity: record.id }, true);
setUserMenu({ }
userId: userId,
menuIds: menuIds,
})
.then(() => {
closeMenuModal();
})
.finally(() => {
loadMenuRef.value = false;
});
}
function handleAddNew() { function handleChangeMenu(userId, menuIds) {
openModal(true, {}, true); loadMenuRef.value = true;
} setUserMenu({
userId: userId,
menuIds: menuIds,
}) .then(() => {
closeMenuModal();
}) .finally(() => {
loadMenuRef.value = false;
});
}
function handleEdit(record) { function handleAddNew() {
openModal(true, record, true); openModal(true, {}, true);
} }
function handleUnlock(record) { function handleEdit(record) {
handleUnLock(record.id).then(() => { openModal(true, record, true);
reloadTable(); }
});
}
function handleChangeStartupMenu(userId, meunId) { function handleUnlock(record) {
setUserStartupMenu(userId, meunId); handleUnLock(record.id).then(() => {
} reloadTable();
});
}
function handleShowClaims(record) { function handleChangeStartupMenu(userId, meunId) {
openClaimModal(true, { id: record.id }); setUserStartupMenu(userId, meunId);
} }
return { function handleShowClaims(record) {
L, openClaimModal(true, { id: record.id });
loadMenuRef, }
hasPermission,
lockEnable,
registerTable,
reloadTable,
registerModal,
openModal,
registerPermissionModal,
showPermissionModal,
registerPasswordModal,
showPasswordModal,
registerClaimModal,
handleShowClaims,
handleDelete,
registerLockModal,
showLockModal,
handleUnLock,
registerMenuModal,
handleAddNew,
handleEdit,
handleUnlock,
handleSetMenu,
handleChangeMenu,
handleChangeStartupMenu,
getListByUser,
getUserClaims,
createClaim,
updateClaim,
deleteClaim,
};
},
});
</script> </script>

14
apps/vue/src/views/identity/user/hooks/useUserForm.ts

@ -106,14 +106,12 @@ export function useUserForm({ userRef, formElRef }: UseUserFormContext) {
const api = user.id const api = user.id
? update(user.id, cloneDeep(user) as UpdateUser) ? update(user.id, cloneDeep(user) as UpdateUser)
: create(cloneDeep(user) as CreateUser); : create(cloneDeep(user) as CreateUser);
api api.then((res) => {
.then((res) => { userRef.value = {};
userRef.value = {}; resolve(res);
resolve(res); }).catch((error) => {
}) reject(error);
.catch((error) => { });
reject(error);
});
}) })
.catch((error) => { .catch((error) => {
reject(error); reject(error);

14
apps/vue/src/views/identity/user/hooks/useUserTable.ts

@ -1,13 +1,14 @@
import { computed } from 'vue'; import { computed } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useTable } from '/@/components/Table'; import { useTable } from '/@/components/Table';
import { deleteById, getList } from '/@/api/identity/user'; import { deleteById, getList } from '/@/api/identity/user';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getDataColumns } from '../datas/TableData'; import { getDataColumns } from '../datas/TableData';
import { getSearchFormSchemas } from '../datas/ModalData'; import { getSearchFormSchemas } from '../datas/ModalData';
import { Modal } from 'ant-design-vue';
export function useUserTable() { export function useUserTable() {
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpIdentity'); const { L } = useLocalization('AbpIdentity');
const [registerTable, { reload: reloadTable }] = useTable({ const [registerTable, { reload: reloadTable }] = useTable({
rowKey: 'id', rowKey: 'id',
@ -51,14 +52,17 @@ export function useUserTable() {
}); });
function handleDelete(user) { function handleDelete(user) {
Modal.warning({ createConfirm({
iconType: 'warning',
title: L('AreYouSure'), title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [user.userName] as Recordable), content: L('ItemWillBeDeletedMessageWithFormat', [user.userName] as Recordable),
okCancel: true, okCancel: true,
onOk: () => { onOk: () => {
deleteById(user.id).then(() => { deleteById(user.id)
reloadTable(); .then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
reloadTable();
});
}, },
}); });
} }

97
apps/vue/src/views/localization/languages/components/LanguageTable.vue

@ -4,73 +4,50 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, onMounted } from 'vue'; import { onMounted } from 'vue';
import { Switch } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, useTable } from '/@/components/Table'; import { BasicTable, useTable } from '/@/components/Table';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getList } from '/@/api/localization/languages'; import { getList } from '/@/api/localization/languages';
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
export default defineComponent({ const { L } = useLocalization(['AbpLocalization', 'AbpUi']);
name: 'LanguageTable', const [registerTable, { setTableData, getForm }] = useTable({
components: { rowKey: 'cultureName',
BasicTable, title: L('Languages'),
Switch, columns: getDataColumns(),
}, beforeFetch: formatPagedRequest,
setup() { pagination: true,
const { L } = useLocalization(['AbpLocalization', 'AbpUi']); striped: false,
const { hasPermission } = usePermission(); useSearchForm: true,
const [registerTable, { setTableData, getForm }] = useTable({ showTableSetting: true,
rowKey: 'cultureName', bordered: true,
title: L('Languages'), showIndexColumn: false,
columns: getDataColumns(), canResize: false,
beforeFetch: formatPagedRequest, immediate: false,
pagination: true, formConfig: {
striped: false, labelWidth: 100,
useSearchForm: true, schemas: [
showTableSetting: true, {
bordered: true, field: 'filter',
showIndexColumn: false, component: 'Input',
canResize: false, label: L('Search'),
immediate: false, colProps: { span: 24 },
formConfig: { defaultValue: '',
labelWidth: 100,
schemas: [
{
field: 'filter',
component: 'Input',
label: L('Search'),
colProps: { span: 24 },
defaultValue: '',
},
],
submitFunc: fetchLanguages,
}, },
}); ],
onMounted(fetchLanguages); submitFunc: fetchLanguages,
function fetchLanguages() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
function handleChange() {
fetchLanguages();
}
return {
L,
hasPermission,
registerTable,
handleChange,
};
}, },
}); });
onMounted(fetchLanguages);
function fetchLanguages() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
</script> </script>

95
apps/vue/src/views/localization/resources/components/ResourceTable.vue

@ -4,71 +4,48 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, onMounted } from 'vue'; import { onMounted } from 'vue';
import { Switch } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, useTable } from '/@/components/Table'; import { BasicTable, useTable } from '/@/components/Table';
import { getList } from '/@/api/localization/resources'; import { getList } from '/@/api/localization/resources';
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
export default defineComponent({ const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
name: 'ResourceTable', const [registerTable, { setTableData, getForm }] = useTable({
components: { rowKey: 'name',
BasicTable, title: L('Resources'),
Switch, columns: getDataColumns(),
}, pagination: true,
setup() { striped: false,
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']); useSearchForm: true,
const { hasPermission } = usePermission(); showTableSetting: true,
const [registerTable, { setTableData, getForm }] = useTable({ bordered: true,
rowKey: 'name', showIndexColumn: false,
title: L('Resources'), canResize: false,
columns: getDataColumns(), immediate: false,
pagination: true, formConfig: {
striped: false, labelWidth: 100,
useSearchForm: true, schemas: [
showTableSetting: true, {
bordered: true, field: 'filter',
showIndexColumn: false, component: 'Input',
canResize: false, label: L('Search'),
immediate: false, colProps: { span: 24 },
formConfig: { defaultValue: '',
labelWidth: 100,
schemas: [
{
field: 'filter',
component: 'Input',
label: L('Search'),
colProps: { span: 24 },
defaultValue: '',
},
],
submitFunc: fetchResources,
}, },
}); ],
onMounted(fetchResources); submitFunc: fetchResources,
function fetchResources() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
function handleChange() {
fetchResources();
}
return {
L,
hasPermission,
registerTable,
handleChange,
};
}, },
}); });
onMounted(fetchResources);
function fetchResources() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
</script> </script>

261
apps/vue/src/views/localization/texts/components/TextModal.vue

@ -11,155 +11,142 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, unref, nextTick } from 'vue'; import { computed, ref, unref, nextTick } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { message } from 'ant-design-vue';
import { BasicForm, FormSchema, FormActionType, useForm } from '/@/components/Form'; import { BasicForm, FormSchema, FormActionType, useForm } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { Text } from '/@/api/localization/model/textsModel'; import { Text } from '/@/api/localization/model/textsModel';
import { getByCulture, setText } from '/@/api/localization/texts'; import { getByCulture, setText } from '/@/api/localization/texts';
import { getList as getLanguages } from '/@/api/localization/languages'; import { getList as getLanguages } from '/@/api/localization/languages';
import { getList as getResources } from '/@/api/localization/resources'; import { getList as getResources } from '/@/api/localization/resources';
export default defineComponent({
name: 'TextModal', const emits = defineEmits(['change', 'register']);
components: { BasicForm, BasicModal },
emits: ['change', 'register'], const { createMessage } = useMessage();
setup(_props, { emit }) { const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']); const modelRef = ref<Nullable<Text>>(null);
const modelRef = ref<Nullable<Text>>(null); const formElRef = ref<Nullable<FormActionType>>(null);
const formElRef = ref<Nullable<FormActionType>>(null); const formSchemas: FormSchema[] = [
const formSchemas: FormSchema[] = [ {
{ field: 'id',
field: 'id', component: 'Input',
component: 'Input', label: 'id',
label: 'id', colProps: { span: 24 },
colProps: { span: 24 }, show: false,
show: false, },
}, {
{ field: 'cultureName',
field: 'cultureName', component: 'ApiSelect',
component: 'ApiSelect', label: L('DisplayName:TargetCultureName'),
label: L('DisplayName:TargetCultureName'), colProps: { span: 24 },
colProps: { span: 24 }, required: true,
required: true, componentProps: {
componentProps: { api: () => getLanguages(),
api: () => getLanguages(), resultField: 'items',
resultField: 'items', labelField: 'uiCultureName',
labelField: 'uiCultureName', valueField: 'cultureName',
valueField: 'cultureName', onChange: (key) => {
onChange: (key) => { //
// const model = unref(modelRef);
const model = unref(modelRef); if (model?.key) {
if (model?.key) { getByCulture({
getByCulture({ key: model!.key,
cultureName: key,
resourceName: model!.resourceName,
}).then((res) => {
if (res) {
modelRef.value = res;
} else {
modelRef.value = {
value: '',
key: model!.key, key: model!.key,
cultureName: key, cultureName: key,
resourceName: model!.resourceName, resourceName: model!.resourceName,
}).then((res) => { };
if (res) {
modelRef.value = res;
} else {
modelRef.value = {
value: '',
key: model!.key,
cultureName: key,
resourceName: model!.resourceName,
};
}
const formEl = unref(formElRef);
formEl?.setFieldsValue(modelRef.value);
});
} }
}, const formEl = unref(formElRef);
}, formEl?.setFieldsValue(modelRef.value);
}, });
{ }
field: 'resourceName',
component: 'ApiSelect',
label: L('DisplayName:ResourceName'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getResources(),
resultField: 'items',
labelField: 'displayName',
valueField: 'name',
},
dynamicDisabled: ({ values }) => {
return values.id ? true : false;
},
},
{
field: 'key',
component: 'Input',
label: L('DisplayName:Key'),
colProps: { span: 24 },
required: true,
dynamicDisabled: ({ values }) => {
return values.id ? true : false;
},
}, },
{ },
field: 'value', },
component: 'InputTextArea', {
label: L('DisplayName:Value'), field: 'resourceName',
colProps: { span: 24 }, component: 'ApiSelect',
required: true, label: L('DisplayName:ResourceName'),
componentProps: { colProps: { span: 24 },
rows: 5, required: true,
showCount: true, componentProps: {
}, api: () => getResources(),
}, resultField: 'items',
]; labelField: 'displayName',
const [registerForm, { resetFields, setFieldsValue }] = useForm({ valueField: 'name',
colon: true, },
labelWidth: 120, dynamicDisabled: ({ values }) => {
schemas: formSchemas, return values.id ? true : false;
showActionButtonGroup: false, },
actionColOptions: { },
span: 24, {
}, field: 'key',
}); component: 'Input',
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((val) => { label: L('DisplayName:Key'),
modelRef.value = val; colProps: { span: 24 },
nextTick(() => { required: true,
resetFields(); dynamicDisabled: ({ values }) => {
setFieldsValue(val); return values.id ? true : false;
}); },
}); },
const formTitle = computed(() => { {
const key = unref(modelRef)?.key; field: 'value',
if (key) { component: 'InputTextArea',
return L('EditByName', [unref(modelRef)?.key] as Recordable); label: L('DisplayName:Value'),
} colProps: { span: 24 },
return L('Text:AddNew'); required: true,
}); componentProps: {
rows: 5,
function handleSubmit() { showCount: true,
const formEl = unref(formElRef); },
formEl?.validate().then((input) => {
changeOkLoading(true);
setText(input).then(() => {
emit('change');
message.success(L('Successful'));
formEl?.resetFields();
closeModal();
})
.finally(() => {
changeOkLoading(false);
});
});
}
return {
L,
formElRef,
formTitle,
registerForm,
registerModal,
handleSubmit,
};
}, },
];
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
colon: true,
labelWidth: 120,
schemas: formSchemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((val) => {
modelRef.value = val;
nextTick(() => {
resetFields();
setFieldsValue(val);
});
});
const formTitle = computed(() => {
const key = unref(modelRef)?.key;
if (key) {
return L('EditByName', [unref(modelRef)?.key] as Recordable);
}
return L('Text:AddNew');
}); });
function handleSubmit() {
validate().then((input) => {
changeOkLoading(true);
setText(input).then(() => {
createMessage.success(L('Successful'));
emits('change');
resetFields();
closeModal();
})
.finally(() => {
changeOkLoading(false);
});
});
}
</script> </script>

112
apps/vue/src/views/localization/texts/components/TextTable.vue

@ -29,10 +29,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { defineComponent } from 'vue';
import { Switch } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
@ -42,74 +40,52 @@
import { getSearchFormSchemas } from './ModalData'; import { getSearchFormSchemas } from './ModalData';
import TextModal from './TextModal.vue'; import TextModal from './TextModal.vue';
export default defineComponent({ const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
name: 'TextTable', const { hasPermission } = usePermission();
components: { const [registerModal, { openModal }] = useModal();
BasicTable, const [registerTable, { setTableData, setPagination, getForm }] = useTable({
Switch, rowKey: 'key',
TableAction, title: L('Texts'),
TextModal, columns: getDataColumns(),
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: getSearchFormSchemas(fetchTexts),
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
}, },
setup() { });
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const [registerTable, { setTableData, setPagination, getForm }] = useTable({
rowKey: 'id',
title: L('Texts'),
columns: getDataColumns(),
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: getSearchFormSchemas(fetchTexts),
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
});
function fetchTexts() {
setPagination({
current: 1,
});
const form = getForm();
return form.validate().then((input) => {
const request = cloneDeep(input);
request.onlyNull = input.onlyNull === 1;
return getList(request).then((res) => {
return setTableData(res.items);
});
})
}
function handleChange() { function fetchTexts() {
fetchTexts(); setPagination({
} current: 1,
});
const form = getForm();
return form.validate().then((input) => {
const request = cloneDeep(input);
request.onlyNull = input.onlyNull === 1;
return getList(request).then((res) => {
return setTableData(res.items);
});
})
}
function handleAddNew() { function handleChange() {
openModal(true, { id: null }); fetchTexts();
} }
function handleEdit(record) { function handleAddNew() {
openModal(true, {...{ id: 1 }, ...record}); openModal(true, { id: null });
} }
return { function handleEdit(record) {
L, openModal(true, {...{ id: 1 }, ...record});
hasPermission, }
registerTable,
registerModal,
openModal,
handleChange,
handleAddNew,
handleEdit,
};
},
});
</script> </script>

156
apps/vue/src/views/oss-management/containers/components/ContainerTable.vue

@ -38,9 +38,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { useMessage } from '/@/hooks/web/useMessage';
import { Modal, message } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { BasicModal, useModal } from '/@/components/Modal'; import { BasicModal, useModal } from '/@/components/Modal';
@ -51,95 +50,74 @@
import { getSearchFormSchemas, getModalFormSchemas } from './ModalData'; import { getSearchFormSchemas, getModalFormSchemas } from './ModalData';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
export default defineComponent({ const { createMessage, createConfirm } = useMessage();
name: 'ContainerTable', const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
components: { const { hasPermission } = usePermission();
BasicForm, const [registerModal, { openModal, closeModal }] = useModal();
BasicModal, const [registerForm, { validate, resetFields }] = useForm({
BasicTable, labelWidth: 120,
TableAction, schemas: getModalFormSchemas(),
showActionButtonGroup: false,
actionColOptions: {
span: 24,
}, },
setup() { });
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']); const [registerTable, { reload }] = useTable({
const { hasPermission } = usePermission(); rowKey: 'name',
const [registerModal, { openModal, closeModal }] = useModal(); title: L('Containers'),
const [registerForm, { validate, resetFields }] = useForm({ columns: getDataColumns(),
labelWidth: 120, api: getContainers,
schemas: getModalFormSchemas(), fetchSetting: {
showActionButtonGroup: false, pageField: 'skipCount',
actionColOptions: { sizeField: 'maxResultCount',
span: 24, listField: 'containers',
}, totalField: 'maxKeys',
}); },
const [registerTable, { reload }] = useTable({ beforeFetch: formatPagedRequest,
rowKey: 'name', pagination: true,
title: L('Containers'), striped: false,
columns: getDataColumns(), useSearchForm: true,
api: getContainers, showTableSetting: true,
fetchSetting: { bordered: true,
pageField: 'skipCount', showIndexColumn: false,
sizeField: 'maxResultCount', canResize: false,
listField: 'containers', immediate: true,
totalField: 'maxKeys', rowSelection: { type: 'checkbox' },
}, formConfig: getSearchFormSchemas(),
beforeFetch: formatPagedRequest, actionColumn: {
pagination: true, width: 120,
striped: false, title: L('Actions'),
useSearchForm: true, dataIndex: 'action',
showTableSetting: true, },
bordered: true, });
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleAddNew() {
resetFields();
openModal(true, {});
}
function handleDelete(record) { function handleAddNew() {
Modal.warning({ resetFields();
title: L('AreYouSure'), openModal(true, {});
content: L('ItemWillBeDeletedMessage'), }
okCancel: true,
onOk: () => {
deleteContainer(record.name).then(() => {
message.success(L('Successful'));
reload();
});
},
});
}
function handleSubmit() { function handleDelete(record) {
validate().then((input) => { createConfirm({
createContainer(input.name).then(() => { iconType: 'warning',
message.success(L('Successful')); title: L('AreYouSure'),
closeModal(); content: L('ItemWillBeDeletedMessage'),
reload(); okCancel: true,
}); onOk: () => {
deleteContainer(record.name).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
}); });
} },
});
}
return { function handleSubmit() {
L, validate().then((input) => {
hasPermission, createContainer(input.name).then(() => {
registerTable, createMessage.success(L('Successful'));
registerForm, closeModal();
registerModal, reload();
openModal, });
handleAddNew, });
handleDelete, }
handleSubmit,
};
},
});
</script> </script>

4
apps/vue/src/views/oss-management/objects/components/FileList.vue

@ -173,7 +173,7 @@
path: props.path, path: props.path,
objects: getSelectRowKeys(), objects: getSelectRowKeys(),
}).then(() => { }).then(() => {
createMessage.success(L('Successful')); createMessage.success(L('SuccessfullyDeleted'));
reload(); reload();
}); });
}, },
@ -199,7 +199,7 @@
path: props.path, path: props.path,
object: record.name, object: record.name,
}).then(() => { }).then(() => {
createMessage.success(L('Successful')); createMessage.success(L('SuccessfullyDeleted'));
reload(); reload();
}); });
}, },

81
apps/vue/src/views/oss-management/objects/components/OssFolderModal.vue

@ -10,59 +10,48 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref } from 'vue'; import { ref, unref } from 'vue';
import { message } from 'ant-design-vue'; import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form'; import { BasicForm, useForm } from '/@/components/Form';
import { getFolderModalSchemas } from '../datas/ModalData'; import { getFolderModalSchemas } from '../datas/ModalData';
import { createObject } from '/@/api/oss-management/oss'; import { createObject } from '/@/api/oss-management/oss';
export default defineComponent({ const emits = defineEmits(['register', 'change']);
name: 'OssFolderModal',
components: { BasicModal, BasicForm },
emits: ['register', 'change'],
setup(_, { emit }) {
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const bucket = ref('');
const path = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
schemas: getFolderModalSchemas(),
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerModal, { closeModal }] = useModalInner((data) => {
resetFields();
path.value = data.path;
bucket.value = data.bucket;
});
function handleSubmit() {
validate().then((input) => {
const name = input.name.endsWith('/') ? input.name : input.name + '/';
createObject({
bucket: unref(bucket),
path: unref(path),
object: name,
overwrite: false,
}).then(() => {
message.success(L('Successful'));
closeModal();
emit('change', name);
});
});
}
return { const { createMessage } = useMessage();
L, const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
registerForm, const bucket = ref('');
registerModal, const path = ref('');
handleSubmit, const [registerForm, { validate, resetFields }] = useForm({
}; labelWidth: 120,
schemas: getFolderModalSchemas(),
showActionButtonGroup: false,
actionColOptions: {
span: 24,
}, },
}); });
const [registerModal, { closeModal }] = useModalInner((data) => {
resetFields();
path.value = data.path;
bucket.value = data.bucket;
});
function handleSubmit() {
validate().then((input) => {
const name = input.name.endsWith('/') ? input.name : input.name + '/';
createObject({
bucket: unref(bucket),
path: unref(path),
object: name,
overwrite: false,
}).then(() => {
createMessage.success(L('Successful'));
closeModal();
emits('change', name);
});
});
}
</script> </script>

75
apps/vue/src/views/oss-management/objects/components/OssManagePage.vue

@ -27,65 +27,42 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { Card, Select } from 'ant-design-vue'; import { Card, Select } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { getContainers } from '/@/api/oss-management/oss'; import { getContainers } from '/@/api/oss-management/oss';
import { OssContainer } from '/@/api/oss-management/model/ossModel'; import { OssContainer } from '/@/api/oss-management/model/ossModel';
import FolderTree from './FolderTree.vue'; import FolderTree from './FolderTree.vue';
import FileList from './FileList.vue'; import FileList from './FileList.vue';
export default defineComponent({ const CardGrid = Card.Grid;
name: 'OssTable', const CardMeta = Card.Meta;
components: {
Card,
CardGrid: Card.Grid,
CardMeta: Card.Meta,
Select,
Option: Select.Option,
FolderTree,
FileList,
},
setup() {
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const currentPath = ref('');
const currentBucket = ref('');
const bucketList = ref<OssContainer[]>([]);
onMounted(fetchBuckets); const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const currentPath = ref('');
const currentBucket = ref('');
const bucketList = ref<OssContainer[]>([]);
function fetchBuckets() { onMounted(fetchBuckets);
getContainers({
prefix: '',
marker: '',
sorting: '',
skipCount: 0,
maxResultCount: 1000,
}).then((res) => {
bucketList.value = res.containers;
});
}
function handleBucketChange(bucket) { function fetchBuckets() {
currentBucket.value = bucket; getContainers({
} prefix: '',
marker: '',
sorting: '',
skipCount: 0,
maxResultCount: 1000,
}).then((res) => {
bucketList.value = res.containers;
});
}
function handlePathChange(path) { function handleBucketChange(bucket) {
currentPath.value = path; currentBucket.value = bucket;
} }
return { function handlePathChange(path) {
L, currentPath.value = path;
bucketList, }
currentBucket,
currentPath,
handleBucketChange,
handlePathChange,
hasPermission,
};
},
});
</script> </script>

47
apps/vue/src/views/oss-management/objects/components/OssPreviewModal.vue

@ -9,8 +9,8 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, unref, watch } from 'vue'; import { computed, ref, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { ImagePreview } from '/@/components/Preview'; import { ImagePreview } from '/@/components/Preview';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
@ -18,36 +18,17 @@
import { generateOssUrl } from '/@/api/oss-management/oss'; import { generateOssUrl } from '/@/api/oss-management/oss';
import { useUserStoreWithOut } from '/@/store/modules/user'; import { useUserStoreWithOut } from '/@/store/modules/user';
export default defineComponent({ const { L } = useLocalization('AbpOssManagement');
name: 'OssPreviewModal', const bucket = ref('');
components: { BasicModal, ImagePreview }, const objects = ref<OssObject[]>([]);
setup() { const [registerModal] = useModalInner((data) => {
const { L } = useLocalization('AbpOssManagement'); bucket.value = data.bucket;
const bucket = ref(''); objects.value = data.objects;
const objects = ref<OssObject[]>([]); });
const previewImages = ref<any[]>([]); const previewImages = computed(() => {
const [registerModal] = useModalInner((data) => { const userStore = useUserStoreWithOut();
bucket.value = data.bucket; return objects.value.map((obj) => {
objects.value = data.objects; return generateOssUrl(unref(bucket), obj.path, obj.name) + '?access_token=' + userStore.getToken;
}); });
const userStore = useUserStoreWithOut();
watch(
() => unref(objects),
(objs) => {
previewImages.value = objs.map((x) => {
return (
generateOssUrl(unref(bucket), x.path, x.name) + '?access_token=' + userStore.getToken
);
});
},
);
return {
L,
previewImages,
registerModal,
};
},
}); });
</script> </script>

303
apps/vue/src/views/oss-management/objects/components/OssUploadModal.vue

@ -50,8 +50,8 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, unref, onMounted, onUnmounted, watch } from 'vue'; import { computed, ref, unref, onMounted, onUnmounted, watch } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Tag, Tooltip } from 'ant-design-vue'; import { Tag, Tooltip } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
@ -60,176 +60,157 @@
import { useUserStoreWithOut } from '/@/store/modules/user'; import { useUserStoreWithOut } from '/@/store/modules/user';
import Uploader from 'simple-uploader.js'; import Uploader from 'simple-uploader.js';
export default defineComponent({ let uploader: any = null;
name: 'OssUploadModal', const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
components: { BasicModal, BasicTable, TableAction, Tag, Tooltip }, const bucket = ref('');
setup() { const path = ref('');
let uploader: any = null; const btnRef = ref<any>();
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']); const [registerModal] = useModalInner((data) => {
const bucket = ref(''); path.value = data.path;
const path = ref(''); bucket.value = data.bucket;
const btnRef = ref<any>(); });
const [registerModal] = useModalInner((data) => { const fileList = ref<Recordable[]>([]);
path.value = data.path; const [registerTable] = useTable({
bucket.value = data.bucket; rowKey: 'id',
}); columns: [
const fileList = ref<Recordable[]>([]); {
const [registerTable] = useTable({ title: 'id',
rowKey: 'id', dataIndex: 'id',
columns: [ width: 1,
{ ifShow: false,
title: 'id', },
dataIndex: 'id', {
width: 1, title: L('DisplayName:Name'),
ifShow: false, dataIndex: 'name',
}, align: 'left',
{ width: 300,
title: L('DisplayName:Name'), sorter: true,
dataIndex: 'name', },
align: 'left', {
width: 300, title: L('DisplayName:Size'),
sorter: true, dataIndex: 'size',
}, align: 'left',
{ width: 100,
title: L('DisplayName:Size'), sorter: true,
dataIndex: 'size', },
align: 'left', {
width: 100, title: L('DisplayName:Status'),
sorter: true, dataIndex: 'status',
}, align: 'left',
{ width: 'auto',
title: L('DisplayName:Status'), sorter: true,
dataIndex: 'status', },
align: 'left', ],
width: 'auto', dataSource: fileList,
sorter: true, pagination: false,
}, striped: false,
], useSearchForm: false,
dataSource: fileList, showTableSetting: false,
pagination: false, bordered: false,
striped: false, showIndexColumn: false,
useSearchForm: false, canResize: false,
showTableSetting: false, immediate: false,
bordered: false, actionColumn: {
showIndexColumn: false, width: 120,
canResize: false, title: L('Actions'),
immediate: false, dataIndex: 'action',
actionColumn: { },
width: 120, });
title: L('Actions'),
dataIndex: 'action',
},
});
onMounted(() => {
const userStore = useUserStoreWithOut();
uploader = new Uploader({
target: uploadUrl,
testChunks: false,
//
maxChunkRetries: 3,
chunkRetryInterval: null,
successStatuses: [200, 201, 202, 204, 205],
permanentErrors: [400, 401, 403, 404, 415, 500, 501],
headers: {
// TODO: 使?
Authorization: `Bearer ${userStore.getToken}`,
},
processParams: (params: any) => {
params.bucket = unref(bucket);
params.path = unref(path);
return params;
},
});
// uploader.on('fileSuccess', _fileSuccess);
uploader.on('filesSubmitted', _filesSubmitted);
uploader.on('fileError', _fileError);
uploader.on('fileProgress', _fileProgress);
});
onUnmounted(() => { onMounted(() => {
// uploader.off('fileSuccess', _fileSuccess); const userStore = useUserStoreWithOut();
uploader.off('filesSubmitted', _filesSubmitted); uploader = new Uploader({
uploader.off('fileError', _fileError); target: uploadUrl,
uploader.off('fileProgress', _fileProgress); testChunks: false,
uploader = null; //
}); maxChunkRetries: 3,
chunkRetryInterval: null,
successStatuses: [200, 201, 202, 204, 205],
permanentErrors: [400, 401, 403, 404, 415, 500, 501],
headers: {
// TODO: 使?
Authorization: `Bearer ${userStore.getToken}`,
},
processParams: (params: any) => {
params.bucket = unref(bucket);
params.path = unref(path);
return params;
},
});
// uploader.on('fileSuccess', _fileSuccess);
uploader.on('filesSubmitted', _filesSubmitted);
uploader.on('fileError', _fileError);
uploader.on('fileProgress', _fileProgress);
});
watch( onUnmounted(() => {
() => unref(btnRef), // uploader.off('fileSuccess', _fileSuccess);
(btn) => { uploader.off('filesSubmitted', _filesSubmitted);
uploader.assignBrowse(btn); uploader.off('fileError', _fileError);
}, uploader.off('fileProgress', _fileProgress);
); uploader = null;
});
function _filesSubmitted(_, files) { watch(
files.forEach((f) => { () => unref(btnRef),
f.paused = true; (btn) => {
f.progress = '0 %'; uploader.assignBrowse(btn);
}); },
fileList.value.push(...files); );
}
function _fileProgress(_, file) { function _filesSubmitted(_, files) {
if (file._prevUploadedSize) { files.forEach((f) => {
file.progress = `${Math.floor((file._prevUploadedSize / file.size) * 100)} %`; f.paused = true;
} f.progress = '0 %';
} });
fileList.value.push(...files);
}
function _fileError(_, file, message) { function _fileProgress(_, file) {
file.paused = true; if (file._prevUploadedSize) {
if (message) { file.progress = `${Math.floor((file._prevUploadedSize / file.size) * 100)} %`;
const formatedError = JSON.parse(message); }
file.errorMsg = formatedError.error?.message; }
}
}
function handleSelect() { function _fileError(_, file, message) {
unref(btnRef)?.click(); file.paused = true;
} if (message) {
const formatedError = JSON.parse(message);
file.errorMsg = formatedError.error?.message;
}
}
function handleResume(record) { function handleSelect() {
if (record.error) { unref(btnRef)?.click();
record.retry(); }
record.errorMsg = '';
}
record.resume();
}
function handlePause(record) { function handleResume(record) {
record.pause(); if (record.error) {
} record.retry();
record.errorMsg = '';
}
record.resume();
}
function handleCancel(record) { function handlePause(record) {
record.cancel(); record.pause();
uploader.removeFile(record); }
fileList.value = fileList.value.filter((f) => f.id !== record.id);
}
const fileSize = computed(() => { function handleCancel(record) {
return (size) => { record.cancel();
return Uploader.utils.formatSize(size); uploader.removeFile(record);
}; fileList.value = fileList.value.filter((f) => f.id !== record.id);
}); }
const averageSpeed = computed(() => { const fileSize = computed(() => {
return (speed) => { return (size) => {
return `${Uploader.utils.formatSize(speed)} / s`; return Uploader.utils.formatSize(size);
}; };
}); });
return { const averageSpeed = computed(() => {
L, return (speed) => {
btnRef, return `${Uploader.utils.formatSize(speed)} / s`;
fileSize, };
averageSpeed,
registerModal,
registerTable,
handleSelect,
handleResume,
handlePause,
handleCancel,
};
},
}); });
</script> </script>

119
apps/vue/src/views/platform/dataDic/components/DataItemModal.vue

@ -4,88 +4,67 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, unref, watch } from 'vue'; import { computed, ref, unref, watch } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DataItem } from '/@/api/platform/model/dataItemModel'; import { DataItem } from '/@/api/platform/model/dataItemModel';
import { getDataItemFormSchemas } from './ModalData'; import { getDataItemFormSchemas } from './ModalData';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index'; import { BasicForm, useForm } from '/@/components/Form/index';
import { createItem, updateItem } from '/@/api/platform/dataDic'; import { createItem, updateItem } from '/@/api/platform/dataDic';
export default defineComponent({
name: 'DataItemModal',
components: {
BasicForm,
BasicModal,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const dataItem = ref<DataItem>();
const { createMessage } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const schemas = getDataItemFormSchemas();
watch( const emits = defineEmits(['change', 'register']);
() => unref(dataItem),
(item) => {
resetFields();
setFieldsValue(item);
},
{
immediate: false,
},
)
const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({ const dataItem = ref<DataItem>();
labelWidth: 120, const { createMessage } = useMessage();
schemas, const { L } = useLocalization(['AppPlatform', 'AbpUi']);
showActionButtonGroup: false, const schemas = getDataItemFormSchemas();
actionColOptions: {
span: 24,
},
});
const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => { watch(
dataItem.value = dataVal; () => unref(dataItem),
}); (item) => {
resetFields();
setFieldsValue(item);
},
{
immediate: false,
},
)
const title = computed(() => { const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
if (unref(dataItem)?.id) { labelWidth: 120,
return L('Data:EditItem'); schemas,
} showActionButtonGroup: false,
return L('Data:AppendItem'); actionColOptions: {
}); span: 24,
},
});
function handleSubmit() { const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => {
validate().then((input) => { dataItem.value = dataVal;
changeLoading(true); });
const api = input.id
? updateItem(input.dataId, input.name, input)
: createItem(input.dataId, input);
api.then(() => {
createMessage.success(L('Successful'));
emit('change', input.dataId);
closeModal();
})
.finally(() => {
changeLoading(false);
});
});
}
return { const title = computed(() => {
L, if (unref(dataItem)?.id) {
title, return L('Data:EditItem');
registerForm, }
register, return L('Data:AppendItem');
dataItem,
handleSubmit,
};
},
}); });
function handleSubmit() {
validate().then((input) => {
changeLoading(true);
const api = input.id
? updateItem(input.dataId, input.name, input)
: createItem(input.dataId, input);
api.then(() => {
createMessage.success(L('Successful'));
emits('change', input.dataId);
closeModal();
}).finally(() => {
changeLoading(false);
});
});
}
</script> </script>

176
apps/vue/src/views/platform/dataDic/components/DataItemTable.vue

@ -31,119 +31,99 @@
<DataItemModal @register="registerModal" @change="fetchItems" /> <DataItemModal @register="registerModal" @change="fetchItems" />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, createVNode, watch } from 'vue'; import { computed, ref, createVNode, watch } from 'vue';
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
import DataItemModal from './DataItemModal.vue'; import { Switch } from 'ant-design-vue';
import { Modal, Switch } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'; import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table'; import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DataItem } from '/@/api/platform/model/dataItemModel'; import { DataItem } from '/@/api/platform/model/dataItemModel';
import { get, removeItem } from '/@/api/platform/dataDic'; import { get, removeItem } from '/@/api/platform/dataDic';
import DataItemModal from './DataItemModal.vue';
const props = { const emits = defineEmits(['reload']);
dataId: { type: String, retuired: true }, const props = defineProps({
} as const; dataId: {
type: String,
export default defineComponent({ retuired: true,
name: 'DataItemTable',
components: {
BasicTable,
TableAction,
DataItemModal,
Switch,
}, },
props, });
emits: ['reload'],
setup(props, { emit }) {
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const dataItems = ref<DataItem[]>([]);
const [registerTable] = useTable({
rowKey: 'id',
title: L('Data:Items'),
columns: getDataColumns(),
dataSource: dataItems,
bordered: true,
canResize: true,
showTableSetting: true,
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerModal, { openModal }] = useModal();
const isEnableNew = computed(() => { const { createMessage, createConfirm } = useMessage();
if (props.dataId && props.dataId !== '') { const { L } = useLocalization(['AppPlatform', 'AbpUi']);
return true; const dataItems = ref<DataItem[]>([]);
} const [registerTable] = useTable({
return false; rowKey: 'id',
}); title: L('Data:Items'),
columns: getDataColumns(),
dataSource: dataItems,
bordered: true,
canResize: true,
showTableSetting: true,
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerModal, { openModal }] = useModal();
watch( const isEnableNew = computed(() => {
() => props.dataId, if (props.dataId && props.dataId !== '') {
(dataId) => { return true;
dataItems.value = []; }
if (dataId) { return false;
fetchItems(dataId); });
}
},
{
immediate: true,
},
)
function fetchItems(dataId: string) { watch(
get(dataId).then((res) => { () => props.dataId,
dataItems.value = res.items; (dataId) => {
}); dataItems.value = [];
if (dataId) {
fetchItems(dataId);
} }
},
{
immediate: true,
},
)
function handleAppendItem() { function fetchItems(dataId: string) {
openModal(true, { dataId: props.dataId }); get(dataId).then((res) => {
} dataItems.value = res.items;
});
}
function handleEdit(record) { function handleAppendItem() {
openModal(true, { dataId: props.dataId, ...record }); openModal(true, { dataId: props.dataId });
} }
function handleDelete(record: Recordable) { function handleEdit(record) {
Modal.confirm({ openModal(true, { dataId: props.dataId, ...record });
title: L('AreYouSure'), }
icon: createVNode(ExclamationCircleOutlined),
content: createVNode(
'div',
{ style: 'color:red;' },
L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
),
onOk: () => {
removeItem(props.dataId!, record.name).then(() => {
emit('reload');
fetchItems(props.dataId!);
});
},
});
}
return { function handleDelete(record: Recordable) {
L, createConfirm({
isEnableNew, iconType: 'error',
registerTable, title: L('AreYouSure'),
dataItems, icon: createVNode(ExclamationCircleOutlined),
registerModal, content: createVNode(
openModal, 'div',
fetchItems, { style: 'color:red;' },
handleAppendItem, L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
handleEdit, ),
handleDelete, onOk: () => {
}; removeItem(props.dataId!, record.name)
}, .then(() => {
}); createMessage.success(L('SuccessfullyDeleted'));
emits('reload');
fetchItems(props.dataId!);
});
},
});
}
</script> </script>

108
apps/vue/src/views/platform/dataDic/components/DataModal.vue

@ -9,78 +9,60 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, nextTick } from 'vue'; import { ref, nextTick } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { get, create, update } from '/@/api/platform/dataDic'; import { get, create, update } from '/@/api/platform/dataDic';
import { getDateFormSchemas } from './ModalData'; import { getDateFormSchemas } from './ModalData';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index'; import { BasicForm, useForm } from '/@/components/Form/index';
export default defineComponent({
name: 'DataModal',
components: {
BasicForm,
BasicModal,
},
emits: ['register', 'change'],
setup(_, { emit }) {
const { createMessage } = useMessage();
const { L } = useLocalization('AppPlatform');
const schemas = getDateFormSchemas();
const title = ref('');
const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
labelWidth: 120,
schemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => {
nextTick(() => {
fetchData(dataVal.id);
});
});
function fetchData(id?: string) { const emits = defineEmits(['register', 'change']);
resetFields();
if (!id) {
title.value = L('Data:AddNew');
} else {
get(id).then((data) => {
setFieldsValue(data);
title.value = L('Data:Edit');
});
}
}
function handleSubmit() { const { createMessage } = useMessage();
validate().then((input) => { const { L } = useLocalization('AppPlatform');
changeLoading(true); const schemas = getDateFormSchemas();
const api = input.id ? update(input.id, input) : create(input); const title = ref('');
api.then((data) => {
createMessage.success(L('Successful'));
closeModal();
emit('change', data);
}).finally(() => {
changeLoading(false);
});
});
}
return { const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
L, labelWidth: 120,
title, schemas,
registerForm, showActionButtonGroup: false,
register, actionColOptions: {
handleSubmit, span: 24,
};
}, },
}); });
const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => {
nextTick(() => {
fetchData(dataVal.id);
});
});
function fetchData(id?: string) {
resetFields();
if (!id) {
title.value = L('Data:AddNew');
} else {
get(id).then((data) => {
setFieldsValue(data);
title.value = L('Data:Edit');
});
}
}
function handleSubmit() {
validate().then((input) => {
changeLoading(true);
const api = input.id ? update(input.id, input) : create(input);
api.then((data) => {
createMessage.success(L('Successful'));
closeModal();
emits('change', data);
}).finally(() => {
changeLoading(false);
});
});
}
</script> </script>

162
apps/vue/src/views/platform/dataDic/components/DataTree.vue

@ -17,112 +17,90 @@
</Card> </Card>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Card } from 'ant-design-vue';
import { Modal, Card } from 'ant-design-vue';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import { BasicTree, ContextMenuItem } from '/@/components/Tree/index'; import { BasicTree, ContextMenuItem } from '/@/components/Tree/index';
import { listToTree } from '/@/utils/helper/treeHelper'; import { listToTree } from '/@/utils/helper/treeHelper';
import { getAll, remove } from '/@/api/platform/dataDic'; import { getAll, remove } from '/@/api/platform/dataDic';
import { Data } from '/@/api/platform/model/dataModel'; import { Data } from '/@/api/platform/model/dataModel';
import DataModal from './DataModal.vue'; import DataModal from './DataModal.vue';
import DataItemModal from './DataItemModal.vue'; import DataItemModal from './DataItemModal.vue';
export default defineComponent({ const emits = defineEmits(['change', 'append-item']);
name: 'DataTree',
components: {
Card,
BasicTree,
DataModal,
DataItemModal,
},
emits: ['change', 'append-item'],
setup(_, { emit }) {
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const title = L('DisplayName:DataDictionary');
const treeData = ref<Data[]>([]);
const replaceFields = ref({
title: 'displayName',
key: 'id',
value: 'id',
});
const [registerItemModal, { openModal: openItemModal }] = useModal();
const [registerDataModal, { openModal: openDataModal }] = useModal();
onMounted(onLoadAllDataDic); const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const title = L('DisplayName:DataDictionary');
const treeData = ref<Data[]>([]);
const replaceFields = ref({
title: 'displayName',
key: 'id',
value: 'id',
});
const [registerItemModal, { openModal: openItemModal }] = useModal();
const [registerDataModal, { openModal: openDataModal }] = useModal();
function getContentMenus(node: any): ContextMenuItem[] { onMounted(onLoadAllDataDic);
return [
{ function getContentMenus(node: any): ContextMenuItem[] {
label: L('Data:Edit'), return [
handler: () => { {
openDataModal(true, { id: node.eventKey }); label: L('Data:Edit'),
}, handler: () => {
icon: 'ant-design:edit-outlined', openDataModal(true, { id: node.eventKey });
}, },
{ icon: 'ant-design:edit-outlined',
label: L('Data:AddNew'), },
handler: () => { {
openDataModal(true, { parentId: node.eventKey }); label: L('Data:AddNew'),
}, handler: () => {
icon: 'ant-design:plus-outlined', openDataModal(true, { parentId: node.eventKey });
}, },
{ icon: 'ant-design:plus-outlined',
label: L('Data:AppendItem'), },
handler: () => { {
openItemModal(true, { dataId: node.eventKey }, true); label: L('Data:AppendItem'),
}, handler: () => {
icon: 'ant-design:plus-square-outlined', openItemModal(true, { dataId: node.eventKey }, true);
}, },
{ icon: 'ant-design:plus-square-outlined',
label: L('Data:Delete'), },
handler: () => { {
Modal.warning({ label: L('Data:Delete'),
title: L('AreYouSure'), handler: () => {
content: L('ItemWillBeDeletedMessage'), createConfirm({
okCancel: true, iconType: 'warning',
onOk: () => { title: L('AreYouSure'),
remove(node.eventKey).then(() => { content: L('ItemWillBeDeletedMessage'),
onLoadAllDataDic(); okCancel: true,
}); onOk: () => {
}, remove(node.eventKey).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
onLoadAllDataDic();
}); });
}, },
icon: 'ant-design:delete-outlined',
},
];
}
function onLoadAllDataDic() {
getAll().then((res) => {
treeData.value = listToTree(res.items, {
pid: 'parentId',
}); });
}); },
} icon: 'ant-design:delete-outlined',
},
];
}
function handleNodeChange(selectKeys: String[]) { function onLoadAllDataDic() {
if (selectKeys.length > 0) { getAll().then((res) => {
emit('change', selectKeys[0]); treeData.value = listToTree(res.items, {
} pid: 'parentId',
} });
});
}
return { function handleNodeChange(selectKeys: String[]) {
L, if (selectKeys.length > 0) {
title, emits('change', selectKeys[0]);
treeData, }
replaceFields, }
registerDataModal,
openDataModal,
registerItemModal,
openItemModal,
getContentMenus,
handleNodeChange,
onLoadAllDataDic,
};
},
});
</script> </script>

36
apps/vue/src/views/platform/dataDic/index.vue

@ -10,34 +10,20 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from 'vue'; export default {
import { useI18n } from '/@/hooks/web/useI18n'; name: 'DataDictionary',
};
</script>
<script lang="ts" setup>
import { ref } from 'vue';
import { Row, Col } from 'ant-design-vue';
import DataTree from './components/DataTree.vue'; import DataTree from './components/DataTree.vue';
import DataItemTable from './components/DataItemTable.vue'; import DataItemTable from './components/DataItemTable.vue';
import { Row, Col } from 'ant-design-vue';
export default defineComponent({ const dataId = ref('');
name: 'DataDictionary',
components: {
DataTree,
DataItemTable,
Row,
Col,
},
setup() {
const { t } = useI18n();
const dataId = ref('');
return { function handleDataChange(id: string) {
t, dataId.value = id;
dataId, }
};
},
methods: {
handleDataChange(id: string) {
this.dataId = id;
},
},
});
</script> </script>

94
apps/vue/src/views/platform/layout/components/LayoutModal.vue

@ -8,9 +8,8 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useModalInner } from '/@/components/Modal'; import { useModalInner } from '/@/components/Modal';
import { BasicModalForm } from '/@/components/ModalForm'; import { BasicModalForm } from '/@/components/ModalForm';
@ -18,60 +17,43 @@
import { Layout } from '/@/api/platform/model/layoutModel'; import { Layout } from '/@/api/platform/model/layoutModel';
import { create, update } from '/@/api/platform/layout'; import { create, update } from '/@/api/platform/layout';
export default defineComponent({ const emits = defineEmits(['change', 'register']);
name: 'LayoutModal',
components: {
BasicModalForm,
},
emits: ['change', 'register'],
setup() {
const { L } = useLocalization('AppPlatform');
const layout = ref<Layout>({} as Layout);
const formItems = getModalFormSchemas(layout.value);
const [register, { closeModal }] = useModalInner((dataVal) => {
layout.value = dataVal;
});
const title = computed(() => { const { L } = useLocalization('AppPlatform');
if (layout.value.id) { const layout = ref<Layout>({} as Layout);
return L('Layout:EditByName', [layout.value.displayName] as Recordable); const formItems = getModalFormSchemas(layout.value);
} const [register, { closeModal }] = useModalInner((dataVal) => {
return L('Layout:AddNew'); layout.value = dataVal;
}); });
return { const title = computed(() => {
L, if (layout.value.id) {
layout, return L('Layout:EditByName', [layout.value.displayName] as Recordable);
register, }
closeModal, return L('Layout:AddNew');
formItems,
title,
};
},
methods: {
handleSaveChanges(data) {
const api =
data.id === undefined
? create({
dataId: data.dataId,
framework: data.framework,
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
})
: update(data.id, {
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
});
return api.then(() => {
this.$emit('change');
});
},
},
}); });
function handleSaveChanges(data) {
const api = data.id === undefined
? create({
dataId: data.dataId,
framework: data.framework,
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
})
: update(data.id, {
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
});
return api.then(() => {
emits('change');
closeModal();
});
}
</script> </script>

105
apps/vue/src/views/platform/layout/components/LayoutTable.vue

@ -26,15 +26,13 @@
</template> </template>
</template> </template>
</BasicTable> </BasicTable>
<LayoutModal @change="reloadTable" @register="registerLayoutModal" :layout-id="layoutId" /> <LayoutModal @change="reload" @register="registerLayoutModal" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Modal } from 'ant-design-vue';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import { BasicTable, useTable, TableAction } from '/@/components/Table'; import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
@ -42,64 +40,49 @@
import { getList, deleteById } from '/@/api/platform/layout'; import { getList, deleteById } from '/@/api/platform/layout';
import { formatPagedRequest } from '/@/utils/http/abp/helper'; import { formatPagedRequest } from '/@/utils/http/abp/helper';
import LayoutModal from './LayoutModal.vue'; import LayoutModal from './LayoutModal.vue';
export default defineComponent({
name: 'LayoutTable',
components: {
BasicTable,
TableAction,
LayoutModal,
},
setup() {
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const layoutId = ref('');
const [registerTable, { reload: reloadTable }] = useTable({
rowKey: 'id',
title: L('DisplayName:Layout'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
bordered: true,
canResize: true,
showTableSetting: true,
useSearchForm: true,
formConfig: getSearchFormSchemas(),
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerLayoutModal, { openModal: openLayoutModal }] = useModal();
return { const { createMessage, createConfirm } = useMessage();
L, const { L } = useLocalization(['AppPlatform', 'AbpUi']);
layoutId, const [registerTable, { reload }] = useTable({
reloadTable, rowKey: 'id',
registerTable, title: L('DisplayName:Layout'),
openLayoutModal, columns: getDataColumns(),
registerLayoutModal, api: getList,
}; beforeFetch: formatPagedRequest,
bordered: true,
canResize: true,
showTableSetting: true,
useSearchForm: true,
formConfig: getSearchFormSchemas(),
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
}, },
methods: { });
handleAddNew() { const [registerLayoutModal, { openModal: openLayoutModal }] = useModal();
this.openLayoutModal(true, {}, true);
}, function handleAddNew() {
handleEdit(record: Recordable) { openLayoutModal(true, {});
this.openLayoutModal(true, record, true); }
},
handleDelete(record: Recordable) { function handleEdit(record: Recordable) {
Modal.warning({ openLayoutModal(true, record);
title: this.L('AreYouSure'), }
content: this.L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
okCancel: true, function handleDelete(record: Recordable) {
onOk: () => { createConfirm({
deleteById(record.id).then(() => { iconType: 'warning',
this.reloadTable(); title: L('AreYouSure'),
}); content: L('ItemWillBeDeletedMessageWithFormat', [record.displayName]),
}, okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
}); });
}, },
}, });
}); }
</script> </script>

77
apps/vue/src/views/platform/menu/components/MenuDrawer.vue

@ -22,58 +22,45 @@
</BasicDrawer> </BasicDrawer>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { nextTick, ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { TabForm, FormActionType } from '/@/components/Form'; import { TabForm, FormActionType } from '/@/components/Form';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { basicProps } from './props'; import { basicProps } from './props';
import { Menu } from '/@/api/platform/model/menuModel'; import { Menu } from '/@/api/platform/model/menuModel';
import { useMenuFormContext } from '../hooks/useMenuFormContext'; import { useMenuFormContext } from '../hooks/useMenuFormContext';
export default defineComponent({ const emits = defineEmits(['change', 'register']);
name: 'MenuDrawer', const props = defineProps(basicProps);
components: {
BasicDrawer,
TabForm,
},
props: basicProps,
emits: ['change', 'register'],
setup(props) {
const menu = ref<Menu>({} as Menu);
const framework = ref<string | undefined>('');
const formElRef = ref<Nullable<FormActionType>>(null);
const { formTitle, getFormSchemas, handleFormSubmit, fetchLayoutResource } =
useMenuFormContext({
menuModel: menu,
formElRef: formElRef,
framework: framework,
});
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (dataVal) => { const { createMessage } = useMessage();
setDrawerProps({ confirmLoading: false }); const { L } = useLocalization(['AppPlatform', 'AbpUi']);
menu.value = dataVal; const menu = ref<Menu>({} as Menu);
framework.value = props.framework; const framework = ref<string | undefined>('');
fetchLayoutResource(dataVal.layoutId); const formElRef = ref<Nullable<FormActionType>>(null);
}); const { formTitle, getFormSchemas, handleFormSubmit, fetchLayoutResource } =
useMenuFormContext({
menuModel: menu,
formElRef: formElRef,
framework: framework,
});
return { const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner((dataVal) => {
formTitle, menu.value = dataVal;
formElRef, framework.value = props.framework;
handleFormSubmit, nextTick(() => {
getFormSchemas, setDrawerProps({ confirmLoading: false });
registerDrawer, fetchLayoutResource(dataVal.layoutId);
closeDrawer, });
};
},
methods: {
handleSubmit() {
this.handleFormSubmit()?.then(() => {
this.closeDrawer();
this.$emit('change');
});
},
},
}); });
function handleSubmit() {
handleFormSubmit()?.then(() => {
createMessage.success(L('Successful'));
closeDrawer();
emits('change');
});
}
</script> </script>

140
apps/vue/src/views/platform/menu/components/MenuTable.vue

@ -30,94 +30,80 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { Modal } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization'; import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, useTable, TableAction } from '/@/components/Table'; import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useDrawer } from '/@/components/Drawer'; import { useDrawer } from '/@/components/Drawer';
import MenuDrawer from './MenuDrawer.vue';
import { getDataColumns } from './TableData'; import { getDataColumns } from './TableData';
import { getSearchFormSchemas } from './ModalData'; import { getSearchFormSchemas } from './ModalData';
import { getAll, getById, deleteById } from '/@/api/platform/menu'; import { getAll, getById, deleteById } from '/@/api/platform/menu';
import { listToTree } from '/@/utils/helper/treeHelper'; import { listToTree } from '/@/utils/helper/treeHelper';
export default defineComponent({ import MenuDrawer from './MenuDrawer.vue';
name: 'MenuTable',
components: { const { createMessage, createConfirm } = useMessage();
BasicTable, const { L } = useLocalization(['AppPlatform', 'AbpUi']);
TableAction, const useFramework = ref('');
MenuDrawer, const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:Menus'),
columns: getDataColumns(),
api: getAll,
beforeFetch: (request) => {
// ,
useFramework.value = request.framework;
return request;
}, },
setup() { afterFetch: (result) => {
const { L } = useLocalization(['AppPlatform', 'AbpUi']); return listToTree(result, {
const useFramework = ref(''); id: 'id',
const [registerTable, { reload: reloadTable }] = useTable({ pid: 'parentId',
rowKey: 'id',
title: L('DisplayName:Menus'),
columns: getDataColumns(),
api: getAll,
beforeFetch: (request) => {
// ,
useFramework.value = request.framework;
return request;
},
afterFetch: (result) => {
return listToTree(result, {
id: 'id',
pid: 'parentId',
});
},
pagination: false,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
}); });
},
pagination: false,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerDrawer, { openDrawer }] = useDrawer(); const [registerDrawer, { openDrawer }] = useDrawer();
return { function handleAddNew() {
L, openDrawer(true, {});
registerTable, }
reloadTable,
registerDrawer, function handleEdit(record: Recordable) {
openDrawer, getById(record.id).then((menu) => {
useFramework, openDrawer(true, menu);
}; });
}, }
methods: {
handleAddNew() { function handleDelete(record: Recordable) {
this.openDrawer(true, {}, true); createConfirm({
}, iconType: 'warning',
handleEdit(record: Recordable) { title: L('AreYouSure'),
getById(record.id).then((menu) => { content: L('ItemWillBeDeletedMessageWithFormat', [record.displayName]),
this.openDrawer(true, menu, true); okCancel: true,
}); onOk: () => {
}, deleteById(record.id).then(() => {
handleDelete(record: Recordable) { createMessage.success(L('SuccessfullyDeleted'));
Modal.warning({ reload();
title: this.L('AreYouSure'),
content: this.L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
this.reloadTable();
});
},
}); });
}, },
handleChange() { });
this.reloadTable(); }
},
}, function handleChange() {
}); reload();
}
</script> </script>

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

Loading…
Cancel
Save