diff --git a/frontend/package.json b/frontend/package.json
index 862fcda4..677c94c8 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -37,6 +37,7 @@
"vue-dompurify-html": "^5.3.0",
"vue-i18n": "^9.14.4",
"vue-router": "^4.5.0",
+ "vue-types": "^6.0.0",
"web-storage-cache": "^1.1.1"
},
"devDependencies": {
diff --git a/frontend/src/api/user.ts b/frontend/src/api/user.ts
new file mode 100644
index 00000000..ded09a9f
--- /dev/null
+++ b/frontend/src/api/user.ts
@@ -0,0 +1,27 @@
+import { request } from '@/utils/request'
+
+export const userImportApi = {
+ downExcelTemplateApi: () => request.post('/user/excelTemplate', {}, { responseType: 'blob' }),
+ importUserApi: (data: any) =>
+ request.post('/user/batchImport', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ }),
+ downErrorRecordApi: (key: string) =>
+ request.get(`/user/errorRecord/${key}`, { responseType: 'blob' }),
+ clearErrorApi: (key: string) => {
+ request.get(`/user/clearErrorRecord/${key}`)
+ },
+}
+
+export const userApi = {
+ pager: (params: any, pageNumber: number, pageSize: number) =>
+ request.get(`/user/pager/${pageNumber}/${pageSize}${params}`),
+ add: (data: any) => request.post('/user', data),
+ edit: (data: any) => request.put('/user', data),
+ clearErrorApi: (key: string) => request.get(`/user/clearErrorRecord/${key}`),
+ delete: (key: string) => request.delete(`/user/${key}`),
+ get: (key: string) => request.get(`/user/${key}`),
+ pwd: (data: any) => request.put('/user/pwd', data),
+}
diff --git a/frontend/src/api/workspace.ts b/frontend/src/api/workspace.ts
new file mode 100644
index 00000000..25b8d6e7
--- /dev/null
+++ b/frontend/src/api/workspace.ts
@@ -0,0 +1,9 @@
+import { request } from '@/utils/request'
+
+export const workspaceUserList = (params: any, pageNum: number, pageSize: number) =>
+ request.get(`/system/workspace/uws/pager/${pageNum}/${pageSize}`, { params })
+
+export const workspaceCreate = (data: any) => request.post('/system/workspace/uws', data)
+export const workspaceDelete = (data: any) => request.delete('/system/workspace/uws', data)
+export const workspaceList = () => request.get('/system/workspace')
+export const workspaceDetail = (id: any) => request.get(`/system/workspace/${id}`)
diff --git a/frontend/src/assets/svg/gou_icon.svg b/frontend/src/assets/svg/gou_icon.svg
new file mode 100644
index 00000000..ef54599e
--- /dev/null
+++ b/frontend/src/assets/svg/gou_icon.svg
@@ -0,0 +1,11 @@
+
diff --git a/frontend/src/assets/svg/icon-filter_outlined.svg b/frontend/src/assets/svg/icon-filter_outlined.svg
new file mode 100644
index 00000000..2cee5a99
--- /dev/null
+++ b/frontend/src/assets/svg/icon-filter_outlined.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/src/assets/svg/icon-member-default.svg b/frontend/src/assets/svg/icon-member-default.svg
index 5444910e..9c932960 100644
--- a/frontend/src/assets/svg/icon-member-default.svg
+++ b/frontend/src/assets/svg/icon-member-default.svg
@@ -4,12 +4,12 @@
-
-
+
+
-
-
+
+
diff --git a/frontend/src/assets/svg/icon_assigned_outlined.svg b/frontend/src/assets/svg/icon_assigned_outlined.svg
new file mode 100644
index 00000000..ca199a73
--- /dev/null
+++ b/frontend/src/assets/svg/icon_assigned_outlined.svg
@@ -0,0 +1,5 @@
+
diff --git a/frontend/src/assets/svg/icon_ban_filled.svg b/frontend/src/assets/svg/icon_ban_filled.svg
new file mode 100644
index 00000000..fa22f12a
--- /dev/null
+++ b/frontend/src/assets/svg/icon_ban_filled.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/src/assets/svg/icon_ccm-upload_outlined.svg b/frontend/src/assets/svg/icon_ccm-upload_outlined.svg
new file mode 100644
index 00000000..938f8ea2
--- /dev/null
+++ b/frontend/src/assets/svg/icon_ccm-upload_outlined.svg
@@ -0,0 +1,4 @@
+
diff --git a/frontend/src/assets/svg/icon_close_outlined.svg b/frontend/src/assets/svg/icon_close_outlined.svg
new file mode 100644
index 00000000..124221e7
--- /dev/null
+++ b/frontend/src/assets/svg/icon_close_outlined.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/src/assets/svg/icon_info_colorful.svg b/frontend/src/assets/svg/icon_info_colorful.svg
new file mode 100644
index 00000000..633d6cc9
--- /dev/null
+++ b/frontend/src/assets/svg/icon_info_colorful.svg
@@ -0,0 +1,12 @@
+
diff --git a/frontend/src/assets/svg/icon_member.svg b/frontend/src/assets/svg/icon_member.svg
new file mode 100644
index 00000000..fe594998
--- /dev/null
+++ b/frontend/src/assets/svg/icon_member.svg
@@ -0,0 +1,4 @@
+
diff --git a/frontend/src/assets/svg/icon_member_filled.svg b/frontend/src/assets/svg/icon_member_filled.svg
new file mode 100644
index 00000000..fded3173
--- /dev/null
+++ b/frontend/src/assets/svg/icon_member_filled.svg
@@ -0,0 +1,4 @@
+
diff --git a/frontend/src/assets/svg/icon_rename_outlined.svg b/frontend/src/assets/svg/icon_rename_outlined.svg
new file mode 100644
index 00000000..f0af70f4
--- /dev/null
+++ b/frontend/src/assets/svg/icon_rename_outlined.svg
@@ -0,0 +1,4 @@
+
diff --git a/frontend/src/assets/svg/icon_upload_outlined.svg b/frontend/src/assets/svg/icon_upload_outlined.svg
new file mode 100644
index 00000000..d38c9c33
--- /dev/null
+++ b/frontend/src/assets/svg/icon_upload_outlined.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/src/assets/workspace/avatar_personal.png b/frontend/src/assets/workspace/avatar_personal.png
new file mode 100644
index 00000000..781f27b8
Binary files /dev/null and b/frontend/src/assets/workspace/avatar_personal.png differ
diff --git a/frontend/src/assets/workspace/default_avatar.png b/frontend/src/assets/workspace/default_avatar.png
new file mode 100644
index 00000000..ee6d4295
Binary files /dev/null and b/frontend/src/assets/workspace/default_avatar.png differ
diff --git a/frontend/src/assets/workspace/icon_custom-tools_colorful.png b/frontend/src/assets/workspace/icon_custom-tools_colorful.png
new file mode 100644
index 00000000..a7ceb246
Binary files /dev/null and b/frontend/src/assets/workspace/icon_custom-tools_colorful.png differ
diff --git a/frontend/src/components/drawer-filter/index.ts b/frontend/src/components/drawer-filter/index.ts
new file mode 100644
index 00000000..481382e6
--- /dev/null
+++ b/frontend/src/components/drawer-filter/index.ts
@@ -0,0 +1,3 @@
+import DrawerFilter from './src/DrawerFilter.vue'
+
+export { DrawerFilter }
diff --git a/frontend/src/components/drawer-filter/src/DrawerEnumFilter.vue b/frontend/src/components/drawer-filter/src/DrawerEnumFilter.vue
new file mode 100644
index 00000000..e845545c
--- /dev/null
+++ b/frontend/src/components/drawer-filter/src/DrawerEnumFilter.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
{{ title }}
+
+ {{ ele.name }}
+
+
+
+
+
diff --git a/frontend/src/components/drawer-filter/src/DrawerFilter.vue b/frontend/src/components/drawer-filter/src/DrawerFilter.vue
new file mode 100644
index 00000000..06724a97
--- /dev/null
+++ b/frontend/src/components/drawer-filter/src/DrawerFilter.vue
@@ -0,0 +1,91 @@
+
+
+
+
+
{{ title }}
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/drawer-main/index.ts b/frontend/src/components/drawer-main/index.ts
new file mode 100644
index 00000000..f8c594cc
--- /dev/null
+++ b/frontend/src/components/drawer-main/index.ts
@@ -0,0 +1,3 @@
+import DrawerMain from './src/DrawerMain.vue'
+
+export { DrawerMain }
diff --git a/frontend/src/components/drawer-main/src/DrawerMain.vue b/frontend/src/components/drawer-main/src/DrawerMain.vue
new file mode 100644
index 00000000..6f149b5b
--- /dev/null
+++ b/frontend/src/components/drawer-main/src/DrawerMain.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+ filterChange(v, component.field, 'in')"
+ />
+ filterChange(v, component.field, 'in')"
+ />
+
+
+
+ {{ t('common.reset') }}
+ {{ t('common.search') }}
+
+
+
+
+
diff --git a/frontend/src/components/filter-text/index.ts b/frontend/src/components/filter-text/index.ts
new file mode 100644
index 00000000..343a0af8
--- /dev/null
+++ b/frontend/src/components/filter-text/index.ts
@@ -0,0 +1,91 @@
+import FilterText from './src/FilterText.vue'
+
+export { FilterText }
+
+const fieldText = (field: string, options: any[]) => {
+ for (let index = 0; index < options.length; index++) {
+ const element = options[index]
+ if (field === element.field) {
+ return element.title
+ }
+ }
+}
+const valueTextFormTree = (val: string, options: any[]) => {
+ let result = null
+ const stack = [...options]
+ while (stack.length) {
+ const item = stack.pop()
+ if (item.value === val) {
+ result = item.label
+ break
+ }
+ if (item.children?.length) {
+ item.children.forEach((kid: any) => stack.push(kid))
+ }
+ }
+ return result || val
+}
+const timestampFormatDate = (value: string) => {
+ if (!value) {
+ return '-'
+ }
+ return new Date(value).toLocaleString()
+}
+const valueText = (field: string, val: string, options: any[]) => {
+ for (let index = 0; index < options.length; index++) {
+ const element = options[index]
+ if (field === element.field) {
+ let isTree = false
+ const selectOption = element.option
+ for (let i = 0; i < selectOption.length; i++) {
+ const item = selectOption[i] as any
+ if (item.children !== undefined) {
+ isTree = true
+ break
+ }
+ if (item.id === val || item.value === val) {
+ return item.name || item.label
+ }
+ }
+ if (element.type === 'time') {
+ return timestampFormatDate(val)
+ }
+ if (isTree) {
+ return valueTextFormTree(val, selectOption)
+ }
+ }
+ }
+ return val
+}
+export const convertFilterText = (conditions: any[], options: any[]) => {
+ console.log('conditions', conditions, options)
+
+ const result: any[] = []
+ conditions.forEach((condition) => {
+ const field = condition.field
+ const ope = condition.operator
+ const value = condition.value
+ const fieldName = fieldText(field, options)
+ const textOpe = ':'
+ let separator = ','
+ if (ope === 'in') {
+ separator = '、'
+ }
+ if (ope === 'between') {
+ separator = '~'
+ }
+ let valText = value
+
+ if (value) {
+ if (Array.isArray(value)) {
+ const valTextArray = value.map((val) => valueText(field, val, options))
+ valText = valTextArray.join(separator)
+ }
+ if (valText?.length) {
+ const obj = fieldName + textOpe + valText
+ result.push(obj)
+ }
+ }
+ })
+ return result
+}
diff --git a/frontend/src/components/filter-text/src/FilterText.vue b/frontend/src/components/filter-text/src/FilterText.vue
new file mode 100644
index 00000000..71fb6329
--- /dev/null
+++ b/frontend/src/components/filter-text/src/FilterText.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
{{ total }}
+
{{ t('common.result_count') }}
+
+
+
+
+
+
+
+ {{ ele }}
+
+
+
+
+
+
+
+
+
+ {{ t('common.clear_filter') }}
+
+
+
+
+
+
+
+
+ {{ t('common.clear_filter') }}
+
+
+
+
diff --git a/frontend/src/components/layout/LayoutDsl.vue b/frontend/src/components/layout/LayoutDsl.vue
index 0bb4da27..d851830b 100644
--- a/frontend/src/components/layout/LayoutDsl.vue
+++ b/frontend/src/components/layout/LayoutDsl.vue
@@ -9,11 +9,22 @@ import icon_moments_categories_outlined from '@/assets/svg/icon_moments-categori
import icon_side_fold_outlined from '@/assets/svg/icon_side-fold_outlined.svg'
import icon_side_expand_outlined from '@/assets/svg/icon_side-expand_outlined.svg'
import { useRoute, useRouter } from 'vue-router'
+
const router = useRouter()
const collapse = ref(false)
+import { useEmitt } from '@/utils/useEmitt'
+
+const handleCollapseChange = (val: any = true) => {
+ collapse.value = val
+}
+useEmitt({
+ name: 'collapse-change',
+ callback: handleCollapseChange,
+})
const handleFoldExpand = () => {
collapse.value = !collapse.value
}
+
const toWorkspace = () => {
router.push('/')
}
@@ -31,11 +42,16 @@ const showSysmenu = computed(() => {
-
+
- {{ collapse ? '' : '返回工作空间' }}
+ {{ collapse ? '' : $t('workspace.return_to_workspace') }}
@@ -85,14 +101,17 @@ const showSysmenu = computed(() => {
line-height: 22px;
width: calc(100% - 32px);
.back-to_workspace {
- background-color: #1f23290a;
- border: 1px solid #d0d3d6;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
height: 40px;
cursor: pointer;
+
+ &:not(.collapse) {
+ background: #1f23290a;
+ border: 1px solid #d9dcdf;
+ }
&:hover {
background-color: #1f23291a;
}
@@ -152,6 +171,7 @@ const showSysmenu = computed(() => {
flex: 1;
padding: 8px 8px 8px 0;
max-height: 100vh;
+ overflow-x: auto;
.content {
width: 100%;
diff --git a/frontend/src/components/layout/MenuItem.vue b/frontend/src/components/layout/MenuItem.vue
index 748452da..24b25d47 100644
--- a/frontend/src/components/layout/MenuItem.vue
+++ b/frontend/src/components/layout/MenuItem.vue
@@ -1,19 +1,22 @@
- {{ $t('ds.title') }}
+
{{ $t('ds.title') }}
@@ -206,6 +211,7 @@ const changeStatus = (row: any) => {
:key="ele.table_name"
class="model"
:class="currentTable.table_name === ele.table_name && 'isActive'"
+ :title="ele.table_name"
@click="clickTable(ele)"
>
@@ -353,8 +359,24 @@ const changeStatus = (row: any) => {
color: #646a73;
border-bottom: 1px solid #1f232926;
+ .ed-button {
+ height: 22px;
+ line-height: 22px;
+ color: #646a73;
+
+ &:hover {
+ background: #1cba901a;
+ color: #1cba90;
+ }
+ &:active {
+ color: #189e7a;
+ background: #1cba9033;
+ }
+ }
+
.name {
color: #1f2329;
+ margin-left: 4px;
}
}
.content {
@@ -372,7 +394,7 @@ const changeStatus = (row: any) => {
justify-content: space-between;
padding: 8px;
- .ed-icon:hover {
+ .ed-icon {
cursor: pointer;
color: var(--ed-color-primary);
}
@@ -392,11 +414,16 @@ const changeStatus = (row: any) => {
padding-left: 8px;
border-radius: 4px;
cursor: pointer;
+
.name {
margin-left: 8px;
font-weight: 500;
font-size: 14px;
line-height: 22px;
+ max-width: 80%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
&:hover {
background: #1f23291a;
diff --git a/frontend/src/views/ds/Datasource.vue b/frontend/src/views/ds/Datasource.vue
index 9881dad4..49c31176 100644
--- a/frontend/src/views/ds/Datasource.vue
+++ b/frontend/src/views/ds/Datasource.vue
@@ -1,5 +1,5 @@
@@ -187,7 +214,7 @@ const dataTableDetail = (ele: any) => {
- {{ $t('datasource.all_types') }}
+ {{ currentDefaultDatasource || $t('datasource.all_types') }}
{
:key="ele.id"
:name="ele.name"
:type="ele.type"
- :type_name="ele.type_name"
+ :type-name="ele.type_name"
+ :num="ele.num"
:description="ele.description"
@question="handleQuestion"
@edit="handleEditDatasource(ele)"
@@ -298,12 +326,13 @@ const dataTableDetail = (ele: any) => {
ref="datasourceFormRef"
:active-step="activeStep"
:active-name="activeName"
- @submit="submit"
+ :active-type="activeType"
+ @refresh="refresh"
@change-active-step="(val: number) => (activeStep = val)"
>
-
+
diff --git a/frontend/src/views/ds/DatasourceForm.vue b/frontend/src/views/ds/DatasourceForm.vue
index 323a4c56..5e502e9e 100644
--- a/frontend/src/views/ds/DatasourceForm.vue
+++ b/frontend/src/views/ds/DatasourceForm.vue
@@ -16,17 +16,19 @@ import EmptyBackground from '@/views/dashboard/common/EmptyBackground.vue'
const props = withDefaults(
defineProps<{
activeName: string
+ activeType: string
activeStep: number
}>(),
{
activeName: '',
+ activeType: '',
activeStep: 0,
}
)
const { wsCache } = useCache()
const dsFormRef = ref
()
-const emit = defineEmits(['refresh', 'submit', 'changeActiveStep'])
+const emit = defineEmits(['refresh', 'changeActiveStep'])
const isCreate = ref(true)
const isEditTable = ref(false)
const checkList = ref([])
@@ -62,7 +64,7 @@ const dialogVisible = ref(false)
const form = ref({
name: '',
description: '',
- type: 'mysql',
+ type: props.activeType,
configuration: '',
driver: '',
host: '',
@@ -330,14 +332,6 @@ onMounted(() => {
}, 100)
})
-const submitModle = () => {
- dsFormRef.value!.validate((res: any) => {
- if (res) {
- emit('submit')
- }
- })
-}
-
const keywords = ref('')
const tableListWithSearch = computed(() => {
if (!keywords.value) return tableList.value
@@ -354,6 +348,13 @@ watch(keywords, () => {
isIndeterminate.value = checkedCount > 0 && checkedCount < tableListWithSearch.value.length
})
+watch(
+ () => props.activeType,
+ (val) => {
+ form.value.type = val
+ }
+)
+
const checkAll = ref(false)
const isIndeterminate = ref(false)
let checkTableList = [] as any[]
@@ -390,7 +391,6 @@ const tableListSave = () => {
defineExpose({
initForm,
- submitModle,
tableListSave,
})
@@ -555,15 +555,15 @@ defineExpose({