Преглед изворни кода

团购-商品管理、团设置

YY пре 2 година
родитељ
комит
827c381800

+ 12 - 0
src/router/module/platGroup.js

@@ -1,4 +1,16 @@
 export default [
+  {
+    path: '/platGroup/goods',
+    name: 'platGroup_goods',
+    meta: { title: '平台团购-商品管理' },
+    component: () => import('@/views/platGroup/goods/index.vue'),
+  },
+  {
+    path: '/platGroup/group',
+    name: 'platGroup_group',
+    meta: { title: '平台团购-开团管理' },
+    component: () => import('@/views/platGroup/group/index.vue'),
+  },
   {
     path: '/platGroup/order',
     name: 'platGroup_order',

+ 24 - 1
src/store/index.js

@@ -3,6 +3,7 @@ import Vuex from 'vuex';
 import * as ustate from './module/user/state';
 import * as umutations from './module/user/mutations';
 import admin from './module/user/action';
+// 用户
 import users from './module/user/users';
 
 import todo from './module/statistics/todo';
@@ -15,8 +16,11 @@ import dictData from './module/dev/dictData';
 import menus from './module/dev/menus';
 import role from './module/dev/role';
 
+// 商品标签
 import goodsTags from './module/system/goodsTags';
+// 广告图
 import banner from './module/system/banner';
+// 首页图标
 import indexModule from './module/system/indexModule';
 import actTags from './module/system/actTags';
 import config from './module/system/config';
@@ -24,24 +28,39 @@ import platformAct from './module/system/platformAct';
 import goodsJoinAct from './module/system/goodsJoinAct';
 import admins from './module/system/admin';
 
+// 店铺信息
 import shop from './module/shop/shop';
+// 商品信息
 import goods from './module/shop/goods';
 import serviceContact from './module/shop/serviceContact';
+// 商品规格
 import goodsSpec from './module/shop/goodsSpec';
 import afterSale from './module/shop/afterSale';
 import getTransportInfo from './module/shop/getTransportInfo';
 import goodsRate from './module/shop/goodsRate';
 
+// 订单
 import order from './module/trade/order';
+// 订单详情
 import orderDetail from './module/trade/orderDetail';
 import sot from './module/trade/sot';
 import coupon from './module/trade/coupon';
 import cashOut from './module/trade/cashOut';
-
+// 尊荣
 import zrGoods from './module/zr/zrGoods';
 import zrOrder from './module/zr/zrOrder';
 import zrSot from './module/zr/zrSot';
 
+// 团购
+// 售后
+import groupAfterSale from './module/group/groupAfterSale';
+// 订单
+import groupOrder from './module/group/groupOrder';
+// 商品
+import goodsConfig from './module/group/goodsConfig';
+// 团表
+import group from './module/group/group';
+
 Vue.use(Vuex);
 
 export default new Vuex.Store({
@@ -82,5 +101,9 @@ export default new Vuex.Store({
     zrGoods,
     zrOrder,
     zrSot,
+    groupAfterSale,
+    groupOrder,
+    goodsConfig,
+    group,
   },
 });

+ 45 - 0
src/store/module/group/goodsConfig.js

@@ -0,0 +1,45 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+const _ = require('lodash');
+Vue.use(Vuex);
+const api = {
+  url: '/point/group/v1/api/goodsConfig',
+};
+
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.url}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.url}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.url}/${payload}`);
+    return res;
+  },
+
+  async update({ commit }, payload) {
+    const id = _.get(payload, 'id', _.get(payload, '_id'));
+    const res = await this.$axios.$post(`${api.url}/${id}`, payload);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.url}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 45 - 0
src/store/module/group/group.js

@@ -0,0 +1,45 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+const _ = require('lodash');
+Vue.use(Vuex);
+const api = {
+  url: '/point/group/v1/api/group',
+};
+
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.url}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.url}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.url}/${payload}`);
+    return res;
+  },
+
+  async update({ commit }, payload) {
+    const id = _.get(payload, 'id', _.get(payload, '_id'));
+    const res = await this.$axios.$post(`${api.url}/${id}`, payload);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.url}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 45 - 0
src/store/module/group/groupAfterSale.js

@@ -0,0 +1,45 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+const _ = require('lodash');
+Vue.use(Vuex);
+const api = {
+  url: '/point/group/v1/api/groupAfterSale',
+};
+
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.url}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.url}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.url}/${payload}`);
+    return res;
+  },
+
+  async update({ commit }, payload) {
+    const id = _.get(payload, 'id', _.get(payload, '_id'));
+    const res = await this.$axios.$post(`${api.url}/${id}`, payload);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.url}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 45 - 0
src/store/module/group/groupOrder.js

@@ -0,0 +1,45 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+const _ = require('lodash');
+Vue.use(Vuex);
+const api = {
+  url: '/point/group/v1/api/groupOrder',
+};
+
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.url}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.url}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.url}/${payload}`);
+    return res;
+  },
+
+  async update({ commit }, payload) {
+    const id = _.get(payload, 'id', _.get(payload, '_id'));
+    const res = await this.$axios.$post(`${api.url}/${id}`, payload);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.url}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 142 - 0
src/views/platGroup/goods/detail.vue

@@ -0,0 +1,142 @@
+<template>
+  <div id="detail">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-col :span="24" style="margin: 0 0 10px 0">
+          <el-col :span="2"><el-button type="primary" size="mini" @click="toBack()">返回</el-button></el-col>
+        </el-col>
+        <el-col :span="24">
+          <data-form :fields="infoFields" :rules="rules" v-model="form" labelWidth="150px" @save="toSave">
+            <template #goods>
+              <el-select
+                v-model="form.goods"
+                filterable
+                remote
+                reserve-keyword
+                placeholder="请选择商品名称"
+                :remote-method="querySearch"
+                :loading="loading"
+                
+                @change="handleSelect"
+                size="small"
+                style="width: 100%"
+              >
+                <el-option v-for="item in goodsList" :key="item._id" :label="item.name" :value="item._id"> </el-option>
+              </el-select>
+              <p style="color: red">输入商品名称查询</p>
+            </template>
+            <template #spec>
+              <el-option v-for="i in specList" :key="i._id" :label="i.name" :value="i._id"></el-option>
+            </template>
+          </data-form> </el-col
+      ></el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: goodsConfig } = createNamespacedHelpers('goodsConfig');
+const { mapActions: goods } = createNamespacedHelpers('goods');
+const { mapActions: goodsSpec } = createNamespacedHelpers('goodsSpec');
+export default {
+  name: 'detail',
+  props: { id: { type: String } },
+  components: {},
+  data: function () {
+    return {
+      // info部分
+      infoFields: [
+        { label: '商品名称', model: 'goods', custom: true },
+        { label: '商品规格', model: 'spec', type: 'select' },
+        { label: '团长价', model: 'leader_price', type: 'number' },
+        { label: '团购价', model: 'price', type: 'number' },
+        { label: '团长提成金额', model: 'leader_get', type: 'number' },
+      ],
+      rules: {
+        goods: [{ required: true, message: '商品名称', trigger: 'change' }],
+        spec: [{ required: true, message: '商品规格', trigger: 'change' }],
+        leader_price: [{ required: true, message: '团长价', trigger: 'blur' }],
+        price: [{ required: true, message: '团购价', trigger: 'blur' }],
+        leader_get: [{ required: true, message: '团长提成金额', trigger: 'blur' }],
+      },
+      form: {},
+      // 加载
+      loading: false,
+      // 远程搜索商品列表
+      goodsList: [],
+      // 规格列表
+      specList: [],
+    };
+  },
+  created() {
+    // this.searchOthers();
+    this.search();
+  },
+  methods: {
+    ...goods({ goodsQuery: 'query', goodsFetch: 'fetch' }),
+    ...goodsSpec({ specQuery: 'query', specFetch: 'fetch' }),
+    ...goodsConfig(['query', 'delete', 'fetch', 'update', 'create']),
+    // 查询
+    async search() {
+      if (this.id) {
+        const res = await this.fetch(this.id);
+        if (this.$checkRes(res)) {
+          let arr = await this.goodsFetch(res.data.goods);
+          if (this.$checkRes(arr)) this.goodsList.push(arr.data);
+          let aee = await this.specFetch(res.data.spec);
+          if (this.$checkRes(aee)) this.specList.push(aee.data);
+          this.$set(this, `form`, res.data);
+        }
+      } else {
+        const obj = { shop: _.get(this.user.shop, '_id') };
+        this.$set(this, 'form', obj);
+      }
+    },
+    // 远程查询
+    async querySearch(value) {
+      this.loading = true;
+      let res = await this.goodsQuery({ name: value });
+      if (this.$checkRes(res)) this.$set(this, 'goodsList', res.data);
+      this.loading = false;
+    },
+    // 选择-查询规格
+    async handleSelect(value) {
+      let res = await this.specQuery({ goods: value });
+      if (this.$checkRes(res)) {
+        this.$set(this, 'specList', res.data);
+      }
+    },
+    // 保存
+    async toSave({ data }) {
+      let res;
+      if (data._id) res = await this.update(data);
+      else res = await this.create(data);
+      if (this.$checkRes(res)) {
+        this.$message({ type: `success`, message: `维护信息成功` });
+        this.toBack();
+        this.search();
+      }
+    },
+    // 返回
+    toBack() {
+      this.$emit('toBack');
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 113 - 0
src/views/platGroup/goods/index.vue

@@ -0,0 +1,113 @@
+<template>
+  <div id="goods">
+    <el-row>
+      <el-col
+        :span="24"
+        class="main animate__animated animate__backInRight"
+        v-loading="loadings"
+        element-loading-text="拼命加载中"
+        element-loading-spinner="el-icon-loading"
+      >
+        <span v-if="view === 'list'">
+          <data-search :fields="searchFields" v-model="searchInfo" @query="search"> </data-search>
+          <data-btn :fields="btnList" @add="toAdd"></data-btn>
+          <data-table
+            ref="dataTable"
+            :fields="fields"
+            :opera="opera"
+            :data="list"
+            :total="total"
+            @query="search"
+            @edit="toEdit"
+            @delete="toDelete"
+          ></data-table>
+        </span>
+        <detail v-if="view === 'info'" :id="id" @toBack="toBack"></detail>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+const _ = require('lodash');
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: goodsConfig } = createNamespacedHelpers('goodsConfig');
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    detail: () => import('./detail.vue'),
+  },
+  data: function () {
+    return {
+      loadings: true,
+      view: 'list',
+      fields: [
+        { label: '商品名称', model: 'goods', showTip: false },
+        { label: '规格名称', model: 'spec' },
+        { label: '团长价', model: 'leader_price' },
+        { label: '团购价', model: 'price' },
+        { label: '团长提成金额', model: 'leader_get' },
+      ],
+      opera: [
+        { label: '修改', method: 'edit' },
+        { label: '删除', method: 'delete', confirm: true, type: 'danger' },
+      ],
+      btnList: [{ label: '添加', method: 'add' }],
+      searchFields: [
+        { label: '商品名称', model: 'goods' },
+        { label: '规格名称', model: 'spec' },
+      ],
+      searchInfo: {},
+      list: [],
+      total: 0,
+      id: '',
+    };
+  },
+  created() {
+    this.search();
+  },
+  methods: {
+    ...goodsConfig(['query', 'delete', 'fetch', 'update', 'create']),
+    // 查询
+    async search({ skip = 0, limit = this.$limit, ...others } = {}) {
+      let query = { skip, limit, ...others };
+      if (Object.keys(this.searchInfo).length > 0) query = { ...query, ...this.searchInfo };
+      const res = await this.query(query);
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+      this.loadings = false;
+    },
+    // 新增
+    toAdd() {
+      let id = '';
+      this.$set(this, `id`, id);
+      this.$set(this, `view`, 'info');
+    },
+    // 修改
+    async toEdit({ data }) {
+      this.$set(this, `id`, data._id);
+      this.$set(this, `view`, 'info');
+    },
+    // 删除
+    async toDelete({ data }) {
+      let res = await this.delete(data._id);
+      if (this.$checkRes(res)) {
+        this.$message({ type: `success`, message: `刪除信息成功` });
+        this.search();
+      }
+    },
+    // 执行返回
+    toBack() {
+      this.view = 'list';
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 262 - 0
src/views/platGroup/group/detail.vue

@@ -0,0 +1,262 @@
+<template>
+  <div id="detail">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-col :span="24" style="margin: 0 0 10px 0">
+          <el-col :span="2"><el-button type="primary" size="mini" @click="toBack()">返回</el-button></el-col>
+        </el-col>
+        <el-col :span="24">
+          <data-form :fields="infoFields" :rules="rules" v-model="form" labelWidth="150px" @save="toSave">
+            <template #goods>
+              <el-select
+                v-model="form.goods"
+                filterable
+                clearable
+                remote
+                reserve-keyword
+                :remote-method="querySearch"
+                placeholder="请选择商品名称"
+                :loading="loading"
+                @change="handleSelect"
+                size="small"
+                style="width: 100%"
+              >
+                <el-option v-for="item in goodsList" :key="item._id" :label="item.name" :value="item._id"> </el-option>
+              </el-select>
+              <p style="color: red">只能查询到设置团购金额的商品</p>
+            </template>
+            <template #leader>
+              <el-select
+                v-model="form.leader"
+                filterable
+                clearable
+                remote
+                reserve-keyword
+                :remote-method="leadSearch"
+                placeholder="请输入团长"
+                size="small"
+                style="width: 100%"
+              >
+                <el-option v-for="item in userList" :key="item._id" :label="item.name" :value="item._id"> </el-option>
+              </el-select>
+            </template>
+            <template #status>
+              <el-option v-for="i in statusList" :key="i.value" :label="i.label" :value="i.value"></el-option>
+            </template>
+            <template #group_config>
+              <el-col :span="24" style="margin: 0 0 10px 0">
+                <el-button type="primary" size="mini" @click="toReset()">重置</el-button>
+              </el-col>
+              <el-table :data="form.group_config" border size="mini">
+                <el-table-column label="规格名称" prop="spec" align="center">
+                  <template #default="{ row }">
+                    <el-input v-model="row.spec" type="text" placeholder="请输入规格名称"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="团长价" prop="leader_price" align="center">
+                  <template #default="{ row }">
+                    <el-input v-model="row.leader_price" type="number" placeholder="请输入团长价"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="团购价" prop="price" align="center">
+                  <template #default="{ row }">
+                    <el-input v-model="row.price" type="number" placeholder="请输入团购价"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="团长提成金额" prop="leader_get" align="center">
+                  <template #default="{ row }">
+                    <el-input v-model="row.leader_get" type="number" placeholder="请输入团长提成金额"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center">
+                  <template #default="scope">
+                    <el-button type="danger" size="mini" @click="toDel(scope.$index, 'idea')">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </template>
+          </data-form>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: group } = createNamespacedHelpers('group'); // 团表
+const { mapActions: goodsConfig } = createNamespacedHelpers('goodsConfig'); // 团购-商品设置
+const { mapActions: dictData } = createNamespacedHelpers('dictData'); // 字典
+const { mapActions: goods } = createNamespacedHelpers('goods'); // 商品
+const { mapActions: goodsSpec } = createNamespacedHelpers('goodsSpec'); // 商品规格
+const { mapActions: users } = createNamespacedHelpers('users'); // 用户;
+export default {
+  name: 'detail',
+  props: { id: { type: String } },
+  components: {},
+  data: function () {
+    return {
+      loading: false,
+      // info部分
+      infoFields: [
+        { label: '商品名称', model: 'goods', custom: true },
+        { label: '团长', model: 'leader', custom: true },
+        { label: '人数限制', model: 'person_limit', type: 'number' },
+        { label: '开始时间', model: 'start_time', type: 'datetime' },
+        { label: '结束时间', model: 'end_time', type: 'datetime' },
+        { label: '团状态', model: 'status', type: 'select' },
+        { label: '团购设置', model: 'group_config', custom: true },
+      ],
+      rules: {
+        goods: [{ required: true, message: '商品名称', trigger: 'change' }],
+        leader: [{ required: true, message: '团长', trigger: 'change' }],
+        person_limit: [{ required: true, message: '人数限制', trigger: 'blur' }],
+        start_time: [{ required: true, message: '开始时间', trigger: 'change' }],
+        end_time: [{ required: true, message: '结束时间', trigger: 'change' }],
+        status: [{ required: true, message: '团状态', trigger: 'change' }],
+      },
+      form: {
+        // 团购设置
+        group_config: [],
+      },
+      // 商品列表
+      goodsList: [],
+      // 团状态
+      statusList: [],
+      // 团长
+      userList: [],
+      users: [],
+    };
+  },
+  created() {
+    this.searchOthers();
+    this.search();
+  },
+  methods: {
+    ...dictData({ getDict: 'query' }),
+    ...goodsConfig({ goodsConfigQuery: 'query', goodsConfigFetch: 'fetch' }),
+    ...group(['query', 'delete', 'fetch', 'update', 'create']),
+    ...goods({ goodsQuery: 'query', goodsFetch: 'fetch' }),
+    ...goodsSpec({ specQuery: 'query', specFetch: 'fetch' }),
+    ...users({ userQuery: 'query' }),
+    // 查询
+    async search({ skip = 0, limit = this.$limit, ...others } = {}) {
+      if (this.id) {
+        const res = await this.fetch(this.id);
+        if (this.$checkRes(res)) {
+          let arr = await this.goodsFetch(res.data.goods);
+          if (this.$checkRes(arr)) this.goodsList.push(arr.data);
+          this.$set(this, `form`, res.data);
+        }
+      } else {
+        const obj = { shop: _.get(this.user.shop, '_id') };
+        this.$set(this, 'form', obj);
+      }
+    },
+    // 查询团长
+    leadSearch(value) {
+      if (value) {
+        let info = this.users.filter((f) => f.name.includes(value));
+        this.$set(this, `userList`, info);
+      } else this.$set(this, `userList`, this.users);
+    },
+    // 远程查询
+    async querySearch(value) {
+      this.loading = true;
+      let res = await this.goodsQuery({ name: value });
+      if (this.$checkRes(res)) {
+        // let list = [];
+        // for (const p1 of res.data) {
+        //   let arr = await this.goodsConfigQuery({ goods: p1._id });
+        //   if (this.$checkRes(arr)) {
+        //     if (arr.total > 0) list.push(p1);
+        //   }
+        // }
+        // console.log(list);
+        // this.$set(this, 'goodsList', list);
+        this.$set(this, 'goodsList', res.data);
+      }
+      this.loading = false;
+    },
+    // 选择-查询商品
+    async handleSelect(value) {
+      let res = await this.goodsConfigQuery({ goods: value });
+      if (this.$checkRes(res)) {
+        this.$set(this.form, 'group_config', res.data);
+      }
+    },
+    // 重置
+    async toReset() {
+      if (this.form.goods) {
+        let res = await this.goodsConfigQuery({ goods: this.form.goods });
+        if (this.$checkRes(res)) this.$set(this.form, 'group_config', res.data);
+      } else {
+        this.$message({ type: `warning`, message: `请选择商品` });
+      }
+    },
+    // 删除
+    toDel(index, type) {
+      var list = this.form.group_config;
+      list.splice(index, 1);
+    },
+    // 保存
+    async toSave({ data }) {
+      let res;
+      if (this.id) res = await this.update(data);
+      else res = await this.create(data);
+      if (this.$checkRes(res)) {
+        this.$message({ type: `success`, message: `维护信息成功` });
+        this.toBack();
+        this.search();
+      }
+    },
+    // 返回
+    toBack() {
+      this.$emit('toBack');
+    },
+    // 查询其他信息
+    async searchOthers() {
+      let res;
+      // res = await this.goodsConfigQuery();
+      // if (this.$checkRes(res)) {
+      //   for (const p1 of res.data) {
+      //     let arr = await this.goodsFetch(p1.goods);
+      //     if (this.$checkRes(arr)) p1.goods_name = arr.data.name;
+      //     let aee = await this.specFetch(p1.spec);
+      //     if (this.$checkRes(aee)) p1.spec_name = aee.data.name;
+      //     p1.name = p1.goods_name + '---' + p1.spec_name;
+      //     delete p1.goods_name;
+      //     delete p1.spec_name;
+      //   }
+      //   this.$set(this, 'goodsList', res.data);
+      // }
+      res = await this.getDict({ code: 'group_status' });
+      if (this.$checkRes(res)) this.$set(this, `statusList`, res.data);
+      // 团长列表
+      res = await this.userQuery({ is_leader: '0' });
+      if (this.$checkRes(res)) {
+        for (const p1 of res.data) {
+          p1.name = '团长' + '---' + p1.phone + '---' + p1.name;
+        }
+        this.$set(this, `userList`, res.data);
+        this.$set(this, `users`, res.data);
+      }
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 131 - 0
src/views/platGroup/group/index.vue

@@ -0,0 +1,131 @@
+<template>
+  <div id="goods">
+    <el-row>
+      <el-col
+        :span="24"
+        class="main animate__animated animate__backInRight"
+        v-loading="loadings"
+        element-loading-text="拼命加载中"
+        element-loading-spinner="el-icon-loading"
+      >
+        <span v-if="view === 'list'">
+          <data-search :fields="searchFields" v-model="searchInfo" @query="search"> </data-search>
+          <data-btn :fields="btnList" @add="toAdd"></data-btn>
+          <data-table
+            ref="dataTable"
+            :fields="fields"
+            :opera="opera"
+            :data="list"
+            :total="total"
+            @query="search"
+            @edit="toEdit"
+            @delete="toDelete"
+          ></data-table>
+        </span>
+        <detail v-if="view === 'info'" :id="id" @toBack="toBack"></detail>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+const _ = require('lodash');
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: group } = createNamespacedHelpers('group'); // 团表
+const { mapActions: dictData } = createNamespacedHelpers('dictData'); // 字典
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    detail: () => import('./detail.vue'),
+  },
+  data: function () {
+    return {
+      loadings: true,
+      view: 'list',
+      fields: [
+        { label: '商品名称', model: 'goods', showTip: false },
+        { label: '团长', model: 'leader' },
+        { label: '开始时间', model: 'start_time' },
+        { label: '结束时间', model: 'end_time' },
+        {
+          label: '团状态',
+          model: 'status',
+          format: (i) => {
+            let data = this.statusList.find((f) => f.value == i);
+            if (data) return data.label;
+            else return '暂无';
+          },
+        },
+      ],
+      opera: [
+        { label: '修改', method: 'edit' },
+        { label: '删除', method: 'delete', confirm: true, type: 'danger' },
+      ],
+      btnList: [{ label: '添加', method: 'add' }],
+      searchFields: [
+        { label: '商品名称', model: 'goods' },
+        { label: '规格名称', model: 'spec' },
+      ],
+      searchInfo: {},
+      list: [],
+      total: 0,
+      // 团状态
+      statusList: [],
+      id: '',
+    };
+  },
+  created() {
+    this.searchOthers();
+    this.search();
+  },
+  methods: {
+    ...dictData({ getDict: 'query' }),
+    ...group(['query', 'delete', 'fetch', 'update', 'create']),
+    // 查询
+    async search({ skip = 0, limit = this.$limit, ...others } = {}) {
+      let query = { skip, limit, ...others };
+      if (Object.keys(this.searchInfo).length > 0) query = { ...query, ...this.searchInfo };
+      const res = await this.query(query);
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+      this.loadings = false;
+    },
+    // 新增
+    toAdd() {
+      let id = '';
+      this.$set(this, `id`, id);
+      this.$set(this, `view`, 'info');
+    },
+    // 修改
+    async toEdit({ data }) {
+      this.$set(this, `id`, data._id);
+      this.$set(this, `view`, 'info');
+    },
+    // 删除
+    async toDelete({ data }) {
+      let res = await this.delete(data._id);
+      if (this.$checkRes(res)) {
+        this.$message({ type: `success`, message: `刪除信息成功` });
+        this.search();
+      }
+    },
+    // 执行返回
+    toBack() {
+      this.view = 'list';
+    },
+    // 查询其他信息
+    async searchOthers() {
+      let res = await this.getDict({ code: 'group_status' });
+      if (this.$checkRes(res)) this.$set(this, `statusList`, res.data);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 193 - 7
src/views/platGroup/order/index.vue

@@ -1,22 +1,190 @@
 <template>
   <div id="index">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col
+        :span="24"
+        class="main animate__animated animate__backInRight"
+        v-loading="loadings"
+        element-loading-text="拼命加载中"
+        element-loading-spinner="el-icon-loading"
+      >
+        <span v-show="view === 'list'">
+          <el-col :span="24" class="one"> <span>订单管理</span> </el-col>
+          <el-col :span="24" class="four">
+            <el-tabs v-model="activeName" @tab-click="handleClick" type="border-card">
+              <el-tab-pane name="1" label="待付款"> </el-tab-pane>
+              <el-tab-pane name="2" label="待发货"> </el-tab-pane>
+              <el-tab-pane name="3" label="部分发货"> </el-tab-pane>
+              <el-tab-pane name="4" label="待收货"> </el-tab-pane>
+              <el-tab-pane name="5" label="已收货"> </el-tab-pane>
+              <el-tab-pane name="6" label="取消订单"> </el-tab-pane>
+              <el-tab-pane name="7" label="申请售后"> </el-tab-pane>
+              <el-tab-pane name="8" label="正在处理售后"> </el-tab-pane>
+              <el-tab-pane name="9" label="售后结束"> </el-tab-pane>
+              <el-col :span="24">
+                <el-col :span="24" class="one">
+                  <search-1 :form="searchForm" @onSubmit="search" @querySearch="querySearch" @toReset="toClose" :shopList="shopList"> </search-1>
+                </el-col>
+                <data-table :fields="fields" :opera="opera" @query="search" :data="list" :total="total" @detail="toDetails" @sales="toSaless">
+                  <!-- <template #is_afterSale="{ row }">
+                    <span :style="{ color: row.is_afterSale === true ? 'red' : '' }">
+                      {{ row.is_afterSale === true ? '该订单有商品申请售后' : '未申请售后' }}
+                    </span>
+                  </template> -->
+                </data-table>
+              </el-col>
+            </el-tabs>
+          </el-col>
+        </span>
+        <!-- <detail_order v-if="view === 'card1_detail'" :id="order_id" @toBack="toBack"></detail_order>
+        <detail_sales_order v-else-if="view === 'card1_sales'" :id="sales_id" @toBack="toBack"></detail_sales_order>
+        <detail_orderDetail v-else-if="view === 'card_detail'" :id="order_id" @toBack="toBack"></detail_orderDetail>
+        <detail_sales_orderDetail v-else-if="view === 'card_sales'" :id="sales_id" :status="status" @toBack="toBack"></detail_sales_orderDetail> -->
+      </el-col>
     </el-row>
   </div>
 </template>
 
 <script>
-import { mapState, createNamespacedHelpers } from 'vuex';
+const _ = require('lodash');
+import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
+const { mapActions: dictData } = createNamespacedHelpers('dictData');
+const { mapActions: shop } = createNamespacedHelpers('shop');
+const { mapActions } = createNamespacedHelpers('groupOrder');
 export default {
   name: 'index',
   props: {},
-  components: {},
+  components: {
+    // card1: () => import('@/components/orderParts/card-2.vue'),
+    // card2: () => import('@/components/orderParts/card-3.vue'),
+    // detail_order: () => import('@/components/orderParts/detail/detail_order.vue'),
+    // detail_orderDetail: () => import('@/components/orderParts/detail/detail_orderDetail.vue'),
+    // detail_sales_order: () => import('@/components/orderParts/detail/detail_sales_order.vue'),
+    // detail_sales_orderDetail: () => import('@/components/orderParts/detail/detail_sales_orderDetail.vue'),
+    search1: () => import('@/components/orderParts/search-2.vue'),
+  },
   data: function () {
-    return {};
+    const that = this;
+    return {
+      loadings: true,
+      view: 'list',
+      activeName: '2',
+      // 类型列表
+      statusList: [],
+      // 店铺列表
+      shopList: [],
+      order_id: '',
+      sales_id: '',
+      status: '',
+      searchForm: {},
+      list: [],
+      total: 0,
+      opera: [
+        { label: '详情', method: 'detail' },
+        { label: '售后', method: 'sales', type: 'danger', display: (i) => i.status == '1' || i.status == '2' || i.status == '2-' || i.status == '3' },
+      ],
+      fields: [
+        { label: '订单号', model: 'no', showTip: false },
+        { label: '下单时间', model: 'buy_time' },
+        { label: '顾客', model: 'customer.name' },
+        { label: '收货人', model: 'address', showTip: false, format: (i) => this.getAddress(i) },
+        { label: '支付金额', model: 'real_pay' },
+        { label: '商品数量', model: 'buy_num_total' },
+        { label: '是否售后', model: 'is_afterSale', format: (i) => (i === true ? '该订单有商品申请售后' : '未申请售后'), custom: true },
+      ],
+    };
+  },
+  async created() {
+    await this.searchOther();
+    await this.search();
+  },
+  methods: {
+    ...dictData({ dictQuery: 'query' }),
+    ...shop({ shopQuery: 'query' }),
+    ...mapActions(['query', 'fetch', 'create', 'update', 'delete']),
+    // 查询
+    async search({ skip = 0, limit = this.$limit, ...info } = {}) {
+      let condition = _.cloneDeep(this.searchForm);
+      // if (condition.buy_time) {
+      //   condition[`buy_time@start`] = _.head(condition.buy_time);
+      //   condition[`buy_time@end`] = _.last(condition.buy_time);
+      //   delete condition.buy_time;
+      // }
+      let res = await this.query({ skip, limit, ...condition, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, 'total', res.total);
+      }
+      this.loadings = false;
+    },
+
+    // 未付款
+    toDetail(val) {
+      this.$set(this, `order_id`, val);
+      this.$set(this, `view`, 'card1_detail');
+    },
+    toSales(val) {
+      this.$set(this, `sales_id`, val);
+      this.$set(this, `view`, 'card1_sales');
+    },
+    // 待收货,已收货
+    toDetails({ data }) {
+      this.$set(this, `order_id`, data._id);
+      this.$set(this, `view`, 'card_detail');
+    },
+    toSaless({ data }) {
+      this.$set(this, `sales_id`, data._id);
+      this.$set(this, `status`, data.status);
+      this.$set(this, `view`, 'card_sales');
+    },
+    // 待发货
+    toDetail_t(data) {
+      this.$set(this, `order_id`, data);
+      this.$set(this, `view`, 'card_detail');
+    },
+    toSales_t(data) {
+      this.$set(this, `sales_id`, data.id);
+      this.$set(this, `status`, data.status);
+      this.$set(this, `view`, 'card_sales');
+    },
+    handleClick(tab) {
+      this.loadings = true;
+      this.search();
+    },
+    toBack() {
+      this.view = 'list';
+    },
+    getAddress(i) {
+      let name = i.name + ',' + i.phone;
+      // let name = i.name + ',' + i.phone + ',' + i.province;
+      return name;
+    },
+    // 店铺名称
+    getShopName(i) {
+      let shopname = i.map((e) => e.shop_name);
+      return shopname.join(',');
+    },
+    // 重置
+    toClose() {
+      this.searchForm = {};
+      this.search();
+    },
+    // 店铺名称远程查询
+    async querySearch(value) {
+      let res = await this.shopQuery({ name: value });
+      if (this.$checkRes(res)) this.$set(this, 'shopList', res.data);
+    },
+    // 查询其他信息
+    async searchOther() {
+      let res;
+      // 类型
+      res = await this.dictQuery({ code: 'order_process' });
+      if (this.$checkRes(res)) this.$set(this, `statusList`, res.data);
+      // 店铺
+      res = await this.shopQuery();
+      if (this.$checkRes(res)) this.$set(this, `shopList`, res.data);
+    },
   },
-  created() {},
-  methods: {},
   computed: {
     ...mapState(['user']),
   },
@@ -33,4 +201,22 @@ export default {
 };
 </script>
 
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+.main {
+  .one {
+    margin: 0 0 10px 0;
+
+    span:nth-child(1) {
+      font-size: 20px;
+      font-weight: 700;
+      margin-right: 10px;
+    }
+  }
+  .two {
+    margin: 0 0 10px 0;
+  }
+  .thr {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 113 - 8
src/views/platGroup/sales/index.vue

@@ -1,22 +1,120 @@
 <template>
-  <div id="index">
+  <div id="card-1">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col
+        :span="24"
+        class="main animate__animated animate__backInRight"
+        v-loading="loadings"
+        element-loading-text="拼命加载中"
+        element-loading-spinner="el-icon-loading"
+      >
+        <span v-show="view === 'list'">
+          <el-col :span="24" class="one"> <span>售后管理</span> </el-col>
+          <el-col :span="24" class="two">
+            <search-1 :form="searchForm" :statusList="statusList" :typeList="typeList" @onSubmit="search" @toReset="toClose"> </search-1>
+          </el-col>
+          <el-col :span="24" class="four">
+            <data-table :fields="fields" :opera="opera" @query="search" :data="list" :total="total" @exam="toExam"> </data-table>
+          </el-col>
+        </span>
+        <!-- <detail v-if="view === 'order'" :id="id" @toBack="toBack"></detail> -->
+      </el-col>
     </el-row>
   </div>
 </template>
 
 <script>
+const _ = require('lodash');
 import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions } = createNamespacedHelpers('groupAfterSale');
+const { mapActions: dictData } = createNamespacedHelpers('dictData');
 export default {
-  name: 'index',
+  name: 'card-1',
   props: {},
-  components: {},
+  components: {
+    search1: () => import('@/components/salesParts/parts/search-1.vue'),
+    // detail: () => import('@/components/salesParts/detail.vue'),
+  },
   data: function () {
-    return {};
+    const that = this;
+    return {
+      loadings: true,
+      view: 'list',
+      searchForm: {},
+      list: [],
+      total: 0,
+      opera: [{ label: '审核', method: 'exam' }],
+      fields: [
+        { label: '顾客', model: 'customer.name', showTip: false },
+        { label: '订单号', model: 'order_detail.no', showTip: false },
+        { label: '商品名称', model: 'goods.goods.name', showTip: false },
+        {
+          label: '售后类型',
+          model: 'type',
+          format: (i) => {
+            let data = that.typeList.find((f) => f.value == i);
+            if (data) return data.label;
+            else return '暂无';
+          },
+        },
+        {
+          label: '售后状态',
+          model: 'status',
+          format: (i) => {
+            let data = that.statusList.find((f) => f.value == i);
+            if (data) return data.label;
+            else return '暂无';
+          },
+        },
+        { label: '退款金额', model: 'money' },
+        { label: '售后处理人', model: 'deal_person.name' },
+        { label: '申请时间', model: 'apply_time' },
+        { label: '结束时间', model: 'end_time' },
+      ],
+      typeList: [],
+      statusList: [],
+      id: '',
+    };
+  },
+  async created() {
+    await this.search();
+    await this.searchOther();
+  },
+  methods: {
+    ...dictData({ dictQuery: 'query' }),
+    ...mapActions(['query', 'fetch', 'create', 'update', 'delete']),
+    // 查询
+    async search({ skip = 0, limit = this.$limit, ...info } = {}) {
+      let condition = _.cloneDeep(this.searchForm);
+      let res = await this.query({ skip, limit, ...condition, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, 'list', res.data);
+        this.$set(this, 'total', res.total);
+      }
+      this.loadings = false;
+    },
+    toExam({ data }) {
+      this.$set(this, `id`, data.id);
+      this.$set(this, `view`, 'order');
+    },
+    toBack() {
+      this.view = 'list';
+    },
+    toClose() {
+      this.searchForm = {};
+      this.search();
+    },
+    // 查询其他信息
+    async searchOther() {
+      let res;
+      // 类型
+      res = await this.dictQuery({ code: 'afterSale_type' });
+      if (this.$checkRes(res)) this.$set(this, `typeList`, res.data);
+      // 售后状态
+      res = await this.dictQuery({ code: 'afterSale_status' });
+      if (this.$checkRes(res)) this.$set(this, `statusList`, res.data);
+    },
   },
-  created() {},
-  methods: {},
   computed: {
     ...mapState(['user']),
   },
@@ -33,4 +131,11 @@ export default {
 };
 </script>
 
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+.one {
+  margin: 0 0 10px 0;
+}
+.two {
+  margin: 0 0 10px 0;
+}
+</style>

+ 5 - 0
vue.config.js

@@ -30,6 +30,11 @@ module.exports = {
         changeOrigin: true,
         ws: false,
       },
+      '/dev/point/group/v1/api': {
+        target: 'https://broadcast.waityou24.cn', // 127.0.0.1:13003
+        changeOrigin: true,
+        ws: false,
+      },
       '/dev/point/zr/v1/api': {
         target: 'https://broadcast.waityou24.cn', // 127.0.0.1:13003
         changeOrigin: true,