@jzt-packages/components 1.0.0

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 (145) hide show
  1. package/package.json +68 -0
  2. package/src/JztBackTop/index.vue +255 -0
  3. package/src/JztButtonList/index.vue +88 -0
  4. package/src/JztChart/index.vue +95 -0
  5. package/src/JztCharts/index.vue +317 -0
  6. package/src/JztClassTabs/index.vue +156 -0
  7. package/src/JztDateSelect/dateSelect.vue +186 -0
  8. package/src/JztDateSelect/dateType.vue +54 -0
  9. package/src/JztDateSelect/index.ts +135 -0
  10. package/src/JztDateSelect/interface/index.ts +13 -0
  11. package/src/JztDialog/index.vue +249 -0
  12. package/src/JztEllipsisTooltip/index.vue +61 -0
  13. package/src/JztEmpty/index.vue +45 -0
  14. package/src/JztErrorPage/403.vue +30 -0
  15. package/src/JztErrorPage/404.vue +19 -0
  16. package/src/JztErrorPage/500.vue +18 -0
  17. package/src/JztErrorPage/assets/401.png +0 -0
  18. package/src/JztErrorPage/assets/403.png +0 -0
  19. package/src/JztErrorPage/assets/404.png +0 -0
  20. package/src/JztErrorPage/assets/500.png +0 -0
  21. package/src/JztErrorPage/index.scss +35 -0
  22. package/src/JztErrorPage/index.vue +35 -0
  23. package/src/JztFilePreview/components/pdfViewer.vue +221 -0
  24. package/src/JztFilePreview/hooks/useImageMethod.ts +256 -0
  25. package/src/JztFilePreview/index.scss +171 -0
  26. package/src/JztFilePreview/index.vue +68 -0
  27. package/src/JztFilePreview/interface/index.ts +18 -0
  28. package/src/JztFilePreview/previewFile.vue +371 -0
  29. package/src/JztFormGrid/README.md +520 -0
  30. package/src/JztFormGrid/components/formItem.vue +209 -0
  31. package/src/JztFormGrid/components/formItemValue.vue +384 -0
  32. package/src/JztFormGrid/components/showDetailForm.vue +172 -0
  33. package/src/JztFormGrid/index.scss +60 -0
  34. package/src/JztFormGrid/index.vue +513 -0
  35. package/src/JztFormGrid/interface/index.ts +106 -0
  36. package/src/JztGrid/components/GridItem.vue +68 -0
  37. package/src/JztGrid/index.vue +179 -0
  38. package/src/JztGrid/interface/index.ts +6 -0
  39. package/src/JztImportExcel/assets/delete.png +0 -0
  40. package/src/JztImportExcel/index.scss +46 -0
  41. package/src/JztImportExcel/index.vue +430 -0
  42. package/src/JztImportExcel/interface/index.ts +25 -0
  43. package/src/JztLabelTitle/index.vue +65 -0
  44. package/src/JztLeftRightMode/components/CollapseButton.vue +80 -0
  45. package/src/JztLeftRightMode/components/LeftCard.vue +203 -0
  46. package/src/JztLeftRightMode/components/LeftLayout.vue +173 -0
  47. package/src/JztLeftRightMode/components/RightHeader.vue +186 -0
  48. package/src/JztLeftRightMode/components/RightLayout.vue +235 -0
  49. package/src/JztLeftRightMode/components/RightTableHeader.vue +43 -0
  50. package/src/JztLeftRightMode/hooks/useCollapse.ts +17 -0
  51. package/src/JztLeftRightMode/hooks/useDefaultProps.ts +19 -0
  52. package/src/JztLeftRightMode/hooks/useLeftLayout.ts +201 -0
  53. package/src/JztLeftRightMode/hooks/useMode.ts +20 -0
  54. package/src/JztLeftRightMode/hooks/usePrevNext.ts +60 -0
  55. package/src/JztLeftRightMode/hooks/useRightLayout.ts +215 -0
  56. package/src/JztLeftRightMode/hooks/useSlots.ts +15 -0
  57. package/src/JztLeftRightMode/index.ts +3 -0
  58. package/src/JztLeftRightMode/index.vue +494 -0
  59. package/src/JztLeftRightMode/types/index.ts +457 -0
  60. package/src/JztLoading/fullScreen.ts +45 -0
  61. package/src/JztLoading/index.scss +67 -0
  62. package/src/JztLoading/index.vue +18 -0
  63. package/src/JztLogin/components/LoginFooter.vue +17 -0
  64. package/src/JztLogin/components/LoginForm.vue +99 -0
  65. package/src/JztLogin/hooks/useLogin.ts +186 -0
  66. package/src/JztLogin/index.scss +142 -0
  67. package/src/JztLogin/index.vue +31 -0
  68. package/src/JztLogin/interface/index.ts +47 -0
  69. package/src/JztNumericalRange/index.vue +81 -0
  70. package/src/JztPageCard/comm/datePicker.vue +151 -0
  71. package/src/JztPageCard/comm/details.vue +60 -0
  72. package/src/JztPageCard/comm/export.vue +24 -0
  73. package/src/JztPageCard/comm/tabs.vue +94 -0
  74. package/src/JztPageCard/comm/tooltip.vue +31 -0
  75. package/src/JztPageCard/index.vue +287 -0
  76. package/src/JztPagination/index.vue +70 -0
  77. package/src/JztProductInfo/components/imagePreview.vue +275 -0
  78. package/src/JztProductInfo/components/qxUnique.vue +101 -0
  79. package/src/JztProductInfo/components/records.vue +265 -0
  80. package/src/JztProductInfo/hooks/useParams.ts +143 -0
  81. package/src/JztProductInfo/hooks/useQxUnique.tsx +466 -0
  82. package/src/JztProductInfo/images/defaultProduct.png +0 -0
  83. package/src/JztProductInfo/index.ts +116 -0
  84. package/src/JztProductInfo/index.vue +108 -0
  85. package/src/JztProductInfo/interface/index.ts +15 -0
  86. package/src/JztQueryDetailTable/index.scss +100 -0
  87. package/src/JztQueryDetailTable/index.vue +400 -0
  88. package/src/JztQueryDetailTable/interface/index.ts +10 -0
  89. package/src/JztQueryTable/QueryTable /345/212/237/350/203/275.md" +1580 -0
  90. package/src/JztQueryTable/README.md +567 -0
  91. package/src/JztQueryTable/components/ColSetting.vue +67 -0
  92. package/src/JztQueryTable/components/ColumnsSetting.vue +404 -0
  93. package/src/JztQueryTable/components/ColumnsSetting1.vue +220 -0
  94. package/src/JztQueryTable/components/DeployToAccountLevelSetting.vue +351 -0
  95. package/src/JztQueryTable/components/Pagination.vue +54 -0
  96. package/src/JztQueryTable/components/TableColumn.vue +109 -0
  97. package/src/JztQueryTable/const.ts +1 -0
  98. package/src/JztQueryTable/hooks/useQueryTable.ts +194 -0
  99. package/src/JztQueryTable/hooks/useSelection.ts +47 -0
  100. package/src/JztQueryTable/hooks/useTableSetting.ts +197 -0
  101. package/src/JztQueryTable/hooks/useTemplate.ts +127 -0
  102. package/src/JztQueryTable/index.scss +91 -0
  103. package/src/JztQueryTable/index.vue +1445 -0
  104. package/src/JztQueryTable/interface/index.ts +185 -0
  105. package/src/JztRegionSelect/index.vue +134 -0
  106. package/src/JztSearchForm/components/SearchFormItem.vue +473 -0
  107. package/src/JztSearchForm/index.vue +530 -0
  108. package/src/JztSearchForm/interface/index.ts +100 -0
  109. package/src/JztSelectFilter/index.scss +63 -0
  110. package/src/JztSelectFilter/index.vue +110 -0
  111. package/src/JztSelectTable/index.vue +257 -0
  112. package/src/JztTable/index.scss +72 -0
  113. package/src/JztTable/index.vue +353 -0
  114. package/src/JztTable/interface/index.ts +1 -0
  115. package/src/JztTime/comm/agencySelect.vue +112 -0
  116. package/src/JztTime/comm/collapseRow.vue +132 -0
  117. package/src/JztTime/comm/dateSelect.vue +292 -0
  118. package/src/JztTime/comm/deptSelect.vue +193 -0
  119. package/src/JztTime/comm/typeSelect.vue +97 -0
  120. package/src/JztTime/index.ts +216 -0
  121. package/src/JztTime/index.vue +303 -0
  122. package/src/JztTime/interface/index.ts +23 -0
  123. package/src/JztTreeFilter/index.scss +44 -0
  124. package/src/JztTreeFilter/index.vue +177 -0
  125. package/src/JztUploadFile/interface/index.ts +21 -0
  126. package/src/JztUploadFile/multiple.scss +215 -0
  127. package/src/JztUploadFile/multiple.vue +318 -0
  128. package/src/JztUploadFile/single.scss +226 -0
  129. package/src/JztUploadFile/single.vue +274 -0
  130. package/src/JztUploadImg/Img.vue +294 -0
  131. package/src/JztUploadImg/Imgs.vue +411 -0
  132. package/src/JztUploadImg/index.scss +138 -0
  133. package/src/JztUploadImg/interface/index.ts +22 -0
  134. package/src/SelectIcon/index.scss +39 -0
  135. package/src/SelectIcon/index.vue +106 -0
  136. package/src/SvgIcon/index.vue +22 -0
  137. package/src/hooks/useAuthButtons.ts +58 -0
  138. package/src/hooks/useFormByUserType.ts +90 -0
  139. package/src/hooks/useTableEvents.ts +30 -0
  140. package/src/hooks/useUploadFileHook.ts +262 -0
  141. package/src/index.ts +91 -0
  142. package/src/typings/global.d.ts +101 -0
  143. package/src/utils/index.ts +107 -0
  144. package/src/utils/tree.ts +57 -0
  145. package/tsconfig.json +45 -0
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <div class="group-header flx-left-center" :class="className" :style="style">
3
+ <div class="label-title flx-left-center">
4
+ <span v-if="isLabel" class="label"></span>
5
+ <slot name="title">
6
+ <span class="title">{{ title }}</span>
7
+ </slot>
8
+ <slot name="icon"></slot>
9
+ </div>
10
+ <div v-if="subTitle" class="sub-title">{{ subTitle }}</div>
11
+ <slot name="titleRight"></slot>
12
+ </div>
13
+ </template>
14
+ <script setup lang="ts" name="JztLabelTitle">
15
+ import { CSSProperties } from 'vue'
16
+
17
+ interface ProTableProps {
18
+ isLabel?: boolean
19
+ title?: string
20
+ fontSize?: string
21
+ subTitle?: string
22
+ className?: string //类名
23
+ style?: CSSProperties // 样式
24
+ }
25
+
26
+ // 默认值
27
+ const props = withDefaults(defineProps<ProTableProps>(), {
28
+ title: '',
29
+ fontSize: '16px',
30
+ isLabel: true,
31
+ subTitle: '',
32
+ style: () => ({}),
33
+ noPadding: false
34
+ })
35
+ </script>
36
+
37
+ <style lang="scss" scoped>
38
+ .group-header {
39
+ width: 100%;
40
+ padding: 10px 12px;
41
+ flex-shrink: 0;
42
+ }
43
+ .label-title {
44
+ font-weight: 600;
45
+ color: var(--el-text-color-primary);
46
+ text-align: left;
47
+ flex-shrink: 0;
48
+ .label {
49
+ display: inline-block;
50
+ width: 4px;
51
+ height: 16px;
52
+ background: var(--el-color-primary);
53
+ margin-right: 8px;
54
+ border-radius: 4px;
55
+ }
56
+
57
+ .title {
58
+ font-size: v-bind(fontSize);
59
+ }
60
+ }
61
+ .sub-title {
62
+ margin-left: 10px;
63
+ font-weight: 400;
64
+ }
65
+ </style>
@@ -0,0 +1,80 @@
1
+ <script setup lang="tsx" name="CollapseButton">
2
+ import { DArrowLeft, DArrowRight } from '@element-plus/icons-vue'
3
+ import { computed } from 'vue'
4
+
5
+ export type Props = {
6
+ /**
7
+ * 是否折叠
8
+ */
9
+ isCollapse: boolean
10
+ /**
11
+ * 折叠时显示的文本
12
+ * @default 主单详细
13
+ */
14
+ text?: string
15
+ }
16
+
17
+ const props = withDefaults(defineProps<Props>(), {
18
+ isCollapse: false,
19
+ text: '主单详细'
20
+ })
21
+
22
+ const emits = defineEmits<{
23
+ /** 点击时触发 */
24
+ (e: 'click'): void
25
+ }>()
26
+
27
+ const texts = computed(() => props.text?.split(''))
28
+ </script>
29
+
30
+ <template>
31
+ <div class="collapse-button" :class="{ 'is-collapse': isCollapse }" @click="emits('click')">
32
+ <transition name="el-fade-in-linear">
33
+ <div v-show="isCollapse" class="collapse-button__text">
34
+ <el-text v-for="item in texts" :key="item" type="primary">{{ item }}</el-text>
35
+ </div>
36
+ </transition>
37
+ <div class="collapse-button__icon">
38
+ <el-text type="primary">
39
+ <el-icon size="14">
40
+ <DArrowRight v-if="isCollapse" />
41
+ <DArrowLeft v-else />
42
+ </el-icon>
43
+ </el-text>
44
+ </div>
45
+ </div>
46
+ </template>
47
+
48
+ <style lang="scss" scoped>
49
+ .collapse-button {
50
+ cursor: pointer;
51
+ &:not(.is-collapse) {
52
+ position: absolute;
53
+ top: 50%;
54
+ right: -50%;
55
+ transform: translateY(-50%);
56
+ transition: right 0.3s ease-in-out;
57
+ }
58
+ &.is-collapse {
59
+ width: 50%;
60
+ display: flex;
61
+ flex-direction: column;
62
+ align-items: center;
63
+ position: absolute;
64
+ top: 50%;
65
+ left: 50%;
66
+ transform: translate(-50%, -50%);
67
+ gap: 6px;
68
+ }
69
+ &__text {
70
+ display: flex;
71
+ flex-direction: column;
72
+ justify-content: center;
73
+ }
74
+ &__icon {
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: center;
78
+ }
79
+ }
80
+ </style>
@@ -0,0 +1,203 @@
1
+ <script setup lang="tsx" name="Card">
2
+ import { computed, ref } from 'vue'
3
+
4
+ import JztEllipsisTooltip from '../../JztEllipsisTooltip/index.vue'
5
+ import { type LeftLayoutProps } from '../types/index'
6
+ // 卡片属性
7
+ const props = defineProps<{
8
+ row: any
9
+ isSelected: boolean
10
+ showSelected: LeftLayoutProps['showSelected']
11
+ showStatus: LeftLayoutProps['showStatus']
12
+ statusProp?: LeftLayoutProps['statusProp']
13
+ statusEnum?: LeftLayoutProps['statusEnum']
14
+ cardProps: LeftLayoutProps['cardProps']
15
+ }>()
16
+ // 卡片事件
17
+ const emits = defineEmits<{
18
+ (e: 'click'): void
19
+ (e: 'select'): void
20
+ }>()
21
+ // 卡片元素
22
+ const root = ref<any>()
23
+ // 内容配置
24
+ const contentConfig = computed<any>(() => {
25
+ const { row, cardProps } = props
26
+ return cardProps?.content.map((item: any) => {
27
+ const arr = Array.isArray(item.props) ? item.props : [item.props]
28
+ return {
29
+ ...item,
30
+ values: arr.map((key: string) => row.options[key]).filter(Boolean)
31
+ }
32
+ })
33
+ })
34
+ // 状态项
35
+ const statusItem = computed(() => {
36
+ const {
37
+ row: { options },
38
+ statusProp,
39
+ statusEnum
40
+ } = props
41
+ return statusEnum?.find(item => [item.value, item.name, item.label].includes(options[statusProp || '']))
42
+ })
43
+
44
+ defineExpose({
45
+ root
46
+ })
47
+ </script>
48
+
49
+ <template>
50
+ <div ref="root" class="order-item">
51
+ <div v-if="showSelected" class="order-checkbox" @click.stop="emits('select')">
52
+ <el-checkbox :model-value="row.selected" @update:model-value="emits('select')" @click.stop></el-checkbox>
53
+ </div>
54
+ <div class="order-card" @click.stop="emits('click')" :class="{ 'is-selected': isSelected }">
55
+ <slot name="title">
56
+ <div class="order-title">
57
+ <slot name="title-left"></slot>
58
+ <slot name="title-center">
59
+ <div v-if="cardProps?.title" class="order-title-content">
60
+ <jzt-ellipsis-tooltip
61
+ placement="top-start"
62
+ :content="`${row.options[cardProps?.title] ?? ''}`"
63
+ ></jzt-ellipsis-tooltip>
64
+ </div>
65
+ </slot>
66
+ <slot name="title-right"></slot>
67
+ <div
68
+ v-if="showStatus && statusItem?.name"
69
+ :class="cardProps?.title ? 'order-title-status' : 'order-title-status-float'"
70
+ >
71
+ <el-tag :type="statusItem?.type || 'primary'" size="small">
72
+ {{ statusItem?.name || '' }}
73
+ </el-tag>
74
+ </div>
75
+ </div>
76
+ </slot>
77
+ <template v-if="contentConfig?.length">
78
+ <div
79
+ class="order-content"
80
+ v-for="(item, index) in contentConfig"
81
+ :key="index"
82
+ :style="{ width: item.width ? `calc(${item.width} - 2px)` : '100%' }"
83
+ >
84
+ <el-text v-if="item.label" class="order-content-label" :style="{ color: item.labelColor }">
85
+ {{ item.label }}:
86
+ </el-text>
87
+ <div class="order-content-value">
88
+ <template v-if="item.render">
89
+ <component :is="item.render(row,item)"></component>
90
+ </template>
91
+ <template v-else v-for="(value, valueIndex) in item.values" :key="valueIndex">
92
+ <jzt-ellipsis-tooltip
93
+ placement="top-start"
94
+ :content="`${value}`"
95
+ :max-width="`${100 / item.values?.length}%`"
96
+ :style="
97
+ Number(valueIndex) + 1 == item.values.length
98
+ ? { flex: 1, maxWidth: 'unset', color: item.valueColor && item.valueColor(row.options) }
99
+ : { color: item.valueColor && item.valueColor(row.options) }
100
+ "
101
+ ></jzt-ellipsis-tooltip>
102
+ <el-divider v-if="Number(valueIndex) < (item.values?.length ?? 0) - 1" direction="vertical" />
103
+ </template>
104
+ </div>
105
+ </div>
106
+ </template>
107
+ <slot name="footer"></slot>
108
+ </div>
109
+ </div>
110
+ </template>
111
+
112
+ <style lang="scss" scoped>
113
+ .order-item {
114
+ display: flex;
115
+ }
116
+ .order-card {
117
+ position: relative;
118
+ padding: 8px 12px;
119
+ height: 100%;
120
+ cursor: pointer;
121
+ border-radius: 4px;
122
+ background-color: #ffffff;
123
+ user-select: none;
124
+ flex: 1;
125
+ overflow: hidden;
126
+ display: flex;
127
+ // flex-direction: column;
128
+ flex-wrap: wrap;
129
+ gap: 0 4px;
130
+ &.is-selected {
131
+ box-shadow: inset 0 0 0 1px rgba(52, 117, 250, 0.6);
132
+ }
133
+ }
134
+ .order-checkbox {
135
+ cursor: pointer;
136
+ display: flex;
137
+ align-items: center;
138
+ flex-shrink: 0;
139
+ padding-right: 8px;
140
+ padding-left: 12px;
141
+ }
142
+ .order-title {
143
+ display: flex;
144
+ align-items: center;
145
+ gap: 4px;
146
+ overflow: hidden;
147
+ flex: 1;
148
+ .order-title-content {
149
+ font-size: 14px;
150
+ font-weight: 600;
151
+ line-height: 22px;
152
+ color: #333333;
153
+ overflow: hidden;
154
+ }
155
+ .order-title-status {
156
+ flex: 1;
157
+ display: flex;
158
+ justify-content: flex-end;
159
+ }
160
+ .order-title-status-float {
161
+ position: absolute;
162
+ right: 12px;
163
+ top: 4px;
164
+ }
165
+ .el-tag {
166
+ border: none;
167
+ padding: 0 4px;
168
+ }
169
+ }
170
+ .order-content {
171
+ font-size: 14px;
172
+ font-weight: 400;
173
+ line-height: 22px;
174
+ color: #333333;
175
+ display: flex;
176
+ align-items: center;
177
+ .order-content-label {
178
+ flex-shrink: 0;
179
+ font-size: 12px;
180
+ font-weight: 400;
181
+ color: #999999;
182
+ line-height: 20px;
183
+ }
184
+ .order-content-value {
185
+ flex: 1;
186
+ display: flex;
187
+ align-items: center;
188
+ overflow: hidden;
189
+ :deep(.ellipsis-text) {
190
+ flex-shrink: 0;
191
+ font-size: 12px;
192
+ font-weight: 400;
193
+ color: #333333;
194
+ line-height: 20px;
195
+ }
196
+ :deep(.el-divider) {
197
+ margin: 0 4px;
198
+ border-left-width: 1.5px;
199
+ border-left-color: #333333;
200
+ }
201
+ }
202
+ }
203
+ </style>
@@ -0,0 +1,173 @@
1
+ <script setup lang="tsx" name="LeftLayout">
2
+ import { JztBackTop as BackTop } from '@jzt-spd/components'
3
+ import { default as Card } from './LeftCard.vue'
4
+
5
+ import { computed } from 'vue'
6
+ import { useLeftProps } from '../hooks/useDefaultProps'
7
+ import { useLeftLayout } from '../hooks/useLeftLayout'
8
+ import { useFilterSlots } from '../hooks/useSlots'
9
+
10
+ import { type LeftLayoutEmits, type LeftLayoutProps } from '../types/index'
11
+
12
+ const props = withDefaults(defineProps<LeftLayoutProps>(), {
13
+ ...useLeftProps(),
14
+ backTopProps: () => ({}),
15
+ topList: () => [],
16
+ columns: () => [],
17
+ cardProps: () => ({ title: '', subTitle: [], content: [] })
18
+ })
19
+
20
+ const emits = defineEmits<LeftLayoutEmits<typeof slotBind>>()
21
+
22
+ const {
23
+ scrollbarRef,
24
+ rows,
25
+ currentIndex,
26
+ isSelectedAll,
27
+ page,
28
+ more,
29
+ selectedIds,
30
+ slotBind,
31
+ expose,
32
+ onLoadList,
33
+ onSelectedAllChange,
34
+ onCardClick,
35
+ onCardSelect,
36
+ onSetItemRef
37
+ } = useLeftLayout(props, emits)
38
+
39
+ const { slots, onFilterSlots } = useFilterSlots()
40
+
41
+ const wrapClass = computed(() => {
42
+ const { showSelected } = props
43
+ return `left-aside-scrollbar ${showSelected ? 'pr12' : 'pl12 pr12'} ${slots.header ? '' : 'pt12'}`
44
+ })
45
+
46
+ defineExpose(expose)
47
+
48
+ export type Expose = typeof expose
49
+ </script>
50
+
51
+ <template>
52
+ <div class="left-aside">
53
+ <slot name="header" v-bind="slotBind"></slot>
54
+ <slot name="main" v-bind="slotBind">
55
+ <el-scrollbar v-if="page.total > 0" ref="scrollbarRef" height="100%" :wrap-class="wrapClass" @scroll="onLoadList">
56
+ <div class="left-aside-list">
57
+ <template v-for="(item, index) in rows" :key="index">
58
+ <slot name="card" :row="item.options" :index="index" :rows="rows">
59
+ <card
60
+ :ref="(el:any) => onSetItemRef(el?.root, index)"
61
+ :key="index"
62
+ :row="item"
63
+ :is-selected="index === currentIndex"
64
+ :card-props="cardProps"
65
+ :status-prop="statusProp"
66
+ :status-enum="statusEnum"
67
+ :show-status="showStatus"
68
+ :show-selected="showSelected"
69
+ @click="onCardClick(item, index)"
70
+ @select="onCardSelect(item)"
71
+ >
72
+ <template v-for="slot in onFilterSlots('card-')" #[slot.templateName]>
73
+ <slot :name="slot.slotName" :row="item.options" :index="index" :rows="rows"></slot>
74
+ </template>
75
+ </card>
76
+ </slot>
77
+ </template>
78
+ </div>
79
+ <div class="left-aside-more">
80
+ <el-button text type="info" :loading="more.loading">
81
+ {{ more.text }}
82
+ </el-button>
83
+ </div>
84
+ </el-scrollbar>
85
+ </slot>
86
+ <slot name="footer" v-bind="slotBind">
87
+ <div v-if="page.total > 0 && showSelected" class="left-aside-footer">
88
+ <el-checkbox
89
+ v-if="showSelected && footerButtonList"
90
+ v-model="isSelectedAll"
91
+ :class="{
92
+ 'align-items-start': footerButtonList.length >= 2,
93
+ 'align-items-center': footerButtonList.length < 2
94
+ }"
95
+ @change="onSelectedAllChange"
96
+ >
97
+ <el-text>全选</el-text>
98
+ <el-text v-if="footerButtonList.length < 2">
99
+ ,已勾选
100
+ <el-text type="warning">{{ ` ${selectedIds.length} ` }}</el-text>
101
+
102
+ </el-text>
103
+ <div v-else>
104
+ <el-text type="info" size="small">
105
+ 已勾选
106
+ <el-text type="warning" size="small">
107
+ {{ ` ${selectedIds.length} ` }}
108
+ </el-text>
109
+
110
+ </el-text>
111
+ </div>
112
+ </el-checkbox>
113
+ <slot name="footer-right" v-bind="slotBind"></slot>
114
+ </div>
115
+ </slot>
116
+ <back-top
117
+ v-if="showBackTop && page.total > 0"
118
+ ref="backTopRef"
119
+ v-bind="backTopProps"
120
+ position="absolute"
121
+ ></back-top>
122
+ </div>
123
+ </template>
124
+
125
+ <style lang="scss" scoped>
126
+ .left-aside {
127
+ position: relative;
128
+ height: 100%;
129
+ display: flex;
130
+ flex-direction: column;
131
+
132
+ &-list {
133
+ display: flex;
134
+ flex-direction: column;
135
+ gap: 8px;
136
+ }
137
+ &-more {
138
+ display: flex;
139
+ justify-content: center;
140
+ align-items: center;
141
+ padding: 12px;
142
+ gap: 2px;
143
+ .el-button {
144
+ height: fit-content;
145
+ padding: 0;
146
+ }
147
+ }
148
+ &-footer {
149
+ padding: 12px;
150
+ display: flex;
151
+ justify-content: space-between;
152
+ align-items: center;
153
+ background: #ffffff;
154
+ gap: 8px;
155
+ }
156
+ }
157
+ :deep(.el-checkbox) {
158
+ --el-checkbox-border-radius: 50%;
159
+ --el-checkbox-input-width: 16px;
160
+ --el-checkbox-input-height: 16px;
161
+ &.align-items-start {
162
+ align-items: start;
163
+ }
164
+ &.align-items-center {
165
+ align-items: center;
166
+ }
167
+ .el-checkbox__inner::after {
168
+ left: 50%;
169
+ top: 49%;
170
+ transform: translate(-50%, -50%) rotate(45deg) scaleY(1);
171
+ }
172
+ }
173
+ </style>
@@ -0,0 +1,186 @@
1
+ <script setup lang="tsx" name="RightHeader">
2
+ import { ArrowDown, ArrowUp, WarningFilled } from '@element-plus/icons-vue'
3
+
4
+ import { useElementSize } from '@vueuse/core'
5
+ import { computed, ref, watch } from 'vue'
6
+
7
+ import { type RightLayoutProps } from '../types'
8
+
9
+ const props = defineProps<
10
+ {
11
+ data: any
12
+ background?: string
13
+ isCollapse: boolean
14
+ } & RightLayoutProps
15
+ >()
16
+
17
+ const emits = defineEmits(['collapse', 'update:background'])
18
+ const reasonRef = ref<HTMLDivElement>()
19
+ const { width } = useElementSize(reasonRef)
20
+
21
+ const HeaderBgColorEnum = {
22
+ primary: ['#eaf1fd', '#fdfdff'],
23
+ danger: ['#ff3a301a', '#ff3a3003'],
24
+ success: ['#44cc771a', '#44cc7703'],
25
+ info: ['#6666661a', '#66666603'],
26
+ warning: ['#ffa00c1a', '#ffa00c03']
27
+ }
28
+
29
+ const statusItem = computed(() => {
30
+ const { data } = props
31
+ const { statusProp, statusEnum } = props.headerProps ?? {}
32
+ return statusEnum?.find(item => [item.value, item.name, item.label].includes(data[statusProp || '']))
33
+ })
34
+
35
+ const background = computed(() => {
36
+ const size = 52
37
+ const { showSyncBg, headerProps } = props
38
+ const type = showSyncBg ? statusItem.value?.type : headerProps?.bgType
39
+ const [startColor, endColor] = HeaderBgColorEnum[type || 'primary']
40
+ return `linear-gradient(180deg, ${startColor} ${size * 0.1}px, ${endColor} ${size * 0.99}px)`
41
+ })
42
+
43
+ const title = computed(() => {
44
+ const { data } = props
45
+ const { titleProp } = props.headerProps ?? {}
46
+ return data?.[titleProp || ''] || ''
47
+ })
48
+
49
+ const subTitle = computed(() => {
50
+ const { data } = props
51
+ const { subTitleProp } = props.headerProps ?? {}
52
+ return data?.[subTitleProp || ''] || ''
53
+ })
54
+
55
+ const reason = computed(() => {
56
+ const { data } = props
57
+ const { reasonProp } = props.headerProps ?? {}
58
+ return data?.[reasonProp || '']?.replace(/\|/g, ';') || ''
59
+ })
60
+
61
+ watch(
62
+ () => background.value,
63
+ newVal => {
64
+ emits('update:background', newVal)
65
+ },
66
+ { immediate: true }
67
+ )
68
+ </script>
69
+
70
+ <template>
71
+ <div
72
+ v-if="showHeader"
73
+ class="right-aside-header right-aside-header_bg"
74
+ :class="{ 'is-reason': headerProps?.reasonProp }"
75
+ >
76
+ <div class="flex align-center">
77
+ <div class="right-aside-header_left" style="flex: 1">
78
+ <slot name="header-title">
79
+ <span v-if="title" class="right-aside-header_title">
80
+ {{ title }}
81
+ </span>
82
+ <span v-if="subTitle">|</span>
83
+ <div v-if="subTitle" class="right-aside-header_subTitle">
84
+ <ellipsis-tooltip :content="subTitle" />
85
+ </div>
86
+ </slot>
87
+ <el-tag v-if="showStatus && statusItem?.name" :type="statusItem?.type" size="small">
88
+ {{ statusItem?.name || statusItem?.name || '' }}
89
+ </el-tag>
90
+ <slot name="header-extra"></slot>
91
+ </div>
92
+ <div v-if="showCollapse && showDescriptions" class="right-aside-header_right">
93
+ <el-text type="primary" class="right-aside-header_toggle" @click="emits('collapse')">
94
+ {{ isCollapse ? '收起信息' : '更多信息' }}
95
+ <el-icon class="el-icon--right ml2">
96
+ <component :is="isCollapse ? ArrowUp : ArrowDown"></component>
97
+ </el-icon>
98
+ </el-text>
99
+ </div>
100
+ </div>
101
+ <div ref="reasonRef" v-if="showReason && headerProps?.reasonProp" class="flex align-center">
102
+ <el-text type="danger" class="mr2">
103
+ <el-icon><WarningFilled /></el-icon>
104
+ </el-text>
105
+ <el-tooltip effect="dark" placement="bottom" :popper-style="{ width: `${width || '200'}px` }">
106
+ <template #content>
107
+ <el-text class="right-aside-header_reason">{{ reason }}</el-text>
108
+ </template>
109
+ <el-text class="right-aside-header_reason is-overflow">驳回原因:{{ reason }}</el-text>
110
+ </el-tooltip>
111
+ </div>
112
+ </div>
113
+ <div v-else class="right-aside-header_bg pt8"></div>
114
+ </template>
115
+
116
+ <style lang="scss" scoped>
117
+ .right-aside-header {
118
+ position: relative;
119
+ box-sizing: border-box;
120
+ border-radius: 8px 8px 0 0;
121
+ font-size: 14px;
122
+ padding: 14px 12px;
123
+ display: flex;
124
+ flex-direction: column;
125
+ gap: 8px;
126
+ &.is-reason {
127
+ padding-bottom: 8px;
128
+ }
129
+ &_left,
130
+ &_right {
131
+ position: relative;
132
+ z-index: 1;
133
+ }
134
+ &_left {
135
+ display: flex;
136
+ align-items: baseline;
137
+ gap: 4px;
138
+ font-size: 14px;
139
+ width: 100%;
140
+ flex: 1;
141
+ }
142
+ &_title {
143
+ flex-shrink: 0;
144
+ color: #333333;
145
+ font-weight: 500;
146
+ }
147
+ &_subTitle {
148
+ overflow: hidden;
149
+ flex: 0 1 auto;
150
+ color: #333333;
151
+ font-weight: 500;
152
+ }
153
+ &_right {
154
+ flex-shrink: 0;
155
+ display: flex;
156
+ align-items: center;
157
+ }
158
+ &_toggle {
159
+ flex-shrink: 0;
160
+ font-weight: 500;
161
+ font-size: 13px;
162
+ cursor: pointer;
163
+ user-select: none;
164
+ display: flex;
165
+ align-items: center;
166
+ .el-icon {
167
+ margin-left: 2px;
168
+ }
169
+ }
170
+ &_reason {
171
+ color: #999999;
172
+ font-size: 13px;
173
+ &.is-overflow {
174
+ overflow: hidden;
175
+ text-overflow: ellipsis;
176
+ white-space: nowrap;
177
+ }
178
+ }
179
+ }
180
+ .flex {
181
+ display: flex;
182
+ }
183
+ .align-center {
184
+ align-items: center;
185
+ }
186
+ </style>