list.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. <template>
  2. <div style="padding-top: 10px;">
  3. <i-page-header :title="pageTitle"></i-page-header>
  4. <Card :bordered="false" dis-hover class="ivu-mt">
  5. <!-- <Form ref="orderData" :model="orderData">
  6. <Row :gutter="24" type="flex">
  7. <Col>
  8. <FormItem label="UID:" label-for="uid">
  9. <Input placeholder="用户UID" v-model="orderData.uid"/>
  10. </FormItem>
  11. </Col>
  12. <Col>
  13. <FormItem label="绑定手机:" label-for="mobile">
  14. <Input placeholder="绑定手机号码" v-model="orderData.mobile"/>
  15. </FormItem>
  16. </Col>
  17. <Col>
  18. <FormItem label="购买时间:">
  19. <DatePicker v-model="orderData.time" format="yyyy/MM/dd HH:mm:ss" type="datetimerange" placement="bottom-start" placeholder="自定义时间" style="width: 300px;" class="mr20" :options="options"></DatePicker>
  20. </FormItem>
  21. </Col>
  22. <Col>
  23. <Button label="default" type="primary" icon="ios-search" class="mr15" style="margin-top: 32px;" @click="orderSearch()">搜索</Button>
  24. </Col>
  25. </Row>
  26. </Form> -->
  27. <Col>
  28. <Button type="primary" class="export" icon="ios-share-outline" @click="sendOpen">添加商品</Button>
  29. </Col>
  30. <Table :columns="columns" :data="orderList" ref="table" :loading="loading" highlight-row no-data-text="暂无数据"
  31. no-filtered-data-text="暂无筛选结果" class="orderData mt25">
  32. <template slot-scope="{ row, index }" slot="order_id">
  33. <span v-text="row.order_id" style="display: block;"></span>
  34. </template>
  35. <template slot-scope="{ row, index }" slot="uid">
  36. <div>{{ row.nickname || '微信用户' }}[UID:{{ row.uid }}]</div>
  37. <div>{{ row.mobile || '未绑定手机号' }}</div>
  38. </template>
  39. <template slot-scope="{ row, index }" slot="imgs">
  40. <div style="display: flex;">
  41. <img v-lazy="row.image" :src="row.image" v-image-preview
  42. style="width: 60px;cursor: pointer" />
  43. </div>
  44. </template>
  45. <template slot-scope="{ row, index }" slot="handle">
  46. <div><el-button plain size="mini" @click="editGood(row)">编辑</el-button></div>
  47. <br />
  48. <div><el-button plain size="mini" @click="delGood(row.id)">删除</el-button></div>
  49. </template>
  50. </Table>
  51. <div class="acea-row row-right page">
  52. <Page :total="page.count" show-elevator show-total @on-change="tapPage" :page-size="page.pageSize" />
  53. </div>
  54. </Card>
  55. <Modal v-model="sendModel" title="添加商品" @on-ok="sendOk('sendFormValidate')" @on-cancel="sendCancel" width="900">
  56. <Form :model="sendData" :label-width="labelWidth" :rules="ruleValidate" ref="sendFormValidate">
  57. <FormItem label="商品名称" prop="store_name">
  58. <Input v-model="sendData.store_name" type="text" placeholder="请输入商品名称"></Input>
  59. </FormItem>
  60. <FormItem label="商品分类" prop="cate_id">
  61. <el-select v-model="sendData.cate_id" placeholder="选择分类">
  62. <el-option :label="item.cate_name" :value="item.id" v-for="(item, index) in cateData"
  63. :key="index"></el-option>
  64. </el-select>
  65. </FormItem>
  66. <FormItem label="兑换积分" prop="price">
  67. <Input v-model="sendData.price" type="number" placeholder="请输入兑换积分"></Input>
  68. </FormItem>
  69. <FormItem label="商品库存" prop="stock">
  70. <Input v-model="sendData.stock" type="number" placeholder="请输入商品库存"></Input>
  71. </FormItem>
  72. <!-- unit_name -->
  73. <FormItem label="商品单位" prop="unit_name">
  74. <Input v-model="sendData.unit_name" type="text" placeholder="请输入商品单位"></Input>
  75. </FormItem>
  76. <FormItem label="商品销量" prop="sales">
  77. <Input v-model="sendData.sales" type="number" placeholder="请输入商品销量"></Input>
  78. </FormItem>
  79. <FormItem label="封面图片" prop="image">
  80. <div class="clearfix">
  81. <div class="upimg-item fx-r fx-bc fx-ac" style="" v-if="sendData.image">
  82. <img v-lazy="sendData.image" :src="sendData.image" v-image-preview />
  83. <i class="el-icon-error img-remove-btn" @click="removeImg(index)"></i>
  84. </div>
  85. <ui-upload style="float: left;" :upUrl="upUrl" fileName="上传图片" :headers="upHeaders"
  86. :updata="{ isz: 0, code: 'goods' }" @onUpload="onUpload"
  87. v-if="sendData.image == ''"></ui-upload>
  88. </div>
  89. </FormItem>
  90. <FormItem label="轮播图片" prop="slider_image">
  91. <div class="clearfix">
  92. <div class="upimg-item fx-r fx-bc fx-ac" style="" v-for="(item, index) in sendData.slider_image"
  93. :key="index">
  94. <img v-lazy="item" :src="item" v-image-preview />
  95. <i class="el-icon-error img-remove-btn" @click="removeImgs(index)"></i>
  96. </div>
  97. <ui-upload style="float: left;" :upUrl="upUrl" fileName="上传图片" :headers="upHeaders"
  98. :updata="{ isz: 0, code: 'goods' }" @onUpload="onUploads"
  99. v-if="sendData.slider_image.length < 6"></ui-upload>
  100. </div>
  101. </FormItem>
  102. <FormItem label="商品详情" prop="content">
  103. <Toolbar style="border: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" />
  104. <!-- 编辑器 -->
  105. <Editor style="height: 400px; overflow-y: hidden;border: 1px solid #ccc;"
  106. :defaultConfig="editorConfig" v-model="sendData.content" @onChange="onChange"
  107. @onCreated="onCreated" />
  108. </FormItem>
  109. <FormItem label="是否上架" prop="status">
  110. <el-radio-group v-model="sendData.is_show">
  111. <el-radio :label="1">上架</el-radio>
  112. <el-radio :label="0">下架</el-radio>
  113. </el-radio-group>
  114. </FormItem>
  115. </Form>
  116. <div slot="footer">
  117. <Button size="large" :loading="modal_loading" @click="sendCancel">取消</Button>
  118. <Button type="primary" size="large" :loading="modal_loading"
  119. @click="sendOk('sendFormValidate')">提交</Button>
  120. </div>
  121. </Modal>
  122. </div>
  123. </template>
  124. <script>
  125. import { getGoodsCate, getGoodsList, saveProduct,delProduct } from "../../../api/system/goods";
  126. import axios from 'axios'
  127. import {
  128. DomEditor
  129. } from '@wangeditor/editor'
  130. import {
  131. Editor,
  132. Toolbar
  133. } from '@wangeditor/editor-for-vue'
  134. import IPageHeader from "../../../layouts/system/page-header/index";
  135. import {
  136. SystemShowTemplateList
  137. } from "../../../api/system/user";
  138. import Setting from '@/setting';
  139. import UiUpload from "@/ui/upload/index";
  140. import {
  141. upLoad
  142. } from '../../../api/system/sys'
  143. export default {
  144. name: "pointsList",
  145. components: {
  146. SystemShowTemplateList,
  147. IPageHeader,
  148. UiUpload,
  149. Editor,
  150. Toolbar
  151. },
  152. computed: {},
  153. data() {
  154. return {
  155. editor: null,
  156. toolbarConfig: {
  157. // toolbarKeys: [ /* 显示哪些菜单,如何排序、分组 */ ],
  158. excludeKeys: ['group-video', 'emotion', 'fullScreen'],
  159. },
  160. editorConfig: {
  161. placeholder: "请输入内容...",
  162. // autoFocus: false,
  163. // 所有的菜单配置,都要在 MENU_CONF 属性下
  164. MENU_CONF: {
  165. uploadImage: {
  166. },
  167. },
  168. },
  169. modal_loading: false,
  170. ruleValidate: {
  171. cate_id: [{
  172. required: true,
  173. message: '请选择商品分类'
  174. }],
  175. store_name: [{
  176. required: true,
  177. message: '请输入商品名称',
  178. trigger: 'blur'
  179. }],
  180. content: [{
  181. required: true,
  182. message: '请输入商品详情',
  183. }],
  184. stock: [{
  185. required: true,
  186. message: '请输入商品库存',
  187. }],
  188. image: [{
  189. required: true,
  190. message: '请上传封面图片'
  191. }],
  192. slider_image: [{
  193. required: true,
  194. message: '请上传轮播图片'
  195. }],
  196. price: [{
  197. required: true,
  198. message: '请输入兑换积分',
  199. trigger: 'blur'
  200. }],
  201. },
  202. labelWidth: 120,
  203. upHeaders: {},
  204. upUrl: '',
  205. sendData: {
  206. sales: '',
  207. cate_id: '',
  208. price: '',
  209. stock: '',
  210. store_name: '',
  211. content: '',
  212. image: '',
  213. slider_image: [],
  214. is_show: 1
  215. },
  216. sendModel: false,
  217. pageTitle: "积分商品",
  218. options: {
  219. shortcuts: [{
  220. text: '今天',
  221. value() {
  222. const end = new Date();
  223. const start = new Date();
  224. start.setTime(new Date(new Date().getFullYear(), new Date().getMonth(), new Date()
  225. .getDate()));
  226. return [start, end];
  227. }
  228. },
  229. {
  230. text: '昨天',
  231. value() {
  232. const end = new Date();
  233. const start = new Date();
  234. start.setTime(start.setTime(new Date(new Date().getFullYear(), new Date().getMonth(),
  235. new Date().getDate() - 1)));
  236. end.setTime(end.setTime(new Date(new Date().getFullYear(), new Date().getMonth(),
  237. new Date().getDate())));
  238. return [start, end];
  239. }
  240. },
  241. {
  242. text: '最近7天',
  243. value() {
  244. const end = new Date();
  245. const start = new Date();
  246. start.setTime(start.setTime(new Date(new Date().getFullYear(), new Date().getMonth(),
  247. new Date().getDate() - 6)));
  248. return [start, end];
  249. }
  250. },
  251. {
  252. text: '最近30天',
  253. value() {
  254. const end = new Date();
  255. const start = new Date();
  256. start.setTime(start.setTime(new Date(new Date().getFullYear(), new Date().getMonth(),
  257. new Date().getDate() - 29)));
  258. return [start, end];
  259. }
  260. },
  261. {
  262. text: '本月',
  263. value() {
  264. const end = new Date();
  265. const start = new Date();
  266. start.setTime(start.setTime(new Date(new Date().getFullYear(), new Date().getMonth(),
  267. 1)));
  268. return [start, end];
  269. }
  270. },
  271. {
  272. text: '本年',
  273. value() {
  274. const end = new Date();
  275. const start = new Date();
  276. start.setTime(start.setTime(new Date(new Date().getFullYear(), 0, 1)));
  277. return [start, end];
  278. }
  279. }
  280. ]
  281. },
  282. orderData: {
  283. uid: "",
  284. status: "all",
  285. time: [],
  286. mobile: "",
  287. show_template_id: "",
  288. unit_name: "",
  289. },
  290. columns: [{
  291. title: 'ID',
  292. align: 'center',
  293. key: 'id',
  294. align: 'center'
  295. },
  296. {
  297. title: '商品封面',
  298. align: 'center',
  299. slot: 'imgs',
  300. align: 'center'
  301. },
  302. {
  303. title: '商品名',
  304. key: 'store_name',
  305. align: 'center'
  306. },
  307. {
  308. title: '单位',
  309. align: 'center',
  310. key: 'unit_name',
  311. align: 'left'
  312. },
  313. {
  314. title: '积分',
  315. align: 'center',
  316. key: 'price',
  317. align: 'left'
  318. },
  319. {
  320. title: '时间',
  321. align: 'center',
  322. key: 'create_time',
  323. align: 'left'
  324. },
  325. {
  326. title: '操作',
  327. align: 'center',
  328. slot: 'handle',
  329. align: 'left'
  330. },
  331. ],
  332. loading: false,
  333. orderList: [],
  334. orderDatalist: {},
  335. orderId: 0,
  336. page: {
  337. total: 0, // 总条数
  338. page: 1, // 当前页
  339. pageSize: 10 // 每页显示条数
  340. },
  341. cateData: [],
  342. }
  343. },
  344. created() {
  345. if (this.$route.query.title) {
  346. this.pageTitle = this.$route.query.title;
  347. }
  348. if (this.$route.query.uid) {
  349. this.orderData.uid = parseInt(this.$route.query.uid);
  350. }
  351. if (this.$route.query.show_template_id) {
  352. this.orderData.show_template_id = parseInt(this.$route.query.show_template_id);
  353. }
  354. this.initView();
  355. this.getGoodsList();
  356. this.getGoodsCate();
  357. },
  358. methods: {
  359. getGoodsList() {
  360. getGoodsList().then(res => {
  361. this.orderList = res.data.list.map(item => {
  362. item.slider_image = item.slider_image.split(',');
  363. return item;
  364. });
  365. })
  366. },
  367. getGoodsCate() {
  368. getGoodsCate().then(res => {
  369. this.cateData = res.data.list;
  370. })
  371. },
  372. onCreated(editor) {
  373. this.editor = Object.seal(editor); // 【注意】一定要用 Object.seal() 否则会报错
  374. console.log(this.editor.getMenuConfig());
  375. },
  376. onChange(editor) {
  377. console.log("onChange", editor.getHtml()); // onChange 时获取编辑器最新内容
  378. },
  379. getEditorText() {
  380. const editor = this.editor;
  381. if (editor == null) return;
  382. console.log(editor.getText()); // 执行 editor API
  383. },
  384. printEditorHtml() {
  385. const editor = this.editor;
  386. if (editor == null) return;
  387. console.log(editor.getHtml()); // 执行 editor API
  388. },
  389. initView: function () {
  390. let that = this
  391. var upHeaders = {};
  392. this.upUrl = Setting.apiBaseURL + "/systemv1/upload/index";
  393. const token = this.$utils.util.cookies.get('system_token');
  394. if (token) {
  395. upHeaders['SYSTEM-ACC-TOKEN'] = token;
  396. }
  397. this.upHeaders = upHeaders;
  398. this.editorConfig.MENU_CONF['uploadImage'] = {
  399. async customUpload(file, insertFn) {
  400. const formData = new FormData()
  401. formData.append('file', file)
  402. formData.append('code', 'good')
  403. formData.append('isz', '0')
  404. // formData.append('sign', this.generateSign(file.name)) // 自定义签名
  405. try {
  406. // const response = await axios.post(that.upUrl, formData, {
  407. // headers: {
  408. // 'SYSTEM-ACC-TOKEN': token
  409. // }
  410. // })
  411. upLoad(formData).then(res => {
  412. insertFn(res.data.img)
  413. })
  414. // if (response.data.success) {
  415. // // 插入图片到编辑器
  416. // }
  417. } catch (error) {
  418. console.error('上传失败:', error)
  419. }
  420. }
  421. }
  422. },
  423. onUpload: function (res) {
  424. if (res.code == -1) {
  425. Notice.error({
  426. title: "系统提示",
  427. content: res.msg
  428. });
  429. } else {
  430. this.sendData.image = res.data.img;
  431. }
  432. },
  433. onUploads: function (res) {
  434. if (res.code == -1) {
  435. Notice.error({
  436. title: "系统提示",
  437. content: res.msg
  438. });
  439. } else {
  440. this.sendData.slider_image.push(res.data.img);
  441. }
  442. },
  443. removeImgs: function (index) {
  444. this.sendData.slider_image.splice(index, 1);
  445. // this.$delete(this.sendData.imgs, index);
  446. },
  447. removeImg: function (index) {
  448. // this.$delete(this.sendData.imgs, index);
  449. this.sendData.image = ''
  450. },
  451. sendOpen() {
  452. this.sendModel = true
  453. },
  454. sendCancel() {
  455. this.sendModel = false
  456. this.sendData = {
  457. content: '',
  458. slider_image: [],
  459. store_name: '',
  460. }
  461. },
  462. sendOk(name) {
  463. console.log(this.sendData);
  464. this.$refs[name].validate((valid) => {
  465. if (valid) {
  466. let pdata = JSON.parse(JSON.stringify(this.sendData));
  467. pdata.slider_image = pdata.slider_image.join(',');
  468. saveProduct(pdata).then(res => {
  469. if (res.code == 200) {
  470. this.sendCancel()
  471. this.getGoodsList()
  472. this.$Message.success('发布成功!');
  473. } else {
  474. this.$Message.error(res.msg);
  475. }
  476. }).catch(err => {
  477. this.$Message.error(err.msg);
  478. })
  479. } else { }
  480. })
  481. },
  482. tabsHandleClick: function (tab, event) {
  483. this.page.page = 1;
  484. this.getData();
  485. },
  486. orderSearch: function () {
  487. this.page.page = 1;
  488. this.getData();
  489. },
  490. /**
  491. * 分页
  492. */
  493. tapPage: function (index) {
  494. this.page.page = index;
  495. this.getData();
  496. },
  497. delGood(id) {
  498. this.$confirm('确定删除吗?', '系统提示', {
  499. confirmButtonText: '确定',
  500. cancelButtonText: '取消',
  501. type: 'warning'
  502. }).then(() => {
  503. delProduct({
  504. id: id
  505. }).then(res => {
  506. if (res.code == 200) {
  507. this.$Message.success('删除成功!');
  508. this.getGoodsList()
  509. } else {
  510. this.$Message.error(res.msg);
  511. }
  512. }).catch(err => {
  513. this.$Message.error(err.msg);
  514. })
  515. }).catch(() => {
  516. this.$Message({
  517. type: 'info',
  518. message: '已取消删除'
  519. });
  520. });
  521. },
  522. editGood(row) {
  523. this.sendData = JSON.parse(JSON.stringify(row));
  524. this.sendModel = true;
  525. },
  526. /**
  527. * 获取数据
  528. */
  529. getData: function () {
  530. var that = this;
  531. // this.loading = true;
  532. var data = {
  533. page: that.page.page,
  534. ...that.orderData
  535. };
  536. // SystemShowTemplateList(data)
  537. // .then(res=>{
  538. // that.loading = false;
  539. // if(res.code == 200) {
  540. // that.orderList = res.data.list;
  541. // that.page.pageSize = res.data.pageSize;
  542. // that.page.count = res.data.pageCount;
  543. // } else {
  544. // that.$alert(res.msg);
  545. // }
  546. // })
  547. // .catch(err=>{
  548. // that.loading = false;
  549. // that.$alert("网络繁忙,加载失败,请稍等片刻在尝试!", '系统提示');
  550. // });
  551. },
  552. }
  553. }
  554. </script>
  555. <style src="@wangeditor/editor/dist/css/style.css"></style>
  556. <style scoped>
  557. @import "~vue2-editor/dist/vue2-editor.css";
  558. .upimg-item {
  559. width: 82px;
  560. height: 82px;
  561. margin-right: 5px;
  562. overflow: hidden;
  563. float: left;
  564. margin-bottom: 5px;
  565. position: relative;
  566. }
  567. .upimg-item img {
  568. width: 82px;
  569. cursor: pointer;
  570. }
  571. .img-remove-btn {
  572. position: absolute;
  573. top: 0px;
  574. right: 0px;
  575. font-size: 24px;
  576. }
  577. </style>