index.vue 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605
  1. <template>
  2. <div class="app-container">
  3. <el-form v-show="showSearch" ref="queryForm" :inline="true" :model="queryParams" label-width="68px">
  4. <!-- <el-form-item label="订单号" prop="orderCode">
  5. <el-input
  6. v-model="queryParams.orderCode"
  7. clearable
  8. placeholder="请输入订单号"
  9. size="small"
  10. @keyup.enter.native="handleQuery"
  11. />
  12. </el-form-item> -->
  13. <el-form-item label="订单号" prop="orderCodes">
  14. <div class="tag-input-container">
  15. <!-- 标签显示区域 -->
  16. <div class="tags-wrapper" @click="focusInput">
  17. <!-- 已添加的订单号标签 -->
  18. <el-tag
  19. v-for="(code, index) in queryParams.orderCodes"
  20. :key="index"
  21. closable
  22. size="small"
  23. @close="removeOrderCode(index)"
  24. class="order-tag"
  25. :class="{ 'tag-error': false }"
  26. >
  27. {{ code }}
  28. </el-tag>
  29. <!-- 输入框 -->
  30. <el-input
  31. ref="tagInput"
  32. v-model="currentInput"
  33. v-show="inputVisible || queryParams.orderCodes.length === 0"
  34. :placeholder="queryParams.orderCodes.length === 0 ? '请输入订单号,按回车或逗号分隔' : '继续输入...'"
  35. size="small"
  36. class="tag-input"
  37. @keydown.native="handleKeyDown"
  38. @keyup.native="handleKeyUp"
  39. @blur="handleInputConfirm"
  40. @focus="inputVisible = true"
  41. clearable
  42. />
  43. <!-- 添加按钮(当没有输入时显示) -->
  44. <el-button
  45. v-if="!inputVisible && queryParams.orderCodes.length > 0"
  46. class="button-new-tag"
  47. size="small"
  48. @click="showInput"
  49. icon="el-icon-plus"
  50. type="text"
  51. >
  52. 添加订单号
  53. </el-button>
  54. </div>
  55. <!-- 输入提示 -->
  56. <div class="input-tips">
  57. <span class="tip-text">
  58. 支持:回车、逗号、空格分隔 |
  59. 已添加 {{ queryParams.orderCodes.length }} 个订单号
  60. <span v-if="maxOrderCodes > 0"> (最多{{ maxOrderCodes }}个)</span>
  61. </span>
  62. </div>
  63. </div>
  64. </el-form-item>
  65. <el-form-item label="运单号" prop="deliveryId">
  66. <el-input
  67. v-model="queryParams.deliveryId"
  68. clearable
  69. placeholder="请输入运单号"
  70. size="small"
  71. @keyup.enter.native="handleQuery"
  72. />
  73. </el-form-item>
  74. <el-form-item label="手机号" prop="userPhone">
  75. <el-input
  76. v-model="queryParams.userPhone"
  77. clearable
  78. placeholder="请输入手机号"
  79. size="small"
  80. @keyup.enter.native="handleQuery"
  81. />
  82. </el-form-item>
  83. <el-form-item label="收件人" prop="realName">
  84. <el-input
  85. v-model="queryParams.realName"
  86. clearable
  87. placeholder="请输入收件人姓名"
  88. size="small"
  89. @keyup.enter.native="handleQuery"
  90. />
  91. </el-form-item>
  92. <el-form-item label="产品" prop="productName">
  93. <el-input
  94. v-model="queryParams.productName"
  95. clearable
  96. placeholder="请输入产品名"
  97. size="small"
  98. @keyup.enter.native="handleQuery"
  99. />
  100. </el-form-item>
  101. <!-- <el-form-item label="订单类型" prop="orderType">
  102. <el-select v-model="queryParams.orderType" placeholder="请选择订单类型" clearable size="small" >
  103. <el-option
  104. v-for="item in orderTypeOptions"
  105. :key="item.dictValue"
  106. :label="item.dictLabel"
  107. :value="item.dictValue"
  108. />
  109. </el-select>
  110. </el-form-item>-->
  111. <!-- <el-form-item label="上传凭证" prop="isUpload">
  112. <el-select v-model="queryParams.isUpload" placeholder="请选择" clearable size="small" >
  113. <el-option key="0" label="未上传" value="0" />
  114. <el-option key="1" label="已上传" value="1" />
  115. </el-select>
  116. </el-form-item>-->
  117. <el-form-item label="物流状态" prop="deliveryStatus">
  118. <el-select v-model="queryParams.deliveryStatus" clearable placeholder="请选择物流状态" size="small">
  119. <el-option
  120. v-for="item in deliveryStatusOptions"
  121. :key="item.dictValue"
  122. :label="item.dictLabel"
  123. :value="item.dictValue"
  124. />
  125. </el-select>
  126. </el-form-item>
  127. <el-form-item label="结算状态" prop="deliveryPayStatus">
  128. <el-select v-model="queryParams.deliveryPayStatus" clearable placeholder="请选择物流结算状态"
  129. size="small" style="width: 200px"
  130. >
  131. <el-option
  132. v-for="item in deliveryPayStatusOptions"
  133. :key="item.dictValue"
  134. :label="item.dictLabel"
  135. :value="item.dictValue"
  136. />
  137. </el-select>
  138. </el-form-item>
  139. <el-form-item label="支付方式" prop="payType">
  140. <el-select v-model="queryParams.payType" clearable placeholder="请选择支付方式" size="small"
  141. style="width: 200px"
  142. >
  143. <el-option
  144. v-for="item in payTypeOptions"
  145. :key="item.dictValue"
  146. :label="item.dictLabel"
  147. :value="item.dictValue"
  148. />
  149. </el-select>
  150. </el-form-item>
  151. <el-form-item label="下单时间" prop="createTimeRange">
  152. <el-date-picker
  153. v-model="createTimeRange"
  154. clearable end-placeholder="结束日期"
  155. size="small"
  156. start-placeholder="开始日期"
  157. style="width:205.4px"
  158. type="daterange"
  159. value-format="yyyy-MM-dd"
  160. >
  161. </el-date-picker>
  162. </el-form-item>
  163. <el-form-item label="支付时间" prop="payTimeRange">
  164. <el-date-picker
  165. v-model="payTimeRange"
  166. clearable end-placeholder="结束日期"
  167. size="small"
  168. start-placeholder="开始日期"
  169. style="width:205.4px"
  170. type="daterange"
  171. value-format="yyyy-MM-dd"
  172. >
  173. </el-date-picker>
  174. </el-form-item>
  175. <el-form-item label="发货时间" prop="deliverySendTimeRange">
  176. <el-date-picker
  177. v-model="deliverySendTimeRange"
  178. clearable end-placeholder="结束日期"
  179. size="small"
  180. start-placeholder="开始日期"
  181. style="width:205.4px"
  182. type="daterange"
  183. value-format="yyyy-MM-dd"
  184. >
  185. </el-date-picker>
  186. </el-form-item>
  187. <el-form-item label="回单时间" prop="deliveryImportTimeRange">
  188. <el-date-picker
  189. v-model="deliveryImportTimeRange"
  190. clearable end-placeholder="结束日期"
  191. size="small"
  192. start-placeholder="开始日期"
  193. style="width:205.4px"
  194. type="daterange"
  195. value-format="yyyy-MM-dd"
  196. >
  197. </el-date-picker>
  198. </el-form-item>
  199. <el-form-item label="小程序" prop="coursePlaySourceConfigId">
  200. <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
  201. <el-option
  202. v-for="dict in appMallOptions"
  203. :key="dict.id"
  204. :label="dict.name + '(' + dict.appid + ')'"
  205. :value="dict.id"
  206. />
  207. </el-select>
  208. </el-form-item>
  209. <el-form-item label="代服账户" prop="erpAccount" v-if="SFDFopen">
  210. <el-select v-model="queryParams.erpAccount" style="width: 215px" placeholder="ERP账户" clearable size="small">
  211. <el-option
  212. v-for="dict in erpAccountQueryList"
  213. :key="dict"
  214. :label="dict"
  215. :value="dict"
  216. />
  217. </el-select>
  218. </el-form-item>
  219. <el-form-item label="代服电话" prop="erpPhoneNumber" v-if="SFDFopen">
  220. <el-input
  221. v-model="queryParams.erpPhoneNumber"
  222. placeholder="ERP电话"
  223. clearable
  224. size="small"
  225. @keyup.enter.native="handleQuery"
  226. />
  227. </el-form-item>
  228. <el-form-item>
  229. <el-button icon="el-icon-search" size="mini" type="cyan" @click="handleQuery">搜索</el-button>
  230. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  231. </el-form-item>
  232. </el-form>
  233. <el-row :gutter="10" class="mb8">
  234. <!-- <el-col :span="1.5">
  235. <el-button
  236. type="primary"
  237. icon="el-icon-plus"
  238. size="mini"
  239. @click="handleAdd"
  240. v-hasPermi="['store:storeOrder:add']"
  241. >创建订单</el-button>
  242. </el-col> -->
  243. <el-col :span="1.5">
  244. <el-button v-hasPermi="['store:storeOrder:importExpress']" icon="el-icon-upload2" plain size="mini" type="info"
  245. @click="handleImport"
  246. >导入银行回单
  247. </el-button>
  248. </el-col>
  249. <el-col :span="1.5">
  250. <el-button
  251. v-hasPermi="['store:healthStoreOrder:export']"
  252. icon="el-icon-download"
  253. size="mini"
  254. type="warning"
  255. @click="handleExport"
  256. >导出订单
  257. </el-button>
  258. </el-col>
  259. <el-col :span="1.5">
  260. <el-button
  261. v-hasPermi="['store:healthStoreOrder:exportItems']"
  262. icon="el-icon-download"
  263. size="mini"
  264. type="warning"
  265. @click="handleExportItems"
  266. >导出订单明细
  267. </el-button>
  268. </el-col>
  269. <el-col :span="1.5">
  270. <el-button
  271. v-hasPermi="['store:healthStoreOrder:export:details']"
  272. icon="el-icon-download"
  273. size="mini"
  274. type="warning"
  275. @click="handleExportDetails"
  276. >导出订单(明文)
  277. </el-button>
  278. </el-col>
  279. <el-col :span="1.5">
  280. <el-button
  281. v-hasPermi="['store:healthStoreOrder:exportItems:details']"
  282. icon="el-icon-download"
  283. size="mini"
  284. type="warning"
  285. @click="handleExportItemsDetails"
  286. >导出订单明细(明文)
  287. </el-button>
  288. </el-col>
  289. <el-col :span="1.5">
  290. <el-button
  291. icon="el-icon-s-order"
  292. size="mini"
  293. type="warning"
  294. @click="openDeliveryNote"
  295. >批量导入物流单号
  296. </el-button>
  297. </el-col>
  298. <el-col :span="1.5">
  299. <el-button
  300. type="danger"
  301. plain
  302. icon="el-icon-delete"
  303. size="mini"
  304. :disabled="multiple"
  305. @click="handleOrderDelete"
  306. v-hasPermi="['store:storeOrder:remove']"
  307. >删除
  308. </el-button>
  309. </el-col>
  310. <el-col :span="1.5" v-if="SFDFopen && orderStatus == 6"> <!--待推送erp-->
  311. <el-tooltip content="默认erp推送手机号" placement="top">
  312. <el-button
  313. type="warning"
  314. plain
  315. icon="el-icon-phone"
  316. size="mini"
  317. @click="handleErpPhone"
  318. v-hasPermi="['store:storeOrder:erpphone']"
  319. >推送手机号码</el-button>
  320. </el-tooltip>
  321. </el-col>
  322. <el-col :span="1.5" v-if="SFDFopen && orderStatus == 6">
  323. <el-tooltip content="批量设置erp推送手机号" placement="top">
  324. <el-button
  325. type="warning"
  326. plain
  327. icon="el-icon-phone"
  328. size="mini"
  329. @click="setErpPhone"
  330. v-hasPermi="['his:storeOrder:createErpOrder']"
  331. >设置推送手机</el-button>
  332. </el-tooltip>
  333. </el-col>
  334. <el-col :span="1.5" v-if="SFDFopen && orderStatus == 6">
  335. <el-tooltip content="批量设置erp账户" placement="top">
  336. <el-button
  337. type="warning"
  338. plain
  339. icon="el-icon-s-cooperation"
  340. size="mini"
  341. @click="showErpAccountSetDialog"
  342. v-hasPermi="['his:storeOrder:createErpOrder']"
  343. >数据分捡</el-button>
  344. </el-tooltip>
  345. </el-col>
  346. <el-col :span="1.5" v-if="SFDFopen && orderStatus == 6">
  347. <el-tooltip content="批量推送erp" placement="top">
  348. <el-button
  349. type="warning"
  350. plain
  351. icon="el-icon-s-cooperation"
  352. size="mini"
  353. @click="showErpAccountDialog"
  354. v-hasPermi="['his:storeOrder:createErpOrder']"
  355. >创建erp</el-button>
  356. </el-tooltip>
  357. </el-col>
  358. <el-col :span="1.5">
  359. <el-button
  360. disabled
  361. plain
  362. type="primary"
  363. size="mini"
  364. >应付金额: {{ payPriceTotal}}</el-button>
  365. </el-col>
  366. <el-col :span="1.5">
  367. <el-button
  368. disabled
  369. plain
  370. type="primary"
  371. size="mini"
  372. >实付金额: {{payMoneyTotal}}</el-button>
  373. </el-col>
  374. <el-col :span="1.5">
  375. <el-button
  376. disabled
  377. plain
  378. type="primary"
  379. size="mini"
  380. >物流代收金额: {{payRemainTotal }}</el-button>
  381. </el-col>
  382. <el-col :span="1.5">
  383. <el-button
  384. disabled
  385. plain
  386. type="primary"
  387. size="mini"
  388. >订单量/金额: {{ total }}/{{payPriceTotal }}</el-button>
  389. </el-col>
  390. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  391. </el-row>
  392. <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
  393. <el-tab-pane label="全部订单" name="00"></el-tab-pane>
  394. <el-tab-pane label="待支付" name="0"></el-tab-pane>
  395. <el-tab-pane label="待推送" name="6"></el-tab-pane>
  396. <el-tab-pane label="待发货" name="1"></el-tab-pane>
  397. <el-tab-pane label="待收货" name="2"></el-tab-pane>
  398. <el-tab-pane label="交易完成" name="3"></el-tab-pane>
  399. <el-tab-pane label="退款中" name="-1"></el-tab-pane>
  400. <el-tab-pane label="已退款" name="-2"></el-tab-pane>
  401. <el-tab-pane label="已取消" name="-3"></el-tab-pane>
  402. </el-tabs>
  403. <el-table ref="orderTable" v-loading="loading" :data="storeOrderList" border height="500" @selection-change="handleSelectionChange"
  404. @sort-change="handleSortChange" :default-sort="{prop: 'createTime', order: 'descending'}">
  405. <el-table-column align="center" type="selection" width="55"/>
  406. <el-table-column align="center" label="订单号" prop="orderCode" width="200px"/>
  407. <el-table-column label="ERP电话" align="center" prop="erpPhone" width="120px" v-if="SFDFopen"/>
  408. <el-table-column label="ERP账号" align="center" prop="erpAccount" width="120px" v-if="SFDFopen"/>
  409. <el-table-column label="小程序名称" align="center" prop="miniProgramName"/>
  410. <el-table-column align="center" label="用户昵称" prop="nickname" width="150px">
  411. <template slot-scope="scope">
  412. <span>{{ scope.row.nickname }} </span>
  413. </template>
  414. </el-table-column>
  415. <el-table-column align="center" label="收件人" prop="realName" width="150px">
  416. <template slot-scope="scope">
  417. <span>{{ scope.row.realName }} </span>
  418. </template>
  419. </el-table-column>
  420. <!-- <el-table-column label="商品" align="center" width="300px" >
  421. <template slot-scope="scope">
  422. <div v-for="(item, index) in scope.row.items" class="items" >
  423. <img class="pic" :src="JSON.parse(item.jsonInfo).image" />
  424. <div class="goods-content">
  425. <div class="goods-title">{{ JSON.parse(item.jsonInfo).productName}}</div>
  426. <div class="sku">{{ JSON.parse(item.jsonInfo).sku}}</div>
  427. <div class="price">¥{{JSON.parse(item.jsonInfo).price}}×{{item.num}}</div>
  428. </div>
  429. </div>
  430. </template>
  431. </el-table-column> -->
  432. <el-table-column align="center" label="订单金额" prop="totalPrice">
  433. <template slot-scope="scope">
  434. <span v-if="scope.row.totalPrice!=null">{{ scope.row.totalPrice.toFixed(2) }}</span>
  435. </template>
  436. </el-table-column>
  437. <el-table-column label="应付金额" align="center" prop="payPrice" width="100px" sortable="custom" :sort-orders="['ascending', 'descending']">
  438. <template slot="header" slot-scope="scope">
  439. <span >应收金额</span>
  440. <el-tooltip content="按应收金额排序" placement="top"/>
  441. </template>
  442. </el-table-column>
  443. <el-table-column align="center" label="下单时间" prop="createTime"/>
  444. <!-- <el-table-column label="支付状态" align="center" prop="paid" /> -->
  445. <el-table-column align="center" label="支付时间" prop="payTime" width="180">
  446. </el-table-column>
  447. <el-table-column align="center" label="发货时间" prop="deliverySendTime"/>
  448. <el-table-column align="center" label="支付方式" prop="payType">
  449. <template slot-scope="scope">
  450. <el-tag v-for="(item, index) in payTypeOptions" v-if="scope.row.payType==item.dictValue" prop="payType">
  451. {{ item.dictLabel }}
  452. </el-tag>
  453. </template>
  454. </el-table-column>
  455. <!-- <el-table-column label="订单类型" align="center" prop="orderType" >
  456. <template slot-scope="scope">
  457. <el-tag prop="status" v-for="(item, index) in orderTypeOptions" v-if="scope.row.orderType==item.dictValue">{{item.dictLabel}}</el-tag>
  458. </template>
  459. </el-table-column>-->
  460. <el-table-column align="center" label="状态" prop="status">
  461. <template slot-scope="scope">
  462. <el-tag v-for="(item, index) in statusOptions" v-if="scope.row.status==item.dictValue" prop="status">
  463. {{ item.dictLabel }}
  464. </el-tag>
  465. </template>
  466. </el-table-column>
  467. <el-table-column align="center" label="物流状态" prop="deliveryStatus">
  468. <template slot-scope="scope">
  469. <el-tag v-for="(item, index) in deliveryStatusOptions" v-if="scope.row.deliveryStatus==item.dictValue"
  470. prop="status"
  471. >{{ item.dictLabel }}
  472. </el-tag>
  473. </template>
  474. </el-table-column>
  475. <el-table-column align="center" label="物流结算状态" prop="deliveryPayStatus">
  476. <template slot-scope="scope">
  477. <el-tag v-for="(item, index) in deliveryPayStatusOptions" v-if="scope.row.deliveryPayStatus==item.dictValue"
  478. prop="status"
  479. >{{ item.dictLabel }}
  480. </el-tag>
  481. </template>
  482. </el-table-column>
  483. <el-table-column align="center" fixed="right" label="操作" width="80px">
  484. <template slot-scope="scope">
  485. <el-button
  486. v-hasPermi="['store:storeOrder:query']"
  487. size="mini"
  488. type="text"
  489. @click="handleDetails(scope.row)"
  490. >查看
  491. </el-button>
  492. <!-- <el-button
  493. size="mini"
  494. type="text"
  495. @click="handleGenPayUrl(scope.row)"
  496. v-hasPermi="['store:storeOrder:genPayUrl']"
  497. >生成付款链接</el-button> -->
  498. </template>
  499. </el-table-column>
  500. </el-table>
  501. <div>
  502. 商品数量合计:{{ productInfo }}
  503. </div>
  504. <!-- 排序状态显示 -->
  505. <div v-if="currentSort.prop" class="sort-info">
  506. <el-tag size="small" type="info" closable @close="clearSort">
  507. <i class="el-icon-sort"></i>
  508. 当前排序:{{ getSortLabel(currentSort.prop) }}
  509. {{ currentSort.order === 'ascending' ? '升序' : '降序' }}
  510. </el-tag>
  511. <el-button
  512. type="text"
  513. size="mini"
  514. @click="clearSort"
  515. style="margin-left: 8px; color: #909399;"
  516. >
  517. </el-button>
  518. </div>
  519. <pagination
  520. v-show="total>0"
  521. :limit.sync="queryParams.pageSize"
  522. :page.sync="queryParams.pageNum"
  523. :total="total"
  524. @pagination="getList"
  525. />
  526. <el-drawer
  527. :title="show.title"
  528. :visible.sync="show.open" size="75%"
  529. >
  530. <product-order ref="order"/>
  531. </el-drawer>
  532. <el-dialog v-if="open" :title="title" :visible.sync="open" append-to-body width="1000px">
  533. <el-form ref="form" :model="form" :rules="rules" label-width="120px">
  534. <el-form-item label="会员信息" prop="userId">
  535. <el-row>
  536. <el-col>
  537. <el-input v-model="phone" placeholder="请输入会员手机号" style="width:240px;cursor:pointer">
  538. </el-input>
  539. <el-button plain style="margin-left:10px;" @click="searchUser()">查询</el-button>
  540. <el-button icon="el-icon-plus" plain style="margin-left:10px;" type="primary" @click="handleAddUser()">
  541. 添加会员
  542. </el-button>
  543. </el-col>
  544. </el-row>
  545. <el-table v-loading="userloading" :data="users" border style="margin-top:5px;">
  546. <el-table-column align="center" label="ID" prop="userId"/>
  547. <el-table-column align="center" label="会员头像" width="80">
  548. <template slot-scope="scope">
  549. <el-popover
  550. placement="right"
  551. title=""
  552. trigger="hover"
  553. >
  554. <img slot="reference" :src="scope.row.avatar" width="50">
  555. <img :src="scope.row.avatar" style="max-width: 120px;">
  556. </el-popover>
  557. </template>
  558. </el-table-column>
  559. <el-table-column align="center" label="昵称" prop="nickname"/>
  560. <el-table-column align="center" label="手机号" prop="phone"/>
  561. <el-table-column align="center" label="状态" prop="status">
  562. <template slot-scope="scope">
  563. <el-tag v-for="(item, index) in userStatusOptions" v-if="scope.row.status==item.dictValue"
  564. prop="status"
  565. >{{ item.dictLabel }}
  566. </el-tag>
  567. </template>
  568. </el-table-column>
  569. </el-table>
  570. </el-form-item>
  571. <el-form-item label="收货信息" prop="addressId">
  572. <el-row>
  573. <el-col>
  574. <el-button icon="el-icon-plus" plain type="primary" @click="handleAddUserAddress()">添加收货地址
  575. </el-button>
  576. </el-col>
  577. </el-row>
  578. <el-radio-group v-model="form.addressId" style="width:100%">
  579. <el-table v-loading="addressloading" :data="address" border style="margin-top:5px;">
  580. <el-table-column align="center" label="ID">
  581. <template slot-scope="scope">
  582. <el-radio :label="scope.row.id"></el-radio>
  583. </template>
  584. </el-table-column>
  585. <el-table-column align="center" label="收货人姓名" prop="realName"/>
  586. <el-table-column align="center" label="收货人电话" prop="phone"/>
  587. <el-table-column align="center" label="地址" prop="detail">
  588. <template slot-scope="scope">
  589. {{ scope.row.province }} {{ scope.row.city }} {{ scope.row.district }} {{ scope.row.detail }}
  590. </template>
  591. </el-table-column>
  592. </el-table>
  593. </el-radio-group>
  594. </el-form-item>
  595. <el-form-item label="商品列表">
  596. <el-row>
  597. <el-col>
  598. <el-button icon="el-icon-plus" plain type="primary" @click="handleAddProduct">添加商品</el-button>
  599. </el-col>
  600. </el-row>
  601. <el-table :key="tablekey" :data="products" border style="margin-top:5px;" width="100%">
  602. <el-table-column align="center" label="商品编号" prop="barCode"/>
  603. <el-table-column align="center" label="商品图片" width="100">
  604. <template slot-scope="scope">
  605. <el-popover
  606. placement="right"
  607. title=""
  608. trigger="hover"
  609. >
  610. <img slot="reference" :src="scope.row.image" width="50">
  611. <img :src="scope.row.image" style="max-width: 50px;">
  612. </el-popover>
  613. </template>
  614. </el-table-column>
  615. <el-table-column align="center" label="商品名称" prop="productName" show-overflow-tooltip/>
  616. <el-table-column align="center" label="商品规格" prop="sku"/>
  617. <el-table-column align="center" label="库存" prop="stock"/>
  618. <el-table-column align="center" label="单价" prop="price"/>
  619. <el-table-column :key="tablekey" align="center" label="数量" prop="count" width="200px">
  620. <template slot-scope="scope">
  621. <div>
  622. <el-input-number v-model="scope.row.count" :max="scope.row.stock" :min="1"
  623. size="mini" @change="handleProductCountChange(scope.row)"
  624. ></el-input-number>
  625. </div>
  626. </template>
  627. </el-table-column>
  628. <el-table-column align="center" label="小计" prop="money"/>
  629. <el-table-column align="center" label="操作" width="100px">
  630. <template slot-scope="scope">
  631. <el-button
  632. icon="el-icon-delete"
  633. size="mini"
  634. type="text"
  635. @click="handleDelete(scope.row)"
  636. >删除
  637. </el-button>
  638. </template>
  639. </el-table-column>
  640. </el-table>
  641. <el-row>
  642. <el-col>
  643. <span>商品合计:{{ products.length }}</span><span style="margin-left:10px;"
  644. >商品总价:{{ totalMoney.toFixed(2) }}</span>
  645. </el-col>
  646. </el-row>
  647. </el-form-item>
  648. <el-form-item label="订单备注" prop="mark">
  649. <el-input v-model="form.mark" placeholder="" rows="2" type="textarea"/>
  650. </el-form-item>
  651. </el-form>
  652. <div slot="footer" class="dialog-footer">
  653. <el-button type="primary" @click="submitForm">确 定</el-button>
  654. <el-button @click="cancel">取 消</el-button>
  655. </div>
  656. </el-dialog>
  657. <el-dialog v-if="product.open" :title="product.title" :visible.sync="product.open" append-to-body width="1000px">
  658. <product-select @selectProduct="selectProduct"/>
  659. </el-dialog>
  660. <el-dialog v-if="user.open" :title="user.title" :visible.sync="user.open" append-to-body width="500px">
  661. <add-user @addUser="addUser"/>
  662. </el-dialog>
  663. <el-dialog v-if="userAddress.open" :title="userAddress.title" :visible.sync="userAddress.open" append-to-body
  664. width="800px"
  665. >
  666. <add-user-address ref="addUserAddress" @addUserAddress="addUserAddress"/>
  667. </el-dialog>
  668. <el-dialog v-if="payQr.open" :title="payQr.title" :visible.sync="payQr.open" append-to-body width="240px">
  669. <div style="padding-bottom:15px;">
  670. <div ref="qrCodeUrl" class="qrcode"></div>
  671. </div>
  672. </el-dialog>
  673. <el-dialog :title="upload.title" :visible.sync="upload.open" append-to-body width="400px">
  674. <el-upload ref="upload" :action="upload.url + '?updateSupport=' + upload.updateSupport" :auto-upload="false" :disabled="upload.isUploading"
  675. :headers="upload.headers" :limit="1"
  676. :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" accept=".xlsx, .xls" drag
  677. >
  678. <i class="el-icon-upload"></i>
  679. <div class="el-upload__text">
  680. 将文件拖到此处,或
  681. <em>点击上传</em>
  682. </div>
  683. <div slot="tip" class="el-upload__tip">
  684. <!-- <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的数据 -->
  685. <el-link style="font-size:12px" type="info" @click="importTemplate">下载模板</el-link>
  686. </div>
  687. <div slot="tip" class="el-upload__tip" style="color:red">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
  688. </el-upload>
  689. <div slot="footer" class="dialog-footer">
  690. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  691. <el-button @click="upload.open = false">取 消</el-button>
  692. </div>
  693. </el-dialog>
  694. <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" :visible.sync="importMsgOpen"
  695. append-to-body title="导入结果" width="500px"
  696. >
  697. <h1>{{importMsg}}</h1>
  698. </el-dialog>
  699. <!-- 批量发货 -->
  700. <el-dialog
  701. :before-close="handleClose"
  702. :visible.sync="deliveryNoteOpen"
  703. center
  704. title="批量发货"
  705. width="35%"
  706. >
  707. <span slot="footer" class="dialog-footer">
  708. <!-- 小程序Appid选择 -->
  709. <!-- <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">-->
  710. <!-- <el-form-item label="小程序:" prop="miniAppId">-->
  711. <!-- <el-select-->
  712. <!-- v-model="ruleForm.miniAppId"-->
  713. <!-- clearable-->
  714. <!-- placeholder="请选择发货小程序"-->
  715. <!-- style="width: 100%"-->
  716. <!-- >-->
  717. <!-- <el-option-->
  718. <!-- v-for="item in miniAppList"-->
  719. <!-- :key="item.appId"-->
  720. <!-- :label="item.appName"-->
  721. <!-- :value="item.appId"-->
  722. <!-- />-->
  723. <!-- </el-select>-->
  724. <!-- </el-form-item>-->
  725. <!-- </el-form>-->
  726. <el-upload ref="upload" :action="orderUpload.url" :auto-upload="false" :disabled="orderUpload.isUploading" :headers="orderUpload.headers"
  727. :limit="1" :on-progress="handleFileUploadProgress"
  728. :on-success="handleFileSuccess" accept=".xlsx, .xls" drag
  729. >
  730. <i class="el-icon-upload"></i>
  731. <div class="el-upload__text">
  732. 将文件拖到此处,或
  733. <em>点击上传</em>
  734. </div>
  735. <div slot="tip" class="el-upload__tip">
  736. <el-link style="font-size:12px" type="info" @click="importDeliveryNoteTemplate">下载模板</el-link>
  737. </div>
  738. <div slot="tip" class="el-upload__tip" style="color:red">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
  739. </el-upload>
  740. <el-divider></el-divider>
  741. <el-button @click="deliveryNoteOpen = false">取 消</el-button>
  742. <el-button type="primary" @click="submitDeliveryNote">确 定</el-button>
  743. </span>
  744. </el-dialog>
  745. <!-- 设置推送手机对话框 -->
  746. <el-dialog :title="erpPhone.title" :visible.sync="erpPhone.open" width="600px" append-to-body>
  747. <div style="margin-bottom: 20px;">
  748. <el-button type="primary" size="small" @click="handleAddPhone">新增手机号</el-button>
  749. </div>
  750. <el-table :data="phoneList" border style="width: 100%">
  751. <el-table-column prop="phone" label="手机号" align="center">
  752. <template slot-scope="scope">
  753. <el-input
  754. v-if="scope.row.editing"
  755. v-model="scope.row.phone"
  756. placeholder="请输入手机号"
  757. @blur="validatePhone(scope.row)"
  758. @keyup.enter.native="handleSavePhone(scope.$index)"
  759. />
  760. <span v-else>{{ scope.row.phone }}</span>
  761. </template>
  762. </el-table-column>
  763. <el-table-column label="操作" align="center" width="300">
  764. <template slot-scope="scope">
  765. <el-button
  766. v-if="scope.row.editing"
  767. type="success"
  768. size="mini"
  769. @click="handleSavePhone(scope.$index)"
  770. >保存</el-button>
  771. <el-button
  772. v-if="scope.row.editing"
  773. type="info"
  774. size="mini"
  775. @click="handleCancelEdit(scope.$index)"
  776. >取消</el-button>
  777. <el-button
  778. v-if="!scope.row.editing"
  779. type="primary"
  780. size="mini"
  781. @click="handleEditPhone(scope.$index)"
  782. >修改</el-button>
  783. <el-button
  784. type="danger"
  785. size="mini"
  786. @click="handleDeletePhone(scope.$index)"
  787. >删除</el-button>
  788. </template>
  789. </el-table-column>
  790. </el-table>
  791. <div slot="footer" class="dialog-footer">
  792. <el-button type="primary" @click="handleSavePhoneList">确 定</el-button>
  793. <el-button @click="handleCancelPhoneDialog">取 消</el-button>
  794. </div>
  795. </el-dialog>
  796. <el-dialog :title="erpPhone.title" :visible.sync="setPhoneOpen" width="600px" append-to-body>
  797. <el-select v-model="erpPhoneValue" multiple placeholder="请选择">
  798. <el-option
  799. v-for="item in phoneList"
  800. :key="item.phone"
  801. :label="item.phone"
  802. :value="item.phone">
  803. </el-option>
  804. </el-select>
  805. <div slot="footer" class="dialog-footer">
  806. <el-button type="primary" @click="submitErpPhone">确 定</el-button>
  807. <el-button @click="handleCancelErpPhone">取 消</el-button>
  808. </div>
  809. </el-dialog>
  810. <!-- ERP账户选择对话框 -->
  811. <el-dialog :title="erpAccountDialog.title" :visible.sync="erpAccountDialog.open" width="600px" append-to-body>
  812. <div v-loading="erpAccountDialog.loading">
  813. <el-form :model="erpAccountForm" label-width="100px">
  814. <el-form-item label="ERP账户" required>
  815. <el-select
  816. v-model="erpAccountForm.selectedAccount"
  817. placeholder="请选择ERP账户"
  818. style="width: 100%"
  819. filterable
  820. >
  821. <el-option
  822. v-for="account in erpAccountList"
  823. :key="account"
  824. :label="account"
  825. :value="account"
  826. >
  827. <span style="float: left">{{ account}}</span>
  828. <span style="float: right; color: #8492a6; font-size: 13px">{{ account.accountCode }}</span>
  829. </el-option>
  830. </el-select>
  831. </el-form-item>
  832. </el-form>
  833. <!-- 订单统计信息 -->
  834. <div class="order-summary" v-if="orderSummary">
  835. <el-divider content-position="left">订单统计</el-divider>
  836. <el-row :gutter="20">
  837. <el-col :span="8">
  838. <div class="summary-item">
  839. <span class="label">选中订单数:</span>
  840. <span class="value">{{ orderSummary.selectedCount }}</span>
  841. </div>
  842. </el-col>
  843. <el-col :span="8">
  844. <div class="summary-item">
  845. <span class="label">总金额:</span>
  846. <span class="value">¥{{ orderSummary.totalAmount }}</span>
  847. </div>
  848. </el-col>
  849. <el-col :span="8">
  850. <div class="summary-item">
  851. <span class="label">查询条件订单:</span>
  852. <span class="value">{{ orderSummary.queryCount }}</span>
  853. </div>
  854. </el-col>
  855. </el-row>
  856. </div>
  857. </div>
  858. <div slot="footer" class="dialog-footer">
  859. <el-button @click="cancelErpAccountDialog">取 消</el-button>
  860. <el-button
  861. type="primary"
  862. @click="confirmCreateErpOrder"
  863. :disabled="!erpAccountForm.selectedAccount"
  864. :loading="erpAccountDialog.submitting"
  865. >确认</el-button>
  866. </div>
  867. </el-dialog>
  868. <!-- 导出字段选择对话框 -->
  869. <el-dialog :title="exportFieldDialog.title" :visible.sync="exportFieldDialog.open" width="800px" append-to-body>
  870. <div v-loading="exportFieldDialog.loading">
  871. <div style="margin-bottom: 20px;">
  872. <el-button type="primary" size="small" @click="selectAllFields">全选</el-button>
  873. <el-button type="default" size="small" @click="unselectAllFields">全不选</el-button>
  874. <el-button type="success" size="small" @click="selectDefaultFields">选择常用</el-button>
  875. </div>
  876. <div class="field-selection-container">
  877. <el-row :gutter="20">
  878. <el-col :span="8" v-for="field in exportFieldOptions" :key="field.key">
  879. <el-checkbox
  880. v-model="field.checked"
  881. :label="field.label"
  882. style="margin-bottom: 12px; width: 100%;"
  883. >
  884. {{ field.label }}
  885. </el-checkbox>
  886. </el-col>
  887. </el-row>
  888. </div>
  889. <div class="field-count-info" style="margin-top: 20px; padding: 10px; background: #f5f7fa; border-radius: 4px;">
  890. <i class="el-icon-info"></i>
  891. <span v-if="getSelectedFieldsCount() > 0">
  892. 已选择 <span style="color: #409EFF; font-weight: bold;">{{ getSelectedFieldsCount() }}</span> 个字段
  893. </span>
  894. <span v-else style="color: #E6A23C; font-weight: bold;">
  895. <i class="el-icon-warning"></i>
  896. 未选择任何字段,将导出所有字段
  897. </span>
  898. </div>
  899. </div>
  900. <div slot="footer" class="dialog-footer">
  901. <el-button @click="cancelExportFieldDialog">取 消</el-button>
  902. <el-button
  903. type="primary"
  904. @click="confirmExportFields"
  905. >确认导出</el-button>
  906. </div>
  907. </el-dialog>
  908. </div>
  909. </template>
  910. <script>
  911. import {
  912. importDeliveryNoteExpressTemplate,
  913. importTemplate,
  914. exportHealthStoreOrderItems,
  915. createUserOrder,
  916. listHealthStoreOrder,
  917. getStoreOrder,
  918. delStoreOrder,
  919. exportHealthStoreOrder, exportHealthStoreOrderDetails, exportHealthStoreOrderItemsDetails,getErpAccount,
  920. queryErpPhone,
  921. saveErpPhone,editErpPhone,batchCreateErpOrder,batchSetErpOrder
  922. } from '@/api/live/liveOrder'
  923. import { getUserList } from '@/api/hisStore/user'
  924. import { getAddressList } from '@/api/hisStore/userAddress'
  925. import productOrder from '@/views/hisStore/components/productOrder'
  926. import productSelect from '@/views/hisStore/components/productSelect'
  927. import addUser from '@/views/hisStore/components/addUser'
  928. import addUserAddress from '@/views/hisStore/components/addUserAddress'
  929. import { getToken } from '@/utils/auth'
  930. import QRCode from 'qrcodejs2'
  931. import { getCompanyList } from '@/api/company/company'
  932. import { treeselect } from '@/api/company/companyDept'
  933. import Treeselect from '@riophae/vue-treeselect'
  934. import '@riophae/vue-treeselect/dist/vue-treeselect.css'
  935. import { getConfigByKey } from '@/api/system/config'
  936. import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
  937. export default {
  938. components: { productOrder, productSelect, addUser, addUserAddress, Treeselect },
  939. name: 'HisHealthStoreOrderList',
  940. watch: {
  941. // 监听deptId
  942. 'deptId': 'currDeptChange'
  943. },
  944. data() {
  945. return {
  946. orderStatus:null,
  947. productInfo:"",
  948. payPriceTotal:"0",
  949. payMoneyTotal:"0",
  950. payRemainTotal:"0",
  951. // 新增排序相关数据
  952. currentSort: {
  953. prop: null,
  954. order: null
  955. },
  956. // 排序字段映射
  957. sortFieldMap: {
  958. 'companyUserName': '员工',
  959. 'packageName': '套餐名称',
  960. 'payPrice': '应收金额',
  961. 'payMoney': '实收金额',
  962. 'createTime': '下单时间'
  963. },
  964. erpSettingType:'set',
  965. SFDFopen:false,
  966. // 最大订单号数量限制
  967. maxOrderCodes: {
  968. type: Number,
  969. default: 50
  970. },
  971. // 输入框是否可见
  972. inputVisible: false,
  973. // 无效订单号对话框
  974. showInvalidDialog: false,
  975. // 当前输入值
  976. currentInput: '',
  977. deptOpen:true,
  978. // ERP账户相关数据
  979. erpAccountDialog: {
  980. open: false,
  981. title: "选择ERP账户",
  982. loading: false,
  983. submitting: false
  984. },
  985. erpAccountList: [], // ERP账户列表
  986. erpAccountQueryList:[], // ERP账户查询条件列表
  987. erpAccountForm: {
  988. selectedAccount: [] // 选中的账户ID
  989. },
  990. orderSummary: null, // 订单统计信息
  991. erpPhoneValue:[],
  992. setPhoneOpen:false,
  993. erpPhone:{
  994. open:false,
  995. title:"设置推送手机号"
  996. },
  997. phoneList: [], // 手机号列表
  998. originalPhoneList: [], // 原始手机号列表,用于取消时恢复
  999. exportFieldDialog: {
  1000. open: false,
  1001. title: "选择导出字段",
  1002. loading: false,
  1003. type:null
  1004. },
  1005. // 可选择的导出字段列表
  1006. exportFieldOptions: [
  1007. { key: 'orderCode', label: '订单号', checked: true },
  1008. { key: 'miniProgramName', label: '小程序名称', checked: true },
  1009. { key: 'patientName', label: '就诊人', checked: true },
  1010. { key: 'productName', label: '编号', checked: true },
  1011. { key: 'barCode', label: '药品信息', checked: false },
  1012. { key: 'payMoney', label: '实收金额', checked: true },
  1013. { key: 'payRemain', label: '物流代收金额', checked: false },
  1014. { key: 'payType', label: '支付方式', checked: true },
  1015. { key: 'createTime', label: '下单时间', checked: true },
  1016. { key: 'payTime', label: '支付时间', checked: true },
  1017. { key: 'status', label: '订单状态', checked: true },
  1018. { key: 'userName', label: '收货人姓名', checked: true },
  1019. { key: 'userPhone', label: '收货人电话', checked: true },
  1020. { key: 'userAddress', label: '详细地址', checked: true },
  1021. { key: 'deliveryCode', label: '快递公司编号', checked: false },
  1022. { key: 'deliveryName', label: '快递公司', checked: false },
  1023. { key: 'deliverySn', label: '快递单号', checked: false },
  1024. { key: 'remark', label: '备注', checked: false },
  1025. { key: 'erpPhone', label: 'ERP电话', checked: false },
  1026. { key: 'erpAccount', label: 'ERP账号', checked: false },
  1027. ],
  1028. appMallOptions:[],
  1029. importMsgOpen: false,
  1030. importMsg: '',
  1031. deliveryPayStatusOptions: [],
  1032. deliveryStatusOptions: [],
  1033. companys: [],
  1034. deptOptions: [],
  1035. companyId: undefined,
  1036. deptId: undefined,
  1037. orderTypeOptions: [],
  1038. payTypeOptions: [],
  1039. payQr: {
  1040. open: false,
  1041. title: '付款二维码'
  1042. },
  1043. user: {
  1044. open: false,
  1045. title: '创建会员'
  1046. },
  1047. userAddress: {
  1048. open: false,
  1049. title: '创建收货地址'
  1050. },
  1051. tablekey: false,
  1052. totalMoney: 0.00,
  1053. products: [],
  1054. product: {
  1055. open: false,
  1056. title: '商品选择'
  1057. },
  1058. userStatusOptions: [],
  1059. phone: null,
  1060. address: [],
  1061. addressloading: false,
  1062. userloading: false,
  1063. users: [],
  1064. show: {
  1065. open: false,
  1066. title: '订单详情'
  1067. },
  1068. activeName: '00',
  1069. statusOptions: [],
  1070. // 遮罩层
  1071. loading: true,
  1072. // 选中数组
  1073. ids: [],
  1074. // 非单个禁用
  1075. single: true,
  1076. // 非多个禁用
  1077. multiple: true,
  1078. // 显示搜索条件
  1079. showSearch: true,
  1080. // 总条数
  1081. total: 0,
  1082. // 订单表格数据
  1083. storeOrderList: [],
  1084. // 弹出层标题
  1085. title: '',
  1086. // 是否显示弹出层
  1087. open: false,
  1088. createTimeRange: [],
  1089. payTimeRange: [],
  1090. deliveryImportTimeRange: [],
  1091. deliverySendTimeRange: [],
  1092. // 查询参数
  1093. queryParams: {
  1094. pageNum: 1,
  1095. pageSize: 10,
  1096. orderCode: null,
  1097. orderCodes:[],
  1098. extendOrderId: null,
  1099. userId: null,
  1100. realName: null,
  1101. userPhone: null,
  1102. userAddress: null,
  1103. cartId: null,
  1104. freightPrice: null,
  1105. totalNum: null,
  1106. totalPrice: null,
  1107. totalPostage: null,
  1108. payPrice: null,
  1109. payPostage: null,
  1110. deductionPrice: null,
  1111. couponId: null,
  1112. couponPrice: null,
  1113. paid: null,
  1114. payTime: null,
  1115. payType: null,
  1116. status: null,
  1117. refundStatus: null,
  1118. refundReasonWapImg: null,
  1119. refundReasonWapExplain: null,
  1120. refundReasonTime: null,
  1121. refundReasonWap: null,
  1122. refundReason: null,
  1123. refundPrice: null,
  1124. deliverySn: null,
  1125. deliveryName: null,
  1126. deliveryType: null,
  1127. deliveryId: null,
  1128. gainIntegral: null,
  1129. useIntegral: null,
  1130. payIntegral: null,
  1131. backIntegral: null,
  1132. mark: null,
  1133. isDel: null,
  1134. cost: null,
  1135. verifyCode: null,
  1136. storeId: null,
  1137. shippingType: null,
  1138. isChannel: null,
  1139. isRemind: null,
  1140. isSysDel: null,
  1141. deptId: null
  1142. },
  1143. // 表单参数
  1144. form: {
  1145. addressId: null,
  1146. userId: null
  1147. },
  1148. // 表单校验
  1149. rules: {
  1150. userId: [
  1151. { required: true, message: '会员信息不能为空' }
  1152. ],
  1153. addressId: [
  1154. { required: true, message: '收货信息不能为空' }
  1155. ],
  1156. miniAppId: [
  1157. { required: true, message: '发货小程序不能为空' }
  1158. ],
  1159. },
  1160. upload: {
  1161. // 是否显示弹出层(用户导入)
  1162. open: false,
  1163. // 弹出层标题(用户导入)
  1164. title: '',
  1165. // 是否禁用上传
  1166. isUploading: false,
  1167. // 是否更新已经存在的用户数据
  1168. updateSupport: 0,
  1169. // 设置上传的请求头部
  1170. headers: { Authorization: 'Bearer ' + getToken() },
  1171. // 上传的地址
  1172. url: process.env.VUE_APP_BASE_API + '/store/storeOrder/importExpress'
  1173. },
  1174. orderUpload: {
  1175. // 是否显示弹出层(用户导入)
  1176. open: false,
  1177. // 弹出层标题(用户导入)
  1178. title: '',
  1179. // 是否禁用上传
  1180. isUploading: false,
  1181. // 是否更新已经存在的用户数据
  1182. updateSupport: 0,
  1183. // 设置上传的请求头部
  1184. headers: { Authorization: 'Bearer ' + getToken() },
  1185. // 上传的地址
  1186. url: process.env.VUE_APP_BASE_API + '/store/store/storeOrder/importDeliveryNoteExpress',
  1187. },
  1188. deliveryNoteOpen: false,
  1189. miniAppList: [],
  1190. ruleForm:{
  1191. miniAppId: null,
  1192. },
  1193. }
  1194. },
  1195. created() {
  1196. getCompanyList().then(response => {
  1197. this.companys = response.data
  1198. if (this.companys != null && this.companys.length > 0) {
  1199. this.companyId = this.companys[0].companyId
  1200. this.getTreeselect()
  1201. }
  1202. })
  1203. this.getDicts('store_order_type').then((response) => {
  1204. this.orderTypeOptions = response.data
  1205. })
  1206. this.getDicts('user_status').then((response) => {
  1207. this.userStatusOptions = response.data
  1208. })
  1209. this.getDicts('store_pay_type').then((response) => {
  1210. this.payTypeOptions = response.data
  1211. })
  1212. this.getDicts('store_order_status').then((response) => {
  1213. this.statusOptions = response.data
  1214. })
  1215. this.getDicts('store_order_delivery_status').then((response) => {
  1216. this.deliveryStatusOptions = response.data
  1217. })
  1218. this.getDicts('store_delivery_pay_status').then((response) => {
  1219. this.deliveryPayStatusOptions = response.data
  1220. })
  1221. this.getList()
  1222. this.getErpAccountList();
  1223. this.getAppMallOptions();
  1224. },
  1225. methods: {
  1226. // 新增排序处理方法
  1227. handleSortChange({ column, prop, order }) {
  1228. console.log('排序变化:', { column, prop, order });
  1229. // 更新当前排序状态
  1230. this.currentSort = {
  1231. prop: prop,
  1232. order: order
  1233. };
  1234. // 更新查询参数
  1235. if (order) {
  1236. this.queryParams.sortField = prop;
  1237. this.queryParams.sortOrder = order === 'ascending' ? 'asc' : 'desc';
  1238. } else {
  1239. this.queryParams.sortField = null;
  1240. this.queryParams.sortOrder = null;
  1241. }
  1242. // 重新查询数据
  1243. this.queryParams.pageNum = 1; // 重置到第一页
  1244. this.getList();
  1245. // 显示排序提示
  1246. if (order) {
  1247. const fieldLabel = this.getSortLabel(prop);
  1248. const orderLabel = order === 'ascending' ? '升序' : '降序';
  1249. this.$message.success(`已按${fieldLabel}${orderLabel}排序`);
  1250. }
  1251. },
  1252. // 获取排序字段的中文标签
  1253. getSortLabel(prop) {
  1254. return this.sortFieldMap[prop] || prop;
  1255. },
  1256. // 清除排序
  1257. clearSort() {
  1258. this.currentSort = {
  1259. prop: null,
  1260. order: null
  1261. };
  1262. this.queryParams.sortField = null;
  1263. this.queryParams.sortOrder = null;
  1264. this.queryParams.pageNum = 1;
  1265. // 重置表格排序状态 - 关键代码
  1266. this.$nextTick(() => {
  1267. if (this.$refs.orderTable) {
  1268. this.$refs.orderTable.clearSort();
  1269. }
  1270. });
  1271. this.getList();
  1272. this.$message.success('已清除排序');
  1273. },
  1274. // 处理键盘按下事件
  1275. handleKeyDown(event) {
  1276. const { key, target } = event
  1277. // 处理退格键删除标签
  1278. if (key === 'Backspace' && !target.value && this.queryParams.orderCodes.length > 0) {
  1279. event.preventDefault()
  1280. this.removeOrderCode(this.queryParams.orderCodes.length - 1)
  1281. }
  1282. // 处理分隔符
  1283. if ([',', ',', ' ', 'Enter'].includes(key)) {
  1284. event.preventDefault()
  1285. this.handleInputConfirm()
  1286. }
  1287. },
  1288. // 处理键盘抬起事件(实时分割输入)
  1289. handleKeyUp(event) {
  1290. const value = event.target.value
  1291. // 检查是否包含分隔符
  1292. if (/[,,\s]/.test(value)) {
  1293. this.handleInputConfirm()
  1294. }
  1295. },
  1296. // 确认输入
  1297. handleInputConfirm() {
  1298. const inputValue = this.currentInput.trim()
  1299. if (inputValue) {
  1300. // 分割多个订单号
  1301. const codes = inputValue.split(/[,,\s]+/).filter(code => code.trim())
  1302. codes.forEach(code => {
  1303. this.addOrderCode(code.trim())
  1304. })
  1305. }
  1306. this.currentInput = ''
  1307. },
  1308. // 添加订单号
  1309. addOrderCode(code) {
  1310. if (!code) return
  1311. // 检查数量限制
  1312. if (this.maxOrderCodes > 0 && this.queryParams.orderCodes.length >= this.maxOrderCodes) {
  1313. this.$message.warning(`最多只能添加 ${this.maxOrderCodes} 个订单号`)
  1314. return
  1315. }
  1316. // 检查重复
  1317. if (this.queryParams.orderCodes.includes(code)) {
  1318. this.$message.warning(`订单号 "${code}" 已存在`)
  1319. return
  1320. }
  1321. // 添加到列表
  1322. this.queryParams.orderCodes.push(code)
  1323. },
  1324. // 删除订单号
  1325. removeOrderCode(index) {
  1326. this.queryParams.orderCodes.splice(index, 1)
  1327. },
  1328. // 清空所有标签
  1329. clearAllTags() {
  1330. this.$confirm('确认清空所有订单号吗?', '提示', {
  1331. confirmButtonText: '确定',
  1332. cancelButtonText: '取消',
  1333. type: 'warning'
  1334. }).then(() => {
  1335. this.queryParams.orderCodes = []
  1336. this.$message.success('已清空所有订单号')
  1337. })
  1338. },
  1339. // 显示输入框
  1340. showInput() {
  1341. this.inputVisible = true
  1342. this.$nextTick(() => {
  1343. this.$refs.tagInput.focus()
  1344. })
  1345. },
  1346. // 删除订单号
  1347. removeOrderCode(index) {
  1348. this.queryParams.orderCodes.splice(index, 1)
  1349. },
  1350. // 聚焦输入框
  1351. focusInput() {
  1352. if (!this.inputVisible) {
  1353. this.showInput()
  1354. }
  1355. },
  1356. // 设置erp账户
  1357. showErpAccountSetDialog() {
  1358. this.erpAccountDialog.open = true;
  1359. this.erpSettingType = 'set'
  1360. this.calculateOrderSummary();
  1361. },
  1362. //显示ERP账户选择对话框
  1363. showErpAccountDialog() {
  1364. this.erpAccountDialog.open = true;
  1365. this.erpSettingType = 'push'
  1366. this.calculateOrderSummary();
  1367. },
  1368. //获取ERP账户列表
  1369. async getErpAccountList() {
  1370. try {
  1371. const response = await getErpAccount();
  1372. if (response.code === 200) {
  1373. const list = response.data || [];
  1374. this.erpAccountList = [...list];
  1375. this.erpAccountQueryList = [...list, '未分拣'];
  1376. // 设置默认值:第一条真实账户
  1377. if (list.length && !this.queryParams.erpAccount) {
  1378. this.$set(this.queryParams, 'erpAccount', list[0]);
  1379. this.getList();
  1380. }
  1381. } else {
  1382. this.$message.error(response.msg || '获取ERP账户列表失败');
  1383. this.erpAccountList = [];
  1384. }
  1385. } catch (error) {
  1386. console.error('获取ERP账户列表失败:', error);
  1387. this.$message.error('获取ERP账户列表失败');
  1388. this.erpAccountList = [];
  1389. } finally {
  1390. this.erpAccountDialog.loading = false;
  1391. }
  1392. },
  1393. // 新增:计算订单统计信息
  1394. calculateOrderSummary() {
  1395. let selectedCount = 0;
  1396. let totalAmount = 0;
  1397. let queryCount = this.total || 0;
  1398. if (this.ids.length > 0) {
  1399. // 如果有选中的订单,统计选中的订单
  1400. selectedCount = this.ids.length;
  1401. this.storeOrderList.forEach(order => {
  1402. if (this.ids.includes(order.orderId)) {
  1403. totalAmount += parseFloat(order.payMoney || 0);
  1404. }
  1405. });
  1406. } else {
  1407. // 如果没有选中订单,统计当前查询条件下的所有订单
  1408. selectedCount = queryCount;
  1409. this.storeOrderList.forEach(order => {
  1410. totalAmount += parseFloat(order.payMoney || 0);
  1411. });
  1412. }
  1413. this.orderSummary = {
  1414. selectedCount,
  1415. totalAmount: totalAmount.toFixed(2),
  1416. queryCount
  1417. };
  1418. },
  1419. //确认创建ERP订单
  1420. confirmCreateErpOrder() {
  1421. if (!this.erpAccountForm.selectedAccount) {
  1422. this.$message.warning('请选择ERP账户');
  1423. return;
  1424. }
  1425. console.log("-----------------",this.erpSettingType)
  1426. if(this.erpSettingType == 'set'){
  1427. this.$confirm(
  1428. `确认将订单设置ERP账户为"${this.erpAccountForm.selectedAccount}"吗?`,
  1429. '确认',
  1430. {
  1431. confirmButtonText: '确定',
  1432. cancelButtonText: '取消',
  1433. type: 'warning'
  1434. }
  1435. ).then(() => {
  1436. this.executSetErpOrder();
  1437. });
  1438. } else if(this.erpSettingType == 'push'){
  1439. this.$confirm(
  1440. `确认将订单推送到ERP账户"${this.erpAccountForm.selectedAccount}"吗?`,
  1441. '确认推送',
  1442. {
  1443. confirmButtonText: '确定推送',
  1444. cancelButtonText: '取消',
  1445. type: 'warning'
  1446. }
  1447. ).then(() => {
  1448. this.executeCreateErpOrder();
  1449. });
  1450. }
  1451. },
  1452. async executSetErpOrder() {
  1453. this.erpAccountDialog.submitting = true;
  1454. try {
  1455. let param = {
  1456. loginAccount: this.erpAccountForm.selectedAccount
  1457. };
  1458. if (this.ids.length > 0) {
  1459. // 如果有选中的订单,只推送选中的
  1460. param.orderIds = this.ids;
  1461. } else {
  1462. // 如果没有选中订单,推送查询条件下的所有订单
  1463. if (this.payTypeArr.length > 0) {
  1464. this.queryParams.payType = this.payTypeArr.toString();
  1465. } else {
  1466. this.queryParams.payType = null;
  1467. }
  1468. if (this.scheduleIdArr.length > 0) {
  1469. this.queryParams.scheduleId = this.scheduleIdArr.toString();
  1470. } else {
  1471. this.queryParams.scheduleId = null;
  1472. }
  1473. if (this.buyTypeArr.length > 0) {
  1474. this.queryParams.orderBuyType = this.buyTypeArr.toString();
  1475. } else {
  1476. this.queryParams.orderBuyType = null;
  1477. }
  1478. if (this.channelArr.length > 0) {
  1479. this.queryParams.orderChannel = this.channelArr.toString();
  1480. } else {
  1481. this.queryParams.orderChannel = null;
  1482. }
  1483. if (this.qwSubjectArr.length > 0) {
  1484. this.queryParams.qwSubject = this.qwSubjectArr.toString();
  1485. } else {
  1486. this.queryParams.qwSubject = null;
  1487. }
  1488. // 合并查询参数
  1489. param = { ...param, ...this.queryParams };
  1490. }
  1491. const response = await batchSetErpOrder(param);
  1492. if (response.code === 200) {
  1493. this.$message.success('订单ERP账号设置成功');
  1494. this.cancelErpAccountDialog();
  1495. this.getErpAccountList(); // 刷新列表
  1496. this.getList();
  1497. } else {
  1498. this.$message.error(response.msg || 'ERP账号设置失败');
  1499. }
  1500. } catch (error) {
  1501. console.error('ERP账号设置失败:', error);
  1502. this.$message.error('ERP账号设置失败');
  1503. } finally {
  1504. this.erpAccountDialog.submitting = false;
  1505. }
  1506. },
  1507. //执行创建ERP订单
  1508. async executeCreateErpOrder() {
  1509. this.erpAccountDialog.submitting = true;
  1510. try {
  1511. let param = {
  1512. loginAccount: this.erpAccountForm.selectedAccount
  1513. };
  1514. if (this.ids.length > 0) {
  1515. // 如果有选中的订单,只推送选中的
  1516. param.orderIds = this.ids;
  1517. } else {
  1518. // 如果没有选中订单,推送查询条件下的所有订单
  1519. if (this.payTypeArr.length > 0) {
  1520. this.queryParams.payType = this.payTypeArr.toString();
  1521. } else {
  1522. this.queryParams.payType = null;
  1523. }
  1524. if (this.scheduleIdArr.length > 0) {
  1525. this.queryParams.scheduleId = this.scheduleIdArr.toString();
  1526. } else {
  1527. this.queryParams.scheduleId = null;
  1528. }
  1529. if (this.buyTypeArr.length > 0) {
  1530. this.queryParams.orderBuyType = this.buyTypeArr.toString();
  1531. } else {
  1532. this.queryParams.orderBuyType = null;
  1533. }
  1534. if (this.channelArr.length > 0) {
  1535. this.queryParams.orderChannel = this.channelArr.toString();
  1536. } else {
  1537. this.queryParams.orderChannel = null;
  1538. }
  1539. if (this.qwSubjectArr.length > 0) {
  1540. this.queryParams.qwSubject = this.qwSubjectArr.toString();
  1541. } else {
  1542. this.queryParams.qwSubject = null;
  1543. }
  1544. // 合并查询参数
  1545. param = { ...param, ...this.queryParams };
  1546. }
  1547. const response = await batchCreateErpOrder(param);
  1548. if (response.code === 200) {
  1549. this.$message.success('ERP订单创建成功');
  1550. this.cancelErpAccountDialog();
  1551. this.getErpAccountList(); // 刷新列表
  1552. this.getList();
  1553. } else {
  1554. this.$message.error(response.msg || 'ERP订单创建失败');
  1555. }
  1556. } catch (error) {
  1557. console.error('创建ERP订单失败:', error);
  1558. this.$message.error('创建ERP订单失败');
  1559. } finally {
  1560. this.erpAccountDialog.submitting = false;
  1561. }
  1562. },
  1563. // 新增:取消ERP账户选择对话框
  1564. cancelErpAccountDialog() {
  1565. this.erpAccountDialog.open = false;
  1566. this.erpAccountForm.selectedAccount = null;
  1567. this.orderSummary = null;
  1568. this.erpAccountList = [];
  1569. },
  1570. handleCancelErpPhone(){
  1571. this.erpPhoneValue = [];
  1572. this.setPhoneOpen = false;
  1573. },
  1574. submitErpPhone(){
  1575. let param = {};
  1576. if(this.ids.length>0){
  1577. param = {orderIds:this.ids,erpPhone:this.erpPhoneValue};
  1578. } else {
  1579. if(this.payTypeArr.length>0){
  1580. this.queryParams.payType=this.payTypeArr.toString();
  1581. }
  1582. else{
  1583. this.queryParams.payType=null
  1584. }
  1585. if(this.scheduleIdArr.length>0){
  1586. this.queryParams.scheduleId=this.scheduleIdArr.toString();
  1587. }
  1588. else{
  1589. this.queryParams.scheduleId=null
  1590. }
  1591. if(this.buyTypeArr.length>0){
  1592. this.queryParams.orderBuyType=this.buyTypeArr.toString();
  1593. }
  1594. else{
  1595. this.queryParams.orderbuyType=null
  1596. }
  1597. if(this.channelArr.length>0){
  1598. this.queryParams.orderChannel=this.channelArr.toString();
  1599. }
  1600. else{
  1601. this.queryParams.orderChannel=null
  1602. }
  1603. if(this.qwSubjectArr.length>0){
  1604. this.queryParams.qwSubject=this.qwSubjectArr.toString();
  1605. }
  1606. else{
  1607. this.queryParams.qwSubject=null
  1608. }
  1609. param = this.queryParams;
  1610. param.erpPhone=this.erpPhoneValue;
  1611. }
  1612. editErpPhone(param).then(response=>{
  1613. this.msgSuccess("修改成功");
  1614. this.setPhoneOpen = false;
  1615. this.getList();
  1616. })
  1617. },
  1618. setErpPhone(){
  1619. this.getErpPhoneList();
  1620. this.setPhoneOpen = true;
  1621. },
  1622. // 设置推送手机相关方法
  1623. handleErpPhone(){
  1624. //查询配置手机号
  1625. this.getErpPhoneList();
  1626. this.erpPhone.open = true
  1627. },
  1628. getErpPhoneList(){
  1629. queryErpPhone().then(response =>{
  1630. if(response.data && response.data != null && response.data.length >0){
  1631. const phones = response.data.filter(phone => phone.trim());
  1632. this.phoneList = phones.map(phone => ({
  1633. phone: phone.trim(),
  1634. editing: false,
  1635. originalPhone: phone.trim()
  1636. }));
  1637. }
  1638. // 保存原始数据用于取消操作
  1639. this.originalPhoneList = this.phoneList;
  1640. });
  1641. },
  1642. // 新增手机号
  1643. handleAddPhone() {
  1644. this.phoneList.push({
  1645. phone: '',
  1646. editing: true,
  1647. originalPhone: '',
  1648. isNew: true
  1649. });
  1650. },
  1651. // 编辑手机号
  1652. handleEditPhone(index) {
  1653. this.$set(this.phoneList[index], 'editing', true);
  1654. this.$set(this.phoneList[index], 'originalPhone', this.phoneList[index].phone);
  1655. },
  1656. // 保存手机号
  1657. handleSavePhone(index) {
  1658. const phone = this.phoneList[index].phone.trim();
  1659. if (!phone) {
  1660. this.$message.error('手机号不能为空');
  1661. return;
  1662. }
  1663. if (!this.validatePhoneFormat(phone)) {
  1664. this.$message.error('请输入正确的手机号格式');
  1665. return;
  1666. }
  1667. // 检查是否重复
  1668. const duplicateIndex = this.phoneList.findIndex((item, idx) =>
  1669. idx !== index && item.phone === phone
  1670. );
  1671. if (duplicateIndex !== -1) {
  1672. this.$message.error('手机号已存在');
  1673. return;
  1674. }
  1675. this.$set(this.phoneList[index], 'editing', false);
  1676. this.$set(this.phoneList[index], 'isNew', false);
  1677. },
  1678. // 取消编辑
  1679. handleCancelEdit(index) {
  1680. if (this.phoneList[index].isNew) {
  1681. // 如果是新增的,直接删除
  1682. this.phoneList.splice(index, 1);
  1683. } else {
  1684. // 如果是编辑的,恢复原值
  1685. this.$set(this.phoneList[index], 'phone', this.phoneList[index].originalPhone);
  1686. this.$set(this.phoneList[index], 'editing', false);
  1687. }
  1688. },
  1689. // 删除手机号
  1690. handleDeletePhone(index) {
  1691. this.$confirm('确认删除该手机号?', '提示', {
  1692. confirmButtonText: '确定',
  1693. cancelButtonText: '取消',
  1694. type: 'warning'
  1695. }).then(() => {
  1696. this.phoneList.splice(index, 1);
  1697. this.$message.success('删除成功');
  1698. });
  1699. },
  1700. // 验证手机号格式
  1701. validatePhoneFormat(phone) {
  1702. const phoneRegex = /^1[3-9]\d{9}$/;
  1703. return phoneRegex.test(phone);
  1704. },
  1705. // 验证手机号
  1706. validatePhone(row) {
  1707. if (row.phone && !this.validatePhoneFormat(row.phone)) {
  1708. this.$message.error('请输入正确的手机号格式');
  1709. }
  1710. },
  1711. // 保存手机号列表
  1712. handleSavePhoneList() {
  1713. // 检查是否有正在编辑的项
  1714. const editingItem = this.phoneList.find(item => item.editing);
  1715. if (editingItem) {
  1716. this.$message.error('请先保存正在编辑的手机号');
  1717. return;
  1718. }
  1719. // 检查是否有空的手机号
  1720. const emptyPhone = this.phoneList.find(item => !item.phone.trim());
  1721. if (emptyPhone) {
  1722. this.$message.error('存在空的手机号,请删除或填写完整');
  1723. return;
  1724. }
  1725. // 构造手机号列表
  1726. const phoneList = this.phoneList.map(item => item.phone);
  1727. // 调用保存接口
  1728. saveErpPhone(phoneList).then(response => {
  1729. if (response.code === 200) {
  1730. this.$message.success('保存成功');
  1731. this.erpPhone.open = false;
  1732. } else {
  1733. this.$message.error(response.msg || '保存失败');
  1734. }
  1735. this.getList();
  1736. }).catch(() => {
  1737. this.$message.error('保存失败');
  1738. });
  1739. },
  1740. // 取消手机号对话框
  1741. handleCancelPhoneDialog() {
  1742. // 恢复原始数据
  1743. this.phoneList = JSON.parse(JSON.stringify(this.originalPhoneList));
  1744. this.erpPhone.open = false;
  1745. },
  1746. // 获取小程序选项列表
  1747. getAppMallOptions() {
  1748. getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
  1749. this.appMallOptions = response.rows;
  1750. })
  1751. },
  1752. // 获取已选择字段数量
  1753. getSelectedFieldsCount() {
  1754. return this.exportFieldOptions.filter(field => field.checked).length;
  1755. },
  1756. // 取消导出字段选择
  1757. cancelExportFieldDialog() {
  1758. this.exportFieldDialog.open = false;
  1759. this.exportFieldDialog.type = null;
  1760. },
  1761. // 选择常用字段
  1762. selectDefaultFields() {
  1763. // 先全不选
  1764. this.unselectAllFields();
  1765. // 然后选择常用字段
  1766. const defaultFields = ['orderCode', 'prescribeCode', 'companyName', 'companyUserNickName',
  1767. 'storeName', 'miniProgramName', 'userName', 'userPhone', 'userAddress', 'totalPrice',
  1768. 'totalNum', 'payPrice', 'payMoney', 'createTime', 'payTime',
  1769. 'payType', 'status', 'packageName', 'patientName'];
  1770. this.exportFieldOptions.forEach(field => {
  1771. if (defaultFields.includes(field.key)) {
  1772. field.checked = true;
  1773. }
  1774. });
  1775. },
  1776. // 确认导出字段
  1777. confirmExportFields() {
  1778. // 获取已选择的字段
  1779. const selectedFieldsArray = this.exportFieldOptions.filter(field => field.checked);
  1780. let selectedFields = '';
  1781. if (selectedFieldsArray.length === 0) {
  1782. // 如果没有选择任何字段,则导出全部字段(不传filter参数)
  1783. selectedFields = null;
  1784. } else {
  1785. // 如果选择了字段,则只导出选中的字段
  1786. selectedFields = selectedFieldsArray.map(field => field.key).join(',');
  1787. }
  1788. // 关闭弹窗
  1789. this.exportFieldDialog.open = false;
  1790. // 执行导出操作
  1791. this.doExportOrder(selectedFields);
  1792. },
  1793. // 执行导出操作
  1794. doExportOrder(selectedFields) {
  1795. if (this.queryParams.status == '00') {
  1796. this.queryParams.status = null
  1797. }
  1798. if (this.createTimeRange != null && this.createTimeRange.length == 2) {
  1799. this.queryParams.createTimeRange = this.createTimeRange[0] + '--' + this.createTimeRange[1]
  1800. } else {
  1801. this.queryParams.createTimeRange = null
  1802. }
  1803. if (this.payTimeRange != null && this.payTimeRange.length == 2) {
  1804. this.queryParams.payTimeRange = this.payTimeRange[0] + '--' + this.payTimeRange[1]
  1805. } else {
  1806. this.queryParams.payTimeRange = null
  1807. }
  1808. if (this.deliveryImportTimeRange != null && this.deliveryImportTimeRange.length == 2) {
  1809. this.queryParams.deliveryImportTimeRange = this.deliveryImportTimeRange[0] + '--' + this.deliveryImportTimeRange[1]
  1810. } else {
  1811. this.queryParams.deliveryImportTimeRange = null
  1812. }
  1813. if (this.deliverySendTimeRange != null && this.deliverySendTimeRange.length == 2) {
  1814. this.queryParams.deliverySendTimeRange = this.deliverySendTimeRange[0] + '--' + this.deliverySendTimeRange[1]
  1815. } else {
  1816. this.queryParams.deliverySendTimeRange = null
  1817. }
  1818. const queryParams = this.addDateRange(this.queryParams, this.dateRange)
  1819. // 根据是否选择字段显示不同的确认消息
  1820. let confirmMessage = '';
  1821. if (selectedFields === null) {
  1822. confirmMessage = '没有选择字段,将导出所有字段的订单数据,确认继续?';
  1823. } else {
  1824. const fieldCount = selectedFields.split(',').length;
  1825. confirmMessage = `确认导出选中的 ${fieldCount} 个字段的订单数据?`;
  1826. }
  1827. this.$confirm('是否确认导出所有订单数据项?', '警告', {
  1828. confirmButtonText: '确定',
  1829. cancelButtonText: '取消',
  1830. type: 'warning'
  1831. }).then(()=> {
  1832. this.exportLoading = true;
  1833. // 构建请求参数
  1834. const requestParams = {...queryParams};
  1835. // 只有当selectedFields不为null时才添加filter参数
  1836. if (selectedFields !== null) {
  1837. requestParams.filter = selectedFields;
  1838. }
  1839. console.log(requestParams)
  1840. if(this.exportFieldDialog.type == 1){
  1841. return exportHealthStoreOrder(requestParams)
  1842. } else if (this.exportFieldDialog.type == 2){
  1843. return exportHealthStoreOrderDetails(requestParams)
  1844. }
  1845. }).then(response => {
  1846. this.download(response.msg)
  1847. }).catch(function() {
  1848. })
  1849. },
  1850. // 导出字段选择相关方法
  1851. // 全选字段
  1852. selectAllFields() {
  1853. this.exportFieldOptions.forEach(field => {
  1854. field.checked = true;
  1855. });
  1856. },
  1857. // 全不选字段
  1858. unselectAllFields() {
  1859. this.exportFieldOptions.forEach(field => {
  1860. field.checked = false;
  1861. });
  1862. },
  1863. handleGenPayUrl(row) {
  1864. this.payQr.open = true
  1865. setTimeout(() => {
  1866. var qrcode = new QRCode(this.$refs.qrCodeUrl, {
  1867. text: config.payQRUrl + row.id, // 需要转换为二维码的内容
  1868. width: 200,
  1869. height: 200,
  1870. colorDark: '#000000',
  1871. colorLight: '#ffffff',
  1872. correctLevel: QRCode.CorrectLevel.H
  1873. })
  1874. }, 200)
  1875. },
  1876. handleAddUser() {
  1877. this.user.open = true
  1878. },
  1879. handleAddUserAddress() {
  1880. if (this.form.userId == null) {
  1881. this.msgError('请选择会员')
  1882. return
  1883. }
  1884. this.userAddress.open = true
  1885. setTimeout(() => {
  1886. this.$refs.addUserAddress.init(this.form.userId)
  1887. }, 500)
  1888. },
  1889. addUser() {
  1890. this.user.open = false
  1891. },
  1892. addUserAddress() {
  1893. this.userAddress.open = false
  1894. //获取地址
  1895. this.getAddressList(this.form.userId)
  1896. },
  1897. compute() {
  1898. this.totalMoney = 0
  1899. var that = this
  1900. this.products.forEach(function(value) {
  1901. that.totalMoney += value.money
  1902. })
  1903. console.log(that.totalMoney)
  1904. },
  1905. handleProductCountChange(row) {
  1906. this.tablekey = !this.tablekey
  1907. console.log(row)
  1908. row.money = row.count * row.price
  1909. this.$forceUpdate()
  1910. this.compute()
  1911. },
  1912. selectProduct(row) {
  1913. console.log(row)
  1914. for (var i = 0; i < this.products.length; i++) {
  1915. if (this.products[i].id == row.id) {
  1916. return
  1917. }
  1918. }
  1919. row.count = 1
  1920. row.money = row.count * row.price
  1921. this.products.push(row)
  1922. this.compute()
  1923. },
  1924. handleAddProduct() {
  1925. this.product.open = true
  1926. },
  1927. searchUser() {
  1928. if (this.phone == null || this.phone == '') {
  1929. return
  1930. }
  1931. var data = { phone: this.phone }
  1932. this.userloading = true
  1933. this.users = []
  1934. this.address = []
  1935. getUserList(data).then(response => {
  1936. this.users = response.data
  1937. this.userloading = false
  1938. if (this.users != null && this.users.length == 1) {
  1939. this.form.userId = this.users[0].userId
  1940. this.getAddressList(this.form.userId)
  1941. }
  1942. })
  1943. },
  1944. getAddressList(userId) {
  1945. var data = { userId: userId }
  1946. this.addressloading = true
  1947. this.address = []
  1948. getAddressList(data).then(response => {
  1949. this.address = response.data
  1950. this.addressloading = false
  1951. })
  1952. },
  1953. handleDetails(row) {
  1954. this.show.open = true
  1955. const orderId = row.id
  1956. setTimeout(() => {
  1957. this.$refs.order.getOrder(orderId)
  1958. }, 500)
  1959. },
  1960. handleClick(tab, event) {
  1961. this.orderStatus = tab.name;
  1962. this.activeName = tab.name
  1963. this.queryParams.status = tab.name
  1964. console.log(this.queryParams.status)
  1965. this.getList()
  1966. },
  1967. /** 查询订单列表 */
  1968. getList() {
  1969. this.loading = true
  1970. if (this.queryParams.status == '00') {
  1971. this.queryParams.status = null
  1972. }
  1973. if (this.createTimeRange != null && this.createTimeRange.length == 2) {
  1974. this.queryParams.createTimeRange = this.createTimeRange[0] + '--' + this.createTimeRange[1]
  1975. } else {
  1976. this.queryParams.createTimeRange = null
  1977. }
  1978. if (this.payTimeRange != null && this.payTimeRange.length == 2) {
  1979. this.queryParams.payTimeRange = this.payTimeRange[0] + '--' + this.payTimeRange[1]
  1980. } else {
  1981. this.queryParams.payTimeRange = null
  1982. }
  1983. if (this.deliveryImportTimeRange != null && this.deliveryImportTimeRange.length == 2) {
  1984. this.queryParams.deliveryImportTimeRange = this.deliveryImportTimeRange[0] + '--' + this.deliveryImportTimeRange[1]
  1985. } else {
  1986. this.queryParams.deliveryImportTimeRange = null
  1987. }
  1988. if (this.deliverySendTimeRange != null && this.deliverySendTimeRange.length == 2) {
  1989. this.queryParams.deliverySendTimeRange = this.deliverySendTimeRange[0] + '--' + this.deliverySendTimeRange[1]
  1990. } else {
  1991. this.queryParams.deliverySendTimeRange = null
  1992. }
  1993. // 处理订单号数组
  1994. if (this.queryParams.orderCodes && this.queryParams.orderCodes.length > 0) {
  1995. this.queryParams.orderCodeList = this.queryParams.orderCodes.join(',');
  1996. } else {
  1997. this.queryParams.orderCodeList = null;
  1998. }
  1999. listHealthStoreOrder(this.queryParams).then(response => {
  2000. this.storeOrderList = response.rows
  2001. this.total = response.total
  2002. if(this.total>0){
  2003. this.payPriceTotal = response.payPriceTotal;
  2004. this.payMoneyTotal = response.payMoneyTotal;
  2005. this.payRemainTotal = response.payRemainTotal;
  2006. this.productInfo = response.productInfo;
  2007. } else {
  2008. this.payPriceTotal = "0"
  2009. this.payMoneyTotal = "0"
  2010. this.payRemainTotal = "0"
  2011. this.productInfo = response.productInfo;
  2012. }
  2013. this.loading = false
  2014. if(response.msg == 'knt'){
  2015. this.SFDFopen = true;
  2016. } else{
  2017. this.SFDFopen = false;
  2018. }
  2019. // 如果有排序,显示排序结果提示
  2020. if (this.currentSort.prop) {
  2021. const fieldLabel = this.getSortLabel(this.currentSort.prop);
  2022. const orderLabel = this.currentSort.order === 'ascending' ? '升序' : '降序';
  2023. console.log(`数据已按${fieldLabel}${orderLabel}加载`);
  2024. }
  2025. }).catch(error => {
  2026. console.error('查询失败:', error);
  2027. this.loading = false;
  2028. this.$message.error('查询数据失败');
  2029. });
  2030. },
  2031. // 取消按钮
  2032. cancel() {
  2033. this.open = false
  2034. this.reset()
  2035. },
  2036. // 表单重置
  2037. reset() {
  2038. this.form = {
  2039. addressId: null,
  2040. userId: null
  2041. }
  2042. this.resetForm('form')
  2043. },
  2044. /** 搜索按钮操作 */
  2045. handleQuery() {
  2046. this.queryParams.pageNum = 1
  2047. this.getList()
  2048. },
  2049. /** 重置按钮操作 */
  2050. resetQuery() {
  2051. this.resetForm('queryForm')
  2052. // 清除排序
  2053. this.currentSort = {
  2054. prop: null,
  2055. order: null
  2056. };
  2057. this.queryParams.sortField = null;
  2058. this.queryParams.sortOrder = null;
  2059. // 重置表格排序状态 - 关键代码
  2060. this.$nextTick(() => {
  2061. if (this.$refs.orderTable) {
  2062. this.$refs.orderTable.clearSort();
  2063. }
  2064. });
  2065. this.handleQuery()
  2066. },
  2067. // 多选框选中数据
  2068. handleSelectionChange(selection) {
  2069. this.ids = selection.map(item => item.id)
  2070. this.single = selection.length !== 1
  2071. this.multiple = !selection.length
  2072. },
  2073. /** 新增按钮操作 */
  2074. handleAdd() {
  2075. this.reset()
  2076. this.open = true
  2077. this.title = '创建订单'
  2078. },
  2079. /** 修改按钮操作 */
  2080. handleUpdate(row) {
  2081. this.reset()
  2082. const id = row.id || this.ids
  2083. getStoreOrder(id).then(response => {
  2084. this.form = response.data
  2085. this.open = true
  2086. this.title = '修改订单'
  2087. })
  2088. },
  2089. /** 提交按钮 */
  2090. submitForm() {
  2091. this.$refs['form'].validate(valid => {
  2092. this.form.products = this.products
  2093. if (valid) {
  2094. console.log(this.form)
  2095. createUserOrder(this.form).then(response => {
  2096. if (response.code === 200) {
  2097. this.msgSuccess('创建成功')
  2098. this.open = false
  2099. this.getList()
  2100. }
  2101. })
  2102. }
  2103. })
  2104. },
  2105. /** 删除按钮操作 */
  2106. handleOrderDelete(row) {
  2107. const ids = row.id || this.ids;
  2108. this.$confirm('是否确认删除当前选择的订单数据项?', "警告", {
  2109. confirmButtonText: "确定",
  2110. cancelButtonText: "取消",
  2111. type: "warning"
  2112. }).then(function () {
  2113. return delStoreOrder(ids);
  2114. }).then(() => {
  2115. this.getList();
  2116. this.msgSuccess("删除成功");
  2117. }).catch(() => {
  2118. });
  2119. },
  2120. /** 删除按钮操作 */
  2121. handleDelete(row) {
  2122. this.products.splice(this.products.findIndex(item => item.id === row.id), 1)
  2123. this.compute()
  2124. },
  2125. /** 导出按钮操作 */
  2126. handleExport() {
  2127. // 打开字段选择对话框
  2128. this.exportFieldDialog.open = true;
  2129. this.exportFieldDialog.type = 1;
  2130. },
  2131. handleExportItems() {
  2132. if (this.queryParams.status == '00') {
  2133. this.queryParams.status = null
  2134. }
  2135. if (this.createTimeRange != null && this.createTimeRange.length == 2) {
  2136. this.queryParams.createTimeRange = this.createTimeRange[0] + '--' + this.createTimeRange[1]
  2137. } else {
  2138. this.queryParams.createTimeRange = null
  2139. }
  2140. if (this.payTimeRange != null && this.payTimeRange.length == 2) {
  2141. this.queryParams.payTimeRange = this.payTimeRange[0] + '--' + this.payTimeRange[1]
  2142. } else {
  2143. this.queryParams.payTimeRange = null
  2144. }
  2145. if (this.deliveryImportTimeRange != null && this.deliveryImportTimeRange.length == 2) {
  2146. this.queryParams.deliveryImportTimeRange = this.deliveryImportTimeRange[0] + '--' + this.deliveryImportTimeRange[1]
  2147. } else {
  2148. this.queryParams.deliveryImportTimeRange = null
  2149. }
  2150. if (this.deliverySendTimeRange != null && this.deliverySendTimeRange.length == 2) {
  2151. this.queryParams.deliverySendTimeRange = this.deliverySendTimeRange[0] + '--' + this.deliverySendTimeRange[1]
  2152. } else {
  2153. this.queryParams.deliverySendTimeRange = null
  2154. }
  2155. const queryParams = this.addDateRange(this.queryParams, this.dateRange)
  2156. this.$confirm('是否确认导出所有订单明细数据项?', '警告', {
  2157. confirmButtonText: '确定',
  2158. cancelButtonText: '取消',
  2159. type: 'warning'
  2160. }).then(function() {
  2161. return exportHealthStoreOrderItems(queryParams)
  2162. }).then(response => {
  2163. this.download(response.msg)
  2164. }).catch(function() {
  2165. })
  2166. },
  2167. /** 导出按钮操作 */
  2168. handleExportDetails() {
  2169. // 打开字段选择对话框
  2170. this.exportFieldDialog.open = true;
  2171. this.exportFieldDialog.type = 2;
  2172. },
  2173. handleExportItemsDetails() {
  2174. if (this.queryParams.status == '00') {
  2175. this.queryParams.status = null
  2176. }
  2177. if (this.createTimeRange != null && this.createTimeRange.length == 2) {
  2178. this.queryParams.createTimeRange = this.createTimeRange[0] + '--' + this.createTimeRange[1]
  2179. } else {
  2180. this.queryParams.createTimeRange = null
  2181. }
  2182. if (this.payTimeRange != null && this.payTimeRange.length == 2) {
  2183. this.queryParams.payTimeRange = this.payTimeRange[0] + '--' + this.payTimeRange[1]
  2184. } else {
  2185. this.queryParams.payTimeRange = null
  2186. }
  2187. if (this.deliveryImportTimeRange != null && this.deliveryImportTimeRange.length == 2) {
  2188. this.queryParams.deliveryImportTimeRange = this.deliveryImportTimeRange[0] + '--' + this.deliveryImportTimeRange[1]
  2189. } else {
  2190. this.queryParams.deliveryImportTimeRange = null
  2191. }
  2192. if (this.deliverySendTimeRange != null && this.deliverySendTimeRange.length == 2) {
  2193. this.queryParams.deliverySendTimeRange = this.deliverySendTimeRange[0] + '--' + this.deliverySendTimeRange[1]
  2194. } else {
  2195. this.queryParams.deliverySendTimeRange = null
  2196. }
  2197. const queryParams = this.addDateRange(this.queryParams, this.dateRange)
  2198. this.$confirm('是否确认导出所有订单明细数据项?', '警告', {
  2199. confirmButtonText: '确定',
  2200. cancelButtonText: '取消',
  2201. type: 'warning'
  2202. }).then(function() {
  2203. return exportHealthStoreOrderItemsDetails(queryParams)
  2204. }).then(response => {
  2205. this.download(response.msg)
  2206. }).catch(function() {
  2207. })
  2208. },
  2209. handleImport() {
  2210. this.upload.title = '导入银行回单'
  2211. this.upload.open = true
  2212. },
  2213. submitFileForm() {
  2214. this.$refs.upload.submit()
  2215. },
  2216. importTemplate() {
  2217. importTemplate().then((response) => {
  2218. this.download(response.msg)
  2219. })
  2220. },
  2221. // 文件上传中处理
  2222. handleFileUploadProgress(event, file, fileList) {
  2223. this.upload.isUploading = true
  2224. },
  2225. // 文件上传成功处理
  2226. handleFileSuccess(response, file, fileList) {
  2227. this.upload.open = false
  2228. this.upload.isUploading = false
  2229. this.$refs.upload.clearFiles()
  2230. this.importMsgOpen = true
  2231. this.importMsg = response.msg
  2232. // this.$alert(response.msg, '导入结果', {
  2233. // dangerouslyUseHTMLString: true
  2234. // });
  2235. this.getList()
  2236. },
  2237. /** 查询部门下拉树结构 */
  2238. getTreeselect() {
  2239. var that = this
  2240. var param = { companyId: this.companyId }
  2241. treeselect(param).then((response) => {
  2242. this.deptOptions = response.data
  2243. console.log(this.deptOptions)
  2244. if (response.data != null && response.data.length > 0) {
  2245. //this.queryParams.deptId=response.data[0].id;
  2246. }
  2247. })
  2248. },
  2249. companyChange(val) {
  2250. console.log(val)
  2251. this.companyId = val
  2252. this.getTreeselect()
  2253. },
  2254. currDeptChange(val) {
  2255. console.log(val)
  2256. this.queryParams.deptId = val
  2257. this.getList()
  2258. },
  2259. //打开发货单
  2260. openDeliveryNote() {
  2261. this.deliveryNoteOpen = true
  2262. // this.getAppList();
  2263. },
  2264. handleClose(done) {
  2265. this.$confirm('确认关闭?')
  2266. .then(_ => {
  2267. done()
  2268. })
  2269. .catch(_ => {
  2270. })
  2271. },
  2272. //发货单模板下载
  2273. importDeliveryNoteTemplate() {
  2274. importDeliveryNoteExpressTemplate().then((response) => {
  2275. this.download(response.msg)
  2276. })
  2277. },
  2278. getAppList() {
  2279. this.miniAppList = []
  2280. const key = 'courseMa.config'
  2281. getConfigByKey(key).then(response => {
  2282. const { code, data } = response
  2283. if (code === 200) {
  2284. let value = data?.configValue
  2285. if (value) {
  2286. const appList = JSON.parse(value)
  2287. this.miniAppList = appList.filter(v => v.type === '1').map(v => {
  2288. return { appId: v.appid, appName: v.name }
  2289. })
  2290. }
  2291. }
  2292. })
  2293. },
  2294. // 提交发货单
  2295. submitDeliveryNote() {
  2296. const uploadFiles = this.$refs.upload.uploadFiles;
  2297. if (uploadFiles.length === 0) {
  2298. this.$message.error('请选择要上传的文件');
  2299. return;
  2300. }
  2301. this.$refs.upload.submit();
  2302. }
  2303. }
  2304. }
  2305. </script>
  2306. <style lang="scss" scoped>
  2307. .items {
  2308. margin: 5px 0px;
  2309. display: flex;
  2310. flex-direction: row;
  2311. align-items: center;
  2312. justify-content: flex-start;
  2313. .pic {
  2314. width: 60px;
  2315. height: 60px;
  2316. }
  2317. .goods-content {
  2318. margin-left: 10px;
  2319. max-width: 200px;
  2320. text-align: left;
  2321. .goods-title {
  2322. overflow: hidden;
  2323. white-space: nowrap;
  2324. text-overflow: ellipsis;
  2325. -o-text-overflow: ellipsis;
  2326. }
  2327. }
  2328. }
  2329. .el-message-box__message p {
  2330. max-height: 400px;
  2331. overflow: scroll;
  2332. }
  2333. .import-msg {
  2334. height: 500px;
  2335. overflow: auto;
  2336. }
  2337. </style>
  2338. <style>
  2339. .el-descriptions-item__label.is-bordered-label {
  2340. font-weight: normal;
  2341. }
  2342. </style>
  2343. <style scoped>
  2344. .tag-input-order-search {
  2345. padding: 20px;
  2346. background: #fff;
  2347. border-radius: 4px;
  2348. }
  2349. .tag-input-container {
  2350. min-width: 445px;
  2351. }
  2352. .tags-wrapper {
  2353. min-height: 32px;
  2354. padding: 4px 8px;
  2355. border: 1px solid #dcdfe6;
  2356. border-radius: 4px;
  2357. cursor: text;
  2358. display: flex;
  2359. flex-wrap: wrap;
  2360. align-items: center;
  2361. gap: 4px;
  2362. transition: border-color 0.2s;
  2363. }
  2364. .tags-wrapper:hover {
  2365. border-color: #c0c4cc;
  2366. }
  2367. .tags-wrapper:focus-within {
  2368. border-color: #409eff;
  2369. box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
  2370. }
  2371. .order-tag {
  2372. margin: 2px;
  2373. flex-shrink: 0;
  2374. }
  2375. .tag-error {
  2376. background-color: #fef0f0;
  2377. border-color: #fbc4c4;
  2378. color: #f56c6c;
  2379. }
  2380. .tag-input {
  2381. border: none;
  2382. outline: none;
  2383. flex: 1;
  2384. min-width: 120px;
  2385. }
  2386. .tag-input >>> .el-input__inner {
  2387. border: none;
  2388. padding: 0;
  2389. height: 24px;
  2390. line-height: 24px;
  2391. }
  2392. .button-new-tag {
  2393. height: 24px;
  2394. line-height: 22px;
  2395. padding: 0 8px;
  2396. margin: 2px;
  2397. }
  2398. .input-tips {
  2399. margin-top: 4px;
  2400. font-size: 12px;
  2401. color: #909399;
  2402. }
  2403. /* 新增排序相关样式 */
  2404. .sort-info {
  2405. margin-top: 10px;
  2406. padding: 8px 0;
  2407. }
  2408. /* 表格布局优化 */
  2409. .el-table {
  2410. min-width: 100%;
  2411. table-layout: fixed;
  2412. }
  2413. .el-table .el-table__body-wrapper {
  2414. overflow-x: auto;
  2415. }
  2416. .tip-text {
  2417. display: flex;
  2418. align-items: center;
  2419. gap: 8px;
  2420. }
  2421. .quick-actions {
  2422. margin-top: 12px;
  2423. display: flex;
  2424. justify-content: space-between;
  2425. align-items: center;
  2426. padding: 8px 0;
  2427. border-top: 1px solid #ebeef5;
  2428. }
  2429. .stats-info {
  2430. font-size: 12px;
  2431. color: #909399;
  2432. display: flex;
  2433. align-items: center;
  2434. gap: 4px;
  2435. }
  2436. .invalid-codes-list {
  2437. margin: 16px 0;
  2438. max-height: 200px;
  2439. overflow-y: auto;
  2440. }
  2441. .invalid-tag {
  2442. margin: 4px;
  2443. }
  2444. .debug-preview {
  2445. margin-top: 20px;
  2446. }
  2447. .debug-content {
  2448. font-size: 12px;
  2449. }
  2450. .debug-content code {
  2451. display: block;
  2452. background: #f5f5f5;
  2453. padding: 8px;
  2454. border-radius: 4px;
  2455. margin: 4px 0 12px 0;
  2456. white-space: pre-wrap;
  2457. }
  2458. /* 响应式设计 */
  2459. @media (max-width: 768px) {
  2460. .tag-input-container {
  2461. min-width: auto;
  2462. width: 100%;
  2463. }
  2464. .tags-wrapper {
  2465. min-height: 40px;
  2466. }
  2467. .quick-actions {
  2468. flex-direction: column;
  2469. align-items: flex-start;
  2470. gap: 8px;
  2471. }
  2472. }
  2473. </style>