index.vue 110 KB

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