index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. <template>
  2. <div class="flow-flowForm-container">
  3. <el-card shadow="hover">
  4. <div class="flow-flowForm-search mb15">
  5. <el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="100px">
  6. <el-row>
  7. <el-col :span="8" class="colBlock">
  8. <el-form-item :label="t('message.flowForm.formName')" prop="name">
  9. <el-input v-model="tableData.param.name" :placeholder="t('message.flowForm.enterFormName')" clearable @keyup.enter.native="flowFormList" />
  10. </el-form-item>
  11. </el-col>
  12. <el-col :span="8" class="colBlock">
  13. <el-form-item :label="t('message.flowForm.status')" prop="status">
  14. <el-select v-model="tableData.param.status" :placeholder="t('message.flowForm.selectStatus')" clearable style="width: 160px">
  15. <el-option v-for="dict in flow_form_status" :key="dict.value" :label="dict.label" :value="dict.value" />
  16. </el-select>
  17. </el-form-item>
  18. </el-col>
  19. <el-col :span="8" :class="!showAll ? 'colBlock' : 'colNone'">
  20. <el-form-item>
  21. <el-button type="primary" @click="flowFormList"
  22. ><el-icon><ele-Search /></el-icon>{{ t('message.flowForm.search') }}</el-button
  23. >
  24. <el-button @click="resetQuery(queryRef)"
  25. ><el-icon><ele-Refresh /></el-icon>{{ t('message.flowForm.reset') }}</el-button
  26. >
  27. <el-button type="primary" link @click="toggleSearch">
  28. {{ word }}
  29. <el-icon v-show="showAll"><ele-ArrowUp /></el-icon>
  30. <el-icon v-show="!showAll"><ele-ArrowDown /></el-icon>
  31. </el-button>
  32. </el-form-item>
  33. </el-col>
  34. <el-col :span="8" :class="showAll ? 'colBlock' : 'colNone'">
  35. <el-form-item :label="t('message.flowForm.createTime')" prop="createdAt">
  36. <el-date-picker
  37. clearable
  38. style="width: 200px"
  39. v-model="tableData.param.createdAt"
  40. format="YYYY-MM-DD HH:mm:ss"
  41. value-format="YYYY-MM-DD HH:mm:ss"
  42. type="datetime"
  43. :placeholder="t('message.flowForm.selectCreateTime')"
  44. ></el-date-picker>
  45. </el-form-item>
  46. </el-col>
  47. <el-col :span="8" :class="showAll ? 'colBlock' : 'colNone'">
  48. <el-form-item>
  49. <el-button type="primary" @click="flowFormList"
  50. ><el-icon><ele-Search /></el-icon>{{ t('message.flowForm.search') }}</el-button
  51. >
  52. <el-button @click="resetQuery(queryRef)"
  53. ><el-icon><ele-Refresh /></el-icon>{{ t('message.flowForm.reset') }}</el-button
  54. >
  55. <el-button type="primary" link @click="toggleSearch">
  56. {{ word }}
  57. <el-icon v-show="showAll"><ele-ArrowUp /></el-icon>
  58. <el-icon v-show="!showAll"><ele-ArrowDown /></el-icon>
  59. </el-button>
  60. </el-form-item>
  61. </el-col>
  62. </el-row>
  63. </el-form>
  64. <el-row :gutter="10" class="mb8">
  65. <el-col :span="1.5">
  66. <el-button type="primary" @click="handleAdd" v-auth="'add'"
  67. ><el-icon><ele-Plus /></el-icon>{{ t('message.flowForm.add') }}</el-button
  68. >
  69. </el-col>
  70. <el-col :span="1.5">
  71. <el-button type="success" :disabled="single" @click="handleUpdate(null)" v-auth="'edit'"
  72. ><el-icon><ele-Edit /></el-icon>{{ t('message.flowForm.edit') }}</el-button
  73. >
  74. </el-col>
  75. <el-col :span="1.5">
  76. <el-button type="danger" :disabled="multiple" @click="handleDelete(null)" v-auth="'del'"
  77. ><el-icon><ele-Delete /></el-icon>{{ t('message.flowForm.delete') }}</el-button
  78. >
  79. </el-col>
  80. <el-col :span="1.5">
  81. <el-button type="info" @click="handleImport"
  82. ><el-icon><ele-Upload /></el-icon>{{ t('message.flowForm.import') }}</el-button
  83. >
  84. </el-col>
  85. <el-col :span="1.5">
  86. <el-button type="primary" :disabled="multiple" @click="handleExport"
  87. ><el-icon><ele-Download /></el-icon>{{ t('message.flowForm.export') }}</el-button
  88. >
  89. </el-col>
  90. </el-row>
  91. </div>
  92. <el-table v-loading="loading" :data="tableData.data" @selection-change="handleSelectionChange">
  93. <el-table-column type="selection" width="55" align="center" />
  94. <el-table-column :label="t('message.flowForm.primaryKey')" align="center" prop="id" min-width="150px" />
  95. <el-table-column :label="t('message.flowForm.formName')" align="center" prop="name" min-width="150px" />
  96. <el-table-column :label="t('message.flowForm.status')" align="center" prop="status" :formatter="statusFormat" min-width="150px" />
  97. <el-table-column :label="t('message.flowForm.deploymentStatus')" align="center" prop="status" :formatter="isPubFormat" min-width="150px" />
  98. <el-table-column :label="t('message.flowForm.remark')" align="center" prop="remark" min-width="150px" />
  99. <el-table-column :label="t('message.flowForm.createTime')" align="center" prop="createdAt" min-width="150px">
  100. <template #default="scope">
  101. <span>{{ proxy.parseTime(scope.row.createdAt, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
  102. </template>
  103. </el-table-column>
  104. <el-table-column :label="t('message.flowForm.creator')" align="center" prop="createdBy" min-width="150px" />
  105. <el-table-column :label="t('message.flowForm.operation')" align="center" class-name="small-padding" min-width="200px" fixed="right">
  106. <template #default="scope">
  107. <el-button type="primary" link @click="handleView(scope.row)" v-auth="'detail'"
  108. ><el-icon><ele-View /></el-icon>{{ t('message.flowForm.detail') }}</el-button
  109. >
  110. <el-button type="primary" link @click="handleUpdate(scope.row)" v-auth="'edit'"
  111. ><el-icon><ele-EditPen /></el-icon>{{ t('message.flowForm.edit') }}</el-button
  112. >
  113. <el-button type="primary" link @click="handleGen(scope.row)" v-auth="'gen'"
  114. ><el-icon><ele-Position /></el-icon>{{ t('message.flowForm.deployForm') }}</el-button
  115. >
  116. <el-button type="primary" link @click="handleDelete(scope.row)" v-auth="'del'"
  117. ><el-icon><ele-DeleteFilled /></el-icon>{{ t('message.flowForm.delete') }}</el-button
  118. >
  119. </template>
  120. </el-table-column>
  121. </el-table>
  122. <pagination
  123. v-show="tableData.total > 0"
  124. :total="tableData.total"
  125. v-model:page="tableData.param.pageNum"
  126. v-model:limit="tableData.param.pageSize"
  127. @pagination="flowFormList"
  128. />
  129. </el-card>
  130. <ApiV1FlowFlowFormDetail ref="detailRef" :statusOptions="flow_form_status" @flowFormList="flowFormList"></ApiV1FlowFlowFormDetail>
  131. </div>
  132. </template>
  133. <script lang="ts">
  134. import { computed, defineComponent, getCurrentInstance, onMounted, reactive, ref, toRaw, toRefs, watch } from 'vue'
  135. import { ElMessage, ElMessageBox, FormInstance } from 'element-plus'
  136. import { useI18n } from 'vue-i18n'
  137. import { addFlowForm, delFlowForm, genFlowForm, getFlowForm, listFlowForm } from '/@/api/flow/flowForm'
  138. import {
  139. FlowFormInfoData,
  140. FlowFormTableColumns,
  141. FlowFormTableDataState
  142. } from '/@/views/flow/flowForm/list/component/model'
  143. import ApiV1FlowFlowFormDetail from '/@/views/flow/flowForm/list/component/detail.vue'
  144. import { useRouter } from 'vue-router'
  145. import download from 'downloadjs'
  146. import { useFileDialog } from '@vueuse/core'
  147. export default defineComponent({
  148. name: 'ApiV1FlowFlowFormList',
  149. components: {
  150. ApiV1FlowFlowFormDetail,
  151. },
  152. setup() {
  153. const router = useRouter()
  154. const { proxy } = <any>getCurrentInstance()
  155. const { t } = useI18n()
  156. const loading = ref(false)
  157. const queryRef = ref()
  158. const editRef = ref()
  159. const detailRef = ref()
  160. // 是否显示所有搜索选项
  161. const showAll = ref(false)
  162. // 非单个禁用
  163. const single = ref(true)
  164. // 非多个禁用
  165. const multiple = ref(true)
  166. const word = computed(() => {
  167. if (showAll.value === false) {
  168. //对文字进行处理
  169. return t('message.flowForm.expandSearch')
  170. } else {
  171. return t('message.flowForm.collapseSearch')
  172. }
  173. })
  174. // 字典选项数据
  175. const { flow_form_status } = proxy.useDict('flow_form_status')
  176. const state = reactive<FlowFormTableDataState>({
  177. ids: [],
  178. tableData: {
  179. data: [],
  180. total: 0,
  181. loading: false,
  182. param: {
  183. pageNum: 1,
  184. pageSize: 10,
  185. name: undefined,
  186. status: undefined,
  187. createdAt: undefined,
  188. dateRange: [],
  189. isPub: undefined,
  190. },
  191. },
  192. })
  193. // 页面加载时
  194. onMounted(() => {
  195. initTableData()
  196. })
  197. // 初始化表格数据
  198. const initTableData = () => {
  199. flowFormList()
  200. }
  201. /** 重置按钮操作 */
  202. const resetQuery = (formEl: FormInstance | undefined) => {
  203. if (!formEl) return
  204. formEl.resetFields()
  205. flowFormList()
  206. }
  207. // 获取列表数据
  208. const flowFormList = () => {
  209. loading.value = true
  210. listFlowForm(state.tableData.param).then((res: any) => {
  211. let list = res.list ?? []
  212. list.map((item: any) => {
  213. item.createdBy = item.createdUser?.userNickname
  214. })
  215. state.tableData.data = list
  216. state.tableData.total = res.total
  217. loading.value = false
  218. })
  219. }
  220. const toggleSearch = () => {
  221. showAll.value = !showAll.value
  222. }
  223. // 状态字典翻译
  224. const statusFormat = (row: FlowFormTableColumns) => {
  225. return proxy.selectDictLabel(flow_form_status.value, row.status)
  226. }
  227. const isPubFormat = (row: FlowFormTableColumns) => {
  228. return row.isPub ? t('message.flowForm.deployed') : t('message.flowForm.notDeployed')
  229. }
  230. // 多选框选中数据
  231. const handleSelectionChange = (selection: Array<FlowFormInfoData>) => {
  232. state.ids = selection.map((item) => item.id)
  233. single.value = selection.length != 1
  234. multiple.value = !selection.length
  235. }
  236. const handleAdd = () => {
  237. router.push('/flow/flowForm/formDesign')
  238. }
  239. const handleUpdate = (row: FlowFormTableColumns) => {
  240. if (!row) {
  241. row = state.tableData.data.find((item: FlowFormTableColumns) => {
  242. return item.id === state.ids[0]
  243. }) as FlowFormTableColumns
  244. }
  245. router.push('/flow/flowForm/formDesign?id=' + row.id)
  246. }
  247. const handleGen = (row: FlowFormTableColumns) => {
  248. ElMessageBox.confirm(t('message.flowForm.confirmDeploy'), t('message.flowForm.tip'), {
  249. confirmButtonText: t('message.flowForm.confirm'),
  250. cancelButtonText: t('message.flowForm.cancel'),
  251. type: 'warning',
  252. })
  253. .then(() => {
  254. genFlowForm(row.id).then(() => {
  255. ElMessage.success(t('message.flowForm.deploySuccess'))
  256. flowFormList()
  257. })
  258. })
  259. .catch()
  260. }
  261. const handleDelete = (row: FlowFormTableColumns) => {
  262. let msg = t('message.flowForm.confirmDeleteSelected')
  263. let id: number[] = []
  264. if (row) {
  265. msg = t('message.flowForm.confirmDeleteSingle')
  266. id = [row.id]
  267. } else {
  268. id = state.ids
  269. }
  270. if (id.length === 0) {
  271. ElMessage.error(t('message.flowForm.pleaseSelectDeleteData'))
  272. return
  273. }
  274. ElMessageBox.confirm(msg, t('message.flowForm.tip'), {
  275. confirmButtonText: t('message.flowForm.confirm'),
  276. cancelButtonText: t('message.flowForm.cancel'),
  277. type: 'warning',
  278. })
  279. .then(() => {
  280. delFlowForm(id).then(() => {
  281. ElMessage.success(t('message.flowForm.deleteSuccess'))
  282. flowFormList()
  283. })
  284. })
  285. .catch(() => {})
  286. }
  287. const handleView = (row: FlowFormTableColumns) => {
  288. detailRef.value.openDialog(toRaw(row))
  289. }
  290. const { open, files, reset } = useFileDialog({
  291. multiple: false,
  292. accept: '.json',
  293. })
  294. const handleImport = open
  295. watch(files, async (newVal) => {
  296. if (newVal === null || newVal?.length === 0) {
  297. return
  298. }
  299. const file = newVal[0]
  300. const json = await new Promise<string>((resolve, reject) => {
  301. const reader = new FileReader()
  302. reader.readAsText(file)
  303. reader.onload = function (e: ProgressEvent<FileReader>) {
  304. if (e.target === null) {
  305. reject()
  306. return
  307. }
  308. if (typeof e.target.result == 'string') {
  309. resolve(e.target.result)
  310. return
  311. }
  312. reject()
  313. }
  314. })
  315. const x = JSON.parse(json)
  316. const result = await Promise.all<{ success: boolean; result?: FlowFormInfoData }>(
  317. x.map(async (it: FlowFormInfoData) => {
  318. return await addFlowForm(it)
  319. .then(() => {
  320. return { success: true }
  321. })
  322. .catch(() => {
  323. return { success: false, result: it }
  324. })
  325. })
  326. )
  327. const failed = result.filter((it) => !it)
  328. if (failed.length == 0) {
  329. ElMessage.success(t('message.flowForm.importSuccess'))
  330. flowFormList()
  331. reset()
  332. return
  333. }
  334. const showErrorDialog = await ElMessageBox.alert(t('message.flowForm.importFailed', { count: failed.length }), t('message.flowForm.tip'), {
  335. confirmButtonText: t('message.flowForm.viewFailedData'),
  336. cancelButtonText: t('message.flowForm.confirm'),
  337. type: 'warning',
  338. })
  339. if (showErrorDialog) {
  340. download(JSON.stringify(failed.map((it) => it.result)), t('message.flowForm.failedFileName'))
  341. }
  342. reset()
  343. })
  344. const handleExport = async () => {
  345. const exp: Array<any> = await Promise.all(state.ids.map(getFlowForm))
  346. download(
  347. JSON.stringify(
  348. exp.map((it) => {
  349. return {
  350. name: it.name,
  351. conf: it.conf,
  352. fields: it.fields,
  353. remark: it.remark,
  354. status: it.status,
  355. }
  356. })
  357. ),
  358. t('message.flowForm.exportFileName')
  359. )
  360. }
  361. return {
  362. t,
  363. proxy,
  364. editRef,
  365. detailRef,
  366. showAll,
  367. loading,
  368. single,
  369. multiple,
  370. word,
  371. queryRef,
  372. resetQuery,
  373. flowFormList,
  374. toggleSearch,
  375. statusFormat,
  376. flow_form_status,
  377. handleSelectionChange,
  378. handleAdd,
  379. handleUpdate,
  380. handleDelete,
  381. handleView,
  382. handleGen,
  383. isPubFormat,
  384. handleImport,
  385. handleExport,
  386. ...toRefs(state),
  387. }
  388. },
  389. })
  390. </script>
  391. <style lang="scss" scoped>
  392. .colBlock {
  393. display: block;
  394. }
  395. .colNone {
  396. display: none;
  397. }
  398. .ml-2 {
  399. margin: 3px;
  400. }
  401. </style>