hrp-ui-base 1.0.6 → 1.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hrp-ui-base",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "HRP 前端公共组件、工具方法和基础样式包",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -0,0 +1,19 @@
1
+ import HttpUtil from "../../../utils/HttpUtil";
2
+ import type ResponseBeanTablePage from "../../common/ResponseBeanTablePage";
3
+ import type TableQueryCriteriaVO from "../../common/TableQueryCriteriaVO";
4
+ import FileExportVO from "./bo/FileExportVO";
5
+
6
+ /**文件导出 */
7
+ export default class FileExportController {
8
+ /**
9
+ * 获取文件导出列表
10
+ */
11
+ static selectExportList(
12
+ queryCriteriaVO: TableQueryCriteriaVO
13
+ ): Promise<ResponseBeanTablePage<FileExportVO[]>> {
14
+ return HttpUtil.postJson(
15
+ "/bms/export/file/select-export-list",
16
+ queryCriteriaVO
17
+ );
18
+ }
19
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 文件导出信息
3
+ */
4
+ export default class FileExportVO {
5
+ /**文件id */
6
+ fileId: string = "";
7
+ /**文件名称 */
8
+ fileName: string = "";
9
+ /**文件类型 */
10
+ fileType: string = "";
11
+ /**文件大小 */
12
+ fileSize: string = "";
13
+ /**创建时间 */
14
+ createTime: string = "";
15
+ /**进度条 */
16
+ progressBar: number = 0;
17
+ }
@@ -1,6 +1,8 @@
1
1
  import HttpUtil from "../../../utils/HttpUtil";
2
2
  import type ResponseBean from "../../common/ResponseBean";
3
3
  import type ResponseBeanList from "../../common/ResponseBeanList";
4
+ import type ResponseBeanTablePage from "../../common/ResponseBeanTablePage";
5
+ import type TableQueryCriteriaVO from "../../common/TableQueryCriteriaVO";
4
6
  import FlowInstanceBO from "../flow/bo/FlowInstanceBO";
5
7
  import AuditBaseInfo from "../flow/bo/AuditBaseInfo";
6
8
  import NodeShowVo from "../flow/bo/NodeShowVo";
@@ -164,4 +166,14 @@ export default class FlowInstanceController {
164
166
  static getRecommendReplyList(id: string, type: string): Promise<ResponseBean<string[]>> {
165
167
  return HttpUtil.get("/bms/work-flow-instance/getRecommendReplies", { id, type });
166
168
  }
169
+
170
+ /** 获取审批列表 - 分页查询 */
171
+ static selectAssociatedApprovalFormListByTest(
172
+ queryCriteriaVO: TableQueryCriteriaVO
173
+ ): Promise<ResponseBeanTablePage<AssociatedApprovalVO[]>> {
174
+ return HttpUtil.postJson(
175
+ "/bms/work-flow-instance/selectAssociatedApprovalFormListByTest",
176
+ queryCriteriaVO
177
+ );
178
+ }
167
179
  }
@@ -0,0 +1,236 @@
1
+ <!--
2
+ * @description: 审批中心抽屉
3
+ * @fileName: ApprovalCenterDrawer.vue
4
+ -->
5
+ <template>
6
+ <el-drawer
7
+ v-model="drawerVisible"
8
+ title="审批中心"
9
+ direction="rtl"
10
+ size="560px"
11
+ :append-to-body="true"
12
+ @close="handleClose"
13
+ >
14
+ <div class="approval-drawer-content" v-loading="loading">
15
+ <div class="approval-drawer-list" v-if="approvalList.length > 0">
16
+ <el-card
17
+ v-for="(item, index) in approvalList"
18
+ :key="index"
19
+ shadow="hover"
20
+ class="approval-drawer-item"
21
+ @click="gotoRelatedPage(item)"
22
+ >
23
+ <div class="approval-item-body">
24
+ <el-badge
25
+ is-dot
26
+ class="item"
27
+ style="display: inline-block; margin-right: 8px"
28
+ :hidden="item.statusName !== '审批中'"
29
+ >
30
+ <div style="width: 32px; height: 32px">
31
+ <img
32
+ style="border-radius: 8px"
33
+ :src="item.avatar || defaultAvatar"
34
+ :alt="item.createUserName"
35
+ width="100%"
36
+ />
37
+ </div>
38
+ </el-badge>
39
+ <div class="approval-item-info">
40
+ <div class="approval-item-title">
41
+ {{ item.createUserName + "发起的" + item.jobName }}
42
+ </div>
43
+ <div class="approval-item-sub">
44
+ 发起人:{{ item.createUserName }}
45
+ </div>
46
+ <div class="approval-item-time">
47
+ 发起时间:{{ item.createTime }}
48
+ </div>
49
+ </div>
50
+ <div class="approval-item-status">
51
+ <el-tag v-if="item.statusName === '已通过'" type="success">{{ item.statusName }}</el-tag>
52
+ <el-tag v-else-if="item.statusName === '已拒绝'" type="danger">{{ item.statusName }}</el-tag>
53
+ <el-tag v-else-if="item.statusName === '审批中'" type="primary">{{ item.statusName }}</el-tag>
54
+ <el-tag v-else-if="item.statusName === '已撤销'" type="info">{{ item.statusName }}</el-tag>
55
+ <el-tag v-else>{{ item.statusName }}</el-tag>
56
+ </div>
57
+ </div>
58
+ </el-card>
59
+ </div>
60
+ <div class="approval-drawer-pagination" v-if="total > 0">
61
+ <el-pagination
62
+ v-model:current-page="pageNum"
63
+ v-model:page-size="pageSize"
64
+ :total="total"
65
+ layout="total, prev, pager, next"
66
+ small
67
+ @current-change="handlePageChange"
68
+ />
69
+ </div>
70
+ <div v-if="!loading && approvalList.length === 0" class="approval-drawer-empty">
71
+ <el-empty description="暂无审批记录" />
72
+ </div>
73
+ </div>
74
+ </el-drawer>
75
+ </template>
76
+
77
+ <script lang="ts" setup>
78
+ import { ref, watch, inject } from "vue";
79
+ import FlowInstanceController from "../../api/bms/flow/FlowInstanceController";
80
+ import type AssociatedApprovalVO from "../../api/bms/flow/bo/AssociatedApprovalVO";
81
+ import TableQueryCriteriaVO from "../../api/common/TableQueryCriteriaVO";
82
+ import { useLayoutMenuStore } from "./stores/useLayoutMenuStore";
83
+ import { LAYOUT_ROUTER_KEY } from "./plugin";
84
+
85
+ // 默认头像 - 使用一个简单的 SVG data URI
86
+ const defaultAvatar = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='16' fill='%23e0e0e0'/%3E%3Ccircle cx='16' cy='12' r='5' fill='%23fff'/%3E%3Cpath d='M6 28c0-5.5 4.5-10 10-10s10 4.5 10 10' fill='%23fff'/%3E%3C/svg%3E";
87
+
88
+ const props = defineProps<{
89
+ visible: boolean;
90
+ }>();
91
+
92
+ const emit = defineEmits<{
93
+ (e: "update:visible", val: boolean): void;
94
+ }>();
95
+
96
+ const router = inject<any>(LAYOUT_ROUTER_KEY);
97
+ const menuStore = useLayoutMenuStore();
98
+
99
+ const drawerVisible = ref(false);
100
+ const loading = ref(false);
101
+ const approvalList = ref<AssociatedApprovalVO[]>([]);
102
+ const total = ref(0);
103
+ const pageNum = ref(1);
104
+ const pageSize = ref(10);
105
+
106
+ watch(
107
+ () => props.visible,
108
+ (val) => {
109
+ drawerVisible.value = val;
110
+ if (val) {
111
+ pageNum.value = 1;
112
+ loadData();
113
+ }
114
+ }
115
+ );
116
+
117
+ watch(
118
+ () => drawerVisible.value,
119
+ (val) => {
120
+ if (!val) {
121
+ emit("update:visible", false);
122
+ }
123
+ }
124
+ );
125
+
126
+ const handleClose = () => {
127
+ emit("update:visible", false);
128
+ };
129
+
130
+ const loadData = async () => {
131
+ loading.value = true;
132
+ try {
133
+ const query = new TableQueryCriteriaVO();
134
+ query.pageNum = pageNum.value;
135
+ query.pageSize = pageSize.value;
136
+ const data = await FlowInstanceController.selectAssociatedApprovalFormListByTest(query);
137
+ if (data && data.code === 200 && data.res) {
138
+ approvalList.value = data.res.records || [];
139
+ total.value = data.res.total || 0;
140
+ }
141
+ } catch (e) {
142
+ console.error("加载审批列表失败", e);
143
+ } finally {
144
+ loading.value = false;
145
+ }
146
+ };
147
+
148
+ const handlePageChange = () => {
149
+ loadData();
150
+ };
151
+
152
+ /** 跳转到审批详情页 */
153
+ const gotoRelatedPage = async (item: AssociatedApprovalVO) => {
154
+ if (!item.approveUrl) return;
155
+ // 跨系统判断
156
+ if (item.funSystem && item.funSystem !== localStorage.getItem("current-application-id")) {
157
+ await menuStore.getDomainAndHomeMenu(item.approveUrl, router);
158
+ }
159
+ router?.push(item.approveUrl);
160
+ emit("update:visible", false);
161
+ };
162
+ </script>
163
+
164
+ <style scoped lang="scss">
165
+ .approval-drawer-content {
166
+ height: 100%;
167
+ display: flex;
168
+ flex-direction: column;
169
+ }
170
+
171
+ .approval-drawer-list {
172
+ flex: 1;
173
+ overflow-y: auto;
174
+ padding: 0 4px;
175
+ }
176
+
177
+ .approval-drawer-item {
178
+ cursor: pointer;
179
+ margin-bottom: 10px;
180
+
181
+ :deep(.el-card__body) {
182
+ padding: 12px;
183
+ }
184
+ }
185
+
186
+ .approval-item-body {
187
+ display: flex;
188
+ align-items: flex-start;
189
+ }
190
+
191
+ .approval-item-info {
192
+ flex: 1;
193
+ min-width: 0;
194
+ }
195
+
196
+ .approval-item-title {
197
+ font-size: 14px;
198
+ font-weight: bold;
199
+ color: var(--el-text-color-primary);
200
+ overflow: hidden;
201
+ text-overflow: ellipsis;
202
+ white-space: nowrap;
203
+ }
204
+
205
+ .approval-item-sub {
206
+ font-size: 12px;
207
+ color: var(--el-color-info);
208
+ margin: 6px 0;
209
+ }
210
+
211
+ .approval-item-time {
212
+ font-size: 12px;
213
+ color: var(--el-color-info);
214
+ }
215
+
216
+ .approval-item-status {
217
+ display: flex;
218
+ align-items: center;
219
+ margin-left: 8px;
220
+ flex-shrink: 0;
221
+ }
222
+
223
+ .approval-drawer-pagination {
224
+ display: flex;
225
+ justify-content: flex-end;
226
+ padding: 12px 0;
227
+ flex-shrink: 0;
228
+ }
229
+
230
+ .approval-drawer-empty {
231
+ flex: 1;
232
+ display: flex;
233
+ align-items: center;
234
+ justify-content: center;
235
+ }
236
+ </style>
@@ -0,0 +1,164 @@
1
+ <!--
2
+ * @description: 下载中心抽屉
3
+ * @fileName: ExportCenterDrawer.vue
4
+ -->
5
+ <template>
6
+ <el-drawer
7
+ v-model="drawerVisible"
8
+ title="下载中心"
9
+ direction="rtl"
10
+ size="560px"
11
+ :append-to-body="true"
12
+ @close="handleClose"
13
+ >
14
+ <div class="export-drawer-content" v-loading="loading">
15
+ <el-table :data="tableData" border style="width: 100%" :header-cell-style="{ background: '#f5f7fa' }">
16
+ <el-table-column prop="fileName" label="文件名" align="center" show-overflow-tooltip />
17
+ <el-table-column prop="fileType" label="类型" align="center" width="80" show-overflow-tooltip />
18
+ <el-table-column prop="fileSize" label="大小" align="center" width="100" show-overflow-tooltip />
19
+ <el-table-column prop="createTime" label="生成时间" align="center" width="160" show-overflow-tooltip />
20
+ <el-table-column label="操作" align="center" width="80" fixed="right">
21
+ <template #default="{ row }">
22
+ <el-button link type="primary" @click="downloadFile(row)">下载</el-button>
23
+ </template>
24
+ </el-table-column>
25
+ </el-table>
26
+ <div class="export-drawer-pagination" v-if="total > 0">
27
+ <el-pagination
28
+ v-model:current-page="pageNum"
29
+ v-model:page-size="pageSize"
30
+ :total="total"
31
+ layout="total, prev, pager, next"
32
+ small
33
+ @current-change="handlePageChange"
34
+ />
35
+ </div>
36
+ <div v-if="!loading && tableData.length === 0" class="export-drawer-empty">
37
+ <el-empty description="暂无导出文件" />
38
+ </div>
39
+ </div>
40
+ </el-drawer>
41
+ </template>
42
+
43
+ <script lang="ts" setup>
44
+ import { ref, watch } from "vue";
45
+ import { ElMessage } from "element-plus";
46
+ import FileExportController from "../../api/bms/file/FileExportController";
47
+ import FileUploadController from "../../api/bms/file/FileUploadController";
48
+ import type FileExportVO from "../../api/bms/file/bo/FileExportVO";
49
+ import TableQueryCriteriaVO from "../../api/common/TableQueryCriteriaVO";
50
+ import { useLayoutConfigStore } from "./stores/useLayoutConfigStore";
51
+
52
+ const props = defineProps<{
53
+ visible: boolean;
54
+ }>();
55
+
56
+ const emit = defineEmits<{
57
+ (e: "update:visible", val: boolean): void;
58
+ }>();
59
+
60
+ const configStore = useLayoutConfigStore();
61
+
62
+ const drawerVisible = ref(false);
63
+ const loading = ref(false);
64
+ const tableData = ref<FileExportVO[]>([]);
65
+ const total = ref(0);
66
+ const pageNum = ref(1);
67
+ const pageSize = ref(10);
68
+
69
+ watch(
70
+ () => props.visible,
71
+ (val) => {
72
+ drawerVisible.value = val;
73
+ if (val) {
74
+ pageNum.value = 1;
75
+ loadData();
76
+ }
77
+ }
78
+ );
79
+
80
+ watch(
81
+ () => drawerVisible.value,
82
+ (val) => {
83
+ if (!val) {
84
+ emit("update:visible", false);
85
+ }
86
+ }
87
+ );
88
+
89
+ const handleClose = () => {
90
+ emit("update:visible", false);
91
+ };
92
+
93
+ const loadData = async () => {
94
+ loading.value = true;
95
+ try {
96
+ const query = new TableQueryCriteriaVO();
97
+ query.pageNum = pageNum.value;
98
+ query.pageSize = pageSize.value;
99
+ const data = await FileExportController.selectExportList(query);
100
+ if (data && data.code === 200 && data.res) {
101
+ tableData.value = data.res.records || [];
102
+ total.value = data.res.total || 0;
103
+ }
104
+ } catch (e) {
105
+ console.error("加载导出文件列表失败", e);
106
+ } finally {
107
+ loading.value = false;
108
+ }
109
+ };
110
+
111
+ const handlePageChange = () => {
112
+ loadData();
113
+ };
114
+
115
+ /** 根据 minio 或 oss 获取下载链接并下载 */
116
+ const downloadFile = async (row: FileExportVO) => {
117
+ const fileType = configStore.userConfig.fileUploadType;
118
+ let downloadUrl = "";
119
+ try {
120
+ if (fileType === "minio") {
121
+ const res = await FileUploadController.getMinioFileUrl(row.fileId);
122
+ downloadUrl = res.res?.url || "";
123
+ } else {
124
+ const res = await FileUploadController.getFileUrl(row.fileId);
125
+ downloadUrl = res.res?.url || "";
126
+ }
127
+ } catch (e) {
128
+ ElMessage.error("获取下载地址失败");
129
+ return;
130
+ }
131
+
132
+ if (downloadUrl) {
133
+ const a = document.createElement("a");
134
+ a.style.display = "none";
135
+ a.download = row.fileName;
136
+ a.href = downloadUrl;
137
+ a.target = "_blank";
138
+ document.body.appendChild(a);
139
+ a.click();
140
+ document.body.removeChild(a);
141
+ } else {
142
+ ElMessage.error("读取文件信息错误");
143
+ }
144
+ };
145
+ </script>
146
+
147
+ <style scoped lang="scss">
148
+ .export-drawer-content {
149
+ height: 100%;
150
+ display: flex;
151
+ flex-direction: column;
152
+ }
153
+ .export-drawer-pagination {
154
+ display: flex;
155
+ justify-content: flex-end;
156
+ padding: 12px 0;
157
+ }
158
+ .export-drawer-empty {
159
+ flex: 1;
160
+ display: flex;
161
+ align-items: center;
162
+ justify-content: center;
163
+ }
164
+ </style>
@@ -72,6 +72,11 @@
72
72
  <!-- 页面内容区域(默认插槽透传) -->
73
73
  <slot></slot>
74
74
  </BaseLayout>
75
+
76
+ <!-- 下载中心抽屉 -->
77
+ <ExportCenterDrawer v-model:visible="exportDrawerVisible" />
78
+ <!-- 审批中心抽屉 -->
79
+ <ApprovalCenterDrawer v-model:visible="approvalDrawerVisible" />
75
80
  </template>
76
81
 
77
82
  <script lang="ts" setup>
@@ -90,6 +95,8 @@ import SysHeader from "./SysHeader.vue";
90
95
  import SysHeaderTabs from "./SysHeaderTabs.vue";
91
96
  import SideMenu from "./sideMenu.vue";
92
97
  import PersonalizationGuideDialog from "./personalization-guide-dialog.vue";
98
+ import ExportCenterDrawer from "./ExportCenterDrawer.vue";
99
+ import ApprovalCenterDrawer from "./ApprovalCenterDrawer.vue";
93
100
  import { useLayoutConfigStore } from "./stores/useLayoutConfigStore";
94
101
  import { useLayoutMenuStore } from "./stores/useLayoutMenuStore";
95
102
  import { useLayoutTabsStore } from "./stores/useLayoutTabsStore";
@@ -161,6 +168,8 @@ const userConfigData = computed(() => ({
161
168
 
162
169
  // ====== 状态 ======
163
170
  const showNoviceGuide = ref(false);
171
+ const exportDrawerVisible = ref(false);
172
+ const approvalDrawerVisible = ref(false);
164
173
  const updateNum = ref<number>(0);
165
174
  const notificationRefs = ref<Map<string, any>>(new Map());
166
175
 
@@ -234,11 +243,11 @@ const handleChangeMenuPosition = (value: string) => {
234
243
  };
235
244
 
236
245
  const handleDownloadClick = () => {
237
- router?.push({ path: "/bms/base-manage/base-information/export-center" });
246
+ exportDrawerVisible.value = true;
238
247
  };
239
248
 
240
249
  const handleTodoClick = () => {
241
- router?.push({ path: "/bms/base-manage/base-information/approval-center" });
250
+ approvalDrawerVisible.value = true;
242
251
  };
243
252
 
244
253
  const handleMessageNavigate = async (notice: NoticeVO) => {
@@ -8,6 +8,8 @@ export { default as SideMenuSonList } from './sideMenuSonList.vue'
8
8
  export { default as PersonalizationGuideDialog } from './personalization-guide-dialog.vue'
9
9
  export { default as MessageNotificationDrawer } from './message/message-notification-drawer.vue'
10
10
  export { default as LayoutContainer } from './LayoutContainer.vue'
11
+ export { default as ExportCenterDrawer } from './ExportCenterDrawer.vue'
12
+ export { default as ApprovalCenterDrawer } from './ApprovalCenterDrawer.vue'
11
13
 
12
14
  // Sub-components
13
15
  export { default as DarkComponent } from './components/dark-component.vue'