specs.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. <template>
  2. <view class="specs">
  3. <checkbox-group @change="checkboxChange">
  4. <view
  5. class="list acea-row"
  6. :class="administer ? 'on' : ''"
  7. v-for="(item, index) in attrsList"
  8. :key="index"
  9. >
  10. <!-- #ifndef MP -->
  11. <checkbox
  12. class="checkbox"
  13. v-if="administer"
  14. :value="item.id.toString()"
  15. :checked="item.checked"
  16. />
  17. <!-- #endif -->
  18. <!-- #ifdef MP -->
  19. <checkbox
  20. class="checkbox"
  21. v-if="administer"
  22. :value="item.id"
  23. :checked="item.checked"
  24. />
  25. <!-- #endif -->
  26. <view class="listCon">
  27. <!-- <view class="item acea-row row-middle">
  28. <view class="name">商品图</view>
  29. <view class="pictrue">
  30. <image :src="item.image" mode="aspectFill"></image>
  31. </view>
  32. </view> -->
  33. <view class="item acea-row row-middle">
  34. <view class="name">规格名称</view>
  35. <view class="info">{{ item.suk }}</view>
  36. </view>
  37. <view class="item acea-row row-middle">
  38. <view class="name">售价</view>
  39. <input
  40. type="digit"
  41. :disabled="administer"
  42. min="0"
  43. v-model="item.price"
  44. placeholder="请填写售价"
  45. placeholder-class="placeholder"
  46. />
  47. </view>
  48. <view class="item acea-row row-middle">
  49. <view class="name">成本价</view>
  50. <input
  51. type="digit"
  52. :disabled="administer"
  53. v-model="item.cost"
  54. placeholder="请填写成本价"
  55. placeholder-class="placeholder"
  56. />
  57. </view>
  58. <view class="item acea-row row-middle">
  59. <view class="name">原价</view>
  60. <input
  61. type="digit"
  62. :disabled="administer"
  63. v-model="item.ot_price"
  64. placeholder="请填写原价"
  65. placeholder-class="placeholder"
  66. />
  67. </view>
  68. <view class="item acea-row row-middle">
  69. <view class="name">库存</view>
  70. <input
  71. type="number"
  72. :disabled="administer"
  73. v-model="item.stock"
  74. placeholder="请填写库存"
  75. placeholder-class="placeholder"
  76. />
  77. </view>
  78. </view>
  79. </view>
  80. </checkbox-group>
  81. <view class="footer on acea-row row-between-wrapper" v-if="administer">
  82. <checkbox-group @change="checkboxAllChange">
  83. <checkbox value="all" :checked="isAllSelect" />
  84. <text class="checkAll">全选</text>
  85. </checkbox-group>
  86. <view class="acea-row row-middle">
  87. <view class="bnt acea-row row-center-wrapper" @click="manageTap"
  88. >取消</view
  89. >
  90. <view class="bnt on acea-row row-center-wrapper" @click="batchEdit"
  91. >批量修改</view
  92. >
  93. </view>
  94. </view>
  95. <view class="footer acea-row row-between-wrapper" v-else>
  96. <view class="bnt acea-row row-center-wrapper" @click="manageTap"
  97. >批量操作</view
  98. >
  99. <view class="bnt on acea-row row-center-wrapper" @click="define"
  100. >保存</view
  101. >
  102. </view>
  103. <edit-price
  104. :visible="visiblePrice"
  105. :goodsInfo="goodsInfo"
  106. @closeDrawer="priceCloseDrawer"
  107. @successChange="successChange"
  108. ></edit-price>
  109. </view>
  110. </template>
  111. <script>
  112. import editPrice from "./components/editPrice/index.vue";
  113. import { getManageProductAttr, postUpdateAttrs } from "@/api/admin";
  114. export default {
  115. components: {
  116. editPrice,
  117. },
  118. data() {
  119. return {
  120. attrsList: [],
  121. id: 0,
  122. administer: false,
  123. isAllSelect: false,
  124. visiblePrice: false,
  125. goodsInfo: {
  126. id: 0,
  127. spec_type: 1,
  128. attr_value: {},
  129. },
  130. };
  131. },
  132. onShow() {},
  133. onLoad(option) {
  134. this.id = option.id;
  135. this.getAttrsList();
  136. },
  137. methods: {
  138. //批量获取id集合
  139. getIds() {
  140. let ids = [];
  141. this.attrsList.forEach((item) => {
  142. if (item.checked) {
  143. ids.push(item.id);
  144. }
  145. });
  146. return ids;
  147. },
  148. batchEdit() {
  149. if (!this.getIds().length) {
  150. this.$util.Tips({
  151. title: "请选择商品规格",
  152. });
  153. return;
  154. }
  155. this.goodsInfo.id = this.id;
  156. this.goodsInfo.attr_value = {
  157. cost: "",
  158. price: "",
  159. ot_price: "",
  160. stock: "",
  161. };
  162. this.visiblePrice = true;
  163. },
  164. define() {
  165. let data = {
  166. attr_value: [],
  167. };
  168. this.attrsList.forEach((item) => {
  169. data.attr_value.push({
  170. cost: item.cost,
  171. price: item.price,
  172. ot_price: item.ot_price,
  173. stock: item.stock,
  174. unique: item.unique,
  175. });
  176. });
  177. postUpdateAttrs(this.id, data)
  178. .then((res) => {
  179. this.$util.Tips(
  180. {
  181. title: res.msg,
  182. },
  183. () => {
  184. uni.redirectTo({
  185. url: "/pages/admin/goods/index",
  186. });
  187. },
  188. );
  189. })
  190. .catch((err) => {
  191. this.$util.Tips({
  192. title: err,
  193. });
  194. });
  195. },
  196. getAttrsList() {
  197. getManageProductAttr(this.id)
  198. .then((res) => {
  199. let data = res.data;
  200. data.forEach((item) => {
  201. item.checked = false;
  202. });
  203. this.attrsList = data;
  204. })
  205. .catch((err) => {
  206. this.$util.Tips({
  207. title: err,
  208. });
  209. });
  210. },
  211. checkboxChange(event) {
  212. let idList = event.detail.value;
  213. this.attrsList.forEach((item) => {
  214. if (idList.indexOf(item.id + "") !== -1) {
  215. item.checked = true;
  216. } else {
  217. item.checked = false;
  218. }
  219. });
  220. if (idList.length == this.attrsList.length) {
  221. this.isAllSelect = true;
  222. } else {
  223. this.isAllSelect = false;
  224. }
  225. },
  226. forGoods(val) {
  227. let that = this;
  228. if (!that.attrsList.length) return;
  229. that.attrsList.forEach((item) => {
  230. if (val) {
  231. item.checked = true;
  232. } else {
  233. item.checked = false;
  234. }
  235. });
  236. },
  237. checkboxAllChange(event) {
  238. let value = event.detail.value;
  239. if (value.length) {
  240. this.isAllSelect = true;
  241. this.forGoods(1);
  242. } else {
  243. this.isAllSelect = false;
  244. this.forGoods(0);
  245. }
  246. },
  247. manageTap() {
  248. this.administer = !this.administer;
  249. },
  250. priceCloseDrawer() {
  251. this.visiblePrice = false;
  252. },
  253. successChange(e) {
  254. this.visiblePrice = false;
  255. let data = e;
  256. this.attrsList.forEach((item) => {
  257. if (item.checked) {
  258. if (data.cost) {
  259. item.cost = data.cost;
  260. }
  261. if (data.price) {
  262. item.price = data.price;
  263. }
  264. if (data.ot_price) {
  265. item.ot_price = data.ot_price;
  266. }
  267. if (data.stock) {
  268. item.stock = data.stock;
  269. }
  270. }
  271. });
  272. this.manageTap();
  273. this.attrsList = this.attrsList.map((item) => {
  274. return {
  275. ...item,
  276. checked: false,
  277. };
  278. });
  279. },
  280. },
  281. };
  282. </script>
  283. <style lang="scss" scoped>
  284. ::v-deep checkbox .uni-checkbox-input.uni-checkbox-input-checked {
  285. border: 1px solid $primary-admin !important;
  286. background-color: $primary-admin !important;
  287. }
  288. ::v-deep checkbox .wx-checkbox-input.wx-checkbox-input-checked {
  289. border: 1px solid $primary-admin !important;
  290. background-color: $primary-admin !important;
  291. }
  292. .specs {
  293. padding: 24rpx 20rpx 112rpx 20rpx;
  294. padding-bottom: calc(
  295. 112rpx + constant(safe-area-inset-bottom)
  296. ); ///兼容 IOS<11.2/
  297. padding-bottom: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  298. .list {
  299. background-color: #fff;
  300. border-radius: 24rpx;
  301. padding: 0 24rpx;
  302. margin-bottom: 20rpx;
  303. .listCon {
  304. flex: 1;
  305. }
  306. &.on {
  307. input {
  308. color: #999999 !important;
  309. }
  310. }
  311. .checkbox {
  312. margin: 32rpx 12rpx 0 0;
  313. }
  314. .item {
  315. min-height: 102rpx;
  316. font-size: 28rpx;
  317. font-family:
  318. PingFang SC,
  319. PingFang SC;
  320. font-weight: 400;
  321. & ~ .item {
  322. border-top: 1px solid #f1f1f1;
  323. }
  324. .name {
  325. color: #333333;
  326. width: 115rpx;
  327. margin-right: 39rpx;
  328. }
  329. .info {
  330. color: #999999;
  331. flex: 1;
  332. }
  333. input {
  334. font-size: 36rpx;
  335. font-family: "Regular";
  336. color: #333333;
  337. }
  338. // #ifdef MP
  339. input {
  340. font-size: 30rpx;
  341. }
  342. // #endif
  343. .placeholder {
  344. font-size: 28rpx;
  345. }
  346. .pictrue {
  347. width: 100rpx;
  348. height: 100rpx;
  349. image {
  350. width: 100%;
  351. height: 100%;
  352. border-radius: 16rpx;
  353. }
  354. }
  355. }
  356. }
  357. .footer {
  358. box-sizing: border-box;
  359. padding: 0 20rpx;
  360. width: 100%;
  361. height: 112rpx;
  362. background-color: #fff;
  363. position: fixed;
  364. bottom: 0;
  365. z-index: 30;
  366. height: calc(112rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  367. height: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  368. padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
  369. padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
  370. width: 100%;
  371. left: 0;
  372. &.on {
  373. height: 96rpx;
  374. height: calc(96rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  375. height: calc(96rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  376. .bnt {
  377. width: 160rpx;
  378. height: 64rpx;
  379. font-size: 24rpx;
  380. &.on {
  381. background-color: $primary-admin;
  382. color: #fff;
  383. margin-left: 16rpx;
  384. }
  385. }
  386. }
  387. .bnt {
  388. width: 346rpx;
  389. height: 72rpx;
  390. border-radius: 200rpx;
  391. border: 1px solid $primary-admin;
  392. color: $primary-admin;
  393. font-size: 26rpx;
  394. font-family:
  395. PingFang SC,
  396. PingFang SC;
  397. font-weight: 500;
  398. &.on {
  399. background-color: $primary-admin;
  400. color: #fff;
  401. }
  402. }
  403. }
  404. }
  405. </style>