index.vue 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  1. <template>
  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="商品分类" prop="cateId">
  5. <treeselect v-model="queryParams.cateId" style="width:205.4px" :options="categoryOptions" :normalizer="normalizer" placeholder="请选择分类" />
  6. </el-form-item>
  7. <el-form-item label="商品名称" prop="productName">
  8. <el-input
  9. v-model="queryParams.productName"
  10. placeholder="请输入商品名称"
  11. clearable
  12. size="small"
  13. @keyup.enter.native="handleQuery"
  14. />
  15. </el-form-item>
  16. <el-form-item label="商品编号" prop="barCode">
  17. <el-input
  18. v-model="queryParams.barCode"
  19. placeholder="请输入商品编号"
  20. clearable
  21. size="small"
  22. @keyup.enter.native="handleQuery"
  23. />
  24. </el-form-item>
  25. <el-form-item label="商品类型" prop="productType">
  26. <el-select v-model="queryParams.productType" placeholder="请选择商品类型" clearable size="small" >
  27. <el-option
  28. v-for="item in productTypeOptions"
  29. :key="item.dictValue"
  30. :label="item.dictLabel"
  31. :value="item.dictValue"
  32. />
  33. </el-select>
  34. </el-form-item>
  35. <!-- <el-form-item label="状态" prop="isShow">
  36. <el-select style="width: 240px" v-model="queryParams.isShow" placeholder="请选择状态" clearable size="small" >
  37. <el-option
  38. v-for="item in isShowOptions"
  39. :key="item.dictValue"
  40. :label="item.dictLabel"
  41. :value="item.dictValue"
  42. />
  43. </el-select>
  44. </el-form-item> -->
  45. <el-form-item>
  46. <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  47. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  48. </el-form-item>
  49. </el-form>
  50. <el-row :gutter="10" class="mb8">
  51. <el-col :span="1.5">
  52. <el-button
  53. type="primary"
  54. icon="el-icon-plus"
  55. size="mini"
  56. @click="handleAdd"
  57. v-hasPermi="['store:storeProduct:add']"
  58. >新增</el-button>
  59. </el-col>
  60. <el-col :span="1.5">
  61. <el-button
  62. type="success"
  63. icon="el-icon-edit"
  64. size="mini"
  65. :disabled="single"
  66. @click="handleUpdate"
  67. v-hasPermi="['store:storeProduct:edit']"
  68. >修改</el-button>
  69. </el-col>
  70. <el-col :span="1.5">
  71. <el-button
  72. type="danger"
  73. icon="el-icon-delete"
  74. size="mini"
  75. :disabled="multiple"
  76. @click="handleDelete"
  77. v-hasPermi="['store:storeProduct:remove']"
  78. >删除</el-button>
  79. </el-col>
  80. <el-col :span="1.5">
  81. <el-button
  82. type="info"
  83. plain
  84. icon="el-icon-upload2"
  85. size="mini"
  86. @click="handleImport"
  87. v-hasPermi="['store:storeProduct:import']"
  88. >导入</el-button>
  89. </el-col>
  90. <el-col :span="1.5">
  91. <el-button
  92. type="warning"
  93. icon="el-icon-download"
  94. size="mini"
  95. @click="handleExport"
  96. v-hasPermi="['store:storePayment:export']"
  97. >导出</el-button>
  98. </el-col>
  99. <el-col :span="1.5">
  100. <el-button
  101. v-if="activeName==0"
  102. type="success"
  103. icon="el-icon-edit"
  104. size="mini"
  105. @click="putOn"
  106. v-hasPermi="['store:storePayment:pullOff']"
  107. >上架</el-button>
  108. </el-col>
  109. <el-col :span="1.5">
  110. <el-button
  111. v-if="activeName==1"
  112. type="success"
  113. icon="el-icon-edit"
  114. size="mini"
  115. @click="pullOff"
  116. v-hasPermi="['store:storePayment:pullOff']"
  117. >下架</el-button>
  118. </el-col>
  119. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  120. </el-row>
  121. <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
  122. <el-tab-pane label="出售中" name="1"></el-tab-pane>
  123. <el-tab-pane label="待上架" name="0"></el-tab-pane>
  124. </el-tabs>
  125. <el-table height="500" border v-loading="loading" :data="storeProductList" @selection-change="handleSelectionChange">
  126. <el-table-column type="selection" width="55" align="center" />
  127. <el-table-column label="ID" align="center" prop="productId" />
  128. <el-table-column label="商品图片" align="center" width="120">
  129. <template slot-scope="scope">
  130. <el-popover
  131. placement="right"
  132. title=""
  133. trigger="hover">
  134. <img slot="reference" :src="scope.row.image" width="100">
  135. <img :src="scope.row.image" style="max-width: 150px;">
  136. </el-popover>
  137. </template>
  138. </el-table-column>
  139. <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName" />
  140. <el-table-column label="分类" align="center" prop="cateName" />
  141. <el-table-column label="售价" align="center" prop="price" >
  142. <template slot-scope="scope" >
  143. <span v-if="scope.row.price!=null">{{scope.row.price.toFixed(2)}}</span>
  144. </template>
  145. </el-table-column>
  146. <el-table-column label="原价" align="center" prop="otPrice" >
  147. <template slot-scope="scope" >
  148. <span v-if="scope.row.otPrice!=null">{{scope.row.otPrice.toFixed(2)}}</span>
  149. </template>
  150. </el-table-column>
  151. <el-table-column label="销量" align="center" prop="sales" />
  152. <el-table-column label="库存" align="center" prop="stock" />
  153. <el-table-column label="类型" align="center" prop="productType" >
  154. <template slot-scope="scope">
  155. <el-tag prop="productType" v-for="(item, index) in productTypeOptions" v-if="scope.row.productType==item.dictValue">{{item.dictLabel}}</el-tag>
  156. </template>
  157. </el-table-column>
  158. <el-table-column label="状态" align="center" prop="isShow" >
  159. <template slot-scope="scope">
  160. <el-tag prop="status" v-for="(item, index) in isShowOptions" v-if="scope.row.isShow==item.dictValue">{{item.dictLabel}}</el-tag>
  161. </template>
  162. </el-table-column>
  163. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  164. <template slot-scope="scope">
  165. <el-button
  166. size="mini"
  167. type="text"
  168. icon="el-icon-edit"
  169. @click="handleUpdate(scope.row)"
  170. v-hasPermi="['store:storeProduct:edit']"
  171. >修改</el-button>
  172. <el-button
  173. size="mini"
  174. type="text"
  175. icon="el-icon-delete"
  176. @click="handleDelete(scope.row)"
  177. v-hasPermi="['store:storeProduct:remove']"
  178. >删除</el-button>
  179. </template>
  180. </el-table-column>
  181. </el-table>
  182. <pagination
  183. v-show="total>0"
  184. :total="total"
  185. :page.sync="queryParams.pageNum"
  186. :limit.sync="queryParams.pageSize"
  187. @pagination="getList"
  188. />
  189. <!-- 添加或修改商品对话框 -->
  190. <el-dialog :title="title" v-if="open" :visible.sync="open" width="1000px" append-to-body>
  191. <el-form ref="form" :model="form" :rules="rules" label-width="100px">
  192. <el-row >
  193. <el-col :span="12">
  194. <el-form-item label="商品名称" prop="productName">
  195. <el-input v-model="form.productName" placeholder="请输入商品名称" />
  196. </el-form-item>
  197. </el-col>
  198. <el-col :span="12">
  199. <el-form-item label="商品分类" prop="cateId">
  200. <treeselect v-model="form.cateId" :options="categoryOptions" :normalizer="normalizer" placeholder="请选择上级分类" />
  201. </el-form-item>
  202. </el-col>
  203. </el-row>
  204. <el-row>
  205. <el-col :span="12">
  206. <el-form-item label="关键字" prop="keyword">
  207. <el-input v-model="form.keyword" placeholder="请输入关键字" />
  208. </el-form-item>
  209. </el-col>
  210. <el-col :span="12">
  211. <el-form-item label="单位名" prop="unitName">
  212. <el-input v-model="form.unitName" placeholder="请输入单位名" />
  213. </el-form-item>
  214. </el-col>
  215. </el-row>
  216. <el-row>
  217. <el-col :span="24">
  218. <el-form-item label="商品简介" prop="productInfo">
  219. <el-input v-model="form.productInfo" type="textarea" :rows="2" placeholder="请输入商品简介" />
  220. </el-form-item>
  221. </el-col>
  222. </el-row>
  223. <el-form-item label="商品图片" prop="image">
  224. <Material v-model="imageArr" type="image" :num="1" :width="150" :height="150" />
  225. </el-form-item>
  226. <el-form-item label="轮播图" prop="sliderImage">
  227. <Material v-model="photoArr" type="image" :num="10" :width="150" :height="150" />
  228. </el-form-item>
  229. <el-row>
  230. <el-col :span="24">
  231. <el-form-item label="商品规格:" props="specType">
  232. <el-radio-group v-model="form.specType" >
  233. <el-radio :label="0" class="radio">单规格</el-radio>
  234. <el-radio :label="1">多规格</el-radio>
  235. </el-radio-group>
  236. </el-form-item>
  237. </el-col>
  238. <!-- 多规格添加-->
  239. <el-col :span="24" v-if="form.specType === 1" class="noForm">
  240. <el-col :span="24">
  241. <el-form-item label="选择规格:" prop="">
  242. <div class="acea-row row-middle">
  243. <el-select v-model="form.selectRule" style="width: 23%;">
  244. <el-option v-for="(item, index) in ruleList" :value="item.ruleName" :key="index">{{ item.ruleName }}</el-option>
  245. </el-select>
  246. <el-button style="margin-left:10px;" type="primary" class="mr20" @click="confirm">确认</el-button>
  247. </div>
  248. </el-form-item>
  249. </el-col>
  250. <el-col :span="24">
  251. <el-form-item v-if="attrs!=null&&attrs.length!==0">
  252. <div v-for="(item, index) in attrs" :key="index">
  253. <div class="acea-row row-middle"><span class="mr5">{{item.value}}</span>
  254. <i class="el-icon-circle-close" @click="handleRemoveRole(index)"></i>
  255. </div>
  256. <div class="rulesBox">
  257. <el-tag type="dot" closable color="primary" v-for="(j, indexn) in item.detail" :key="indexn" :name="j" class="mr20" @close="handleRemove2(item.detail,indexn)">{{j}}</el-tag>
  258. <el-input placeholder="请输入属性名称" v-model="item.detail.attrsVal"
  259. style="width: 200px">
  260. <el-button slot="append" type="primary" @click="createAttr(item.detail.attrsVal,index)">添加</el-button>
  261. </el-input>
  262. </div>
  263. </div>
  264. </el-form-item>
  265. </el-col>
  266. <el-col :span="24" v-if="createBnt">
  267. <el-form-item>
  268. <el-button type="primary" size="small" icon="md-add" @click="addBtn" class="mr15">添加新规格</el-button>
  269. <el-button type="success" size="small" @click="generate">立即生成</el-button>
  270. </el-form-item>
  271. </el-col>
  272. <el-col :span="24" v-if="showIput">
  273. <el-col :xl="6" :lg="9" :md="10" :sm="24" :xs="24" >
  274. <el-form-item label="规格:">
  275. <el-input placeholder="请输入规格" v-model="formDynamic.attrsName" />
  276. </el-form-item>
  277. </el-col>
  278. <el-col :xl="6" :lg="9" :md="10" :sm="24" :xs="24">
  279. <el-form-item label="规格值:">
  280. <el-input v-model="formDynamic.attrsVal" placeholder="请输入规格值" />
  281. </el-form-item>
  282. </el-col>
  283. <el-col :xl="6" :lg="5" :md="10" :sm="24" :xs="24" >
  284. <el-button type="primary" @click="createAttrName">确定</el-button>
  285. <el-button type="danger" @click="closeAttrName" >取消</el-button>
  286. </el-col>
  287. </el-col>
  288. <!-- 多规格设置-->
  289. <el-col :xl="24" :lg="24" :md="24" :sm="24" :xs="24" v-if="manyFormValidate!=null&&manyFormValidate.length">
  290. <!-- 多规格表格-->
  291. <el-col :span="24">
  292. <el-form-item label="商品属性:" class="labeltop">
  293. <el-table :data="manyFormValidate" size="small" style="width: 90%;">
  294. <el-table-column type="myindex" v-for="(item,index) in form.header" :key="index" :width="item.minWidth" :label="item.title" :property="item.slot" align="center">
  295. <template slot-scope="scope">
  296. <div v-if="scope.column.property == 'image'" align="center">
  297. <single-img v-model="scope.row[scope.column.property]" type="image" :num="1" :width="60" :height="60" />
  298. </div>
  299. <div v-else-if="scope.column.property.indexOf('value') != -1" align="center">
  300. {{ scope.row[scope.column.property] }}
  301. </div>
  302. <div v-else-if="scope.column.property == 'action'" align="center" >
  303. <a @click="delAttrTable(scope.$index)" align="center">删除</a>
  304. </div>
  305. <div v-else align="center">
  306. <el-input v-model="scope.row[scope.column.property]" align="center" />
  307. </div>
  308. </template>
  309. </el-table-column>
  310. </el-table>
  311. </el-form-item>
  312. </el-col>
  313. </el-col>
  314. </el-col>
  315. <!-- 单规格表格-->
  316. <el-col :xl="23" :lg="24" :md="24" :sm="24" :xs="24" v-if="form.specType === 0">
  317. <el-form-item >
  318. <el-table :data="oneFormValidate" size="small" style="width: 90%;">
  319. <el-table-column prop="image" label="图片" align="center">
  320. <template slot-scope="scope">
  321. <single-img v-model="scope.row.image" type="image" :num="1" :width="60" :height="60" />
  322. </template>
  323. </el-table-column>
  324. <el-table-column prop="price" label="售价" align="center">
  325. <template slot-scope="scope">
  326. <el-input type="text" v-model="scope.row.price"/>
  327. </template>
  328. </el-table-column>
  329. <el-table-column prop="agentPrice" label="代理价" align="center">
  330. <template slot-scope="scope">
  331. <el-input type="text" v-model="scope.row.agentPrice"/>
  332. </template>
  333. </el-table-column>
  334. <el-table-column prop="cost" label="成本价" align="center">
  335. <template slot-scope="scope">
  336. <el-input type="text" v-model="scope.row.cost"/>
  337. </template>
  338. </el-table-column>
  339. <el-table-column prop="otPrice" label="原价" align="center">
  340. <template slot-scope="scope">
  341. <el-input type="text" v-model="scope.row.otPrice"/>
  342. </template>
  343. </el-table-column>
  344. <el-table-column prop="stock" label="库存" align="center">
  345. <template slot-scope="scope">
  346. <el-input type="text" v-model="scope.row.stock" maxlength="7"/>
  347. </template>
  348. </el-table-column>
  349. <el-table-column prop="barCode" label="商品编号" width="130px" align="center">
  350. <template slot-scope="scope">
  351. <el-input type="text" v-model="scope.row.barCode"/>
  352. </template>
  353. </el-table-column>
  354. <el-table-column prop="barCode" label="组合编号" width="130px" align="center">
  355. <template slot-scope="scope">
  356. <el-input type="text" v-model="scope.row.groupBarCode"/>
  357. </template>
  358. </el-table-column>
  359. <el-table-column prop="weight" label="重量(KG)" align="center">
  360. <template slot-scope="scope">
  361. <el-input type="text" v-model="scope.row.weight"/>
  362. </template>
  363. </el-table-column>
  364. <el-table-column prop="volume" label="体积(m³)" align="center">
  365. <template slot-scope="scope">
  366. <el-input type="text" v-model="scope.row.volume"/>
  367. </template>
  368. </el-table-column>
  369. <el-table-column prop="volume" label="所需积分" align="center">
  370. <template slot-scope="scope">
  371. <el-input type="text" v-model="scope.row.integral"/>
  372. </template>
  373. </el-table-column>
  374. <el-table-column prop="volume" label="一级返佣" align="center">
  375. <template slot-scope="scope">
  376. <el-input type="text" v-model="scope.row.brokerage"/>
  377. </template>
  378. </el-table-column>
  379. <el-table-column prop="volume" label="二级返佣" align="center">
  380. <template slot-scope="scope">
  381. <el-input type="text" v-model="scope.row.brokerageTwo"/>
  382. </template>
  383. </el-table-column>
  384. <el-table-column prop="volume" label="三级返佣" align="center">
  385. <template slot-scope="scope">
  386. <el-input type="text" v-model="scope.row.brokerageThree"/>
  387. </template>
  388. </el-table-column>
  389. </el-table>
  390. </el-form-item>
  391. </el-col>
  392. <el-col :span="24">
  393. <el-form-item label="运费模板:" prop="tempId">
  394. <div class="acea-row">
  395. <el-select v-model="form.tempId" class="mr20">
  396. <el-option v-for="(item,index) in templateList" :value="item.id" :key="index" :label="item.name">
  397. </el-option>
  398. </el-select>
  399. </div>
  400. </el-form-item>
  401. </el-col>
  402. </el-row>
  403. <el-form-item label="商品详情" prop="description">
  404. <editor ref="myeditor" @on-text-change="updateText" />
  405. </el-form-item>
  406. <el-row>
  407. <el-col :span="8">
  408. <el-form-item label="商品状态" prop="isShow">
  409. <el-radio-group v-model="form.isShow">
  410. <el-radio :label="item.dictValue" v-for="item in isShowOptions" >{{item.dictLabel}}</el-radio>
  411. </el-radio-group>
  412. </el-form-item>
  413. </el-col>
  414. <el-col :span="8">
  415. <el-form-item label="是否热卖" prop="isHot">
  416. <el-radio-group v-model="form.isHot">
  417. <el-radio :label="item.dictValue" v-for="item in isHotOptions" >{{item.dictLabel}}</el-radio>
  418. </el-radio-group>
  419. </el-form-item>
  420. </el-col>
  421. <el-col :span="8">
  422. <el-form-item label="猜你喜欢" prop="isGood">
  423. <el-radio-group v-model="form.isGood">
  424. <el-radio :label="item.dictValue" v-for="item in isGoodOptions" >{{item.dictLabel}}</el-radio>
  425. </el-radio-group>
  426. </el-form-item>
  427. </el-col>
  428. </el-row>
  429. <el-row>
  430. <el-col :span="8">
  431. <el-form-item label="精品推荐" prop="isBest">
  432. <el-radio-group v-model="form.isBest">
  433. <el-radio :label="item.dictValue" v-for="item in isBestOptions" >{{item.dictLabel}}</el-radio>
  434. </el-radio-group>
  435. </el-form-item>
  436. </el-col>
  437. <el-col :span="8">
  438. <el-form-item label="新品首发" prop="isNew">
  439. <el-radio-group v-model="form.isNew">
  440. <el-radio :label="item.dictValue" v-for="item in isNewOptions" >{{item.dictLabel}}</el-radio>
  441. </el-radio-group>
  442. </el-form-item>
  443. </el-col>
  444. <el-col :span="8">
  445. <el-form-item label="返还积分">
  446. <el-input-number v-model="form.giveIntegral" :min="0" placeholder="请输入积分" />
  447. </el-form-item>
  448. </el-col>
  449. </el-row>
  450. <el-row>
  451. <el-col :span="8">
  452. <el-form-item label="商城展示" prop="isDisplay">
  453. <el-radio-group v-model="form.isDisplay">
  454. <el-radio :label="item.dictValue" v-for="item in isDisplayOptions" >{{item.dictLabel}}</el-radio>
  455. </el-radio-group>
  456. </el-form-item>
  457. </el-col>
  458. <el-col :span="8">
  459. <el-form-item label="排序" prop="sort">
  460. <el-input-number :min="0" v-model="form.sort" placeholder="请输入排序" />
  461. </el-form-item>
  462. </el-col>
  463. <el-col :span="8">
  464. <el-form-item label="销量" prop="sales">
  465. <el-input-number :min="0" v-model="form.sales" placeholder="请输入销量" />
  466. </el-form-item>
  467. </el-col>
  468. </el-row>
  469. <el-form-item label="推广分类" prop="tuiCateId">
  470. <el-select style="width: 240px" v-model="form.tuiCateId" placeholder="请选择推广分类" clearable size="small" >
  471. <el-option
  472. v-for="item in productTuiCateOptions"
  473. :key="item.dictValue"
  474. :label="item.dictLabel"
  475. :value="item.dictValue"
  476. />
  477. </el-select>
  478. </el-form-item>
  479. <el-form-item label="商品类型" prop="productType">
  480. <el-select style="width: 240px" v-model="form.productType" placeholder="请选择商品类型" clearable size="small" >
  481. <el-option
  482. v-for="item in productTypeOptions"
  483. :key="item.dictValue"
  484. :label="item.dictLabel"
  485. :value="item.dictValue"
  486. />
  487. </el-select>
  488. </el-form-item>
  489. <el-form-item label="国药准字" v-if="form.productType==2" prop="prescribeCode">
  490. <el-input v-model="form.prescribeCode" placeholder="请输入国药准字" />
  491. </el-form-item>
  492. <el-form-item label="规格" v-if="form.productType==2" prop="prescribeSpec">
  493. <el-input v-model="form.prescribeSpec" placeholder="请输入规格" />
  494. </el-form-item>
  495. <el-form-item label="生产厂家" v-if="form.productType==2" prop="prescribeFactory">
  496. <el-input v-model="form.prescribeFactory" placeholder="请输入生产厂家" />
  497. </el-form-item>
  498. <el-form-item label="处方名" v-if="form.productType==2" prop="prescribeName">
  499. <el-input v-model="form.prescribeName" placeholder="请输入处方名" />
  500. </el-form-item>
  501. </el-form>
  502. <div slot="footer" class="dialog-footer">
  503. <el-button type="primary" @click="submitForm">确 定</el-button>
  504. <el-button @click="cancel">取 消</el-button>
  505. </div>
  506. </el-dialog>
  507. <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
  508. <el-upload
  509. ref="upload"
  510. :limit="1"
  511. accept=".xlsx, .xls"
  512. :headers="upload.headers"
  513. :action="upload.url + '?updateSupport=' + upload.updateSupport"
  514. :disabled="upload.isUploading"
  515. :on-progress="handleFileUploadProgress"
  516. :on-success="handleFileSuccess"
  517. :auto-upload="false"
  518. drag
  519. >
  520. <i class="el-icon-upload"></i>
  521. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  522. <div class="el-upload__tip text-center" slot="tip">
  523. <div class="el-upload__tip" slot="tip">
  524. <!-- <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的数据 -->
  525. </div>
  526. <span>仅允许导入xls、xlsx格式文件。</span>
  527. <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
  528. </div>
  529. </el-upload>
  530. <div slot="footer" class="dialog-footer">
  531. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  532. <el-button @click="upload.open = false">取 消</el-button>
  533. </div>
  534. </el-dialog>
  535. </div>
  536. </template>
  537. <script>
  538. import {genFormatAttr, putOn,pullOff,listStoreProduct, getStoreProduct, delStoreProduct, addOrEdit, exportStoreProduct,importTemplate } from "@/api/store/storeProduct";
  539. import { getAllStoreProductCategory } from "@/api/store/storeProductCategory";
  540. import { getAllStoreProductRule } from "@/api/store/storeProductRule";
  541. import { getAllShippingTemplates } from "@/api/store/shippingTemplates";
  542. import { getToken } from "@/utils/auth";
  543. import Treeselect from "@riophae/vue-treeselect";
  544. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  545. import Editor from '@/components/Editor/wang';
  546. import Material from '@/components/Material'
  547. import singleImg from '@/components/Material/single'
  548. export default {
  549. name: "StoreProduct",
  550. components: {
  551. Treeselect,
  552. Editor,
  553. Material,
  554. singleImg,
  555. },
  556. watch: {
  557. imageArr: function(val) {
  558. this.form.image = val.join(',')
  559. },
  560. photoArr: function(val) {
  561. this.form.sliderImage = val.join(',')
  562. }
  563. },
  564. data() {
  565. return {
  566. upload: {
  567. // 是否显示弹出层
  568. open: false,
  569. // 弹出层标题
  570. title: "",
  571. // 是否禁用上传
  572. isUploading: false,
  573. // 是否更新已经存在的用户数据
  574. updateSupport: 0,
  575. // 设置上传的请求头部
  576. headers: { Authorization: "Bearer " + getToken() },
  577. // 上传的地址
  578. url: process.env.VUE_APP_BASE_API + "/store/storeProduct/importData"
  579. },
  580. productTuiCateOptions:[],
  581. showIput: false,
  582. createBnt:true,
  583. // 规格数据
  584. formDynamic: {
  585. attrsName: '',
  586. attrsVal: ''
  587. },
  588. isBtn: false,
  589. columns: [],
  590. attrs:[],
  591. templateList:[],
  592. ruleList:[],
  593. // 多规格表格data
  594. manyFormValidate: [],
  595. // 单规格表格data
  596. oneFormValidate: [
  597. {
  598. image: '',
  599. price: 0,
  600. cost: 0,
  601. agentPrice: 0,
  602. otPrice: 0,
  603. stock: 0,
  604. barCode: '',
  605. weight: 0,
  606. volume: 0,
  607. integral: 0
  608. }
  609. ],
  610. photoArr:[],
  611. imageArr:[],
  612. activeName:"1",
  613. productTypeOptions:[],
  614. isDisplayOptions:[],
  615. isGoodOptions:[],
  616. isNewOptions:[],
  617. isBestOptions:[],
  618. isHotOptions:[],
  619. isShowOptions:[],
  620. categoryOptions:[],
  621. // 遮罩层
  622. loading: true,
  623. // 选中数组
  624. ids: [],
  625. // 非单个禁用
  626. single: true,
  627. // 非多个禁用
  628. multiple: true,
  629. // 显示搜索条件
  630. showSearch: true,
  631. // 总条数
  632. total: 0,
  633. // 商品表格数据
  634. storeProductList: [],
  635. // 弹出层标题
  636. title: "",
  637. // 是否显示弹出层
  638. open: false,
  639. // 查询参数
  640. queryParams: {
  641. pageNum: 1,
  642. pageSize: 10,
  643. productName: null,
  644. productType: null,
  645. isShow: "1",
  646. barCode:null,
  647. },
  648. // 表单参数
  649. form: {},
  650. // 表单校验
  651. rules: {
  652. image: [
  653. { required: true, message: "商品图片不能为空", trigger: "blur" }
  654. ],
  655. sliderImage: [
  656. { required: true, message: "轮播图不能为空", trigger: "blur" }
  657. ],
  658. productName: [
  659. { required: true, message: "商品名称不能为空", trigger: "blur" }
  660. ],
  661. productInfo: [
  662. { required: true, message: "商品简介不能为空", trigger: "blur" }
  663. ],
  664. unitName: [
  665. { required: true, message: "单位名不能为空", trigger: "blur" }
  666. ],
  667. keyword: [
  668. { required: true, message: "关键字不能为空", trigger: "blur" }
  669. ],
  670. cateId: [
  671. { required: true, message: "分类id不能为空", trigger: "blur" }
  672. ],
  673. price: [
  674. { required: true, message: "商品价格不能为空", trigger: "blur" }
  675. ],
  676. prescribeCode: [
  677. { required: true, message: "国药准字不能为空", trigger: "blur" }
  678. ],
  679. prescribeSpec: [
  680. { required: true, message: "规格不能为空", trigger: "blur" }
  681. ],
  682. prescribeFactory: [
  683. { required: true, message: "生产厂家不能为空", trigger: "blur" }
  684. ],
  685. prescribeName: [
  686. { required: true, message: "处方药不能为空", trigger: "blur" }
  687. ],
  688. }
  689. };
  690. },
  691. created() {
  692. this.getDicts("store_product_tui_cate").then((response) => {
  693. this.productTuiCateOptions = response.data;
  694. });
  695. this.getDicts("store_product_enable").then((response) => {
  696. this.isNewOptions = response.data;
  697. this.isBestOptions = response.data;
  698. this.isHotOptions = response.data;
  699. this.isGoodOptions=response.data;
  700. this.isDisplayOptions=response.data;
  701. });
  702. this.getDicts("store_product_type").then((response) => {
  703. this.productTypeOptions = response.data;
  704. });
  705. this.getDicts("store_product_is_show").then((response) => {
  706. this.isShowOptions = response.data;
  707. });
  708. getAllShippingTemplates().then(response => {
  709. this.templateList =response.data;
  710. });
  711. getAllStoreProductRule().then(response => {
  712. this.ruleList =response.data;
  713. });
  714. this.getTreeselect();
  715. this.getList();
  716. },
  717. methods: {
  718. // 提交上传文件
  719. submitFileForm() {
  720. this.$refs.upload.submit();
  721. },
  722. // 文件上传中处理
  723. handleFileUploadProgress(event, file, fileList) {
  724. this.upload.isUploading = true;
  725. },
  726. // 文件上传成功处理
  727. handleFileSuccess(response, file, fileList) {
  728. this.upload.open = false;
  729. this.upload.isUploading = false;
  730. this.$refs.upload.clearFiles();
  731. this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
  732. this.getList();
  733. },
  734. handleImport() {
  735. this.upload.title = "商品导入";
  736. this.upload.open = true;
  737. },
  738. importTemplate() {
  739. importTemplate().then(response => {
  740. this.download(response.msg);
  741. });
  742. },
  743. // 删除表格中的属性
  744. delAttrTable (index) {
  745. this.manyFormValidate.splice(index, 1);
  746. },
  747. addBtn () {
  748. this.clearAttr();
  749. this.createBnt = false;
  750. this.showIput = true;
  751. },
  752. //生成SKU
  753. generate () {
  754. genFormatAttr(this.form.productId, { attrs: this.attrs }).then(res => {
  755. if(this.form.specType === 0){
  756. this.oneFormValidate = res.value;
  757. this.form.header = res.header;
  758. let header = res.header;
  759. header.pop();
  760. this.oneFormValidate.map((item) => {
  761. if(this.imageArr.length>0){
  762. item.image = this.imageArr[0]
  763. }
  764. });
  765. }else if(this.form.specType === 1) {
  766. this.manyFormValidate = res.value;
  767. let headerdel = {
  768. title: '操作',
  769. slot: 'action',
  770. fixed: 'right',
  771. width: 220
  772. };
  773. res.header.push(headerdel);
  774. this.form.header = res.header;
  775. let header = res.header;
  776. header.pop();
  777. // this.manyFormValidate.map((item) => {
  778. // if(this.imageArr.length>0){
  779. // item.image = this.imageArr[0]
  780. // }
  781. // });
  782. }
  783. }).catch(res => {
  784. })
  785. },
  786. // 取消添加新规格
  787. closeAttrName () {
  788. this.showIput = false;
  789. this.createBnt = true;
  790. },
  791. clearAttr () {
  792. this.formDynamic.attrsName = '';
  793. this.formDynamic.attrsVal = '';
  794. },
  795. // 删除规格
  796. handleRemoveRole (index) {
  797. this.attrs.splice(index, 1);
  798. this.manyFormValidate.splice(index, 1);
  799. },
  800. // 删除属性
  801. handleRemove2 (item, index) {
  802. item.splice(index, 1);
  803. },
  804. // 添加规则名称
  805. createAttrName () {
  806. if (this.formDynamic.attrsName && this.formDynamic.attrsVal) {
  807. let data = {
  808. value: this.formDynamic.attrsName,
  809. detail: [
  810. this.formDynamic.attrsVal
  811. ]
  812. };
  813. this.attrs.push(data);
  814. var hash = {};
  815. this.attrs = this.attrs.reduce(function (item, next) {
  816. hash[next.value] ? '' : hash[next.value] = true && item.push(next);
  817. return item
  818. }, [])
  819. this.clearAttr();
  820. this.showIput = false;
  821. this.createBnt = true;
  822. } else {
  823. this.$message.warning('请添加完整的规格!');
  824. }
  825. },
  826. // 添加属性
  827. createAttr (num, idx) {
  828. if (num) {
  829. this.attrs[idx].detail.push(num);
  830. var hash = {};
  831. this.attrs[idx].detail = this.attrs[idx].detail.reduce(function (item, next) {
  832. hash[next] ? '' : hash[next] = true && item.push(next);
  833. return item
  834. }, [])
  835. } else {
  836. this.$message.warning('请添加属性!');
  837. }
  838. },
  839. confirm () {
  840. let that = this;
  841. that.createBnt = true;
  842. if (that.form.selectRule==null||that.form.selectRule.trim().length <= 0) {
  843. return this.$message({
  844. message:'请选择属性',
  845. type: 'error'
  846. });
  847. }
  848. that.ruleList.forEach(function (item, index) {
  849. if (item.ruleName === that.form.selectRule) {
  850. that.attrs =JSON.parse( item.ruleValue);
  851. }
  852. });
  853. },
  854. updateText(text){
  855. this.form.description=text
  856. },
  857. handleClick(tab, event) {
  858. this.queryParams.isShow=tab.name;
  859. this.getList();
  860. },
  861. /** 转换商品分类数据结构 */
  862. normalizer(node) {
  863. if (node.children && !node.children.length) {
  864. delete node.children;
  865. }
  866. return {
  867. id: node.cateId,
  868. label: node.cateName,
  869. children: node.children
  870. };
  871. },
  872. getTreeselect() {
  873. getAllStoreProductCategory().then(response => {
  874. this.categoryOptions = [];
  875. const data = this.handleTree(response.data, "cateId", "pid");
  876. this.categoryOptions=data;
  877. });
  878. },
  879. /** 查询商品列表 */
  880. getList() {
  881. this.loading = true;
  882. listStoreProduct(this.queryParams).then(response => {
  883. this.storeProductList = response.rows;
  884. this.total = response.total;
  885. this.loading = false;
  886. });
  887. },
  888. // 取消按钮
  889. cancel() {
  890. this.open = false;
  891. this.reset();
  892. },
  893. // 表单重置
  894. reset() {
  895. this.form = {
  896. productId: 0,
  897. image: null,
  898. sliderImage: null,
  899. productName: null,
  900. productInfo: null,
  901. keyword: null,
  902. barCode: null,
  903. cateId: null,
  904. price: null,
  905. vipPrice: null,
  906. otPrice: null,
  907. postage: null,
  908. unitName: null,
  909. sort: null,
  910. sales: null,
  911. stock: null,
  912. isShow: "0",
  913. isHot: "0",
  914. isBenefit: "0",
  915. isBest: "0",
  916. isNew: "0",
  917. description: null,
  918. createTime: null,
  919. updateTime: null,
  920. isPostage: null,
  921. isDel: null,
  922. giveIntegral: null,
  923. cost: null,
  924. isGood: "0",
  925. browse: null,
  926. codePath: null,
  927. tempId: "",
  928. specType: 0,
  929. isIntegral: null,
  930. integral: null,
  931. productType: "1",
  932. prescribeCode: null,
  933. prescribeSpec: null,
  934. prescribeFactory: null,
  935. prescribeName: null,
  936. isDisplay:"1"
  937. };
  938. this.resetForm("form");
  939. this.oneFormValidate = [
  940. {
  941. image: '',
  942. price: 0,
  943. agentPrice: 0,
  944. cost: 0,
  945. otPrice: 0,
  946. stock: 0,
  947. barCode: '',
  948. weight: 0,
  949. volume: 0,
  950. integral: 0,
  951. brokerage:0,
  952. brokerageTwo:0
  953. }
  954. ]
  955. this.attrs=[];
  956. this.photoArr=[];
  957. this.imageArr=[];
  958. },
  959. /** 搜索按钮操作 */
  960. handleQuery() {
  961. this.queryParams.pageNum = 1;
  962. this.getList();
  963. },
  964. /** 重置按钮操作 */
  965. resetQuery() {
  966. this.resetForm("queryForm");
  967. this.handleQuery();
  968. },
  969. // 多选框选中数据
  970. handleSelectionChange(selection) {
  971. this.ids = selection.map(item => item.productId)
  972. this.single = selection.length!==1
  973. this.multiple = !selection.length
  974. },
  975. /** 新增按钮操作 */
  976. handleAdd() {
  977. this.reset();
  978. this.open = true;
  979. this.title = "添加商品";
  980. setTimeout(() => {
  981. this.$refs.myeditor.setText("");
  982. }, 500);
  983. },
  984. /** 修改按钮操作 */
  985. handleUpdate(row) {
  986. var that=this;
  987. this.reset();
  988. const productId = row.productId || this.ids
  989. getStoreProduct(productId).then(response => {
  990. this.form = response.data;
  991. this.form.isShow = response.data.isShow.toString();
  992. this.form.isHot = response.data.isHot.toString();
  993. this.form.isGood = response.data.isGood.toString();
  994. this.form.isBest = response.data.isBest.toString();
  995. this.form.isNew = response.data.isNew.toString();
  996. this.form.productType = response.data.productType.toString();
  997. this.form.isDisplay = response.data.isDisplay.toString();
  998. if(this.form.tuiCateId!=null){
  999. this.form.tuiCateId = response.data.tuiCateId.toString();
  1000. }
  1001. //组装attrs数据
  1002. if(response.attrs!=null){
  1003. this.attrs=[];
  1004. response.attrs.forEach(function (item, index) {
  1005. var data={value:item.attrName,detail:item.attrValues.split(',')}
  1006. that.attrs.push(data);
  1007. });
  1008. }
  1009. setTimeout(() => {
  1010. that.generate();
  1011. }, 200);
  1012. if(this.form.specType === 0){
  1013. that.manyFormValidate = [];
  1014. }else {
  1015. that.createBnt = true;
  1016. that.oneFormValidate = [
  1017. {
  1018. image: '',
  1019. price: 0,
  1020. agentPrice: 0,
  1021. cost: 0,
  1022. otPrice: 0,
  1023. stock: 0,
  1024. barCode: '',
  1025. weight: 0,
  1026. volume: 0,
  1027. integral: 0,
  1028. brokerage:0,
  1029. brokerageTwo:0
  1030. }
  1031. ]
  1032. }
  1033. setTimeout(() => {
  1034. if(this.form.description==null){
  1035. this.$refs.myeditor.setText("");
  1036. }
  1037. else{
  1038. this.$refs.myeditor.setText(this.form.description);
  1039. }
  1040. }, 200);
  1041. if(this.form.image!=null){
  1042. this.imageArr=this.form.image.split(",");
  1043. }
  1044. if(this.form.sliderImage!=null){
  1045. this.photoArr=this.form.sliderImage.split(",");
  1046. }
  1047. console.log(this.oneFormValidate)
  1048. this.open = true;
  1049. this.title = "修改商品";
  1050. });
  1051. },
  1052. /** 提交按钮 */
  1053. submitForm() {
  1054. this.$refs["form"].validate(valid => {
  1055. if (valid) {
  1056. if(this.form.specType ===0 ){
  1057. this.form.items = [];
  1058. this.form.values = this.oneFormValidate;
  1059. }else{
  1060. this.form.items = this.attrs;
  1061. this.form.values = this.manyFormValidate;
  1062. }
  1063. if(this.form.specType === 1 && this.manyFormValidate.length===0){
  1064. return this.$message.warning('请点击生成规格!');
  1065. }
  1066. addOrEdit(this.form).then(response => {
  1067. if (response.code === 200) {
  1068. this.msgSuccess("修改成功");
  1069. this.open = false;
  1070. this.getList();
  1071. }
  1072. });
  1073. }
  1074. });
  1075. },
  1076. /** 删除按钮操作 */
  1077. handleDelete(row) {
  1078. const productIds = row.productId || this.ids;
  1079. this.$confirm('是否确认删除商品编号为"' + productIds + '"的数据项?', "警告", {
  1080. confirmButtonText: "确定",
  1081. cancelButtonText: "取消",
  1082. type: "warning"
  1083. }).then(function() {
  1084. return delStoreProduct(productIds);
  1085. }).then(() => {
  1086. this.getList();
  1087. this.msgSuccess("删除成功");
  1088. }).catch(function() {});
  1089. },
  1090. putOn() {
  1091. const productIds =this.ids;
  1092. if(productIds==null||productIds==""){
  1093. return this.$message("未选择商品");
  1094. }
  1095. this.$confirm('是否确认批量上架商品?', "警告", {
  1096. confirmButtonText: "确定",
  1097. cancelButtonText: "取消",
  1098. type: "warning"
  1099. }).then(function() {
  1100. return putOn(productIds);
  1101. }).then(() => {
  1102. this.getList();
  1103. this.msgSuccess("上架成功");
  1104. }).catch(function() {});
  1105. },
  1106. pullOff() {
  1107. const productIds =this.ids;
  1108. if(productIds==null||productIds==""){
  1109. return this.$message("未选择商品");
  1110. }
  1111. this.$confirm('是否确认批量下架商品?', "警告", {
  1112. confirmButtonText: "确定",
  1113. cancelButtonText: "取消",
  1114. type: "warning"
  1115. }).then(function() {
  1116. return pullOff(productIds);
  1117. }).then(() => {
  1118. this.getList();
  1119. this.msgSuccess("下架成功");
  1120. }).catch(function() {});
  1121. },
  1122. /** 导出按钮操作 */
  1123. handleExport() {
  1124. const queryParams = this.queryParams;
  1125. this.$confirm('是否确认导出所有商品数据项?', "警告", {
  1126. confirmButtonText: "确定",
  1127. cancelButtonText: "取消",
  1128. type: "warning"
  1129. }).then(function() {
  1130. return exportStoreProduct(queryParams);
  1131. }).then(response => {
  1132. this.download(response.msg);
  1133. }).catch(function() {});
  1134. }
  1135. }
  1136. };
  1137. </script>