index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. <template>
  2. <!-- 营销-积分商品 -->
  3. <div>
  4. <Card :bordered="false" dis-hover class="ivu-mt" :padding="0">
  5. <div class="new_card_pd">
  6. <!-- 查询条件 -->
  7. <Form ref="tableFrom" inline :model="tableFrom" :label-width="labelWidth"
  8. :label-position="labelPosition" @submit.native.prevent>
  9. <!-- <FormItem label="创建时间:" label-for="user_time">
  10. <DatePicker
  11. :editable="false"
  12. @on-change="onchangeTime"
  13. :value="timeVal"
  14. format="yyyy/MM/dd"
  15. type="datetimerange"
  16. placement="bottom-start"
  17. placeholder="自定义时间"
  18. class="mr20 input-add"
  19. :options="options"
  20. ></DatePicker>
  21. </FormItem> -->
  22. <!-- <FormItem label="上架状态:">
  23. <Select
  24. placeholder="请选择"
  25. clearable
  26. class="input-add"
  27. v-model="tableFrom.is_show"
  28. >
  29. <Option value="1">上架</Option>
  30. <Option value="0">下架</Option>
  31. </Select>
  32. </FormItem> -->
  33. <FormItem label="门店:">
  34. <Select v-model="tableFrom.store_id" clearable filterable @on-change="userSearchs"
  35. class="input-add">
  36. <Option v-for="item in staffData" :value="item.id" :key="item.id" :label="item.name">
  37. {{item.id}}-{{ item.name }}
  38. </Option>
  39. </Select>
  40. </FormItem>
  41. <!-- <Button type="primary" @click="add" class="mr10">添加镜像</Button>
  42. <Button v-auth="['export-storeSeckill']" class="export" icon="ios-share-outline"
  43. @click="exports">导出</Button> -->
  44. </Form>
  45. </div>
  46. </Card>
  47. <Card :bordered="false" dis-hover class="ivu-mt">
  48. <!-- 操作 -->
  49. <Button v-auth="['admin-erp-product_add']" type="primary" @click="add" class="mr10">添加镜像</Button>
  50. <!-- 积分商品-表格 -->
  51. <Table :columns="columns1" :data="tableList" :loading="loading" highlight-row no-userFrom-text="暂无数据"
  52. no-filtered-userFrom-text="暂无筛选结果" class="ivu-mt">
  53. <template slot-scope="{ row, index }" slot="passageway">
  54. <span> {{ row.bin_number.slice(0,2) }}</span>
  55. </template>
  56. <template slot-scope="{ row, index }" slot="control">
  57. <span> {{ row.bin_number.slice(2,3) }}</span>
  58. </template>
  59. <template slot-scope="{ row, index }" slot="layer">
  60. <span> {{ row.bin_number.slice(3,4) }}</span>
  61. </template>
  62. <template slot-scope="{ row, index }" slot="number">
  63. <span> {{ row.bin_number.slice(4) }}</span>
  64. </template>
  65. <template slot-scope="{ row, index }" slot="is_show">
  66. <i-switch v-auth="['admin-erp-product-setshow']" v-model="row.is_show" :value="row.is_show"
  67. :true-value="1" :false-value="0" @on-change="changeSwitch(row)" size="large">
  68. <span slot="open">上架</span>
  69. <span slot="close">下架</span>
  70. </i-switch>
  71. </template>
  72. <template slot-scope="{ row, index }" slot="unit_name_1">
  73. <div v-if="row.unit_name_1">
  74. <div>名称:{{row.unit_name_1}}</div>
  75. <div>转换率:1{{row.unit_name_1}} = {{row.unit_rate_1*1}}{{row.unit_name}}</div>
  76. </div>
  77. </template>
  78. <template slot-scope="{ row, index }" slot="unit_name_2">
  79. <div v-if="row.unit_name_2">
  80. <div>名称:{{row.unit_name_2}}</div>
  81. <div>转换率:1{{row.unit_name_2}} = {{row.unit_rate_2*1}}{{row.unit_name}}</div>
  82. </div>
  83. </template>
  84. <template slot-scope="{ row, index }" slot="is_weigh">
  85. {{row.is_weigh == 1?'是': '否'}}
  86. </template>
  87. <template slot-scope="{ row, index }" slot="action">
  88. <!-- <a @click="look(row)">详情</a>
  89. <Divider type="vertical" /> -->
  90. <a @click="edit(row)" v-auth="['admin-erp-product_add']">编辑</a>
  91. <!-- <template v-auth="['admin-erp-product-del']">
  92. <Divider type="vertical" />
  93. <a @click="del(row, '删除商品', index)">删除</a>
  94. </template> -->
  95. <template v-auth="['admin-erp-product-del']">
  96. <Divider type="vertical" />
  97. <a @click="tbprod(row,index)">同步商品</a>
  98. </template>
  99. </template>
  100. </Table>
  101. <div class="acea-row row-right page">
  102. <Page :total="total" :current="tableFrom.page" show-elevator show-total @on-change="pageChange"
  103. :page-size="tableFrom.limit" />
  104. </div>
  105. </Card>
  106. <Modal v-model="modal" scrollable title="创建" class="order_box" :closable="false" :mask-closable="false">
  107. <Form ref="remarks" :model="remarks" :label-width="80" @submit.native.prevent>
  108. <FormItem label="门店:">
  109. <Select v-model="remarks.store_id" clearable filterable @on-change="storeChoose" class="input-add">
  110. <Option v-for="item in staffData" :value="item.id" :key="item.id">{{ item.name }}
  111. </Option>
  112. </Select>
  113. </FormItem>
  114. <FormItem label="创建人:">
  115. <Select v-model="remarks.create_uid" clearable filterable @on-change="userSearchse" class="input-add">
  116. <Option v-for="item in authLists" :value="item.id" :key="item.id">{{ item.staff_name }}
  117. </Option>
  118. </Select>
  119. </FormItem>
  120. </Form>
  121. <div slot="footer">
  122. <Button type="primary" @click="putRemark()">创建</Button>
  123. <Button @click="cancel()">取消</Button>
  124. </div>
  125. </Modal>
  126. <!-- <productDetail ref="productDetail"></productDetail> -->
  127. </div>
  128. </template>
  129. <script>
  130. import {
  131. staffListInfo
  132. } from "@/api/store";
  133. import {
  134. mapState
  135. } from "vuex";
  136. import {
  137. productInfoApi,
  138. cascaderListApi,
  139. productAddApi,
  140. generateAttrApi,
  141. productGetRuleApi,
  142. productGetTemplateApi,
  143. productGetTempKeysApi,
  144. checkActivityApi,
  145. labelListApi,
  146. productCache,
  147. cacheDelete,
  148. brandList,
  149. productCreateApi,
  150. productAllUnit,
  151. productUnitCreate,
  152. uploadType,
  153. productAllEnsure,
  154. productLabelAdd,
  155. productAllSpecs,
  156. allSystemForm
  157. } from "@/api/product";
  158. import {
  159. integralProductListApi,
  160. integralIsShowApi,
  161. storeSeckillApi,
  162. } from "@/api/marketing";
  163. import {
  164. mirrorList,
  165. getUserInfo,
  166. getGoodInfo,
  167. setShow,
  168. mainSetShow,
  169. mirrorExport,
  170. getUserList,
  171. addMirror
  172. } from "@/api/erp";
  173. import {
  174. formatDate
  175. } from "@/utils/validate";
  176. import timeOptions from "@/utils/timeOptions";
  177. import Setting from "@/setting";
  178. // import productDetail from './productDetail.vue'
  179. import exportExcel from "@/utils/newToExcel.js";
  180. export default {
  181. name: "jingxiang",
  182. filters: {
  183. formatDate(time) {
  184. if (time !== 0) {
  185. let date = new Date(time * 1000);
  186. return formatDate(date, "yyyy-MM-dd");
  187. }
  188. },
  189. },
  190. data() {
  191. return {
  192. remarks: {
  193. create_uid: '',
  194. create_admin_id: '',
  195. store_id: '',
  196. },
  197. modal: false,
  198. staffData: [],
  199. stId: '',
  200. jgTime: 50,
  201. roterPre: Setting.roterPre,
  202. loading: false,
  203. options: timeOptions,
  204. columns1: [{
  205. title: "ID",
  206. key: "id",
  207. width: 80,
  208. },
  209. {
  210. title: "商品名称",
  211. key: "store_name",
  212. minWidth: 90,
  213. },
  214. {
  215. title: "总销量",
  216. key: "all_sales",
  217. minWidth: 90,
  218. },
  219. {
  220. title: "总库存",
  221. key: "stock",
  222. minWidth: 90,
  223. },
  224. {
  225. title: "单位",
  226. key: "unit_name",
  227. minWidth: 90,
  228. },
  229. {
  230. title: "上下架",
  231. slot: "is_show",
  232. minWidth: 90,
  233. },
  234. {
  235. title: "大单位",
  236. slot: "unit_name_1",
  237. minWidth: 90,
  238. },
  239. {
  240. title: "超大单位",
  241. slot: "unit_name_2",
  242. minWidth: 90,
  243. },
  244. {
  245. title: "商品条码",
  246. key: "bar_code",
  247. minWidth: 90,
  248. },
  249. {
  250. title: "成本价",
  251. key: "cost",
  252. minWidth: 90,
  253. },
  254. {
  255. title: "是否称重",
  256. slot: "is_weigh",
  257. minWidth: 90,
  258. },
  259. {
  260. title: "操作",
  261. slot: "action",
  262. fixed: "right",
  263. width: 200,
  264. },
  265. ],
  266. tableList: [],
  267. timeVal: [],
  268. grid: {
  269. xl: 7,
  270. lg: 10,
  271. md: 12,
  272. sm: 24,
  273. xs: 24,
  274. },
  275. tableFrom: {
  276. // integral_time: "",
  277. // is_show: "",
  278. // store_name: "",
  279. store_id: '',
  280. key: '',
  281. page: 1,
  282. limit: 10,
  283. },
  284. total: 0,
  285. loadingss: false,
  286. isDan: false,
  287. ylprod: [],
  288. ylLen: 0,
  289. authLists: []
  290. };
  291. },
  292. computed: {
  293. ...mapState("admin/layout", ["isMobile"]),
  294. labelWidth() {
  295. return this.isMobile ? undefined : 96;
  296. },
  297. labelPosition() {
  298. return this.isMobile ? "top" : "right";
  299. },
  300. },
  301. created() {
  302. this.getList();
  303. this.staffList()
  304. },
  305. methods: {
  306. putRemark() {
  307. addMirror(this.remarks).then(res => {
  308. })
  309. },
  310. cancel(){
  311. this.remarks = {
  312. create_admin_id: '',
  313. create_uid: '',
  314. store_id: ''
  315. };
  316. this.modal = false
  317. },
  318. userSearchse(e) {
  319. let auth = this.authLists.find(item => item.id == e)
  320. this.remarks.create_admin_id = auth.admin_id
  321. },
  322. handleFileSelect(event) {
  323. console.log(event, 'event')
  324. const file = event.target.files[0]
  325. const reader = new FileReader()
  326. reader.readAsText(file, "UTF-8")
  327. reader.onload = (evt) => {
  328. let fileString = evt.target.result;
  329. fileString = fileString.replace(/\n/g, ',').replace(/\r/g, '')
  330. // const count = fileString.trim().split('\n').length
  331. this.ylprod = fileString.split(',');
  332. this.ylLen = this.ylprod.length;
  333. // this.bgProd()
  334. // console.log(typeof(fileString),fileString,arr,'fileString',evt)
  335. // this.dataArr = []
  336. // for (let index = 1; index < count; index++) {
  337. // const fileline = fileString.split("\r\n")[index].split(",")[0]
  338. // const filelineNumber = (fileline.split(/\s+/)).map(Number)
  339. // this.dataArr.push(filelineNumber)
  340. // }
  341. }
  342. },
  343. bgProd(index = 0) {
  344. let that = this
  345. if (index == that.ylLen) return;
  346. // 获取商品信息
  347. getGoods({
  348. id: that.ylprod[index]
  349. }).then(res => {
  350. // console.log(res.data.data)
  351. let arr = res.data.data;
  352. if (arr.length > 0) {
  353. let qdata = that.setUpdate(arr[0])
  354. // console.log(qdata)
  355. productAddApi(qdata).then(ress => {
  356. that.$Message.success(ress.msg);
  357. index++;
  358. that.bgProd(index);
  359. })
  360. }
  361. })
  362. },
  363. tbprod(row, index) {
  364. this.isDan = true;
  365. this.upGoods(row, index)
  366. },
  367. changeSwitch(row) {
  368. console.log(row, row.id, row.is_show)
  369. if (!this.tableFrom.store_id) {
  370. mainSetShow({
  371. id: row.id,
  372. is_show: row.is_show
  373. }).then(res => {
  374. this.$Message.success(res.msg);
  375. this.getList(1)
  376. }).catch(err => {
  377. this.$Message.success(err.msg);
  378. this.getList(1)
  379. })
  380. } else {
  381. setShow({
  382. store_id: this.tableFrom.store_id,
  383. id: row.id,
  384. is_show: row.is_show
  385. }).then(res => {
  386. this.$Message.success(res.msg);
  387. this.getList(1)
  388. }).catch(err => {
  389. this.$Message.success(err.msg);
  390. this.getList(1)
  391. })
  392. }
  393. },
  394. staffList() {
  395. staffListInfo()
  396. .then((res) => {
  397. this.staffData = res.data;
  398. })
  399. .catch((err) => {
  400. this.$Message.error(err.msg);
  401. });
  402. },
  403. userSearchs(e) {
  404. this.getList(1)
  405. },
  406. begin(index = 0) {
  407. // if(this.)
  408. let that = this;
  409. let len = that.tableList.length;
  410. if (index == len) {
  411. this.tableFrom.page++;
  412. this.loadingss = true
  413. this.getList()
  414. return;
  415. };
  416. console.log('开始');
  417. setTimeout(() => {
  418. that.upGoods(that.tableList[index], index)
  419. }, that.jgTime)
  420. // that.upGoods(that.tableList[index],index)
  421. },
  422. setUpdate(good) {
  423. return {
  424. "stock": 10,
  425. "is_weigh": good.is_weigh,
  426. "applicable_store_id": [],
  427. "system_form_id": 0,
  428. "is_presale_product": 0,
  429. "is_limit": 0,
  430. "limit_type": 1,
  431. "limit_num": 1,
  432. "is_vip_product": 0,
  433. "is_support_refund": 1,
  434. "disk_info": "",
  435. "presale_day": 1,
  436. "presale_time": [],
  437. "auto_on_time": "",
  438. "video_open": false,
  439. "store_name": good.store_name,
  440. "freight": 1,
  441. "postage": 0,
  442. "custom_form": [],
  443. "cate_id": [
  444. 1,
  445. 2
  446. ],
  447. "label_id": [],
  448. "ensure_id": [],
  449. "keyword": "",
  450. "applicable_type": 0,
  451. "unit_name": good.unit_name,
  452. "specs_id": 0,
  453. "store_info": "",
  454. "bar_code": good.bar_code,
  455. "code": "",
  456. "image": "",
  457. "recommend_image": "",
  458. "slider_image": [
  459. "https://shop.yiqucguoyuan.com/uploads/attach/2024/07/20240724/efb26cf8e741fa950209589f58e0df5a.png"
  460. ],
  461. "description": "<p>" + good.store_name + "<br/></p>",
  462. "ficti": 0,
  463. "give_integral": 0,
  464. "sort": 0,
  465. "is_show": 1,
  466. "is_hot": 0,
  467. "is_benefit": 0,
  468. "is_best": 0,
  469. "is_new": 0,
  470. "is_good": 0,
  471. "is_postage": 0,
  472. "is_sub": [],
  473. "id": 0,
  474. "spec_type": 0,
  475. "video_link": "",
  476. "temp_id": "",
  477. "attrs": [{
  478. "pic": "https://shop.yiqucguoyuan.com/uploads/attach/2024/07/20240724/efb26cf8e741fa950209589f58e0df5a.png",
  479. "price": good.price,
  480. "settle_price": 0,
  481. "cost": 0,
  482. "ot_price": 0,
  483. "erp_product_id": good.id,
  484. "unit": good.unit_name,
  485. "uint_to_erp_unit": 1,
  486. "bar_code": good.bar_code,
  487. "code": "",
  488. "weight": good.is_weigh,
  489. "volume": 0,
  490. "brokerage": 0,
  491. "brokerage_two": 0,
  492. "vip_price": good.vip_price,
  493. "virtual_list": [],
  494. "write_times": 0,
  495. "write_valid": 1,
  496. "days": 1
  497. }],
  498. "items": [],
  499. "activity": [
  500. "默认",
  501. "秒杀",
  502. "砍价",
  503. "拼团"
  504. ],
  505. "couponName": [],
  506. "header": [],
  507. "selectRule": "",
  508. "coupon_ids": [],
  509. "command_word": "",
  510. "delivery_type": [
  511. "1",
  512. "3",
  513. "2"
  514. ],
  515. "specs": [],
  516. "recommend_list": [],
  517. "brand_id": [],
  518. "product_type": 0,
  519. "type": 0,
  520. "store_label_id": []
  521. }
  522. },
  523. upGoods(good, index) {
  524. let qdata = this.setUpdate()
  525. if (this.stId && this.stId > good.id) {
  526. return;
  527. }
  528. productAddApi(qdata).then(res => {
  529. this.$Message.success(res.msg);
  530. if (this.isDan) {
  531. return this.isDan = false;
  532. } else {
  533. index++;
  534. this.begin(index);
  535. }
  536. })
  537. },
  538. look(row) {
  539. try {
  540. this.$refs.productDetail.getInfo(row.id)
  541. } catch (e) {
  542. //TODO handle the exception
  543. }
  544. // getGoodInfo(row.id).then(res=> {
  545. // console.log(res,'商品详情');
  546. // })
  547. },
  548. // 添加
  549. add() {
  550. this.modal = true
  551. // this.$router.push({
  552. // path: this.roterPre + "/erp/product_add?id=0"
  553. // });
  554. },
  555. storeChoose(row) {
  556. console.log('xje',row)
  557. try{
  558. let qdata = {}
  559. qdata.store_id = row;
  560. this.authLists = [];
  561. this.remarks.create_uid = '';
  562. this.remarks.create_admin_id = '';
  563. getUserList(qdata).then(res => {
  564. this.authLists = res.data.data;
  565. })
  566. }catch(e) {
  567. console.log(e)
  568. }
  569. },
  570. addMore() {
  571. this.$router.push({
  572. path: this.roterPre + "/marketing/store_integral/add_store_integral",
  573. });
  574. },
  575. orderList(row) {
  576. this.$router.push({
  577. path: this.roterPre + "/marketing/store_integral/order_list",
  578. query: {
  579. product_id: row.id,
  580. },
  581. });
  582. },
  583. // 导出
  584. exports() {
  585. mirrorExport({
  586. store_id: this.tableFrom.store_id
  587. })
  588. .then((res) => {
  589. // location.href = res.data[0];
  590. let data = res.data
  591. exportExcel(data.header, data.filekey, data.fileName, data.export);
  592. })
  593. .catch((res) => {
  594. this.$Message.error(res.msg);
  595. });
  596. },
  597. // 编辑
  598. edit(row) {
  599. this.$router.push({
  600. path: this.roterPre + "/erp/product_add?id=" + row.id
  601. });
  602. },
  603. // 一键复制
  604. copy(row) {
  605. this.$router.push({
  606. path: this.roterPre + "/marketing/store_integral/create/" + row.id + "/1",
  607. });
  608. },
  609. // 删除
  610. del(row, tit, num) {
  611. let delfromData = {
  612. title: tit,
  613. num: num,
  614. url: `/erp/goods/del/${row.id}`,
  615. method: "DELETE",
  616. ids: "",
  617. };
  618. this.$modalSure(delfromData)
  619. .then((res) => {
  620. this.$Message.success(res.msg);
  621. this.tableList.splice(num, 1);
  622. if (!this.tableList.length) {
  623. this.tableFrom.page =
  624. this.tableFrom.page == 1 ? 1 : this.tableFrom.page - 1;
  625. }
  626. this.getList();
  627. })
  628. .catch((res) => {
  629. this.$Message.error(res.msg);
  630. });
  631. },
  632. // 列表
  633. getList() {
  634. this.loading = true;
  635. // this.tableFrom.start_status = this.tableFrom.start_status || "";
  636. // this.tableFrom.is_show = this.tableFrom.is_show || "";
  637. mirrorList(this.tableFrom)
  638. .then(async (res) => {
  639. let data = res.data;
  640. this.tableList = data.data;
  641. this.total = data.count;
  642. this.loading = false;
  643. if (this.loadingss && this.tableList.length > 0) {
  644. this.begin(0)
  645. }
  646. })
  647. .catch((res) => {
  648. this.loading = false;
  649. this.$Message.error(res.msg);
  650. });
  651. },
  652. pageChange(index) {
  653. this.tableFrom.page = index;
  654. this.getList();
  655. },
  656. // 表格搜索
  657. tableSearchs() {
  658. this.tableFrom.page = 1;
  659. this.getList();
  660. },
  661. // 具体日期
  662. onchangeTime(e) {
  663. this.timeVal = e;
  664. this.tableFrom.integral_time = this.timeVal[0] ? this.timeVal.join("-") : "";
  665. },
  666. // 修改是否显示
  667. onchangeIsShow(row) {
  668. let data = {
  669. id: row.id,
  670. is_show: row.is_show,
  671. };
  672. integralIsShowApi(data)
  673. .then(async (res) => {
  674. this.$Message.success(res.msg);
  675. })
  676. .catch((res) => {
  677. this.$Message.error(res.msg);
  678. });
  679. },
  680. },
  681. };
  682. </script>
  683. <style scoped lang="stylus">
  684. .tabBox_img {
  685. width: 36px;
  686. height: 36px;
  687. border-radius: 4px;
  688. cursor: pointer;
  689. img {
  690. width: 100%;
  691. height: 100%;
  692. }
  693. }
  694. </style>