zkqh-lagrange-utils 0.0.54 → 0.0.55

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,7 +1,7 @@
1
1
  {
2
2
  "name": "zkqh-lagrange-utils",
3
3
  "private": false,
4
- "version": "0.0.54",
4
+ "version": "0.0.55",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -56,14 +56,28 @@
56
56
  </div>
57
57
  </div>
58
58
  </template>
59
+
60
+ <!-- 插件导出:任务名称弹窗(内置) -->
61
+ <ExportTaskModal
62
+ v-if="showTaskModal"
63
+ :kind="kind"
64
+ :args="args"
65
+ :dirname="dirname"
66
+ :get-token="getToken"
67
+ :get-url="getUrl"
68
+ :validate-args="validateArgs"
69
+ @success="onTaskModalSuccess"
70
+ @close="showTaskModal = false" />
59
71
  </div>
60
72
  </template>
61
73
 
62
74
  <script>
63
75
  import { defineComponent, ref, computed, toRefs, onMounted } from "vue"
64
76
  import PluginDirSelect from "./internal/plugin-dir-select.vue"
77
+ import ExportTaskModal from "./internal/export-task-modal.vue"
65
78
  import { usePluginHealth } from "./hooks/use-plugin-health.js"
66
79
  import { isOverSizeLimit, isPreviewOverflowDisk } from "./utils/size.js"
80
+ import { validateTimeRangeArgs } from "./utils/export-task.js"
67
81
  /** 组件局部使用 lc iconfont(不依赖宿主全局引入) */
68
82
  import "zkqh-lagrange-utils/assets/font/iconfont-lc.css"
69
83
  import "./internal/styles/plugin-local-export.less"
@@ -75,11 +89,11 @@ const DEFAULT_PREVIEW = {
75
89
  }
76
90
 
77
91
  /**
78
- * 本地导出组合区:平台/应用小文件导出 + 插件目录导出 + 50MB 分流
92
+ * 本地导出组合区:平台/应用小文件导出 + 插件目录导出 + 50MB 分流 + 任务弹窗
79
93
  */
80
94
  export default defineComponent({
81
95
  name: "PluginLocalExport",
82
- components: { PluginDirSelect },
96
+ components: { PluginDirSelect, ExportTaskModal },
83
97
  props: {
84
98
  /**
85
99
  * 预览与分流控制
@@ -91,12 +105,32 @@ export default defineComponent({
91
105
  },
92
106
  /** 插件安装包下载地址 */
93
107
  downloadUrl: { type: String, default: "" },
108
+ /** 导出 kind(插件创建任务用) */
109
+ kind: { type: String, default: "event" },
110
+ /** 筛选参数(插件创建任务用) */
111
+ args: { type: Object, default: () => ({}) },
112
+ /**
113
+ * 获取登录 token;不传则读 localStorage.token
114
+ * @type {(() => string) | string}
115
+ */
116
+ getToken: { type: [Function, String], default: null },
117
+ /**
118
+ * 获取平台根 URL;不传则读 window.sys_con.baseURL
119
+ * @type {(() => string) | string}
120
+ */
121
+ getUrl: { type: [Function, String], default: null },
122
+ /**
123
+ * 导出前校验 args;不传则校验时间范围
124
+ * @type {(args: object) => boolean}
125
+ */
126
+ validateArgs: { type: Function, default: null },
94
127
  },
95
128
  emits: ["success"],
96
129
  setup(props, { emit }) {
97
- const { previewInfo, downloadUrl } = toRefs(props)
130
+ const { previewInfo, downloadUrl, kind, args, getToken, getUrl, validateArgs } = toRefs(props)
98
131
  const dirname = ref("")
99
132
  const diskInfo = ref({ total_size: 0, used_size: 0 })
133
+ const showTaskModal = ref(false)
100
134
 
101
135
  const health = usePluginHealth({
102
136
  downloadUrl: () => downloadUrl.value,
@@ -112,6 +146,8 @@ export default defineComponent({
112
146
  ...(previewInfo.value || {}),
113
147
  }))
114
148
 
149
+ const resolveValidate = () => validateArgs.value || validateTimeRangeArgs
150
+
115
151
  /**
116
152
  * 是否展示平台/应用导出区(≤50MB)
117
153
  */
@@ -169,6 +205,9 @@ export default defineComponent({
169
205
 
170
206
  /** 平台/应用路径:确认后回调 */
171
207
  const onPlatformExportClick = () => {
208
+ const exportArgs = { ...(args.value || {}) }
209
+ if (!resolveValidate()(exportArgs)) return
210
+
172
211
  window.$dialog?.warning?.({
173
212
  title: "确认导出",
174
213
  content: "确认按当前筛选条件通过平台打包下载?",
@@ -180,14 +219,28 @@ export default defineComponent({
180
219
  })
181
220
  }
182
221
 
183
- /** 插件路径:校验后回调(含 dirname) */
222
+ /** 插件路径:打开任务名称弹窗 */
184
223
  const onPluginExportClick = () => {
185
224
  if (pluginExportDisabled.value) return
225
+ const exportArgs = { ...(args.value || {}) }
226
+ if (!resolveValidate()(exportArgs)) return
227
+ showTaskModal.value = true
228
+ }
229
+
230
+ /** 插件任务创建成功 */
231
+ const onTaskModalSuccess = () => {
232
+ showTaskModal.value = false
186
233
  emit("success", { mode: "plugin", dirname: dirname.value })
187
234
  }
188
235
 
189
236
  return {
190
237
  dirname,
238
+ kind,
239
+ args,
240
+ getToken,
241
+ getUrl,
242
+ validateArgs,
243
+ showTaskModal,
191
244
  pluginReady,
192
245
  usePlatformExport,
193
246
  usePluginExport,
@@ -198,6 +251,7 @@ export default defineComponent({
198
251
  onInstall,
199
252
  onPlatformExportClick,
200
253
  onPluginExportClick,
254
+ onTaskModalSuccess,
201
255
  }
202
256
  },
203
257
  })
@@ -22,6 +22,14 @@ function _downloadPlugin(url = "") {
22
22
  /**
23
23
  * 导出插件 health:单次检测 + 安装后轮询,就绪后自动停止
24
24
  * @param {{ interval?: number, downloadUrl?: string | import('vue').Ref<string> | (() => string) }} [options]
25
+ * @returns {{
26
+ * pluginReady: import('vue').Ref<boolean>,
27
+ * polling: import('vue').Ref<boolean>,
28
+ * checkHealth: () => Promise<boolean>,
29
+ * startPoll: () => void,
30
+ * stopPoll: () => void,
31
+ * triggerInstall: (url?: string) => void,
32
+ * }}
25
33
  */
26
34
  export function usePluginHealth(options = {}) {
27
35
  const intervalMs = options.interval ?? PLUGIN_HEALTH_INTERVAL
@@ -3,13 +3,16 @@
3
3
  *
4
4
  * 对外:
5
5
  * - pluginApi:可独立引用
6
- * - PluginLocalExport:平台/插件导出区组合组件
6
+ * - PluginLocalExport:平台/插件导出区组合组件(含任务名称弹窗)
7
+ * - ExportTaskModal:也可单独使用
8
+ * - usePluginHealth:插件存活检测 / 安装轮询
7
9
  *
8
10
  * @example
9
- * import { pluginApi, PluginLocalExport } from "zkqh-lagrange-utils/export_plugin"
10
- * import { pluginApi } from "zkqh-lagrange-utils/export_plugin/api"
11
+ * import { pluginApi, PluginLocalExport, usePluginHealth } from "zkqh-lagrange-utils/export_plugin"
11
12
  */
12
13
 
13
14
  export { pluginApi } from "./api/plugin.js"
14
15
  export { default as PluginLocalExport } from "./PluginLocalExport.vue"
16
+ export { default as ExportTaskModal } from "./internal/export-task-modal.vue"
17
+ export { usePluginHealth } from "./hooks/use-plugin-health.js"
15
18
  export { default } from "./PluginLocalExport.vue"
@@ -0,0 +1,149 @@
1
+ <template>
2
+ <n-modal
3
+ :show="true"
4
+ preset="dialog"
5
+ title="导出任务"
6
+ positive-text="确认导出"
7
+ negative-text="取消"
8
+ :mask-closable="false"
9
+ :loading="exporting"
10
+ @update:show="onShowUpdate"
11
+ @positive-click="onConfirm">
12
+ <div class="export_plugin_modals_hint lc-fs-s">请填写导出任务名称,任务可在「导出进度」中查看。</div>
13
+ <n-input
14
+ v-model:value="taskName"
15
+ size="small"
16
+ placeholder="请输入导出任务名称"
17
+ class="mt-8"
18
+ @keyup.enter="onConfirm" />
19
+ </n-modal>
20
+ </template>
21
+
22
+ <script>
23
+ import { defineComponent, ref } from "vue"
24
+ import { pluginApi } from "../api/plugin.js"
25
+ import {
26
+ buildTaskName,
27
+ getDefaultToken,
28
+ getDefaultUrl,
29
+ validateTimeRangeArgs,
30
+ } from "../utils/export-task.js"
31
+ import "./styles/export-plugin-modals.less"
32
+
33
+ /**
34
+ * 导出任务名称弹窗(创建插件导出作业)
35
+ */
36
+ export default defineComponent({
37
+ name: "ExportTaskModal",
38
+ props: {
39
+ /** 导出 kind */
40
+ kind: { type: String, default: "event" },
41
+ /** 筛选参数 */
42
+ args: { type: Object, default: () => ({}) },
43
+ /** 本地导出目录 */
44
+ dirname: { type: String, default: "" },
45
+ /**
46
+ * 获取登录 token;不传则读 localStorage.token
47
+ * @type {(() => string) | string}
48
+ */
49
+ getToken: { type: [Function, String], default: null },
50
+ /**
51
+ * 获取平台根 URL;不传则读 window.sys_con.baseURL
52
+ * @type {(() => string) | string}
53
+ */
54
+ getUrl: { type: [Function, String], default: null },
55
+ /**
56
+ * 导出前校验 args;不传则校验时间范围
57
+ * @type {(args: object) => boolean}
58
+ */
59
+ validateArgs: { type: Function, default: null },
60
+ },
61
+ emits: ["close", "success"],
62
+ setup(props, { emit }) {
63
+ const taskName = ref(buildTaskName())
64
+ const exporting = ref(false)
65
+
66
+ const resolveToken = () => {
67
+ if (props.getToken == null) return getDefaultToken()
68
+ return typeof props.getToken === "function" ? props.getToken() : String(props.getToken || "")
69
+ }
70
+
71
+ const resolveUrl = () => {
72
+ if (props.getUrl == null) return getDefaultUrl()
73
+ return typeof props.getUrl === "function" ? props.getUrl() : String(props.getUrl || "")
74
+ }
75
+
76
+ const close = () => {
77
+ emit("close")
78
+ }
79
+
80
+ const onShowUpdate = (v) => {
81
+ if (!v) close()
82
+ }
83
+
84
+ /**
85
+ * 创建导出任务
86
+ * @param {string} name 任务名称
87
+ * @returns {Promise<boolean>}
88
+ */
89
+ const createExport = async (name) => {
90
+ const exportArgs = { ...(props.args || {}) }
91
+ const validate = props.validateArgs || validateTimeRangeArgs
92
+ if (!validate(exportArgs)) return false
93
+
94
+ const token = resolveToken()
95
+ const url = resolveUrl()
96
+ if (!token) {
97
+ window.$message?.error?.("登录态失效,请重新登录")
98
+ return false
99
+ }
100
+
101
+ exporting.value = true
102
+ try {
103
+ const res = await pluginApi.createExport({
104
+ name,
105
+ kind: props.kind,
106
+ token,
107
+ url,
108
+ dirname: props.dirname,
109
+ args: exportArgs,
110
+ })
111
+ if (res.code === 200) {
112
+ window.$message?.success?.(res.msg || "已创建导出任务")
113
+ return true
114
+ }
115
+ window.$message?.error?.(res.msg || "创建导出任务失败")
116
+ return false
117
+ } catch (e) {
118
+ console.error(e)
119
+ window.$message?.error?.("创建导出任务失败,请确认插件可用")
120
+ return false
121
+ } finally {
122
+ exporting.value = false
123
+ }
124
+ }
125
+
126
+ const onConfirm = async () => {
127
+ const name = taskName.value.trim()
128
+ if (!name) {
129
+ window.$message?.warning?.("请输入导出任务名称")
130
+ return false
131
+ }
132
+
133
+ const ok = await createExport(name)
134
+ if (!ok) return false
135
+
136
+ emit("success")
137
+ close()
138
+ return true
139
+ }
140
+
141
+ return {
142
+ taskName,
143
+ exporting,
144
+ onShowUpdate,
145
+ onConfirm,
146
+ }
147
+ },
148
+ })
149
+ </script>
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 默认读取平台登录 token(可被 props.getToken 覆盖)
3
+ * @returns {string}
4
+ */
5
+ export const getDefaultToken = () => {
6
+ try {
7
+ const token = localStorage.getItem("token")
8
+ if (!token) return ""
9
+ return JSON.parse(token)?.access_token || ""
10
+ } catch {
11
+ return ""
12
+ }
13
+ }
14
+
15
+ /**
16
+ * 默认平台根地址(可被 props.getUrl 覆盖)
17
+ * @returns {string}
18
+ */
19
+ export const getDefaultUrl = () => {
20
+ const base =
21
+ (typeof window !== "undefined" && window.sys_con?.baseURL) ||
22
+ `${location.protocol}//${location.host}`
23
+ return String(base).replace(/\/$/, "")
24
+ }
25
+
26
+ /**
27
+ * 默认校验:导出 args 需含完整时间范围
28
+ * @param {Record<string, any>} args
29
+ * @returns {boolean}
30
+ */
31
+ export const validateTimeRangeArgs = (args = {}) => {
32
+ if (!(args.start_time && args.end_time)) {
33
+ window.$message?.warning?.("请选择发生时间")
34
+ return false
35
+ }
36
+ return true
37
+ }
38
+
39
+ /**
40
+ * 生成导出默认名称:导出数据_<年><月><日>
41
+ * @returns {string}
42
+ */
43
+ export const buildTaskName = () => {
44
+ const d = new Date()
45
+ const y = d.getFullYear()
46
+ const m = String(d.getMonth() + 1).padStart(2, "0")
47
+ const day = String(d.getDate()).padStart(2, "0")
48
+ return `导出数据_${y}${m}${day}`
49
+ }