index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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. const newIds: any = []
  213. map.forEach((v) => {
  214. newIds.push(v.id)
  215. v.haveOrNo = route.query.haveOrNo
  216. if (!state.allSelected.has(v.id)) {
  217. state.allSelected.set(v.id, JSON.parse(JSON.stringify(v)))
  218. }
  219. })
  220. Array.from(state.allSelected.keys()).forEach((v) => {
  221. if (!newIds.includes(v)) {
  222. state.allSelected.delete(v)
  223. }
  224. })
  225. }
  226. const onClear = () => {
  227. ElMessageBox.confirm('请确认是否清空全部数据?', '提示')
  228. .then(() => {
  229. state.allSelected.clear()
  230. })
  231. .catch(() => {})
  232. }
  233. const onTextImport = () => {
  234. state.textImport.transfer = {}
  235. state.textImport.show = true
  236. }
  237. const onGetTextImport = (arr) => {
  238. arr.forEach((v) => {
  239. v.haveOrNo = route.query.haveOrNo
  240. if (!state.allSelected.has(v.id)) {
  241. state.allSelected.set(v.id, v)
  242. }
  243. })
  244. }
  245. const onExcelImport = () => {
  246. state.excelImport.transfer = {}
  247. state.excelImport.show = true
  248. }
  249. const onGetExcelImport = (arr) => {
  250. arr.forEach((v) => {
  251. v.haveOrNo = route.query.haveOrNo
  252. if (!state.allSelected.has(v.id)) {
  253. state.allSelected.set(v.id, v)
  254. }
  255. })
  256. }
  257. const onSubmit = () => {
  258. const list: any = Array.from(state.allSelected.values())
  259. const ids = Array.from(state.allSelected.keys()).join(',')
  260. if (route.query.haveOrNo == 1) {
  261. for (let i = 0; i < list.length; i++) {
  262. if (!isValue(list[i].reserves)) {
  263. ElMessage({
  264. // dangerouslyUseHTMLString: true,
  265. // grouping: true,
  266. // 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>)`,
  267. type: 'warning',
  268. message: h(
  269. 'span',
  270. {
  271. class: 'text-[14px] text-[var(--czr-warning-color)]',
  272. },
  273. [
  274. h(
  275. 'span',
  276. null,
  277. `${state.query.head.filter((v) => v.value === 'reserves')[0].label}不可为空(第${Math.ceil((i + 1) / state.query.page.pageSize)}页,第${(i + 1) % state.query.page.pageSize}条数据)`,
  278. ),
  279. Object.keys(state.query.formReal).length > 0
  280. ? h(
  281. 'span',
  282. {
  283. class: '__hover text-[var(--czr-main-color)] font-bold',
  284. onClick: onReset,
  285. },
  286. '重置查询',
  287. )
  288. : undefined,
  289. ],
  290. ),
  291. })
  292. return
  293. }
  294. }
  295. }
  296. axios
  297. .post(
  298. `${ApiProxy.value}/api/blade-dcms/hazardouschemicalscatalog/selectCatalogStrBYIds`,
  299. {
  300. ids: ids,
  301. apiname: import.meta.env.VITE_API_NAME,
  302. },
  303. {},
  304. )
  305. .then((res: any) => {
  306. if (res.data.code == 0) {
  307. const strs = res.data.data
  308. onConfirmIframe({ wfIds: ids, wfList: list, wfStrs: strs })
  309. } else {
  310. ElMessage.error(res.data.msg)
  311. }
  312. })
  313. .catch((e) => {
  314. console.log(e)
  315. ElMessage.error(e.response.data.msg)
  316. })
  317. }
  318. const initList = (wfList) => {
  319. const map = new Map()
  320. wfList?.forEach((v) => {
  321. map.set(v.id, v)
  322. })
  323. state.allSelected = map
  324. }
  325. onBeforeMount(() => {
  326. if (!route.query.haveOrNo) {
  327. ElMessage.error('URL地址缺少参数haveOrNo')
  328. }
  329. // ⼆级⻚⾯需要通过监听 getFormIframeData 事件,获取表单中⼼⼀级⻚⾯传递过来的数据。
  330. // formItem 表单项配置数据,该数据在⼆级⻚⾯回传数据给⼀级⻚⾯时需要原封不动传回 Object
  331. // formData 表单项填写数据 Object
  332. // userData ⽤户信息数据 Object
  333. // payload 额外的荷载数据,⼦表组件下的要素能通过此项获取到⼦表⾏数据 Object
  334. // apis 表单中⼼接⼝配置数据,详情可查看 ApisObject 参数说明 ApisObject
  335. // ApisObject.headers 接⼝请求头配置 Object
  336. // ApisObject.params 接⼝请求参数配置 Object
  337. // ApisObject.config 接⼝配置信息 Object
  338. window.addEventListener('message', (e) => {
  339. const data = e.data
  340. console.log(data)
  341. if (data.type === 'getFormIframeData') {
  342. const { formItem, formData, userData, apis, payload } = data.data
  343. state.formMessage = JSON.parse(JSON.stringify(data.data))
  344. state.isInit = true
  345. initList(formData.wfList)
  346. }
  347. })
  348. window.parent.postMessage(
  349. {
  350. type: 'setFormConfig',
  351. formHeight: 800,
  352. },
  353. '*',
  354. )
  355. })
  356. onMounted(() => {
  357. initDictionary()
  358. onReset()
  359. })
  360. const initDictionary = () => {}
  361. const onConfirmIframe = (msgData) => {
  362. window.parent.postMessage(
  363. {
  364. type: 'onConfirmIframe',
  365. data: JSON.parse(
  366. JSON.stringify({
  367. ...state.formMessage,
  368. msgData, // ⼆级⻚⾯数据
  369. }),
  370. ),
  371. },
  372. '*',
  373. )
  374. }
  375. const onCloseIframe = () => {
  376. window.parent.postMessage(
  377. {
  378. type: 'onCloseIframe',
  379. },
  380. '*',
  381. )
  382. }
  383. </script>
  384. <style lang="scss" scoped></style>