index.vue 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014
  1. <template xmlns:el-col="http://www.w3.org/1999/html">
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  4. <el-form-item label="提醒状态">
  5. <el-button
  6. size="mini"
  7. type="danger"
  8. @click="handleRemindFilter('overdue')"
  9. >
  10. 逾期
  11. </el-button>
  12. <el-button
  13. size="mini"
  14. type="warning"
  15. @click="handleRemindFilter('urgent')"
  16. >
  17. 7天内到期
  18. </el-button>
  19. <el-button
  20. size="mini"
  21. type="primary"
  22. @click="handleRemindFilter('important')"
  23. >
  24. 15天内到期
  25. </el-button>
  26. <el-button
  27. size="mini"
  28. @click="handleRemindFilter('warning')"
  29. >
  30. 30天内到期
  31. </el-button>
  32. </el-form-item>
  33. <el-form-item label="店铺名称" prop="storeName">
  34. <el-input
  35. v-model="queryParams.storeName"
  36. placeholder="请输入店铺名称"
  37. clearable
  38. size="small"
  39. @keyup.enter.native="handleQuery"
  40. />
  41. </el-form-item>
  42. <el-form-item label="地址" prop="address">
  43. <el-input
  44. v-model="queryParams.address"
  45. placeholder="请输入地址"
  46. clearable
  47. size="small"
  48. @keyup.enter.native="handleQuery"
  49. />
  50. </el-form-item>
  51. <el-form-item label="店铺电话" prop="phone">
  52. <el-input
  53. v-model="queryParams.phone"
  54. placeholder="请输入店铺电话"
  55. clearable
  56. size="small"
  57. @keyup.enter.native="handleQuery"
  58. />
  59. </el-form-item>
  60. <el-form-item label="状态" prop="status">
  61. <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
  62. <el-option
  63. v-for="dict in statusOptions"
  64. :key="dict.dictValue"
  65. :label="dict.dictLabel"
  66. :value="dict.dictValue"
  67. />
  68. </el-select>
  69. </el-form-item>
  70. <el-form-item label="审核状态" prop="isAudit">
  71. <el-select v-model="queryParams.isAudit" placeholder="请选择审核状态" clearable size="small">
  72. <el-option
  73. v-for="dict in isAuditOptions"
  74. :key="dict.dictValue"
  75. :label="dict.dictLabel"
  76. :value="dict.dictValue"
  77. />
  78. </el-select>
  79. </el-form-item>
  80. <el-form-item label="登录帐号" prop="account">
  81. <el-input
  82. v-model="queryParams.account"
  83. placeholder="请输入登录帐号"
  84. clearable
  85. size="small"
  86. @keyup.enter.native="handleQuery"
  87. />
  88. </el-form-item>
  89. <el-form-item label="店铺Id" prop="storeSeq">
  90. <el-input
  91. v-model="queryParams.storeSeq"
  92. placeholder="请输入店铺Id"
  93. clearable
  94. size="small"
  95. @keyup.enter.native="handleQuery"
  96. />
  97. </el-form-item>
  98. <el-form-item label="商家Id" prop="merchantId">
  99. <el-input
  100. v-model="queryParams.merchantId"
  101. placeholder="请输入商家Id"
  102. clearable
  103. size="small"
  104. @keyup.enter.native="handleQuery"
  105. />
  106. </el-form-item>
  107. <el-form-item label="是否设置推送店铺" prop="hasErpInfo">
  108. <el-select v-model="queryParams.hasErpInfo" placeholder="请选择状态" clearable size="small">
  109. <el-option label="已设置" :value="1" />
  110. <el-option label="未设置" :value="0" />
  111. </el-select>
  112. </el-form-item>
  113. <el-form-item label="580编码" prop="pharmacyCodeFilter">
  114. <el-select v-model="queryParams.pharmacyCodeFilter" placeholder="请选择状态" clearable size="small">
  115. <el-option label="已填写" :value="1" />
  116. <el-option label="未填写" :value="0" />
  117. </el-select>
  118. </el-form-item>
  119. <el-form-item>
  120. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  121. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  122. </el-form-item>
  123. </el-form>
  124. <el-row :gutter="10" class="mb8">
  125. <el-col :span="1.5">
  126. <el-button
  127. type="primary"
  128. plain
  129. icon="el-icon-plus"
  130. size="mini"
  131. @click="handleAdd"
  132. v-hasPermi="['his:store:add']"
  133. >新增</el-button>
  134. </el-col>
  135. <el-col :span="1.5">
  136. <el-button
  137. type="success"
  138. plain
  139. icon="el-icon-edit"
  140. size="mini"
  141. :disabled="single"
  142. @click="handleUpdate"
  143. v-hasPermi="['his:store:edit']"
  144. >修改</el-button>
  145. </el-col>
  146. <el-col :span="1.5">
  147. <el-button
  148. type="danger"
  149. plain
  150. icon="el-icon-delete"
  151. size="mini"
  152. :disabled="multiple"
  153. @click="handleDelete"
  154. v-hasPermi="['his:store:remove']"
  155. >删除</el-button>
  156. </el-col>
  157. <el-col :span="1.5">
  158. <el-button
  159. type="warning"
  160. plain
  161. icon="el-icon-download"
  162. size="mini"
  163. :loading="exportLoading"
  164. @click="handleExport"
  165. v-hasPermi="['his:store:export']"
  166. >导出</el-button>
  167. </el-col>
  168. <el-col :span="1.5">
  169. <el-button
  170. type="success"
  171. icon="el-icon-video-play"
  172. size="mini"
  173. :loading="enableLoading"
  174. :disabled="multiple"
  175. @click="handleEnable"
  176. v-hasPermi="['his:store:edit']"
  177. >一键启用</el-button>
  178. </el-col>
  179. <el-col :span="1.5">
  180. <el-button
  181. type="danger"
  182. icon="el-icon-video-pause"
  183. size="mini"
  184. :loading="disableLoading"
  185. :disabled="multiple"
  186. @click="handleDisable"
  187. v-hasPermi="['his:store:edit']"
  188. >一键停用</el-button>
  189. </el-col>
  190. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  191. </el-row>
  192. <el-table v-loading="loading" border :data="storeList" @selection-change="handleSelectionChange">
  193. <el-table-column type="selection" width="55" align="center" />
  194. <!-- <el-table-column label="店铺id" align="center" prop="storeId" width="120px"/>-->
  195. <el-table-column label="商家ID" align="center" prop="merchantId" width="150px"/>
  196. <el-table-column label="店铺ID" align="center" prop="storeSeq" width="150px"/>
  197. <el-table-column label="580编码" align="center" prop="pharmacyCode" width="150px"/>
  198. <el-table-column label="店铺名称" align="center" prop="storeName" width="120px"/>
  199. <el-table-column label="机构全称" align="center" prop="fullName" width="120px"/>
  200. <el-table-column label="店铺LOGO" align="center" prop="logoUrl" width="100px">
  201. <template slot-scope="scope">
  202. <el-popover
  203. placement="right"
  204. title=""
  205. trigger="hover">
  206. <img slot="reference" :src="scope.row.logoUrl" width="80px" height="80px">
  207. <img :src="scope.row.logoUrl" style="max-width: 160px;">
  208. </el-popover>
  209. </template>
  210. </el-table-column>
  211. <el-table-column label="地址" align="center" prop="enterpriseAddress" width="200px"/>
  212. <el-table-column label="店铺电话" align="center" prop="phone" width="120px"/>
  213. <el-table-column label="审核状态" align="center" prop="isAudit">
  214. <template slot-scope="scope">
  215. <dict-tag :options="isAuditOptions" :value="scope.row.isAudit"/>
  216. </template>
  217. </el-table-column>
  218. <el-table-column label="商品总数" align="center" prop="productCount" />
  219. <el-table-column label="状态" align="center" prop="status">
  220. <template slot-scope="scope">
  221. <dict-tag :options="statusOptions" :value="scope.row.status"/>
  222. </template>
  223. </el-table-column>
  224. <el-table-column label="销量" align="center" prop="salesCount" />
  225. <el-table-column label="余额" align="center" prop="balance" />
  226. <el-table-column label="累计金额" align="center" prop="totalMoney" />
  227. <el-table-column label="登录帐号" align="center" prop="account" width="150px" />
  228. <el-table-column label="上次审核日期" align="center" prop="qualificationUpdateTime" width="150px" />
  229. <el-table-column label="网销报告" align="center" width="100px">
  230. <template slot-scope="scope">
  231. <el-button
  232. v-if="scope.row.reportUrl"
  233. size="mini"
  234. type="text"
  235. icon="el-icon-view"
  236. @click="viewReportFileByUrl(scope.row.reportUrl)">查看</el-button>
  237. <span v-else>-</span>
  238. </template>
  239. </el-table-column>
  240. <el-table-column label="下次到期日" align="center" prop="nextQualificationUpdateTime" width="150px" />
  241. <el-table-column label="剩余天数" align="center" prop="daysDiff" width="150px" />
  242. <el-table-column label="提醒状态(标签)" align="center" prop="daysDiff" width="150px">
  243. <template slot-scope="scope">
  244. <el-tag
  245. v-if="scope.row.daysDiff !== null"
  246. :type="getRemindTagType(scope.row.daysDiff)"
  247. size="small"
  248. >
  249. {{ getRemindTagName(scope.row.daysDiff) }}
  250. </el-tag>
  251. <span v-else>-</span>
  252. </template>
  253. </el-table-column>
  254. <el-table-column label="是否设置推送店铺" align="center" prop="hasErpInfo" width="100px">
  255. <template slot-scope="scope">
  256. <el-tag :type="scope.row.hasErpInfo === 1 ? 'success' : 'danger'" size="small">
  257. {{ scope.row.hasErpInfo === 1 ? '已设置' : '未设置' }}
  258. </el-tag>
  259. </template>
  260. </el-table-column>
  261. <el-table-column label="创建时间" align="center" prop="createTime" width="150px"/>
  262. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="380px">
  263. <template slot-scope="scope">
  264. <el-button
  265. size="mini"
  266. type="text"
  267. icon="el-icon-edit"
  268. @click="handleUpdate(scope.row, true)"
  269. v-hasPermi="['his:store:edit']"
  270. >修改</el-button>
  271. <el-button
  272. size="mini"
  273. type="text"
  274. icon="el-icon-s-promotion"
  275. @click="handleUpdate(scope.row, false)"
  276. >详情
  277. </el-button>
  278. <el-button
  279. size="mini"
  280. type="text"
  281. icon="el-icon-delete"
  282. @click="handleDelete(scope.row)"
  283. v-hasPermi="['his:store:remove']"
  284. >删除</el-button>
  285. <el-button
  286. size="mini"
  287. type="text"
  288. icon="el-icon-refresh"
  289. @click="handleRefresh(scope.row)"
  290. v-hasPermi="['his:store:refresh']"
  291. >重置密码</el-button>
  292. <el-button
  293. size="mini"
  294. type="text"
  295. icon="el-icon-s-tools"
  296. @click="handleErpInfo(scope.row)"
  297. v-hasPermi="['his:storeErpInfo:edit']"
  298. >设置ERP信息</el-button>
  299. <el-button
  300. size="mini"
  301. type="text"
  302. icon="el-icon-edit-outline"
  303. @click="handlePharmacyCode(scope.row)"
  304. v-hasPermi="['his:store:edit:code']"
  305. >设置编码</el-button>
  306. <el-button
  307. size="mini"
  308. type="text"
  309. icon="el-icon-s-promotion"
  310. @click="handleStoreExport(scope.row)"
  311. >导出
  312. </el-button>
  313. </template>
  314. </el-table-column>
  315. </el-table>
  316. <pagination
  317. v-show="total>0"
  318. :total="total"
  319. :page.sync="queryParams.pageNum"
  320. :limit.sync="queryParams.pageSize"
  321. @pagination="getList"
  322. />
  323. <!-- 添加或修改店铺管理对话框 -->
  324. <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body :close-on-click-modal="false">
  325. <el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="top" :disabled="isViewMode">
  326. <el-divider content-position="left">基础信息</el-divider>
  327. <el-row>
  328. <el-col :span="12">
  329. <el-form-item label="店铺名称" prop="storeName">
  330. <el-input v-model="form.storeName" placeholder="请输入店铺名称" />
  331. </el-form-item>
  332. </el-col>
  333. <el-col :span="12">
  334. <el-form-item label="电话" prop="phone">
  335. <el-input v-model="form.phone" placeholder="请输入店铺电话" />
  336. </el-form-item>
  337. </el-col>
  338. </el-row>
  339. <el-form-item label="企业全称" prop="fullName">
  340. <el-input v-model="form.fullName" placeholder="请输入企业全称" />
  341. </el-form-item>
  342. <el-row>
  343. <el-col :span="12">
  344. <el-form-item label="店铺LOGO" prop="logoUrl">
  345. <el-upload
  346. v-model="form.logoUrl"
  347. class="avatar-uploader"
  348. :action="uploadUrl"
  349. :show-file-list="false"
  350. :on-success="handleAvatarSuccess"
  351. :before-upload="beforeAvatarUpload"
  352. :disabled="isDeleting"
  353. >
  354. <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
  355. <div class="avatar-wrapper" v-if="form.logoUrl">
  356. <img :src="form.logoUrl" class="avatar" width="200px">
  357. <!-- 显示删除还是显示放大是更具编辑或者详情来的 -->
  358. <!-- <div v-if="isViewMode" class="view-mask" @click.stop="previewImage(form.logoUrl)">-->
  359. <!-- <i class="el-icon-zoom-in"></i>-->
  360. <!-- </div>-->
  361. <!-- <div v-else class="delete-mask" @click.stop="handleDeleteLogo">-->
  362. <!-- <i class="el-icon-delete"></i>-->
  363. <!-- </div>-->
  364. <!-- 并排显示就好了-->
  365. <div class="button-group">
  366. <div class="preview-btn" @click.stop="previewImage(form.logoUrl)">
  367. <i class="el-icon-zoom-in"></i>
  368. </div>
  369. <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDeleteLogo">
  370. <i class="el-icon-delete"></i>
  371. </div>
  372. </div>
  373. </div>
  374. <!-- 未上传图片时显示的默认图标 -->
  375. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  376. </el-upload>
  377. </el-form-item>
  378. </el-col>
  379. <el-col :span="12"></el-col>
  380. <el-col :span="12">
  381. </el-col>
  382. </el-row>
  383. <el-row>
  384. <el-col :span="24">
  385. <el-form-item label="店铺介绍" prop="descs" >
  386. <el-input v-model="form.descs" placeholder="请输入店铺介绍" type="textarea" maxlength="100"/>
  387. </el-form-item>
  388. </el-col>
  389. </el-row>
  390. <el-row>
  391. <el-col :span="12">
  392. <el-form-item label="所属城市" prop="cityIds">
  393. <el-cascader
  394. ref="citySelect"
  395. v-model="form.cityIds"
  396. :options="citys"
  397. @change="handleCityChange">
  398. </el-cascader>
  399. </el-form-item>
  400. </el-col>
  401. <el-col :span="12">
  402. <el-form-item label="地址" prop="enterpriseAddress">
  403. <el-input v-model="form.enterpriseAddress" placeholder="请输入地址"/>
  404. </el-form-item>
  405. </el-col>
  406. </el-row>
  407. <el-row>
  408. <el-col :span="12">
  409. <el-form-item label="法人姓名" prop="legalPersonName">
  410. <el-input v-model="form.legalPersonName" placeholder="请输入法人姓名" />
  411. </el-form-item>
  412. </el-col>
  413. <el-col :span="12">
  414. <el-form-item label="统一社会信用代码" prop="unifiedSocialCreditCode">
  415. <el-input v-model="form.unifiedSocialCreditCode" placeholder="请输入统一社会信用代码" />
  416. </el-form-item>
  417. </el-col>
  418. </el-row>
  419. <el-form-item label="营业范围" prop="businessScope">
  420. <el-input v-model="form.businessScope" placeholder="请输入营业范围" type="textarea" />
  421. </el-form-item>
  422. <!-- 证书上传相关字段 -->
  423. <el-divider content-position="left">资质证书信息</el-divider>
  424. <el-row>
  425. <el-col :span="12">
  426. <el-form-item label="营业执照上传" prop="businessLicense">
  427. <el-upload
  428. class="avatar-uploader"
  429. :action="uploadUrl"
  430. :show-file-list="false"
  431. :on-success="(response, file) => handleFileSuccess(response, file, 'businessLicense')"
  432. :before-upload="beforeAvatarUpload"
  433. :disabled="isDeleting"
  434. >
  435. <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
  436. <div class="avatar-wrapper" v-if="form.businessLicense">
  437. <img :src="form.businessLicense" class="avatar" width="200px">
  438. <!-- 悬停显示的删除按钮 -->
  439. <!-- <div class="delete-mask" @click.stop="handleDelete5">-->
  440. <!-- <i class="el-icon-delete"></i>-->
  441. <!-- </div>-->
  442. <div class="button-group">
  443. <div class="preview-btn" @click.stop="previewImage(form.businessLicense)">
  444. <i class="el-icon-zoom-in"></i>
  445. </div>
  446. <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete5">
  447. <i class="el-icon-delete"></i>
  448. </div>
  449. </div>
  450. </div>
  451. <!-- 未上传图片时显示的默认图标 -->
  452. <div v-else class="no-image-placeholder">
  453. <span v-if="isViewMode">用户未上传</span>
  454. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  455. </div>
  456. </el-upload>
  457. </el-form-item>
  458. <el-col :span="12">
  459. <el-form-item label="营业执照编号" prop="businessCode" style="margin-left: 5px;margin-bottom: 20px">
  460. <el-input v-model="form.businessCode" placeholder="请输入营业制造编号" />
  461. </el-form-item>
  462. </el-col>
  463. </el-col>
  464. <el-col :span="12"></el-col>
  465. <el-col :span="12">
  466. <el-form-item label="营业执照是否长期有效" prop="isBusinessLicensePermanent">
  467. <el-switch
  468. @change="switchChange()"
  469. v-model="switchValue"
  470. active-color="#13ce66"
  471. inactive-color="#ff4949">
  472. </el-switch>
  473. </el-form-item>
  474. <el-form-item label="营业执照失效日期" prop="businessLicenseExpire" v-if="!switchValue">
  475. <el-date-picker
  476. v-model="form.businessLicenseExpire"
  477. type="daterange"
  478. value-format="yyyy-MM-dd"
  479. range-separator="至"
  480. start-placeholder="开始日期"
  481. end-placeholder="结束日期">
  482. </el-date-picker>
  483. </el-form-item>
  484. </el-col>
  485. </el-row>
  486. <div v-if="medicalMallConfig.isMedicalMall">
  487. <el-row>
  488. <el-col :span="12">
  489. <el-form-item label="药品经营许可证上传" prop="drugLicense">
  490. <el-upload
  491. class="avatar-uploader"
  492. :action="uploadUrl"
  493. :show-file-list="false"
  494. :on-success="(response, file) => handleFileSuccess(response, file, 'drugLicense')"
  495. :before-upload="beforeAvatarUpload"
  496. :disabled="isDeleting"
  497. >
  498. <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
  499. <div class="avatar-wrapper" v-if="form.drugLicense">
  500. <img :src="form.drugLicense" class="avatar" width="200px">
  501. <!-- 悬停显示的删除按钮 -->
  502. <!-- <div class="delete-mask" @click.stop="handleDelete6">-->
  503. <!-- <i class="el-icon-delete"></i>-->
  504. <!-- </div>-->
  505. <div class="button-group">
  506. <div class="preview-btn" @click.stop="previewImage(form.drugLicense)">
  507. <i class="el-icon-zoom-in"></i>
  508. </div>
  509. <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete6">
  510. <i class="el-icon-delete"></i>
  511. </div>
  512. </div>
  513. </div>
  514. <!-- 未上传图片时显示的默认图标 -->
  515. <div v-else class="no-image-placeholder">
  516. <span v-if="isViewMode">用户未上传</span>
  517. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  518. </div>
  519. </el-upload>
  520. </el-form-item>
  521. <el-col :sapn="24">
  522. <el-form-item label="药品经营许可证范围" prop="drugLicenseBusinessScope" style="margin-left: 5px">
  523. <el-input v-model="form.drugLicenseBusinessScope" placeholder="请输入药品经营许可证范围" type="textarea"/>
  524. </el-form-item>
  525. </el-col>
  526. <!-- 新增的单选框 -->
  527. <!-- <el-col :span="24">-->
  528. <!-- <el-form-item label="药品经营许可证范围是否包含" prop="drugScopeHasFrozen" style="margin-left: 5px">-->
  529. <!-- <el-radio-group v-model="form.drugScopeHasFrozen">-->
  530. <!-- <el-radio label="0">否</el-radio>-->
  531. <!-- <el-radio label="1">冷冻</el-radio>-->
  532. <!-- <el-radio label="2">冷藏</el-radio>-->
  533. <!-- <el-radio label="3">冷冻冷藏</el-radio>-->
  534. <!-- </el-radio-group>-->
  535. <!-- </el-form-item>-->
  536. <!-- </el-col>-->
  537. <!-- 结束 -->
  538. <el-col :span="14">
  539. <el-form-item label="药品经营许可证编号" prop="drugCode" style="margin-left: 5px">
  540. <el-input v-model="form.drugCode" placeholder="请输入药品经营许可证编号" />
  541. </el-form-item>
  542. </el-col>
  543. </el-col>
  544. <el-col :span="12">
  545. <el-form-item label="药品经营许可证有效期" prop="drugLicenseExpiry">
  546. <el-date-picker
  547. v-model="form.drugLicenseExpiry"
  548. type="daterange"
  549. value-format="yyyy-MM-dd"
  550. range-separator="至"
  551. start-placeholder="开始日期"
  552. end-placeholder="结束日期">
  553. </el-date-picker>
  554. </el-form-item>
  555. </el-col>
  556. </el-row>
  557. <el-row>
  558. <el-col :span="12">
  559. <el-form-item label="2类医疗器械备案证书上传" prop="medicalDevice2">
  560. <el-upload
  561. class="avatar-uploader"
  562. :action="uploadUrl"
  563. :show-file-list="false"
  564. :on-success="(response, file) => handleFileSuccess(response, file, 'medicalDevice2')"
  565. :before-upload="beforeAvatarUpload"
  566. :disabled="isDeleting"
  567. >
  568. <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
  569. <div class="avatar-wrapper" v-if="form.medicalDevice2">
  570. <img :src="form.medicalDevice2" class="avatar" width="200px">
  571. <!-- 悬停显示的删除按钮 -->
  572. <!-- <div class="delete-mask" @click.stop="handleDelete7">-->
  573. <!-- <i class="el-icon-delete"></i>-->
  574. <!-- </div>-->
  575. <div class="button-group">
  576. <div class="preview-btn" @click.stop="previewImage(form.medicalDevice2)">
  577. <i class="el-icon-zoom-in"></i>
  578. </div>
  579. <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete7">
  580. <i class="el-icon-delete"></i>
  581. </div>
  582. </div>
  583. </div>
  584. <!-- 未上传图片时显示的默认图标 -->
  585. <div v-else class="no-image-placeholder">
  586. <span v-if="isViewMode">用户未上传</span>
  587. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  588. </div>
  589. </el-upload>
  590. </el-form-item>
  591. <el-col :sapn="24">
  592. <el-form-item label="2类器械经营范围" prop="medicalDevice2BusinessScope" style="margin-left: 5px">
  593. <el-input v-model="form.medicalDevice2BusinessScope" placeholder="请输入2类器械经营范围" type="textarea"/>
  594. </el-form-item>
  595. </el-col>
  596. <el-col :span="14">
  597. <el-form-item label="2类器械生产备案编号" prop="medicalDevice2Code" style="margin-left: 5px">
  598. <el-input v-model="form.medicalDevice2Code" placeholder="请输入2类器械生产备案编号" />
  599. </el-form-item>
  600. </el-col>
  601. </el-col>
  602. <el-col :span="12"></el-col>
  603. <el-col :span="12">
  604. <el-form-item label="2类医疗器械备案是否长期有效" prop="isMedicalDevice2ExpiryPermanent">
  605. <el-switch
  606. @change="switchChange()"
  607. v-model="medicalDevice2ExpiryValue"
  608. active-color="#13ce66"
  609. inactive-color="#ff4949">
  610. </el-switch>
  611. </el-form-item>
  612. <el-form-item label="2类医疗器械备案有效期" prop="medicalDevice2Expiry" v-if="!medicalDevice2ExpiryValue">
  613. <el-date-picker
  614. v-model="form.medicalDevice2Expiry"
  615. type="daterange"
  616. value-format="yyyy-MM-dd"
  617. range-separator="至"
  618. start-placeholder="开始日期"
  619. end-placeholder="结束日期">
  620. </el-date-picker>
  621. </el-form-item>
  622. </el-col>
  623. </el-row>
  624. <el-row>
  625. <el-col :span="12">
  626. <el-form-item label="3类器械经营许可证上传" prop="medicalDevice3">
  627. <el-upload
  628. class="avatar-uploader"
  629. :action="uploadUrl"
  630. :show-file-list="false"
  631. :on-success="(response, file) => handleFileSuccess(response, file, 'medicalDevice3')"
  632. :before-upload="beforeAvatarUpload"
  633. :disabled="isDeleting"
  634. >
  635. <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
  636. <div class="avatar-wrapper" v-if="form.medicalDevice3">
  637. <img :src="form.medicalDevice3" class="avatar" width="200px">
  638. <!-- 悬停显示的删除按钮 -->
  639. <!-- <div class="delete-mask" @click.stop="handleDelete2">-->
  640. <!-- <i class="el-icon-delete"></i>-->
  641. <!-- </div>-->
  642. <div class="button-group">
  643. <div class="preview-btn" @click.stop="previewImage(form.medicalDevice3)">
  644. <i class="el-icon-zoom-in"></i>
  645. </div>
  646. <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete2">
  647. <i class="el-icon-delete"></i>
  648. </div>
  649. </div>
  650. </div>
  651. <!-- 未上传图片时显示的默认图标 -->
  652. <div v-else class="no-image-placeholder">
  653. <span v-if="isViewMode">用户未上传</span>
  654. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  655. </div>
  656. </el-upload>
  657. </el-form-item>
  658. <el-col :sapn="24">
  659. <el-form-item label="3类器械经营范围" prop="medicalDevice3BusinessScope" style="margin-left: 5px">
  660. <el-input v-model="form.medicalDevice3BusinessScope" placeholder="请输入3类器械经营范围" type="textarea"/>
  661. </el-form-item>
  662. </el-col>
  663. <el-form-item label="3类器械生产备案编号" prop="medicalDevice3Code" style="margin-left: 5px">
  664. <el-input v-model="form.medicalDevice3Code" placeholder="请输入3类器械生产备案编号" />
  665. </el-form-item>
  666. </el-col>
  667. <el-col :span="12"></el-col>
  668. <el-col :span="12">
  669. <el-form-item label="3类器械经营许可证有效期" prop="medicalDevice3Expiry">
  670. <el-date-picker
  671. v-model="form.medicalDevice3Expiry"
  672. type="daterange"
  673. value-format="yyyy-MM-dd"
  674. range-separator="至"
  675. start-placeholder="开始日期"
  676. end-placeholder="结束日期">
  677. </el-date-picker>
  678. </el-form-item>
  679. </el-col>
  680. </el-row>
  681. <el-row>
  682. <el-col :span="24">
  683. <el-form-item label="食品经营许可证/备案凭证上传" prop="foodLicense">
  684. <el-upload
  685. class="avatar-uploader"
  686. :action="uploadUrl"
  687. :show-file-list="false"
  688. :on-success="(response, file) => handleFoodLicenseSuccess(response, file)"
  689. :before-upload="beforeAvatarUpload"
  690. :disabled="isDeleting"
  691. :limit="3"
  692. :on-exceed="handleFoodLicenseExceed"
  693. >
  694. <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
  695. <div v-if="form.foodLicense && form.foodLicense.length > 0" class="food-license-container">
  696. <div v-for="(url, index) in form.foodLicense" :key="index" class="food-license-item">
  697. <div class="avatar-wrapper">
  698. <img :src="url" class="avatar small-avatar" />
  699. <div class="button-group">
  700. <div class="preview-btn" @click.stop="previewImage(url)">
  701. <i class="el-icon-zoom-in"></i>
  702. </div>
  703. <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDeleteFoodLicense(index)">
  704. <i class="el-icon-delete"></i>
  705. </div>
  706. </div>
  707. </div>
  708. </div>
  709. <!-- 添加上传按钮,当图片数量少于3张时显示 -->
  710. <div v-if="form.foodLicense.length < 3 && !isViewMode" class="avatar-wrapper add-btn small-avatar">
  711. <i class="el-icon-plus avatar-uploader-icon"></i>
  712. </div>
  713. </div>
  714. <!-- 未上传图片时显示的默认图标 -->
  715. <div v-else class="no-image-placeholder small-placeholder">
  716. <span v-if="isViewMode">用户未上传</span>
  717. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  718. </div>
  719. </el-upload>
  720. </el-form-item>
  721. <el-form-item label="食品经营许可证/备案凭证编号" prop="foodCode" style="margin-left: 5px">
  722. <el-input v-model="form.foodCode" placeholder="请输入食品经营许可证/备案凭证编号" />
  723. </el-form-item>
  724. </el-col>
  725. <el-col :span="12"></el-col>
  726. <el-col :span="12">
  727. <el-form-item label="食品经营许可证/备案凭证是否长期有效" prop="isFoodLicenseExpiryPermanent">
  728. <el-switch
  729. @change="switchChange()"
  730. v-model="foodLicenseExpiryValue"
  731. active-color="#13ce66"
  732. inactive-color="#ff4949">
  733. </el-switch>
  734. </el-form-item>
  735. <el-form-item label="食品经营许可证/备案凭证有效期" prop="foodLicenseExpiry" v-if="!foodLicenseExpiryValue">
  736. <el-date-picker
  737. v-model="form.foodLicenseExpiry"
  738. type="daterange"
  739. value-format="yyyy-MM-dd"
  740. range-separator="至"
  741. start-placeholder="开始日期"
  742. end-placeholder="结束日期">
  743. </el-date-picker>
  744. </el-form-item>
  745. </el-col>
  746. <el-col :sapn="24">
  747. <el-form-item label="食品经营许可证/备案凭证经营范围" prop="foodLicenseBusinessScope">
  748. <el-input v-model="form.foodLicenseBusinessScope" placeholder="请输入食品经营许可证/备案凭证经营范围" type="textarea"/>
  749. </el-form-item>
  750. </el-col>
  751. </el-row>
  752. </div>
  753. <div v-hasPermi="['his:store:AgreementSigned']">
  754. <el-divider content-position="left">签署协议与特殊资质信息</el-divider>
  755. <el-row :gutter="20">
  756. <el-col :span="8">
  757. <div class="agreement-section">
  758. <el-form-item label="其它资质-入驻协议">
  759. <el-input
  760. v-model="form.titleNameOne"
  761. placeholder="请输入标题"
  762. class="agreement-title"
  763. />
  764. <el-upload
  765. class="file-uploader"
  766. :action="uploadUrl"
  767. :show-file-list="false"
  768. :on-success="(response, file) => handleFileSuccess1(response, file, 'settlementAgreement')"
  769. :on-error="handleFileError"
  770. :before-upload="beforeFileUpload"
  771. :disabled="!!form.settlementAgreement"
  772. accept=".jpg,.jpeg,.png,.gif,.doc,.docx,.pdf"
  773. >
  774. <div v-if="form.settlementAgreement" class="uploaded-file">
  775. <img
  776. v-if="isImageFile(form.settlementAgreement, 'settlementAgreement')"
  777. :src="form.settlementAgreement"
  778. class="uploaded-img"
  779. width="100px"
  780. @click="viewAgreementFile('settlementAgreement')"
  781. />
  782. <div v-else class="document-icon" @click="viewAgreementFile('settlementAgreement')">
  783. <i :class="getDocumentIconClass(form.settlementAgreement, 'settlementAgreement')" class="icon"></i>
  784. <span class="file-name">{{ form.settlementAgreementFileName || getFileName(form.settlementAgreement) }}</span>
  785. </div>
  786. <i class="el-icon-delete delete-icon" @click.stop="handleFileRemove('settlementAgreement')"></i>
  787. </div>
  788. <div v-else class="upload-btn">
  789. <div class="upload-btn-inner">
  790. <i class="el-icon-plus"></i>
  791. <span class="upload-tip">点击上传</span>
  792. </div>
  793. </div>
  794. </el-upload>
  795. <el-form-item prop="settlementAgreementCode">
  796. <el-input
  797. v-model="form.settlementAgreementCode"
  798. placeholder="请输入备注内容"
  799. />
  800. </el-form-item>
  801. <el-form-item label="协议是否长期有效" prop="isEffectivePermanent1">
  802. <el-switch
  803. @change="switchChange()"
  804. v-model="medicalLicenseExpiryValue1"
  805. active-color="#13ce66"
  806. inactive-color="#ff4949">
  807. </el-switch>
  808. </el-form-item>
  809. <el-form-item
  810. label="协议有效期"
  811. prop="medicalLicenseExpiry"
  812. v-if="!medicalLicenseExpiryValue1"
  813. >
  814. <el-date-picker
  815. v-model="form.settlementAgreementExpiry"
  816. type="daterange"
  817. value-format="yyyy-MM-dd"
  818. range-separator="至"
  819. start-placeholder="开始日期"
  820. end-placeholder="结束日期" style="width: 100%">
  821. </el-date-picker>
  822. </el-form-item>
  823. </el-form-item>
  824. </div>
  825. </el-col>
  826. <el-col :span="8">
  827. <div class="agreement-section">
  828. <el-form-item label="质量保证协议">
  829. <el-input
  830. v-model="form.titleNameTwo"
  831. placeholder="请输入标题"
  832. class="agreement-title"
  833. />
  834. <el-upload
  835. class="file-uploader"
  836. :action="uploadUrl"
  837. :show-file-list="false"
  838. :on-success="(response, file) => handleFileSuccess1(response, file, 'qualityAssuranceAgreement')"
  839. :on-error="handleFileError"
  840. :before-upload="beforeFileUpload"
  841. :disabled="!!form.qualityAssuranceAgreement"
  842. accept=".jpg,.jpeg,.png,.gif,.doc,.docx,.pdf"
  843. >
  844. <div v-if="form.qualityAssuranceAgreement" class="uploaded-file">
  845. <img
  846. v-if="isImageFile(form.qualityAssuranceAgreement, 'qualityAssuranceAgreement')"
  847. :src="form.qualityAssuranceAgreement"
  848. class="uploaded-img"
  849. width="100px"
  850. @click="viewAgreementFile('qualityAssuranceAgreement')"
  851. />
  852. <div v-else class="document-icon" @click="viewAgreementFile('qualityAssuranceAgreement')">
  853. <i :class="getDocumentIconClass(form.qualityAssuranceAgreement, 'qualityAssuranceAgreement')" class="icon"></i>
  854. <span class="file-name">{{ form.qualityAssuranceAgreementFileName || getFileName(form.qualityAssuranceAgreement) }}</span>
  855. </div>
  856. <i class="el-icon-delete delete-icon" @click.stop="handleFileRemove('qualityAssuranceAgreement')"></i>
  857. </div>
  858. <div v-else class="upload-btn">
  859. <div class="upload-btn-inner">
  860. <i class="el-icon-plus"></i>
  861. <span class="upload-tip">点击上传</span>
  862. </div>
  863. </div>
  864. </el-upload>
  865. <el-form-item prop="qualityAssuranceAgreementCode">
  866. <el-input
  867. v-model="form.qualityAssuranceAgreementCode"
  868. placeholder="请输入备注内容"
  869. />
  870. </el-form-item>
  871. <el-form-item label="协议是否长期有效" prop="isEffectivePermanent2">
  872. <el-switch
  873. @change="switchChange()"
  874. v-model="medicalLicenseExpiryValue2"
  875. active-color="#13ce66"
  876. inactive-color="#ff4949">
  877. </el-switch>
  878. </el-form-item>
  879. <el-form-item
  880. label="协议有效期"
  881. prop="medicalLicenseExpiry"
  882. v-if="!medicalLicenseExpiryValue2"
  883. >
  884. <el-date-picker
  885. v-model="form.qualityAssuranceAgreementExpiry"
  886. type="daterange"
  887. value-format="yyyy-MM-dd"
  888. range-separator="至"
  889. start-placeholder="开始日期"
  890. end-placeholder="结束日期" style="width: 100%">
  891. </el-date-picker>
  892. </el-form-item>
  893. </el-form-item>
  894. </div>
  895. </el-col>
  896. <el-col :span="8">
  897. <div class="agreement-section">
  898. <el-form-item label="其它特殊资质">
  899. <el-input
  900. v-model="form.titleNameThree"
  901. placeholder="请输入标题"
  902. class="agreement-title"
  903. />
  904. <el-upload
  905. class="file-uploader"
  906. :action="uploadUrl"
  907. :show-file-list="false"
  908. :on-success="(response, file) => handleFileSuccess1(response, file, 'otherSpecialQualification')"
  909. :on-error="handleFileError"
  910. :before-upload="beforeFileUpload"
  911. :disabled="!!form.otherSpecialQualification"
  912. accept=".jpg,.jpeg,.png,.gif,.doc,.docx,.pdf"
  913. >
  914. <div v-if="form.otherSpecialQualification" class="uploaded-file">
  915. <img
  916. v-if="isImageFile(form.otherSpecialQualification, 'otherSpecialQualification')"
  917. :src="form.otherSpecialQualification"
  918. class="uploaded-img"
  919. width="100px"
  920. @click="viewAgreementFile('otherSpecialQualification')"
  921. />
  922. <div v-else class="document-icon" @click="viewAgreementFile('otherSpecialQualification')">
  923. <i :class="getDocumentIconClass(form.otherSpecialQualification, 'otherSpecialQualification')" class="icon"></i>
  924. <span class="file-name">{{ form.otherSpecialQualificationFileName || getFileName(form.otherSpecialQualification) }}</span>
  925. </div>
  926. <i class="el-icon-delete delete-icon" @click.stop="handleFileRemove('otherSpecialQualification')"></i>
  927. </div>
  928. <div v-else class="upload-btn">
  929. <div class="upload-btn-inner">
  930. <i class="el-icon-plus"></i>
  931. <span class="upload-tip">点击上传</span>
  932. </div>
  933. </div>
  934. </el-upload>
  935. <el-form-item prop="otherSpecialQualificationCode">
  936. <el-input
  937. v-model="form.otherSpecialQualificationCode"
  938. placeholder="请输入备注内容"
  939. />
  940. </el-form-item>
  941. <el-form-item label="协议是否长期有效" prop="isEffectivePermanent3">
  942. <el-switch
  943. @change="switchChange()"
  944. v-model="medicalLicenseExpiryValue3"
  945. active-color="#13ce66"
  946. inactive-color="#ff4949">
  947. </el-switch>
  948. </el-form-item>
  949. <el-form-item
  950. label="协议有效期"
  951. prop="medicalLicenseExpiry"
  952. v-if="!medicalLicenseExpiryValue3"
  953. >
  954. <el-date-picker
  955. v-model="form.otherSpecialQualificationExpiry"
  956. type="daterange"
  957. value-format="yyyy-MM-dd"
  958. range-separator="至"
  959. start-placeholder="开始日期"
  960. end-placeholder="结束日期" style="width: 100%">
  961. </el-date-picker>
  962. </el-form-item>
  963. </el-form-item>
  964. </div>
  965. </el-col>
  966. </el-row>
  967. </div>
  968. <el-divider content-position="left">店铺配置信息</el-divider>
  969. <el-col :span="12">
  970. <el-form-item label="网销报告" prop="reportUrl">
  971. <el-upload
  972. class="upload-demo"
  973. :action="uploadUrl"
  974. :on-remove="handleRemove"
  975. :before-remove="beforeRemove"
  976. :limit="1"
  977. :on-exceed="handleExceed"
  978. :on-success="(response, file) => handleReportUploadSuccess(response, file, 'reportUrl')"
  979. :before-upload="beforeReportUpload"
  980. :disabled="!!form.reportUrl"
  981. accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf"
  982. >
  983. <div class="report-file-wrapper" v-if="form.reportUrl">
  984. <img
  985. v-if="isImageFile(form.reportUrl)"
  986. :src="form.reportUrl"
  987. class="uploaded-file-thumb"
  988. width="100px"
  989. @click="viewReportFile('reportUrl')"
  990. />
  991. <div v-else class="document-file-icon" @click="viewReportFile('reportUrl')">
  992. <i class="el-icon-document"></i>
  993. <span class="file-name">{{ getFileName(form.reportUrl) }}</span>
  994. </div>
  995. </div>
  996. <div v-else class="upload-btn-wrapper">
  997. <el-button size="small" type="primary">点击上传</el-button>
  998. </div>
  999. <div v-if="form.reportUrl" class="report-preview-btn">
  1000. <el-button size="mini" type="success" @click.stop="viewReportFile('reportUrl')">查看已上传文件</el-button>
  1001. <el-button size="mini" type="danger" @click.stop="handleReportRemove('reportUrl')">删除</el-button>
  1002. </div>
  1003. </el-upload>
  1004. </el-form-item>
  1005. </el-col>
  1006. <el-col :span="12">
  1007. <el-form-item label="备案" prop="filingUrl">
  1008. <el-upload
  1009. class="upload-demo"
  1010. :action="uploadUrl"
  1011. :on-remove="handleRemove"
  1012. :before-remove="beforeRemove"
  1013. :limit="1"
  1014. :on-exceed="handleExceed"
  1015. :on-success="(response, file) => handleReportUploadSuccess(response, file, 'filingUrl')"
  1016. :before-upload="beforeReportUpload"
  1017. :disabled="!!form.filingUrl"
  1018. accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf"
  1019. >
  1020. <div class="report-file-wrapper" v-if="form.filingUrl">
  1021. <img
  1022. v-if="isImageFile(form.filingUrl)"
  1023. :src="form.filingUrl"
  1024. class="uploaded-file-thumb"
  1025. width="100px"
  1026. @click="viewReportFile('filingUrl')"
  1027. />
  1028. <div v-else class="document-file-icon" @click="viewReportFile('filingUrl')">
  1029. <i class="el-icon-document"></i>
  1030. <span class="file-name">{{ getFileName(form.filingUrl) }}</span>
  1031. </div>
  1032. </div>
  1033. <div v-else class="upload-btn-wrapper">
  1034. <el-button size="small" type="primary">点击上传</el-button>
  1035. </div>
  1036. <div v-if="form.filingUrl" class="report-preview-btn">
  1037. <el-button size="mini" type="success" @click.stop="viewReportFile('filingUrl')">查看已上传文件</el-button>
  1038. <el-button size="mini" type="danger" @click.stop="handleReportRemove('filingUrl')">删除</el-button>
  1039. </div>
  1040. </el-upload>
  1041. </el-form-item>
  1042. </el-col>
  1043. <el-form-item label="退货地址" prop="refundAddress">
  1044. <el-input v-model="form.refundAddress" placeholder="请输入退货地址" />
  1045. </el-form-item>
  1046. <el-row>
  1047. <el-col :span="12">
  1048. <el-form-item label="退货电话" prop="refundPhone">
  1049. <el-input v-model="form.refundPhone" placeholder="请输入退货电话" />
  1050. </el-form-item>
  1051. </el-col>
  1052. <el-col :span="12">
  1053. <el-form-item label="退货收货人" prop="refundConsignee">
  1054. <el-input v-model="form.refundConsignee" placeholder="请输入退货收货人" />
  1055. </el-form-item>
  1056. </el-col>
  1057. </el-row>
  1058. <el-form-item label="寄件人电话" prop="sendPhone">
  1059. <el-input v-model="form.sendPhone" placeholder="请输入寄件人电话" />
  1060. </el-form-item>
  1061. <el-row>
  1062. <el-col :span="12">
  1063. <el-form-item label="商品总数" prop="productCount">
  1064. <el-input-number v-model="form.productCount" :min="0" label="描述文字"></el-input-number>
  1065. </el-form-item>
  1066. </el-col>
  1067. <el-col :span="12">
  1068. <el-form-item label="销量" prop="salesCount">
  1069. <el-input-number v-model="form.salesCount" :min="0" label="描述文字"></el-input-number>
  1070. </el-form-item>
  1071. </el-col>
  1072. </el-row>
  1073. <el-row>
  1074. <el-col :span="12">
  1075. <el-form-item label="累计金额" prop="totalMoney">
  1076. <el-input-number v-model="form.totalMoney" :precision="2" :step="0.1"></el-input-number>
  1077. </el-form-item>
  1078. </el-col>
  1079. <el-col :span="12">
  1080. </el-col>
  1081. </el-row>
  1082. <el-row>
  1083. <el-col :span="12" v-if="false">
  1084. <el-form-item label="状态">
  1085. <el-radio-group v-model="form.status">
  1086. <el-radio
  1087. v-for="dict in statusOptions"
  1088. :key="dict.dictValue"
  1089. :label="parseInt(dict.dictValue)"
  1090. >{{dict.dictLabel}}</el-radio>
  1091. </el-radio-group>
  1092. </el-form-item>
  1093. </el-col>
  1094. <el-col :span="12" v-if="false">
  1095. <el-form-item label="分佣方式" prop="brokerageType">
  1096. <el-radio-group v-model="form.brokerageType" disabled>
  1097. <el-radio label="1" >每盒</el-radio>
  1098. <el-radio label="2" >总价</el-radio>
  1099. </el-radio-group>
  1100. </el-form-item>
  1101. </el-col>
  1102. </el-row>
  1103. <el-form-item label="配送方式" prop="shippingType" v-if="false">
  1104. <el-checkbox-group v-model="form.shippingType" size="medium">
  1105. <el-checkbox v-for="(item, index) in shippingTypeOptions" :key="index" :label="item.value"
  1106. :disabled="item.disabled">{{item.label}}</el-checkbox>
  1107. </el-checkbox-group>
  1108. </el-form-item>
  1109. <el-divider content-position="left">登录信息</el-divider>
  1110. <el-form-item label="登录帐号" prop="account" v-if="title != '修改店铺管理'">
  1111. <el-input v-model="form.account" placeholder="请输入登录帐号" />
  1112. </el-form-item>
  1113. <!-- tips-->
  1114. <span class="tip-text" v-if="title !== '修改店铺管理'">请及时修改密码,初试密码XyzAbc~12</span>
  1115. </el-form>
  1116. <div slot="footer" class="dialog-footer">
  1117. <el-button v-if="!isViewMode" type="primary" @click="submitForm">确 定</el-button>
  1118. <el-button @click="cancel">{{ isViewMode ? '关 闭' : '取 消' }}</el-button>
  1119. </div>
  1120. </el-dialog>
  1121. <!-- 图片预览对话框,支持放大缩小 -->
  1122. <el-dialog :visible.sync="imagePreviewVisible" width="1100px" append-to-body :modal-append-to-body="false" @close="onImagePreviewClose">
  1123. <div slot="title">
  1124. <span>图片预览</span>
  1125. <span style="margin-left: 16px; font-size: 13px; color: #909399;">{{ previewScale }}%</span>
  1126. </div>
  1127. <div
  1128. class="img-preview-body"
  1129. @wheel.prevent="onPreviewWheel"
  1130. @mousedown="onImgMouseDown"
  1131. @mousemove="onImgMouseMove"
  1132. @mouseup="onImgMouseUp"
  1133. @mouseleave="onImgMouseUp"
  1134. >
  1135. <img
  1136. :src="previewImageUrl"
  1137. :style="{
  1138. transform: `translate(${dragOffset.x}px, ${dragOffset.y}px) scale(${previewScale / 100})`,
  1139. transition: isDragging ? 'none' : 'transform .15s',
  1140. cursor: isDragging ? 'grabbing' : (previewScale > 100 ? 'grab' : 'default')
  1141. }"
  1142. style="max-width: 100%; max-height: 65vh; user-select: none;"
  1143. ref="previewImg"
  1144. @dragstart.prevent
  1145. />
  1146. </div>
  1147. <div slot="footer" class="dialog-footer" style="text-align: left;">
  1148. <el-button-group>
  1149. <el-button size="small" icon="el-icon-zoom-out" :disabled="previewScale <= 25" @click="zoomOut">缩小</el-button>
  1150. <el-button size="small" icon="el-icon-refresh" @click="resetZoom">复位</el-button>
  1151. <el-button size="small" icon="el-icon-zoom-in" :disabled="previewScale >= 300" @click="zoomIn">放大</el-button>
  1152. </el-button-group>
  1153. <el-button size="small" style="float: right;" @click="imagePreviewVisible = false">关 闭</el-button>
  1154. </div>
  1155. </el-dialog>
  1156. <!-- 设置ERP店铺信息对话框 -->
  1157. <el-dialog title="设置ERP店铺信息" :visible.sync="erpDialogVisible" width="600px" append-to-body :close-on-click-modal="false">
  1158. <el-form ref="erpForm" :model="erpForm" :rules="erpRules" label-width="140px">
  1159. <el-form-item label="店铺名称">
  1160. <el-input v-model="erpForm.storeName" disabled />
  1161. </el-form-item>
  1162. <el-form-item label="店铺编码" prop="shopCode" v-if="false">
  1163. <el-input v-model="erpForm.shopCode" placeholder="请输入店铺编码(选填)" maxlength="100" />
  1164. </el-form-item>
  1165. <el-form-item label="仓库编码" prop="warehouseCode">
  1166. <el-input v-model="erpForm.warehouseCode" placeholder="请输入仓库编码(选填)" maxlength="50" />
  1167. </el-form-item>
  1168. <el-form-item label="退件收货人" prop="returnReceiver">
  1169. <el-input v-model="erpForm.returnReceiver" placeholder="请输入退件收货人" maxlength="100" />
  1170. </el-form-item>
  1171. <el-form-item label="退件收货人手机号" prop="returnPhone">
  1172. <el-input v-model="erpForm.returnPhone" placeholder="请输入退件收货人手机号" maxlength="20" />
  1173. </el-form-item>
  1174. <el-form-item label="推荐收货地址" prop="returnAddress">
  1175. <el-input v-model="erpForm.returnAddress" type="textarea" :rows="3" placeholder="请输入推荐收货地址" maxlength="500" show-word-limit />
  1176. </el-form-item>
  1177. </el-form>
  1178. <div slot="footer" class="dialog-footer">
  1179. <el-button type="primary" @click="submitErpInfo" :loading="erpSubmitLoading">保 存</el-button>
  1180. <el-button @click="erpDialogVisible = false">取 消</el-button>
  1181. </div>
  1182. </el-dialog>
  1183. <el-dialog title="设置编码" :visible.sync="pharmacyCodeDialogVisible" width="500px" append-to-body :close-on-click-modal="false">
  1184. <el-form ref="pharmacyCodeForm" :model="pharmacyCodeForm" :rules="pharmacyCodeRules" label-width="120px">
  1185. <el-form-item label="店铺名称">
  1186. <el-input v-model="pharmacyCodeForm.storeName" disabled />
  1187. </el-form-item>
  1188. <el-form-item label="580编码" prop="pharmacyCode">
  1189. <el-input v-model="pharmacyCodeForm.pharmacyCode" placeholder="请输入580编码/药店编码" maxlength="64" />
  1190. </el-form-item>
  1191. </el-form>
  1192. <div slot="footer" class="dialog-footer">
  1193. <el-button type="primary" @click="submitPharmacyCode" :loading="pharmacyCodeSubmitLoading">保 存</el-button>
  1194. <el-button @click="pharmacyCodeDialogVisible = false">取 消</el-button>
  1195. </div>
  1196. </el-dialog>
  1197. <el-dialog
  1198. title="店铺资质消息提示"
  1199. :visible.sync="dialogVisible"
  1200. width="40%"
  1201. center>
  1202. <div v-for="(item,index) in promptList">({{index+1}})、{{item}}</div>
  1203. <span slot="footer" class="dialog-footer">
  1204. <el-button type="primary" @click="dialogVisible = false">已 知 晓</el-button>
  1205. </span>
  1206. </el-dialog>
  1207. </div>
  1208. </template>
  1209. <script>
  1210. import { listStore, getStore, delStore, addStore, updateStore, exportStore, refreshPasWod,exportFsStream, businessLicenseCheck, getStoreErpInfo, saveStoreErpInfo, enableStore, disableStore, updatePharmacyCode } from '@/api/hisStore/store'
  1211. import storeDetails from '../components/storeDetails.vue';
  1212. import StoreDialog from '../components/StoreDialog.vue';
  1213. import {getCitys} from "@/api/store/city";
  1214. import { getConfigByKey } from '@/api/system/config'
  1215. import { qualifications } from '@/api/system/user';
  1216. export default {
  1217. name: "Store",
  1218. components: { storeDetails, StoreDialog },
  1219. data() {
  1220. return {
  1221. reportFileList:[],
  1222. fileList:[],
  1223. previewImageUrl: '', // 添加预览图片URL
  1224. imagePreviewVisible: false,// 添加图片预览对话框可见性控制
  1225. previewScale: 100, // 图片预览缩放比例
  1226. dragOffset: { x: 0, y: 0 }, // 拖动偏移
  1227. isDragging: false, // 是否正在拖动
  1228. dragStart: { x: 0, y: 0 }, // 拖动起始坐标
  1229. // 新增:控制LOGO上传组件禁用状态
  1230. isDeleting: false,
  1231. promptList:[],
  1232. dialogVisible: false,
  1233. // ERP店铺信息弹窗
  1234. erpDialogVisible: false,
  1235. erpSubmitLoading: false,
  1236. erpForm: {
  1237. refId: null,
  1238. storeName: '',
  1239. shopCode: '',
  1240. warehouseCode: '',
  1241. returnReceiver: '',
  1242. returnPhone: '',
  1243. returnAddress: ''
  1244. },
  1245. erpRules: {
  1246. shopCode: [
  1247. ],
  1248. returnReceiver: [
  1249. { required: true, message: '请输入退件收货人', trigger: 'blur' }
  1250. ],
  1251. returnPhone: [
  1252. { required: true, message: '请输入退件收货人手机号', trigger: 'blur' },
  1253. { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
  1254. ],
  1255. returnAddress: [
  1256. { required: true, message: '请输入推荐收货地址', trigger: 'blur' }
  1257. ]
  1258. },
  1259. // 药店编码弹窗
  1260. pharmacyCodeDialogVisible: false,
  1261. pharmacyCodeSubmitLoading: false,
  1262. pharmacyCodeForm: {
  1263. storeId: null,
  1264. storeName: '',
  1265. pharmacyCode: ''
  1266. },
  1267. pharmacyCodeRules: {
  1268. pharmacyCode: [
  1269. { required: true, message: '请输入580编码', trigger: 'blur' }
  1270. ]
  1271. },
  1272. // 控制是否为查看模式(只读)
  1273. isViewMode: false,
  1274. // 店铺对话框相关
  1275. storeDialogVisible: false,
  1276. storeDialogMode: 'add', // add, edit, detail
  1277. currentStoreData: {},
  1278. auditLogs: [],
  1279. switchValue:false,
  1280. switchMedicalValue:false,
  1281. medicalDevice2ExpiryValue:false,
  1282. medicalLicenseExpiryValue:false,
  1283. foodLicenseExpiryValue:false,
  1284. medicalLicenseExpiryValue1:false,//协议有效期控制
  1285. medicalLicenseExpiryValue2:false,//协议有效期控制
  1286. medicalLicenseExpiryValue3:false,//协议有效期控制
  1287. shippingType: [],
  1288. medicalMallConfig:{},
  1289. citys: [],
  1290. licenseuploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS",
  1291. uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS",
  1292. baseUrl: process.env.VUE_APP_BASE_API,
  1293. shippingTypeOptions: [{
  1294. "label": "配送",
  1295. "value": "1"
  1296. }, {
  1297. "label": "自提",
  1298. "value": "2"
  1299. }, {
  1300. "label": "配送自提",
  1301. "value": "3"
  1302. }],
  1303. // 遮罩层
  1304. loading: true,
  1305. // 导出遮罩层
  1306. exportLoading: false,
  1307. enableLoading: false,
  1308. disableLoading: false,
  1309. originalForm: null,
  1310. excludedFields: [
  1311. 'storeId', 'createTime', 'updateTime',
  1312. 'balance', 'totalMoney', 'salesCount', 'productCount',
  1313. 'qualificationUpdateTime', 'nextQualificationUpdateTime', 'daysDiff', 'remainDays',
  1314. 'permStatus', 'storeSeq', 'merchantId', 'selectableProductTypes',
  1315. 'doctorList', 'queryStoreId', 'hasErpInfo',
  1316. 'shippingType', 'brokerageType', 'brokerageRate', 'status',
  1317. 'password', 'licenseImages'
  1318. ],
  1319. agreementFields: [
  1320. 'settlementAgreement', 'settlementAgreementFileName', 'settlementAgreementCode',
  1321. 'settlementAgreementStart', 'settlementAgreementEnd', 'settlementAgreementExpiry', 'settlementAgreementFileType',
  1322. 'qualityAssuranceAgreement', 'qualityAssuranceAgreementFileName', 'qualityAssuranceAgreementCode',
  1323. 'qualityAssuranceAgreementStart', 'qualityAssuranceAgreementEnd', 'qualityAssuranceAgreementExpiry', 'qualityAssuranceAgreementFileType',
  1324. 'otherSpecialQualification', 'otherSpecialQualificationFileName', 'otherSpecialQualificationCode',
  1325. 'otherSpecialQualificationStart', 'otherSpecialQualificationEnd', 'otherSpecialQualificationExpiry', 'otherSpecialQualificationFileType',
  1326. 'titleNameOne', 'titleNameTwo', 'titleNameThree',
  1327. 'isEffectivePermanent1', 'isEffectivePermanent2', 'isEffectivePermanent3'
  1328. ],
  1329. // 选中数组
  1330. ids: [],
  1331. // 非单个禁用
  1332. single: true,
  1333. // 非多个禁用
  1334. multiple: true,
  1335. // 显示搜索条件
  1336. showSearch: true,
  1337. // 总条数
  1338. total: 0,
  1339. // 店铺管理表格数据
  1340. storeList: [],
  1341. // 弹出层标题
  1342. title: "",
  1343. // 是否显示弹出层
  1344. open: false,
  1345. // 状态字典
  1346. statusOptions: [],
  1347. // 审核状态字典
  1348. isAuditOptions: [],
  1349. deliveryTypeOptions: [],
  1350. // 查询参数
  1351. queryParams: {
  1352. pageNum: 1,
  1353. pageSize: 10,
  1354. storeName: null,
  1355. address: null,
  1356. phone: null,
  1357. status: null,
  1358. isAudit: null,
  1359. account: null,
  1360. hasErpInfo: null,
  1361. pharmacyCodeFilter: null,
  1362. daysDiffMin: null, // 添加最小剩余天数查询条件
  1363. daysDiffMax: null // 添加最大剩余天数查询条件
  1364. },
  1365. // 表单参数
  1366. form: {
  1367. medicalDevice3BusinessScope: null,
  1368. medicalDevice2BusinessScope: null,
  1369. settlementAgreementFileType: '', // 入驻协议文件类型(如 application/pdf)
  1370. qualityAssuranceAgreementFileType: '', // 质量保证协议文件类型
  1371. otherSpecialQualificationFileType: '', // 其他特殊资质文件类型
  1372. settlementAgreement: null,
  1373. settlementAgreementFileName: null, // 新增:存储文件名
  1374. qualityAssuranceAgreement: null,
  1375. qualityAssuranceAgreementFileName: null, // 新增:存储文件名
  1376. otherSpecialQualification: null,
  1377. otherSpecialQualificationFileName: null, // 新增:存储文件名
  1378. foodLicense: [], // 食品经营许可证/备案凭证上传(支持多张图片)
  1379. },
  1380. // 表单校验
  1381. rules: {
  1382. drugLicenseBusinessScope: [
  1383. { required: true, message: "药品经营许可证范围不能为空", trigger: "blur" }
  1384. ],
  1385. // 添加新的验证规则
  1386. // drugScopeHasFrozen: [
  1387. // { required: true, message: "请选择药品经营许可证范围是否包含冷冻/冷藏", trigger: "change" }
  1388. // ],
  1389. storeName: [
  1390. { required: true, message: "店铺名称不能为空", trigger: "blur" }
  1391. ],
  1392. fullName: [
  1393. { required: true, message: "店铺名称不能为空", trigger: "blur" }
  1394. ],
  1395. businessLicenseExpire: [
  1396. { required: true, message: "营业执照失效日期不能为空", trigger: "blur" }
  1397. ],
  1398. businessLicense: [
  1399. { required: true, message: "营业执照不能为空", trigger: "blur" }
  1400. ],
  1401. businessCode:[
  1402. { required: true, message: "营业执照编号不能为空", trigger: "blur" }
  1403. ],
  1404. drugLicense: [
  1405. { required: true, message: "药品经营许可证不能为空", trigger: "blur" }
  1406. ],
  1407. drugCode:[
  1408. { required: true, message: "药品经营许可证编号不能为空", trigger: "blur" }
  1409. ],
  1410. drugLicenseExpiry: [
  1411. { required: true, message: "药品经营许可证有效期不能为空", trigger: "blur" }
  1412. ],
  1413. // medicalDevice3: [
  1414. // { required: true, message: "3类器械经营许可证不能为空", trigger: "blur" }
  1415. // ],
  1416. // medicalDevice3Code: [
  1417. // { required: true, message: "3类器械生产备案编号不能为空", trigger: "blur" }
  1418. // ],
  1419. // medicalDevice3Expiry: [
  1420. // { required: true, message: "3类器械经营许可证有效期不能为空", trigger: "blur" }
  1421. // ],
  1422. // foodLicense: [
  1423. // {
  1424. // validator: (rule, value, callback) => {
  1425. // if (!value || (Array.isArray(value) && value.length === 0)) {
  1426. // callback(new Error('请至少上传一张食品经营许可证图片'));
  1427. // } else {
  1428. // callback();
  1429. // }
  1430. // },
  1431. // trigger: 'change'
  1432. // }
  1433. // ],
  1434. // foodCode: [
  1435. // { required: true, message: "食品经营许可证编号不能为空", trigger: "blur" }
  1436. // ],
  1437. // foodLicenseExpiry: [
  1438. // { required: true, message: "食品经营许可证有效期不能为空", trigger: "blur" }
  1439. // ],
  1440. logoUrl: [
  1441. { required: true, message: "店铺LOGO不能为空", trigger: "blur" }
  1442. ],
  1443. cityIds: [
  1444. { required: true, message: "所属城市不能为空", trigger: "blur" }
  1445. ],
  1446. address: [
  1447. { required: true, message: "地址不能为空", trigger: "blur" }
  1448. ],
  1449. licenseImages: [
  1450. { required: true, message: "资质证书不能为空", trigger: "blur" }
  1451. ],
  1452. account: [
  1453. { required: true, message: "登录账号不能为空", trigger: "blur" }
  1454. ],
  1455. refundPhone: [
  1456. { required: true, message: "退货电话不能为空", trigger: "blur" }
  1457. ],
  1458. refundAddress: [
  1459. { required: true, message: "退货地址不能为空", trigger: "blur" }
  1460. ],
  1461. refundConsignee: [
  1462. { required: true, message: "退货收货人不能为空", trigger: "blur" }
  1463. ],
  1464. sendPhone: [
  1465. { required: true, message: "寄件人电话不能为空", trigger: "blur" },
  1466. ],
  1467. phone: [
  1468. {
  1469. pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
  1470. message: "请输入正确的手机号码",
  1471. trigger: "blur",
  1472. required: true
  1473. }
  1474. ],
  1475. // 新增字段校验规则
  1476. enterpriseShortName: [
  1477. { required: true, message: "企业简称不能为空", trigger: "blur" }
  1478. ],
  1479. enterpriseFullName: [
  1480. { required: true, message: "企业全称不能为空", trigger: "blur" }
  1481. ],
  1482. contactPhone: [
  1483. { required: true, message: "电话号码不能为空", trigger: "blur" }
  1484. ],
  1485. enterpriseAddress: [
  1486. { required: true, message: "企业地址不能为空", trigger: "blur" }
  1487. ],
  1488. legalPersonName: [
  1489. { required: true, message: "法人姓名不能为空", trigger: "blur" }
  1490. ],
  1491. unifiedSocialCreditCode: [
  1492. { required: true, message: "统一社会信用代码不能为空", trigger: "blur" }
  1493. ],
  1494. businessScope: [
  1495. { required: true, message: "营业范围不能为空", trigger: "blur" }
  1496. ],
  1497. password: [
  1498. { required: true, message: "新密码不能为空", trigger: "blur" },
  1499. { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
  1500. ],
  1501. }
  1502. };
  1503. },
  1504. created() {
  1505. this.getCitys();
  1506. this.getList();
  1507. getConfigByKey("medicalMall.func.switch").then(response => {
  1508. if(response.data && response.data.configValue) {
  1509. this.medicalMallConfig = JSON.parse(response.data.configValue);
  1510. }
  1511. });
  1512. this.getDicts("sys_company_status").then(response => {
  1513. this.statusOptions = response.data;
  1514. });
  1515. this.getDicts("sys_company_isaudit").then(response => {
  1516. this.isAuditOptions = response.data;
  1517. });
  1518. this.getDicts("sys_store_delivery_type").then(response => {
  1519. this.deliveryTypeOptions = response.data;
  1520. });
  1521. this.$nextTick(()=>{
  1522. console.log("是否执行资质提示方法")
  1523. this.handleNoticeInfo();
  1524. })
  1525. },
  1526. methods: {
  1527. // 处理提醒状态筛选
  1528. handleRemindFilter(type) {
  1529. // 重置其他查询条件
  1530. this.resetForm("queryForm");
  1531. // 根据不同类型设置查询参数
  1532. switch (type) {
  1533. case 'overdue': // 严重逾期
  1534. this.queryParams.daysDiffMin = null;
  1535. this.queryParams.daysDiffMax = 0;
  1536. break;
  1537. case 'urgent': // 紧急提醒 (7天内)
  1538. this.queryParams.daysDiffMin = 0;
  1539. this.queryParams.daysDiffMax = 7;
  1540. break;
  1541. case 'important': // 重点提醒 (15天内)
  1542. this.queryParams.daysDiffMin = 0;
  1543. this.queryParams.daysDiffMax = 15;
  1544. break;
  1545. case 'warning': // 常规预警 (30天内)
  1546. this.queryParams.daysDiffMin = 0;
  1547. this.queryParams.daysDiffMax = 30;
  1548. break;
  1549. default: // 默认情况,清空条件
  1550. this.queryParams.daysDiffMin = null;
  1551. this.queryParams.daysDiffMax = null;
  1552. break;
  1553. }
  1554. this.handleQuery();
  1555. },
  1556. // 获取提醒标签类型
  1557. getRemindTagType(daysDiff) {
  1558. if (daysDiff < 0) {
  1559. return 'danger'; // 严重逾期 - 红色
  1560. } else if (daysDiff <= 7) {
  1561. return 'warning'; // 紧急提醒 - 橙色
  1562. } else if (daysDiff <= 15) {
  1563. return ''; // 重点提醒 - 黄色 (Element UI 中空字符串是黄色)
  1564. } else if (daysDiff <= 30) {
  1565. return 'primary'; // 常规预警 - 蓝色 (Element UI 中 primary 是蓝色)
  1566. }
  1567. return 'info'; // 其他情况 - 灰色
  1568. },
  1569. // 获取提醒标签名称
  1570. getRemindTagName(daysDiff) {
  1571. if (daysDiff < 0) {
  1572. return '逾期';
  1573. } else if (daysDiff <= 7) {
  1574. return '7天内到期';
  1575. } else if (daysDiff <= 15) {
  1576. return '15天内到期';
  1577. } else if (daysDiff <= 30) {
  1578. return '30天内到期';
  1579. }
  1580. return '正常';
  1581. },
  1582. // 添加图片预览方法
  1583. previewImage(url) {
  1584. this.previewImageUrl = url
  1585. this.previewScale = 100
  1586. this.imagePreviewVisible = true
  1587. },
  1588. handleNoticeInfo() {
  1589. qualifications()
  1590. .then(response => {
  1591. console.log("noticeInfo接口完整响应:", response);
  1592. if (response.code === 200) {
  1593. this.promptList = response.data;
  1594. if (this.promptList && this.promptList.length > 0) {
  1595. this.dialogVisible = true;
  1596. }
  1597. console.log("通知信息请求完成!", this.promptList);
  1598. } else {
  1599. console.warn("接口返回非成功状态:", response.code);
  1600. }
  1601. })
  1602. .catch(err => {
  1603. console.error("获取通知信息失败:", err);
  1604. this.$message.error("加载通知信息失败,请稍后重试");
  1605. });
  1606. },
  1607. // 在 methods 中添加新的方法
  1608. checkBusinessLicense(imageUrl) {
  1609. if (!imageUrl) return;
  1610. // 使用正确的参数格式调用接口
  1611. businessLicenseCheck(imageUrl).then(response => {
  1612. if (response.code === 200) {
  1613. if (!response.data.flag) {
  1614. // 检查失败,显示错误信息
  1615. this.$message.error(response.data.message || '营业执照校验失败');
  1616. // 清除刚上传的图片
  1617. this.form.businessLicense = '';
  1618. this.$forceUpdate();
  1619. }else {
  1620. // 检查成功,回填数据
  1621. this.form.legalPersonName = response.data.person; // 法人姓名
  1622. this.form.unifiedSocialCreditCode = response.data.regNum; // 统一社会信用代码
  1623. this.form.businessScope = response.data.businessStr; // 营业范围
  1624. this.form.businessCode = response.data.regNum; // 营业执照编号
  1625. }
  1626. } else {
  1627. this.$message.error('营业执照校验接口调用失败');
  1628. }
  1629. }).catch(error => {
  1630. console.error('营业执照校验失败:', error);
  1631. this.$message.error('营业执照校验失败');
  1632. });
  1633. },
  1634. handleCityChange(value) {
  1635. var nodes = this.$refs.citySelect.getCheckedNodes();
  1636. this.form.address = nodes[0].pathLabels[0] + nodes[0].pathLabels[1] + nodes[0].pathLabels[2];
  1637. this.form.cityIds = value.toString();
  1638. },
  1639. getCitys() {
  1640. getCitys().then(res => {
  1641. this.loading = false;
  1642. this.citys = res.data;
  1643. })
  1644. },
  1645. handleAvatarSuccess(res, file) {
  1646. if (res.code === 200) {
  1647. this.form.logoUrl = res.url;
  1648. this.$forceUpdate()
  1649. } else {
  1650. this.msgError(res.msg);
  1651. }
  1652. },
  1653. beforeAvatarUpload(file) {
  1654. const isLt1M = file.size / 1024 / 1024 < 1;
  1655. if (!isLt1M) {
  1656. this.$message.error('上传图片大小不能超过 1MB!');
  1657. }
  1658. return isLt1M;
  1659. },
  1660. // 通用文件上传成功处理函数
  1661. handleFileSuccess(response, file, field) {
  1662. if (response.code === 200) {
  1663. this.$set(this.form, field, response.url);
  1664. this.$forceUpdate();
  1665. // 如果是营业执照上传,则进行检查
  1666. if (field === 'businessLicense') {
  1667. this.checkBusinessLicense(response.url);
  1668. }
  1669. } else {
  1670. this.msgError(response.msg);
  1671. }
  1672. },
  1673. // 食品经营许可证上传成功处理函数
  1674. handleFoodLicenseSuccess(response, file) {
  1675. if (response.code === 200) {
  1676. // 初始化数组(如果尚未初始化)
  1677. if (!Array.isArray(this.form.foodLicense)) {
  1678. this.$set(this.form, 'foodLicense', []);
  1679. }
  1680. // 添加新上传的图片URL到数组中
  1681. this.form.foodLicense.push(response.url);
  1682. this.$forceUpdate();
  1683. } else {
  1684. this.msgError(response.msg);
  1685. }
  1686. },
  1687. // 食品经营许可证上传超出限制处理函数
  1688. handleFoodLicenseExceed(files, fileList) {
  1689. this.$message.warning(`当前最多只能上传 3 张图片`);
  1690. },
  1691. /** 查询店铺管理列表 */
  1692. getList() {
  1693. this.loading = true;
  1694. listStore(this.queryParams).then(response => {
  1695. this.storeList = response.rows;
  1696. this.total = response.total;
  1697. this.loading = false;
  1698. });
  1699. },
  1700. // 取消按钮
  1701. cancel() {
  1702. this.open = false;
  1703. this.reset();
  1704. },
  1705. // 表单重置
  1706. reset() {
  1707. this.switchValue = false;
  1708. this.switchMedicalValue=false;
  1709. this.isDeleting = false;
  1710. this.reportFileList = [];
  1711. this.fileList = [];
  1712. this.originalForm = null;
  1713. this.form = {
  1714. storeId: null,
  1715. cityIds: null,
  1716. storeName: null,
  1717. descs: null,
  1718. logoUrl: null,
  1719. address: null,
  1720. lng: null,
  1721. lat: null,
  1722. phone: null,
  1723. licenseImages: null,
  1724. productCount: null,
  1725. status: 0,
  1726. createTime: null,
  1727. updateTime: null,
  1728. salesCount: null,
  1729. balance: null,
  1730. totalMoney: null,
  1731. isAudit: 0,
  1732. account: null,
  1733. password: null,
  1734. shippingType: ["1"],
  1735. brokerageType: "1",
  1736. brokerageRate: 0,
  1737. fullName: null,
  1738. // 重置新增字段
  1739. enterpriseShortName: null, // 企业简称
  1740. enterpriseFullName: null, // 企业全称
  1741. contactPhone: null, // 联系电话
  1742. enterpriseAddress: null, // 企业地址
  1743. legalPersonName: null, // 法人姓名
  1744. unifiedSocialCreditCode: null, // 统一社会信用代码
  1745. businessScope: null, // 营业范围
  1746. // 重置证书相关字段
  1747. businessLicense: null, // 营业执照文件
  1748. businessLicenseExpire: null, // 营业执照失效日期
  1749. drugLicense: null, // 药品经营许可证有效期
  1750. drugLicenseExpiry: null, // 药品经营许可证文件
  1751. // 医疗器械相关证书
  1752. medicalDevice1: null, // 一类医疗器械备案证书
  1753. medicalDevice1Expiry: null, // 二类医疗器械备案有效期
  1754. medicalDevice2: null, // 二类器械生产备案文件
  1755. medicalDevice2Expiry: null, // 一类生产备案有效期
  1756. medicalDevice3: null, // 三类器械经营许可证文件
  1757. medicalDevice3Expiry: null, // 三类器械经营许可证有效期
  1758. // 其他许可证相关字段
  1759. foodLicense: [], // 食品经营许可证文件(支持多张图片)
  1760. foodLicenseExpiry: null, // 食品经营许可证有效期
  1761. medicalLicense: null, // 医疗机构执业许可证文件
  1762. medicalLicenseExpiry: null, // 医疗机构执业许可证有效期
  1763. settlementAgreement: null, //其它资质-入驻协议
  1764. settlementAgreementFileName: null,
  1765. qualityAssuranceAgreementFileName: null, // 新增:质量保证协议文件名
  1766. otherSpecialQualificationFileName: null,// 新增:其他特殊资质文件名
  1767. settlementAgreementExpiry: null,//其它资质-有效期
  1768. qualityAssuranceAgreement: null,//质量保证协议
  1769. qualityAssuranceAgreementExpiry: null,//质量保证协议有效期
  1770. otherSpecialQualification: null,//其它特殊资质
  1771. otherSpecialQualificationExpiry: null,//其它特殊资质有效期
  1772. businessCode: null,
  1773. drugLicenseBusinessScope:null,
  1774. drugScopeHasFrozen: 0,
  1775. drugCode:null,
  1776. medicalDevice1Code:null,
  1777. medicalDevice2Code:null,
  1778. medicalDevice3Code:null,
  1779. foodCode:null,
  1780. medicalCode:null,
  1781. otherSpecialQualificationCode:null,
  1782. qualityAssuranceAgreementCode:null,
  1783. settlementAgreementCode: null,
  1784. titleNameOne: null,
  1785. titleNameTwo: null,
  1786. titleNameThree: null,
  1787. settlementAgreementFileType: '',
  1788. qualityAssuranceAgreementFileType: '',
  1789. otherSpecialQualificationFileType: ''
  1790. };
  1791. this.resetForm("form");
  1792. },
  1793. /** 搜索按钮操作 */
  1794. handleQuery() {
  1795. this.queryParams.pageNum = 1;
  1796. this.getList();
  1797. },
  1798. /** 重置按钮操作 */
  1799. resetQuery() {
  1800. this.queryParams.daysDiffMin = null;
  1801. this.queryParams.daysDiffMax = null;
  1802. this.resetForm("queryForm");
  1803. this.handleQuery();
  1804. },
  1805. // 多选框选中数据
  1806. handleSelectionChange(selection) {
  1807. this.ids = selection.map(item => item.storeId)
  1808. this.single = selection.length !== 1
  1809. this.multiple = !selection.length
  1810. },
  1811. /** 新增按钮操作 */
  1812. handleAdd() {
  1813. this.reset();
  1814. this.isViewMode = false; // 新增时可编辑
  1815. this.open = true;
  1816. this.title = "添加店铺";
  1817. },
  1818. // 修复LOGO删除逻辑:确保删除后可重新上传
  1819. handleDeleteLogo() {
  1820. this.deleteImage('logoUrl', 'Logo');
  1821. },
  1822. handleDelete2() {
  1823. this.deleteImage('medicalDevice3', '3类器械经营许可证');
  1824. },
  1825. // 删除指定索引的食品经营许可证图片
  1826. handleDeleteFoodLicense(index) {
  1827. this.$confirm(`确定要删除这张食品经营许可证图片吗?`, '提示', {
  1828. confirmButtonText: '确定',
  1829. cancelButtonText: '取消',
  1830. type: 'warning'
  1831. }).then(() => {
  1832. this.form.foodLicense.splice(index, 1);
  1833. this.$message.success('图片已删除');
  1834. this.$forceUpdate();
  1835. }).catch(() => {
  1836. this.$message.info('已取消删除');
  1837. });
  1838. },
  1839. handleDelete5() {
  1840. this.deleteImage('businessLicense', '营业执照');
  1841. },
  1842. handleDelete6() {
  1843. this.deleteImage('drugLicense', '药品经营许可证');
  1844. },
  1845. handleDelete7() {
  1846. this.deleteImage('medicalDevice2', '2类医疗器械备案证书');
  1847. },
  1848. // 通用图片删除方法
  1849. deleteImage(field, itemType) {
  1850. this.isDeleting = true; // 临时禁用上传组件
  1851. this.$confirm(`确定要删除这张${itemType}吗?`, '提示', {
  1852. confirmButtonText: '确定',
  1853. cancelButtonText: '取消',
  1854. type: 'warning'
  1855. }).then(() => {
  1856. this.form[field] = ''; // 清空图片URL
  1857. this.$message.success(`${itemType}已删除`);
  1858. }).catch(() => {
  1859. this.$message.info('已取消删除');
  1860. }).finally(() => {
  1861. this.isDeleting = false; // 无论操作结果,恢复上传组件可用
  1862. this.$forceUpdate(); // 强制刷新确保状态同步
  1863. });
  1864. },
  1865. /** 修改/详情按钮操作 */
  1866. handleUpdate(row, isEdit = true) {
  1867. this.reset();
  1868. this.isViewMode = !isEdit; // 设置是否为查看模式
  1869. const storeId = row.storeId || this.ids
  1870. getStore(storeId).then(response => {
  1871. this.form = response.data;
  1872. // 确保 brokerageType 是字符串类型
  1873. if (this.form.brokerageType) {
  1874. this.form.brokerageType = this.form.brokerageType.toString();
  1875. }
  1876. // 如果后端返回的数据中没有这个字段,则设置默认值
  1877. if (this.form.drugScopeHasFrozen === undefined) {
  1878. this.form.drugScopeHasFrozen = 0;
  1879. }
  1880. this.switchValue = this.form.isBusinessLicensePermanent == 1;
  1881. this.switchMedicalValue = this.form.isMedicalDevice1ExpiryPermanent == 1
  1882. this.medicalDevice2ExpiryValue = this.form.isMedicalDevice2ExpiryPermanent == 1
  1883. this.medicalLicenseExpiryValue = this.form.isMedicalLicenseExpiryPermanent == 1
  1884. this.medicalLicenseExpiryValue1 = this.form.isEffectivePermanent1 == 1;
  1885. this.foodLicenseExpiryValue = this.form.isFoodLicenseExpiryPermanent == 1;
  1886. this.medicalLicenseExpiryValue2 = this.form.isEffectivePermanent2 == 1;
  1887. this.medicalLicenseExpiryValue3 = this.form.isEffectivePermanent3 == 1
  1888. this.open = true;
  1889. this.title = this.isViewMode ? "店铺详情" : "修改店铺";
  1890. let str = this.form.shippingType
  1891. this.form.shippingType = str.split(",")
  1892. this.form.cityIds = ((this.form.cityIds).split(",")).map(Number)
  1893. const dateFields = [
  1894. 'drugLicenseExpiry',
  1895. 'medicalDevice1Expiry',
  1896. 'medicalDevice2Expiry',
  1897. 'medicalDevice3Expiry',
  1898. 'foodLicenseExpiry',
  1899. 'medicalLicenseExpiry',
  1900. 'businessLicenseExpire'
  1901. ];
  1902. dateFields.forEach(field => {
  1903. const startField = field + 'Start';
  1904. const endField = field + 'End';
  1905. if (this.form[startField] && this.form[endField]) {
  1906. this.$set(this.form, field, [this.form[startField], this.form[endField]]);
  1907. }
  1908. });
  1909. // 入驻协议有效期
  1910. if (this.form.settlementAgreementStart && this.form.settlementAgreementEnd) {
  1911. this.$set(this.form, 'settlementAgreementExpiry', [
  1912. this.form.settlementAgreementStart,
  1913. this.form.settlementAgreementEnd
  1914. ]);
  1915. }
  1916. // 质量保证协议有效期
  1917. if (this.form.qualityAssuranceAgreementStart && this.form.qualityAssuranceAgreementEnd) {
  1918. this.$set(this.form, 'qualityAssuranceAgreementExpiry', [
  1919. this.form.qualityAssuranceAgreementStart,
  1920. this.form.qualityAssuranceAgreementEnd
  1921. ]);
  1922. }
  1923. // 其它特殊资质有效期
  1924. if (this.form.otherSpecialQualificationStart && this.form.otherSpecialQualificationEnd) {
  1925. this.$set(this.form, 'otherSpecialQualificationExpiry', [
  1926. this.form.otherSpecialQualificationStart,
  1927. this.form.otherSpecialQualificationEnd
  1928. ]);
  1929. }
  1930. this.reportFileList = this.urlToFileList(this.form.reportUrl);
  1931. this.fileList = this.urlToFileList(this.form.filingUrl);
  1932. // 处理食品经营许可证图片数据,支持逗号分隔的字符串
  1933. if (this.form.foodLicense) {
  1934. if (typeof this.form.foodLicense === 'string') {
  1935. // 如果是逗号分隔的字符串,则分割成数组
  1936. this.form.foodLicense = this.form.foodLicense.split(',').filter(url => url.trim() !== '');
  1937. } else if (!Array.isArray(this.form.foodLicense)) {
  1938. // 如果既不是字符串也不是数组,则初始化为空数组
  1939. this.form.foodLicense = [];
  1940. }
  1941. } else {
  1942. // 如果为空,则初始化为空数组
  1943. this.form.foodLicense = [];
  1944. }
  1945. this.originalForm = JSON.parse(JSON.stringify(this.form));
  1946. });
  1947. },
  1948. // 验证所有执照有效性验证方法
  1949. validateLicenses() {
  1950. const currentDate = new Date();
  1951. //营业执照证
  1952. if(!this.switchValue){
  1953. const businessLicenseExpireEndDate = new Date(this.form.businessLicenseExpire[1]);
  1954. if (businessLicenseExpireEndDate < currentDate) {
  1955. this.$message.warning('营业执照证已过期,无法提交');
  1956. return false;
  1957. }
  1958. }
  1959. //药品经营许
  1960. const drugLicenseExpiryEndDate = new Date(this.form.drugLicenseExpiry[1]);
  1961. if (drugLicenseExpiryEndDate < currentDate) {
  1962. this.$message.warning('药品经营许可证已过期,无法提交');
  1963. return false;
  1964. }
  1965. //2类
  1966. if(!!this.form.medicalDevice2 && !this.medicalDevice2ExpiryValue){
  1967. if(!this.form.medicalDevice2Expiry){
  1968. this.$message.warning('2类医疗器械备案有效期不为空!');
  1969. return false;
  1970. }else{
  1971. const medicalDevice2ExpiryEndDate = new Date(this.form.medicalDevice2Expiry[1]);
  1972. if (medicalDevice2ExpiryEndDate < currentDate) {
  1973. this.$message.warning('2类医疗器械可证已过期,无法提交');
  1974. return false;
  1975. }
  1976. }
  1977. }
  1978. //3类医疗器械备案
  1979. if(!!this.form.medicalDevice3 && !this.medicalDevice3ExpiryValue){
  1980. if(!this.form.medicalDevice3Expiry){
  1981. this.$message.warning('3类医疗器械备案有效期不为空!');
  1982. return false;
  1983. }else{
  1984. const medicalDevice3ExpiryEndDate = new Date(this.form.medicalDevice3Expiry[1]);
  1985. if (medicalDevice3ExpiryEndDate < currentDate) {
  1986. this.$message.warning('3类医疗器械可证已过期,无法提交');
  1987. return false;
  1988. }
  1989. }
  1990. }
  1991. //食品经营许可证
  1992. if(this.form.foodLicense.length > 0 && !this.foodLicenseExpiryValue){
  1993. if(!this.form.foodLicenseExpiry){
  1994. this.$message.warning('食品经营许可证/备案凭证有效期不为空!');
  1995. return false;
  1996. }else{
  1997. const foodLicenseExpiryEndDate = new Date(this.form.foodLicenseExpiry[1]);
  1998. if (foodLicenseExpiryEndDate < currentDate) {
  1999. this.$message.warning('食品经营许可证/备案凭证已过期,无法提交');
  2000. return false;
  2001. }
  2002. }
  2003. }
  2004. return true;
  2005. },
  2006. /** 提交按钮 */
  2007. submitForm() {
  2008. this.$refs["form"].validate(valid => {
  2009. if (valid) {
  2010. // 添加所有执照有效性检查
  2011. if (!this.validateLicenses()) {
  2012. return; // 验证失败,停止提交
  2013. }
  2014. const isEdit = this.form.storeId != null;
  2015. let isAgreementOnlySave = false;
  2016. if (isEdit && this.originalForm) {
  2017. const changedFields = this.getChangedFields(this.originalForm, this.form);
  2018. if (changedFields.length === 0) {
  2019. this.$message.warning("未检测到任何修改,无需提交");
  2020. return;
  2021. }
  2022. const agreementFieldSet = this.getAgreementFieldSet();
  2023. isAgreementOnlySave = changedFields.every(f => agreementFieldSet.has(f));
  2024. }
  2025. // 处理表单数据
  2026. const formData = Object.assign({}, this.form);
  2027. //清空非必填日期控件
  2028. if(formData.medicalDevice2Expiry == null){
  2029. formData.medicalDevice2ExpiryEnd = null;
  2030. formData.medicalDevice2ExpiryStart = null;
  2031. }
  2032. if(formData.medicalDevice3Expiry == null){
  2033. formData.medicalDevice3ExpiryEnd = null;
  2034. formData.medicalDevice3ExpiryStart = null;
  2035. }
  2036. if(formData.foodLicenseExpiry == null){
  2037. formData.foodLicenseExpiryEnd = null;
  2038. formData.foodLicenseExpiryStart = null;
  2039. }
  2040. // 处理城市ID
  2041. if (formData.cityIds) {
  2042. formData.cityIds = formData.cityIds.toString();
  2043. }
  2044. // 处理配送方式
  2045. if (formData.shippingType) {
  2046. formData.shippingType = formData.shippingType.toString();
  2047. }
  2048. // 处理日期范围字段
  2049. const dateRangeFields = [
  2050. 'drugLicenseExpiry',
  2051. 'medicalDevice2Expiry',
  2052. 'medicalDevice1Expiry',
  2053. 'medicalDevice3Expiry',
  2054. 'foodLicenseExpiry',
  2055. 'medicalLicenseExpiry',
  2056. 'businessLicenseExpire'
  2057. ];
  2058. dateRangeFields.forEach(field => {
  2059. if (formData[field] && formData[field].length === 2) {
  2060. formData[`${field}Start`] = formData[field][0];
  2061. formData[`${field}End`] = formData[field][1];
  2062. }
  2063. });
  2064. //其他执照处理
  2065. const agreementFields = [
  2066. {
  2067. expiryField: 'settlementAgreementExpiry',
  2068. startField: 'settlementAgreementStart',
  2069. endField: 'settlementAgreementEnd',
  2070. permanentFlag: this.medicalLicenseExpiryValue1,
  2071. message: '其它资质-入驻协议,有效期开始日期或结束日期不能为空!'
  2072. },
  2073. {
  2074. expiryField: 'qualityAssuranceAgreementExpiry',
  2075. startField: 'qualityAssuranceAgreementStart',
  2076. endField: 'qualityAssuranceAgreementEnd',
  2077. permanentFlag: this.medicalLicenseExpiryValue2,
  2078. message: '质量保证协议,有效期开始日期或结束日期不能为空!'
  2079. },
  2080. {
  2081. expiryField: 'otherSpecialQualificationExpiry',
  2082. startField: 'otherSpecialQualificationStart',
  2083. endField: 'otherSpecialQualificationEnd',
  2084. permanentFlag: this.medicalLicenseExpiryValue3,
  2085. message: '其它特殊资质,有效期开始日期或结束日期不能为空!'
  2086. }
  2087. ];
  2088. for (const field of agreementFields) {
  2089. if (field.permanentFlag) continue;
  2090. if (formData[field.expiryField] && formData[field.expiryField].length === 2) {
  2091. formData[field.startField] = formData[field.expiryField][0];
  2092. formData[field.endField] = formData[field.expiryField][1];
  2093. } else {
  2094. if (formData[field.expiryField.replace('Expiry', '')] != null) {
  2095. return this.$message.warning(field.message);
  2096. }
  2097. }
  2098. }
  2099. // 处理各类许可证是否永久有效的开关状态
  2100. formData.isFoodLicenseExpiryPermanent = this.foodLicenseExpiryValue ? 1 : 0;
  2101. formData.isBusinessLicensePermanent = this.switchValue ? 1 : 0;
  2102. formData.isMedicalDevice1ExpiryPermanent = this.switchMedicalValue ? 1 : 0;
  2103. formData.isMedicalDevice2ExpiryPermanent = this.medicalDevice2ExpiryValue ? 1 : 0;
  2104. formData.isMedicalLicenseExpiryPermanent = this.medicalLicenseExpiryValue ? 1 : 0;
  2105. formData.isEffectivePermanent1 = this.medicalLicenseExpiryValue1 ? 1 : 0;
  2106. formData.isEffectivePermanent2 = this.medicalLicenseExpiryValue2 ? 1 : 0;
  2107. formData.isEffectivePermanent3 = this.medicalLicenseExpiryValue3 ? 1 : 0;
  2108. // 处理食品经营许可证图片数据,转换为逗号分隔的字符串
  2109. if (Array.isArray(formData.foodLicense)) {
  2110. formData.foodLicense = formData.foodLicense.join(',');
  2111. }
  2112. if (isAgreementOnlySave) {
  2113. delete formData.isAudit;
  2114. updateStore(formData).then(response => {
  2115. this.msgSuccess("直接保存成功(未触发审核)");
  2116. this.open = false;
  2117. this.getList();
  2118. });
  2119. } else if (isEdit) {
  2120. updateStore(formData).then(response => {
  2121. this.msgSuccess("提交审核成功");
  2122. this.open = false;
  2123. this.getList();
  2124. });
  2125. } else {
  2126. addStore(formData).then(response => {
  2127. this.msgSuccess("新增成功");
  2128. this.open = false;
  2129. this.getList();
  2130. });
  2131. }
  2132. }
  2133. });
  2134. },
  2135. /** 删除按钮操作 */
  2136. handleDelete(row) {
  2137. const storeIds = row.storeId || this.ids;
  2138. this.$confirm('是否确认删除店铺管理编号为"' + storeIds + '"的数据项?', "警告", {
  2139. confirmButtonText: "确定",
  2140. cancelButtonText: "取消",
  2141. type: "warning"
  2142. }).then(function() {
  2143. return delStore(storeIds);
  2144. }).then(() => {
  2145. this.getList();
  2146. this.msgSuccess("删除成功");
  2147. }).catch(() => {
  2148. });
  2149. },
  2150. handleRefresh(row) {
  2151. const storeIds = row.storeId || this.ids;
  2152. this.$confirm('是否确认重置店铺管理编号为"' + storeIds + '"的密码为XyzAbc~12 ', "警告", {
  2153. confirmButtonText: "确定",
  2154. cancelButtonText: "取消",
  2155. type: "warning"
  2156. }).then(function() {
  2157. return refreshPasWod(storeIds);
  2158. }).then(() => {
  2159. this.getList();
  2160. this.msgSuccess("修改成功");
  2161. }).catch(() => {
  2162. });
  2163. },
  2164. /** 导出按钮操作 */
  2165. handleExport() {
  2166. const queryParams = this.queryParams;
  2167. this.$confirm('是否确认导出所有店铺管理数据项?', "警告", {
  2168. confirmButtonText: "确定",
  2169. cancelButtonText: "取消",
  2170. type: "warning"
  2171. }).then(() => {
  2172. this.exportLoading = true;
  2173. return exportStore(queryParams);
  2174. }).then(response => {
  2175. this.download(response.msg);
  2176. this.exportLoading = false;
  2177. }).catch(() => {
  2178. });
  2179. },
  2180. handleStoreExport(row){
  2181. const queryStoreId = row.storeId;
  2182. this.exportLoading = true;
  2183. exportFsStream({ queryStoreId: queryStoreId }).then(response => {
  2184. this.download(response.msg);
  2185. this.exportLoading = false;
  2186. }).catch(() => {
  2187. this.exportLoading = false;
  2188. });
  2189. },
  2190. handleEnable() {
  2191. const storeIds = this.ids
  2192. if (storeIds.length === 0) {
  2193. this.$message.warning('请选择要启用的店铺')
  2194. return
  2195. }
  2196. const storeNames = this.storeList
  2197. .filter(s => storeIds.includes(s.storeId))
  2198. .map(s => s.storeName)
  2199. .join('、')
  2200. this.$confirm(`确认一键启用以下店铺吗?启用后需等待管理员审核。<br/>${storeNames}`, '一键启用', {
  2201. confirmButtonText: '确定',
  2202. cancelButtonText: '取消',
  2203. type: 'warning',
  2204. dangerouslyUseHTMLString: true
  2205. }).then(() => {
  2206. this.enableLoading = true
  2207. const promises = storeIds.map(id => enableStore(id))
  2208. Promise.all(promises).then(responses => {
  2209. this.enableLoading = false
  2210. const failures = responses.filter(r => r.code !== 200)
  2211. if (failures.length > 0) {
  2212. const msgs = failures.map(f => f.msg).join('<br/>')
  2213. this.$message({ dangerouslyUseHTMLString: true, message: msgs, type: 'error', duration: 5000 })
  2214. } else {
  2215. this.$message.success('已提交审核,请等待管理员审核通过')
  2216. }
  2217. this.getList()
  2218. }).catch(() => {
  2219. this.enableLoading = false
  2220. this.getList()
  2221. })
  2222. }).catch(() => {})
  2223. },
  2224. /** 一键停用店铺 */
  2225. handleDisable() {
  2226. const storeIds = this.ids
  2227. if (storeIds.length === 0) {
  2228. this.$message.warning('请选择要停用的店铺')
  2229. return
  2230. }
  2231. const storeNames = this.storeList
  2232. .filter(s => storeIds.includes(s.storeId))
  2233. .map(s => s.storeName)
  2234. .join('、')
  2235. this.$confirm(`确认一键停用以下店铺吗?停用后店铺将无法进行业务操作。<br/>${storeNames}`, '一键停用', {
  2236. confirmButtonText: '确定停用',
  2237. cancelButtonText: '取消',
  2238. type: 'warning',
  2239. dangerouslyUseHTMLString: true
  2240. }).then(() => {
  2241. this.disableLoading = true
  2242. const promises = storeIds.map(id => disableStore(id))
  2243. Promise.all(promises).then(responses => {
  2244. this.disableLoading = false
  2245. const failures = responses.filter(r => r.code !== 200)
  2246. if (failures.length > 0) {
  2247. const msgs = failures.map(f => f.msg).join('<br/>')
  2248. this.$message({ dangerouslyUseHTMLString: true, message: msgs, type: 'error', duration: 5000 })
  2249. } else {
  2250. this.$message.success('停用成功')
  2251. }
  2252. this.getList()
  2253. }).catch(() => {
  2254. this.disableLoading = false
  2255. this.getList()
  2256. })
  2257. }).catch(() => {})
  2258. },
  2259. /** 设置ERP店铺信息按钮 */
  2260. handleErpInfo(row) {
  2261. this.erpForm = {
  2262. refId: row.storeId,
  2263. storeName: row.storeName || '',
  2264. shopCode: '',
  2265. warehouseCode: '',
  2266. returnReceiver: '',
  2267. returnPhone: '',
  2268. returnAddress: ''
  2269. };
  2270. getStoreErpInfo(row.storeId).then(response => {
  2271. if (response && response.data) {
  2272. this.erpForm.shopCode = response.data.shopCode || '';
  2273. this.erpForm.warehouseCode = response.data.warehouseCode || '';
  2274. this.erpForm.returnReceiver = response.data.returnReceiver || '';
  2275. this.erpForm.returnPhone = response.data.returnPhone || '';
  2276. this.erpForm.returnAddress = response.data.returnAddress || '';
  2277. }
  2278. this.erpDialogVisible = true;
  2279. this.$nextTick(() => {
  2280. if (this.$refs.erpForm) {
  2281. this.$refs.erpForm.clearValidate();
  2282. }
  2283. });
  2284. });
  2285. },
  2286. /** 保存ERP店铺信息 */
  2287. submitErpInfo() {
  2288. this.$refs.erpForm.validate(valid => {
  2289. if (!valid) {
  2290. return;
  2291. }
  2292. this.erpSubmitLoading = true;
  2293. const data = {
  2294. refId: this.erpForm.refId,
  2295. type: 1,
  2296. shopCode: this.erpForm.shopCode,
  2297. warehouseCode: this.erpForm.warehouseCode,
  2298. returnReceiver: this.erpForm.returnReceiver,
  2299. returnPhone: this.erpForm.returnPhone,
  2300. returnAddress: this.erpForm.returnAddress
  2301. };
  2302. saveStoreErpInfo(data).then(() => {
  2303. this.msgSuccess('保存成功');
  2304. this.erpDialogVisible = false;
  2305. this.getList();
  2306. }).finally(() => {
  2307. this.erpSubmitLoading = false;
  2308. });
  2309. });
  2310. },
  2311. /** 设置药店编码 */
  2312. handlePharmacyCode(row) {
  2313. this.pharmacyCodeForm = {
  2314. storeId: row.storeId,
  2315. storeName: row.storeName,
  2316. pharmacyCode: row.pharmacyCode || ''
  2317. };
  2318. this.pharmacyCodeDialogVisible = true;
  2319. this.$nextTick(() => {
  2320. if (this.$refs.pharmacyCodeForm) {
  2321. this.$refs.pharmacyCodeForm.clearValidate();
  2322. }
  2323. });
  2324. },
  2325. /** 提交药店编码 */
  2326. submitPharmacyCode() {
  2327. this.$refs.pharmacyCodeForm.validate(valid => {
  2328. if (!valid) return;
  2329. this.pharmacyCodeSubmitLoading = true;
  2330. updatePharmacyCode({
  2331. storeId: this.pharmacyCodeForm.storeId,
  2332. pharmacyCode: this.pharmacyCodeForm.pharmacyCode
  2333. }).then(() => {
  2334. this.msgSuccess('设置编码成功');
  2335. this.pharmacyCodeDialogVisible = false;
  2336. this.getList();
  2337. }).finally(() => {
  2338. this.pharmacyCodeSubmitLoading = false;
  2339. });
  2340. });
  2341. },
  2342. //长期有效营业执照选择
  2343. switchChange(){
  2344. console.log(this.form.isBusinessLicensePermanent);
  2345. },
  2346. // 判断是否为图片文件(根据URL后缀)
  2347. isImageFile(url, field) {
  2348. // 若有存储的文件类型,直接用 MIME 类型判断
  2349. if (this.form[`${field}FileType`]) {
  2350. return this.form[`${field}FileType`].startsWith('image/');
  2351. }
  2352. // 后备:用 URL 后缀判断
  2353. const imageExts = ['jpg', 'jpeg', 'png', 'gif'];
  2354. const ext = url.split('.').pop()?.toLowerCase() || '';
  2355. return imageExts.includes(ext);
  2356. },
  2357. // 根据文件类型获取文档图标(优先用 MIME 类型)
  2358. getDocumentIconClass(url, field) {
  2359. // 若有存储的文件类型,直接用 MIME 类型判断
  2360. if (this.form[`${field}FileType`]) {
  2361. const fileType = this.form[`${field}FileType`];
  2362. if (fileType === 'application/msword' || fileType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
  2363. return 'el-icon-document';
  2364. } else if (fileType === 'application/pdf') {
  2365. return 'el-icon-file-pdf';
  2366. }
  2367. return 'el-icon-file';
  2368. }
  2369. // 后备:用 URL 后缀判断
  2370. const ext = url.split('.').pop()?.toLowerCase() || '';
  2371. if (ext === 'doc' || ext === 'docx') {
  2372. return 'el-icon-document';
  2373. } else if (ext === 'pdf') {
  2374. return 'el-icon-file-pdf';
  2375. }
  2376. return 'el-icon-file';
  2377. },
  2378. // /// 从URL中提取文件名代码回退
  2379. getFileName(url) {
  2380. return url.split('/').pop().split('?')[0].slice(-8);
  2381. },
  2382. // 文件上传前校验
  2383. beforeFileUpload(file) {
  2384. // 校验文件类型
  2385. const acceptTypes = [
  2386. 'image/jpeg',
  2387. 'image/png',
  2388. 'image/gif',
  2389. 'application/msword',
  2390. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  2391. 'application/pdf'
  2392. ];
  2393. if (!acceptTypes.includes(file.type)) {
  2394. this.$message.error('请上传JPG、PNG、GIF、Word或PDF格式的文件');
  2395. return false;
  2396. }
  2397. // 2. 校验文件大小(10MB)
  2398. const maxSize = 10 * 1024 * 1024; // 10MB
  2399. if (file.size > maxSize) {
  2400. this.$message.error('文件大小不能超过10MB');
  2401. return false;
  2402. }
  2403. return true;
  2404. },
  2405. // 文件上传成功处理(复用原有逻辑,仅优化提示)
  2406. handleFileSuccess1(response, file, field) {
  2407. this.form[field] = response.url;
  2408. this.form[`${field}FileName`] = file.name;
  2409. this.form[`${field}FileType`] = file.type; // 新增:记录文件 MIME 类型
  2410. this.$message.success(`文件:${file.name}上传成功`);
  2411. },
  2412. // 文件上传失败处理
  2413. handleFileError(err, file) {
  2414. this.$message.error(`文件《${file.name}》上传失败,请重试`);
  2415. },
  2416. // 移除已上传文件
  2417. handleFileRemove(field) {
  2418. this.form[field] = '';
  2419. this.form[`${field}FileName`] = ''; // 清空文件名
  2420. this.$message.info('文件已移除');
  2421. },
  2422. handleRemove(file, fileList) {
  2423. console.log(file, fileList);
  2424. },
  2425. handlePreview(file) {
  2426. console.log(file);
  2427. },
  2428. handleReportRemove(field) {
  2429. this.$set(this.form, field, '');
  2430. this.$message.info('文件已移除');
  2431. },
  2432. handleReportUploadSuccess(response, file, field) {
  2433. if (response.code === 200) {
  2434. this.$set(this.form, field, response.url);
  2435. this.$message.success(`文件:${file.name}上传成功`);
  2436. this.$forceUpdate();
  2437. } else {
  2438. this.msgError(response.msg);
  2439. }
  2440. },
  2441. beforeReportUpload(file) {
  2442. const isValid = file.type.startsWith('image/') || file.type === 'application/pdf'
  2443. if (!isValid) {
  2444. this.$message.error('仅支持 jpg/png/gif/bmp 图片或 PDF 文件')
  2445. return false
  2446. }
  2447. const isLt10M = file.size / 1024 / 1024 < 10
  2448. if (!isLt10M) {
  2449. this.$message.error('文件大小不能超过 10MB')
  2450. return false
  2451. }
  2452. return true
  2453. },
  2454. isImageFile(url) {
  2455. if (!url) return false
  2456. return /\.(jpg|jpeg|png|gif|bmp|webp)(\?|$)/i.test(url)
  2457. },
  2458. viewReportFile(field) {
  2459. const url = this.form[field]
  2460. if (!url) {
  2461. this.$message.warning('暂无文件')
  2462. return
  2463. }
  2464. this.viewReportFileByUrl(url)
  2465. },
  2466. viewReportFileByUrl(url) {
  2467. if (this.isImageFile(url)) {
  2468. this.previewImageUrl = url
  2469. this.previewScale = 100
  2470. this.imagePreviewVisible = true
  2471. } else {
  2472. window.open(url, '_blank')
  2473. }
  2474. },
  2475. viewAgreementFile(field) {
  2476. const url = this.form[field]
  2477. if (!url) return
  2478. if (this.isImageFile(url, field)) {
  2479. this.previewImageUrl = url
  2480. this.previewScale = 100
  2481. this.imagePreviewVisible = true
  2482. } else {
  2483. window.open(url, '_blank')
  2484. }
  2485. },
  2486. onImagePreviewClose() {
  2487. this.previewScale = 100
  2488. this.dragOffset = { x: 0, y: 0 }
  2489. this.isDragging = false
  2490. this.imagePreviewVisible = false
  2491. },
  2492. zoomOut() {
  2493. if (this.previewScale > 25) {
  2494. this.previewScale = Math.max(25, this.previewScale - 25)
  2495. this.dragOffset = { x: 0, y: 0 }
  2496. }
  2497. },
  2498. zoomIn() {
  2499. if (this.previewScale < 300) {
  2500. this.previewScale = Math.min(300, this.previewScale + 25)
  2501. }
  2502. },
  2503. resetZoom() {
  2504. this.previewScale = 100
  2505. this.dragOffset = { x: 0, y: 0 }
  2506. },
  2507. onPreviewWheel(e) {
  2508. if (e.deltaY < 0) {
  2509. this.zoomIn()
  2510. } else {
  2511. this.zoomOut()
  2512. }
  2513. },
  2514. onImgMouseDown(e) {
  2515. this.isDragging = true
  2516. this.dragStart = { x: e.clientX - this.dragOffset.x, y: e.clientY - this.dragOffset.y }
  2517. },
  2518. onImgMouseMove(e) {
  2519. if (!this.isDragging) return
  2520. this.dragOffset = {
  2521. x: e.clientX - this.dragStart.x,
  2522. y: e.clientY - this.dragStart.y
  2523. }
  2524. },
  2525. onImgMouseUp() {
  2526. this.isDragging = false
  2527. },
  2528. fieldsEqual(a, b) {
  2529. if (a === b) return true;
  2530. if (a == null && b == null) return true;
  2531. if (a == null || b == null) return false;
  2532. if (Array.isArray(a) && Array.isArray(b)) {
  2533. if (a.length !== b.length) return false;
  2534. return a.every((v, i) => this.fieldsEqual(v, b[i]));
  2535. }
  2536. if ((a === '' && b === null) || (a === null && b === '')) return true;
  2537. return String(a) === String(b);
  2538. },
  2539. getChangedFields(original, current) {
  2540. const changed = [];
  2541. for (const key of Object.keys(original)) {
  2542. if (this.excludedFields.indexOf(key) !== -1) continue;
  2543. if (!this.fieldsEqual(original[key], current[key])) {
  2544. changed.push(key);
  2545. }
  2546. }
  2547. return changed;
  2548. },
  2549. getAgreementFieldSet() {
  2550. return new Set(this.agreementFields);
  2551. },
  2552. handleExceed(files, fileList) {
  2553. this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
  2554. },
  2555. beforeRemove(file, fileList) {
  2556. return this.$confirm(`确定移除 ${ file.name }?`);
  2557. },
  2558. // 将逗号分隔的URL字符串转换为文件对象数组
  2559. urlToFileList(urlStr) {
  2560. if (!urlStr) return [];
  2561. return urlStr.split(',').map(url => {
  2562. const fileName = url.substring(url.lastIndexOf('/') + 1);
  2563. return {
  2564. name: fileName,
  2565. url: url,
  2566. uid: Date.now() + Math.random().toString(36).substr(2, 9) // 生成唯一ID
  2567. };
  2568. });
  2569. },
  2570. }
  2571. };
  2572. </script>
  2573. <style>
  2574. .file-uploader {
  2575. display: inline-block;
  2576. }
  2577. /* 已上传文件容器 */
  2578. .uploaded-file {
  2579. position: relative;
  2580. display: inline-block;
  2581. cursor: default;
  2582. }
  2583. /* 已上传图片样式 */
  2584. .uploaded-img {
  2585. width: 150px;
  2586. height: 150px;
  2587. border-radius: 4px;
  2588. border: 1px solid #e4e7ed;
  2589. vertical-align: middle;
  2590. cursor: pointer;
  2591. }
  2592. /* 文档图标容器 */
  2593. /* 文档图标容器 */
  2594. .document-icon {
  2595. width: 150px;
  2596. height: 150px;
  2597. border: 1px solid #e4e7ed;
  2598. border-radius: 4px;
  2599. display: flex;
  2600. flex-direction: column;
  2601. align-items: center;
  2602. justify-content: center;
  2603. background-color: #f5f7fa;
  2604. vertical-align: middle;
  2605. cursor: pointer;
  2606. }
  2607. .document-icon .icon {
  2608. font-size: 36px;
  2609. color: #409eff;
  2610. margin-bottom: 8px;
  2611. font-family: "element-icons" !important; /* 强制使用 Element 图标字体 */
  2612. display: inline-block; /* 确保图标正常渲染 */
  2613. font-style: normal;
  2614. font-weight: normal;
  2615. font-variant: normal;
  2616. text-transform: none;
  2617. line-height: 1;
  2618. vertical-align: baseline;
  2619. -webkit-font-smoothing: antialiased; /* 优化渲染 */
  2620. -moz-osx-font-smoothing: grayscale; /* Firefox 优化渲染 */
  2621. }
  2622. .document-icon .file-name {
  2623. font-size: 12px;
  2624. color: #606266;
  2625. white-space: nowrap;
  2626. overflow: hidden;
  2627. text-overflow: ellipsis;
  2628. width: 80%;
  2629. text-align: center;
  2630. }
  2631. /* 删除图标 */
  2632. .delete-icon {
  2633. position: absolute;
  2634. top: -8px;
  2635. right: -8px;
  2636. width: 20px;
  2637. height: 20px;
  2638. line-height: 20px;
  2639. text-align: center;
  2640. background-color: #f56c6c;
  2641. color: #fff;
  2642. border-radius: 50%;
  2643. cursor: pointer;
  2644. font-size: 12px;
  2645. box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  2646. }
  2647. /* 上传按钮(外层正方形边框) */
  2648. .upload-btn {
  2649. width: 150px;
  2650. height: 150px;
  2651. /* 正方形边框 - 实线边框,默认灰色 */
  2652. border: 1px solid #dcdfe6;
  2653. border-radius: 4px;
  2654. display: flex;
  2655. align-items: center;
  2656. justify-content: center;
  2657. cursor: pointer;
  2658. transition: all 0.3s;
  2659. }
  2660. /* 上传按钮 hover 效果(边框变色) */
  2661. .upload-btn:hover {
  2662. border-color: #409eff;
  2663. background-color: #f0f7ff; /* 轻微背景色变化,增强交互感 */
  2664. }
  2665. /* 上传按钮内部内容容器 */
  2666. .upload-btn-inner {
  2667. display: flex;
  2668. flex-direction: column;
  2669. align-items: center;
  2670. justify-content: center;
  2671. color: #c0c4cc;
  2672. }
  2673. .upload-btn-inner i {
  2674. font-size: 28px;
  2675. margin-bottom: 8px;
  2676. }
  2677. .upload-btn-inner .upload-tip {
  2678. font-size: 12px;
  2679. }
  2680. /* 上传说明 */
  2681. .upload-desc {
  2682. margin-top: 8px;
  2683. font-size: 12px;
  2684. color: #909399;
  2685. }
  2686. .avatar-uploader .el-upload {
  2687. border: 1px dashed #d9d9d9;
  2688. border-radius: 6px;
  2689. cursor: pointer;
  2690. position: relative;
  2691. overflow: hidden;
  2692. }
  2693. .avatar-uploader .el-upload:hover {
  2694. border-color: #409EFF;
  2695. }
  2696. .avatar-uploader-icon {
  2697. font-size: 28px;
  2698. color: #8c939d;
  2699. width: 150px;
  2700. height: 150px;
  2701. line-height: 150px !important;
  2702. text-align: center;
  2703. }
  2704. .el-divider__text {
  2705. font-size: 16px;
  2706. font-weight: bold;
  2707. }
  2708. /* LOGO上传区域样式优化 */
  2709. .avatar-wrapper {
  2710. position: relative;
  2711. display: inline-block;
  2712. }
  2713. .avatar {
  2714. width: 200px;
  2715. height: 200px;
  2716. object-fit: cover;
  2717. border-radius: 4px;
  2718. }
  2719. .delete-mask {
  2720. position: absolute;
  2721. top: 0;
  2722. left: 0;
  2723. width: 100%;
  2724. height: 100%;
  2725. background-color: rgba(0, 0, 0, 0.5);
  2726. color: white;
  2727. display: flex;
  2728. align-items: center;
  2729. justify-content: center;
  2730. font-size: 24px;
  2731. opacity: 0;
  2732. cursor: pointer;
  2733. transition: opacity 0.3s ease;
  2734. border-radius: 4px;
  2735. }
  2736. .avatar-wrapper:hover .delete-mask {
  2737. opacity: 1;
  2738. }
  2739. .avatar-uploader {
  2740. display: inline-block;
  2741. }
  2742. .agreement-section {
  2743. border: 1px solid #ebeef5;
  2744. border-radius: 4px;
  2745. padding: 15px;
  2746. margin-bottom: 20px;
  2747. background-color: #fafafa;
  2748. }
  2749. .agreement-section .agreement-title {
  2750. margin-bottom: 10px;
  2751. }
  2752. .agreement-section .el-form-item {
  2753. margin-bottom: 15px;
  2754. }
  2755. .agreement-section .el-form-item__label {
  2756. font-weight: normal;
  2757. }
  2758. .agreement-section .el-date-editor.el-input__inner {
  2759. width: 100%;
  2760. }
  2761. .agreement-section .el-date-editor--daterange.el-input__inner {
  2762. width: 100%;
  2763. }
  2764. /* 并排按钮样式 */
  2765. .button-group {
  2766. position: absolute;
  2767. top: 10px;
  2768. right: 10px;
  2769. display: flex;
  2770. gap: 5px;
  2771. }
  2772. .preview-btn,
  2773. .delete-btn {
  2774. width: 30px;
  2775. height: 30px;
  2776. border-radius: 50%;
  2777. background-color: rgba(0, 0, 0, 0.5);
  2778. color: white;
  2779. display: flex;
  2780. align-items: center;
  2781. justify-content: center;
  2782. cursor: pointer;
  2783. font-size: 16px;
  2784. transition: background-color 0.3s;
  2785. }
  2786. .preview-btn:hover {
  2787. background-color: rgba(0, 0, 0, 0.7);
  2788. }
  2789. .delete-btn:hover {
  2790. background-color: #f56c6c;
  2791. }
  2792. /* 无图片占位符样式 */
  2793. .no-image-placeholder {
  2794. width: 200px;
  2795. height: 200px;
  2796. border: 1px dashed #d9d9d9;
  2797. border-radius: 6px;
  2798. display: flex;
  2799. align-items: center;
  2800. justify-content: center;
  2801. color: #999;
  2802. background-color: #fafafa;
  2803. }
  2804. .small-placeholder {
  2805. width: 150px;
  2806. height: 150px;
  2807. }
  2808. .avatar-wrapper {
  2809. position: relative;
  2810. display: inline-block;
  2811. }
  2812. .avatar {
  2813. width: 200px;
  2814. height: 200px;
  2815. object-fit: cover;
  2816. border-radius: 4px;
  2817. }
  2818. .small-avatar {
  2819. width: 150px;
  2820. height: 150px;
  2821. }
  2822. /* 食品经营许可证容器 */
  2823. .food-license-container {
  2824. display: flex;
  2825. flex-direction: row;
  2826. flex-wrap: wrap;
  2827. gap: 10px;
  2828. align-items: flex-start;
  2829. justify-content: flex-start;
  2830. }
  2831. /* 食品经营许可证单项 */
  2832. .food-license-item {
  2833. position: relative;
  2834. display: inline-block;
  2835. text-align: center;
  2836. }
  2837. /* 添加按钮样式 */
  2838. .add-btn {
  2839. display: flex;
  2840. align-items: center;
  2841. justify-content: center;
  2842. cursor: pointer;
  2843. border: 1px dashed #d9d9d9;
  2844. background-color: #fafafa;
  2845. width: 150px;
  2846. height: 150px;
  2847. }
  2848. .add-btn:hover {
  2849. border-color: #409EFF;
  2850. background-color: #f0f7ff;
  2851. }
  2852. .img-preview-body {
  2853. display: flex;
  2854. align-items: center;
  2855. justify-content: center;
  2856. min-height: 300px;
  2857. overflow: hidden;
  2858. }
  2859. .report-file-wrapper {
  2860. display: inline-block;
  2861. }
  2862. .uploaded-file-thumb {
  2863. width: 100px;
  2864. height: 100px;
  2865. border-radius: 4px;
  2866. border: 1px solid #e4e7ed;
  2867. cursor: pointer;
  2868. vertical-align: middle;
  2869. }
  2870. .document-file-icon {
  2871. width: 150px;
  2872. height: 100px;
  2873. border: 1px solid #e4e7ed;
  2874. border-radius: 4px;
  2875. display: flex;
  2876. flex-direction: column;
  2877. align-items: center;
  2878. justify-content: center;
  2879. background-color: #f5f7fa;
  2880. cursor: pointer;
  2881. vertical-align: middle;
  2882. }
  2883. .document-file-icon .el-icon-document {
  2884. font-size: 32px;
  2885. color: #409eff;
  2886. margin-bottom: 4px;
  2887. }
  2888. .document-file-icon .file-name {
  2889. font-size: 12px;
  2890. color: #606266;
  2891. white-space: nowrap;
  2892. overflow: hidden;
  2893. text-overflow: ellipsis;
  2894. max-width: 120px;
  2895. text-align: center;
  2896. }
  2897. .upload-btn-wrapper {
  2898. display: inline-block;
  2899. }
  2900. .report-preview-btn {
  2901. margin-top: 8px;
  2902. }
  2903. </style>