addComponent.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. <template>
  2. <div class="style-information-component">
  3. <el-form-item label="商品图片" />
  4. <div class="upload-wrap">
  5. <el-upload
  6. ref="upImagesFiles"
  7. list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove"
  8. :headers="headers" :data="dataObj" :file-list="form.imgs" :limit="20"
  9. :on-success="handleImageSuccess"
  10. :action="action"
  11. :before-upload="changeFiles"
  12. >
  13. <i slot="default" class="el-icon-plus" />
  14. <div slot="file" slot-scope="{ file }">
  15. <img v-if="!isVideo(file.imgPath)" class="el-upload-list__item-thumbnail" :src="file.imgPath">
  16. <video
  17. v-else class="el-upload-list__item-thumbnail" style="width: 148px;height: 148px;"
  18. :src="file.imgPath"
  19. ></video>
  20. <span class="el-upload-list__item-actions">
  21. <span
  22. v-if="!isVideo(file.imgPath)" class="el-upload-list__item-preview"
  23. @click="handlePictureCardPreview(file)"
  24. >
  25. <i class="el-icon-zoom-in" />
  26. </span>
  27. <span @click="playVideo(file.imgPath)">
  28. <i class="el-icon-video-play"></i>
  29. </span>
  30. <span class="el-upload-list__item-delete" @click="handleRemove(file)">
  31. <i class="el-icon-delete" />
  32. </span>
  33. </span>
  34. </div>
  35. </el-upload>
  36. </div>
  37. <el-form-item label="款式设置">
  38. <el-radio-group v-model="form.attrStyle">
  39. <el-radio :label="0">单款式</el-radio>
  40. <el-radio :label="1">多款式</el-radio>
  41. </el-radio-group>
  42. </el-form-item>
  43. <div class="style-container">
  44. <div v-if="form.attrStyle === 0" class="single-style">
  45. <el-table :data="skuList" style="width: 100%" :header-cell-style="{ background: '#EEF3FF', color: '#333333' }">
  46. <el-table-column label="规格">
  47. <template slot-scope="scope">
  48. <el-input v-model="singleStyle.skuValue" :sss="scope" maxlength="20" />
  49. </template>
  50. </el-table-column>
  51. <el-table-column label="售价">
  52. <template slot-scope="scope">
  53. <el-input-number
  54. v-model="scope.row.price" :controls="false" :max="999999999" :min="0"
  55. :precision="2"
  56. :step="0.01" style="width: auto;"
  57. />
  58. </template>
  59. </el-table-column>
  60. <el-table-column label="原价">
  61. <template slot-scope="scope">
  62. <el-input-number
  63. v-model="scope.row.originalPrice" :controls="false" :max="999999999" :min="0"
  64. :precision="2" :step="0.01" style="width: auto;"
  65. />
  66. </template>
  67. </el-table-column>
  68. <el-table-column label="库存">
  69. <template slot-scope="scope">
  70. <el-input-number
  71. v-model="scope.row.stockNumber" :controls="false" :max="999999999" :min="0"
  72. :precision="0" style="width: auto;"
  73. />
  74. </template>
  75. </el-table-column>
  76. <el-table-column label="重量(KG)">
  77. <template slot-scope="scope">
  78. <el-input-number
  79. v-model="scope.row.weight" :controls="false" :max="999" :min="0"
  80. :precision="2"
  81. :step="0.01" style="width: auto;"
  82. />
  83. </template>
  84. </el-table-column>
  85. <el-table-column label="赠送代金券">
  86. <template slot-scope="scope">
  87. <span>代金券</span>
  88. <!-- <el-input-number
  89. v-model="scope.row.presenter_voucher" :controls="false" :max="999" :min="0"
  90. :precision="2"
  91. :step="0.01" style="width: auto;"
  92. /> -->
  93. </template>
  94. </el-table-column>
  95. <el-table-column label="代金卷最大抵扣额度(一般设置全额抵扣)">
  96. <template slot-scope="scope">
  97. <el-input-number v-model="scope.row.voucherPrice" :controls="false" :min="0" :precision="6" :step="0.01" style="width: auto;" />
  98. </template>
  99. </el-table-column>
  100. <el-table-column label="商品绑定的代金卷">
  101. <template slot-scope="scope">
  102. <el-select v-model="scope.row.voucherId" placeholder="请选择商品绑定的代金卷">
  103. <el-option v-for="item in voucherList" :key="item.id" :label="item.voucherName" :value="item.id">
  104. </el-option>
  105. </el-select>
  106. </template>
  107. </el-table-column>
  108. <el-table-column label="国际条码">
  109. <template slot-scope="scope">
  110. <el-input v-model="scope.row.sku" maxlength="20" />
  111. </template>
  112. </el-table-column>
  113. </el-table>
  114. </div>
  115. <div v-else class="multiple-styles">
  116. <div v-for="(skuAttr, index) in form.skuAttrList" :key="index" class="sku-attr-list">
  117. <el-form-item label="规格名">
  118. <el-input v-model="skuAttr.skuName" maxlength="20" />
  119. <i v-if="index != 0" class="el-icon-close delImg" @click="delSkuAttrList(index)" />
  120. <el-checkbox v-if="index === 0" v-model="skuAttr.needImg" style="margin-left: 20px;">需要配图</el-checkbox>
  121. </el-form-item>
  122. <el-form-item label="规格值">
  123. <div class="attr-value-list">
  124. <div v-for="(sku, index1) in skuAttr.values" :key="index + '-' + index1" class="main-diagram m-8">
  125. <!-- 去除了长度限制 -->
  126. <el-input v-model="sku.skuValue" />
  127. <i v-if="index === 0 && index1 === 0" />
  128. <i v-else class="el-icon-close delImg" @click="delValue(index, index1)" />
  129. <div v-if="skuAttr.needImg && index === 0" class="upload-wrap diagram-upload">
  130. <div class="span-wrap">
  131. <el-upload
  132. list-type="picture-card" :show-file-list="false" :on-preview="handlePictureCardPreview"
  133. :on-remove="handleRemove" :headers="headers" :data="dataObj" :file-list="[ sku ]"
  134. :multiple="false"
  135. :on-success="handleImageSuccess1" :action="action"
  136. >
  137. <i v-if="!sku.image" slot="trigger" class="el-icon-plus" />
  138. <div v-else class="attr-value-img">
  139. <img class="attr-thumbnail" :src="sku.image">
  140. </div>
  141. </el-upload>
  142. <div v-if="sku.image" class="attr-actions">
  143. <span class="attr-preview" @click="handlePictureCardPreview({ imgPath: sku.image })">
  144. <i class="el-icon-zoom-in" />
  145. </span>
  146. <span class="attr-delete" @click="handleRemove1(sku)">
  147. <i class="el-icon-delete" />
  148. </span>
  149. </div>
  150. </div>
  151. </div>
  152. </div>
  153. <el-button type="text" style="margin-left: 10px;" @click="addAttrValue(index)">添加</el-button>
  154. </div>
  155. </el-form-item>
  156. </div>
  157. <el-button class="add-attr-btn" type="primary" @click="addSkuAttrList">添加规格</el-button>
  158. <el-table :data="skuList" style="width: 100%" :header-cell-style="{ background: '#EEF3FF', color: '#333333' }">
  159. <el-table-column v-for="(skuAttr, index) in skuAttrName" :key="index" :label="skuAttr.skuName">
  160. <template slot-scope="scope">
  161. {{ scope.row.skuAttrCodeDTOList && scope.row.skuAttrCodeDTOList[index] | attrValueFilter(form.skuAttrList) }}
  162. </template>
  163. </el-table-column>
  164. <el-table-column label="售价">
  165. <template slot-scope="scope">
  166. <el-input-number
  167. v-model="scope.row.price" :controls="false" :max="999999999" :min="0"
  168. :precision="2"
  169. :step="0.01" style="width: auto;"
  170. />
  171. </template>
  172. </el-table-column>
  173. <el-table-column label="原价">
  174. <template slot-scope="scope">
  175. <el-input-number
  176. v-model="scope.row.originalPrice" :controls="false" :max="999999999" :min="0"
  177. :precision="2" :step="0.01" style="width: auto;"
  178. />
  179. </template>
  180. </el-table-column>
  181. <el-table-column label="库存">
  182. <template slot-scope="scope">
  183. <el-input-number
  184. v-model="scope.row.stockNumber" :controls="false" :max="999999999" :min="0"
  185. :precision="0" style="width: auto;"
  186. />
  187. </template>
  188. </el-table-column>
  189. <el-table-column label="重量(KG)">
  190. <template slot-scope="scope">
  191. <el-input-number
  192. v-model="scope.row.weight" :controls="false" :max="999" :min="0"
  193. :precision="6"
  194. :step="0.01" style="width: auto;"
  195. />
  196. </template>
  197. </el-table-column>
  198. <el-table-column label="赠送代金券">
  199. <template slot-scope="scope">
  200. <el-input-number
  201. v-model="scope.row.presenterVoucher" :controls="false" :max="scope.row.price" :min="0"
  202. :precision="6"
  203. :step="1" style="width: auto;"
  204. />
  205. </template>
  206. </el-table-column>
  207. <el-table-column label="代金卷最大抵扣额度(一般设置全额抵扣)">
  208. <template #header="scope">
  209. <div>代金卷最大抵扣额度(一般设置全额抵扣)<el-button type="warning" size="mini" @click="$emit('syncVoucherPrice')">同步售价</el-button></div>
  210. </template>
  211. <template slot-scope="scope">
  212. <el-input-number v-model="scope.row.voucherPrice" :controls="false" :min="0" :precision="6" :step="0.01" style="width: auto;" />
  213. </template>
  214. </el-table-column>
  215. <el-table-column label="商品绑定的代金卷">
  216. <template #header="scope">
  217. <div>
  218. 商品绑定的代金卷
  219. <el-dropdown size="mini" split-button type="primary" @command="(e) => $emit('syncVoucherId', e)">
  220. 统一选择
  221. <el-dropdown-menu slot="dropdown">
  222. <el-dropdown-item v-for="item in voucherList" :key="item.id" :command="item.id">{{ item.voucherName }}</el-dropdown-item>
  223. </el-dropdown-menu>
  224. </el-dropdown>
  225. </div>
  226. </template>
  227. <template slot-scope="scope">
  228. <el-select v-model="scope.row.voucherId" placeholder="请选择商品绑定的代金卷">
  229. <el-option v-for="item in voucherList" :key="item.id" :label="item.voucherName" :value="item.id">
  230. </el-option>
  231. </el-select>
  232. </template>
  233. </el-table-column>
  234. <el-table-column label="国际条码">
  235. <template slot-scope="scope">
  236. <el-input v-model="scope.row.sku" maxlength="20" />
  237. </template>
  238. </el-table-column>
  239. <!-- <el-table-column label="操作">
  240. <template slot-scope="scope">
  241. <el-button type="text" @click="delAttrValue(scope.row,scope.$index,scope.row,scope)">删除</el-button>
  242. </template>
  243. </el-table-column> -->
  244. </el-table>
  245. </div>
  246. </div>
  247. <el-dialog
  248. :append-to-body="true" :visible.sync="dialogVisible" class="check-image-dialog" title="查看图片"
  249. center="center"
  250. >
  251. <img width="100%" :src="dialogImageUrl" alt>
  252. </el-dialog>
  253. <el-dialog
  254. width="30%" :append-to-body="true" :visible.sync="previewVideoVisible" class="check-image-dialog"
  255. title="预览视频" center="center"
  256. >
  257. <div style="display: flex; align-items: center; justify-content: center;">
  258. <video controls autoplay muted style="width: 400px; height: 400px;" :src="dialogVideoUrl"></video>
  259. </div>
  260. </el-dialog>
  261. </div>
  262. </template>
  263. <script>
  264. import { uploadUrl } from '@/utils/request'
  265. import { getToken } from '@/utils/auth'
  266. import { isVideo } from '@/utils/index'
  267. export default {
  268. // eslint-disable-next-line vue/match-component-file-name, vue/component-definition-name-casing
  269. name: 'addComponent',
  270. filters: {
  271. attrValueFilter(map, list) {
  272. const hasChilds =
  273. list &&
  274. list.filter((skuAttr) => {
  275. const hasChild = skuAttr.values.some((attr) => attr.skuValue)
  276. return skuAttr.skuName && hasChild
  277. })
  278. if (!map) {
  279. return ''
  280. }
  281. const { code, valueCode } = map
  282. let codeStr = ''
  283. // eslint-disable-next-line array-callback-return
  284. hasChilds.map((item) => {
  285. const { values } = item
  286. values &&
  287. values.some((attr) => {
  288. const isSome = item.code === code && attr.valueCode === valueCode
  289. if (isSome) {
  290. codeStr = attr.skuValue
  291. }
  292. return isSome
  293. })
  294. })
  295. return codeStr
  296. }
  297. },
  298. props: {
  299. form: {
  300. type: Object,
  301. default() {
  302. return {}
  303. }
  304. },
  305. voucherList: {
  306. type: Array,
  307. // eslint-disable-next-line vue/require-valid-default-prop
  308. default: []
  309. }
  310. },
  311. data() {
  312. return {
  313. dialogImageUrl: '',
  314. dialogVideoUrl: '',
  315. dialogVisible: false,
  316. previewVideoVisible: false,
  317. headers: {
  318. 'Authorization-business': getToken(),
  319. 'tenant': 'MDAwMA=='
  320. },
  321. action: uploadUrl,
  322. dataObj: {
  323. folderId: 1
  324. },
  325. fileList: [],
  326. // 记录当前是哪里增加或者删除的
  327. idx:null
  328. }
  329. },
  330. computed: {
  331. skuAttrName() {
  332. return (
  333. this.form.skuAttrList &&
  334. this.form.skuAttrList.filter((skuAttr) => {
  335. const hasChilds = skuAttr.values.some((attr) => attr.skuValue)
  336. return skuAttr.skuName && hasChilds
  337. })
  338. )
  339. },
  340. singleStyle() {
  341. if (this.form.skuAttrList && this.form.skuAttrList[0]) {
  342. return this.form.skuAttrList && this.form.skuAttrList[0].values[0]
  343. }
  344. return {
  345. skuValue: ''
  346. }
  347. },
  348. skuList() {
  349. // console.log(this.form)
  350. if (this.form.attrStyle === 0) {
  351. return this.form.skuList.slice(0, 1)
  352. }
  353. return this.form.skuList
  354. }
  355. },
  356. watch: {
  357. 'form.skuAttrList': {
  358. handler(newVal, oldVal) {
  359. // 判断是否有规格值
  360. const hasChilds =
  361. this.form.skuAttrList &&
  362. this.form.skuAttrList.filter((skuAttr) => {
  363. const hasChild = skuAttr.values.some((attr) => attr.skuValue)
  364. return skuAttr.skuName && hasChild
  365. })
  366. // console.log(hasChilds);
  367. if (this.form.attrStyle === 1 && hasChilds.length) {
  368. this.skuFormat()
  369. }
  370. },
  371. deep: true
  372. },
  373. 'form.skuList': {
  374. handler(newVal, oldVal) {
  375. // console.log(newVal)
  376. // console.log(oldVal)
  377. // 修复因为添加规格导致的价格归零的问题
  378. oldVal.forEach((item, index) => {
  379. // newVal[index] = Object.assign(item, newVal[index])
  380. for (const key in newVal[index]) {
  381. if (item[key]) {
  382. newVal[index][key] = item[key]
  383. }
  384. }
  385. })
  386. // console.log(newVal)
  387. },
  388. deep: true
  389. }
  390. },
  391. methods: {
  392. isVideo,
  393. playVideo(url) {
  394. this.dialogVideoUrl = url
  395. this.previewVideoVisible = true
  396. },
  397. handleImageSuccess(response) {
  398. const url = response.data.url
  399. // eslint-disable-next-line vue/no-mutating-props
  400. this.form.imgs.push({
  401. imgPath: url
  402. })
  403. },
  404. // 移除图片
  405. handleRemove(file) {
  406. const { imgPath } = file
  407. // eslint-disable-next-line vue/no-mutating-props
  408. this.form.imgs = this.form.imgs.filter((item) => item.imgPath !== imgPath)
  409. },
  410. handleRemove1(file) {
  411. file.image = ''
  412. },
  413. handlePictureCardPreview(file) {
  414. this.dialogImageUrl = file.imgPath
  415. this.dialogVisible = true
  416. },
  417. handleImageSuccess1(response, file, fileList) {
  418. const url = response.data.url
  419. fileList[0].image = url
  420. },
  421. addAttrValue(index) {
  422. // eslint-disable-next-line vue/no-mutating-props
  423. this.form.skuAttrList[index].values.push({
  424. skuId: '',
  425. valueCode: '',
  426. skuValue: '',
  427. image: ''
  428. })
  429. if (this.idx == index) {
  430. this.form.deletes.splice(this.form.deletes.length - 1, 1)
  431. }
  432. // console.log(JSON.parse(JSON.stringify(this.form)))
  433. // console.log(this.form.skuAttrList[index])
  434. },
  435. addSkuAttrList() {
  436. // eslint-disable-next-line vue/no-mutating-props
  437. this.form.skuAttrList.push({
  438. code: '',
  439. skuName: '',
  440. values: [
  441. {
  442. skuValue: '',
  443. valueCode: '',
  444. image: '',
  445. isDelete: 0,
  446. sortOrder: 0
  447. }
  448. ],
  449. isDelete: 0,
  450. needImg: 0,
  451. sortOrder: 0
  452. })
  453. // console.log(this.form.skuAttrList)
  454. },
  455. // 删除规格值
  456. delValue(index, index1) {
  457. if (index1 < this.form.skuAttrList[index].values.length - 1) return
  458. this.idx = index
  459. const newList = JSON.parse(JSON.stringify(this.form.skuAttrList[index]))
  460. const valueObj = {
  461. code: newList.code,
  462. skuId: newList.skuId,
  463. valueCode: newList.values[index1].valueCode
  464. }
  465. // eslint-disable-next-line vue/no-mutating-props
  466. this.form.deletes.push(valueObj)
  467. console.log(this.form.deletes, '删除')
  468. // console.log(this.valueObj)
  469. this.form.skuAttrList[index].values.splice(index1, 1)
  470. // console.log(this.form.skuAttrList[index].values);
  471. },
  472. // 删除规格名
  473. delSkuAttrList(index) {
  474. const newList = JSON.parse(JSON.stringify(this.form.skuAttrList[index]))
  475. newList.values.forEach((item) => {
  476. const valueObj = {
  477. code: newList.code,
  478. skuId: newList.skuId,
  479. valueCode: ''
  480. }
  481. valueObj.valueCode = item.valueCode
  482. // eslint-disable-next-line vue/no-mutating-props
  483. this.form.deletes.push(valueObj)
  484. })
  485. // eslint-disable-next-line vue/no-mutating-props
  486. this.form.skuAttrList.splice(index, 1)
  487. },
  488. delAttrValue1(row, index, arr) { },
  489. skuFormat() {
  490. const skuListArray = []
  491. const result = {
  492. originalPrice: 0,
  493. price: 0,
  494. productId: '',
  495. skuAttrCodeDTOList: [
  496. {
  497. code: '',
  498. valueCode: ''
  499. }
  500. ],
  501. skuId: '',
  502. skuImage: '',
  503. stockNumber: 0,
  504. voucherId: 0,
  505. voucherPrice: 0,
  506. weight: 0
  507. }
  508. const doExchange = (arr, depth) => {
  509. const map = {
  510. arr: []
  511. }
  512. for (var i = 0; i < arr[depth].length; i++) {
  513. map.arr.push(arr[depth][i])
  514. const { code, valueCode, attrId } = arr[depth][i]
  515. result.skuAttrCodeDTOList[depth] = {
  516. code,
  517. valueCode,
  518. attrId
  519. }
  520. if (depth !== arr.length - 1) {
  521. doExchange(arr, depth + 1)
  522. } else {
  523. skuListArray.push(JSON.parse(JSON.stringify(result)))
  524. }
  525. }
  526. }
  527. // this.form.skuList = skuListArray
  528. // 获取规格值的所有组合
  529. const values = []
  530. // eslint-disable-next-line array-callback-return
  531. this.form.skuAttrList.map((skuItem, index) => {
  532. const attrList = []
  533. skuItem.code = skuItem.code || 'attr_code_' + index
  534. const { code } = skuItem
  535. skuItem.values &&
  536. // eslint-disable-next-line array-callback-return
  537. skuItem.values.map((attrItem, index1) => {
  538. attrItem.valueCode = skuItem.valueCode || code + '_value_' + index1
  539. const skuId = attrItem.skuId
  540. const attrId = attrItem.attrId
  541. if (attrItem.skuValue) {
  542. attrList.push({
  543. skuId,
  544. attrId,
  545. code,
  546. valueCode: attrItem.valueCode
  547. })
  548. }
  549. })
  550. if (attrList.length) {
  551. values.push(attrList)
  552. }
  553. })
  554. // 相互组合
  555. if (values.length) {
  556. doExchange(values, 0)
  557. }
  558. // console.log(this.form.skuList)
  559. // eslint-disable-next-line vue/no-mutating-props
  560. this.form.skuList = skuListArray.map((sku1) => {
  561. const { skuAttrList, skuAttrCodeDTOList } = sku1
  562. const skuAttrList1 = skuAttrCodeDTOList || skuAttrList
  563. const skuMap = this.form.skuList.filter((sku2) => {
  564. const skuAttrList2 = sku2.skuAttrList
  565. sku2.skuAttrCodeDTOList = skuAttrList2
  566. if (!skuAttrList2) return false
  567. const ids = []
  568. skuAttrList1.filter((item) => ids.push(item.id))
  569. const result = skuAttrList2.every((item) => ids.indexOf(item.attrValueId) !== -1)
  570. return result
  571. })
  572. let selectMap = sku1
  573. if (skuMap && skuMap.length) {
  574. selectMap = JSON.parse(JSON.stringify(skuMap[0]))
  575. selectMap.skuAttrCodeDTOList = skuAttrCodeDTOList
  576. }
  577. return selectMap
  578. })
  579. },
  580. changeFiles(file, fileList) {
  581. // console.log(file)
  582. // console.log(fileList)
  583. // eslint-disable-next-line prefer-const
  584. let uid = file.uid
  585. const isLt =
  586. file.size / 1024 / 5 >= 1 && file.size / 1024 / 1024 / 5 <= 1
  587. if (!isLt) {
  588. // this.$refs.upImagesFiles.abort()
  589. this.$message.error('上传文件大小不得小于5KB,不得大于5MB!')
  590. return false
  591. }
  592. // console.log(fileList)
  593. }
  594. }
  595. }
  596. </script>
  597. <style lang="scss" scoped>
  598. @import url("../../../styles/elDialog.scss");
  599. .style-information-component {
  600. width: 100%;
  601. min-height: 300px;
  602. padding: 24px;
  603. background-color: rgb(255, 255, 255);
  604. .el-form-item {
  605. margin-bottom: 10px;
  606. }
  607. .attr-value-list {
  608. display: flex;
  609. flex-wrap: wrap;
  610. .main-diagram {
  611. position: relative;
  612. width: 180px;
  613. .span-wrap {
  614. position: relative;
  615. display: inline-block;
  616. margin-top: 10px;
  617. .attr-actions {
  618. line-height: 100px;
  619. position: absolute;
  620. width: 100%;
  621. height: 100%;
  622. left: 0;
  623. top: 0;
  624. cursor: default;
  625. text-align: center;
  626. color: #fff;
  627. opacity: 0;
  628. font-size: 20px;
  629. background-color: rgba(0, 0, 0, 0.5);
  630. -webkit-transition: opacity 0.3s;
  631. transition: opacity 0.3s;
  632. z-index: 1;
  633. &:hover {
  634. opacity: 1;
  635. .attr-preview {
  636. display: inline-block;
  637. }
  638. i {
  639. color: #fff;
  640. font-size: 20px;
  641. }
  642. }
  643. }
  644. .attr-preview {
  645. display: none;
  646. cursor: pointer;
  647. font-size: 20px;
  648. color: #fff;
  649. }
  650. .attr-delete {
  651. margin-left: 15px;
  652. color: #fff;
  653. }
  654. }
  655. .attr-value-img {
  656. width: 100%;
  657. height: 100%;
  658. img {
  659. width: 100%;
  660. height: 100%;
  661. object-fit: contain;
  662. }
  663. }
  664. }
  665. }
  666. .m-8 {
  667. margin-right: 8px;
  668. }
  669. .upload-btn {
  670. box-sizing: border-box;
  671. display: flex;
  672. align-items: center;
  673. justify-content: center;
  674. width: 100%;
  675. height: 110px;
  676. cursor: pointer;
  677. border: 2px dashed #2e60f8;
  678. border-radius: 2px;
  679. background-color: #f8f9fb;
  680. text-align: center;
  681. font-size: 20px;
  682. color: #2e60f8;
  683. i {
  684. color: #2e60f8;
  685. font-size: 20px;
  686. }
  687. .upload-title {
  688. margin-left: 10px;
  689. font-size: 14px;
  690. }
  691. }
  692. .upload-wrap {
  693. margin-bottom: 25px;
  694. .el-upload-list__item {
  695. transition: none !important;
  696. }
  697. .el-upload,
  698. .el-upload-list__item {
  699. width: 100px;
  700. height: 100px;
  701. line-height: 100px;
  702. }
  703. .el-progress,
  704. .el-progress-circle {
  705. width: 80px !important;
  706. height: 80px !important;
  707. }
  708. }
  709. .sku-attr-list {
  710. .el-input {
  711. width: 180px;
  712. }
  713. }
  714. .single-style {
  715. .el-input {
  716. max-width: 180px;
  717. }
  718. }
  719. .add-attr-btn {
  720. margin-bottom: 25px;
  721. }
  722. .check-image-dialog {
  723. .el-dialog {
  724. margin-top: 25px;
  725. .el-dialog__body {
  726. img {
  727. max-width: 100%;
  728. max-height: 100%;
  729. height: 500px;
  730. object-fit: contain;
  731. }
  732. }
  733. }
  734. }
  735. .delImg {
  736. position: absolute;
  737. top: 12px;
  738. margin-left: -24px
  739. }
  740. .delImg:hover {
  741. border-radius: 50%;
  742. color: #ffffff;
  743. background: #2e60f8;
  744. cursor: pointer;
  745. }
  746. }
  747. </style>