index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. <template>
  2. <div class="w-full h-full flex flex-col" v-if="state.isInit">
  3. <div class="flex-1">
  4. <CzrContent
  5. v-model:tableHead="state.query.tableHead"
  6. @handleReset="onReset"
  7. @handleSearch="onSearch"
  8. v-model:full="state.query.isFull"
  9. >
  10. <template #fieldOut>
  11. <CzrForm label-width="auto" @handleEnter="onSearch">
  12. <CzrFormColumn
  13. :span="6"
  14. label="名称"
  15. v-model:param="state.query.form.name"
  16. />
  17. <CzrFormColumn
  18. :span="6"
  19. label="别名"
  20. v-model:param="state.query.form.alias"
  21. />
  22. <CzrFormColumn
  23. :span="6"
  24. label="CAS号"
  25. v-model:param="state.query.form.casNo"
  26. />
  27. <CzrSearchButtons @handleSearch="onSearch" @handleReset="onReset" />
  28. </CzrForm>
  29. </template>
  30. <template #tableTitle>
  31. <div class="flex gap-[10px]">
  32. <CzrButton type="import" title="Excel导入" @click="onExcelImport" />
  33. <CzrButton type="import" title="文本导入" @click="onTextImport" />
  34. <CzrButton type="add" title="新增" @click="onAdd" />
  35. <CzrButton type="del" title="清空全部" @click="onClear" />
  36. </div>
  37. </template>
  38. <template #table>
  39. <CzrTable
  40. v-loading="state.query.loading"
  41. ref="ref_cusTable"
  42. :data="tableDataCpt"
  43. :head="state.query.head"
  44. :total="state.allSelected.size"
  45. :page="state.query.page.pageNum"
  46. :pageSize="state.query.page.pageSize"
  47. @handlePage="onPage"
  48. >
  49. <template #reserves-column-value="{ scope }">
  50. <CzrFormColumn
  51. class="__czr-table-form-column"
  52. label-width="0px"
  53. :span="24"
  54. v-model:param="scope.row.reserves"
  55. link="number"
  56. :min="0.00001"
  57. :decimal="5"
  58. />
  59. </template>
  60. <template #caozuo-column-value="{ scope }">
  61. <div class="__czr-table-operations">
  62. <CzrButton
  63. type="table-del"
  64. @click="state.allSelected.delete(scope.row.id)"
  65. />
  66. </div>
  67. </template>
  68. </CzrTable>
  69. </template>
  70. </CzrContent>
  71. </div>
  72. <div class="w-full flex justify-center gap-[10px] py-[20px]">
  73. <div class="__czr-dialog-foot_submit __hover" @click="onSubmit">确定</div>
  74. <div class="__czr-dialog-foot_cancel __hover" @click="onCloseIframe">
  75. 取消
  76. </div>
  77. </div>
  78. <listCom
  79. v-model:show="state.list.show"
  80. :transfer="state.list.transfer"
  81. @refresh="onGetList"
  82. />
  83. <textImportCom
  84. v-model:show="state.textImport.show"
  85. :transfer="state.textImport.transfer"
  86. @refresh="onGetTextImport"
  87. />
  88. <excelImportCom
  89. v-model:show="state.excelImport.show"
  90. :transfer="state.excelImport.transfer"
  91. @refresh="onGetExcelImport"
  92. />
  93. </div>
  94. </template>
  95. <script setup lang="ts">
  96. import {
  97. computed,
  98. getCurrentInstance,
  99. h,
  100. onBeforeMount,
  101. onMounted,
  102. provide,
  103. reactive,
  104. ref,
  105. } from 'vue'
  106. import listCom from './list.vue'
  107. import textImportCom from './text-import.vue'
  108. import excelImportCom from './excel-import.vue'
  109. import { ElMessage, ElMessageBox } from 'element-plus'
  110. import axios from 'axios'
  111. import { useRoute } from 'vue-router'
  112. import { useDictionaryStore } from '@/stores'
  113. import CzrFormColumn from '@/components/czr-ui/CzrFormColumn.vue'
  114. import { isValue } from '@/utils/czr-util'
  115. const route = useRoute()
  116. const DictionaryStore = useDictionaryStore()
  117. const emit = defineEmits([])
  118. const props = defineProps({})
  119. const { proxy }: any = getCurrentInstance()
  120. const state: any = reactive({
  121. isInit: false,
  122. query: {
  123. loading: false,
  124. head: [
  125. { value: 'name', label: '名称', show: true },
  126. { value: 'alias', label: '别名', show: true },
  127. { value: 'casNo', label: 'CAS号', show: true },
  128. {
  129. value: 'haveOrNo',
  130. label: '有/无存储',
  131. show: true,
  132. dictList: DictionaryStore.businessModelHaveOrNoList,
  133. },
  134. {
  135. value: 'reserves',
  136. label: '储量(m³/吨)',
  137. show: true,
  138. required: route.query.haveOrNo == 1,
  139. },
  140. {
  141. value: 'caozuo',
  142. label: '操作',
  143. show: true,
  144. width: 300,
  145. fixed: 'right',
  146. popover: false,
  147. },
  148. ],
  149. page: {
  150. pageNum: 1,
  151. pageSize: 20,
  152. },
  153. form: {},
  154. formReal: {},
  155. result: {
  156. total: 0,
  157. data: [],
  158. },
  159. },
  160. formMessage: null,
  161. allSelected: new Map(),
  162. list: {
  163. show: false,
  164. transfer: {},
  165. },
  166. textImport: {
  167. show: false,
  168. transfer: {},
  169. },
  170. excelImport: {
  171. show: false,
  172. transfer: {},
  173. },
  174. })
  175. const ApiProxy = ref(`${import.meta.env.DEV ? '' : location.origin}/wForm`)
  176. provide('ApiProxy', ApiProxy)
  177. provide('haveOrNo', route.query.haveOrNo)
  178. const tableDataCpt = computed(() => {
  179. let arr = [...Array.from(state.allSelected.values())]
  180. // 添加表单参数
  181. for (const [k, v] of Object.entries(state.query.formReal)) {
  182. if (proxy.$czrUtil.isValue(v)) {
  183. arr = arr.filter((d: any) => d[k].includes(v))
  184. }
  185. }
  186. return arr.slice(
  187. (state.query.page.pageNum - 1) * state.query.page.pageSize,
  188. state.query.page.pageNum * state.query.page.pageSize,
  189. )
  190. })
  191. const onPage = (pageNum, pageSize) => {
  192. state.query.page = {
  193. pageNum: pageNum,
  194. pageSize: pageSize,
  195. }
  196. }
  197. const onSearch = () => {
  198. state.query.formReal = JSON.parse(JSON.stringify(state.query.form))
  199. onPage(1, state.query.page.pageSize)
  200. }
  201. const onReset = () => {
  202. state.query.form = {}
  203. onSearch()
  204. }
  205. const onAdd = () => {
  206. state.list.transfer = {
  207. allSelected: state.allSelected,
  208. }
  209. state.list.show = true
  210. }
  211. const onGetList = (map) => {
  212. map.forEach((v) => {
  213. v.haveOrNo = route.query.haveOrNo
  214. })
  215. state.allSelected = new Map(map)
  216. }
  217. const onClear = () => {
  218. ElMessageBox.confirm('请确认是否清空全部数据?', '提示')
  219. .then(() => {
  220. state.allSelected.clear()
  221. })
  222. .catch(() => {})
  223. }
  224. const onTextImport = () => {
  225. state.textImport.transfer = {}
  226. state.textImport.show = true
  227. }
  228. const onGetTextImport = (arr) => {
  229. arr.forEach((v) => {
  230. v.haveOrNo = route.query.haveOrNo
  231. state.allSelected.set(v.id, v)
  232. })
  233. }
  234. const onExcelImport = () => {
  235. state.excelImport.transfer = {}
  236. state.excelImport.show = true
  237. }
  238. const onGetExcelImport = (arr) => {
  239. arr.forEach((v) => {
  240. v.haveOrNo = route.query.haveOrNo
  241. state.allSelected.set(v.id, v)
  242. })
  243. }
  244. const onSubmit = () => {
  245. const list: any = Array.from(state.allSelected.values())
  246. const ids = Array.from(state.allSelected.keys()).join(',')
  247. if (route.query.haveOrNo == 1) {
  248. for (let i = 0; i < list.length; i++) {
  249. if (!isValue(list[i].reserves)) {
  250. ElMessage({
  251. // dangerouslyUseHTMLString: true,
  252. // grouping: true,
  253. // message: `${state.query.head.filter((v) => v.value === 'reserves')[0].label}不可为空(第${Math.ceil((i + 1) / state.query.page.pageSize)}页,第${(i + 1) % state.query.page.pageSize}条数据,<span class="__hover text-[var(--czr-main-color)]" @click="onReset">重置查询</span>)`,
  254. type: 'warning',
  255. message: h(
  256. 'span',
  257. {
  258. class: 'text-[14px] text-[var(--czr-warning-color)]',
  259. },
  260. [
  261. h(
  262. 'span',
  263. null,
  264. `${state.query.head.filter((v) => v.value === 'reserves')[0].label}不可为空(第${Math.ceil((i + 1) / state.query.page.pageSize)}页,第${(i + 1) % state.query.page.pageSize}条数据)`,
  265. ),
  266. Object.keys(state.query.formReal).length > 0
  267. ? h(
  268. 'span',
  269. {
  270. class: '__hover text-[var(--czr-main-color)] font-bold',
  271. onClick: onReset,
  272. },
  273. '重置查询',
  274. )
  275. : undefined,
  276. ],
  277. ),
  278. })
  279. return
  280. }
  281. }
  282. }
  283. axios
  284. .post(
  285. `${ApiProxy.value}/api/blade-dcms/hazardouschemicalscatalog/selectCatalogStrBYIds`,
  286. {
  287. ids: ids,
  288. apiname: import.meta.env.VITE_API_NAME,
  289. },
  290. {},
  291. )
  292. .then((res: any) => {
  293. if (res.data.code == 0) {
  294. const strs = res.data.data
  295. onConfirmIframe({ wfIds: ids, wfList: list, wfStrs: strs })
  296. } else {
  297. ElMessage.error(res.data.msg)
  298. }
  299. })
  300. .catch((e) => {
  301. console.log(e)
  302. ElMessage.error(e.response.data.msg)
  303. })
  304. }
  305. const initList = (wfList) => {
  306. const map = new Map()
  307. wfList?.forEach((v) => {
  308. map.set(v.id, v)
  309. })
  310. state.allSelected = map
  311. }
  312. onBeforeMount(() => {
  313. if (!route.query.haveOrNo) {
  314. ElMessage.error('URL地址缺少参数haveOrNo')
  315. }
  316. // ⼆级⻚⾯需要通过监听 getFormIframeData 事件,获取表单中⼼⼀级⻚⾯传递过来的数据。
  317. // formItem 表单项配置数据,该数据在⼆级⻚⾯回传数据给⼀级⻚⾯时需要原封不动传回 Object
  318. // formData 表单项填写数据 Object
  319. // userData ⽤户信息数据 Object
  320. // payload 额外的荷载数据,⼦表组件下的要素能通过此项获取到⼦表⾏数据 Object
  321. // apis 表单中⼼接⼝配置数据,详情可查看 ApisObject 参数说明 ApisObject
  322. // ApisObject.headers 接⼝请求头配置 Object
  323. // ApisObject.params 接⼝请求参数配置 Object
  324. // ApisObject.config 接⼝配置信息 Object
  325. window.addEventListener('message', (e) => {
  326. const data = e.data
  327. if (data.type === 'getFormIframeData') {
  328. const { formItem, formData, userData, apis, payload, wfList } = data.data
  329. state.formMessage = JSON.parse(JSON.stringify(data.data))
  330. state.isInit = true
  331. initList(wfList)
  332. }
  333. })
  334. })
  335. onMounted(() => {
  336. initDictionary()
  337. onReset()
  338. window.parent.postMessage(
  339. {
  340. type: 'setFormConfig',
  341. data: JSON.parse(
  342. JSON.stringify({
  343. formHeight: 800,
  344. }),
  345. ),
  346. },
  347. '*',
  348. )
  349. })
  350. const initDictionary = () => {}
  351. const onConfirmIframe = (msgData) => {
  352. window.parent.postMessage(
  353. {
  354. type: 'onConfirmIframe',
  355. data: JSON.parse(
  356. JSON.stringify({
  357. ...state.formMessage,
  358. msgData, // ⼆级⻚⾯数据
  359. }),
  360. ),
  361. },
  362. '*',
  363. )
  364. }
  365. const onCloseIframe = () => {
  366. window.parent.postMessage(
  367. {
  368. type: 'onCloseIframe',
  369. },
  370. '*',
  371. )
  372. }
  373. </script>
  374. <style lang="scss" scoped></style>