@scx-js/scx-admin 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/components/crud/crud-add-button.vue +28 -0
  2. package/components/crud/crud-batch-delete.vue +27 -0
  3. package/components/crud/crud-edit-dialog.vue +36 -0
  4. package/components/crud/crud-edit-form.vue +28 -0
  5. package/components/crud/crud-form-footer.vue +28 -0
  6. package/components/crud/crud-pagination.vue +51 -0
  7. package/components/crud/crud-reset-button.vue +19 -0
  8. package/components/crud/crud-search-button.vue +25 -0
  9. package/components/crud/crud-table-delete-button.vue +31 -0
  10. package/components/crud/crud-table-edit-button.vue +26 -0
  11. package/components/crud/crud-table.vue +131 -0
  12. package/components/crud/index.css +46 -0
  13. package/components/crud/index.vue +37 -0
  14. package/components/easy-ckeditor/default-editor-config.js +199 -0
  15. package/components/easy-ckeditor/easy-ckeditor-lazy.css +17 -0
  16. package/components/easy-ckeditor/easy-ckeditor-lazy.vue +106 -0
  17. package/components/easy-ckeditor/index.css +3 -0
  18. package/components/easy-ckeditor/index.vue +58 -0
  19. package/components/easy-ckeditor/plugins/scx-upload-adapter.js +39 -0
  20. package/components/easy-form-item/index.vue +168 -0
  21. package/components/easy-image/index.css +24 -0
  22. package/components/easy-image/index.vue +75 -0
  23. package/components/easy-monaco-editor/index.css +8 -0
  24. package/components/easy-monaco-editor/index.vue +70 -0
  25. package/components/easy-monaco-editor/use-worker.js +27 -0
  26. package/components/easy-select/index.vue +29 -0
  27. package/components/easy-upload/index.vue +94 -0
  28. package/components/easy-upload-list/index.vue +107 -0
  29. package/components/index.js +69 -0
  30. package/components/left-tree/index.css +74 -0
  31. package/components/left-tree/index.vue +130 -0
  32. package/components/scx-container/index.css +19 -0
  33. package/components/scx-container/index.vue +22 -0
  34. package/components/user-profile/change-password-dialog.vue +100 -0
  35. package/components/user-profile/change-user-avatar.vue +43 -0
  36. package/components/user-profile/change-username-dialog.vue +82 -0
  37. package/components/user-profile/index.css +8 -0
  38. package/components/user-profile/index.vue +77 -0
  39. package/index.js +4 -0
  40. package/layout/img/default-avatar.gif +0 -0
  41. package/layout/index.vue +24 -0
  42. package/layout/scx-app.vue +110 -0
  43. package/layout/scx-input.vue +84 -0
  44. package/layout/scx-logo.vue +65 -0
  45. package/layout/scx-main.vue +48 -0
  46. package/layout/scx-menu-item.vue +47 -0
  47. package/layout/scx-menu-toggle.vue +69 -0
  48. package/layout/scx-menu.vue +122 -0
  49. package/layout/scx-navbar.vue +47 -0
  50. package/layout/scx-notice.vue +211 -0
  51. package/layout/scx-sidebar.vue +70 -0
  52. package/layout/scx-theme-switch.vue +54 -0
  53. package/layout/scx-user-panel.vue +193 -0
  54. package/package.json +30 -0
  55. package/routes.js +57 -0
  56. package/scx/ali-oss.js +87 -0
  57. package/scx/auth-fetch.js +68 -0
  58. package/scx/crud-context.js +522 -0
  59. package/scx/easy-option.js +131 -0
  60. package/scx/index.js +8 -0
  61. package/scx/scx-auth-info.js +48 -0
  62. package/scx/scx-auth.js +197 -0
  63. package/scx/scx-config-manager.js +105 -0
  64. package/scx/scx-router.js +273 -0
  65. package/styles/index.css +37 -0
  66. package/util/cities.js +350 -0
  67. package/util/duration-format.js +27 -0
  68. package/util/element-plus-helper.js +114 -0
  69. package/util/get-order-number.js +7 -0
  70. package/util/index.js +4 -0
  71. package/util/nations.js +16 -0
  72. package/util/provinces.js +41 -0
  73. package/views/error-page.vue +79 -0
  74. package/views/login/index.css +95 -0
  75. package/views/login/login-and-register.vue +66 -0
  76. package/views/login/login-bg.vue +121 -0
  77. package/views/login/login-form-bg.vue +61 -0
  78. package/views/login/login-form.vue +137 -0
  79. package/views/login/login-message.js +28 -0
  80. package/views/login/login.vue +29 -0
  81. package/views/login/register-form.vue +148 -0
  82. package/views/no-perm.vue +7 -0
  83. package/views/not-found.vue +7 -0
  84. package/views/rocket.vue +84 -0
@@ -0,0 +1,70 @@
1
+ <template>
2
+ <div ref="monacoEditorDomRef" class="easy-monaco-editor"></div>
3
+ </template>
4
+ <script>
5
+ import "./index.css";
6
+ import {onMounted, ref, watch} from "vue";
7
+ import {editor} from "monaco-editor";
8
+ import "./use-worker.js";
9
+
10
+ export default {
11
+ name: "easy-monaco-editor",
12
+ props: {
13
+ modelValue: {
14
+ type: String,
15
+ default: ""
16
+ },
17
+ language: {
18
+ type: String,
19
+ default: "javascript"
20
+ },
21
+ theme: {
22
+ type: String,
23
+ default: "vs-dark"
24
+ }
25
+ },
26
+ setup(props, ctx) {
27
+
28
+ const monacoEditorDomRef = ref();
29
+
30
+ let currentEditor = null;
31
+
32
+ function initEditor() {
33
+ return editor.create(monacoEditorDomRef.value, {
34
+ value: "",
35
+ language: props.language,
36
+ automaticLayout: true
37
+ });
38
+ }
39
+
40
+ function startWatch() {
41
+ watch(() => props.modelValue, (value) => {
42
+ if (value !== currentEditor.getValue()) {
43
+ currentEditor.setValue(value);
44
+ }
45
+ }, {immediate: true});
46
+
47
+ watch(() => props.theme, (value) => {
48
+ editor.setTheme(value);
49
+ }, {immediate: true});
50
+ }
51
+
52
+ function bindEvent() {
53
+ currentEditor.onDidChangeModelContent((c) => {
54
+ const value = currentEditor.getValue();
55
+ ctx.emit("update:modelValue", value);
56
+ });
57
+ }
58
+
59
+ onMounted(() => {
60
+ currentEditor = initEditor();
61
+ startWatch();
62
+ bindEvent();
63
+ });
64
+
65
+ return {
66
+ monacoEditorDomRef
67
+ };
68
+ }
69
+ };
70
+ </script>
@@ -0,0 +1,27 @@
1
+ import EditorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
2
+ import JsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
3
+ import CSSWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
4
+ import HTMLWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
5
+ import TSWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
6
+
7
+ self.MonacoEnvironment = {
8
+ getWorker(workerId, label) {
9
+ switch (label) {
10
+ case "json":
11
+ return new JsonWorker();
12
+ case "css":
13
+ case "scss":
14
+ case "less":
15
+ return new CSSWorker();
16
+ case "html":
17
+ case "handlebars":
18
+ case "razor":
19
+ return new HTMLWorker();
20
+ case "typescript":
21
+ case "javascript":
22
+ return new TSWorker();
23
+ default:
24
+ return new EditorWorker();
25
+ }
26
+ },
27
+ };
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <el-select clearable filterable>
3
+ <el-option v-for="item in easyOption.options"
4
+ :key="easyOption.valueSupplier(item)"
5
+ :label="easyOption.labelSupplier(item)"
6
+ :value="easyOption.valueSupplier(item)"/>
7
+ </el-select>
8
+ </template>
9
+
10
+ <script>
11
+ import {EasyOption} from "../../scx/index.js";
12
+
13
+ export default {
14
+ name: "easy-select",
15
+ props: {
16
+ easyOption: {
17
+ type: EasyOption,
18
+ default: null,
19
+ }
20
+ },
21
+ setup(props) {
22
+
23
+ }
24
+ };
25
+ </script>
26
+
27
+ <style scoped>
28
+
29
+ </style>
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <scx-upload v-model="proxyModelValue"
3
+ :before-upload="beforeUpload"
4
+ :disabled="disabled"
5
+ :file-info-handler="getFileInfoHandler()"
6
+ :on-error="onError"
7
+ :upload-handler="getUploadHandler()"/>
8
+ </template>
9
+
10
+ <script>
11
+ import {computed} from "vue";
12
+ import {ElMessage} from "element-plus";
13
+ import {useAliOSS} from "../../index.js";
14
+ import {ScxUpload} from "@scx-js/scx-ui";
15
+
16
+ export default {
17
+ name: "easy-upload",
18
+ components: {ScxUpload},
19
+ props: {
20
+ modelValue: {
21
+ type: String,
22
+ default: null
23
+ },
24
+ uploadHandler: {
25
+ type: Function,
26
+ default: null //优先级大于 uploadHandlerType 指定的
27
+ },
28
+ fileInfoHandler: {
29
+ type: Function,
30
+ default: null
31
+ },
32
+ beforeUpload: {
33
+ type: Function,
34
+ default: null
35
+ },
36
+ uploadHandlerType: {
37
+ type: String,
38
+ default: "scx-fss" // 取值 scx-fss ali-oss
39
+ },
40
+ disabled: {
41
+ type: Boolean,
42
+ default: false
43
+ }
44
+ },
45
+ setup(props, ctx) {
46
+ const aliOSS = useAliOSS();
47
+
48
+ const proxyModelValue = computed({
49
+ get() {
50
+ return props.modelValue;
51
+ },
52
+ set(value) {
53
+ ctx.emit("update:modelValue", value);
54
+ }
55
+ });
56
+
57
+ function getUploadHandler() {
58
+ if (props.uploadHandler) {
59
+ return props.uploadHandler;
60
+ } else if (props.uploadHandlerType === "scx-fss") {
61
+ return null;
62
+ } else if (props.uploadHandlerType === "ali-oss") {
63
+ return (e, p) => aliOSS.upload(e, p);
64
+ } else {
65
+ throw new Error("未知的 uploadHandlerType : " + props.uploadHandlerType);
66
+ }
67
+ }
68
+
69
+ function getFileInfoHandler() {
70
+ if (props.fileInfoHandler) {
71
+ return props.fileInfoHandler;
72
+ } else if (props.uploadHandlerType === "scx-fss") {
73
+ return null;//这里添加压缩参数
74
+ } else if (props.uploadHandlerType === "ali-oss") {
75
+ return (e) => aliOSS.info(e);
76
+ } else {
77
+ throw new Error("未知的 uploadHandlerType : " + props.uploadHandlerType);
78
+ }
79
+ }
80
+
81
+ const onError = (error, files) => {
82
+ ElMessage.error(error);
83
+ };
84
+
85
+ return {
86
+ proxyModelValue,
87
+ getUploadHandler,
88
+ getFileInfoHandler,
89
+ onError,
90
+ };
91
+
92
+ }
93
+ };
94
+ </script>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <scx-upload-list v-model="proxyModelValue"
3
+ :before-upload="getBeforeUpload"
4
+ :file-info-handler="getFileInfoHandler()"
5
+ :on-error="onError"
6
+ :upload-handler="getUploadHandler()">
7
+ <template #default="{index,item}">
8
+ <slot :index="index" :item="item">
9
+ </slot>
10
+ </template>
11
+ </scx-upload-list>
12
+ </template>
13
+
14
+ <script>
15
+ import {computed} from "vue";
16
+ import {ElMessage} from "element-plus";
17
+ import {useAliOSS} from "../../index.js";
18
+ import {ScxUploadList} from "@scx-js/scx-ui";
19
+
20
+ export default {
21
+ name: "easy-upload-list",
22
+ components: {ScxUploadList},
23
+ props: {
24
+ modelValue: {
25
+ type: Array,
26
+ default: null
27
+ },
28
+ uploadHandler: {
29
+ type: Function,
30
+ default: null //优先级大于 uploadHandlerType 指定的
31
+ },
32
+ fileInfoHandler: {
33
+ type: Function,
34
+ default: null
35
+ },
36
+ beforeUpload: {
37
+ type: Function,
38
+ default: null
39
+ },
40
+ uploadHandlerType: {
41
+ type: String,
42
+ default: "scx-fss" // 取值 scx-fss ali-oss
43
+ },
44
+ limit: {
45
+ type: Number,
46
+ default: null
47
+ }
48
+ },
49
+ setup(props, ctx) {
50
+ const aliOSS = useAliOSS();
51
+
52
+ const proxyModelValue = computed({
53
+ get() {
54
+ return props.modelValue ? props.modelValue : [];
55
+ },
56
+ set(value) {
57
+ ctx.emit("update:modelValue", value);
58
+ }
59
+ });
60
+
61
+ function getUploadHandler() {
62
+ if (props.uploadHandler) {
63
+ return props.uploadHandler;
64
+ } else if (props.uploadHandlerType === "scx-fss") {
65
+ return null;
66
+ } else if (props.uploadHandlerType === "ali-oss") {
67
+ return (e, p) => aliOSS.upload(e, p);
68
+ } else {
69
+ throw new Error("未知的 uploadHandlerType : " + props.uploadHandlerType);
70
+ }
71
+ }
72
+
73
+ function getFileInfoHandler() {
74
+ if (props.fileInfoHandler) {
75
+ return props.fileInfoHandler;
76
+ } else if (props.uploadHandlerType === "scx-fss") {
77
+ return null;//这里添加压缩参数
78
+ } else if (props.uploadHandlerType === "ali-oss") {
79
+ return (e) => aliOSS.info(e);
80
+ } else {
81
+ throw new Error("未知的 uploadHandlerType : " + props.uploadHandlerType);
82
+ }
83
+ }
84
+
85
+ const onError = (error, files) => {
86
+ ElMessage.error(error);
87
+ };
88
+
89
+ const getBeforeUpload = (files) => {
90
+ if (props.limit && proxyModelValue.value.length + files.length > props.limit) {
91
+ ElMessage.warning("文件数量超出上限, 上限 : " + props.limit + " !!!");
92
+ return false;
93
+ }
94
+ return props.beforeUpload ? props.beforeUpload(files) : true;
95
+ };
96
+
97
+ return {
98
+ proxyModelValue,
99
+ getUploadHandler,
100
+ getFileInfoHandler,
101
+ onError,
102
+ getBeforeUpload
103
+ };
104
+
105
+ }
106
+ };
107
+ </script>
@@ -0,0 +1,69 @@
1
+ //以下为组件
2
+ import CrudAddButton from "./crud/crud-add-button.vue";
3
+ import CrudBatchDelete from "./crud/crud-batch-delete.vue";
4
+ import CrudEditDialog from "./crud/crud-edit-dialog.vue";
5
+ import CrudEditForm from "./crud/crud-edit-form.vue";
6
+ import CrudFormFooter from "./crud/crud-form-footer.vue";
7
+ import CrudPagination from "./crud/crud-pagination.vue";
8
+ import CrudResetButton from "./crud/crud-reset-button.vue";
9
+ import CrudSearchButton from "./crud/crud-search-button.vue";
10
+ import CrudTable from "./crud/crud-table.vue";
11
+ import CrudTableDeleteButton from "./crud/crud-table-delete-button.vue";
12
+ import CrudTableEditButton from "./crud/crud-table-edit-button.vue";
13
+ import Crud from "./crud/index.vue";
14
+ //组件过重 暂时不引入 如需使用请单独引入
15
+ // import EasyCkeditor from "./easy-ckeditor/index.vue";
16
+ // import EasyCkeditorLazy from "./easy-ckeditor/easy-ckeditor-lazy.vue";
17
+ import EasyFormItem from "./easy-form-item/index.vue";
18
+ import EasyImage from "./easy-image/index.vue";
19
+ //组件过重 暂时不引入 如需使用请单独引入
20
+ // import EasyMonacoEditor from "./easy-monaco-editor/index.vue";
21
+ import EasySelect from "./easy-select/index.vue";
22
+ import EasyUpload from "./easy-upload/index.vue";
23
+ import EasyUploadList from "./easy-upload-list/index.vue";
24
+ import LeftTree from "./left-tree/index.vue";
25
+ import ScxContainer from "./scx-container/index.vue";
26
+ import UserProfile from "./user-profile/index.vue";
27
+
28
+
29
+ const components = [
30
+ CrudAddButton,
31
+ CrudBatchDelete,
32
+ CrudEditDialog,
33
+ CrudEditForm,
34
+ CrudFormFooter,
35
+ CrudPagination,
36
+ CrudResetButton,
37
+ CrudSearchButton,
38
+ CrudTable,
39
+ CrudTableDeleteButton,
40
+ CrudTableEditButton,
41
+ Crud,
42
+ EasyFormItem,
43
+ EasyImage,
44
+ EasySelect,
45
+ EasyUpload,
46
+ EasyUploadList,
47
+ LeftTree,
48
+ ScxContainer,
49
+ UserProfile,
50
+ ];
51
+
52
+ const directives = [];
53
+
54
+ const ScxAdminComponent = {
55
+
56
+ install(app) {
57
+ //安装组件
58
+ components.forEach(c => {
59
+ app.component(c.name, c);
60
+ console.log(c);
61
+ });
62
+ //安装指令
63
+ directives.forEach(d => app.directive(d.name, d));
64
+ },
65
+ };
66
+
67
+ export {
68
+ ScxAdminComponent,
69
+ };
@@ -0,0 +1,74 @@
1
+ .left-tree {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ row-gap: 5px;
6
+ height: 100%;
7
+ width: 100%;
8
+ padding: 5px;
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ .left-tree-hearer {
13
+ position: relative;
14
+ width: 100%;
15
+ display: flex;
16
+ justify-content: center;
17
+ align-items: center;
18
+ }
19
+
20
+ .left-tree-refresh-button {
21
+ position: absolute;
22
+ left: 2px;
23
+ }
24
+
25
+ .left-tree-title {
26
+ font-size: 20px;
27
+ }
28
+
29
+ .left-tree-title-info {
30
+ position: absolute;
31
+ right: 2px;
32
+ bottom: 0;
33
+ font-size: 13px;
34
+ font-weight: 600;
35
+ color: #5d5d5d;
36
+ }
37
+
38
+ .tree1 {
39
+ height: 100%;
40
+ width: 100%;
41
+ overflow: auto;
42
+ background-color: var(--scx-overlay-bg);
43
+ box-shadow: var(--scx-box-shadow-center);
44
+ }
45
+
46
+ .custom-tree-node {
47
+ flex: 1;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: space-between;
51
+ font-size: 14px;
52
+ padding-right: 8px;
53
+ }
54
+
55
+ /* 针对 常用情况定义的 css */
56
+
57
+ .custom-tree-node > .e1 {
58
+ display: flex;
59
+ user-select: none;
60
+ font-weight: 600;
61
+ }
62
+
63
+ .custom-tree-node > .e1 > .e2 {
64
+ color: #13ce2f;
65
+ margin-right: 5px
66
+ }
67
+
68
+ .custom-tree-node > .e1 > .e2:hover {
69
+ color: #067e18;
70
+ }
71
+
72
+ .custom-tree-node .e7 {
73
+ font-weight: 600;
74
+ }
@@ -0,0 +1,130 @@
1
+ <template>
2
+
3
+ <div class="left-tree">
4
+
5
+ <div class="left-tree-hearer">
6
+
7
+ <el-button class="left-tree-refresh-button" size="small" @click="refresh()">
8
+ <scx-icon icon="outlined-sync"/>
9
+ </el-button>
10
+
11
+ <div class="left-tree-title">
12
+ <slot name="left-tree-title">
13
+
14
+ </slot>
15
+ </div>
16
+
17
+ <div class="left-tree-title-info">
18
+ <slot name="left-tree-title-info">
19
+
20
+ </slot>
21
+ </div>
22
+
23
+ </div>
24
+
25
+ <el-input v-model="filterText" clearable placeholder="输入名称进行过滤"/>
26
+
27
+ <el-tree ref="treeRef"
28
+ :allow-drag="allowDrag"
29
+ :allow-drop="allowDrop"
30
+ :data="treeData"
31
+ :draggable="!readonly"
32
+ :expand-on-click-node="false"
33
+ :filter-node-method="filterNode"
34
+ :highlight-current="true"
35
+ class="tree1" default-expand-all node-key="id"
36
+ @node-click="nodeClick" @node-contextmenu="nodeContextMenu" @node-drop="nodeDrop">
37
+
38
+ <template #default="{ data }">
39
+
40
+ <div class="custom-tree-node">
41
+ <slot :data="data" name="tree-node">
42
+
43
+ </slot>
44
+ </div>
45
+
46
+ </template>
47
+
48
+ </el-tree>
49
+
50
+ <slot>
51
+
52
+ </slot>
53
+
54
+ </div>
55
+ </template>
56
+ <script>
57
+ import {ref, watch} from "vue";
58
+
59
+ export default {
60
+ name: "left-tree",
61
+ props: {
62
+ readonly: {
63
+ type: Boolean,
64
+ default: false
65
+ },
66
+ treeData: {
67
+ type: Array,
68
+ default: [],
69
+ },
70
+ allowDrag: {
71
+ type: Function,
72
+ default: null
73
+ },
74
+ allowDrop: {
75
+ type: Function,
76
+ default: null
77
+ }
78
+ },
79
+ emits: ["refresh", "nodeClick", "nodeContextMenu", "nodeDrop"],
80
+ setup(props, ctx) {
81
+
82
+ const filterText = ref("");
83
+
84
+ const treeRef = ref();
85
+
86
+ //监控 filterText 以实现树的过滤
87
+ watch(filterText, (val) => {
88
+ treeRef.value.filter(val);
89
+ });
90
+
91
+ function filterNode(value, data) {
92
+ if (!value) {
93
+ return true;
94
+ }
95
+ return data.name.indexOf(value) !== -1;
96
+ }
97
+
98
+ function refresh() {
99
+ ctx.emit("refresh");
100
+ }
101
+
102
+ function nodeDrop(dragNode, dropNode, type) {
103
+ ctx.emit("nodeDrop", dragNode, dropNode, type);
104
+ }
105
+
106
+ function nodeClick(node) {
107
+ ctx.emit("nodeClick", node);
108
+ }
109
+
110
+ function nodeContextMenu(e, data) {
111
+ ctx.emit("nodeContextMenu", e, data);
112
+ }
113
+
114
+ return {
115
+ filterText,
116
+ filterNode,
117
+ refresh,
118
+ nodeDrop,
119
+ nodeClick,
120
+ nodeContextMenu
121
+
122
+ };
123
+ }
124
+ };
125
+
126
+ </script>
127
+ <style>
128
+ @import "./index.css";
129
+
130
+ </style>
@@ -0,0 +1,19 @@
1
+ .scx-container {
2
+ display: flex;
3
+ height: 100%;
4
+ }
5
+
6
+ .scx-container .left-page {
7
+ width: 20%;
8
+ min-width: 15%;
9
+ max-width: 50%;
10
+ border-right: 2px solid #a5a3a3;
11
+ flex-shrink: 0;
12
+ resize: horizontal;
13
+ overflow: auto;
14
+ }
15
+
16
+ .scx-container .right-page {
17
+ width: 100%;
18
+ overflow: auto;
19
+ }
@@ -0,0 +1,22 @@
1
+ <template>
2
+
3
+ <div class="scx-container">
4
+
5
+ <div class="left-page">
6
+ <slot name="left-page"/>
7
+ </div>
8
+
9
+ <div class="right-page">
10
+ <slot/>
11
+ </div>
12
+
13
+ </div>
14
+
15
+ </template>
16
+ <script>
17
+ import "./index.css";
18
+
19
+ export default {
20
+ name: "scx-container"
21
+ };
22
+ </script>