@xilonglab/vue-main 0.7.8

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 (53) hide show
  1. package/dist/page/app.vue +86 -0
  2. package/dist/page/login.vue +185 -0
  3. package/dist/page/setting.vue +72 -0
  4. package/dist/style/app.less +58 -0
  5. package/dist/style/reset.css +32 -0
  6. package/package.json +15 -0
  7. package/packages/XlBreadcrumb.vue +85 -0
  8. package/packages/XlControlBar.vue +64 -0
  9. package/packages/XlSideBar.vue +135 -0
  10. package/packages/button/XlAsyncButton.vue +67 -0
  11. package/packages/button/XlButton.vue +25 -0
  12. package/packages/button/XlDeleteButton.vue +22 -0
  13. package/packages/button/XlEditButton.vue +22 -0
  14. package/packages/button/XlIconButton.vue +22 -0
  15. package/packages/button/XlUploadButton.vue +109 -0
  16. package/packages/dialog/XlDialog.vue +116 -0
  17. package/packages/dialog/XlEditReviewDialog.vue +81 -0
  18. package/packages/dialog/XlFormDialog.vue +79 -0
  19. package/packages/dialog/XlImagePreviewDialog.vue +40 -0
  20. package/packages/dialog/XlMessageDialog.vue +74 -0
  21. package/packages/dialog/XlReviewDialog.vue +115 -0
  22. package/packages/dialog/XlStateDialog.vue +21 -0
  23. package/packages/form/XlCascader.vue +46 -0
  24. package/packages/form/XlCheckbox.vue +45 -0
  25. package/packages/form/XlDate.vue +54 -0
  26. package/packages/form/XlFormCol.vue +19 -0
  27. package/packages/form/XlFormRow.vue +20 -0
  28. package/packages/form/XlImageInput.vue +127 -0
  29. package/packages/form/XlInput.vue +53 -0
  30. package/packages/form/XlMapSelect.vue +72 -0
  31. package/packages/form/XlNumber.vue +11 -0
  32. package/packages/form/XlRadio.vue +42 -0
  33. package/packages/form/XlRawSelect.vue +71 -0
  34. package/packages/form/XlRegion.vue +51 -0
  35. package/packages/form/XlSearchSelect.vue +85 -0
  36. package/packages/form/XlSelect.vue +77 -0
  37. package/packages/form/XlSwitch.vue +33 -0
  38. package/packages/form/XlTabRadio.vue +43 -0
  39. package/packages/form/XlTags.vue +105 -0
  40. package/packages/form/XlTextarea.vue +48 -0
  41. package/packages/form/XlTime.vue +50 -0
  42. package/packages/form/data/areas.json +1 -0
  43. package/packages/index.js +130 -0
  44. package/packages/main/XlAutoSaver.vue +75 -0
  45. package/packages/main/XlDataView.vue +212 -0
  46. package/packages/main/XlFormDialog2.vue +80 -0
  47. package/packages/main/XlLoginForm.vue +192 -0
  48. package/packages/main/XlNavBar.vue +89 -0
  49. package/packages/main/XlStatusIndicator.vue +36 -0
  50. package/packages/main/XlTabView.vue +81 -0
  51. package/packages/main/XlToolBar.vue +132 -0
  52. package/packages/main/XlUpdateIndicator.vue +40 -0
  53. package/packages/main/XlVerticalMenu.vue +72 -0
@@ -0,0 +1,89 @@
1
+ <script setup>
2
+ defineOptions({ name: "XlNavBar" })
3
+
4
+ // 添加props以支持自定义配置
5
+ const props = defineProps({
6
+ // 允许自定义左右列�?
7
+ leftSpan: {
8
+ type: Number,
9
+ default: 12
10
+ },
11
+ rightSpan: {
12
+ type: Number,
13
+ default: 12
14
+ },
15
+ // 是否固定在顶�?
16
+ fixed: {
17
+ type: Boolean,
18
+ default: false
19
+ },
20
+ // 自定义高�?
21
+ height: {
22
+ type: [Number, String],
23
+ default: 59
24
+ }
25
+ })
26
+
27
+ // 计算样式
28
+ const barStyle = computed(() => ({
29
+ height: typeof props.height === 'number' ? `${props.height}px` : props.height,
30
+ position: props.fixed ? 'fixed' : 'relative',
31
+ top: props.fixed ? '0' : 'auto',
32
+ zIndex: props.fixed ? 1000 : 'auto'
33
+ }))
34
+ </script>
35
+
36
+ <template>
37
+ <div class="xl-nav-bar" :style="barStyle">
38
+ <el-col :span="leftSpan" class="left">
39
+ <slot name="left" />
40
+ </el-col>
41
+ <el-col :span="rightSpan" class="right">
42
+ <slot name="right" />
43
+ </el-col>
44
+ <!-- 添加中间插槽 -->
45
+ <slot />
46
+ </div>
47
+ </template>
48
+
49
+ <style lang="less">
50
+ .xl-nav-bar {
51
+ width: 100%;
52
+ background: #fff;
53
+ color: #000;
54
+ display: flex;
55
+ align-items: center;
56
+ box-shadow: 0 1px 4px rgba(222, 222, 222, 0.08);
57
+
58
+ // 增加过渡效果
59
+ transition: all 0.3s;
60
+
61
+ .left {
62
+ display: flex;
63
+ align-items: center;
64
+ font-size: 18px;
65
+ padding-left: 20px;
66
+ height: 100%;
67
+ }
68
+
69
+ .right {
70
+ display: flex;
71
+ align-items: center; // 添加垂直居中
72
+ justify-content: flex-end;
73
+ padding-right: 40px;
74
+ height: 100%;
75
+ }
76
+ }
77
+
78
+ // 添加响应式样�?
79
+ @media screen and (max-width: 768px) {
80
+ .xl-nav-bar {
81
+ .left {
82
+ padding-left: 10px;
83
+ }
84
+ .right {
85
+ padding-right: 20px;
86
+ }
87
+ }
88
+ }
89
+ </style>
@@ -0,0 +1,36 @@
1
+ <script setup>
2
+ defineOptions({ name: "XlStatusIndicator" })
3
+
4
+ const props = defineProps({
5
+ index: {
6
+ type: Number,
7
+ },
8
+ data: {
9
+ type: Array,
10
+ required: true,
11
+ },
12
+ })
13
+ </script>
14
+
15
+ <template>
16
+ <span :class="['xl-status-indicator', data[index].class]">{{ data[index].text }}</span>
17
+ </template>
18
+
19
+ <style lang="less">
20
+ .xl-status-indicator {
21
+ margin-right: 15px;
22
+ color: black;
23
+
24
+ &.red {
25
+ color: red;
26
+ }
27
+
28
+ &.blue {
29
+ color: blue;
30
+ }
31
+
32
+ &.green {
33
+ color: green;
34
+ }
35
+ }
36
+ </style>
@@ -0,0 +1,81 @@
1
+ <script setup>
2
+ defineOptions({ name: "XlTabView" })
3
+
4
+ import { ref, watch } from 'vue'
5
+
6
+ const emits = defineEmits(['change'])
7
+
8
+ const props = defineProps({
9
+ index: {
10
+ type: Number,
11
+ default: 0,
12
+ },
13
+ frames: {
14
+ type: Array,
15
+ default: () => [],
16
+ required: true
17
+ },
18
+ data: {
19
+ type: Object,
20
+ default: () => ({})
21
+ }
22
+ })
23
+
24
+ const tabIndex = ref(String(props.index))
25
+
26
+ watch(tabIndex, (newVal) => {
27
+ emits('change', newVal)
28
+ })
29
+ </script>
30
+
31
+ <template>
32
+ <div class="xl-tab-view">
33
+ <el-tabs class="tabs" v-model="tabIndex">
34
+ <el-tab-pane
35
+ v-for="(frame, index) in props.frames"
36
+ :key="frame.label"
37
+ :label="frame.label"
38
+ :name="String(index)"
39
+ />
40
+ </el-tabs>
41
+ <component
42
+ v-for="(frame, index) in frames"
43
+ :key="frame.label"
44
+ v-show="tabIndex === String(index)"
45
+ :is="frame.entity"
46
+ :tab-index="tabIndex"
47
+ :data="data"
48
+ class="frame"
49
+ />
50
+ </div>
51
+ </template>
52
+
53
+ <style lang="less" scoped>
54
+ .xl-tab-view {
55
+ display: flex;
56
+ flex-flow: column;
57
+ flex-grow: 1;
58
+ position: relative;
59
+ background: #fff;
60
+ color: #000;
61
+
62
+ .tabs {
63
+ height: 40px;
64
+
65
+ :deep(.el-tabs__nav-wrap) {
66
+ padding-left: 10px;
67
+ }
68
+
69
+ :deep(.el-tabs__header) {
70
+ margin: 0;
71
+ }
72
+ }
73
+
74
+ .frame {
75
+ flex-grow: 1;
76
+ overflow-y: scroll;
77
+ display: flex;
78
+ flex-flow: column;
79
+ }
80
+ }
81
+ </style>
@@ -0,0 +1,132 @@
1
+ <script setup>
2
+ defineOptions({ name: "XlToolBar" })
3
+
4
+ import { onMounted } from 'vue';
5
+
6
+
7
+ const emits = defineEmits(['query', 'clear'])
8
+
9
+ const props = defineProps({
10
+ type: {},
11
+ table: {},
12
+ params: {
13
+ type: Object,
14
+ default: () => ({})
15
+ },
16
+ });
17
+
18
+ const defaultFilter = { ...props.params }
19
+
20
+
21
+ const handlers = {
22
+ query() {
23
+ if (props.table) {
24
+ props.table.value.query()
25
+ }
26
+ emits('query')
27
+ },
28
+ clear() {
29
+ if (props.table) {
30
+ reset(props.params, defaultFilter)
31
+ props.table.value.query()
32
+ }
33
+ emits('clear')
34
+ }
35
+ }
36
+
37
+ function reset(a, b) {
38
+ for (const key in a) {
39
+ delete a[key];
40
+ }
41
+ for (const key in b) {
42
+ a[key] = b[key];
43
+ }
44
+ }
45
+
46
+ onMounted(() => {
47
+ props.params.view = 'table'
48
+ })
49
+ </script>
50
+
51
+
52
+ <template>
53
+ <div class="xl-tool-bar">
54
+ <el-radio-group v-if="type == 'view'" class="xl-radio" v-model="params.view">
55
+ <el-radio-button label="table">
56
+ <el-icon>
57
+ <Grid />
58
+ </el-icon>
59
+ </el-radio-button>
60
+ <el-radio-button label="chart">
61
+ <el-icon>
62
+ <TrendCharts />
63
+ </el-icon>
64
+
65
+ </el-radio-button>
66
+ </el-radio-group>
67
+ <div class="inputs" @keyup.enter="handlers.query">
68
+ <slot name="inputs" />
69
+ <xl-button class="query-btn" type="primary" @click="handlers.query">查询</xl-button>
70
+ <xl-button class="reset-btn" @click="handlers.clear">重置</xl-button>
71
+ </div>
72
+ <div class="buttons">
73
+ <slot name="buttons" />
74
+ </div>
75
+ </div>
76
+ </template>
77
+
78
+
79
+ <style lang="less">
80
+ .xl-tool-bar {
81
+ display: flex;
82
+ flex-flow: row;
83
+ align-items: center;
84
+ width: 100%;
85
+ padding: 3px 0;
86
+ background: #fff !important;
87
+
88
+ .el-tabs__header {
89
+ background: #fff !important;
90
+ }
91
+
92
+ .el-icon {
93
+ font-size: 20px;
94
+ }
95
+
96
+ .el-radio-button__inner {
97
+ padding: 4px 10px;
98
+ }
99
+
100
+ .inputs {
101
+ text-align: left;
102
+
103
+ >* {
104
+ margin-right: 5px !important;
105
+ }
106
+ }
107
+
108
+ .xl-radio {
109
+ margin-right: 5px;
110
+ margin-left: 3px;
111
+ }
112
+
113
+ .buttons {
114
+ flex-grow: 1;
115
+ padding: 0 5px;
116
+ width: 150px;
117
+ text-align: right;
118
+
119
+ .xl-button {
120
+ display: inline-block !important;
121
+ }
122
+
123
+ >* {
124
+ margin-right: 5px !important;
125
+ }
126
+ }
127
+
128
+ .el-button+.el-button {
129
+ margin: 0;
130
+ }
131
+ }
132
+ </style>
@@ -0,0 +1,40 @@
1
+ <script setup>
2
+ defineOptions({ name: "XlUpdateIndicator" })
3
+
4
+ import { computed } from 'vue'
5
+
6
+
7
+ const props = defineProps({
8
+ state: {
9
+ type: Object,
10
+ default: () => ({}),
11
+ },
12
+ })
13
+
14
+ const formatDatetime = (date) => {
15
+ const options = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false };
16
+ return new Intl.DateTimeFormat('zh-CN', options).format(date);
17
+ }
18
+
19
+ const text = computed(() => {
20
+ const { lastUpdateTime } = props.state
21
+ return lastUpdateTime ? `上次保存时间:${formatDatetime(lastUpdateTime)}` : "";
22
+ })
23
+ </script>
24
+
25
+
26
+ <template>
27
+ <span class="xl-update-indicator">
28
+ <span v-if="props.state.saving">保存中...</span>
29
+ <span v-else>{{ text }}</span>
30
+ </span>
31
+ </template>
32
+
33
+
34
+ <style lang="less">
35
+ .xl-update-indicator {
36
+ color: grey;
37
+ font-size: 10px;
38
+ margin-right: 15px;
39
+ }
40
+ </style>
@@ -0,0 +1,72 @@
1
+ <script setup>
2
+ defineOptions({ name: "XlVerticalMenu" })
3
+
4
+ import { ref } from 'vue'
5
+
6
+
7
+ const emits = defineEmits(['change', 'item-contextmenu'])
8
+
9
+ const props = defineProps({
10
+ items: {
11
+ type: Array,
12
+ default: () => [],
13
+ },
14
+ name: {
15
+ type: String,
16
+ default: "label",
17
+ },
18
+ width: {
19
+ default: 200,
20
+ },
21
+ loading: {
22
+ default: false,
23
+ },
24
+ })
25
+
26
+ const activeIndex = ref(0)
27
+
28
+
29
+ function handleClickItem(index, item) {
30
+ activeIndex.value = index;
31
+ emits('change', item)
32
+ }
33
+
34
+ function handleContextMenu(e, item) {
35
+ emits('item-contextmenu', e, item)
36
+ }
37
+ </script>
38
+
39
+
40
+ <template>
41
+ <div class="xl-vertical-menu" :style="{ width: `${width}px` }" v-loading="loading">
42
+ <div class="item" v-for="(item, index) in items" :key="index" :class="{ active: activeIndex == index }"
43
+ @click="handleClickItem(index, item)" @contextmenu="handleContextMenu($event, item)">
44
+ <span :title="item[name]">{{ item[name] }}</span>
45
+ </div>
46
+ </div>
47
+ </template>
48
+
49
+
50
+ <style lang="less" scoped>
51
+ .xl-vertical-menu {
52
+ font-size: 13px;
53
+ border-right: 1px solid rgb(240, 240, 240);
54
+ overflow-y: scroll;
55
+ background: #fff;
56
+
57
+ .active {
58
+ background: rgb(26, 157, 255);
59
+ color: rgb(240, 240, 240);
60
+ }
61
+
62
+ &>div {
63
+ padding: 10px 7px;
64
+ color: rgb(70, 100, 150);
65
+ overflow: hidden;
66
+ white-space: nowrap;
67
+ text-overflow: ellipsis;
68
+ cursor: pointer;
69
+ text-align: left;
70
+ }
71
+ }
72
+ </style>