index.vue 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920
  1. <!-- 📚📚📚 Vxe-Table 文档: https://vxetable.cn/#/table/start/install -->
  2. <template>
  3. <!-- 查询表单 card -->
  4. <!-- <div class="table-box"> -->
  5. <SearchForm
  6. v-if="ifSearch && isShowSearch"
  7. :search="search"
  8. :reset="reset"
  9. :columns="searchColumns"
  10. :search-param="searchParam"
  11. :search-col="searchCol"
  12. :search-btn-size-extent="searchBtnSizeExtent"
  13. :project="tableprop_save?.searchProject"
  14. :form-props="tableprop_save?.search ?? {}"
  15. :layout-attr-define="searchFormDefault"
  16. @confirm="saveSearchSettingFunc"
  17. @save-project="editSearchProjectFunc"
  18. @updata-params="autoUpdataSearchParams"
  19. />
  20. <!-- 表格内容 card -->
  21. <div class="table-main flx-col" :class="`${propsDefine.height == 'auto' ? 'flx-1 overflow-hidden' : ''} ${tableCls}`">
  22. <!-- 表格头部 操作按钮 -->
  23. <div class="table-header flx-shrink">
  24. <div class="header-button-lf">
  25. <slot name="tableHeader" />
  26. </div>
  27. <div class="header-button-ri" v-if="toolButton.length" id="toolButton">
  28. <slot name="toolButton" :openColSetting="openColSetting" :refresh="refresh" :settingBtnLoading="settingBtnLoading">
  29. <template v-if="!collapseButtons">
  30. <el-tooltip
  31. v-if="defaultSort.length"
  32. effect="dark"
  33. :content="$t('common.table.clearSortBtn')"
  34. placement="top"
  35. :show-after="200"
  36. >
  37. <el-button :icon="Brush" round @click="clearSortEvent()">
  38. <span class="flx-center mr-6" v-for="(item, idx) in defaultSort" :key="idx">
  39. <!-- {{ item.field }} -->
  40. <span :class="globalStore.assemblySize == 'small' ? 'text-f-c' : 'text-body-c'">
  41. {{ item.title ? item.title : $t(`table.${item.table}.${item.field}`) }}
  42. </span>
  43. <i
  44. :class="{
  45. iconfont: true,
  46. 'iconarrow-narrow-up': item.order == 'asc',
  47. 'iconarrow-narrow-down': item.order == 'desc'
  48. }"
  49. ></i>
  50. </span>
  51. </el-button>
  52. </el-tooltip>
  53. <!-- <el-button-group class="table-main__tool-button ml-12 mr-12" -->
  54. <el-dropdown trigger="contextmenu" ref="printerListTpDropdownRef" v-if="getToolButton('print')">
  55. <el-button :icon="Printer" circle @click="checkPrintTemplateList('')"> </el-button>
  56. <template #dropdown>
  57. <el-dropdown-menu>
  58. <template v-if="printerTpList.length">
  59. <el-dropdown-item
  60. class="flx-justify-between"
  61. v-for="(item, index) in printerTpList"
  62. :key="index"
  63. @click="openPrintPriveiew('', item, Boolean(item.printer))"
  64. >
  65. {{ item.aliase || item.printid }}
  66. <el-tooltip
  67. v-if="item.printer"
  68. effect="dark"
  69. :content="$t('sys.print.directPrint')"
  70. placement="top"
  71. :show-after="200"
  72. :enterable="false"
  73. :hide-after="0"
  74. >
  75. <i class="iconfont iconflash ml-8" :style="{ color: _variables.colorPolarGreen4 }"></i>
  76. </el-tooltip>
  77. </el-dropdown-item>
  78. </template>
  79. <el-dropdown-item :divided="Boolean(printerTpList.length)" @click="openPrint('')">
  80. <div class="flx-center">
  81. <el-icon>
  82. <Setting />
  83. </el-icon>
  84. {{ $t("common.setText") }}
  85. </div>
  86. </el-dropdown-item>
  87. </el-dropdown-menu>
  88. </template>
  89. </el-dropdown>
  90. <!-- <el-button class="pl-10 pr-10" :icon="Setting" @click="openPrint('')"> </el-button> -->
  91. <!-- </el-button-group> -->
  92. <el-button-group class="table-main__tool-button mr-12" v-if="getToolButton('printMx')">
  93. <el-tooltip
  94. v-if="Boolean(hiprinterStateMx)"
  95. effect="dark"
  96. :content="$t('sys.print.directPrint')"
  97. placement="top"
  98. :show-after="200"
  99. >
  100. <el-button class="pl-10 pr-10" @click="openPrintPriveiew('_mx', true)">
  101. <template #icon>
  102. <i class="iconfont iconflash"></i>
  103. </template>
  104. </el-button>
  105. </el-tooltip>
  106. <el-tooltip effect="dark" :content="$t('common.table.print')" placement="top" :show-after="200">
  107. <el-button :icon="Printer" @click="openPrintPriveiew('_mx', null)">
  108. <span class="text-body-c">{{ $t("common.table.detail") }}</span>
  109. </el-button>
  110. </el-tooltip>
  111. <el-button :icon="Setting" class="pl-10 pr-10" @click="openPrint('_mx')"> </el-button>
  112. </el-button-group>
  113. <el-button class="refresh-btn" :icon="Refresh" circle @click="refresh" v-if="toolButton.indexOf('refresh') > -1" />
  114. <el-tooltip
  115. effect="dark"
  116. v-if="getToolButton('export')"
  117. :content="$t('common.table.downloadBtn')"
  118. placement="top"
  119. :show-after="200"
  120. >
  121. <el-button class="default-btn" :icon="Download" circle @click="exportDataEvent" />
  122. </el-tooltip>
  123. <el-tooltip
  124. effect="dark"
  125. :content="$t('common.table.searchBtn')"
  126. placement="top"
  127. :show-after="200"
  128. v-if="toolButton.indexOf('search') > -1 && searchColumns.length"
  129. >
  130. <el-button
  131. :icon="Search"
  132. circle
  133. :type="isShowSearch ? 'primary' : ''"
  134. class="search-btn default-btn"
  135. :class="{ active: isShowSearch }"
  136. @click="isShowSearch = !isShowSearch"
  137. />
  138. </el-tooltip>
  139. <el-tooltip
  140. effect="dark"
  141. :content="$t('common.table.location')"
  142. placement="top"
  143. :show-after="200"
  144. v-if="toolButton.indexOf('location') > -1"
  145. >
  146. <el-button ref="locationBtnRef" :icon="Location" circle class="search-btn default-btn" />
  147. </el-tooltip>
  148. <el-tooltip
  149. effect="dark"
  150. v-if="toolButton.indexOf('guide') > -1"
  151. :content="$t('common.table.guide')"
  152. placement="top"
  153. :show-after="200"
  154. >
  155. <el-button class="default-btn" :icon="Guide" circle @click="checkIfNeedGuide(true)" />
  156. </el-tooltip>
  157. <template v-if="toolButton.indexOf('setting') > -1 && columns.length">
  158. <el-divider direction="vertical" />
  159. <el-tooltip effect="dark" :content="$t('common.table.tableSetBtn')" placement="top" :show-after="200">
  160. <el-button
  161. class="default-btn"
  162. id="toolButtonSetting"
  163. :icon="Operation"
  164. circle
  165. :loading="settingBtnLoading"
  166. @click="openColSetting"
  167. />
  168. </el-tooltip>
  169. </template>
  170. </template>
  171. </slot>
  172. </div>
  173. </div>
  174. <!-- 表格主体 -->
  175. <div
  176. id="vxeTableBody"
  177. class="relative table-warpper"
  178. :class="{ 'flx-1': propsDefine.height == 'auto' }"
  179. :style="{ minHeight: propsDefine?.minHeight }"
  180. >
  181. <el-dropdown
  182. v-if="collapseButtons && (defaultSort.length || toolButton.length)"
  183. class="collapse-buttons__group"
  184. placement="bottom-end"
  185. trigger="click"
  186. :teleported="false"
  187. >
  188. <el-button class="more-btn" :icon="More" circle></el-button>
  189. <template #dropdown>
  190. <el-dropdown-menu>
  191. <el-dropdown-item v-if="defaultSort.length" :icon="Brush" @click="clearSortEvent()">
  192. {{ $t("common.table.clearSortBtn") }}
  193. </el-dropdown-item>
  194. <el-dropdown-item v-if="toolButton.indexOf('refresh') > -1" :icon="Refresh" @click="refresh">
  195. {{ $t("tabs.refresh") }}
  196. </el-dropdown-item>
  197. <el-dropdown-item
  198. v-if="toolButton.indexOf('search') > -1 && searchColumns.length"
  199. :icon="Search"
  200. @click="isShowSearch = !isShowSearch"
  201. >
  202. {{ $t("common.table.searchBtn") }}
  203. </el-dropdown-item>
  204. <div ref="locationBtnRef" v-if="toolButton.indexOf('location') > -1">
  205. <el-dropdown-item :icon="Location">
  206. {{ $t("common.table.location") }}
  207. </el-dropdown-item>
  208. </div>
  209. <el-dropdown-item v-if="getToolButton('export')" :icon="Download" @click="exportDataEvent">
  210. {{ $t("common.table.downloadBtn") }}
  211. </el-dropdown-item>
  212. <el-dropdown-item v-if="getToolButton('import')" :icon="Upload" @click="importDataEvent">
  213. {{ $t("common.table.ImportBtn") }}
  214. </el-dropdown-item>
  215. <el-dropdown-item v-if="toolButton.indexOf('guide') > -1" :icon="Guide" @click="checkIfNeedGuide(true)">
  216. {{ $t("common.table.guide") }}
  217. </el-dropdown-item>
  218. <el-dropdown-item divided v-if="toolButton.indexOf('setting') > -1" :icon="Operation" @click="openColSetting">
  219. {{ $t("common.table.tableSetBtn") }}
  220. </el-dropdown-item>
  221. </el-dropdown-menu>
  222. </template>
  223. </el-dropdown>
  224. <vxe-table
  225. ref="tableRef"
  226. class="lj-vxetable"
  227. v-bind="tableOptions"
  228. :data="data ?? tableData"
  229. :key="isUpdate"
  230. :loading="tableLoading || extraLoading"
  231. v-on="propsEvents"
  232. :size="tableSize"
  233. >
  234. <!-- @resizable-change="handleResizChange" -->
  235. <!-- 默认插槽 -->
  236. <slot></slot>
  237. <template v-for="item in tableColumns" :key="item">
  238. <!-- checkbox || seq || expand -->
  239. <vxe-column v-bind="item" :align="item.align ?? 'center'" v-if="item.type && TABLE_TYPE_FILTER.includes(item.type)">
  240. <template #content="scope" v-if="item.type == 'expand'">
  241. <slot :name="item.type" v-bind="scope"></slot>
  242. </template>
  243. </vxe-column>
  244. <TableColumn
  245. v-if="(!item.type || item.type == 'html') && item.field && item.visible"
  246. :column="item"
  247. :editable="tableOptions?.editConfig?.enabled"
  248. >
  249. <template v-for="slotKey in Object.keys($slots)" #[slotKey]="scope">
  250. <slot :name="slotKey" v-bind="scope"></slot>
  251. </template>
  252. <template v-for="slotKey in Object.keys($slots)" #[`edit_${slotKey}`]="scope">
  253. <slot :name="`edit_${slotKey}`" v-bind="scope"></slot>
  254. </template>
  255. </TableColumn>
  256. </template>
  257. <!-- 插入表格最后一行之后的插槽 -->
  258. <!-- <template #append>
  259. <slot name="append"> </slot>
  260. </template> -->
  261. <!-- 无数据 -->
  262. <template #empty>
  263. <div class="table-empty">
  264. <slot name="empty">
  265. <img src="@/assets/images/notData.png" alt="notData" />
  266. <div>暂无数据</div>
  267. </slot>
  268. </div>
  269. </template>
  270. <template #loading>
  271. <LoadingCom />
  272. </template>
  273. </vxe-table>
  274. </div>
  275. <!-- 分页组件 -->
  276. <div class="flx-shrink">
  277. <div class="flx-justify-between">
  278. <div class="left_part">
  279. <slot name="pagination_left" />
  280. </div>
  281. <slot
  282. name="pagination"
  283. :pagination="pagination"
  284. :pageable="pageable"
  285. :pageSizes="pageSizes"
  286. :pageChange="handlePageChange"
  287. >
  288. <Pagination v-if="pagination" :pageable="pageable" :page-sizes="pageSizes" :handle-page-change="handlePageChange" />
  289. </slot>
  290. </div>
  291. </div>
  292. </div>
  293. <!-- 列设置 -->
  294. <ColSetting
  295. v-if="toolButton.length && toolButton.indexOf('setting') > -1"
  296. ref="baseMsgSettingRef"
  297. :data="colSetting"
  298. :title="props.title"
  299. :enum-map="baseEnumMap"
  300. :scroll-y-default="propsDefine.scrollY"
  301. @to-scroll-col="funcScrollToCol"
  302. @confirm="settingConfirm"
  303. @reset="resetSetting"
  304. @save-default="saveDefaultLayout"
  305. />
  306. <PrintEditor ref="printEditorRef" v-if="toolButton.length && toolButton.indexOf('print') > -1" @closed="toClosedPrintEditor" />
  307. <PrintTemplateSelector
  308. ref="printTemplateRef"
  309. v-if="toolButton.length && toolButton.indexOf('print') > -1"
  310. @newtemplate="toEditPrintTemplate"
  311. @edittemplate="toEditPrintTemplate"
  312. @preview="toPreviewPrintTemplate"
  313. @confirm="toPrintPrintTemplate"
  314. @closed="toGetPrinterState"
  315. />
  316. <!-- <LjDialog
  317. ref="locationDialogRef"
  318. :modal="false"
  319. width="20%"
  320. class="small find-dialog"
  321. :closed="autoCloseLocation"
  322. :close-on-click-modal="false"
  323. >
  324. <template #header>
  325. <el-tabs v-model="locationTabActive" class="tableheader-tabs">
  326. <el-tab-pane :label="$t('common.table.find') + $t('common.table.data')" name="data"></el-tab-pane>
  327. <el-tab-pane :label="$t('common.table.find') + $t('common.table.col')" name="col"></el-tab-pane>
  328. </el-tabs>
  329. </template>
  330. <el-form :model="locationFrom" label-width="auto">
  331. <el-form-item :label="$t('common.table.col')" class="mb-8">
  332. <el-autocomplete
  333. ref="locationAutocompleteRef"
  334. v-model="locationFrom.field"
  335. :fetch-suggestions="locationQuerySearch"
  336. popper-class="my-autocomplete"
  337. :placeholder="$t('common.table.locationTips')"
  338. value-key="field"
  339. clearable
  340. class="w-full"
  341. @select="funcScrollToCol"
  342. >
  343. <template #default="{ item }">
  344. <div class="flx-justify-between">
  345. <div class="text-body-b">{{ item.title }}</div>
  346. <span class="pl-8 text-secondary-text">{{ item.field }}</span>
  347. </div>
  348. </template>
  349. </el-autocomplete>
  350. </el-form-item>
  351. <el-form-item :label="$t('common.table.data')" style="margin-bottom: 0" v-if="locationTabActive == 'data'">
  352. <el-input v-model="locationFrom.value" @input="disshow(locationFrom.value)">
  353. <template #suffix>
  354. <template v-if="matchData.length">
  355. <span>
  356. {{ `${matchIndex + 1}/${matchData.length}` }}
  357. </span>
  358. </template>
  359. <el-button class="ml-4 pl-5 pr-5" text size="small" @click="funcChangeLocation(-1)">
  360. <template #icon>
  361. <i class="iconfont iconarrow-narrow-up"></i>
  362. </template>
  363. </el-button>
  364. <el-button class="ml-2 pl-5 pr-5" text size="small" @click="funcChangeLocation(1)">
  365. <template #icon>
  366. <i class="iconfont iconarrow-narrow-down"></i>
  367. </template>
  368. </el-button>
  369. </template>
  370. </el-input>
  371. </el-form-item>
  372. </el-form>
  373. </LjDialog> -->
  374. <el-popover
  375. ref="locationRef"
  376. :virtual-ref="locationBtnRef"
  377. trigger="click"
  378. virtual-triggering
  379. placement="bottom-end"
  380. :width="240"
  381. :show-arrow="!collapseButtons"
  382. @show="autoShowLocationPopover"
  383. >
  384. <div class="text-h5-m mb-8">
  385. {{ $t("common.table.location") }}
  386. </div>
  387. <el-autocomplete
  388. ref="locationAutocompleteRef"
  389. v-model="scrollCol"
  390. :fetch-suggestions="locationQuerySearch"
  391. popper-class="my-autocomplete"
  392. :placeholder="$t('common.table.locationTips')"
  393. value-key="field"
  394. clearable
  395. class="w-full"
  396. placement="bottom-end"
  397. @select="funcScrollToCol"
  398. >
  399. <template #default="{ item }">
  400. <div class="flx-justify-between">
  401. <div class="text-body-b">{{ item.title }}</div>
  402. <span class="pl-8 text-secondary-text">{{ item.field }}</span>
  403. </div>
  404. </template>
  405. </el-autocomplete>
  406. </el-popover>
  407. <!-- </div> -->
  408. </template>
  409. <script setup lang="ts" name="LjVxeTable">
  410. import { ref, reactive, watch, computed, provide, onMounted, nextTick, toRef, unref, inject } from "vue";
  411. // import { ElTable } from "element-plus";
  412. import { useTable } from "@/hooks/useTable";
  413. import { useSelection } from "@/hooks/useSelection";
  414. import { useDwLayout } from "@/hooks/useDwLayout";
  415. import { BreakPoint } from "@/components/Grid/interface";
  416. import { ColumnProps, getDefaultFilter, dwnameSaveLayoutAttr, LjVxetableProps } from "./interface";
  417. import {
  418. Refresh,
  419. Printer,
  420. Operation,
  421. Search,
  422. DCaret,
  423. Download,
  424. SortDown,
  425. SortUp,
  426. Brush,
  427. More,
  428. Setting,
  429. Location,
  430. Guide,
  431. Upload
  432. } from "@element-plus/icons-vue";
  433. import { filterEnum, formatValue, handleProp, handleRowAccordingToProp, streamlineFunc, floatAdd } from "@/utils";
  434. import SearchForm from "./components/SearchForm.vue";
  435. import Pagination from "./components/Pagination.vue";
  436. import ColSetting from "./components/ColSetting.vue";
  437. import TableColumn from "./components/TableColumn.vue";
  438. import PrintEditor from "@/components/PrintEditor/index.vue";
  439. // import LjDialog from "@/components/LjDialog/index.vue";
  440. import PrintTemplateSelector from "@/components/Selector/PrintTemplate/index.vue";
  441. import { VxeTablePropTypes, VxeTableProps, VxeTableInstance, Colgroup } from "vxe-table";
  442. import { cloneDeep, pick, defaultsDeep, throttle, omit } from "lodash-es";
  443. import { useLayoutStore } from "@/stores/modules/layout";
  444. import { useI18n } from "vue-i18n";
  445. import { useUserStore } from "@/stores/modules/user";
  446. import { useGlobalStore } from "@/stores/modules/global";
  447. import { ElMessage, ElNotification } from "element-plus";
  448. import LoadingCom from "../Loading/index.vue";
  449. import { TABLE_LAYOUT_ATTR, TABLE_LAYOUT_ATTR_DEFINE, PRINT_KEY_ATTR, TABLE_TYPE_FILTER, ALLOW_EDIT_STATE } from "@/config/index";
  450. import { useHiprinterStore } from "@/stores/modules/hiprinter";
  451. import { usePrint } from "@/hooks/usePrint";
  452. import variables from "@/styles/js.module.scss";
  453. import { useAuthButtons } from "@/hooks/useAuthButtons";
  454. import { pinyinFilter } from "@/utils/pinyin";
  455. import { TourEnum } from "@/enums/tourEnum";
  456. import { useTour } from "@/hooks/useTour";
  457. // import { onKeyStroke } from "@vueuse/core";
  458. import dayjs from "dayjs";
  459. import { onClickOutside } from "@vueuse/core";
  460. import { CommonDynamicSelect } from "@/api/modules/common";
  461. import { isBoolean, isFunction, isNumber } from "@/utils/is";
  462. const { t } = useI18n();
  463. const globalStore = useGlobalStore();
  464. const userStore = useUserStore();
  465. const _variables: any = variables;
  466. const tableSize = computed(() => {
  467. let _size: VxeTablePropTypes.Size = "";
  468. switch (globalStore.assemblySize) {
  469. case "large":
  470. _size = "";
  471. break;
  472. case "small":
  473. _size = "mini";
  474. break;
  475. default:
  476. _size = "medium";
  477. break;
  478. }
  479. return _size;
  480. });
  481. // /**
  482. // * @description 虚拟滚动参数
  483. // */
  484. // const scrollYDefault = ref({
  485. // enabled: true,
  486. // oSize: 0,
  487. // mode: "default"
  488. // });
  489. const searchFormDefault = {
  490. labelPosition: "left",
  491. labelWidth: ""
  492. };
  493. // 接受父组件参数,配置默认值
  494. const props = withDefaults(defineProps<LjVxetableProps>(), {
  495. columns: () => [],
  496. requestAuto: true,
  497. pagination: false,
  498. pageSizes: () => [20, 50, 100, 500, 1000, 10000],
  499. initParam: {},
  500. border: true,
  501. // toolButton: true,
  502. rowKey: "id",
  503. searchCol: () => ({ xs: 3, sm: 4, md: 5, lg: 6, xl: 8 }),
  504. // settingCol: () => ({ xs: 24, sm: 12, md: 8, lg: 6, xl: 4 }),
  505. layoutAttr: () => TABLE_LAYOUT_ATTR,
  506. layoutAttrDefine: () => TABLE_LAYOUT_ATTR_DEFINE,
  507. // height: "auto",
  508. tableCls: "card h-full",
  509. tableProps: {},
  510. extraLoading: false,
  511. tableEvents: {},
  512. toolButton: () => ["refresh", "setting", "search", "location"],
  513. toolButtonPower: () => [],
  514. autoLoadLayout: true,
  515. collapseButtons: true,
  516. miniSearchbar: true,
  517. footerSumAttrs: () => [],
  518. searchBtnSizeExtent: () => ["xs", "sm", "md"],
  519. multiSelect: undefined,
  520. editable: false,
  521. autoSelectFirstAfterRefresh: false,
  522. ifLoadQueryHabit: true,
  523. ifSearch: true
  524. });
  525. /**
  526. * @description 是否可编辑
  527. */
  528. const orderStatus = inject("orderStatus", ref(""));
  529. // 默认表格props
  530. const _defineProps = ref({
  531. border: true,
  532. showOverflow: "tooltip",
  533. showHeaderOverflow: false,
  534. height: "auto",
  535. minHeight: "100px",
  536. rowConfig: {
  537. isCurrent: true,
  538. isHover: true,
  539. useKey: true,
  540. currentMethod: ({ row }: any) => {
  541. if (Object.keys(props).includes("lockRow")) {
  542. if (isBoolean(props?.lockRow)) {
  543. return !props.lockRow;
  544. } else if (isFunction(props?.lockRow)) {
  545. return !props?.lockRow(row);
  546. }
  547. }
  548. return true;
  549. }
  550. },
  551. columnConfig: { isCurrent: true, isHover: true, resizable: true },
  552. exportConfig: {},
  553. sortConfig: { trigger: "cell", multiple: true, chronological: true, defaultSort: {}, showIcon: false },
  554. checkboxConfig: { checkField: "checked", range: true },
  555. scrollY: {
  556. gt: 200,
  557. enabled: true,
  558. oSize: 0,
  559. mode: "default",
  560. scrollToTopOnChange: true
  561. },
  562. mouseConfig: { selected: true },
  563. keyboardConfig: { isArrow: true, isDel: true, isEnter: true, isTab: true, isEdit: true, isChecked: true },
  564. menuConfig: {
  565. header: {
  566. options: [
  567. [
  568. {
  569. code: "clear",
  570. name: t("common.table.filterClear"),
  571. visible: true,
  572. disabled: false
  573. }
  574. ],
  575. [
  576. {
  577. code: "clearAll",
  578. name: t("common.table.filterClearAll"),
  579. visible: true,
  580. disabled: false
  581. },
  582. {
  583. code: "export",
  584. name: t("common.export"),
  585. prefixIcon: "vxe-icon-download",
  586. visible: true,
  587. disabled: false
  588. }
  589. ],
  590. [
  591. {
  592. code: "hideColumn",
  593. name: t("common.table.hideColumn")
  594. }
  595. ]
  596. ]
  597. },
  598. body: {
  599. options: [
  600. [
  601. {
  602. code: "filter",
  603. name: t("common.table.filter"),
  604. visible: true,
  605. disabled: false,
  606. prefixIcon: "iconfont iconfilter-funnel-01",
  607. suffixIcon: "iconfont iconedit-02",
  608. children: [
  609. {
  610. code: "clear",
  611. name: t("common.table.filterClear"),
  612. visible: true,
  613. disabled: false,
  614. prefixIcon: "iconfont iconbrush-03-1"
  615. }
  616. ]
  617. },
  618. {
  619. code: "copy",
  620. name: t("common.table.copy"),
  621. visible: true,
  622. disabled: false,
  623. prefixIcon: "iconfont iconcopy-07"
  624. },
  625. // {
  626. // code: "find",
  627. // name: t("common.table.find"),
  628. // visible: true,
  629. // disabled: false,
  630. // prefixIcon: "iconfont iconcopy-07"
  631. // },
  632. {
  633. code: "sort",
  634. name: "排序",
  635. prefixIcon: "iconfont iconswitch-vertical-02",
  636. children: [
  637. {
  638. code: "sortAsc",
  639. name: t("sys.setting.asc"),
  640. visible: true,
  641. disabled: false,
  642. prefixIcon: "iconfont iconarrow-narrow-up"
  643. },
  644. {
  645. code: "sortDesc",
  646. name: t("sys.setting.desc"),
  647. visible: true,
  648. disabled: false,
  649. prefixIcon: "iconfont iconarrow-narrow-down"
  650. },
  651. {
  652. code: "sortClear",
  653. name: t("common.clear"),
  654. visible: true,
  655. disabled: false,
  656. prefixIcon: "iconfont iconbrush-03-1"
  657. }
  658. ]
  659. }
  660. ],
  661. [
  662. {
  663. code: "clearAll",
  664. name: t("common.table.filterClearAll"),
  665. visible: true,
  666. disabled: false,
  667. prefixIcon: "iconfont icontrash-01"
  668. },
  669. {
  670. code: "export",
  671. name: t("common.export"),
  672. prefixIcon: "iconfont icondownload-01",
  673. visible: true,
  674. disabled: false
  675. }
  676. ]
  677. ]
  678. },
  679. visibleMethod({ options, column, row }: any) {
  680. options.forEach((list: any) => {
  681. list.forEach((item: any) => {
  682. if (item.children && item.children.length > 0) {
  683. item.children.forEach((itm: any) => {
  684. if (!row) {
  685. item.visible = false;
  686. } else {
  687. item.visible = true;
  688. }
  689. });
  690. }
  691. if (item.code === "filter") {
  692. // 复制
  693. if (row) {
  694. let _val = row[column.field] ? " - " + row[column.field] : row[column.field];
  695. item.name = t("common.table.filter") + _val;
  696. item.visible = true;
  697. } else {
  698. item.name = t("common.table.filter");
  699. item.visible = false;
  700. }
  701. // } else if (item.code === "copy") {
  702. // // 复制
  703. // if (row && row[column.field]) {
  704. // item.name = t("common.table.copy") + " - " + row[column.field];
  705. // item.visible = true;
  706. // } else {
  707. // item.name = t("common.table.copy");
  708. // item.visible = false;
  709. // }
  710. } else if (["copy", "clear"].includes(item.code)) {
  711. if (!row) {
  712. item.visible = false;
  713. } else {
  714. item.visible = true;
  715. }
  716. }
  717. });
  718. });
  719. return true;
  720. }
  721. },
  722. headerCellClassName: ({ column }: any) => {
  723. if (ALLOW_EDIT_STATE.includes(orderStatus.value) || props.editable) {
  724. if (column?.editRender && column.editRender.enabled !== false) {
  725. return "vxecol-edit";
  726. }
  727. }
  728. return null;
  729. },
  730. cellClassName: data => {
  731. let { column } = data;
  732. if (ALLOW_EDIT_STATE.includes(orderStatus.value) || props.editable) {
  733. if (column?.editRender && column.editRender.enabled !== false) {
  734. return "vxecol-edit";
  735. }
  736. }
  737. return props.cellClassName ? props.cellClassName(data, ALLOW_EDIT_STATE.includes(orderStatus.value) || props.editable) : null;
  738. }
  739. });
  740. // const propsDefine = Object.assign(_defineProps.value, props.tableProps);
  741. interface RowVO {
  742. [key: string]: any;
  743. }
  744. // 获取缓存中当前页面的每页数量
  745. let curPageSizes = undefined;
  746. if (props.dwname && globalStore.pageSizes && globalStore.pageSizes.hasOwnProperty(props.dwname)) {
  747. curPageSizes = globalStore.pageSizes[props.dwname];
  748. }
  749. const { CheckPower } = useAuthButtons(t);
  750. /**
  751. * @description 过滤表格按钮权限
  752. * @param type 按钮类型
  753. */
  754. const getToolButton = (type: string) => {
  755. let _idx = props.toolButton.indexOf(type);
  756. if (_idx > -1) {
  757. if (props.toolButtonPower.length && _idx < props.toolButtonPower.length && props.toolButtonPower[_idx] != 0) {
  758. return CheckPower(props.toolButtonPower[_idx]);
  759. } else {
  760. return true;
  761. }
  762. }
  763. return false;
  764. };
  765. const emit = defineEmits([
  766. "afterMounted",
  767. "firstMounted",
  768. "layoutChange",
  769. "keydownStart",
  770. "keydown",
  771. "keydownEnd",
  772. "currentChange",
  773. "radioChange",
  774. "checkboxChange",
  775. "checkboxAll",
  776. "checkboxRangeStart",
  777. "checkboxRangeChange",
  778. "checkboxRangeEnd",
  779. "cellClick",
  780. "cellDblclick",
  781. "cellMenu",
  782. "cellMouseenter",
  783. "cellMouseleave",
  784. "cellDeleteValue",
  785. "headerCellClick",
  786. "headerCellDblclick",
  787. "headerCellMenu",
  788. "footerCellClick",
  789. "footerCellDblclick",
  790. "footerCellMenu",
  791. "clearMerge",
  792. "sortChange",
  793. "clearSort",
  794. "filterChange",
  795. "filterVisible",
  796. "clearFilter",
  797. "resizableChange",
  798. "toggleRowExpand",
  799. "toggleTreeExpand",
  800. "menuClick",
  801. "cellSelected",
  802. "editClosed",
  803. "editActivated",
  804. "editDisabled",
  805. "validError",
  806. "scroll",
  807. "scrollBoundary",
  808. "custom",
  809. "rowDragstart",
  810. "rowDragend"
  811. ]);
  812. // 表格绑定的事件
  813. const propsEvents = computed(() => {
  814. let defineEv = {
  815. keydownStart: (data: any) => emit("keydownStart", data),
  816. keydown: (data: any) => emit("keydown", data),
  817. keydownEnd: (data: any) => emit("keydownEnd", data),
  818. currentChange: (data: any) => {
  819. console.log("currentChange !!!!!!!!!!!!:>> ", data);
  820. emit("currentChange", data);
  821. },
  822. radioChange: (data: any) => emit("radioChange", data),
  823. checkboxChange: (data: any) => emit("checkboxChange", data),
  824. checkboxAll: (data: any) => emit("checkboxAll", data),
  825. checkboxRangeStart: (data: any) => emit("checkboxRangeStart", data),
  826. checkboxRangeChange: (data: any) => emit("checkboxRangeChange", data),
  827. checkboxRangeEnd: (data: any) => emit("checkboxRangeEnd", data),
  828. cellClick: (data: any) => {
  829. const { row, rowIndex, column, columnIndex } = data;
  830. // currentEditCell.value.row = row;
  831. currentEditCell.value.rowIndex = rowIndex;
  832. // currentEditCell.value.column = column;
  833. currentEditCell.value.field = column.field;
  834. console.log("editConfig cellClick :>> ", row, currentEditCell.value);
  835. emit("cellClick", data);
  836. },
  837. cellDblclick: (data: any) => emit("cellDblclick", data),
  838. cellMenu: (data: any) => emit("cellMenu", data),
  839. cellMouseenter: (data: any) => emit("cellMouseenter", data),
  840. cellMouseleave: (data: any) => emit("cellMouseleave", data),
  841. cellDeleteValue: (data: any) => emit("cellDeleteValue", data),
  842. headerCellClick: (data: any) => emit("headerCellClick", data),
  843. headerCellDblclick: (data: any) => emit("headerCellDblclick", data),
  844. headerCellMenu: (data: any) => emit("headerCellMenu", data),
  845. footerCellClick: (data: any) => emit("footerCellClick", data),
  846. footerCellDblclick: (data: any) => emit("footerCellDblclick", data),
  847. footerCellMenu: (data: any) => emit("footerCellMenu", data),
  848. clearMerge: (data: any) => emit("clearMerge", data),
  849. sortChange: (data: any) => {
  850. handleSortChange(data);
  851. emit("sortChange", data);
  852. },
  853. clearSort: (data: any) => emit("clearSort", data),
  854. filterChange: (data: any) => emit("filterChange", data),
  855. filterVisible: (data: any) => emit("filterVisible", data),
  856. clearFilter: (data: any) => emit("clearFilter", data),
  857. resizableChange: (data: any) => {
  858. handleResizChange(data);
  859. emit("resizableChange", data);
  860. },
  861. toggleRowExpand: (data: any) => emit("toggleRowExpand", data),
  862. toggleTreeExpand: (data: any) => emit("toggleTreeExpand", data),
  863. cellSelected: (data: any) => {
  864. handleCellSelected(data);
  865. emit("cellSelected", data);
  866. },
  867. editClosed: (data: any) => emit("editClosed", data),
  868. editActivated: (data: any) => emit("editActivated", data),
  869. editDisabled: (data: any) => emit("editDisabled", data),
  870. validError: (data: any) => emit("validError", data),
  871. scroll: (data: any) => emit("scroll", data),
  872. scrollBoundary: (data: any) => emit("scrollBoundary", data),
  873. custom: (data: any) => emit("custom", data),
  874. rowDragstart: (data: any) => emit("rowDragstart", data),
  875. rowDragend: (data: any) => emit("rowDragend", data),
  876. menuClick({ menu, type, row, rowIndex, column, columnIndex, $event }: any) {
  877. console.log("menu :>> ", menu);
  878. console.log("menu row :>> ", row);
  879. console.log("menu column :>> ", column);
  880. const $table = tableRef.value;
  881. if ($table) {
  882. switch (menu.code) {
  883. case "filter":
  884. if (column.filterRender) {
  885. // 自定义筛选
  886. // 修改第一个选项为勾选状态
  887. const option = column.filters[0];
  888. option.data.vals = [row[column.field].toString()];
  889. option.checked = true;
  890. // 如果是直接修复筛选条件,则需要手动调用 updateData 处理表格数据
  891. console.log("option", option);
  892. } else {
  893. // 定制筛选
  894. column.filters.forEach((item: any) => {
  895. if (item.value == row[column.field]) {
  896. item.checked = true;
  897. } else {
  898. item.checked = false;
  899. }
  900. });
  901. }
  902. if ($event.target.className.indexOf("iconedit-02") > -1) {
  903. if (column.filterRender) {
  904. column.filters[0].data.sVal = row[column.field].toString();
  905. }
  906. // 点击修改图标,弹出筛选下拉
  907. $table.openFilter(column.field);
  908. } else {
  909. $table.updateData();
  910. }
  911. break;
  912. case "copy":
  913. if (row && column) {
  914. const input = document.createElement("textarea");
  915. input.value = row[column.field];
  916. document.body.appendChild(input);
  917. input.select();
  918. document.execCommand("Copy");
  919. document.body.removeChild(input);
  920. ElMessage({
  921. type: "success",
  922. message: t("common.copySuccess")
  923. });
  924. }
  925. break;
  926. // case "find":
  927. // locationTabActive.value = "data";
  928. // if (locationFrom.field != column.field) {
  929. // matchData.value = [];
  930. // matchIndex.value = 0;
  931. // locationFrom.value = "";
  932. // }
  933. // locationFrom.field = column.field;
  934. // locationDialogRef.value.show();
  935. // break;
  936. case "clear":
  937. $table.clearFilter(column);
  938. break;
  939. case "clearAll":
  940. $table.clearFilter();
  941. break;
  942. case "export":
  943. $table.openExport();
  944. break;
  945. case "hideColumn":
  946. // 隐藏列
  947. colSetting.forEach(item => {
  948. if (column.field === item.field) {
  949. item.visible = false;
  950. return;
  951. }
  952. });
  953. console.log("colSetting :>> ", colSetting);
  954. settingConfirm(colSetting);
  955. break;
  956. case "sortAsc":
  957. column && $table.sort({ field: column.field, order: "asc" });
  958. console.log("sortAsc $table.getSortColumns() :>> ", $table.getSortColumns());
  959. handleSortChange({ sortList: $table.getSortColumns() });
  960. break;
  961. case "sortDesc":
  962. column && $table.sort({ field: column.field, order: "desc" });
  963. console.log("sortDesc $table.getSortColumns() :>> ", $table.getSortColumns());
  964. handleSortChange({ sortList: $table.getSortColumns() });
  965. break;
  966. case "sortClear":
  967. column && clearSortEvent(column.field);
  968. break;
  969. }
  970. emit("menuClick", { menu, type, row, rowIndex, column, columnIndex, $event });
  971. }
  972. }
  973. };
  974. return Object.assign(defineEv, props.tableEvents);
  975. });
  976. // 通用查询接口返回的布局数据,保存
  977. const loadDwLayout = (data: any) => {
  978. console.log("layout data:>> ", data);
  979. // 表格结构: {tableprop: string, columns: string}
  980. // typeof layout.itemvalue == "string" && (layout.itemvalue = JSON.parse(layout.itemvalue.replace(/'/g, '"')));
  981. // 兼容部分结构直接记录行数据
  982. if (data.hasOwnProperty("columns") && data.columns) {
  983. dwLayout.value = data.columns;
  984. } else {
  985. dwLayout.value = data;
  986. }
  987. loadLayoutCallBack(data);
  988. props.dwname && layoutStore.setDwLayout(props.dwname, data, t, false);
  989. console.log("onMounted dwLayout.value :>> ", dwLayout.value);
  990. loadDwLayoutFunc(dwLayout.value);
  991. // tableColumns.value = cloneDeep(props.columns);
  992. console.log("数行化BF,还原个性设置 tableColumns.value :>> ", tableColumns.value);
  993. // 扁平化,并读取个性设置
  994. flatColumns.value = flatColumnsFunc(cloneDeep(props.columns), dwFieldMap);
  995. console.log("读取个性设置 flatColumns.value loadDwLayout:>> ", flatColumns.value);
  996. initLayoutColumns();
  997. };
  998. /**
  999. * @description 指引步骤
  1000. */
  1001. const TourSteps = [
  1002. {
  1003. element: "#searchForm",
  1004. popover: {
  1005. title: t("business.guide.table.step1.title"),
  1006. description: t("business.guide.table.step1.description"),
  1007. side: "bottom"
  1008. }
  1009. },
  1010. {
  1011. element: "#searchForm_searchProject",
  1012. popover: {
  1013. title: t("business.guide.table.step2.title"),
  1014. description: t("business.guide.table.step2.description"),
  1015. side: "bottom"
  1016. }
  1017. },
  1018. {
  1019. element: "#toolButton",
  1020. popover: {
  1021. title: t("business.guide.table.step3.title"),
  1022. description: t("business.guide.table.step3.description"),
  1023. side: "bottom"
  1024. }
  1025. },
  1026. {
  1027. element: "#toolButtonSetting",
  1028. popover: {
  1029. title: t("business.guide.table.step4.title"),
  1030. description: t("business.guide.table.step4.description"),
  1031. side: "bottom"
  1032. }
  1033. },
  1034. {
  1035. element: "#vxeTableBody",
  1036. popover: {
  1037. title: t("business.guide.table.step5.title"),
  1038. description: t("business.guide.table.step5.description")
  1039. }
  1040. },
  1041. {
  1042. element: "#ljVxePagination",
  1043. popover: {
  1044. title: t("business.guide.table.step6.title"),
  1045. description: t("business.guide.table.step6.description"),
  1046. side: "top"
  1047. }
  1048. }
  1049. ];
  1050. // 新手指导
  1051. const { checkIfNeedGuide } = useTour(t, TourEnum.table, TourSteps);
  1052. const defaultRequest = (params: any) => {
  1053. if (!props.requestAuto) return undefined;
  1054. let newParams: any = {};
  1055. params.pageNum && (newParams.pageindex = params.pageNum);
  1056. params.pageSize && (newParams.pagesize = params.pageSize);
  1057. delete params.pageNum;
  1058. delete params.pageSize;
  1059. newParams.queryParams = JSON.parse(JSON.stringify(params));
  1060. console.log("newParams", newParams);
  1061. let pkeys = Object.keys(newParams.queryParams);
  1062. console.log("pkeys :>> ", pkeys);
  1063. let flatSearchColumns = new Map<string, any>();
  1064. for (let searchCol of searchColumns.value) {
  1065. flatSearchColumns.set(searchCol.field || "", searchCol);
  1066. }
  1067. for (let pk of pkeys) {
  1068. console.log("pk :>> ", pk);
  1069. console.log("haspk", flatSearchColumns.has(pk));
  1070. if (flatSearchColumns.has(pk)) {
  1071. let searchInfo = flatSearchColumns.get(pk);
  1072. console.log("searchInfo :>> ", searchInfo);
  1073. if (searchInfo.search && searchInfo.search.props && searchInfo.search.props.type == "date") {
  1074. const today = dayjs(dayjs().format("YYYY-MM-DD"));
  1075. if (isNumber(newParams.queryParams[pk])) {
  1076. newParams.queryParams[pk] = today.add(newParams.queryParams[pk], "day").format("YYYY-MM-DD HH:mm:ss");
  1077. }
  1078. }
  1079. }
  1080. }
  1081. newParams.dsname = props.dwname;
  1082. return CommonDynamicSelect(newParams, newParams.dsname);
  1083. };
  1084. const defaultDataCallback = (data: any) => {
  1085. return {
  1086. list: data.datatable,
  1087. tableinfo: data.tableinfo,
  1088. total: data.totalcnt,
  1089. pageNum: data.pageindex,
  1090. pageSize: data.pagesize
  1091. };
  1092. };
  1093. // 表格操作 Hooks
  1094. const {
  1095. tableData,
  1096. pageable,
  1097. searchParam,
  1098. totalParam,
  1099. searchInitParam,
  1100. tableLoading,
  1101. getTableList,
  1102. search,
  1103. reset,
  1104. // handleSizeChange,
  1105. // handleCurrentChange,
  1106. handlePageChange
  1107. } = useTable(
  1108. props.requestApi || defaultRequest,
  1109. props.initParam,
  1110. props.pagination,
  1111. props.dataCallback || defaultDataCallback,
  1112. props.requestError,
  1113. props.dwname,
  1114. curPageSizes,
  1115. !props.autoLoadLayout,
  1116. loadDwLayout,
  1117. props?.pageChangeCallBack
  1118. );
  1119. /**
  1120. * @description 默认表尾合计
  1121. */
  1122. const defineFooterMethod = ({ columns, data }: any) => {
  1123. // 返回一个二维数组的表尾合计
  1124. return [
  1125. columns.map((column: any, columnIndex: number) => {
  1126. if (columnIndex === 0) {
  1127. return "合计";
  1128. }
  1129. if (columnIndex === 1) {
  1130. return data.length;
  1131. }
  1132. if ((column.field && column.field.indexOf("qty") > -1) || props.footerSumAttrs?.includes(column.field)) {
  1133. let count = 0;
  1134. data.forEach((item: any) => {
  1135. item && (count = floatAdd(count, isNaN(Number(item[column.field])) ? 0 : Number(item[column.field])));
  1136. });
  1137. return count;
  1138. }
  1139. })
  1140. ];
  1141. };
  1142. const propsDefine = defaultsDeep(props.tableProps, _defineProps.value);
  1143. // 表格参数:init
  1144. const tableOptions = reactive<any>({
  1145. showFooter: typeof props.footerMethod != "boolean",
  1146. footerMethod: typeof props.footerMethod != "boolean" ? props.footerMethod ?? defineFooterMethod : undefined,
  1147. ...propsDefine
  1148. });
  1149. watch(
  1150. () => props.editable,
  1151. (newVal, oldVal) => {
  1152. tableOptions.editConfig.enabled = newVal;
  1153. }
  1154. );
  1155. console.log("init propsDefine :>> ", propsDefine);
  1156. if (props?.multiSelect != undefined) {
  1157. tableOptions.checkboxConfig = {
  1158. range: true,
  1159. trigger: "cell",
  1160. highlight: true
  1161. };
  1162. tableOptions.checkboxConfig.checkField = props.multiSelect ?? "";
  1163. if (!props.columns.some(c => c.type == "checkbox")) {
  1164. props.columns.unshift({
  1165. type: "checkbox",
  1166. width: 50
  1167. });
  1168. }
  1169. }
  1170. if (props?.editable) {
  1171. if (tableOptions.editConfig == undefined) {
  1172. tableOptions.editConfig = { trigger: "click", mode: "cell" };
  1173. }
  1174. tableOptions.editConfig.enabled = props?.editable ?? false;
  1175. }
  1176. /**表格存储参数 */
  1177. const tableprop_save = ref<dwnameSaveLayoutAttr>({
  1178. scrollY: {},
  1179. search: {},
  1180. basicinfo: {},
  1181. searchProject: []
  1182. });
  1183. // 是否显示搜索模块
  1184. const isShowSearch = ref(true);
  1185. // 是否更新数据
  1186. const isUpdate = ref(0);
  1187. // 表格 DOM 元素
  1188. const tableRef = ref<VxeTableInstance>();
  1189. // 表格多选 Hooks
  1190. // const { selectionChange, selectedList, selectedListIds, isSelected } = useSelection(props.rowKey);
  1191. /**
  1192. * @description 当前已选列表
  1193. */
  1194. const selectRecords = ref<any>();
  1195. const loadLayoutCallBack = (data: any) => {
  1196. if (data?.hasOwnProperty("tableprop") && data.tableprop) {
  1197. tableprop_save.value = data.tableprop;
  1198. console.log("warch project newVal bbbbbf tableprop_save.value:>> ", tableprop_save.value);
  1199. let _scrollY = tableprop_save.value.hasOwnProperty("scrollY") ? cloneDeep(tableprop_save.value.scrollY) : {};
  1200. console.log("_scrollY :>> ", _scrollY);
  1201. tableOptions.scrollY = defaultsDeep(_scrollY, propsDefine.scrollY);
  1202. }
  1203. console.log("warch project newVal loadLayoutCallBack tableprop_save.value:>> ", tableprop_save.value);
  1204. };
  1205. const flatColumnsCallBack = (col: any) => {
  1206. // 设置 enumMap
  1207. setEnumMap(col);
  1208. // 设置 表格基础信息-format枚举
  1209. setBaseEnumMap(col);
  1210. col.filterRender = col.filterRender
  1211. ? col.filterRender
  1212. : col.filters
  1213. ? undefined
  1214. : {
  1215. name: "FilterExtend",
  1216. props: {
  1217. sortfunc: (data: any) => {
  1218. console.log("flatColumnsCallBack sortfunc :>> ", data);
  1219. handleSortChange(data);
  1220. },
  1221. enum: enumMap.value.get(col.field!) ?? [],
  1222. col: pick(col, ["field", "datatype"])
  1223. }
  1224. };
  1225. col.filters = col.filters ?? getDefaultFilter(col);
  1226. return col;
  1227. };
  1228. // 表格布局读取与存储
  1229. const {
  1230. tableColumns,
  1231. dwLayout,
  1232. dwFieldMap,
  1233. flatColumns,
  1234. loadLayoutFunc,
  1235. loadDwLayoutFunc,
  1236. flatColumnsFunc,
  1237. getDefineAttr,
  1238. loadRenderAttr,
  1239. columnStreamlineFunc,
  1240. getOriColumns
  1241. } = useDwLayout(
  1242. "table",
  1243. t,
  1244. cloneDeep(props.columns),
  1245. props.layoutAttr,
  1246. props.layoutAttrDefine,
  1247. props.autoLoadLayout,
  1248. props.dwname,
  1249. loadLayoutCallBack,
  1250. flatColumnsCallBack,
  1251. props?.editable
  1252. );
  1253. /**
  1254. * @description 打印前检测状态
  1255. */
  1256. const funcBeforePrintCheck = () => {
  1257. let _status = true;
  1258. const $table = tableRef.value;
  1259. if ($table) {
  1260. const _records = $table.getCheckboxRecords() ?? [];
  1261. const curRecords = $table.getCurrentRecord() ?? null;
  1262. selectRecords.value = [];
  1263. if (_records.length) {
  1264. // 获取勾选列表
  1265. selectRecords.value = _records;
  1266. } else if (curRecords) {
  1267. // 获取当前选中数据
  1268. selectRecords.value = [curRecords];
  1269. } else {
  1270. // 默认获取第一条记录
  1271. let fullData = $table.getTableData().fullData;
  1272. if (fullData.length) {
  1273. selectRecords.value = [fullData[0]];
  1274. $table.setCurrentRow(fullData[0]);
  1275. }
  1276. }
  1277. console.log("funcBeforePrintCheck selectRecords.value :>> ", selectRecords.value);
  1278. props.beforePrintCallback && (_status = props.beforePrintCallback(selectRecords.value));
  1279. console.log("beforePrintCallback _status :>> ", _status);
  1280. } else {
  1281. ElMessage("$table: 表格对象获取失败");
  1282. _status = false;
  1283. }
  1284. return _status;
  1285. };
  1286. const getSelectRecords = () => {
  1287. return selectRecords.value;
  1288. };
  1289. const {
  1290. printEditorRef,
  1291. printTemplateRef,
  1292. printerListTpDropdownRef,
  1293. activePrint,
  1294. hiprinterStateList,
  1295. hiprinterStateMx,
  1296. printerTpList,
  1297. toGetPrinterState,
  1298. openPrint,
  1299. openPrintPriveiew,
  1300. toPreviewPrintTemplate,
  1301. toPrintPrintTemplate,
  1302. toEditPrintTemplate,
  1303. checkPrintTemplateList
  1304. } = usePrint(t, props.dwname, getSelectRecords, funcBeforePrintCheck, props.printDataCallback);
  1305. // 清空选中数据列表
  1306. // const clearSelection = () => tableRef.value!.clearSelection();
  1307. // 定义 enumMap 存储 enum 值(避免异步请求无法格式化单元格内容 || 无法填充搜索下拉选择)
  1308. const enumMap = ref(new Map<string, { [key: string]: any }[]>());
  1309. const baseEnumMap = ref(new Map<string, { [key: string]: any }[]>());
  1310. provide("enumMap", enumMap);
  1311. const setEnumMap = async (col: ColumnProps) => {
  1312. if (!col.enum) return;
  1313. // 如果当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
  1314. console.log("col.enum :>> ", col.field, col.enum);
  1315. if (typeof col.enum !== "function") {
  1316. let _enum = col.enum!;
  1317. if (col.enumFilter) {
  1318. _enum = col.enumFilter(searchParam.value, _enum, "");
  1319. }
  1320. return enumMap.value.set(col.field!, _enum);
  1321. }
  1322. const { data } = await col.enum();
  1323. enumMap.value.set(col.field!, data);
  1324. };
  1325. const setBaseEnumMap = async (col: ColumnProps) => {
  1326. if (!col.formatEnum) return;
  1327. // 如果当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
  1328. if (typeof col.formatEnum !== "function") return baseEnumMap.value.set(col.field!, col.formatEnum!);
  1329. const { data } = await col.formatEnum();
  1330. baseEnumMap.value.set(col.field!, data);
  1331. };
  1332. // // 扁平化 初始化 columns
  1333. // const flatColumnsFunc = (columns: ColumnProps[], dwMap: Map<KeyType, any> = new Map(), flatArr: ColumnProps[] = []) => {
  1334. // columns.forEach(async (col: any) => {
  1335. // if (col._children?.length) flatArr.push(...flatColumnsFunc(col._children, dwMap));
  1336. // flatArr.push(col);
  1337. // // 给每一项 column 添加默认属性
  1338. // col.visible = col?.visible == false ? false : props.layoutAttrDefine.visible; // true
  1339. // col.width = col.width ?? props.layoutAttrDefine.width; // 200
  1340. // col.align = col.align ?? props.layoutAttrDefine.align; // "center"
  1341. // col.sortable = col.sortable ?? props.layoutAttrDefine.sortable; // false
  1342. // col.order = col.order ?? props.layoutAttrDefine.order; // ""
  1343. // col.fixed = col.fixed ?? props.layoutAttrDefine.fixed; // ""
  1344. // // col.isFilterEnum = col.isFilterEnum ?? true;
  1345. // col.filterRender = col.filterRender ? col.filterRender : col.filters ? undefined : { name: "FilterExtend" };
  1346. // col.filters = col.filters ?? defaultFilter.value;
  1347. // // 读取个性设置属性
  1348. // if (dwMap.size) {
  1349. // let userStyle = dwMap.get(col.field);
  1350. // if (userStyle) {
  1351. // for (let prop of props.layoutAttr) {
  1352. // if (userStyle.hasOwnProperty(prop) && prop != "title") {
  1353. // col[prop] = userStyle[prop];
  1354. // }
  1355. // }
  1356. // col.colorder = userStyle.colorder;
  1357. // if (userStyle.search && col.search) {
  1358. // col.search.order = userStyle.search.order ?? undefined;
  1359. // col.search.span = userStyle.search.span ?? undefined;
  1360. // col.search.labelPosition = userStyle.search.labelPosition ?? undefined;
  1361. // col.search.labelWidth = userStyle.search.labelWidth ?? undefined;
  1362. // }
  1363. // }
  1364. // }
  1365. // if (TABLE_TYPE_FILTER.includes(col.type!)) {
  1366. // } else if (col.field == "operation") {
  1367. // col.title = t(`table.${col.field}`);
  1368. // } else {
  1369. // col.title = t(`table.${col.table}.${col.field}`);
  1370. // }
  1371. // // 搜索栏,读取个性设置属性
  1372. // if (col.search) {
  1373. // col.search.labelPosition = col.search.labelPosition ?? props.searchLayoutAttrDefine.labelPosition; // "top"
  1374. // col.search.labelWidth = col.search.labelWidth ?? props.searchLayoutAttrDefine.labelWidth; // 120
  1375. // col.search.span = col.search.span ?? props.searchLayoutAttrDefine.span; // 1
  1376. // }
  1377. // // 设置 enumMap
  1378. // !enumMap.value.size && setEnumMap(col);
  1379. // // 设置 表格基础信息-format枚举
  1380. // !baseEnumMap.value.size && setBaseEnumMap(col);
  1381. // });
  1382. // // 读取个性设置后,排序,
  1383. // if (dwFieldMap.size) {
  1384. // flatArr.sort((a, b) => {
  1385. // return a.colorder! - b.colorder!;
  1386. // });
  1387. // }
  1388. // return flatArr.filter(item => !item._children?.length);
  1389. // };
  1390. // 读取个性布局,用Map()储存
  1391. // const dwFieldMap = new Map();
  1392. // const loadDwLayoutFunc = (loadLayout: ColumnProps[] = []) => {
  1393. // console.log("loadLayout.value :>> ", loadLayout);
  1394. // if (!loadLayout || !loadLayout.length) return false;
  1395. // // 个性布局加顺序号
  1396. // for (const i in loadLayout) {
  1397. // loadLayout[i].colorder = Number(i);
  1398. // }
  1399. // // 个性布局构建键值Map()
  1400. // dwFieldMap.clear();
  1401. // for (const item of loadLayout) {
  1402. // dwFieldMap.set(item.field, item);
  1403. // }
  1404. // console.log("dwFieldMap :>> ", dwFieldMap);
  1405. // };
  1406. // 布局暂存数据
  1407. const layoutStore = useLayoutStore();
  1408. // const dwLayout = ref([]);
  1409. //
  1410. // /**
  1411. // * @description 树形化:接收 columns 并设置为响应式
  1412. // */
  1413. // let tableColumns = ref<ColumnProps[]>(cloneDeep(props.columns));
  1414. // console.log("init tableColumns.value :>> ", tableColumns.value);
  1415. // /**
  1416. // * @description 扁平化:columns,用于打印、记录
  1417. // */
  1418. // const flatColumns = ref<ColumnProps[]>();
  1419. // console.log("flatColumns.value :>> ", flatColumns.value);
  1420. /**
  1421. * @description 个性化设置columns
  1422. */
  1423. let colSetting = reactive<ColumnProps[]>([]);
  1424. // let prototypeCol = reactive<ColumnProps[]>([]);
  1425. let defaultSort = ref<any[]>([]);
  1426. provide("defaultSort", defaultSort);
  1427. // 过滤需要搜索的配置项
  1428. let searchColumns = ref<ColumnProps[]>([]);
  1429. // const searchColumns = flatColumns.value.filter(item => item.search?.el || item.search?.render);
  1430. // // 设置搜索表单排序默认值 && 设置搜索表单项的默认值
  1431. // searchColumns.forEach((column, index) => {
  1432. // column.search!.order = column.search!.order ?? index + 2;
  1433. // if (column.search?.defaultValue !== undefined && column.search?.defaultValue !== null) {
  1434. // searchInitParam.value[column.search.key ?? handleProp(column.field!)] = column.search?.defaultValue;
  1435. // searchParam.value[column.search.key ?? handleProp(column.field!)] = column.search?.defaultValue;
  1436. // }
  1437. // });
  1438. // // 排序搜索表单项
  1439. // searchColumns.sort((a, b) => a.search!.order! - b.search!.order!);
  1440. // 列设置 ==> 过滤掉不需要设置的列
  1441. // const colRef = ref();
  1442. // const colSetting = tableColumns.value!.filter(
  1443. // item => !["checkbox", "index", "expand"].includes(item.type!) && item.field !== "operation" && !item.visible
  1444. // );
  1445. // const openColSetting = () => colRef.value.openColSetting();
  1446. let settingBtnLoading = ref(false);
  1447. const baseMsgSettingRef = ref();
  1448. const currentColumn = ref();
  1449. /**
  1450. * @description 打开设置窗口
  1451. */
  1452. const openColSetting = () => {
  1453. settingBtnLoading.value = true;
  1454. setTimeout(() => {
  1455. baseMsgSettingRef.value?.openColSetting(tableOptions.scrollY, currentColumn.value);
  1456. settingBtnLoading.value = false;
  1457. }, 1);
  1458. };
  1459. /**
  1460. * @description 监听当前高亮单元格
  1461. */
  1462. const handleCellSelected = ({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }: any) => {
  1463. currentColumn.value = column;
  1464. };
  1465. // let settingColumn: any = reactive(quoteColumns.cloumns);
  1466. // const fnUpdateSettingColumn = (prop: string, val: any) => {
  1467. // console.log("prop :>> ", prop);
  1468. // console.log("colSetting :>> ", colSetting);
  1469. // for (let i = 0; i < colSetting.length; i++) {
  1470. // if (colSetting[i].field == prop) {
  1471. // console.log("settingColumn[i] :>> ", colSetting[i]);
  1472. // // quoteColumns.cloumns[i][prop] = val
  1473. // }
  1474. // }
  1475. // };
  1476. // provide("updateSettingColumn", fnUpdateSettingColumn);
  1477. // const emit = defineEmits(["update:columns"]);
  1478. // const columnStreamlineFunc = (column: any, scrollParam?: any) => {
  1479. // let oriColumns = cloneDeep(props.columns);
  1480. // console.log("column :>> ", column);
  1481. // console.log("oriColumns :>> ", oriColumns);
  1482. // // 默认值字段集合
  1483. // let defineAttr = getKeys(props.layoutAttrDefine);
  1484. // defineAttr.unshift("field");
  1485. // // 取默认值 + 自定义业务columns = 动态默认值属性
  1486. // let oriDedine = oriColumns
  1487. // .filter((item: any) => item.field)
  1488. // .map((item: any) => {
  1489. // let _define = getDefineAttr(item, props.layoutAttrDefine);
  1490. // return pick(defaultsDeep(item, _define), defineAttr);
  1491. // });
  1492. // console.log("streamlineFunc column :>> ", column);
  1493. // console.log("streamlineFunc props.layoutAttr :>> ", props.layoutAttr);
  1494. // console.log("streamlineFunc oriDedine :>> ", oriDedine);
  1495. // let _columns = column.filter((item: any) => item.field);
  1496. // /**
  1497. // * @argument tableprop table属性,api参考vxe-table
  1498. // * @argument columns 个性化数据列集合
  1499. // */
  1500. // let saveCol: any = {
  1501. // columns: streamlineFunc(_columns, props.layoutAttr, oriDedine)
  1502. // };
  1503. // let _scroll = undefined;
  1504. // console.log("settingConfirm saveCol :>> ", saveCol);
  1505. // if (scrollParam) {
  1506. // _scroll = {
  1507. // enabled: scrollParam?.enabled,
  1508. // oSize: scrollParam.oSize,
  1509. // mode: scrollParam.mode
  1510. // };
  1511. // tableOptions.scrollY!.enabled = scrollParam.enabled;
  1512. // tableOptions.scrollY!.oSize = scrollParam.oSize;
  1513. // tableOptions.scrollY!.mode = scrollParam.mode;
  1514. // } else {
  1515. // console.log("tableOptions.scrollY no :>> ", tableOptions.scrollY);
  1516. // tableOptions.scrollY!.enabled = tableOptions.scrollY!.enabled ?? scrollYDefault.value?.enabled;
  1517. // tableOptions.scrollY!.oSize = tableOptions.scrollY!.oSize ?? scrollYDefault.value?.oSize;
  1518. // tableOptions.scrollY!.mode = tableOptions.scrollY!.mode ?? "default";
  1519. // _scroll = {
  1520. // enabled: tableOptions.scrollY!.enabled,
  1521. // oSize: tableOptions.scrollY!.oSize,
  1522. // mode: tableOptions.scrollY!.mode
  1523. // };
  1524. // }
  1525. // console.log("_scroll :>> ", _scroll);
  1526. // saveCol.tableprop = _scroll;
  1527. // console.log("settingConfirm saveCol :>> ", saveCol);
  1528. // return saveCol;
  1529. // };
  1530. // const saveLayoutfunc = async(column: any, scrollParam?: any) => {
  1531. // // 简化储存字段,以props.layoutAttr为标准
  1532. // let saveCol = [];
  1533. // saveCol = columnStreamlineFunc(column, searchColumns.value);
  1534. // let _scroll = undefined;
  1535. // console.log("settingConfirm saveCol :>> ", saveCol);
  1536. // if (scrollParam) {
  1537. // _scroll = {
  1538. // enabled: scrollParam?.enabled,
  1539. // oSize: scrollParam.oSize,
  1540. // mode: scrollParam.mode
  1541. // };
  1542. // tableOptions.scrollY!.enabled = scrollParam.enabled;
  1543. // tableOptions.scrollY!.oSize = scrollParam.oSize;
  1544. // tableOptions.scrollY!.mode = scrollParam.mode;
  1545. // } else {
  1546. // console.log("tableOptions.scrollY no :>> ", tableOptions.scrollY);
  1547. // tableOptions.scrollY!.enabled = tableOptions.scrollY!.enabled ?? scrollYDefault.value?.enabled;
  1548. // tableOptions.scrollY!.oSize = tableOptions.scrollY!.oSize ?? scrollYDefault.value?.oSize;
  1549. // tableOptions.scrollY!.mode = tableOptions.scrollY!.mode ?? "default";
  1550. // _scroll = {
  1551. // enabled: tableOptions.scrollY!.enabled,
  1552. // oSize: tableOptions.scrollY!.oSize,
  1553. // mode: tableOptions.scrollY!.mode
  1554. // };
  1555. // }
  1556. // console.log("_scroll :>> ", _scroll);
  1557. // // 保存布局
  1558. // props.dwname && (await layoutStore.setDwLayout(props.dwname, { tableprop: _scroll, columns: saveCol }, t));
  1559. // }
  1560. /**
  1561. * @description 整理保存属性
  1562. * @param {Array} column 列数组
  1563. * @param {Object} scrollParam 虚拟滚动属性
  1564. * @param {boolean} online 是否获取线上版本
  1565. * @param {number} empid 员工id
  1566. * @returns {Object} saveCol 整理后的保存属性
  1567. */
  1568. const saveColumnsFunc = async (argColumns: any, param: any = {}, online: boolean = false, empid?: number) => {
  1569. console.log("argColumns :>> ", argColumns);
  1570. console.log("scrollParam :>> ", param);
  1571. console.log("tableColumns.value :>> ", tableColumns.value);
  1572. const prefixList = tableColumns.value.filter((item: any) => TABLE_TYPE_FILTER.includes(item?.type));
  1573. const affixList = tableColumns.value.filter((item: any) => item.field == "operation");
  1574. const _tableCol = tableColumns.value.filter(
  1575. (item: any) => !TABLE_TYPE_FILTER.includes(item?.type) && item.field != "operation"
  1576. );
  1577. const oriColumns = await getOriColumns(true, online, empid, enumMap.value);
  1578. // 详情页基础信息构建键值Map()
  1579. let columnBasicinfoMap = new Map();
  1580. for (const i in oriColumns.columns) {
  1581. columnBasicinfoMap.set(oriColumns.columns[i].field, oriColumns.columns[i].basicinfo);
  1582. }
  1583. // 个性布局构建键值Map()
  1584. let columnMap = new Map();
  1585. // 个性布局加顺序号
  1586. for (const i in argColumns) {
  1587. argColumns[i].colorder = Number(i) + 2;
  1588. columnMap.set(argColumns[i].field, argColumns[i]);
  1589. }
  1590. console.log("bf settingConfirm argColumns :>> ", argColumns);
  1591. const _attr = [...props.layoutAttr, "colorder"];
  1592. console.log("bf settingConfirm _attr :>> ", _attr);
  1593. console.log("bf settingConfirm _tableCol :>> ", _tableCol);
  1594. _tableCol.forEach((col: any) => {
  1595. let colMap = columnMap.get(col.field);
  1596. let colBasicMap = columnBasicinfoMap.get(col.field);
  1597. if (colMap) {
  1598. // 只更新关键字段,但不更新field和title字段
  1599. for (const key of _attr) {
  1600. if (col.hasOwnProperty(key) && !["field", "title"].includes(key)) {
  1601. col[key] = colMap[key];
  1602. } else if (key.indexOf("basicinfo") > -1) {
  1603. let _attr = key.split(".")[1];
  1604. colBasicMap && colBasicMap.hasOwnProperty(_attr) && (col.basicinfo[_attr] = colBasicMap[_attr]);
  1605. } else if (key.indexOf("search") > -1) {
  1606. let _attr = key.split(".")[1];
  1607. colMap?.search.hasOwnProperty(_attr) && (col.search[_attr] = colMap.search[_attr]);
  1608. }
  1609. }
  1610. }
  1611. });
  1612. // 排序搜索表单项
  1613. _tableCol.sort((a: any, b: any) => a.colorder! - b.colorder!);
  1614. console.log("aaaaf settingConfirm _tableCol :>> ", _tableCol);
  1615. let arr = prefixList;
  1616. arr = arr.concat(restoreColumnsFunc(_tableCol));
  1617. arr = arr.concat(affixList);
  1618. console.log("arr :>> ", arr);
  1619. // tableColumns.value = arr;
  1620. // $table?.reloadColumn(arr);
  1621. // isUpdate.value++;
  1622. // console.log("settingConfirm tableColumns.value :>> ", tableColumns.value);
  1623. // // 更新个性属性设置数据源
  1624. // colSetting = cloneDeep(column);
  1625. // let _save = cloneDeep(tableprop_save.value);
  1626. // if (param.hasOwnProperty("search")) {
  1627. // _save.search = param.search;
  1628. // }
  1629. // if (param.hasOwnProperty("scrollY")) {
  1630. // _save.scrollY = param.scrollY;
  1631. // }
  1632. // if (param.hasOwnProperty("searchProject")) {
  1633. // _save.searchProject = param.searchProject;
  1634. // }
  1635. let oriOtherParams = omit(oriColumns, ["columns"])?.tableprop ?? {};
  1636. // 空值时,重复赋值
  1637. param.hasOwnProperty("searchProject") && (oriOtherParams.searchProject = param.searchProject);
  1638. let _save = defaultsDeep(param, oriOtherParams);
  1639. console.log("saveColumnsFunc _save :>> ", _save);
  1640. let saveCol = columnStreamlineFunc(arr, _save);
  1641. console.log("saveColumnsFunc saveCol :>> ", JSON.stringify(saveCol));
  1642. return {
  1643. arr,
  1644. _save,
  1645. saveCol
  1646. };
  1647. };
  1648. /**
  1649. * @description 表格设置窗口,布局保存
  1650. * @param {Array} column 列数组
  1651. * @param {Object} scrollParam 虚拟滚动属性
  1652. * @param {Boolean} updateLocal 本地数据刷新 默认true
  1653. * @param {Function} cb
  1654. */
  1655. const settingConfirm = async (column: any, param: any = {}, updateLocal = true, cb?: any) => {
  1656. if (!props.dwname) {
  1657. ElMessage.error("LjVextable组件未设置储存的模版名称,无法保存");
  1658. return false;
  1659. }
  1660. console.log("settingConfirm column :>> ", JSON.stringify(column));
  1661. console.log("settingConfirm param :>> ", param);
  1662. let { arr, _save, saveCol }: any = await saveColumnsFunc(column, param);
  1663. const $table = tableRef.value;
  1664. // 保存布局
  1665. console.log("settingConfirm settingConfirm saveCol _save :>> ", JSON.stringify(saveCol), _save);
  1666. await layoutStore.setDwLayout(props.dwname, saveCol, t);
  1667. if (updateLocal) {
  1668. /** 本地刷新数据 */
  1669. tableprop_save.value = _save;
  1670. tableOptions.scrollY!.enabled = saveCol?.tableprop.scrollY.enabled;
  1671. tableOptions.scrollY!.oSize = saveCol?.tableprop.scrollY.oSize;
  1672. tableOptions.scrollY!.mode = saveCol?.tableprop.scrollY.mode;
  1673. tableColumns.value = arr;
  1674. $table?.reloadColumn(arr);
  1675. isUpdate.value++;
  1676. console.log("settingConfirm tableColumns.value :>> ", tableColumns.value);
  1677. console.log("warch project newVal settingConfirm tableprop_save.value:>> ", tableprop_save.value);
  1678. // 更新个性属性设置数据源
  1679. colSetting = cloneDeep(column);
  1680. }
  1681. cb && cb();
  1682. };
  1683. /**
  1684. * @description 搜索栏,布局保存
  1685. */
  1686. const saveSearchSettingFunc = async (columns: any, searchParam: any = {}, callback: any) => {
  1687. console.log("saveSearchSettingFunc t param :>> ", typeof searchParam);
  1688. console.log("saveSearchSettingFunc param :>> ", searchParam);
  1689. // let _param = { search: cloneDeep(searchParam) };
  1690. // // // 精简当前布局
  1691. // let flatColumn = cloneDeep(tableColumns.value).filter(
  1692. // (item: any) => !TABLE_TYPE_FILTER.includes(item.type!) && item.field !== "operation"
  1693. // );
  1694. // console.log("saveSearchSettingFunc flatColumns :>> ", flatColumn);
  1695. // loadDwLayoutFunc(columns, false);
  1696. // console.log("saveSearchSettingFunc dwFieldMap :>> ", dwFieldMap);
  1697. // flatColumn = flatColumnsFunc(flatColumn, dwFieldMap);
  1698. // console.log("saveSearchSettingFunc flatColumns :>> ", flatColumn);
  1699. // console.log("saveSearchSettingFunc param :>> ", param);
  1700. // // // 保存布局
  1701. // // props.dwname && layoutStore.setDwLayout(props.dwname, saveCol, t);
  1702. await settingConfirm(columns, { search: searchParam }, false);
  1703. // .then(() => {
  1704. console.log("saveSearchSettingFunc success columns :>> ", columns);
  1705. searchColumns.value = columns;
  1706. callback && callback();
  1707. // });
  1708. };
  1709. /**
  1710. * @description 搜索栏,保存搜索方案
  1711. */
  1712. const editSearchProjectFunc = async (columns: any, params: any, callback: any) => {
  1713. console.log("editSearchProjectFunc columns :>> ", columns);
  1714. console.log("editSearchProjectFunc params :>> ", params);
  1715. await settingConfirm(columns, { searchProject: params }, false);
  1716. callback && callback();
  1717. };
  1718. const autoUpdataSearchParams = (data: any) => {
  1719. // searchParam.value = defaultsDeep(data, searchParam.value);
  1720. searchParam.value = { ...data, pageNum: 1, pageSize: searchParam.value.pageSize };
  1721. console.log("autoUpdataSearchParams searchParam.value :>> ", searchParam.value, tableprop_save.value);
  1722. };
  1723. //表格拖拽调整列宽
  1724. const handleResizChange = (ev: any) => {
  1725. tableColumns.value.forEach(item => {
  1726. if (item.field == ev.column.field) {
  1727. item.width = ev.resizeWidth;
  1728. }
  1729. });
  1730. colSetting.forEach(item => {
  1731. if (item.field == ev.column.field) {
  1732. item.width = ev.resizeWidth;
  1733. }
  1734. });
  1735. console.log("tableColumns :>> ", tableColumns.value);
  1736. // 精简当前布局
  1737. let saveCol = columnStreamlineFunc(tableColumns.value, tableprop_save.value);
  1738. // 保存布局
  1739. props.dwname && layoutStore.setDwLayout(props.dwname, saveCol, t);
  1740. };
  1741. /**
  1742. *
  1743. * @param columns 列
  1744. * @param flatArr 还原数组
  1745. *
  1746. * @returns {Array} flatArr
  1747. */
  1748. const restoreColumnsFunc = (columns: ColumnProps[]) => {
  1749. //先检测是不是数组类型
  1750. if (!Array.isArray(columns)) {
  1751. return [];
  1752. }
  1753. // JS的对象就是hash表
  1754. const targetArr: ColumnProps[] = [];
  1755. columns.forEach((item: ColumnProps) => {
  1756. if (!item?.parents) {
  1757. targetArr.push(item);
  1758. } else {
  1759. if (item?.parents.length > 1) {
  1760. targetArr.push(releaseParentsFunc(item?.parents, item));
  1761. } else {
  1762. let rtArr = {
  1763. field: item?.parents[item?.parents.length - 1],
  1764. visible: true,
  1765. _children: [item]
  1766. };
  1767. targetArr.push(rtArr);
  1768. }
  1769. }
  1770. });
  1771. return gatherColFunc(targetArr);
  1772. };
  1773. /**
  1774. * 还原父级各层级
  1775. * @param arr 数组
  1776. * @param item ColumnProps
  1777. */
  1778. const releaseParentsFunc = (arr: string[], item: any) => {
  1779. let oArr = JSON.parse(JSON.stringify(arr));
  1780. oArr.shift();
  1781. let obj: any = {
  1782. field: arr[0],
  1783. visible: true,
  1784. _children: []
  1785. };
  1786. if (oArr.length == 0) {
  1787. obj._children.push(item);
  1788. } else {
  1789. obj._children.push(releaseParentsFunc(oArr, item));
  1790. }
  1791. return obj;
  1792. };
  1793. /**
  1794. * 相邻层级归类
  1795. * @param columns 列数组
  1796. */
  1797. const gatherColFunc = (columns: ColumnProps[]) => {
  1798. if (!Array.isArray(columns)) {
  1799. return [];
  1800. }
  1801. const prefixList = columns.filter((item: any) => TABLE_TYPE_FILTER.includes(item?.type));
  1802. const affixList = columns.filter((item: any) => item.field == "operation");
  1803. // JS的对象就是hash表
  1804. let arr: any = [];
  1805. const objKey: any = [];
  1806. columns.forEach((item: ColumnProps) => {
  1807. if ((!item.type || item.type == "html") && item.field != "operation") {
  1808. if (objKey.length && item?.field == objKey[objKey.length - 1]) {
  1809. arr[objKey.length - 1]._children = arr[objKey.length - 1]._children?.concat(item._children);
  1810. } else {
  1811. arr.push(item);
  1812. objKey.push(item.field);
  1813. }
  1814. }
  1815. });
  1816. arr.forEach((item: ColumnProps) => {
  1817. if (item._children) {
  1818. item._children = gatherColFunc(item?._children);
  1819. let chidlNum = item._children?.filter(val => !val._children).length;
  1820. if (chidlNum) {
  1821. // item.visible = item._children?.filter(val => !val.visible).length != item._children?.filter(val => !val._children).length;
  1822. item.visible = Boolean(item._children?.filter(val => val.visible).length);
  1823. item.parentHidden =
  1824. item._children?.filter(val => val.parentHidden && !val._children).length ==
  1825. item._children?.filter(val => !val._children).length;
  1826. } else {
  1827. // 子级的均含有_children,即没有显示列,
  1828. item.visible = Boolean(item._children?.filter(val => val.visible).length);
  1829. item.parentHidden = Boolean(item._children?.filter(val => val.parentHidden).length);
  1830. }
  1831. if (item._children) {
  1832. item.fixed = item._children[0].fixed ?? undefined;
  1833. }
  1834. }
  1835. });
  1836. let result = prefixList;
  1837. result = result.concat(arr);
  1838. result = result.concat(affixList);
  1839. return result;
  1840. };
  1841. // 🙅‍♀️ 不需要打印可以把以下方法删除,打印功能目前存在很多 bug
  1842. // 处理打印数据(把后台返回的值根据 enum 做转换)
  1843. // const printData = computed(() => {
  1844. // const handleData = props.data ?? tableData.value;
  1845. // const printDataList = JSON.parse(JSON.stringify(selectedList.value.length ? selectedList.value : handleData));
  1846. // // 找出需要转换数据的列(有 enum || 多级 prop && 需要根据 enum 格式化)
  1847. // const needTransformCol = flatColumns.value!.filter(
  1848. // item => (item.enum || (item.field && item.field.split(".").length > 1)) && item.isFilterEnum
  1849. // );
  1850. // needTransformCol.forEach(colItem => {
  1851. // printDataList.forEach((tableItem: { [key: string]: any }) => {
  1852. // tableItem[handleProp(colItem.field!)] =
  1853. // colItem.field!.split(".").length > 1 && !colItem.enum
  1854. // ? formatValue(handleRowAccordingToProp(tableItem, colItem.field!))
  1855. // : filterEnum(handleRowAccordingToProp(tableItem, colItem.field!), enumMap.value.get(colItem.field!), colItem.fieldNames);
  1856. // for (const key in tableItem) {
  1857. // if (tableItem[key] === null) tableItem[key] = formatValue(tableItem[key]);
  1858. // }
  1859. // });
  1860. // });
  1861. // return printDataList;
  1862. // });
  1863. // 打印表格数据(💥 多级表头数据打印时,只能扁平化成一维数组,printJs 不支持多级表头打印)
  1864. // const print = () => {
  1865. // const header = `<div style="text-align: center"><h2>${props.title}</h2></div>`;
  1866. // const gridHeaderStyle = "border: 1px solid #ebeef5;height: 45px;color: #232425;text-align: center;background-color: #fafafa;";
  1867. // const gridStyle = "border: 1px solid #ebeef5;height: 40px;color: #494b4e;text-align: center";
  1868. // printJS({
  1869. // printable: printData.value,
  1870. // header: props.title && header,
  1871. // properties: flatColumns
  1872. // .value!.filter(item => !["checkbox", "index", "expand"].includes(item.type!) && !item.visible && item.field !== "operation")
  1873. // .map((item: ColumnProps) => ({ field: handleProp(item.field!), displayName: item.label })),
  1874. // type: "json",
  1875. // gridHeaderStyle,
  1876. // gridStyle
  1877. // });
  1878. // };
  1879. const initLayoutColumns = () => {
  1880. // 数行化,还原个性设置
  1881. tableColumns.value = loadRenderAttr(restoreColumnsFunc(flatColumns.value));
  1882. // tableRef.value?.reloadColumn(tableColumns.value);
  1883. console.log("数行化,还原个性设置 tableColumns.value :>> ", tableColumns.value);
  1884. colSetting = cloneDeep(flatColumns.value).filter(
  1885. (item: any) => !TABLE_TYPE_FILTER.includes(item.type!) && item.field !== "operation"
  1886. );
  1887. let dSort = tableColumns.value.filter(col => col.field && col.sortable && col.order);
  1888. console.log("defaultSort :>> ", dSort);
  1889. defaultSort.value = dSort.map(col => {
  1890. return {
  1891. field: col.field!,
  1892. table: col.table!,
  1893. order: col.order!,
  1894. sortTime: col.sortTime ?? 0
  1895. };
  1896. });
  1897. defaultSort.value.sort((a, b) => a.sortTime - b.sortTime);
  1898. tableOptions.sortConfig!.defaultSort = defaultSort.value;
  1899. console.log("tableOptions :>> ", tableOptions);
  1900. // // 记录原始列
  1901. // let prototype = flatColumnsFunc(cloneDeep(props.columns));
  1902. // prototypeCol = prototype.filter(
  1903. // (item: any) => !TABLE_TYPE_FILTER.includes(item.type!) && item.field !== "operation"
  1904. // );
  1905. // tableRef.value?.reloadColumn(tableColumns.value);
  1906. nextTick(() => {
  1907. isUpdate.value++;
  1908. });
  1909. // 过滤需要搜索的配置项
  1910. searchColumns.value = flatColumns.value.filter((item: any) => item.search?.el || item.search?.render);
  1911. console.log("init searchColumns.value :>> ", searchColumns.value);
  1912. // 读取缓存搜索记录
  1913. let queryHabit = {};
  1914. if (props.dwname && props.ifLoadQueryHabit) {
  1915. queryHabit = userStore.getQueryHabit(props.dwname);
  1916. }
  1917. console.log("init LayoutColumns queryHabit :>> ", queryHabit);
  1918. // 设置搜索表单排序默认值 && 设置搜索表单项的默认值
  1919. searchColumns.value.forEach((column, index) => {
  1920. column.search!.order = column.search!.order ?? index + 2;
  1921. if (column.search?.defaultValue !== undefined && column.search?.defaultValue !== null) {
  1922. searchInitParam.value[column.search.key ?? handleProp(column.field!)] = column.search?.defaultValue;
  1923. searchParam.value[column.search.key ?? handleProp(column.field!)] = column.search?.defaultValue;
  1924. }
  1925. });
  1926. console.log("init LayoutColumns searchParam.value :>> ", searchParam.value);
  1927. // 表格搜索栏,设置缓存搜索信息
  1928. /** 赋值初始化搜索表单 */
  1929. if (props.initParam) {
  1930. for (const key in props.initParam) {
  1931. !Object.keys(searchParam.value).includes(key) && (searchParam.value[key] = props.initParam[key]);
  1932. }
  1933. }
  1934. Object.assign(searchParam.value, queryHabit);
  1935. // 第一次搜索带入参数
  1936. totalParam.value = searchParam.value;
  1937. // 排序搜索表单项
  1938. searchColumns.value.sort((a, b) => a.search!.order! - b.search!.order!);
  1939. emit("layoutChange", tableColumns.value);
  1940. };
  1941. const loadColumns = (columns: any) => {
  1942. flatColumns.value = flatColumnsFunc(cloneDeep(columns));
  1943. tableColumns.value = loadRenderAttr(restoreColumnsFunc(flatColumns.value));
  1944. console.log("数行化,还原个性设置 tableColumns.value onllyyyyy:>> ", columns, tableColumns.value);
  1945. nextTick(() => {
  1946. isUpdate.value++;
  1947. });
  1948. };
  1949. /**
  1950. * @description 获取表格数据后,自动执行选中第一行
  1951. */
  1952. const afterGetData = () => {
  1953. emit("afterMounted", tableData.value);
  1954. if (props.autoSelectFirstAfterRefresh && tableData.value.length) {
  1955. nextTick(() => {
  1956. tableRef.value?.setCurrentRow(tableData.value[0]);
  1957. if (props.tableEvents && "current-change" in props.tableEvents) {
  1958. props.tableEvents["current-change"]({ newValue: tableData.value[0], row: tableData.value[0] });
  1959. }
  1960. });
  1961. }
  1962. };
  1963. // 初始化请求
  1964. onMounted(async () => {
  1965. await loadLayoutFunc();
  1966. initLayoutColumns();
  1967. console.log("onMounted .ifLoadQueryHabit :>> ", searchParam.value);
  1968. if (props.requestAuto) {
  1969. getTableList().then(() => {
  1970. emit("firstMounted", tableData.value);
  1971. console.log("onMounted tableColumns.value :>> ", tableColumns.value);
  1972. nextTick(() => {
  1973. // 指导
  1974. props.toolButton.indexOf("guide") > -1 && checkIfNeedGuide();
  1975. afterGetData();
  1976. });
  1977. });
  1978. } else {
  1979. emit("firstMounted", tableData.value);
  1980. afterGetData();
  1981. }
  1982. /**
  1983. * @description 获取打印机选项状态
  1984. */
  1985. toGetPrinterState();
  1986. });
  1987. /**
  1988. * @description 重置布局
  1989. */
  1990. const resetSetting = async (cb: any) => {
  1991. let oriColumns = await getOriColumns(true, true, -1, enumMap.value);
  1992. console.log("oriColumns :>> ", oriColumns);
  1993. if (oriColumns.columns.length) {
  1994. } else {
  1995. ElMessage.warning(t("sys.layout.empty") + props.dwname);
  1996. }
  1997. cb && cb(oriColumns);
  1998. // layoutStore.getDwLayout_online(-1, props.dwname!, 0).then((layout: any) => {
  1999. // console.log("layoutStore dwlayoutGet:>> ", layoutStore.dwlayoutGet);
  2000. // if (layout?.hasOwnProperty("itemvalue") && layout.itemvalue) {
  2001. // let dwLayout: ColumnProps[] = [];
  2002. // let scrollYDefault = {};
  2003. // console.log("resetSetting loadLayoutFunc layout :>> ", layout);
  2004. // if (layout?.hasOwnProperty("itemvalue") && layout.itemvalue) {
  2005. // // 表格结构: {tableprop: string, columns: string}
  2006. // typeof layout.itemvalue == "string" && (layout.itemvalue = JSON.parse(layout.itemvalue.replace(/'/g, '"')));
  2007. // // 兼容部分结构直接记录行数据
  2008. // if (layout.itemvalue.hasOwnProperty("columns") && layout.itemvalue.columns) {
  2009. // dwLayout = layout.itemvalue.columns;
  2010. // } else {
  2011. // dwLayout = layout.itemvalue;
  2012. // }
  2013. // if (layout.itemvalue?.hasOwnProperty("tableprop") && layout.itemvalue.tableprop) {
  2014. // scrollYDefault = layout.itemvalue.tableprop;
  2015. // }
  2016. // }
  2017. // // 读取默认属性
  2018. // loadDwLayoutFunc(props.columns, false);
  2019. // console.log(" resetSetting dwFieldMap :>>>>>>>>>>>>>>>>>>>>>", dwFieldMap);
  2020. // let prototype = flatColumnsFunc(dwLayout, dwFieldMap);
  2021. // let prototypeCol = prototype.filter((item: any) => !TABLE_TYPE_FILTER.includes(item.type!) && item.field !== "operation");
  2022. // cb && cb(prototypeCol, scrollYDefault);
  2023. // } else {
  2024. // ElMessage.warning(t("sys.layout.empty") + props.dwname);
  2025. // cb && cb([]);
  2026. // }
  2027. // });
  2028. };
  2029. /**
  2030. * @description 保存系统默认模版
  2031. */
  2032. const saveDefaultLayout = async (column: any, param: any, cb: any) => {
  2033. if (!props.dwname) {
  2034. ElMessage.error("LjVextable组件未设置储存的模版名称,无法保存");
  2035. return false;
  2036. }
  2037. let { saveCol }: any = await saveColumnsFunc(column, param, true, -1);
  2038. // const $table = tableRef.value;
  2039. // 保存布局
  2040. console.log("settingConfirm saveCol :>> ", saveCol);
  2041. await layoutStore.saveDwLayout_online(-1, props.dwname, saveCol);
  2042. cb && cb();
  2043. // settingConfirm(tableColumns.value, {}, false).then(() => {
  2044. // let orderstr = defaultSort.value.map((item: any) => `${item.field} ${item.order}`).join(", ");
  2045. // console.log("after settingConfirm orderstr :>> ", orderstr);
  2046. // searchInitParam.value.orderstr = orderstr;
  2047. // // 当页码大于1时,才重新加载数据
  2048. // if (fullData.length >= pageable.value.pageSize) {
  2049. // getTableList();
  2050. // }
  2051. // });
  2052. };
  2053. /**
  2054. * @description 主动刷新数据
  2055. */
  2056. const refresh = async (outline?: boolean) => {
  2057. !outline && (await getTableList());
  2058. nextTick(() => {
  2059. isUpdate.value++;
  2060. afterGetData();
  2061. });
  2062. };
  2063. /**
  2064. * @description 清除排序
  2065. */
  2066. const clearSortEvent = (field?: string) => {
  2067. const $table = tableRef.value;
  2068. if (field) {
  2069. if ($table) {
  2070. $table.clearSort(field);
  2071. defaultSort.value = defaultSort.value.filter((itm: any) => itm.field !== field);
  2072. }
  2073. tableColumns.value.forEach((item: any) => {
  2074. if (item.field === field) {
  2075. item.order = "";
  2076. item.sortTime = 0;
  2077. return;
  2078. }
  2079. });
  2080. } else {
  2081. if ($table) {
  2082. $table.clearSort();
  2083. defaultSort.value = [];
  2084. }
  2085. tableColumns.value.forEach((item: any) => {
  2086. item.order = "";
  2087. item.sortTime = 0;
  2088. });
  2089. }
  2090. let fullData = [];
  2091. if ($table) {
  2092. fullData = $table.getTableData().fullData;
  2093. }
  2094. settingConfirm(tableColumns.value, {}, false).then(() => {
  2095. let orderstr = defaultSort.value.map((item: any) => `${item.field} ${item.order}`).join(", ");
  2096. console.log("after settingConfirm orderstr :>> ", orderstr);
  2097. searchInitParam.value.orderstr = orderstr;
  2098. // 当页码大于1时,才重新加载数据
  2099. if (fullData.length >= pageable.value.pageSize) {
  2100. getTableList();
  2101. }
  2102. });
  2103. };
  2104. /**
  2105. * @description 监听排序变化
  2106. */
  2107. const handleSortChange = (data: any) => {
  2108. console.log("handleSortChange data :>> ", data);
  2109. const { sortList } = data;
  2110. defaultSort.value = sortList.map((itm: any) => {
  2111. return {
  2112. field: itm.field,
  2113. title: itm.column.title,
  2114. order: itm.order,
  2115. sortTime: itm.sortTime
  2116. };
  2117. });
  2118. console.log("defaultSort.value :>> ", defaultSort.value);
  2119. console.log("searchInitParam.value :>> ", searchInitParam.value);
  2120. defaultSort.value.map((sortitem: any) => {
  2121. tableColumns.value.forEach((item: any) => {
  2122. if (item.field == sortitem.field) {
  2123. item.order = sortitem.order;
  2124. item.sortTime = sortitem.sortTime;
  2125. return;
  2126. }
  2127. });
  2128. });
  2129. const $table = tableRef.value;
  2130. let fullData = [];
  2131. if ($table) {
  2132. fullData = $table.getTableData().fullData;
  2133. }
  2134. settingConfirm(tableColumns.value, {}, false).then(() => {
  2135. let orderstr = defaultSort.value.map((item: any) => `${item.field} ${item.order}`).join(", ");
  2136. console.log("after settingConfirm orderstr :>> ", orderstr);
  2137. searchInitParam.value.orderstr = orderstr;
  2138. // 当页码大于1时,才重新加载数据
  2139. if (fullData.length >= pageable.value.pageSize) {
  2140. getTableList();
  2141. }
  2142. });
  2143. };
  2144. /**
  2145. * @description 导出数据
  2146. */
  2147. const exportDataEvent = () => {
  2148. const $table = tableRef.value;
  2149. $table?.openExport();
  2150. };
  2151. /**
  2152. * @description 导出数据
  2153. */
  2154. const importDataEvent = () => {
  2155. const $table = tableRef.value;
  2156. $table?.importData({
  2157. remote: true,
  2158. importMethod: ({ file }) => {
  2159. console.log("importMethod file :>> ", file);
  2160. // 处理表单
  2161. // const formBody = new FormData();
  2162. // formBody.append("file", file);
  2163. // console.log("importMethod formBody :>> ", formBody);
  2164. // 上传文件
  2165. return props
  2166. .importApi([file])
  2167. .then(rest => {
  2168. // if (rest.status === 200) {
  2169. // this.$refs.grid.commitProxy('query');
  2170. // this.$message({
  2171. // type: 'success',
  2172. // message: '导入成功'
  2173. // });
  2174. // } else {
  2175. // this.$message({
  2176. // type: 'error',
  2177. // message: '导入失败'
  2178. // });
  2179. // }
  2180. })
  2181. .catch(() => {
  2182. // this.$message({ content: '导入失败,请检查数据是否正确!', status: 'error' })
  2183. });
  2184. }
  2185. });
  2186. };
  2187. /**
  2188. * @description 打印模块
  2189. */
  2190. // const printEditorRef = ref();
  2191. // const PrintTemplateRef = ref();
  2192. // const hiprinterStore = useHiprinterStore();
  2193. // /**
  2194. // * @description 获取打印模块个性名称
  2195. // * @param name 额外名称
  2196. // */
  2197. // const getPrintDwname = (name = "") => {
  2198. // return props.dwname + name + "_print_template";
  2199. // };
  2200. // /**
  2201. // * @description 直接打印:明细设置记录
  2202. // */
  2203. // const hiprinterStateList = ref(false);
  2204. // /**
  2205. // * @description 直接打印:条码设置记录
  2206. // */
  2207. // const hiprinterStateMx = ref(false);
  2208. // const toGetPrinterState = () => {
  2209. // let _mx = JSON.stringify(hiprinterStore.getPrinter(getPrintDwname(""))) != "{}";
  2210. // hiprinterStateList.value = _mx;
  2211. // let _barcode = JSON.stringify(hiprinterStore.getPrinter(getPrintDwname("_mx"))) != "{}";
  2212. // hiprinterStateMx.value = _barcode;
  2213. // };
  2214. // /**
  2215. // * 获取打印数据, 并返回厂商comid
  2216. // */
  2217. // const getPrintDataFunc = (callback: any) => {
  2218. // const $table = tableRef.value;
  2219. // if ($table) {
  2220. // const _records = $table.getCheckboxRecords() ?? [];
  2221. // const curRecords = $table.getCurrentRecord() ?? null;
  2222. // let cuscomid = 0;
  2223. // if (_records.length == 0 && !curRecords) {
  2224. // ElMessage.warning(t("common.table.printSelectDataTips"));
  2225. // return;
  2226. // } else {
  2227. // if (_records.length > 0) {
  2228. // cuscomid = _records[0].cuscomid;
  2229. // for (let i = 1; i < _records.length; i++) {
  2230. // if (_records[i].cuscomid != cuscomid) {
  2231. // ElMessage.warning(t("common.table.printSelectSameTips"));
  2232. // return false;
  2233. // }
  2234. // }
  2235. // } else if (curRecords) {
  2236. // cuscomid = curRecords.cuscomid;
  2237. // }
  2238. // }
  2239. // selectRecords.value = !_records.length ? [curRecords] : _records;
  2240. // let checkData = true;
  2241. // props.beforePrintCallback && (checkData = props.beforePrintCallback(selectRecords.value));
  2242. // console.log("checkData :>> ", checkData);
  2243. // if (!checkData) return false;
  2244. // callback && callback(cuscomid);
  2245. // }
  2246. // };
  2247. // const activePrint = ref("");
  2248. // /**
  2249. // * @description 打开打印
  2250. // */
  2251. // const openPrint = (name = "") => {
  2252. // activePrint.value = name ?? "";
  2253. // // 获取打印数据
  2254. // getPrintDataFunc((cuscomid: number) => {
  2255. // PrintTemplateRef.value?.open({
  2256. // dwname: getPrintDwname(name),
  2257. // opposidecomid: cuscomid
  2258. // });
  2259. // });
  2260. // };
  2261. // /**
  2262. // * @description 直接打开预览
  2263. // */
  2264. // const openPrintPriveiew = (name = "", direct = false) => {
  2265. // activePrint.value = name ?? "";
  2266. // // 获取打印数据
  2267. // getPrintDataFunc(async (cuscomid: number) => {
  2268. // // PrintTemplateRef.value.getData()
  2269. // // let _key = getPrintDwname(name);
  2270. // // // 获取打印模板
  2271. // // const data = await getPrintTemplate({
  2272. // // dwname: _key,
  2273. // // opposidecomid: cuscomid
  2274. // // });
  2275. // // console.log("getData data :>> ", data);
  2276. // // if (data?.templateList.length) {
  2277. // // toPreviewPrintTemplate(data.templateList[0], _key, direct);
  2278. // // } else {
  2279. // // ElMessage.warning(t("business.selector.printTemplate.printTemplageEmpty"));
  2280. // // PrintTemplateRef.value?.open({
  2281. // // dwname: _key,
  2282. // // opposidecomid: cuscomid
  2283. // // });
  2284. // // }
  2285. // });
  2286. // };
  2287. // /**
  2288. // * 修改:打印模板列表页-修改
  2289. // * @param data 打印模板
  2290. // */
  2291. // const toEditPrintTemplate = (data?: any) => {
  2292. // console.log("toEditPrintTemplate data :>> ", data);
  2293. // if (data && data.comid == 0) {
  2294. // // 系统模板,另存为
  2295. // data.aliase = "新建模版";
  2296. // // 新增模版
  2297. // delete data.printid;
  2298. // }
  2299. // let tem = data ?? {
  2300. // tid: 0,
  2301. // aliase: "新建模版",
  2302. // dwname: props.dwname + "_print_template",
  2303. // content: {},
  2304. // };
  2305. // if (typeof tem.content == "string") {
  2306. // tem.content = JSON.parse(tem.content);
  2307. // }
  2308. // console.log("selectRecords.value :>> ", selectRecords.value);
  2309. // let printData = {
  2310. // userInfo: userStore.userInfo,
  2311. // // cusname: selectRecords.value[0].comname,
  2312. // table: selectRecords.value
  2313. // };
  2314. // if (props.printDataCallback) {
  2315. // props.printDataCallback(printData).then((res: any) => {
  2316. // console.log("res :>> ", res);
  2317. // printEditorRef.value?.open(tem, res);
  2318. // });
  2319. // } else {
  2320. // printEditorRef.value?.open(tem, printData);
  2321. // }
  2322. // };
  2323. // /**
  2324. // * @description 预览:打印模板列表-预览
  2325. // */
  2326. // const toPreviewPrintTemplate = (data: any) => {
  2327. // // console.log("toEditPrintTemplate data :>> ", data);
  2328. // // let tem = data;
  2329. // // if (typeof tem.content == "string") {
  2330. // // tem.content = JSON.parse(tem.content);
  2331. // // }
  2332. // // let printData = {
  2333. // // comInfo: userStore.comInfo,
  2334. // // cusname: selectRecords.value[0].comname,
  2335. // // table: selectRecords.value
  2336. // // };
  2337. // // if (props.printDataCallback) {
  2338. // // props.printDataCallback(printData).then((res: any) => {
  2339. // // printEditorRef.value?.onlyPreview(tem, res, tem.aliase);
  2340. // // });
  2341. // // } else {
  2342. // // printEditorRef.value?.onlyPreview(tem, printData, tem.aliase);
  2343. // // }
  2344. // };
  2345. /**
  2346. * @description 打印:打印模板列表-打印
  2347. */
  2348. // const toPrintPrintTemplate = (data: any, callback: any) => {
  2349. // console.log("toEditPrintTemplate data :>> ", data);
  2350. // let tem = data;
  2351. // if (typeof tem.content == "string") {
  2352. // tem.content = JSON.parse(tem.content);
  2353. // }
  2354. // let printData = {
  2355. // comInfo: userStore.comInfo,
  2356. // cusname: selectRecords.value[0].comname,
  2357. // table: selectRecords.value
  2358. // };
  2359. // if (props.printDataCallback) {
  2360. // props.printDataCallback(printData).then((res: any) => {
  2361. // printEditorRef.value?.onlyPrint(tem, res, tem.aliase);
  2362. // callback && callback();
  2363. // });
  2364. // } else {
  2365. // printEditorRef.value?.onlyPrint(tem, printData, tem.aliase);
  2366. // callback && callback();
  2367. // }
  2368. // };
  2369. // /**
  2370. // * 保存:打印模板编辑器
  2371. // * @param data 打印模板参数
  2372. // */
  2373. // const toSavePrintTemplate = async (data: any, callback?: any) => {
  2374. // let _data = pick(data, PRINT_KEY_ATTR);
  2375. // await savePrintTemplate({ template: _data });
  2376. // ElMessage.success(t("sys.api.sueccessToSave"));
  2377. // callback && callback();
  2378. // };
  2379. /**
  2380. * 关闭后,是否刷新打印模板列表页
  2381. * @param saved 是否有保存过
  2382. */
  2383. const toClosedPrintEditor = (saved: boolean) => {
  2384. saved && printTemplateRef.value?.getData();
  2385. };
  2386. const locationRef = ref();
  2387. const locationBtnRef = ref();
  2388. const scrollCol = ref("");
  2389. const locationAutocompleteRef = ref();
  2390. const oriTableData = ref<any>([]);
  2391. const locationFrom = reactive({
  2392. field: "",
  2393. value: ""
  2394. });
  2395. // onKeyStroke(["f", "Ctrl"], e => {
  2396. // e.preventDefault();
  2397. // oriTableData.value = cloneDeep(tableData.value);
  2398. // locationDialogRef.value.show();
  2399. // console.log("onKeyStroke e :>> ", e);
  2400. // });
  2401. /**
  2402. * @description 定位列
  2403. */
  2404. const funcScrollToCol = (item: any) => {
  2405. console.log("locationAutocompleteRef.value :>> ", locationAutocompleteRef.value);
  2406. // if (locationTabActive.value == "data") return false;
  2407. let idx = tableColumns.value.findIndex((v: any) => v.field == item.field);
  2408. let lastField = item.field;
  2409. if (idx > 0) {
  2410. lastField = tableColumns.value[idx - 1].field;
  2411. }
  2412. let _space = 400; //ms
  2413. if (tableRef.value) {
  2414. tableRef.value.scrollToColumn(lastField);
  2415. tableRef.value.setCurrentColumn(item.field).then(() => {
  2416. setTimeout(() => {
  2417. tableRef.value &&
  2418. tableRef.value.clearCurrentColumn().then(() => {
  2419. setTimeout(() => {
  2420. tableRef.value &&
  2421. tableRef.value.setCurrentColumn(item.field).then(() => {
  2422. setTimeout(() => {
  2423. tableRef.value && tableRef.value.clearCurrentColumn();
  2424. }, _space);
  2425. });
  2426. }, _space);
  2427. });
  2428. }, _space);
  2429. });
  2430. }
  2431. };
  2432. const matchData = ref<any>([]);
  2433. const matchIndex = ref(0);
  2434. const funcChangeLocation = (index: number) => {
  2435. console.log("index :>> ", index);
  2436. let _index = matchIndex.value + index;
  2437. if (_index >= matchData.value.length) {
  2438. _index = 0;
  2439. } else if (_index < 0) {
  2440. _index = matchData.value.length - 1;
  2441. }
  2442. funcSrollToRow(locationFrom.value, _index);
  2443. };
  2444. /**
  2445. * @description 定位行
  2446. */
  2447. const funcSrollToRow = (value: any, index = 0) => {
  2448. matchIndex.value = index;
  2449. const filterVal = String(value).trim().toLowerCase();
  2450. if (filterVal) {
  2451. const filterRE = new RegExp(filterVal, "gi");
  2452. tableData.value = cloneDeep(oriTableData.value);
  2453. matchData.value = tableData.value.filter((v: any) => {
  2454. let _match = false;
  2455. for (const key in v) {
  2456. if (String(v[key]).toLowerCase().indexOf(value) > -1) {
  2457. _match = true;
  2458. v[key] = String(v[key]).replace(filterRE, match => `<span class="keyword-lighten">${match}</span>`);
  2459. }
  2460. let idx = tableColumns.value.findIndex((itm: any) => key == itm.field);
  2461. if (idx > 0 && ["hmlt", null, undefined].includes(tableColumns.value[idx].type)) {
  2462. tableColumns.value[idx].type = _match ? "html" : null;
  2463. }
  2464. }
  2465. // v.type = _match ? "html" : null;
  2466. return _match;
  2467. // return String(v[locationFrom.field]).toLowerCase().indexOf(value) > -1;
  2468. });
  2469. console.log(" tableData.value :>> ", tableData.value, tableColumns.value, matchData.value);
  2470. let idx = tableColumns.value.findIndex((v: any) => v.field == locationFrom.field);
  2471. let lastField = locationFrom.field;
  2472. if (idx > 0) {
  2473. lastField = tableColumns.value[idx - 1].field || lastField;
  2474. }
  2475. let _space = 400; //ms
  2476. if (tableRef.value) {
  2477. // let getRow = tableRef.value.getRowById(matchData.value[matchIndex.value]._X_ROW_KEY);
  2478. let _row = matchData.value[matchIndex.value];
  2479. // console.log("getRow :>> ", getRow);
  2480. tableRef.value.scrollToRow(_row, lastField);
  2481. tableRef.value.setCurrentColumn(locationFrom.field);
  2482. tableRef.value.setCurrentRow(_row).then(() => {
  2483. setTimeout(() => {
  2484. if (tableRef.value) {
  2485. tableRef.value.clearCurrentColumn();
  2486. tableRef.value.clearCurrentRow();
  2487. }
  2488. }, _space);
  2489. });
  2490. }
  2491. }
  2492. };
  2493. // 节流
  2494. const disshow = throttle((val: any) => {
  2495. funcSrollToRow(val);
  2496. }, 500);
  2497. /**
  2498. * @description 定位行/列
  2499. */
  2500. const locationQuerySearch = (queryString: string, cb: any) => {
  2501. let _query = queryString.toLowerCase();
  2502. const results = queryString ? pinyinFilter(_query, tableColumns.value, ["title", "field"]) : tableColumns.value;
  2503. console.log("results :>> ", results);
  2504. cb(results);
  2505. };
  2506. const autoShowLocationPopover = () => {
  2507. locationAutocompleteRef.value.focus();
  2508. };
  2509. const autoCloseLocation = () => {
  2510. tableData.value = cloneDeep(oriTableData.value);
  2511. tableColumns.value = tableColumns.value.map(item => {
  2512. if (["hmlt", null, undefined].includes(item.type)) {
  2513. item.type = null;
  2514. }
  2515. return item;
  2516. });
  2517. };
  2518. // const locationDialogRef = ref();
  2519. // const locationTabActive = ref("col");
  2520. // const handleShowLocation = () => {
  2521. // locationTabActive.value = "col";
  2522. // locationDialogRef.value.show();
  2523. // };
  2524. // /**动态合并 */
  2525. // const mergeCells = ref<VxeTablePropTypes.MergeCells>([
  2526. // { row: 4, col: 2, rowspan: 2, colspan: 5 },
  2527. // { row: 30, col: 3, rowspan: 10, colspan: 1 },
  2528. // { row: 80, col: 4, rowspan: 30, colspan: 3 }
  2529. // ]);
  2530. // 监听页面 initParam 改化,重新获取表格数据
  2531. watch(
  2532. () => props.initParam,
  2533. async val => {
  2534. await search();
  2535. afterGetData();
  2536. },
  2537. { deep: true }
  2538. );
  2539. /**
  2540. * @description vxeTable方法封装
  2541. */
  2542. const vxeTableEvents = {
  2543. getTableData: () => tableRef.value?.getTableData(),
  2544. insertAt: (records: any | any[], row?: any | -1 | 0) => tableRef.value?.insertAt(records, row),
  2545. setCurrentRow: (params: any) =>
  2546. nextTick(() => {
  2547. tableRef.value?.setCurrentRow(params);
  2548. }),
  2549. setRow: (rows: any, record: any) => tableRef.value?.setRow(rows, record),
  2550. remove: (params: any) => tableRef.value?.remove(params),
  2551. getCurrentRecord: () => tableRef.value?.getCurrentRecord(),
  2552. getCheckboxRecords: (isFull: any) => tableRef.value?.getCheckboxRecords(isFull),
  2553. /**
  2554. * @description 获取当前勾选/选中的数据,否则自动选择第一条数据
  2555. */
  2556. getCurrentRecords: () => {
  2557. const _records = tableRef.value?.getCheckboxRecords() ?? [];
  2558. const _cRecords = tableRef.value?.getCurrentRecord() ?? null;
  2559. let curRecords: any[] = [];
  2560. if (_records.length) {
  2561. // 获取勾选列表
  2562. curRecords = _records;
  2563. } else if (_cRecords) {
  2564. // 获取当前选中数据
  2565. curRecords = [_cRecords];
  2566. } else {
  2567. // 默认获取第一条记录
  2568. let visibleData = tableRef.value?.getTableData().visibleData;
  2569. if (visibleData?.length) {
  2570. curRecords = [visibleData[0]];
  2571. tableRef.value?.setCurrentRow(visibleData[0]);
  2572. }
  2573. }
  2574. return curRecords;
  2575. }
  2576. };
  2577. /**
  2578. * @description 点击表格外部,关闭编辑状态
  2579. */
  2580. onClickOutside(tableRef, event => {
  2581. let ifEdit = tableRef.value.getEditRecord();
  2582. // 检查点击事件的目标元素是否在排除列表中,(下拉)
  2583. const excludeElements = [
  2584. event.target?.closest(".el-popper") ?? undefined,
  2585. event.target?.closest(".vxe-select--panel") ?? undefined,
  2586. event.target?.closest(".vxe-input--panel") ?? undefined
  2587. ];
  2588. const isExcluded = excludeElements.filter(Boolean).some(el => el.contains(event.target));
  2589. // console.log("onClickOutside excludeElements :>> ", excludeElements);
  2590. // console.log("onClickOutside isExcluded :>> ", isExcluded, !isExcluded && ifEdit);
  2591. if (!isExcluded && ifEdit) {
  2592. tableRef.value.clearEdit();
  2593. }
  2594. });
  2595. /**
  2596. * @description 当前编辑的单元格
  2597. */
  2598. const currentEditCell = ref<any>({
  2599. field: 0,
  2600. rowIndex: 0
  2601. });
  2602. const scrollTo = (row: any, field?: any) => {
  2603. tableRef.value.setCurrentRow(row);
  2604. tableRef.value.scrollToRow(row, field);
  2605. };
  2606. // 暴露给父组件的参数和方法(外部需要什么,都可以从这里暴露出去)
  2607. defineExpose({
  2608. element: tableRef,
  2609. ...vxeTableEvents,
  2610. tableData,
  2611. // pageable,
  2612. searchParam,
  2613. // searchInitParam,
  2614. tableColumns,
  2615. getTableList,
  2616. search,
  2617. reset,
  2618. refresh,
  2619. // handleSizeChange,
  2620. // handleCurrentChange,
  2621. handlePageChange,
  2622. openColSetting,
  2623. // clearSelection,
  2624. enumMap,
  2625. baseEnumMap,
  2626. // isSelected,
  2627. // selectedList,
  2628. // selectedListIds
  2629. initLayoutColumns,
  2630. currentEditCell,
  2631. scrollTo,
  2632. loadColumns
  2633. });
  2634. </script>
  2635. <style lang="scss" scoped>
  2636. .table-main {
  2637. &.card {
  2638. padding-top: 12px;
  2639. padding-bottom: 0;
  2640. }
  2641. .search-btn.active {
  2642. box-shadow: $shadow-1-down-inset;
  2643. }
  2644. .table-main__tool-button {
  2645. margin-right: 12px;
  2646. margin-left: 12px;
  2647. :deep(.el-button-group) {
  2648. .el-button:first-child {
  2649. border-top-left-radius: 16px;
  2650. border-bottom-left-radius: 16px;
  2651. }
  2652. .el-button:last-child {
  2653. border-top-right-radius: 16px;
  2654. border-bottom-right-radius: 16px;
  2655. }
  2656. }
  2657. }
  2658. .table-warpper {
  2659. overflow: hidden;
  2660. .collapse-buttons__group {
  2661. position: absolute;
  2662. top: 6px;
  2663. right: $space-b1;
  2664. z-index: 5;
  2665. }
  2666. // .more-btn {
  2667. // // opacity: 0.68;
  2668. // transition: all ease-in-out 0.2s;
  2669. // transform: translateX(70%);
  2670. // }
  2671. // &:hover {
  2672. // .more-btn {
  2673. // // opacity: 1;
  2674. // transform: translateX(0);
  2675. // }
  2676. // }
  2677. }
  2678. }
  2679. .lj-main-body.small .table-main {
  2680. &.card {
  2681. padding-top: 8px;
  2682. padding-bottom: 0;
  2683. }
  2684. }
  2685. .card + .card {
  2686. margin-top: $space-b2;
  2687. }
  2688. /* 滚动条整体部分 */
  2689. .lj-vxetable ::-webkit-scrollbar {
  2690. width: 12px;
  2691. height: 12px;
  2692. }
  2693. .lj-vxetable ::-moz-scrollbar {
  2694. width: 12px;
  2695. height: 12px;
  2696. }
  2697. .lj-vxetable {
  2698. :deep(.vxe-loading) {
  2699. background-color: rgb($color-gray-1 / 60%);
  2700. backdrop-filter: blur(2px);
  2701. }
  2702. }
  2703. </style>
  2704. <style lang="scss">
  2705. .lj-main-body {
  2706. .tableheader-tabs {
  2707. .el-tabs__header {
  2708. margin-bottom: 0;
  2709. }
  2710. }
  2711. &.small {
  2712. .tableheader-tabs {
  2713. --el-tabs-header-height: 33px;
  2714. }
  2715. .table-box .table-search,
  2716. .table-main .table-search {
  2717. margin-bottom: 0;
  2718. }
  2719. }
  2720. }
  2721. </style>