Browse Source

feat:运营账号、公司账号、公司角色

snow 2 years ago
parent
commit
ac249bb7f7
36 changed files with 5075 additions and 1087 deletions
  1. 23 0
      src/apis/service/goodStore/grossProfit/index.js
  2. 17 0
      src/apis/service/goodStore/platform/index.js
  3. 7 17
      src/apis/service/interest/account/index.js
  4. 2 3
      src/apis/service/system/expressSettings/index.js
  5. 13 19
      src/apis/service/system/operationAccount/index.js
  6. 8 1
      src/apis/user/axios.js
  7. 13 1
      src/apis/user/index.js
  8. 6 5
      src/layout/components/Navbar.vue
  9. 199 10
      src/layout/components/company-select/index.vue
  10. 24 0
      src/mixins/reloadData.js
  11. 7 2
      src/store/modules/user.js
  12. 282 0
      src/views/goodStore/grossProfit/addEdit.vue
  13. 382 0
      src/views/goodStore/grossProfit/addEditRate.vue
  14. 534 0
      src/views/goodStore/grossProfit/index.vue
  15. 0 0
      src/views/goodStore/grossProfit/公司分类毛利
  16. 226 0
      src/views/goodStore/platform/addEdit.vue
  17. 465 0
      src/views/goodStore/platform/index.vue
  18. 0 0
      src/views/goodStore/platform/平台管理
  19. 277 0
      src/views/goodStore/platformGrossProfit/addEditRate.vue
  20. 471 0
      src/views/goodStore/platformGrossProfit/index.vue
  21. 0 0
      src/views/goodStore/platformGrossProfit/公司平台分类毛利
  22. 27 363
      src/views/interest/account/addEdit.vue
  23. 34 28
      src/views/interest/account/index.vue
  24. 839 0
      src/views/interest/role-origin/addEdit.vue
  25. 392 0
      src/views/interest/role-origin/index.vue
  26. 0 0
      src/views/interest/role-origin/角色管理
  27. 32 21
      src/views/interest/role/addEdit.vue
  28. 22 6
      src/views/interest/role/index.vue
  29. 0 0
      src/views/interest/role/公司角色管理
  30. 2 2
      src/views/login/index.vue
  31. 0 277
      src/views/system/expressSettings/index.vue
  32. 5 6
      src/views/system/menuOperator/index.vue
  33. 272 77
      src/views/system/operationAccount/addEdit.vue
  34. 301 249
      src/views/system/operationAccount/index.vue
  35. 193 0
      src/views/system/operationAccount/resetPassword.vue
  36. 0 0
      src/views/system/operationAccount/运营账号管理

+ 23 - 0
src/apis/service/goodStore/grossProfit/index.js

@@ -0,0 +1,23 @@
+// 物业管理员
+import http from "@/apis/axios";
+const api = "admin/";
+export default {
+  // 分页查询
+  list: (data, params) => http(api + "scpList", data, "post", params),
+  // 添加
+  add: (data, params) => http(api + "scpAdd", data, "post", params),
+  // 删除
+  delete: (data, params) => http(api + "delete", data, "post", params),
+  // 详情
+  detail: (data, params) => http(api + "catinfo", data, "post", params),
+  // 更新
+  update: (data, params) => http(api + "catedit", data, "post", params),
+  // 修改状态
+  status: (data, params) => http(api + "catstatus", data, "post", params),
+  // 商品分类列表
+  goodsList: (data, params) => http(api + "catlist", data, "post", params),
+  // 全部规格列表
+  specstitle: (data, params) => http(api + "specstitle", data, "post", params),
+  // 修改毛利率
+  editRate: (data, params) => http(api + "catratedit", data, "post", params)
+};

+ 17 - 0
src/apis/service/goodStore/platform/index.js

@@ -0,0 +1,17 @@
+// 物业管理员
+import http from "@/apis/axios";
+const api = "admin/";
+export default {
+  // 添加
+  add: (data, params) => http(api + "platformcreate", data, "post", params),
+  // 详情
+  detail: (data, params) => http(api + "platforminfo", data, "post", params),
+  // 分页查询
+  list: (data, params) => http(api + "platformlist", data, "post", params),
+  // 更新
+  update: (data, params) => http(api + "platformedit", data, "post", params),
+  // 修改状态
+  status: (data, params) => http(api + 'platformstatus', data, 'post', params),
+  // 删除
+  delete: (data, params) => http(api + "platformdelete", data, "post", params),
+};

+ 7 - 17
src/apis/service/interest/account/index.js

@@ -2,28 +2,18 @@
 import http from '@/apis/axios'
 const api = 'admin/'
 export default {
-
-
   // 分页查询
-  list: (data, params) => http(api + 'userlist', data, 'post', params),
+  list: (data, params) => http(api + 'userCompanyBasicList', data, 'post', params),
   // 详情
-  detail: (data, params) => http(api + 'userinfo', data, 'post', params),
+  detail: (data, params) => http(api + 'userCompanyBasicInfo', data, 'post', params),
   // 更新
-  update: (data, params) => http(api + 'usersave', data, 'post', params),
-  // 获取部门表
-  getClist: (data, params) => http(api + 'query', data, 'post', params),
+  update: (data, params) => http(api + 'userCompanyBasicUpdate', data, 'post', params),
   // 添加
-  add: (data, params) => http(api + 'accountadd', data, 'post', params),
+  add: (data, params) => http(api + 'userCompanyAdd', data, 'post', params),
   // 删除
-  delete: (data, params) => http(api + 'delete', data, 'post', params),
+  delete: (data, params) => http(api + 'userCompanyBasicDelete', data, 'post', params),
   // 修改密码
-  setpwd: (data, params) => http(api + 'passset', data, 'post', params),
+  setpwd: (data, params) => http(api + 'userCompanyBasicPassword', data, 'post', params),
   // 修改状态
-  status: (data, params) => http(api + 'userstatus', data, 'post', params),
-  // 拉取角色列表
-  getRole: (data, params) => http(api + 'roleall', data, 'post', params),
-  // 获取业务公司列表
-  getWorkList: (data, params) => http(api + "businesslist", data, "post", params),
-  // 获取平台
-  getTerraceList: (data, params) => http(api + "platformlist", data, "post", params),
+  status: (data, params) => http(api + 'userCompanyBasicStatus', data, 'post', params)
 }

+ 2 - 3
src/apis/service/system/expressSettings/index.js

@@ -3,8 +3,7 @@ import http from '@/apis/axios'
 const api = 'admin/'
 export default {
   // 分页查询
-  list: (data, params) => http(api + 'menulist', data, 'post', params),
+  list: (data, params) => http(api + 'getSupplierExpress', data, 'post', params),
   // 状态
-  actionstatus: (data, params) =>
-    http(api + 'menuactionstatus', data, 'post', params),
+  actionstatus: (data, params) => http(api + 'menuactionstatus', data, 'post', params)
 }

+ 13 - 19
src/apis/service/system/operationAccount/index.js

@@ -1,26 +1,20 @@
-// 系统权限-菜单管理-贾增超
+// 运营账号
 import http from '@/apis/axios'
 const api = 'admin/'
+
 export default {
   // 分页查询
-  list: (data, params) => http(api + 'menulist', data, 'post', params),
+  list: (data, params) => http(api + 'userlist', data, 'post', params),
+  // 详情
+  detail: (data, params) => http(api + 'userinfo', data, 'post', params),
   // 更新
-  update: (data, params) => http(api + 'menusave', data, 'post', params),
-  // 菜单状态
-  menustatus: (data, params) => http(api + 'menustatus', data, 'post', params),
-  // 菜单删除
-  menudel: (data, params) => http(api + 'menudel', data, 'post', params),
-
-  // 按钮
-  // 列表
-  actionList: (data, params) => http(api + 'menuaction', data, 'post', params),
+  update: (data, params) => http(api + 'userCompanyBasicUpdate', data, 'post', params),
   // 添加
-  actionadd: (data, params) => http(api + 'menuactionadd', data, 'post', params),
-  // 更新
-  actionedit: (data, params) => http(api + 'menuactionsave', data, 'post', params),
-  // 状态
-  actionstatus: (data, params) =>
-    http(api + 'menuactionstatus', data, 'post', params),
-      // 删除
-  actiondel: (data, params) => http(api + 'menuactiondel', data, 'post', params),
+  add: (data, params) => http(api + 'userCompanyAdd', data, 'post', params),
+  // 删除
+  delete: (data, params) => http(api + 'userCompanyBasicDelete', data, 'post', params),
+  // 修改密码
+  setpwd: (data, params) => http(api + 'userCompanyBasicPassword', data, 'post', params),
+  // 修改状态
+  status: (data, params) => http(api + 'userCompanyBasicStatus', data, 'post', params)
 }

+ 8 - 1
src/apis/user/axios.js

@@ -1,6 +1,6 @@
 // import axios from 'axios'
 // import Router from '@/router/index'
-// import store from '@/store'
+import store from '@/store'
 
 import {
   getToken
@@ -53,6 +53,13 @@ export default async (
       if (!config.data.token) {
         config.data.token = getToken()
       }
+      
+      //todo:区分是否超管决定传递关联公司
+      // const relaComNo = store.state.user.currentCompany;
+      // const { noCompany } = config.data;
+      // noCompany ? "" : relaComNo
+      config.data.relaComNo = "";
+      // noCompany && delete config.data['noCompany']
       return config
     },
     error => {

+ 13 - 1
src/apis/user/index.js

@@ -37,7 +37,10 @@ export function usergetinfo(data) {
   return http({
     url: `${urlConfig.baseURL}admin/userinfo`,
     method: "post",
-    data,
+    data:{
+      noCompany:true,
+      ...data
+    },
   });
 }
 // 获取角色流程节点详情
@@ -57,3 +60,12 @@ export function requsetCompanyList(data){
     data,
   });
 }
+
+//超管用户获取所有企业列表
+export function requsetCompanyAll(data){
+  return http({
+    url: `${urlConfig.baseURL}admin/supplerlist`,
+    method: "post",
+    data,
+  });
+}

+ 6 - 5
src/layout/components/Navbar.vue

@@ -11,7 +11,7 @@
 
     <div class="right-menu">
       <div class="right-menu-item">
-        <comapny-select />
+        <company-select select-all global placeholder="请选择供应商" />
       </div>
 
       <template v-if="device !== 'mobile'">
@@ -53,7 +53,7 @@
         </el-dropdown-menu>
       </el-dropdown>
     </div>
-    <el-select
+    <!-- <el-select
       class="fr right-menu-item"
       v-model="companyNo"
       :size="'mini'"
@@ -69,7 +69,7 @@
         :value="item.supplierNo"
       >
       </el-option>
-    </el-select>
+    </el-select> -->
 
     <el-dialog
       title="系统公告"
@@ -147,6 +147,8 @@ import { mapGetters } from "vuex";
 
 import asyncRequest from "@/apis/service/system/updates";
 import resToken from "@/mixins/resToken";
+import CompanySelect from "./company-select/index.vue";
+
 import {
   getNotice,
   setNotice,
@@ -179,7 +181,7 @@ export default {
     };
   },
   components: {
-    ComapnySelect,
+    CompanySelect,
   },
   mounted() {
     this.companyNo = get_business_companyNo() || "";
@@ -197,7 +199,6 @@ export default {
       if (code === 0) {
         if (count != 0) {
           this.activeMsg = item;
-          console.log(this.activeMsg);
           if (is) {
             this.typeShow();
           } else {

+ 199 - 10
src/layout/components/company-select/index.vue

@@ -1,24 +1,213 @@
 <template>
-  <el-select style="width:380px" size="small" placeholder="请选择公司" :value="currentCompany" @change="setCurrentCompany">
-    <el-option v-for="(company,index) in companyList" :key="index" :label="company.companyNo + '/' + company.company" :value="company.companyNo" />
+  <el-select
+    style="width:380px"
+    :size="size"
+    :placeholder="placeholder"
+    :value="value ? value : currentCompany"
+    @change="setCurrentCompany"
+    :remote-method="handleRemoteSearch"
+    :disabled="disabled"
+    reserve-keyword
+    filterable
+    remote
+  >
+    <!-- 当selectAll为true 且为超管账号允许选择所有公司 -->
+    <el-option v-if="selectAll" label="所有公司" value />
+
+    <el-option
+      class="custom-company"
+      v-for="(company, index) in companylist"
+      :label="company.code + '/' + company.name"
+      :value="company.code"
+      :key="index"
+    />
+
+    <p class="company-loading" v-if="state.loading">
+      <i class="el-icon-loading" />
+      加载中...
+    </p>
+
+    <p class="company-more" v-if="state.noMore">没有更多数据了...</p>
   </el-select>
 </template>
 
-
 <script>
 import { mapState } from "vuex";
+import { requsetCompanyAll } from "@/apis/user";
 
 export default {
-  computed:{
+  props: {
+    /**
+     *@description 超管账号是否可以选择所有公司
+     */
+    selectAll: {
+      type: Boolean,
+      default: false
+    },
+    /**
+     * @description 选择器尺寸
+     */
+    size: {
+      type: String,
+      default: "small"
+    },
+    /**
+     * @description 选择器placeholder
+     */
+    placeholder: {
+      type: String,
+      default: ""
+    },
+    /**
+     * @description 是否禁用选择器
+     */
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    /***
+     * @description 是否设置全局选中公司
+     */
+    global: {
+      type: Boolean,
+      default: false
+    },
+    value: {
+      type: String,
+      default: ""
+    }
+  },
+  computed: {
     ...mapState({
-      companyList:(state) => state.user.companyList,
-      currentCompany:(state) => state.user.currentCompany
+      currentCompany: state => state.user.currentCompany
     })
   },
-  methods:{
-    setCurrentCompany(currentCompany){
-      this.$store.commit("user/setCurrentCompany",currentCompany)
+  data() {
+    return {
+      companylist: [],
+      scrollWrapper: null,
+      state: {
+        loading: false,
+        noMore: false
+      },
+      params: {
+        name: "",
+        page: 1,
+        size: 10
+      }
+    };
+  },
+  async mounted() {
+    this.initalData();
+    this.scrollWrapper = await this.getScrollWrapper();
+    this.scrollWrapper && this.bindEvent(this.scrollWrapper);
+  },
+  beforeDetoryed() {
+    this.scrollWrapper && this.removeEvent(this.scrollWrapper);
+  },
+  methods: {
+    async initalData() {
+      //todo:区分是否超管用户请求不同接口
+      this.state.loading = true;
+      const { code, data, message } = await requsetCompanyAll(this.params);
+      if (data.list.length < 10) this.state.noMore = true;
+      this.state.loading = false;
+      this.params.page++;
+      //todo:超管默认查所有所有公司(空) 业务账号取列表第一个作为默认公司
+      this.setCurrentCompany("");
+      if (Number(code) === 0) this.companylist = data.list;
+    },
+
+    setCurrentCompany(currentCompany) {
+      this.$emit("update:value", currentCompany);
+      this.$emit("change", currentCompany);
+      //作为通用组件使用不设置全局选中公司
+      if (!this.global) return null;
+      this.$store.commit("user/setCurrentCompany", currentCompany);
+    },
+
+    getScrollWrapper() {
+      return new Promise(resolve => {
+        setTimeout(() => {
+          let optionEl = document.querySelector(".custom-company");
+          if (optionEl && (optionEl = optionEl.parentElement)) {
+            resolve(optionEl.parentElement);
+            return;
+          }
+          resolve(null);
+        }, 500);
+      });
+    },
+
+    async handleScroll() {
+      const scrollWrapper = this.scrollWrapper;
+      const height = scrollWrapper.clientHeight;
+      const scrollTop = scrollWrapper.scrollTop;
+      const scrollHeight = scrollWrapper.scrollHeight;
+
+      const { loading, noMore } = this.state;
+      const isLoad = !loading && !noMore;
+
+      if (height + scrollTop >= scrollHeight && isLoad) {
+        const list = await this.loadMore();
+        this.companylist = [...this.companylist, ...list];
+      }
+    },
+
+    async loadMore() {
+      this.state.loading = true;
+      //todo:区分是否超管用户请求不同接口
+      const { data } = await requsetCompanyAll(this.params);
+      this.state.loading = false;
+
+      if (
+        this.companylist.length >= Number(data.count) ||
+        data.list.length < 10
+      ) {
+        this.state.noMore = true;
+        return [];
+      }
+
+      this.params.page++;
+      return data.list;
+    },
+
+    handleRemoteSearch(name) {
+      this.companylist = [];
+      this.params.name = name;
+      this.params.page = 1;
+      this.state.noMore = false;
+      this.state.loading = false;
+      this.initalData();
+    },
+
+    bindEvent(scrollWrapper) {
+      scrollWrapper.addEventListener("scroll", this.handleScroll);
+    },
+
+    removeEvent(scrollWrapper) {
+      scrollWrapper.removeEventListener("scroll", this.handleScroll);
     }
   }
-}
+};
 </script>
+
+
+<style lang="scss" scoped>
+.company-more {
+  text-align: center;
+  color: #999;
+  font-size: 14px;
+  line-height: 38px;
+}
+
+.company-loading {
+  display: flex;
+  font-size: 14px;
+  justify-content: center;
+  align-items: center;
+  color: #999;
+  gap: 10px;
+  line-height: 38px;
+}
+</style>

+ 24 - 0
src/mixins/reloadData.js

@@ -0,0 +1,24 @@
+import { mapState } from "vuex";
+
+/***
+ * 超管用户切换公司后刷新列表
+*/
+const reloadData = (callback) => ({
+  computed: {
+    ...mapState({
+      currentCompany: (state) => state.user.currentCompany
+    })
+  },
+  watch: {
+    currentCompany: {
+      handler() {
+        const ctx = this;
+        //超管角色刷新列表
+        callback && callback(ctx);
+      },
+      deep: true
+    }
+  }
+})
+
+export default reloadData

+ 7 - 2
src/store/modules/user.js

@@ -48,7 +48,7 @@ const state = {
   business_companyNo: get_business_companyNo() || "",
   private_field: get_private_field() || [],
   roleProcess: get_action_data() || [],
-  currentCompany: null,
+  currentCompany: "",
   companyList: []
 };
 const mutations = {
@@ -103,6 +103,9 @@ const mutations = {
     state.private_field = val;
     set_private_field(val);
   },
+  setCurrentCompany(state,val){
+    state.currentCompany = val;
+  }
 };
 
 const actions = {
@@ -187,6 +190,8 @@ const actions = {
           // } else {
             // 保存默认业务公司编号
             // commit("roleProcess", pdata ?? []);
+
+
             const { mcode, mdata, mmsg } = await getRoleMenuList();
             if (mcode >= 100 && mcode <= 104) {
               resolve("noToken");
@@ -423,4 +428,4 @@ export default {
   state,
   mutations,
   actions,
-};
+};

+ 282 - 0
src/views/goodStore/grossProfit/addEdit.vue

@@ -0,0 +1,282 @@
+<template>
+  <el-dialog
+    v-loading="loading"
+    :title="title"
+    :center="true"
+    align="left"
+    top="12vh"
+    width="650px"
+    :close-on-click-modal="false"
+    :visible.sync="showModelThis"
+    element-loading-text="拼命加载中"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)"
+    @close="showModelThis = false"
+  >
+    <el-card style="margin: -20px 0 0 0">
+      <el-row :gutter="10">
+        <el-col :span="24">
+          <el-form
+            ref="ruleForm"
+            :model="ruleForm"
+            status-icon
+            :rules="rulesThis"
+            label-width="95px"
+            class="demo-ruleForm"
+          >
+            <el-form-item label="分类名称" prop="cat_name">
+              <el-input
+                v-model="ruleForm.cat_name"
+                :disabled="id == '007'"
+                placeholder="分类名称"
+                maxlength="20"
+              >
+                <template slot="prepend" v-if="pid_name">{{
+                  pid_name
+                }}</template></el-input
+              >
+            </el-form-item>
+            <el-form-item label="分类规格" prop="specs_id">
+              <el-select
+                v-model="ruleForm.specs_id"
+                multiple
+                :disabled="id == '007'"
+                style="width: 100%"
+                placeholder="分类规格"
+              >
+                <el-option
+                  v-for="item in specOptions"
+                  :key="item.id"
+                  :label="item.spec_name"
+                  :value="item.id"
+                >
+                </el-option>
+              </el-select>
+            </el-form-item>
+            <!-- 
+            <el-form-item label="财务核算码" prop="fund_code">
+              <el-input
+                v-model="ruleForm.fund_code"
+                :disabled="id == '007'"
+                placeholder="财务核算码"
+                maxlength="50"
+              />
+             </el-form-item> 
+            -->
+            <el-form-item label="售后说明" prop="cat_desc">
+              <el-input
+                v-model="ruleForm.cat_desc"
+                :disabled="id == '007'"
+                placeholder="售后说明"
+                type="textarea"
+                :rows="5"
+                maxlength="2000"
+                show-word-limit
+              />
+            </el-form-item>
+          </el-form>
+        </el-col>
+        <el-col :span="24" style="text-align: right">
+          <el-button v-if="id !== '007'" type="primary" @click="submitForm"
+            >保 存
+          </el-button>
+          <el-button @click="showModelThis = false">{{
+            id == "007" ? "关 闭" : "取 消"
+          }}</el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+  </el-dialog>
+</template>
+<script>
+import asyncRequest from "@/apis/service/goodStore/sort";
+import resToken from "@/mixins/resToken";
+import { isChinese } from "@/utils/validate";
+export default {
+  name: "sort",
+  props: ["showModel", "id", "sitem", "titleList"],
+  mixins: [resToken],
+  data() {
+    const validate_fund_code = (rule, value, callback) => {
+      if (value === "") {
+        callback();
+      } else if (isChinese(value)) {
+        callback(new Error("财务核算码不能包含汉字!"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      loading: false,
+      title: "添加分类",
+      pid_name: "",
+      showModelThis: this.showModel,
+      specOptions: [],
+      ruleForm: {
+        id: "",
+        cat_name: "",
+        specs_id: [],
+        cat_desc: "",
+      },
+      rulesThis: this.rules,
+      rules: {
+        cat_name: [
+          { required: true, message: "分类名称不能为空", trigger: "blur" },
+        ],
+        specs_id: [
+          {
+            type: "array",
+            required: true,
+            message: "请至少选择一个分类规格",
+            trigger: "change",
+          },
+        ],
+        fund_code: [
+          { required: false, validator: validate_fund_code, trigger: "blur" },
+        ],
+
+        cat_desc: [{ required: false, message: "", trigger: "blur" }],
+      },
+    };
+  },
+  watch: {
+    showModel: function (val) {
+      this.showModelThis = val;
+      if (val) {
+        this.initForm();
+      }
+    },
+    showModelThis(val) {
+      if (!val) {
+        this.$emit("cancel");
+      }
+    },
+  },
+  methods: {
+    async initForm() {
+      this.loading = true;
+      this.pid_name = "";
+      this.titleList.forEach((e, i) => {
+        this.pid_name += i !== 0 ? `${e.titleName}/` : "";
+      });
+      await this.resetForm();
+      if (this.id === "003") {
+        this.title = "添加分类";
+        this.rulesThis = this.rules;
+      } else if (this.id === "005") {
+        this.title = "修改分类";
+        this.rulesThis = this.rules;
+        await this.initData();
+      } else {
+        this.title = "分类详情";
+        this.rulesThis = {};
+        await this.initData();
+      }
+
+      await this.getAllSpecs();
+
+      this.loading = false;
+    },
+
+    async resetForm() {
+      // 重置
+      await this.$nextTick(() => {
+        if (this.$refs.ruleForm) {
+          this.$refs.ruleForm.resetFields();
+          this.$refs.ruleForm.clearValidate();
+          const { id, cat_name, cat_desc } = this.sitem;
+          this.ruleForm = {
+            pid: this.titleList[this.titleList.length - 1].id || "",
+            id: id || "",
+            cat_name: cat_name || "",
+            specs_id: [],
+            cat_desc: cat_desc || "",
+          };
+        }
+      });
+    },
+
+    async getAllSpecs() {
+      this.specOptions = [];
+      let res = await asyncRequest.specstitle({});
+      if (res && res.code === 0) {
+        this.specOptions = res.data;
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        this.specOptions = [];
+        await this.logout();
+      } else {
+        this.specOptions = [];
+        this.$message.warning(res.message);
+      }
+    },
+
+    async initData() {
+      const res = await asyncRequest.detail({ id: this.sitem.id });
+      if (res && res.code === 0 && res.data) {
+        const { pid, id, cat_name, cat_desc, spec, fund_code } = res.data;
+        let specs_id = [];
+        if (spec && spec.length > 0) {
+          spec.forEach((e) => {
+            specs_id.push(e.id);
+          });
+        }
+        this.ruleForm = {
+          pid: pid || "",
+          id: id || "",
+          cat_name: cat_name || "",
+          specs_id: specs_id || [],
+          fund_code: fund_code || "",
+          cat_desc: cat_desc || "",
+        };
+        this.$refs.ruleForm.resetFields();
+        this.$refs.ruleForm.clearValidate();
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        await this.logout();
+      } else {
+        this.$message.warning(res.message);
+      }
+    },
+    
+    async submitForm() {
+      await this.$refs.ruleForm.validate(async (valid) => {
+        if (valid) {
+          if (!this.loading) {
+            this.loading = true;
+            let model = JSON.parse(JSON.stringify(this.ruleForm));
+            let res = {};
+            if (this.id === "003") {
+              delete model["id"];
+              res = await asyncRequest.add(model);
+            } else {
+              res = await asyncRequest.update(model);
+            }
+            this.loading = false;
+            if (res && res.code === 0) {
+              const title = this.id === "add" ? "添加成功!" : "修改成功!";
+              this.$notify.success({
+                title,
+                message: "",
+              });
+              this.showModelThis = false;
+              // 刷新
+              this.$emit("refresh");
+            } else if (res && res.code >= 100 && res.code <= 104) {
+              await this.logout();
+            } else {
+              this.$message.warning(res.message);
+            }
+          }
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.sort {
+}
+</style>

+ 382 - 0
src/views/goodStore/grossProfit/addEditRate.vue

@@ -0,0 +1,382 @@
+<template>
+  <el-dialog
+    v-loading="loading"
+    :title="'设置毛利率'"
+    :center="true"
+    align="left"
+    top="12vh"
+    width="600px"
+    :close-on-click-modal="false"
+    :visible.sync="showModelThis"
+    element-loading-text="拼命加载中"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)"
+    @close="showModelThis = false"
+  >
+    <el-card style="margin: -20px 0 0 0">
+      <el-row :gutter="0">
+        <el-col :span="24">
+          <el-form
+            ref="ruleForm"
+            :model="ruleForm"
+            status-icon
+            :size="'small'"
+            :rules="rulesThis"
+            label-width="110px"
+            class="demo-ruleForm"
+          >
+            <el-form-item label="分类名称" prop="cat_name">
+              <el-input
+                v-model="ruleForm.cat_name"
+                disabled
+                placeholder="分类名称"
+                maxlength="20"
+                ><template slot="prepend" v-if="pid_name">{{
+                  pid_name
+                }}</template></el-input
+              >
+            </el-form-item>
+            <el-form-item label="财务核算码" prop="fund_code">
+              <el-input
+                v-model="ruleForm.fund_code"
+                disabled
+                placeholder="财务核算码"
+                maxlength="50"
+              />
+            </el-form-item>
+            <el-form-item label="预算→成本" prop="order_rate">
+              <digital-input
+                :values="ruleForm.order_rate"
+                :placeholder="'预算→成本'"
+                :min="0"
+                :max="100000000000"
+                :position="'right'"
+                :precision="2"
+                :size="'mini'"
+                :controls="false"
+                :append="'%'"
+                @reschange="rate_change($event, 'order_rate')"
+              />
+            </el-form-item>
+            <el-form-item label="成本→售价" prop="sale_rate">
+              <digital-input
+                :values="ruleForm.sale_rate"
+                :placeholder="'成本→售价'"
+                :min="-100"
+                :max="100000000000"
+                :position="'right'"
+                :precision="2"
+                :size="'mini'"
+                :controls="false"
+                :append="'%'"
+                @reschange="rate_change($event, 'sale_rate')"
+              />
+            </el-form-item>
+
+            <el-form-item label="主管利率" prop="rate">
+              <digital-input
+                :values="ruleForm.rate"
+                :placeholder="'主管利率'"
+                :min="-100"
+                :max="100000000000"
+                :position="'right'"
+                :precision="2"
+                :size="'mini'"
+                :controls="false"
+                :append="'%'"
+                @reschange="rate_change($event, 'rate')"
+              />
+            </el-form-item>
+            <el-form-item label="财务利率" prop="money_rate">
+              <digital-input
+                :values="ruleForm.money_rate"
+                :placeholder="'财务利率'"
+                :min="-100"
+                :max="100000000000"
+                :position="'right'"
+                :precision="2"
+                :size="'mini'"
+                :controls="false"
+                :append="'%'"
+                @reschange="rate_change($event, 'money_rate')"
+              />
+            </el-form-item>
+            <el-form-item label="项目最低毛利" prop="low_rate">
+              <digital-input
+                :values="ruleForm.low_rate"
+                :placeholder="'项目最低毛利'"
+                :min="-100"
+                :max="100000000000"
+                :position="'right'"
+                :precision="2"
+                :size="'mini'"
+                :controls="false"
+                :append="'%'"
+                @reschange="rate_change($event, 'low_rate')"
+              />
+            </el-form-item>
+            <!-- <el-form-item label="BOSS毛利率" prop="lower_rate">
+              <digital-input
+                :values="ruleForm.lower_rate"
+                :placeholder="'BOSS毛利率'"
+                :min="-100"
+                :max="100000000000"
+                :position="'right'"
+                :precision="2"
+                :size="'mini'"
+                :controls="false"
+                :append="'%'"
+                @reschange="rate_change($event, 'lower_rate')"
+              />
+            </el-form-item>-->
+          </el-form>
+        </el-col>
+        <el-col :span="24" style="text-align: right">
+          <el-button
+            v-if="id !== '007'"
+            type="primary"
+            :size="'small'"
+            @click="submitForm"
+            >保 存
+          </el-button>
+          <el-button :size="'small'" @click="showModelThis = false">{{
+            id == "007" ? "关 闭" : "取 消"
+          }}</el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+  </el-dialog>
+</template>
+
+<script>
+import asyncRequest from "@/apis/service/goodStore/sort";
+import resToken from "@/mixins/resToken";
+export default {
+  name: "sort",
+  props: ["showModel", "id", "sitem", "titleList"],
+  mixins: [resToken],
+  data() {
+    const validate_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("主管利率毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_order_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("预算→成本毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_sale_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("成本→售价毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+
+    const validate_lower_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("BOSS毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_low_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("项目最低毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_money_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("财务毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      loading: false,
+      showModelThis: this.showModel,
+      pid_name: "",
+      ruleForm: {
+        id: "",
+        cat_name: "",
+        order_rate: "0",
+        sale_rate: "0",
+        lower_rate: "0",
+        rate: "0",
+        low_rate: "0",
+        money_rate: "0",
+      },
+      rulesThis: this.rules,
+      rules: {
+        order_rate: [
+          { required: true, validator: validate_order_rate, trigger: "blur" },
+        ],
+        sale_rate: [
+          { required: true, validator: validate_sale_rate, trigger: "blur" },
+        ],
+        lower_rate: [
+          { required: false, validator: validate_lower_rate, trigger: "blur" },
+        ],
+        rate: [{ required: true, validator: validate_rate, trigger: "blur" }],
+        low_rate: [
+          { required: true, validator: validate_low_rate, trigger: "blur" },
+        ],
+        money_rate: [
+          { required: true, validator: validate_money_rate, trigger: "blur" },
+        ],
+      },
+    };
+  },
+  watch: {
+    showModel: function (val) {
+      this.showModelThis = val;
+      if (val) {
+        this.initForm();
+      }
+    },
+    showModelThis(val) {
+      if (!val) {
+        this.$emit("cancel");
+      }
+    },
+  },
+  methods: {
+    async initForm() {
+      this.loading = true;
+      this.pid_name = "";
+      this.titleList.forEach((e, i) => {
+        this.pid_name += i !== 0 ? `${e.titleName}/` : "";
+      });
+      this.rulesThis = this.rules;
+      await this.resetForm();
+      await this.initData();
+      this.loading = false;
+    },
+
+    async resetForm() {
+      // 重置
+      await this.$nextTick(() => {
+        if (this.$refs.ruleForm) {
+          this.$refs.ruleForm.resetFields();
+          this.$refs.ruleForm.clearValidate();
+          
+          const {
+            pid,
+            id,
+            cat_name,
+            order_rate,
+            sale_rate,
+            lower_rate,
+            rate,
+            fund_code,
+            low_rate,
+            money_rate,
+          } = this.sitem;
+          
+          this.ruleForm = {
+            pid: pid || "",
+            id: id || "",
+            cat_name: cat_name || "",
+            fund_code: fund_code || "",
+            order_rate: order_rate || "0",
+            sale_rate: sale_rate || "0",
+            lower_rate: lower_rate || "0",
+            rate: rate || "0",
+            low_rate: low_rate || "0",
+            money_rate: money_rate || "0",
+          };
+        }
+      });
+    },
+    rate_change(e, key) {
+      this.ruleForm[key] = e + "";
+      this.$refs.ruleForm.validateField(key);
+    },
+
+    async initData() {
+      const { code, data, message } = await asyncRequest.detail({
+        id: this.sitem.id,
+      });
+      if (code === 0) {
+        const {
+          pid,
+          id,
+          cat_name,
+          order_rate,
+          sale_rate,
+          lower_rate,
+          rate,
+          fund_code,
+          low_rate,
+          money_rate,
+        } = data;
+        this.ruleForm = {
+          pid: pid || "",
+          id: id || "",
+          cat_name: cat_name || "",
+          fund_code: fund_code || "",
+          order_rate: order_rate || "0",
+          sale_rate: sale_rate || "0",
+          lower_rate: lower_rate || "0",
+          rate: rate || "0",
+          low_rate: low_rate || "0",
+          money_rate: money_rate || "0",
+        };
+      } else if (code >= 100 && code <= 104) {
+        await this.logout();
+      } else {
+        this.$message.warning(message);
+      }
+    },
+    async submitForm() {
+      await this.$refs.ruleForm.validate(async (valid) => {
+        if (valid) {
+          if (!this.loading) {
+            this.loading = true;
+            let model = JSON.parse(JSON.stringify(this.ruleForm));
+            delete model["cat_name"];
+            delete model["pid"];
+            delete model["fund_code"];
+            let res = await asyncRequest.editRate(model);
+            this.loading = false;
+            if (res && res.code === 0) {
+              this.$notify.success({
+                title: "毛利率设置成功!",
+                message: "",
+              });
+              this.showModelThis = false;
+              // 刷新
+              this.$emit("refresh");
+            } else if (res && res.code >= 100 && res.code <= 104) {
+              await this.logout();
+            } else {
+              this.$message.warning(res.message);
+            }
+          }
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+  },
+};
+</script>
+
+   <style lang="scss" scoped>
+.sort {
+}
+</style>

+ 534 - 0
src/views/goodStore/grossProfit/index.vue

@@ -0,0 +1,534 @@
+<template>
+  <div class="sort pagePadding">
+    <ex-table
+      v-loading="loading"
+      v-if=" powers.some((i) => i == '001')"
+      :table="table"
+      :data="tableData"
+      :columns="columns"
+      :page="pageInfo"
+      :size="size"
+      @page-curr-change="handlePageChange"
+      @page-size-change="handleSizeChange"
+      @screen-reset="
+        pageInfo.curr = 1;
+        parmValue.page = 1;
+        searchList();
+      "
+      @screen-submit="
+        pageInfo.curr = 1;
+        parmValue.page = 1;
+        searchList();
+      "
+    >
+      <template #table-header="{}">
+        <div style="width: 100%">
+          <el-row style="padding: 0 0 10px 80px">
+            <el-col :span="3" style="width: 748px">
+              <div class="my-breadcrumb clear">
+                <div
+                  class="my-breadcrumb-item"
+                  v-for="(item, index) in titleList"
+                  :key="item + index"
+                  @click="changeBreadcrumb(index)"
+                >
+                  <span class="label">{{ item.titleName }}</span>
+                  <span class="separator" v-if="index + 1 !== titleList.length">/</span>
+                </div>
+              </div>
+            </el-col>
+
+            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
+              <el-button type="primary" :size="searchSize" @click="searchList">刷新</el-button>
+            </el-col>
+            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
+              <el-button type="warning" :size="searchSize" @click="restSearch">重置</el-button>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="4" style="width: 160px">
+              <el-select
+                v-model="parmValue.status"
+                filterable
+                clearable
+                :size="searchSize"
+                placeholder="分类状态"
+                style="width: 100%"
+                @change="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+              >
+                <el-option
+                  v-for="item in statusList"
+                  :key="'status' + item.code"
+                  :label="item.name"
+                  :value="item.code"
+                />
+              </el-select>
+            </el-col>
+            <el-col :span="4" style="width: 380px; padding: 0 0 0 10px">
+              <el-input
+                :size="searchSize"
+                v-model="parmValue.cat_name"
+                :maxlength="40"
+                @blur="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+                placeholder="分类名称"
+              ></el-input>
+            </el-col>
+            <el-col :span="4" style="width: 170px; padding: 0 0 0 10px">
+              <el-input
+                :size="searchSize"
+                v-model="parmValue.company_name"
+                :maxlength="40"
+                @blur="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+                placeholder="创建人部门"
+              ></el-input>
+            </el-col>
+            <el-col
+              :span="3"
+              class="fr"
+              style="width: 66px; padding: 0 0 0 10px"
+              v-if="powers.some((i) => i == '003')"
+            >
+              <el-button
+                :size="searchSize"
+                type="success"
+                style="float: right"
+                @click="openModal({}, '003')"
+              >添加</el-button>
+            </el-col>
+          </el-row>
+        </div>
+      </template>
+      <template #status="{ scope }">
+        <el-tag
+          :size="tablebtnSize"
+          :type="scope.row.status == '0' ? 'warning' : ''"
+          v-text="
+            (statusOptions.find((item) => item.id == scope.row.status) || {})
+              .label || '--'
+          "
+        ></el-tag>
+      </template>
+
+      <template #operation="{ scope }">
+        <el-tooltip
+          v-if="powers.some((i) => i == '007')"
+          effect="dark"
+          content="详情"
+          placement="top"
+        >
+          <i class="el-icon-view tb-icon" @click="openModal(scope.row, '007')"></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '005')"
+          effect="dark"
+          content="修改"
+          placement="top"
+        >
+          <i class="el-icon-edit tb-icon" @click="openModal(scope.row, '005')"></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="
+            powers.some((i) => i == '004') && scope.row.status === '1'
+          "
+          effect="dark"
+          content="禁用"
+          placement="top"
+        >
+          <i
+            class="el-icon-video-pause tb-icon"
+            @click="changeStatus(scope.row.id, scope.row.status)"
+          ></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="
+            powers.some((i) => i == '004') && scope.row.status === '0'
+          "
+          effect="dark"
+          content="启用"
+          placement="top"
+        >
+          <i
+            class="el-icon-video-play tb-icon"
+            @click="changeStatus(scope.row.id, scope.row.status)"
+          ></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '006')"
+          effect="dark"
+          content="删除"
+          placement="top"
+        >
+          <i class="el-icon-delete tb-icon" @click="deleteItem(scope.row.id)"></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '060')"
+          effect="dark"
+          content="设置毛利率"
+          placement="top"
+        >
+          <i class="el-icon-s-check tb-icon" @click="setRate(scope.row)"></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="parseInt(scope.row.level) < 3"
+          effect="dark"
+          content="下级分类"
+          placement="top"
+        >
+          <i class="el-icon-arrow-right tb-icon" @click="openChildren(scope.row)"></i>
+        </el-tooltip>
+      </template>
+    </ex-table>
+    <no-auth v-else></no-auth>
+    <!-- 弹窗 新增/修改 -->
+    <add-edit
+      :id="modelId"
+      :show-model="showModel"
+      :sitem="sitem"
+      :titleList="titleList"
+      @refresh="searchList"
+      @cancel="showModel = false"
+    />
+    <!-- 弹窗 新增/修改 -->
+    <add-edit-rate
+      :id="modelRateId"
+      :show-model="showRateModel"
+      :sitem="sitemRate"
+      :titleList="titleList"
+      @refresh="searchList"
+      @cancel="showRateModel = false"
+    />
+  </div>
+</template>
+<script>
+import addEdit from "./addEdit";
+import addEditRate from "./addEditRate";
+import asyncRequest from "@/apis/service/goodStore/grossProfit";
+import mixinPage from "@/mixins/elPaginationHandle";
+import { statusList } from "@/assets/js/statusList";
+import roleLevel from "@/assets/js/roleLevel";
+import reloadData from "@/mixins/reloadData";
+import resToken from "@/mixins/resToken";
+import { mapGetters } from "vuex";
+
+export default {
+  name: "grossProfit",
+  mixins: [mixinPage, resToken, reloadData(ctx => ctx.searchList())],
+  components: {
+    addEdit,
+    addEditRate
+  },
+  computed: {
+    //组件SIZE设置
+    ...mapGetters(["tablebtnSize", "searchSize", "size"]),
+    powers() {
+      const { btnList } = this.$store.getters;
+      const tran = btnList.find(i => i.menu_route == "grossProfit") || {};
+      const { action } = tran ?? {};
+      return action ?? [];
+    }
+  },
+  data() {
+    return {
+      statusList: statusList,
+      roleLevel: roleLevel,
+      loading: true,
+      showModel: false,
+      modelId: "000",
+      sitem: {},
+      showRateModel: false,
+      modelRateId: "000",
+      sitemRate: {},
+      titleList: [],
+      parmValue: {
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+        cat_name: "",
+        pid: "0"
+      },
+      // 状态
+      statusOptions: [
+        { id: "0", label: "禁用" },
+        { id: "1", label: "启用" }
+      ],
+      // 表格 - 数据
+      tableData: [],
+      // 表格 - 参数
+      table: {
+        stripe: true,
+        border: true,
+        _defaultHeader_: ["setcol"]
+      },
+      // 表格 - 分页
+      pageInfo: {
+        size: 15,
+        curr: 1,
+        total: 0
+      },
+      // 表格 - 列参数
+      columns: [
+        {
+          prop: "cat_name",
+          label: "分类名称",
+          width: "130px"
+        },
+        {
+          prop: "supplierNo",
+          label: "公司编码"
+        },
+        {
+          prop: "supplierName",
+          label: "公司名称"
+        },
+        {
+          prop: "status",
+          label: "状态",
+          _slot_: "status",
+          width: "70px"
+        },
+        {
+          prop: "status",
+          label: "状态",
+          width: "70px"
+        },
+        {
+          prop: "addtime",
+          label: "创建时间",
+          width: "145px"
+        },
+        {
+          prop: "",
+          label: "操作",
+          fixed: "right",
+          width: "200px",
+          _noset_: true,
+          _slot_: "operation"
+        }
+      ]
+    };
+  },
+  mounted() {
+    this.initTitleList();
+    this.parmValue.pid = "0";
+    this.searchList();
+  },
+  methods: {
+    restSearch() {
+      // 表格 - 分页
+      this.pageInfo = {
+        size: 15,
+        curr: 1,
+        total: 0
+      };
+      this.parmValue = {
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+        status: "",
+        company_name: "", //创建人部门
+        pid: "0",
+        cat_name: ""
+      };
+      this.initTitleList();
+      this.searchList();
+    },
+    initTitleList() {
+      this.titleList = [];
+      let model = { id: "0", titleName: "全部一级分类" };
+      this.titleList.push(model);
+    },
+    //查看下一级分类
+    async openChildren(item) {
+      this.parmValue.pid = item.id;
+      this.pageInfo.curr = 1;
+      this.parmValue.page = 1;
+      await this.searchList();
+      let model = {
+        id: item.id,
+        titleName: item.cat_name
+      };
+      this.titleList.push(model);
+    },
+    //设置毛利率
+    setRate(row) {
+      this.modelRateId = row.id;
+      this.sitemRate = row;
+      this.showRateModel = true;
+    },
+    // 新建/编辑/详情
+    openModal(row, type) {
+      const { status } = row;
+      if (type === "005" && status === "1") {
+        this.$message.warning("禁用后,才可以修改!");
+        return;
+      }
+      this.sitem = row;
+      this.modelId = type;
+      this.showModel = true;
+    },
+    async changeBreadcrumb(index) {
+      if (index + 1 === this.titleList.length) {
+        return;
+      } else {
+        this.parmValue.pid = this.titleList[index].id;
+        this.titleList = this.titleList.slice(0, index + 1);
+      }
+
+      this.pageInfo.curr = 1;
+      this.parmValue.page = 1;
+      await this.searchList();
+    },
+    /**
+     * 启用/禁用
+     * @param {String} id id
+     * @param {String} status 0-禁用 1-启用
+     */
+    async changeStatus(id, status) {
+      await this.$confirm(`确定要改为${status === "1" ? "禁用" : "启用"}?`, {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(async () => {
+          this.loading = true;
+
+          const model = {
+            id: id,
+            status: status === "1" ? "0" : "1"
+          };
+
+          const res = await asyncRequest.status(model);
+          if (res && res.code === 0) {
+            this.loading = false;
+
+            this.$notify.success({
+              title: "状态修改成功!",
+              message: ""
+            });
+
+            await this.searchList();
+          } else if (res && res.code >= 100 && res.code <= 104) {
+            await this.logout();
+          } else {
+            this.loading = false;
+            this.$message.warning(res.message);
+          }
+        })
+        .catch(() => {
+          console.log("取消");
+        });
+    },
+    async deleteItem(id) {
+      await this.$confirm("确定要删除?", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(async () => {
+          const model = {
+            id: id
+          };
+          const res = await asyncRequest.delete(model);
+          if (res && res.code === 0) {
+            this.$notify.success({
+              title: "删除成功",
+              message: ""
+            });
+            this.searchList();
+          } else if (res && res.code >= 100 && res.code <= 104) {
+            await this.logout();
+          } else {
+            this.$message.warning(res.message);
+          }
+        })
+        .catch(() => {
+          console.log("取消");
+        });
+    },
+    // 刷新表格
+    async searchList() {
+      if (!this.currentCompany) {
+        this.$message.warning("请在右上角选择一家公司");
+        this.loading = false;
+        this.tableData = [];
+        return;
+      }
+
+      this.parmValue.supplierNo = this.currentCompany;
+
+      this.loading = true;
+      const res = await asyncRequest.list(this.parmValue);
+      if (res && res.code === 0 && res.data) {
+        this.tableData = res.data.list;
+        this.tableData.forEach(e => {
+          if (e.im && e.im.length > 0) {
+            e.specs = "";
+            e.im.forEach((a, i) => {
+              e.specs += i === 0 ? a.spec_name : `,${a.spec_name}`;
+            });
+          } else {
+            e.specs = "";
+          }
+        });
+        this.pageInfo.total = Number(res.data.count);
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        await this.logout();
+      } else {
+        this.tableData = [];
+        this.pageInfo.total = 0;
+      }
+      this.loading = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.sort {
+  .my-breadcrumb {
+    .my-breadcrumb-item {
+      float: left;
+      span {
+        height: 32px;
+        line-height: 32px;
+      }
+      .label {
+        padding: 0 5px 0 0;
+        color: 010101;
+      }
+      .separator {
+        color: #787878;
+        font-size: 13px;
+        padding: 0 5px 0 0;
+      }
+      &:last-child {
+        .label {
+          color: #787878;
+        }
+      }
+      &:hover {
+        cursor: pointer;
+      }
+      &:last-child {
+        cursor: default;
+      }
+      &:only-child {
+        cursor: pointer;
+      }
+      // &.chover {
+      //   cursor: pointer;
+      // }
+    }
+  }
+}
+</style>

+ 0 - 0
src/views/interest/role/角色管理 → src/views/goodStore/grossProfit/公司分类毛利


+ 226 - 0
src/views/goodStore/platform/addEdit.vue

@@ -0,0 +1,226 @@
+<template>
+  <el-dialog
+    v-loading="loading"
+    :title="title"
+    :center="true"
+    align="left"
+    top="18vh"
+    width="500px"
+    :close-on-click-modal="false"
+    :visible.sync="showModelThis"
+    element-loading-text="拼命加载中"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)"
+    @close="showModelThis = false"
+  >
+    <el-card style="margin: -20px 0 0 0">
+      <el-row :gutter="10">
+        <el-col :span="24">
+          <el-form
+            ref="ruleForm"
+            :model="ruleForm"
+            status-icon
+            :rules="rulesThis"
+            label-width="80px"
+            class="demo-ruleForm"
+          >
+            <el-form-item label="关联公司" prop="companyNo">
+              <company-select
+                :value.sync="ruleForm.companyNo"
+                style="width:100%"
+                size="default"
+                placeholder="请选择关联公司"
+              />
+            </el-form-item>
+
+            <el-form-item label="平台名称" prop="platform_name">
+              <el-input
+                v-model="ruleForm.platform_name"
+                :disabled="id == '007'"
+                placeholder="平台名称"
+                maxlength="20"
+              />
+            </el-form-item>
+            <el-form-item label="平台类型" prop="use_type">
+              <el-select
+                v-model="ruleForm.use_type"
+                style="width: 100%"
+                :disabled="id == '007'"
+                placeholder="请选择平台类型"
+              >
+                <el-option
+                  v-for="item in use_type_options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="对接平台" prop="platform_type">
+              <el-select
+                v-model="ruleForm.platform_type"
+                style="width: 100%"
+                :disabled="id == '007'"
+                placeholder="请选择对接平台"
+              >
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-form>
+        </el-col>
+        <el-col :span="24" style="text-align: right">
+          <el-button v-if="id !== '007'" type="primary" @click="submitForm">保 存</el-button>
+          <el-button @click="showModelThis = false">
+            {{
+            id == "007" ? "关 闭" : "取 消"
+            }}
+          </el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+  </el-dialog>
+</template>
+<script>
+import asyncRequest from "@/apis/service/serviceParam/terrace";
+import CompanySelect from "@/layout/components/company-select";
+import resToken from "@/mixins/resToken";
+
+export default {
+  name: "terrace",
+  props: ["showModel", "id", "sitem"],
+  mixins: [resToken],
+  data() {
+    return {
+      loading: false,
+      title: "添加平台",
+      showModelThis: this.showModel,
+      options: [
+        { value: "0", label: "无对接" },
+        { value: "1", label: "有赞平台" }
+      ],
+      use_type_options: [
+        { value: "1", label: "ToB" },
+        { value: "2", label: "ToC" }
+      ],
+      ruleForm: {
+        id: "",
+        companyNo: "",
+        platform_name: "",
+        platform_type: "0",
+        use_type: "1"
+      },
+      rulesThis: this.rules,
+      rules: {
+        platform_name: [
+          { required: true, message: "平台名称不能为空", trigger: "blur" }
+        ],
+        companyNo: [
+          { required: true, message: "请选择关联公司", trigger: "blur" }
+        ],
+        platform_type: [
+          { required: true, message: "请选择对接平台", trigger: "change" }
+        ],
+        use_type: [
+          { required: true, message: "请选择平台类型", trigger: "change" }
+        ]
+      }
+    };
+  },
+  components: {
+    CompanySelect
+  },
+  watch: {
+    showModel: function(val) {
+      this.showModelThis = val;
+      if (val) {
+        this.initForm();
+      }
+    },
+    showModelThis(val) {
+      if (!val) {
+        this.$emit("cancel");
+      }
+    }
+  },
+  methods: {
+    async initForm() {
+      this.loading = true;
+      if (this.id === "003") {
+        this.title = "添加平台";
+        this.rulesThis = this.rules;
+      } else if (this.id === "005") {
+        this.title = "修改平台";
+        this.rulesThis = this.rules;
+      } else {
+        this.title = "平台详情";
+        this.rulesThis = {};
+      }
+      await this.resetForm();
+      this.loading = false;
+    },
+    async resetForm() {
+      // 重置
+      await this.$nextTick(() => {
+        if (this.$refs.ruleForm) {
+          this.$refs.ruleForm.resetFields();
+          this.$refs.ruleForm.clearValidate();
+          const { id, platform_name, platform_type, use_type } = this.sitem;
+          this.ruleForm = {
+            id: id || "",
+            platform_name: platform_name || "",
+            platform_type:platform_type ? String(platform_type) : "0",
+            use_type: use_type ? String(use_type) : "1"
+          };
+        }
+      });
+    },
+    async submitForm() {
+      await this.$refs.ruleForm.validate(async valid => {
+        if (valid) {
+          if (this.loading) {
+            return;
+          }
+          this.loading = true;
+          let model = JSON.parse(JSON.stringify(this.ruleForm));
+          let res = {};
+          if (this.id === "003") {
+            delete model["id"];
+            res = await asyncRequest.add(model);
+          } else {
+            res = await asyncRequest.update(model);
+          }
+
+          this.loading = false;
+          if (res && res.code === 0) {
+            const title = this.id === "003" ? "添加成功!" : "修改成功!";
+            this.$notify.success({
+              title,
+              message: ""
+            });
+
+            this.showModelThis = false;
+            // 刷新
+            this.$emit("refresh");
+          } else if (res && res.code >= 100 && res.code <= 104) {
+            await this.logout();
+          } else {
+            this.$message.warning(res.message);
+          }
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.terrace {}
+</style>

+ 465 - 0
src/views/goodStore/platform/index.vue

@@ -0,0 +1,465 @@
+<template>
+  <div class="terrace pagePadding">
+    <ex-table
+      v-loading="loading"
+      v-if=" powers.some((i) => i == '001')"
+      :table="table"
+      :data="tableData"
+      :columns="columns"
+      :page="pageInfo"
+      :size="size"
+      @page-curr-change="handlePageChange"
+      @page-size-change="handleSizeChange"
+      @screen-reset="
+        pageInfo.curr = 1;
+        parmValue.page = 1;
+        searchList();
+      "
+      @screen-submit="
+        pageInfo.curr = 1;
+        parmValue.page = 1;
+        searchList();
+      "
+    >
+      <template #table-header="{}">
+        <div style="width: 100%">
+          <el-row style="padding: 0 0 10px 80px">
+            <el-col :span="6" style="width: 303px">
+              <period-date-picker
+                :type="1"
+                :width="'135px'"
+                :size="searchSize"
+                :start="parmValue.start"
+                :end="parmValue.end"
+                @timeReturned="handleTime"
+              />
+            </el-col>
+            <el-col :span="4" style="width: 160px">
+              <el-select
+                v-model="parmValue.status"
+                filterable
+                clearable
+                :size="searchSize"
+                placeholder="平台状态"
+                style="width: 100%"
+                @change="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+              >
+                <el-option
+                  v-for="item in statusList"
+                  :key="'status' + item.code"
+                  :label="item.name"
+                  :value="item.code"
+                />
+              </el-select>
+            </el-col>
+
+            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
+              <el-button type="primary" :size="searchSize" @click="searchList">刷新</el-button>
+            </el-col>
+            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
+              <el-button type="warning" :size="searchSize" @click="restSearch">重置</el-button>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="4" style="width: 373px">
+              <el-input
+                :size="searchSize"
+                v-model="parmValue.platform_name"
+                :maxlength="40"
+                @blur="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+                placeholder="平台名称"
+              ></el-input>
+            </el-col>
+            <el-col :span="4" style="width: 170px; padding: 0 0 0 10px">
+              <el-input
+                :size="searchSize"
+                v-model="parmValue.creater"
+                :maxlength="40"
+                @change="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+                placeholder="创建人"
+              ></el-input>
+            </el-col>
+            <el-col :span="4" style="width: 170px; padding: 0 0 0 10px">
+              <el-input
+                :size="searchSize"
+                v-model="parmValue.company_name"
+                :maxlength="40"
+                @change="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+                placeholder="创建人部门"
+              ></el-input>
+            </el-col>
+            <el-col
+              :span="3"
+              class="fr"
+              style="width: 66px; padding: 0 0 0 10px"
+              v-if="powers.some((i) => i == '003')"
+            >
+              <el-button
+                :size="searchSize"
+                type="success"
+                style="float: right"
+                @click="openModal({}, '003')"
+              >添加</el-button>
+            </el-col>
+          </el-row>
+        </div>
+      </template>
+      <template #status="{ scope }">
+        <el-tag
+          :size="tablebtnSize"
+          :type="scope.row.status == '0' ? 'warning' : ''"
+          v-text="
+            (statusOptions.find((item) => item.id == scope.row.status) || {}).label ||
+            '--'
+          "
+        ></el-tag>
+      </template>
+      <template #platform_type="{ scope }">
+        <el-tag
+          :size="tablebtnSize"
+          v-text="
+            (options.find((item) => item.value == scope.row.platform_type) || {}).label ||
+            '--'
+          "
+        ></el-tag>
+      </template>
+
+      <template #operation="{ scope }">
+        <el-tooltip
+          v-if="powers.some((i) => i == '007')"
+          effect="dark"
+          content="详情"
+          placement="top"
+        >
+          <i class="el-icon-view tb-icon" @click="openModal(scope.row, '007')"></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '005')"
+          effect="dark"
+          content="修改"
+          placement="top"
+        >
+          <i class="el-icon-edit tb-icon" @click="openModal(scope.row, '005')"></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '004') && scope.row.status === '1'"
+          effect="dark"
+          content="禁用"
+          placement="top"
+        >
+          <i
+            class="el-icon-video-pause tb-icon"
+            @click="changeStatus(scope.row.id, scope.row.status)"
+          ></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '004') && scope.row.status === '0'"
+          effect="dark"
+          content="启用"
+          placement="top"
+        >
+          <i
+            class="el-icon-video-play tb-icon"
+            @click="changeStatus(scope.row.id, scope.row.status)"
+          ></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '006')"
+          effect="dark"
+          content="删除"
+          placement="top"
+        >
+          <i class="el-icon-delete tb-icon" @click="deleteItem(scope.row.id)"></i>
+        </el-tooltip>
+      </template>
+    </ex-table>
+    <no-auth v-else></no-auth>
+    <!-- 弹窗 新增/修改 -->
+    <add-edit
+      :id="modelId"
+      :show-model="showModel"
+      :sitem="sitem"
+      @refresh="searchList"
+      @cancel="showModel = false"
+    />
+  </div>
+</template>
+<script>
+import addEdit from "./addEdit";
+import asyncRequest from "@/apis/service/serviceParam/terrace";
+import { statusList } from "@/assets/js/statusList";
+import roleLevel from "@/assets/js/roleLevel";
+import mixinPage from "@/mixins/elPaginationHandle";
+import { mapGetters } from "vuex";
+import resToken from "@/mixins/resToken";
+
+export default {
+  name: "terrace",
+  mixins: [mixinPage, resToken],
+  components: {
+    addEdit
+  },
+  computed: {
+    //组件SIZE设置
+    ...mapGetters(["tablebtnSize", "searchSize", "size"]),
+    powers() {
+      const { btnList } = this.$store.getters
+      const tran = btnList.find(i => i.menu_route == "platform") || {};
+      const { action } = tran ?? {};
+      return action ?? [];
+    }
+  },
+  data() {
+    return {
+      statusList: statusList,
+      roleLevel: roleLevel,
+      loading: true,
+      showModel: false,
+      modelId: "000",
+      sitem: {},
+      parmValue: {
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+        start: "",
+        end: "",
+        company_name: "", //创建人部门
+        status: "",
+        creater: "",
+        platform_name: ""
+      },
+      // 状态
+      statusOptions: [
+        { id: "0", label: "禁用" },
+        { id: "1", label: "启用" }
+      ],
+      options: [
+        { value: "0", label: "无对接" },
+        { value: "1", label: "有赞平台" }
+      ],
+      // 表格 - 数据
+      tableData: [],
+      // 表格 - 参数
+      table: {
+        stripe: true,
+        border: true,
+        _defaultHeader_: ["setcol"]
+      },
+      // 表格 - 分页
+      pageInfo: {
+        size: 15,
+        curr: 1,
+        total: 0
+      },
+      // 表格 - 列参数
+      columns: [
+        // {
+        //   prop: "id",
+        //   label: "ID",
+        // },
+        {
+          prop: "platform_code",
+          label: "平台编号",
+          width: "160px"
+        },
+        {
+          prop: "platform_name",
+          label: "平台名称"
+        },
+        {
+          prop: "companyNo",
+          label: "公司编号",
+          width: "160px"
+        },
+        {
+          prop: "companyName",
+          label: "公司名称",
+          width: "160px"
+        },
+        {
+          prop: "platform_type",
+          label: "对接平台",
+          _slot_: "platform_type"
+        },
+        {
+          prop: "status",
+          label: "状态",
+          _slot_: "status"
+        },
+        {
+          prop: "creater",
+          label: "创建人"
+        },
+        {
+          prop: "company_name",
+          label: "创建人部门",
+          minWidth: "120px"
+        },
+        {
+          prop: "addtime",
+          label: "创建时间",
+          minWidth: "145px"
+        },
+        {
+          prop: "",
+          label: "操作",
+          fixed: "right",
+          _noset_: true,
+          width: "145px",
+          _slot_: "operation"
+        }
+      ]
+    };
+  },
+  mounted() {
+    this.searchList();
+  },
+  methods: {
+    restSearch() {
+      // 表格 - 分页
+      this.pageInfo = {
+        size: 15,
+        curr: 1,
+        total: 0
+      };
+      this.parmValue = {
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+        start: "",
+        end: "",
+        status: "",
+        company_name: "", //创建人部门
+        creater: "",
+        platform_name: ""
+      };
+      this.searchList();
+    },
+    // 新建/编辑/详情
+    openModal(row, type) {
+      const { status } = row;
+      if (type === "005" && status === "1") {
+        this.$message.warning("禁用后,才可以修改!");
+        return;
+      }
+
+      this.sitem = row;
+      this.modelId = type;
+      this.showModel = true;
+    },
+    // 时间
+    async handleTime(event) {
+      const { startTime, endTime } = event;
+      this.parmValue.start = startTime || "";
+      this.parmValue.end = endTime || "";
+      const { start, end } = this.parmValue;
+
+      if ((start !== "" && end !== "") || (start === "" && end === "")) {
+        this.pageInfo.curr = 1;
+        this.parmValue.page = 1;
+        await this.searchList();
+      }
+    },
+    /**
+     * 启用/禁用
+     * @param {String} id id
+     * @param {String} status 0-禁用 1-启用
+     */
+    async changeStatus(id, status) {
+      await this.$confirm(`确定要改为${status === "1" ? "禁用" : "启用"}?`, {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(async () => {
+          this.loading = true;
+          const model = {
+            id: id,
+            status: status === "1" ? "0" : "1"
+          };
+          const res = await asyncRequest.status(model);
+          if (res && res.code === 0) {
+            this.loading = false;
+            this.$notify.success({
+              title: "状态修改成功!",
+              message: ""
+            });
+            await this.searchList();
+          } else if (res && res.code >= 100 && res.code <= 104) {
+            await this.logout();
+          } else {
+            this.loading = false;
+            this.$message.warning(res.message);
+          }
+        })
+        .catch(() => {
+          console.log("取消");
+        });
+    },
+    async deleteItem(id) {
+      await this.$confirm("确定要删除?", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(async () => {
+          const model = {
+            id: id
+          };
+          const res = await asyncRequest.delete(model);
+          if (res && res.code === 0) {
+            this.$notify.success({
+              title: "删除成功",
+              message: ""
+            });
+            this.searchList();
+          } else if (res && res.code >= 100 && res.code <= 104) {
+            await this.logout();
+          } else {
+            this.$message.warning(res.message);
+          }
+        })
+        .catch(() => {
+          console.log("取消");
+        });
+    },
+    // 刷新表格
+    async searchList() {
+      const { start, end } = this.parmValue;
+      if ((start !== "" && end === "") || (start == "" && end != "")) {
+        this.$message.warning("开始时间和结束时间不能为空");
+        return;
+      }
+
+      this.loading = true;
+      const res = await asyncRequest.list(this.parmValue);
+      if (res && res.code === 0 && res.data) {
+        this.tableData = res.data.list;
+        this.pageInfo.total = Number(res.data.count);
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        await this.logout();
+      } else {
+        this.tableData = [];
+        this.pageInfo.total = 0;
+      }
+      this.loading = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped></style>

+ 0 - 0
src/views/goodStore/platform/平台管理


+ 277 - 0
src/views/goodStore/platformGrossProfit/addEditRate.vue

@@ -0,0 +1,277 @@
+<template>
+  <el-dialog
+    v-loading="loading"
+    :title="'设置毛利率'"
+    :center="true"
+    align="left"
+    top="12vh"
+    width="600px"
+    :close-on-click-modal="false"
+    :visible.sync="showModelThis"
+    element-loading-text="拼命加载中"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)"
+    @close="showModelThis = false"
+  >
+    <el-card style="margin: -20px 0 0 0">
+      <el-row :gutter="0">
+        <el-col :span="24">
+          <el-form
+            ref="ruleForm"
+            :model="ruleForm"
+            status-icon
+            :size="'small'"
+            :rules="rulesThis"
+            label-width="110px"
+            class="demo-ruleForm"
+          >
+            <el-form-item label="分类名称" prop="cat_name">
+              <el-input
+                v-model="ruleForm.cat_name"
+                disabled
+                placeholder="分类名称"
+                maxlength="20"
+                >
+                <template slot="prepend" v-if="pid_name">
+                  {{ pid_name }}
+                </template>
+               </el-input>
+            </el-form-item>
+            <el-form-item label="财务核算码" prop="fund_code">
+              <el-input
+                v-model="ruleForm.fund_code"
+                disabled
+                placeholder="财务核算码"
+                maxlength="50"
+              />
+            </el-form-item>
+            <el-form-item label="成本→售价" prop="sale_rate">
+              <digital-input
+                :values="ruleForm.sale_rate"
+                :placeholder="'成本→售价'"
+                :min="-100"
+                :max="100000000000"
+                :position="'right'"
+                :precision="2"
+                :size="'mini'"
+                :controls="false"
+                :append="'%'"
+                @reschange="rate_change($event, 'sale_rate')"
+              />
+            </el-form-item>
+          </el-form>
+        </el-col>
+        <el-col :span="24" style="text-align: right">
+          <el-button
+            v-if="id !== '007'"
+            type="primary"
+            :size="'small'"
+            @click="submitForm"
+            >保 存
+          </el-button>
+          <el-button :size="'small'" @click="showModelThis = false">{{
+            id == "007" ? "关 闭" : "取 消"
+          }}</el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+  </el-dialog>
+</template>
+<script>
+import asyncRequest from "@/apis/service/youzan/othsearchSort";
+import resToken from "@/mixins/resToken";
+export default {
+  name: "sort",
+  props: ["showModel", "id", "sitem", "titleList"],
+  mixins: [resToken],
+  data() {
+    const validate_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("主管利率毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_order_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("预算→成本毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_sale_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("成本→售价毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+
+    const validate_lower_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("BOSS毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_low_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("项目最低毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    const validate_money_rate = (rule, value, callback) => {
+      const { required } = rule;
+      if (value === "" && required) {
+        callback(new Error("财务毛利率不能为空!"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      loading: false,
+      showModelThis: this.showModel,
+      pid_name: "",
+      ruleForm: {
+        platform_id: "",
+        cat_id: "",
+        cat_name: "",
+        order_rate: "0",
+        sale_rate: "0",
+        lower_rate: "0",
+        rate: "0",
+        low_rate: "0",
+        money_rate: "0",
+      },
+      rulesThis: this.rules,
+      rules: {
+        order_rate: [{ required: true, validator: validate_order_rate, trigger: "blur" }],
+        sale_rate: [{ required: true, validator: validate_sale_rate, trigger: "blur" }],
+        lower_rate: [{ required: false, validator: validate_lower_rate, trigger: "blur" }],
+        rate: [{ required: true, validator: validate_rate, trigger: "blur" }],
+        low_rate: [{ required: true, validator: validate_low_rate, trigger: "blur" }],
+        money_rate: [{ required: true, validator: validate_money_rate, trigger: "blur" }],
+      },
+    };
+  },
+  watch: {
+    showModel: function (val) {
+      this.showModelThis = val;
+      if (val) {
+        this.initForm();
+      }
+    },
+    showModelThis(val) {
+      if (!val) {
+        this.$emit("cancel");
+      }
+    },
+  },
+  methods: {
+    async initForm() {
+      this.loading = true;
+      this.pid_name = "";
+      this.titleList.forEach((e, i) => {
+        this.pid_name += i !== 0 ? `${e.titleName}/` : "";
+      });
+      this.rulesThis = this.rules;
+      await this.resetForm();
+      this.loading = false;
+    },
+
+    async resetForm() {
+      // 重置
+      await this.$nextTick(() => {
+        if (this.$refs.ruleForm) {
+          this.$refs.ruleForm.resetFields();
+          this.$refs.ruleForm.clearValidate();
+          const {
+            platform_id,
+            id,
+            cat_name,
+            order_rate,
+            sale_rate,
+            lower_rate,
+            rate,
+            fund_code,
+            low_rate,
+            money_rate,
+          } = this.sitem;
+          this.ruleForm = {
+            platform_id: platform_id + "" || "",
+            cat_id: id || "",
+            cat_name: cat_name || "",
+            fund_code: fund_code || "",
+            order_rate: order_rate || "0",
+            sale_rate: sale_rate || "0",
+            lower_rate: lower_rate || "0",
+            rate: rate || "0",
+            low_rate: low_rate || "0",
+            money_rate: money_rate || "0",
+          };
+        }
+      });
+    },
+    rate_change(e, key) {
+      this.ruleForm[key] = e + "";
+      this.$refs.ruleForm.validateField(key);
+    },
+    async submitForm() {
+      await this.$refs.ruleForm.validate(async (valid) => {
+        if (valid) {
+          if (!this.loading) {
+            this.loading = true;
+            let model = JSON.parse(JSON.stringify(this.ruleForm));
+            delete model["cat_name"];
+            // delete model["pid"];
+            // delete model["fund_code"];
+            const { code, data, message } = await asyncRequest.update(model);
+            this.loading = false;
+            if (code === 0) {
+              this.$notify.success({
+                title: "毛利率设置成功!",
+                message: "",
+              });
+              this.showModelThis = false;
+              // 刷新
+              this.$emit("refresh");
+            } else if (code >= 100 && code <= 104) {
+              await this.logout();
+            } else if (code === 10004) {
+              const { skuCode } = data;
+              let resList = JSON.parse(JSON.stringify(skuCode));
+
+              let htmlList = "<ul>";
+              resList.forEach((v) => {
+                htmlList += `<li><span>${v.skuCode}__</span><span>${v.good_name}</span></li>`;
+              });
+              htmlList += "</ul>";
+              this.$notify({
+                title: "新毛利已影响以下线上商品售价,请下线后再修改!",
+                dangerouslyUseHTMLString: true,
+                message: htmlList,
+              });
+            } else {
+              this.$message.warning(message);
+            }
+          }
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.sort {
+}
+</style>

+ 471 - 0
src/views/goodStore/platformGrossProfit/index.vue

@@ -0,0 +1,471 @@
+<template>
+  <div class="sort pagePadding">
+    <ex-table
+      v-loading="loading"
+      v-if=" powers.some((i) => i == '001')"
+      :table="table"
+      :data="tableData"
+      :columns="columns"
+      :page="pageInfo"
+      :size="size"
+      @page-curr-change="handlePageChange"
+      @page-size-change="handleSizeChange"
+      @screen-reset="
+        pageInfo.curr = 1;
+        parmValue.page = 1;
+        searchList();
+      "
+      @screen-submit="
+        pageInfo.curr = 1;
+        parmValue.page = 1;
+        searchList();
+      "
+    >
+      <template #table-header="{}">
+        <div style="width: 100%">
+          <el-row style="padding: 0 0 10px 90px">
+            <el-col :span="3" style="width: 748px">
+              <div class="my-breadcrumb clear">
+                <div
+                  class="my-breadcrumb-item"
+                  v-for="(item, index) in titleList"
+                  :key="item + index"
+                  @click="changeBreadcrumb(index)"
+                >
+                  <span class="label">{{ item.titleName }}</span
+                  ><span class="separator" v-if="index + 1 !== titleList.length">/</span>
+                </div>
+              </div>
+            </el-col>
+
+            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
+              <el-button type="primary" :size="searchSize" @click="searchList">
+                刷新
+              </el-button>
+            </el-col>
+            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
+              <el-button type="warning" :size="searchSize" @click="restSearch">
+                重置
+              </el-button>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="4" style="width: 140px">
+              <el-select
+                v-model="parmValue.status"
+                filterable
+                clearable
+                :size="searchSize"
+                placeholder="分类状态"
+                style="width: 100%"
+                @change="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+              >
+                <el-option
+                  v-for="item in statusList"
+                  :key="'status' + item.code"
+                  :label="item.name"
+                  :value="item.code"
+                />
+              </el-select>
+            </el-col>
+            <el-col :span="4" style="width: 390px; padding: 0 0 0 10px">
+              <search-terrace
+                :value="parmValue.platform_id"
+                :disabled="false"
+                :size="'mini'"
+                :isDetail="false"
+                :is_show="'0'"
+                :placeholder="'平台名称'"
+                @searchChange="platform_codeChange"
+              />
+            </el-col>
+            <el-col :span="4" style="width: 390px; padding: 0 0 0 10px">
+              <el-input
+                :size="searchSize"
+                v-model="parmValue.cat_name"
+                :maxlength="40"
+                @blur="
+                  pageInfo.curr = 1;
+                  parmValue.page = 1;
+                  searchList();
+                "
+                placeholder="分类名称"
+              ></el-input>
+            </el-col>
+          </el-row>
+        </div></template
+      >
+      <template #status="{ scope }">
+        <el-tag
+          :size="tablebtnSize"
+          :type="scope.row.status == '0' ? 'warning' : ''"
+          v-text="
+            (statusOptions.find((item) => item.id == scope.row.status) || {}).label ||
+            '--'
+          "
+        ></el-tag>
+      </template>
+      <template #order_rate="{ scope }">
+        <div>
+          {{
+            private_field &&
+            private_field.length > 0 &&
+            private_field.some((item) => item == "3")
+              ? scope.row.order_rate
+              : "****"
+          }}
+        </div>
+      </template>
+      <template #sale_rate="{ scope }">
+        <div>
+          {{
+            private_field &&
+            private_field.length > 0 &&
+            private_field.some((item) => item == "3")
+              ? scope.row.sale_rate
+              : "****"
+          }}
+        </div>
+      </template>
+      <template #rate="{ scope }">
+        <div>
+          {{
+            private_field &&
+            private_field.length > 0 &&
+            private_field.some((item) => item == "3")
+              ? scope.row.rate
+              : "****"
+          }}
+        </div>
+      </template>
+      <template #money_rate="{ scope }">
+        <div>
+          {{
+            private_field &&
+            private_field.length > 0 &&
+            private_field.some((item) => item == "3")
+              ? scope.row.money_rate
+              : "****"
+          }}
+        </div>
+      </template>
+      <template #low_rate="{ scope }">
+        <div>
+          {{
+            private_field &&
+            private_field.length > 0 &&
+            private_field.some((item) => item == "3")
+              ? scope.row.low_rate
+              : "****"
+          }}
+        </div>
+      </template>
+
+      <template #operation="{ scope }">
+        <el-tooltip
+          v-if="powers.some((i) => i == '005')"
+          effect="dark"
+          content="修改毛利率"
+          placement="top"
+        >
+          <i class="el-icon-s-check tb-icon" @click="setRate(scope.row)"></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="parseInt(scope.row.level) < 3"
+          effect="dark"
+          content="下级分类"
+          placement="top"
+        >
+          <i class="el-icon-arrow-right tb-icon" @click="openChildren(scope.row)"></i>
+        </el-tooltip>
+      </template>
+    </ex-table>
+    <no-auth v-else></no-auth>
+
+    <!-- 弹窗 新增/修改 -->
+    <add-edit-rate
+      :id="modelRateId"
+      :show-model="showRateModel"
+      :sitem="sitemRate"
+      :titleList="titleList"
+      @refresh="searchList"
+      @cancel="showRateModel = false"
+    />
+  </div>
+</template>
+<script>
+import addEditRate from "./addEditRate";
+import asyncRequest from "@/apis/service/youzan/othsearchSort";
+import { statusList } from "@/assets/js/statusList";
+import roleLevel from "@/assets/js/roleLevel";
+import mixinPage from "@/mixins/elPaginationHandle";
+import { mapGetters } from "vuex";
+import resToken from "@/mixins/resToken";
+import reloadData from "@/mixins/reloadData";
+export default {
+  name: "othsearchSort",
+  mixins: [mixinPage, resToken,reloadData(ctx => ctx.searchList())],
+  components: {
+    addEditRate,
+  },
+  computed: {
+    //组件SIZE设置
+    ...mapGetters(["tablebtnSize", "searchSize", "size"]),
+    powers() {
+      const { btnList } = this.$store.getters;
+      const tran = btnList.find((i) => i.menu_route == "othsearchSort") || {};
+      const { action } = tran ?? {};
+      return action ?? [];
+    },
+  },
+  data() {
+    return {
+      private_field:[],
+      statusList: statusList,
+      roleLevel: roleLevel,
+      loading: false,
+      sitem: {},
+      showRateModel: false,
+      modelRateId: "000",
+      sitemRate: {},
+      titleList: [],
+      parmValue: {
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+        status: "",
+        platform_id: "",
+        cat_name: "",
+        pid: "0",
+      },
+      // 状态
+      statusOptions: [
+        { id: "0", label: "禁用" },
+        { id: "1", label: "启用" },
+      ],
+      // 表格 - 数据
+      tableData: [],
+      // 表格 - 参数
+      table: {
+        stripe: true,
+        border: true,
+        _defaultHeader_: ["setcol"],
+      },
+      // 表格 - 分页
+      pageInfo: {
+        size: 15,
+        curr: 1,
+        total: 0,
+      },
+      // 表格 - 列参数
+      columns: [
+        // {
+        //   prop: "id",
+        //   label: "ID",
+        //   "min-width": "100px",
+        // },
+        {
+          prop: "cat_name",
+          label: "分类名称",
+          minwidth: "130px",
+        },
+        {
+          prop: "level",
+          label: "等级",
+          width: "50px",
+        },
+        {
+          prop: "status",
+          label: "状态",
+          _slot_: "status",
+          width: "70px",
+        },
+        {
+          prop: "platform_name",
+          label: "平台名称",
+          minwidth: "190px",
+        },
+        {
+          prop: "companyNo",
+          label: "公司编号"
+        },
+        {
+          prop: "companyName",
+          label: "公司名称"
+        },
+        {
+          prop: "fund_code",
+          label: "财务核算码",
+          width: "150px",
+        },
+        {
+          prop: "sale_rate",
+          label: "成本→售价",
+          _slot_: "sale_rate",
+          width: "90px",
+        },
+        {
+          prop: "creater",
+          label: "创建人",
+          width: "70px",
+        },
+        {
+          prop: "addtime",
+          label: "创建时间",
+          width: "145px",
+        },
+        {
+          prop: "",
+          label: "操作",
+          fixed: "right",
+          width: "110px",
+          _noset_: true,
+          _slot_: "operation",
+        },
+      ],
+    };
+  },
+  mounted() {
+    this.initTitleList();
+    this.parmValue.pid = "0";
+    this.searchList();
+  },
+  methods: {
+    restSearch() {
+      // 表格 - 分页
+      this.pageInfo = {
+        size: 15,
+        curr: 1,
+        total: 0,
+      };
+      this.parmValue = {
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+        status: "",
+        cat_name: "",
+        platform_id: "",
+        pid: "0",
+      };
+      this.initTitleList();
+      this.searchList();
+    },
+    async platform_codeChange(e) {
+      const { id } = e;
+      this.parmValue.platform_id = id || "";
+      this.pageInfo.curr = 1;
+      this.parmValue.page = 1;
+      await this.searchList();
+    },
+    initTitleList() {
+      this.titleList = [];
+      let model = { id: "0", titleName: "全部一级分类" };
+      this.titleList.push(model);
+    },
+    //查看下一级分类
+    async openChildren(item) {
+      this.parmValue.pid = item.id;
+      this.pageInfo.curr = 1;
+      this.parmValue.page = 1;
+      await this.searchList();
+      let model = {
+        id: item.id,
+        titleName: item.cat_name,
+      };
+      this.titleList.push(model);
+    },
+    //设置毛利率
+    setRate(row) {
+      this.modelRateId = row.id;
+      this.sitemRate = row;
+      this.showRateModel = true;
+    },
+    async changeBreadcrumb(index) {
+      if (index + 1 === this.titleList.length) {
+        return;
+      } else {
+        this.parmValue.pid = this.titleList[index].id;
+        this.titleList = this.titleList.slice(0, index + 1);
+      }
+      // if (this.titleList.length === 1) {
+      //   this.titleList = [];
+      // }
+      this.parmValue.cat_name = "";
+      this.pageInfo.curr = 1;
+      this.parmValue.page = 1;
+      await this.searchList();
+    },
+
+    // 刷新表格
+    async searchList() {
+      if (this.loading) return;
+
+      if(!this.currentCompany){
+        this.$message.warning("请选择公司!");
+        return 
+      }
+
+      if (this.parmValue.platform_id === "") {
+        this.$message.warning("请选择平台!");
+        return;
+      }
+
+      this.parmValue.companyNo = this.currentCompany;
+
+
+      this.loading = true;
+      const { code, data } = await asyncRequest.list(this.parmValue);
+      if (code === 0) {
+        const { list, count } = data ?? {};
+        this.tableData = list ?? [];
+        this.pageInfo.total = count ?? 0;
+      } else if (code >= 100 && code <= 104) {
+        await this.logout();
+      } else {
+        this.tableData = [];
+        this.pageInfo.total = 0;
+      }
+      this.loading = false;
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.sort {
+  .my-breadcrumb {
+    .my-breadcrumb-item {
+      float: left;
+      span {
+        height: 32px;
+        line-height: 32px;
+      }
+      .label {
+        padding: 0 5px 0 0;
+        color: 010101;
+      }
+      .separator {
+        color: #787878;
+        font-size: 13px;
+        padding: 0 5px 0 0;
+      }
+      &:last-child {
+        .label {
+          color: #787878;
+        }
+      }
+      &:hover {
+        cursor: pointer;
+      }
+      &:last-child {
+        cursor: default;
+      }
+      &:only-child {
+        cursor: pointer;
+      }
+    }
+  }
+}
+</style>

+ 0 - 0
src/views/goodStore/platformGrossProfit/公司平台分类毛利


+ 27 - 363
src/views/interest/account/addEdit.vue

@@ -25,31 +25,19 @@
             label-width="80px"
             class="demo-ruleForm"
           >
-            <el-row>
-              <el-col :span="12">
-                <el-form-item
-                  v-if="id === 'add' || isDetail"
-                  label="账号"
-                  prop="username"
-                >
-                  <el-input
-                    v-model="ruleForm.username"
-                    maxlength="100"
-                    :disabled="isDetail"
-                  />
-                </el-form-item>
-              </el-col>
-              <el-col :span="12">
-                <el-form-item label="真实姓名" prop="name">
+            <el-row style="margin-bottom:20px">
+              <el-col :span="24">
+                <el-form-item label="真实姓名" prop="nickname">
                   <el-input
-                    v-model="ruleForm.name"
+                    v-model="ruleForm.nickname"
                     :placeholder="'真实姓名'"
                     :disabled="isDetail"
                     maxlength="100"
                   />
                 </el-form-item>
               </el-col>
-              <el-col :span="12">
+              
+              <el-col :span="24">
                 <el-form-item label="手机号" prop="mobile">
                   <el-input
                     v-model="ruleForm.mobile"
@@ -59,112 +47,6 @@
                   />
                 </el-form-item>
               </el-col>
-              <el-col :span="12">
-                <el-form-item label="所在部门" prop="itemid">
-                  <all-organize
-                    :value="ruleForm.itemid"
-                    :is-detail="isDetail"
-                    :disabled="isDetail"
-                    :multiple="true"
-                    :size="'mini'"
-                    :checkStrictly="true"
-                    :placeholder="'所在部门'"
-                    @searchChange="itemidChange"
-                  />
-                </el-form-item>
-              </el-col>
-              <el-col :span="12">
-                <el-form-item label="邮箱" prop="email">
-                  <el-input
-                    v-model="ruleForm.email"
-                    :placeholder="'邮箱'"
-                    maxlength="100"
-                    :disabled="isDetail"
-                  />
-                </el-form-item>
-              </el-col>
-              <el-col :span="24">
-                <el-form-item label="角色" prop="role_id">
-                  <el-radio-group
-                    v-model="ruleForm.role_id"
-                    :size="'mini'"
-                    :disabled="isDetail"
-                  >
-                    <el-radio
-                      v-for="item in roleList"
-                      :key="item.id"
-                      :label="item.id"
-                      :disabled="item.status !== '1'"
-                      >{{ item.role_name }}</el-radio
-                    >
-                  </el-radio-group>
-                </el-form-item>
-              </el-col>
-              <el-col :span="24">
-                <el-form-item label="业务公司" prop="companyArr">
-                  <el-row>
-                    <el-col :span="20">
-                      <el-checkbox
-                        :size="'mini'"
-                        :indeterminate="isIndeterminate"
-                        v-model="ruleForm.is_all"
-                        @change="handleCheckAllChange"
-                        >全选</el-checkbox
-                      >
-                      <el-checkbox-group
-                        :size="'mini'"
-                        v-model="ruleForm.companyArr"
-                        @change="handleCheckedCitiesChange"
-                        class="“fl"
-                      >
-                        <el-checkbox
-                          style="display: block; margin: 0; box-sizing: border-box"
-                          v-for="(item, i) in coptions"
-                          :key="item.id + i"
-                          :label="item.id"
-                          :disabled="item.status === '0'"
-                          >{{ item.company }}</el-checkbox
-                        >
-                      </el-checkbox-group>
-                    </el-col>
-                    <el-col :span="4" style="padding: 33px 0 0 0">
-                      <el-radio-group v-model="ruleForm.is_main">
-                        <el-radio
-                          v-for="(si, sii) in is_mainoptions"
-                          :key="si.id + sii"
-                          style="
-                            display: block;
-                            margin: 0;
-                            padding: 6px 0 0 0;
-                            height: 28px;
-                            box-sizing: border-box;
-                          "
-                          :disabled="si.status === '0'"
-                          :label="si.id"
-                          >设为默认</el-radio
-                        >
-                      </el-radio-group>
-                    </el-col>
-                  </el-row>
-                </el-form-item>
-              </el-col>
-              <el-col :span="24">
-                <el-form-item label="业务平台" prop="platform">
-                  <el-checkbox-group
-                    :size="'mini'"
-                    v-model="ruleForm.platform"
-                    class="“fl"
-                  >
-                    <el-checkbox
-                      style="display: block; margin: 0; box-sizing: border-box"
-                      v-for="(item, i) in platformoptions"
-                      :key="item.id + i"
-                      :label="item.id"
-                      >{{ item.platform_name }}</el-checkbox
-                    >
-                  </el-checkbox-group>
-                </el-form-item>
-              </el-col>
             </el-row>
           </el-form>
         </el-col>
@@ -183,6 +65,7 @@
 <script>
 import asyncRequest from "@/apis/service/interest/account";
 import resToken from "@/mixins/resToken";
+
 import {
   isnumber,
   isMobile,
@@ -216,6 +99,7 @@ export default {
         }
       }
     };
+
     const validatename = (rule, value, callback) => {
       if (value === "") {
         callback(new Error("真实姓名不能为空!"));
@@ -231,6 +115,7 @@ export default {
         }
       }
     };
+
     const validatemobile = (rule, value, callback) => {
       if (value === "") {
         callback(new Error("手机号不能为空!"));
@@ -243,17 +128,6 @@ export default {
       }
     };
 
-    const validateEmail = (rule, value, callback) => {
-      if (value === "") {
-        callback();
-      } else {
-        if (!validEmail(value)) {
-          callback(new Error("邮箱格式不正确!"));
-        } else {
-          callback();
-        }
-      }
-    };
     return {
       roleList: [],
       loading: false,
@@ -264,35 +138,20 @@ export default {
       is_mainoptions: [],
       isIndeterminate: false,
       ruleForm: {
-        username: "", // 账号
-        name: "", // 真实姓名
-        mobile: "",
-        email: "",
-        role_id: "",
-        is_all: "",
-        status: "1",
-        itemid: [],
-        companyArr: [],
-        is_main: "",
-        platform: [],
+        nickname: "", // 真实姓名
+        mobile: "", //手机号
+        role_id: "", //角色id
       },
       platformoptions: [],
       rulesThis: this.rules,
       rules: {
-        name: [
+        nickname: [
           {
             required: true,
             validator: validatename,
             trigger: "blur",
           },
         ],
-        username: [
-          {
-            required: true,
-            validator: validateusername,
-            trigger: "blur",
-          },
-        ],
         mobile: [
           {
             required: true,
@@ -300,13 +159,6 @@ export default {
             trigger: "blur",
           },
         ],
-        email: [
-          {
-            required: false,
-            validator: validateEmail,
-            trigger: "blur",
-          },
-        ],
         role_id: [
           {
             required: true,
@@ -314,32 +166,6 @@ export default {
             trigger: "change",
           },
         ],
-        itemid: [
-          {
-            type: "array",
-            required: true,
-            message: "请选择所在部门",
-            trigger: "change",
-          },
-        ],
-
-        companyArr: [
-          {
-            type: "array",
-            required: true,
-            message: "至少选择一个业务公司",
-            trigger: "change",
-          },
-        ],
-
-        platform: [
-          {
-            type: "array",
-            required: true,
-            message: "至少选择一个业务平台",
-            trigger: "change",
-          },
-        ],
       },
     };
   },
@@ -356,7 +182,6 @@ export default {
       }
     },
   },
-  mounted() {},
   methods: {
     itemidChange(e) {
       this.ruleForm.itemid = e;
@@ -365,10 +190,6 @@ export default {
     async initForm() {
       this.loading = true;
 
-      await this.getClist();
-      await this.getRole();
-      await this.getWorkList();
-      await this.getTerraceList();
       if (this.id === "add") {
         await this.resetForm();
       } else {
@@ -403,58 +224,6 @@ export default {
         this.$message.warning(message);
       }
     },
-    //获取全部业务公司
-    async getWorkList() {
-      this.coptions = [];
-      this.is_mainoptions = [];
-      const { code, data, message } = await asyncRequest.getWorkList({
-        size: 10000,
-        page: 1,
-      });
-      if (code === 0) {
-        const { list, count } = data;
-        this.coptions = list;
-        this.coptions.forEach((e) => {
-          this.is_mainoptions.push({
-            id: e.id,
-            status: e.status,
-          });
-        });
-      } else if (code >= 100 && code <= 104) {
-        await this.logout();
-      } else {
-        this.$message.warning(message);
-      }
-    },
-    //获取全部业务平台
-    async getTerraceList() {
-      this.platformoptions = [];
-      const { code, data, message } = await asyncRequest.getTerraceList({
-        size: 10000,
-        page: 1,
-        is_show: "0",
-      });
-      if (code === 0) {
-        const { list, count } = data;
-        this.platformoptions = list;
-      } else if (code >= 100 && code <= 104) {
-        await this.logout();
-      } else {
-        this.$message.warning(message);
-      }
-    },
-    handleCheckAllChange(val) {
-      let checkedCount = val ? this.coptions.length : 0;
-      this.isIndeterminate = checkedCount > 0 && checkedCount < this.coptions.length;
-      this.ruleForm.companyArr = [];
-      if (checkedCount !== 0) {
-        this.coptions.forEach((e) => {
-          if (e.status === "1") {
-            this.ruleForm.companyArr.push(e.id);
-          }
-        });
-      }
-    },
     handleCheckedCitiesChange(value) {
       console.log(value);
       let checkedCount = value.length;
@@ -511,95 +280,22 @@ export default {
           this.$refs.ruleForm.clearValidate();
           if (sitem) {
             const {
-              username,
               nickname,
               mobile,
-              email,
-              roleid,
-              status,
-              depart,
-              business,
-              platform,
+              id
             } = sitem;
-            let depart_code = [];
-            if (depart && depart.length > 0) {
-              depart.forEach((a) => {
-                depart_code.push(a.depart_code);
-              });
-            }
-            let copyBusiness =
-              business && business.length > 0 ? JSON.parse(JSON.stringify(business)) : [];
-
-            let businessList =
-              business && business.length > 0 ? JSON.parse(JSON.stringify(business)) : [];
-            businessList.forEach((a, ai) => {
-              let sindex = this.coptions.findIndex((b) => b.id == a.businessid);
-              if (sindex === -1) {
-                copyBusiness.splice(ai, 1);
-              }
-            });
-            let is_all = false,
-              add = 0;
-            // if(copyBusiness.length===)
-
-            let resbusinesslist = [],
-              is_main = "";
-            if (copyBusiness && copyBusiness.length > 0) {
-              copyBusiness.forEach((a) => {
-                resbusinesslist.push(a.businessid);
-                if (a.is_main === "1") {
-                  is_main = a.businessid;
-                }
-              });
-            }
-
-            let copyplatform =
-              platform && platform.length > 0 ? JSON.parse(JSON.stringify(platform)) : [];
-            let platformList =
-              platform && platform.length > 0 ? JSON.parse(JSON.stringify(platform)) : [];
-            platformList.forEach((a, ai) => {
-              let sindex = this.platformoptions.findIndex((b) => b.id == a.id);
-              if (sindex === -1) {
-                copyplatform.splice(ai, 1);
-              }
-            });
-            let resplatformlist = [];
-            if (copyplatform && copyplatform.length > 0) {
-              copyplatform.forEach((a) => {
-                resplatformlist.push(a.id);
-              });
-            }
 
             this.ruleForm = {
-              username: username || "", // 账号
-              name: nickname || "", // 真实姓名
-              mobile: mobile || "",
-              email: email || "",
-              role_id: roleid || "",
-              status: status || "",
-              itemid: depart_code,
-              is_main: is_main || "",
-              companyArr: resbusinesslist || [],
-              platform: resplatformlist || [],
-              is_all: resbusinesslist.length === this.coptions.length,
+              id,
+              nickname: nickname || "",
+              mobile: mobile || ""
             };
-            this.isIndeterminate =
-              resbusinesslist.length > 0 && resbusinesslist.length < this.coptions.length;
+
           } else {
             this.ruleForm = {
-              username: "", // 账号
-              name: "", // 真实姓名
-              mobile: "",
-              email: "",
-              role_id: "",
-              is_all: "",
-              status: "1",
-              itemid: [],
-              companyArr: [],
-              is_main: "",
-              platform: [],
+              nickname: "", // 真实姓名
+              mobile: ""
             };
-            this.handleCheckAllChange();
           }
         }
       });
@@ -610,49 +306,17 @@ export default {
           if (!this.loading) {
             this.loading = true;
             const {
-              username,
-              name,
+              nickname,
               mobile,
-              email,
-              role_id,
-              status,
-              itemid,
-              is_main,
-              is_all,
-              companyArr,
-              platform,
+              id
             } = JSON.parse(JSON.stringify(this.ruleForm));
-            let list = [],
-              isok = true;
-            companyArr.forEach((e) => {
-              let item = {
-                businessid: e,
-                is_main: is_main === e ? "1" : "0",
-              };
-              list.push(item);
-              let findex = this.coptions.findIndex((a) => a.id === e && a.status === "0");
-              if (findex !== -1) {
-                isok = false;
-              }
-            });
-            if (!isok) {
-              this.$message.warning("不能选择禁用的业务企业!");
-              this.loading = true;
-              return;
-            }
+
             const model = {
-              id: this.id,
-              username: username || "", // 账号
-              nickname: name || "", // 真实姓名
-              mobile: mobile || "",
-              email: email || "",
-              role: role_id || "",
-              status: status || "",
-              itemid: itemid || [],
-              is_all: is_all ? "1" : "0",
-              platform: platform || [],
-              companyArr: list,
+              nickname,
+              mobile,
+              id
             };
+
             let res = {};
             if (this.id === "add") {
               delete model["id"];

+ 34 - 28
src/views/interest/account/index.vue

@@ -121,7 +121,7 @@
           ></el-tag>
         </template>
         <template #operation="{ scope }">
-          <el-tooltip
+          <!-- <el-tooltip
             v-if="powers.some((i) => i == '002')"
             effect="dark"
             content="重置密码"
@@ -131,7 +131,7 @@
               class="el-icon-refresh-left tb-icon"
               @click="openPasswordModal(scope.row.id, false)"
             ></i>
-          </el-tooltip>
+          </el-tooltip> -->
 
           <el-tooltip
             v-if="powers.some((i) => i == '007')"
@@ -144,7 +144,7 @@
               @click="openModal(scope.row.id, true, scope.row)"
             ></i>
           </el-tooltip>
-          <el-tooltip
+          <!-- <el-tooltip
             v-if="powers.some((i) => i == '005')"
             effect="dark"
             content="修改"
@@ -176,7 +176,7 @@
               class="el-icon-video-play tb-icon"
               @click="statusConfirm(scope.row.id, scope.row.status)"
             ></i>
-          </el-tooltip>
+          </el-tooltip> -->
         </template>
       </ex-table>
       <add-edit
@@ -209,18 +209,20 @@ import resetPassword from "./resetPassword";
 import { statusList } from "@/assets/js/statusList";
 import { mapGetters } from "vuex";
 import resToken from "@/mixins/resToken";
+import reloadData from "@/mixins/reloadData";
+
 export default {
   name: "Account",
   components: {
     addEdit,
     resetPassword,
   },
-  mixins: [mixinPage, resToken],
+  mixins: [mixinPage, resToken,reloadData(ctx => ctx.searchList())],
   computed: {
     ...mapGetters(["tablebtnSize", "searchSize", "size"]),
     powers() {
-      const tran =
-        this.$store.getters.btnList.find((i) => i.menu_route == "account") || {};
+      const { btnList } = this.$store.getters;
+      const tran = btnList.find((i) => i.menu_route == "account") || {};
       const { action } = tran ?? {};
       return action ?? [];
     },
@@ -268,28 +270,28 @@ export default {
         {
           prop: "nickname",
           label: "真实姓名",
-          width: "110px",
-        },
-        {
-          prop: "role_name",
-          label: "角色名称",
-          width: "110px",
+          // width: "110px",
         },
+        // {
+          // prop: "role_name",
+          // label: "角色名称",
+          // width: "110px",
+        // },
         {
           prop: "mobile",
           label: "联系电话",
-          width: "110px",
-        },
-        {
-          prop: "depart_info",
-          label: "所在部门",
-          _slot_: "depart_info",
-          // width: "80px",
-        },
-        {
-          prop: "email",
-          label: "邮箱",
+          // width: "110px",
         },
+        // {
+        //   prop: "depart_info",
+        //   label: "所在部门",
+        //   _slot_: "depart_info",
+        //   // width: "80px",
+        // },
+        // {
+        //   prop: "email",
+        //   label: "邮箱",
+        // },
         {
           prop: "status",
           label: "状态",
@@ -300,14 +302,14 @@ export default {
           prop: "addtime",
           label: "创建时间",
           sortable: true,
-          width: "140px",
+          // width: "140px",
         },
         {
           prop: "",
           label: "操作",
           fixed: "right",
           _noset_: true,
-          width: "140px",
+          width: "60px",
           _slot_: "operation",
         },
       ],
@@ -333,12 +335,14 @@ export default {
       };
       this.searchList();
     },
+
     openModal(id, isDetail, sitem) {
       this.showModel = true;
       this.modelId = id;
       this.isDetail = isDetail;
       this.sitem = sitem;
     },
+
     openPasswordModal(id, isDetail) {
       this.passwordModel = true;
       this.passwordModelId = id;
@@ -375,6 +379,8 @@ export default {
     },
     async searchList() {
       this.loading = true;
+      this.parmValue.comnpanyNo = this.currentCompany;
+      
       const res = await asyncRequest.list(this.parmValue);
       if (res && res.code === 0 && res.data) {
         this.tableData = res.data.list;
@@ -399,6 +405,7 @@ export default {
             id: id,
             status: status === "1" ? "0" : "1",
           };
+          
           const res = await asyncRequest.status(model);
           if (res && res.code === 0) {
             this.loading = false;
@@ -421,6 +428,5 @@ export default {
 };
 </script>
 <style lang="scss" scoped>
-.account {
-}
+.account {}
 </style>

+ 839 - 0
src/views/interest/role-origin/addEdit.vue

@@ -0,0 +1,839 @@
+<template>
+  <el-dialog
+    v-loading="loading"
+    :title="title"
+    :center="true"
+    align="left"
+    top="5vh"
+    width="1040px"
+    :close-on-click-modal="false"
+    :visible.sync="showModelThis"
+    element-loading-text="拼命加载中"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)"
+    @close="showModelThis = false"
+  >
+    <el-card style="margin-top: -20px">
+      <el-row :gutter="10">
+        <el-form
+          ref="ruleForm"
+          :model="ruleForm"
+          status-icon
+          :size="'mini'"
+          :rules="rulesThis"
+          label-width="80px"
+          class="demo-ruleForm"
+        >
+          <el-col :span="9">
+            <el-form-item label="角色名称" prop="role_name">
+              <el-input
+                v-model="ruleForm.role_name"
+                :disabled="isDetail"
+                maxlength="50"
+                placeholder="角色名称"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="9">
+            <el-form-item
+              label="关键字段权限"
+              prop="private_field"
+              label-width="110px"
+            >
+              <el-checkbox-group
+                v-model="ruleForm.private_field"
+                :disabled="isDetail"
+                placeholder="关键字段权限"
+              >
+                <el-checkbox :label="'1'">成本价</el-checkbox>
+                <el-checkbox :label="'2'">销售价</el-checkbox>
+                <el-checkbox :label="'3'">毛利率</el-checkbox>
+              </el-checkbox-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="角色等级" prop="level">
+              <el-select
+                v-model="ruleForm.level"
+                filterable
+                :disabled="isDetail"
+                placeholder="请选择角色等级"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="item in roleLevel"
+                  :key="'ruleid' + item.code"
+                  :label="item.name"
+                  :value="item.code"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+
+          <div class="quanxian-main">
+            <div class="quanxian-title">
+              <span style="color: #ff8888">*</span
+              ><span
+                style="
+                  font-size: 14px;
+                  color: #606266;
+                  line-height: 40px;
+                  padding: 0 12px 0 0;
+                  font-weight: 700;
+                "
+                >功能权限</span
+              >
+            </div>
+            <div class="rule-view">
+              <div class="rule-list">
+                <el-row
+                  v-for="(item, index) in actionList"
+                  :key="'menu' + item.id + index"
+                >
+                  <el-col
+                    v-if="item.child && item.child.length > 0"
+                    class="ffff"
+                    :span="24"
+                  >
+                    <div class="ftitle">
+                      <span>{{ item.menu_name }}</span>
+                    </div>
+                    <div class="fbody">
+                      <div
+                        class="fbody-item"
+                        v-for="(subItem, subIndex) in item.child"
+                        :key="'yemian' + subItem.id + subIndex"
+                      >
+                        <template
+                          v-if="
+                            !(
+                              subItem.action &&
+                              subItem.action.length === 0 &&
+                              subItem.action_data &&
+                              subItem.action_data.length === 0
+                            )
+                          "
+                        >
+                          <div class="stitle">
+                            <span class="_h2">{{ subItem.menu_name }}</span>
+                            <el-radio-group
+                              style="margin: 0 0 0 20px"
+                              size="mini"
+                              :disabled="isDetail"
+                              v-if="
+                                subItem &&
+                                subItem.private &&
+                                subItem.private.length === 2
+                              "
+                              v-model="subItem.is_private_change"
+                            >
+                              <el-radio-button
+                                :disabled="isDetail"
+                                v-for="(radioN, ri) in subItem.private"
+                                :key="radioN.label + ri"
+                                :label="radioN.id"
+                                >{{ radioN.label }}</el-radio-button
+                              >
+                            </el-radio-group>
+                          </div>
+                          <div
+                            class="scheck"
+                            v-if="subItem.action && subItem.action.length > 0"
+                          >
+                            <div class="checkAll">
+                              <el-checkbox
+                                v-model="subItem.checkAll"
+                                :disabled="isDetail"
+                                :indeterminate="indeterminateCheck(subItem)"
+                                @change="
+                                  handleCheckAllChange(
+                                    $event,
+                                    index,
+                                    item,
+                                    subIndex
+                                  )
+                                "
+                                >功能全选</el-checkbox
+                              >
+                            </div>
+                            <div class="checkItem">
+                              <el-checkbox-group
+                                v-model="subItem.checkList"
+                                :disabled="isDetail"
+                                @change="
+                                  handleCheckedGroupChange(
+                                    $event,
+                                    index,
+                                    item,
+                                    subIndex
+                                  )
+                                "
+                              >
+                                <template v-for="children in subItem.action">
+                                  <el-checkbox
+                                    :disabled="isDetail"
+                                    :key="'checkItem' + children.id"
+                                    :label="children.id"
+                                    @change="
+                                      handleCheckedChange(
+                                        $event,
+                                        children.id,
+                                        index,
+                                        subIndex,
+                                        item
+                                      )
+                                    "
+                                    >{{ children.action_name }}</el-checkbox
+                                  >
+                                </template>
+                              </el-checkbox-group>
+                            </div>
+                          </div>
+                          <div
+                            class="sfield"
+                            v-if="
+                              subItem.action_data &&
+                              subItem.action_data.length > 0
+                            "
+                          >
+                            <div class="checkAll">
+                              <el-checkbox
+                                v-model="subItem.fieldAll"
+                                :disabled="isDetail"
+                                :indeterminate="indeterminateField(subItem)"
+                                @change="
+                                  handleFieldAllChange(
+                                    $event,
+                                    index,
+                                    item,
+                                    subIndex
+                                  )
+                                "
+                                >字段全选</el-checkbox
+                              >
+                            </div>
+                            <div class="checkItem">
+                              <el-checkbox-group
+                                v-model="subItem.fieldList"
+                                :disabled="isDetail"
+                                @change="
+                                  handleFieldGroupChange(
+                                    $event,
+                                    index,
+                                    item,
+                                    subIndex
+                                  )
+                                "
+                              >
+                                <template
+                                  v-for="children in subItem.action_data"
+                                >
+                                  <el-checkbox
+                                    :key="'FieldItem' + children.id"
+                                    :label="children.id"
+                                    :disabled="isDetail"
+                                    @change="
+                                      handleFieldChange(
+                                        $event,
+                                        children.id,
+                                        index,
+                                        subIndex,
+                                        item
+                                      )
+                                    "
+                                    >{{ children.field_name }}</el-checkbox
+                                  >
+                                </template>
+                              </el-checkbox-group>
+                            </div>
+                          </div>
+                        </template>
+                      </div>
+                    </div>
+                  </el-col>
+                </el-row>
+              </div>
+            </div>
+          </div>
+        </el-form>
+        <el-col :span="24" style="text-align: right">
+          <el-button
+            v-if="!isDetail"
+            type="primary"
+            :size="'mini'"
+            @click="submitForm"
+            >保 存
+          </el-button>
+          <el-button @click="showModelThis = false" :size="'mini'">{{
+            isDetail ? "关 闭" : "取 消"
+          }}</el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+  </el-dialog>
+</template>
+<script>
+import asyncRequest from "@/apis/service/interest/role";
+import roleLevel from "@/assets/js/roleLevel";
+import { isChinese, isEmoticon } from "@/utils/validate";
+import resToken from "@/mixins/resToken";
+export default {
+  name: "Role",
+  props: ["showModel", "id", "isDetail"],
+  mixins: [resToken],
+  data() {
+    const validatename = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("角色名称不能为空!"));
+      } else {
+        if (value.lenght < 2 || value.lenght > 10) {
+          callback(new Error("角色名称规则为2~10位汉字!"));
+        } else if (!isChinese(value)) {
+          callback(new Error("角色名称规则为2~10位汉字!"));
+        } else if (isEmoticon(value)) {
+          callback(new Error("角色名称规则为2~10位汉字!"));
+        } else {
+          callback();
+        }
+      }
+    };
+    return {
+      loading: false,
+      title: "添加角色",
+      private_data: [], //私有数据菜单ID
+      showModelThis: this.showModel,
+      roleLevel: roleLevel,
+      ruleForm: {
+        role_name: "",
+        level: "1",
+        private_field: [],
+      },
+      action_data: [], // 字段数据
+      action: [], // 功能数据
+      // 当前角色
+      roleActive: {
+        rules: [],
+      },
+      // 角色列表
+      roleList: [],
+      // 功能权限列表
+      ruleList: [],
+      dataList: [],
+      actionList: [],
+      rulesThis: this.rules,
+      rules: {
+        private_field: [
+          {
+            type: "array",
+            required: true,
+            message: "请选择关键字段权限",
+            trigger: "change",
+          },
+        ],
+        role_name: [
+          {
+            required: true,
+            validator: validatename,
+            trigger: "blur",
+          },
+        ],
+        level: [
+          { required: true, message: "请选择角色等级", trigger: "change" },
+        ],
+      },
+    };
+  },
+  computed: {
+    indeterminateCheck() {
+      return (item) => {
+        // 选中子节点的数量
+        const selectItemLength = item.action.filter(
+          (filitem) =>
+            item.checkList.findIndex((finditem) => finditem === filitem.id) > -1
+        ).length;
+        // 未选中子节点的数量
+        const noSlectItemLength = item.action.filter(
+          (filitem) =>
+            item.checkList.findIndex((finditem) => finditem === filitem.id) ==
+            -1
+        ).length;
+        // // 当前节点的index
+        // 存在选中子节点且存在未选中子节点为中间态
+        return selectItemLength > 0 && noSlectItemLength > 0;
+      };
+    },
+    indeterminateField() {
+      return (item) => {
+        // 选中子节点的数量
+        const selectItemLength = item.action_data.filter(
+          (filitem) =>
+            item.fieldList.findIndex((finditem) => finditem === filitem.id) > -1
+        ).length;
+        // 未选中子节点的数量
+        const noSlectItemLength = item.action_data.filter(
+          (filitem) =>
+            item.fieldList.findIndex((finditem) => finditem === filitem.id) ==
+            -1
+        ).length;
+        // // 当前节点的index
+        // 存在选中子节点且存在未选中子节点为中间态
+        return selectItemLength > 0 && noSlectItemLength > 0;
+      };
+    },
+  },
+  watch: {
+    showModel: function (val) {
+      this.showModelThis = val;
+      if (val) {
+        this.initForm();
+      }
+    },
+    showModelThis(val) {
+      if (!val) {
+        this.$emit("cancel");
+      }
+    },
+  },
+  methods: {
+    // 全选/全不选
+    handleCheckAllChange(checkAll, index, item, subIndex) {
+      this.actionList[index].child[subIndex].checkAll = checkAll;
+      this.$set(this.actionList, index, item);
+      this.actionList[index].child[subIndex].action.forEach((element) => {
+        const findindex = this.actionList[index].child[
+          subIndex
+        ].checkList.findIndex((findItem) => findItem === element.id);
+        if (checkAll && findindex == -1) {
+          this.actionList[index].child[subIndex].checkList.push(element.id);
+        } else if (!checkAll && findindex > -1) {
+          this.actionList[index].child[subIndex].checkList.splice(findindex, 1);
+        }
+      });
+    },
+    // 全选/全不选
+    handleFieldAllChange(fieldAll, index, item, subIndex) {
+      this.actionList[index].child[subIndex].fieldAll = fieldAll;
+      this.$set(this.actionList, index, item);
+      this.actionList[index].child[subIndex].action_data.forEach((element) => {
+        const findindex = this.actionList[index].child[
+          subIndex
+        ].fieldList.findIndex((findItem) => findItem === element.id);
+        if (fieldAll && findindex == -1) {
+          this.actionList[index].child[subIndex].fieldList.push(element.id);
+        } else if (!fieldAll && findindex > -1) {
+          this.actionList[index].child[subIndex].fieldList.splice(findindex, 1);
+        }
+      });
+    },
+    // 复选框组内的选中/不选中
+    handleCheckedGroupChange(event, index, item, subIndex) {
+      this.actionList[index].child[subIndex].checkAll = this.actionList[
+        index
+      ].child[subIndex].action.every(
+        (evitem) =>
+          this.actionList[index].child[subIndex].checkList.findIndex(
+            (finditem) => finditem === evitem.id
+          ) > -1
+      );
+      this.$set(this.actionList, index, item);
+    },
+    // 复选框组内的选中/不选中
+    handleFieldGroupChange(event, index, item, subIndex) {
+      this.actionList[index].child[subIndex].fieldAll = this.actionList[
+        index
+      ].child[subIndex].action_data.every(
+        (evitem) =>
+          this.actionList[index].child[subIndex].fieldList.findIndex(
+            (finditem) => finditem === evitem.id
+          ) > -1
+      );
+      this.$set(this.actionList, index, item);
+    },
+
+    // 单项复选框选中/不选中
+
+    handleCheckedChange(checked, id, index, subIndex, item) {
+      // console.log(checked, id, index, subIndex);
+      if (checked) {
+        // 选中时检查pid的选中状态
+        this.actionList[index].child[subIndex].checkList.indexOf(id) == -1 &&
+          this.actionList[index].child[subIndex].checkList.push(id);
+      } else {
+        const find = this.actionList[index].child[subIndex].checkList.findIndex(
+          (e) => e == id
+        );
+        if (find > -1) {
+          this.actionList[index].child[subIndex].checkList.splice(find, 1);
+        }
+        this.actionList[index].child[subIndex].checkAll = false;
+      }
+      this.$set(this.actionList, index, item);
+    },
+    // 单项复选框选中/不选中
+    handleFieldChange(checked, id, index, subIndex, item) {
+      // console.log(checked, id, index, subIndex);
+      if (checked) {
+        // 选中时检查pid的选中状态
+        this.actionList[index].child[subIndex].fieldList.indexOf(id) == -1 &&
+          this.actionList[index].child[subIndex].fieldList.push(id);
+      } else {
+        const find = this.actionList[index].child[subIndex].fieldList.findIndex(
+          (e) => e == id
+        );
+        if (find > -1) {
+          this.actionList[index].child[subIndex].fieldList.splice(find, 1);
+        }
+        this.actionList[index].child[subIndex].fieldAll = false;
+      }
+      this.$set(this.actionList, index, item);
+      // console.log(this.actionList[index].child[subIndex]);
+    },
+
+    async initForm() {
+      this.loading = true;
+      if (this.id === "add") {
+        this.title = "添加角色";
+        // this.ruleForm.isAdmin = 0;
+        this.rulesThis = this.rules;
+        await this.resetForm();
+        await this.initActionList();
+        this.loading = false;
+      } else {
+        if (this.isDetail) {
+          this.title = "角色";
+          this.rulesThis = {};
+        } else {
+          this.title = "修改角色";
+          this.rulesThis = this.rules;
+        }
+        await this.resetForm();
+        await this.initActionList();
+        await this.initData();
+        this.loading = false;
+      }
+    },
+    async initData() {
+      const res = await asyncRequest.detail({ roleid: this.id });
+      if (res && res.code === 0 && res.data) {
+        let resD = res.data;
+        resD.private_field =
+          resD.private_field === "" ? [] : resD.private_field;
+        this.ruleForm = resD;
+
+        if (resD.action && resD.action.length > 0) {
+          this.action = resD.action;
+        } else {
+          this.action = [];
+        }
+        if (resD.action_data && resD.action_data.length > 0) {
+          this.action_data = resD.action_data;
+        } else {
+          this.action_data = [];
+        }
+        if (resD.private_data === "") {
+          resD.private_data = [];
+        }
+        if (resD.private_data && resD.private_data.length > 0) {
+          this.private_data = resD.private_data;
+        } else {
+          this.private_data = [];
+        }
+        const arr = JSON.parse(JSON.stringify(this.actionList));
+        arr.map((x) => {
+          if (x.child && x.child.length > 0) {
+            x.child.map((y) => {
+              if (y.action && y.action.length > 0) {
+                y.action.map((z) => {
+                  const Aindex = this.action.findIndex((a) => a === z.id);
+                  if (Aindex !== -1) {
+                    y.checkList.push(this.action[Aindex]);
+                  }
+                  return z;
+                });
+                if (y.action.length === y.checkList.length) {
+                  y.checkAll = true;
+                }
+              }
+              if (y.action_data && y.action_data.length > 0) {
+                y.action_data.map((z) => {
+                  const Bindex = this.action_data.findIndex((a) => a === z.id);
+                  if (Bindex !== -1) {
+                    y.fieldList.push(this.action_data[Bindex]);
+                  }
+                  return z;
+                });
+                if (y.action_data.length === y.fieldList.length) {
+                  y.fieldAll = true;
+                }
+              }
+              if (y.private && y.private.length === 2) {
+                let Cindex = this.private_data.findIndex((a) => a === y.id);
+                if (Cindex !== -1) {
+                  y.is_private_change = "1";
+                } else {
+                  y.is_private_change = "0";
+                }
+              } else {
+                y.is_private_change = "0";
+              }
+              return y;
+            });
+          }
+          return x;
+        });
+
+        this.actionList = arr;
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        await this.logout();
+      } else {
+        this.$message.warning(res.message);
+      }
+    },
+    async initActionList() {
+      const res = await asyncRequest.actionList({});
+      if (res && res.code === 0) {
+        const list = res.data;
+        let arr = list.filter((item) => item.child && item.child.length > 0);
+        arr = arr.map((x) => {
+          x.child.map((y) => {
+            y.checkAll = false;
+            y.checkList = [];
+            y.fieldAll = false;
+            y.fieldList = [];
+            y.is_private_change = "0";
+            if (y.is_private === "0") {
+              y.private = [];
+            } else {
+              y.private = [
+                {
+                  id: "0",
+                  label: "公有数据",
+                },
+                {
+                  id: "1",
+                  label: "私有数据",
+                },
+              ];
+            }
+            return y;
+          });
+          return x;
+        });
+
+        this.actionList = arr;
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        await this.logout();
+      } else {
+        this.$message.warning(res.message);
+      }
+    },
+    async resetForm() {
+      // 重置
+      await this.$nextTick(() => {
+        if (this.$refs.ruleForm) {
+          this.$refs.ruleForm.resetFields();
+          this.$refs.ruleForm.clearValidate();
+          this.ruleForm = {
+            role_name: "",
+            private_field: [],
+            level: "1",
+          };
+        }
+      });
+    },
+    async submitForm() {
+      await this.$refs.ruleForm.validate(async (valid) => {
+        if (valid) {
+          if (this.loading) {
+            return;
+          }
+          this.action_data = []; // 字段数据
+          this.action = []; // 功能数据
+          let arr = [];
+          this.actionList.forEach((x) => {
+            x.child.forEach((y) => {
+              this.action_data.push(...y.fieldList);
+              this.action.push(...y.checkList);
+              if (y.is_private_change === "1") {
+                arr.push(y.id);
+              }
+            });
+          });
+          // this.action_data.length === 0 ||和字段
+          if (this.action.length === 0) {
+            this.$message.warning("请选择功能!");
+          } else {
+            this.loading = true;
+            const model = {
+              roleid: this.id,
+              role_name: this.ruleForm.role_name,
+              private_field: JSON.parse(
+                JSON.stringify(this.ruleForm.private_field)
+              ),
+              level: this.ruleForm.level,
+              action: this.action,
+              action_data: this.action_data,
+              private_data: arr,
+            };
+            console.log(this.ruleForm.private_field);
+            console.log(model);
+            let res = {};
+            if (this.id === "add") {
+              delete model["roleid"];
+              res = await asyncRequest.add(model);
+            } else {
+              res = await asyncRequest.update(model);
+            }
+            this.loading = false;
+            if (res && res.code === 0) {
+              const title = this.id === "add" ? "添加成功" : "修改成功";
+              this.$notify.success({
+                title,
+                message: "",
+              });
+              this.showModelThis = false;
+              // 刷新
+              this.$emit("refresh");
+            } else if (res && res.code >= 100 && res.code <= 104) {
+              await this.logout();
+            } else {
+              this.$message.warning(res.message);
+            }
+          }
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+  },
+};
+</script>
+
+   <style lang="scss" scoped>
+.role {
+  .quanxian-main {
+    width: 100%;
+    display: flex;
+    .quanxian-title {
+      width: 84px;
+      position: relative;
+      padding: 8px 0 0 7px;
+    }
+
+    .rule-view {
+      width: calc(100% - 84px);
+      position: relative;
+      height: 550px;
+      overflow-y: scroll;
+      border-top: 1px solid #dfe6ec;
+      border-left: 1px solid #dfe6ec;
+      // padding: 0 0 0 16px;
+      .ffff {
+        width: 100%;
+        display: flex;
+        align-items: stretch;
+        .ftitle {
+          width: 110px;
+          text-align: center;
+          border-right: 1px solid #dfe6ec;
+          border-bottom: 1px solid #dfe6ec;
+          padding: 12px 14px;
+          display: flex;
+          align-items: center;
+          span {
+            display: inline-block;
+            width: 100%;
+            font-size: 17px;
+            text-align: center;
+            color: #97a8be;
+          }
+        }
+        .fbody {
+          width: calc(100% - 110px);
+          .fbody-item {
+            border-right: 1px solid #dfe6ec;
+            border-bottom: 1px solid #dfe6ec;
+
+            .stitle {
+              padding: 18px 18px 12px 18px;
+              border-bottom: 1px dashed #dfe6ec;
+              font-size: 14px;
+              color: #97a8be;
+              ._h2 {
+                display: inline-block;
+                // width: 100px;
+              }
+            }
+            .scheck {
+              padding: 15px 0 10px 0;
+              display: flex;
+              width: 100%;
+              .checkAll {
+                width: 140px;
+                text-align: right;
+                padding: 0 35px 0 0;
+              }
+              .checkItem {
+                width: calc(100% - 140px);
+              }
+            }
+            .sfield {
+              padding: 0 0 10px 0;
+              display: flex;
+              width: 100%;
+              .checkAll {
+                width: 140px;
+                text-align: right;
+                padding: 0 35px 0 0;
+              }
+              .checkItem {
+                width: calc(100% - 140px);
+              }
+            }
+          }
+        }
+      }
+      // .rule-list {
+      //   height: 100%;
+      //   overflow-y: auto;
+      //   padding: 0 0 80px 0;
+      //   .rule-title {
+      //     .title {
+      //       font-size: 20px;
+      //       color: #333;
+      //     }
+      //     .desc {
+      //       margin: 10px 0;
+      //       font-size: 12px;
+      //       color: #999;
+      //     }
+      //   }
+      //   .rule-item {
+      //     .title {
+      //       margin: 30px 30px 10px 0;
+      //       font-size: 18px;
+      //       padding-bottom: 12px;
+      //       border-bottom: 1px solid #eee;
+      //       color: #333;
+      //       .el-checkbox {
+      //         margin-left: 10px;
+      //       }
+      //     }
+      //     .el-checkbox-group {
+      //       margin: 10px 30px 30px 0;
+      //       .el-checkbox {
+      //         line-height: 30px;
+      //       }
+      //       .children-checkbox-hr {
+      //         margin: 8px 0;
+      //         border: none;
+      //         border-top: 2px dotted #eee;
+      //       }
+      //     }
+      //   }
+      // }
+    }
+  }
+}
+</style>

+ 392 - 0
src/views/interest/role-origin/index.vue

@@ -0,0 +1,392 @@
+<template>
+  <div class="role pagePadding">
+    <ex-table
+      v-loading="loading"
+      v-if=" powers.some((i) => i == '001')"
+      :table="table"
+      :data="tableData"
+      :columns="columns"
+      :page="pageInfo"
+      :size="size"
+      @page-curr-change="handlePageChange"
+      @page-size-change="handleSizeChange"
+      @screen-reset="
+        pageInfo.curr = 1;
+        searchList();
+      "
+      @screen-submit="
+        pageInfo.curr = 1;
+        searchList();
+      "
+    >
+      <template #table-header="{}">
+        <div style="width: 100%">
+          <el-row>
+            <el-col :span="24" style="padding: 0 0 0 80px">
+              <el-col :span="3" style="width: 120px">
+                <el-select
+                  v-model="parmValue.status"
+                  filterable
+                  clearable
+                  :size="searchSize"
+                  placeholder="角色状态"
+                  style="width: 100%"
+                  @change="
+                    pageInfo.curr = 1;
+                    parmValue.page = 1;
+                    searchList();
+                  "
+                >
+                  <el-option
+                    v-for="item in statusList"
+                    :key="'status' + item.code"
+                    :label="item.name"
+                    :value="item.code"
+                  />
+                </el-select>
+              </el-col>
+
+              <el-col :span="3" style="width: 130px; padding: 0 0 0 10px">
+                <el-select
+                  :size="searchSize"
+                  v-model="parmValue.level"
+                  filterable
+                  placeholder="角色等级"
+                  style="width: 100%"
+                  @change="
+                    pageInfo.curr = 1;
+                    parmValue.page = 1;
+                    searchList();
+                  "
+                >
+                  <el-option
+                    v-for="item in roleLevel"
+                    :key="'ruleid' + item.code"
+                    :label="item.name"
+                    :value="item.code"
+                  />
+                </el-select>
+              </el-col>
+              <el-col :span="3" style="width: 150px; padding: 0 0 0 10px">
+                <el-input
+                  :size="searchSize"
+                  v-model="parmValue.role_name"
+                  :maxlength="40"
+                  placeholder="角色名称"
+                />
+              </el-col>
+
+              <el-col :span="3" style="width: 54px">
+                <el-button
+                  type="primary"
+                  class="fr"
+                  :size="searchSize"
+                  icon="el-icon-search"
+                  @click="searchList"
+                />
+              </el-col>
+              <el-col
+                :span="3"
+                style="width: 66px"
+              >
+                <el-button
+                  type="warning"
+                  class="fr"
+                  :size="searchSize"
+                  @click="restSearch"
+                >
+                  重置
+                </el-button>
+              </el-col>
+              <el-col
+                :span="3"
+                style="width: 66px; float: right"
+              >
+                <el-button
+                  type="primary"
+                  :size="searchSize"
+                  style="float: right"
+                  @click="searchList"
+                >
+                  刷新
+                </el-button></el-col
+              >
+              <el-col
+                :span="3"
+                style="width: 66px; float: right"
+                v-if="powers.some((i) => i == '003')"
+              >
+                <el-button
+                  :size="searchSize"
+                  type="success"
+                  style="float: right"
+                  @click="openModal('add', false)"
+                >
+                  添加
+                </el-button>
+              </el-col>
+            </el-col>
+          </el-row>
+        </div>
+      </template>
+      <template #status="{ scope }">
+        <el-tag
+          :size="tablebtnSize"
+          :type="scope.row.status == '0' ? 'warning' : ''"
+          v-text="
+            (statusOptions.find((item) => item.id == scope.row.status) || {})
+              .label || '--'
+          "
+        ></el-tag>
+      </template>
+
+      <template #operation="{ scope }">
+        <el-tooltip
+          v-if="powers.some((i) => i == '007')"
+          effect="dark"
+          content="详情"
+          placement="top"
+        >
+          <i
+            class="el-icon-view tb-icon"
+            @click="openModal(scope.row.id, true)"
+          ></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="powers.some((i) => i == '005')"
+          effect="dark"
+          content="修改"
+          placement="top"
+        >
+          <i
+            class="el-icon-edit tb-icon"
+            @click="openModal(scope.row.id, false)"
+          ></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="
+            powers.some((i) => i == '004') && scope.row.status === '1'
+          "
+          effect="dark"
+          content="禁用"
+          placement="top"
+        >
+          <i
+            class="el-icon-video-pause tb-icon"
+            @click="changeStatus(scope.row.id, scope.row.status)"
+          ></i>
+        </el-tooltip>
+        <el-tooltip
+          v-if="
+            powers.some((i) => i == '004') && scope.row.status === '0'
+          "
+          effect="dark"
+          content="启用"
+          placement="top"
+        >
+          <i
+            class="el-icon-video-play tb-icon"
+            @click="changeStatus(scope.row.id, scope.row.status)"
+          ></i>
+        </el-tooltip>
+      </template>
+    </ex-table>
+    <no-auth v-else></no-auth>
+    <!-- 弹窗 新增/修改 -->
+    <add-edit
+      :id="modelId"
+      :show-model="showModel"
+      :is-detail="isDetail"
+      @refresh="searchList"
+      @cancel="showModel = false"
+    />
+  </div>
+</template>
+<script>
+import addEdit from "./addEdit";
+import asyncRequest from "@/apis/service/interest/role";
+import {statusList} from "@/assets/js/statusList";
+import roleLevel from "@/assets/js/roleLevel";
+import mixinPage from "@/mixins/elPaginationHandle";
+import resToken from "@/mixins/resToken";
+import { mapGetters } from "vuex";
+export default {
+  name: "role",
+  mixins: [mixinPage, resToken],
+  components: {
+    addEdit,
+  },
+  computed: {
+    //组件SIZE设置
+    ...mapGetters(["tablebtnSize", "searchSize", "size"]),
+    powers() {
+      const tran =
+        this.$store.getters.btnList.find((i) => i.menu_route == "role") ||
+        {};
+      const { action } = tran ?? {};
+      return action ?? [];
+    },
+  },
+  data() {
+    return {
+      statusList: statusList,
+      roleLevel: roleLevel,
+      loading: true,
+      showModel: false,
+      isDetail: false,
+      modelId: 0,
+      parmValue: {
+        loginName: "", // 账户
+        fullName: "", // 姓名
+        type: 2, // 用户类型(1运营人员 2物业人员)
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+      },
+      // 状态
+      statusOptions: [
+        { id: 0, label: "禁用" },
+        { id: 1, label: "启用" },
+      ],
+      // 角色等级
+      authOptions: [
+        { id: "1", label: "管理员" },
+        { id: "2", label: "非管理员" },
+      ],
+      // 表格 - 数据
+      tableData: [],
+      // 表格 - 参数
+      table: {
+        stripe: true,
+        border: true,
+        _defaultHeader_: ["setcol"],
+      },
+      // 表格 - 分页
+      pageInfo: {
+        size: 15,
+        curr: 1,
+        total: 0,
+      },
+      // 表格 - 列参数
+      columns: [
+        {
+          prop: "role_name",
+          label: "角色名称",
+        },
+        {
+          prop: "level",
+          label: "角色等级",
+          _format_: (d) => {
+            return (
+              this.authOptions.find((item) => {
+                return item.id == d.level;
+              }) || {}
+            ).label;
+          },
+        },
+
+        {
+          prop: "addtime",
+          label: "创建时间",
+          sortable: true,
+        },
+        {
+          prop: "status",
+          label: "状态",
+          sortable: true,
+          _slot_: "status",
+        },
+        {
+          prop: "",
+          label: "操作",
+          fixed: "right",
+          _noset_: true,
+          _slot_: "operation",
+        },
+      ],
+    };
+  },
+  mounted() {
+    this.searchList();
+  },
+  methods: {
+    restSearch() {
+      // 表格 - 分页
+      this.pageInfo = {
+        size: 15,
+        curr: 1,
+        total: 0,
+      };
+      this.parmValue = {
+        status: "", // 账户
+        level: "", // 姓名
+        role_name: "",
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+      };
+      this.searchList();
+    },
+    // 新建/编辑/详情
+    openModal(id, isDetail) {
+      this.showModel = true;
+      this.modelId = id;
+      this.isDetail = isDetail;
+    },
+    /**
+     * 启用/禁用
+     * @param {String} id id
+     * @param {String} status 0-禁用 1-启用
+     */
+    async changeStatus(id, status) {
+      await this.$confirm(`确定要改为${status === "1" ? "禁用" : "启用"}?`, {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(async () => {
+          const model = {
+            roleid: id,
+            status: status === "1" ? "0" : "1",
+          };
+          const res = await asyncRequest.status(model);
+          if (res && res.code === 0) {
+            this.$notify.success({
+              title: "状态修改成功",
+              message: "",
+            });
+            this.searchList();
+          } else if (res && res.code >= 100 && res.code <= 104) {
+            await this.logout();
+          } else {
+            this.$message.warning(res.message);
+          }
+        })
+        .catch(() => {
+          console.log("取消");
+        });
+    },
+
+    // 刷新表格
+    async searchList() {
+      this.loading = true;
+      const res = await asyncRequest.list(this.parmValue);
+      if (res && res.code === 0 && res.data) {
+        this.tableData = res.data.list;
+        // this.tableData.map((v1) => {
+        //   v1.addtime = v1.addtime.replace(".000", "");
+        //   return v1;
+        // });
+        this.pageInfo.total = Number(res.data.count);
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        await this.logout();
+      } else {
+        this.tableData = [];
+        this.pageInfo.total = 0;
+      }
+      this.loading = false;
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 0 - 0
src/views/interest/role-origin/角色管理


+ 32 - 21
src/views/interest/role/addEdit.vue

@@ -24,7 +24,7 @@
           label-width="80px"
           class="demo-ruleForm"
         >
-          <el-col :span="9">
+          <el-col :span="8">
             <el-form-item label="角色名称" prop="role_name">
               <el-input
                 v-model="ruleForm.role_name"
@@ -34,24 +34,23 @@
               />
             </el-form-item>
           </el-col>
-          <el-col :span="9">
+          <el-col :span="8">
             <el-form-item
-              label="关键字段权限"
-              prop="private_field"
-              label-width="110px"
+              label="是否允许查看价格"
+              prop="is_allow_see_price"
+              label-width="140px"
             >
-              <el-checkbox-group
-                v-model="ruleForm.private_field"
+              <el-select
+                v-model="ruleForm.is_allow_see_price"
                 :disabled="isDetail"
-                placeholder="关键字段权限"
+                placeholder="是否允许查看价格"
               >
-                <el-checkbox :label="'1'">成本价</el-checkbox>
-                <el-checkbox :label="'2'">销售价</el-checkbox>
-                <el-checkbox :label="'3'">毛利率</el-checkbox>
-              </el-checkbox-group>
+                <el-option :label="'允许'" :value="1" />
+                <el-option :label="'不允许'" :value="0" />
+              </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="6">
+          <el-col :span="8">
             <el-form-item label="角色等级" prop="level">
               <el-select
                 v-model="ruleForm.level"
@@ -277,6 +276,7 @@ import asyncRequest from "@/apis/service/interest/role";
 import roleLevel from "@/assets/js/roleLevel";
 import { isChinese, isEmoticon } from "@/utils/validate";
 import resToken from "@/mixins/resToken";
+import { mapState } from "vuex";
 export default {
   name: "Role",
   props: ["showModel", "id", "isDetail"],
@@ -322,11 +322,10 @@ export default {
       actionList: [],
       rulesThis: this.rules,
       rules: {
-        private_field: [
+        is_allow_see_price: [
           {
-            type: "array",
             required: true,
-            message: "请选择关键字段权限",
+            message: "选择是否允许查看价格",
             trigger: "change",
           },
         ],
@@ -344,6 +343,9 @@ export default {
     };
   },
   computed: {
+    ...mapState({
+      currentCompany: (state) => state.user.currentCompany
+    }),
     indeterminateCheck() {
       return (item) => {
         // 选中子节点的数量
@@ -642,6 +644,11 @@ export default {
       });
     },
     async submitForm() {
+      if(!this.currentCompany){
+        this.$message.warning('请在右上角选择一家公司');
+        return
+      }
+
       await this.$refs.ruleForm.validate(async (valid) => {
         if (valid) {
           if (this.loading) {
@@ -664,24 +671,28 @@ export default {
             this.$message.warning("请选择功能!");
           } else {
             this.loading = true;
+            
             const model = {
               roleid: this.id,
               role_name: this.ruleForm.role_name,
-              private_field: JSON.parse(
-                JSON.stringify(this.ruleForm.private_field)
-              ),
+              // private_field: JSON.parse(
+              //   JSON.stringify(this.ruleForm.private_field)
+              // ),
+              is_allow_see_price:this.ruleForm.is_allow_see_price,
               level: this.ruleForm.level,
               action: this.action,
               action_data: this.action_data,
               private_data: arr,
             };
-            console.log(this.ruleForm.private_field);
-            console.log(model);
+
+
             let res = {};
             if (this.id === "add") {
               delete model["roleid"];
+              model.companyNo = this.currentCompany;
               res = await asyncRequest.add(model);
             } else {
+              model.companyNo = this.ruleForm.companyNo;
               res = await asyncRequest.update(model);
             }
             this.loading = false;

+ 22 - 6
src/views/interest/role/index.vue

@@ -207,12 +207,13 @@ import addEdit from "./addEdit";
 import asyncRequest from "@/apis/service/interest/role";
 import {statusList} from "@/assets/js/statusList";
 import roleLevel from "@/assets/js/roleLevel";
-import mixinPage from "@/mixins/elPaginationHandle";
+import mixinPage from "@/mixins/elPaginationHandle";``
 import resToken from "@/mixins/resToken";
+import reloadData from "@/mixins/reloadData";
 import { mapGetters } from "vuex";
 export default {
   name: "role",
-  mixins: [mixinPage, resToken],
+  mixins: [mixinPage, resToken,reloadData(ctx => ctx.searchList())],
   components: {
     addEdit,
   },
@@ -220,9 +221,8 @@ export default {
     //组件SIZE设置
     ...mapGetters(["tablebtnSize", "searchSize", "size"]),
     powers() {
-      const tran =
-        this.$store.getters.btnList.find((i) => i.menu_route == "role") ||
-        {};
+      const { btnList } = this.$store.getters;
+      const tran = btnList.find((i) => i.menu_route == "role") || {};
       const { action } = tran ?? {};
       return action ?? [];
     },
@@ -283,7 +283,14 @@ export default {
             ).label;
           },
         },
-
+        {
+          prop:'companyNo',
+          label:'公司编号'
+        },
+        {
+          prop:'companyName',
+          label:'公司名称'
+        },
         {
           prop: "addtime",
           label: "创建时间",
@@ -299,6 +306,7 @@ export default {
           prop: "",
           label: "操作",
           fixed: "right",
+          width:'85px',
           _noset_: true,
           _slot_: "operation",
         },
@@ -327,6 +335,11 @@ export default {
     },
     // 新建/编辑/详情
     openModal(id, isDetail) {
+      if(!this.currentCompany){
+        this.$message.warning('请在右上角选择一家公司');
+        return
+      }
+
       this.showModel = true;
       this.modelId = id;
       this.isDetail = isDetail;
@@ -368,6 +381,9 @@ export default {
     // 刷新表格
     async searchList() {
       this.loading = true;
+      const companyNo = this.currentCompany;
+      this.parmValue.companyNo = companyNo;
+
       const res = await asyncRequest.list(this.parmValue);
       if (res && res.code === 0 && res.data) {
         this.tableData = res.data.list;

+ 0 - 0
src/views/interest/role/公司角色管理


+ 2 - 2
src/views/login/index.vue

@@ -149,8 +149,8 @@ export default {
       loginBeian: urlConfig.loginBeian,
       loginBeianUrl: urlConfig.loginBeianUrl,
       loginForm: {
-        username: "",
-        password: "",
+        username: "17531816886",
+        password: "dingding123",
       },
       loginRules: {
         username: [{ required: true, trigger: "blur", validator: validateUsername }],

+ 0 - 277
src/views/system/expressSettings/index.vue

@@ -1,277 +0,0 @@
-<template>
-  <div class="parameter pagePadding">
-    <ex-table
-      v-loading="loading"
-      v-if=" powers.some((i) => i == '001')"
-      :table="table"
-      :data="tableData"
-      :columns="columns"
-      :page="pageInfo"
-      :size="size"
-      @page-curr-change="handlePageChange"
-      @page-size-change="handleSizeChange"
-      @screen-reset="
-        pageInfo.curr = 1;
-        parmValue.page = 1;
-        searchList();
-      "
-      @screen-submit="
-        pageInfo.curr = 1;
-        parmValue.page = 1;
-        searchList();
-      "
-    >
-      <template #table-header="{}">
-        <div style="width: 100%">
-          <el-row style="padding: 0 0 10px 80px">
-            <el-col :span="4" style="width: 160px;margin-right:10px">
-              <el-select
-                v-model="parmValue.status"
-                clearable
-                :size="searchSize"
-                placeholder="快递属性"
-                style="width: 100%"
-                @change="
-                  pageInfo.curr = 1;
-                  parmValue.page = 1;
-                  searchList();
-                "
-              >
-                <el-option
-                  v-for="item in statusList"
-                  :key="'status' + item.value"
-                  :label="item.label"
-                  :value="item.value"
-                />
-              </el-select>
-            </el-col>
-
-            <el-col :span="4" style="margin-right:10px">
-              <el-input
-                :size="searchSize"
-                placeholder="快递名称"
-                @blur="pageInfo.curr = 1;
-                  parmValue.page = 1;
-                  searchList();"
-              />
-            </el-col>
-
-            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
-              <el-button type="primary" :size="searchSize" @click="searchList">刷新</el-button>
-            </el-col>
-            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
-              <el-button type="warning" :size="searchSize" @click="restSearch">重置</el-button>
-            </el-col>
-          </el-row>
-        </div>
-      </template>
-      <template #status="{ scope }">
-        <el-tag
-          :size="tablebtnSize"
-          :type="scope.row.status == '0' ? 'warning' : ''"
-          v-text="
-            (statusOptions.find((item) => item.id == scope.row.status) || {})
-              .label || '--'
-          "
-        ></el-tag>
-      </template>
-
-      <template #operation="{ scope }">
-        <el-tooltip
-          v-if="
-            powers.some((i) => i == '004') && scope.row.status === '1'
-          "
-          effect="dark"
-          content="禁用"
-          placement="top"
-        >
-          <i
-            class="el-icon-video-pause tb-icon"
-            @click="changeStatus(scope.row.id, scope.row.status)"
-          ></i>
-        </el-tooltip>
-        <el-tooltip
-          v-if="
-            powers.some((i) => i == '004') && scope.row.status === '0'
-          "
-          effect="dark"
-          content="启用"
-          placement="top"
-        >
-          <i
-            class="el-icon-video-play tb-icon"
-            @click="changeStatus(scope.row.id, scope.row.status)"
-          ></i>
-        </el-tooltip>
-      </template>
-    </ex-table>
-    <no-auth v-else></no-auth>
-  </div>
-</template>
-<script>
-import asyncRequest from "@/apis/service/system/expressSettings";
-import roleLevel from "@/assets/js/roleLevel";
-import mixinPage from "@/mixins/elPaginationHandle";
-import { mapGetters } from "vuex";
-import resToken from "@/mixins/resToken";
-import { actionTypes } from "@/utils/actionType";
-export default {
-  name: "parameter",
-  mixins: [mixinPage, resToken],
-  computed: {
-    //组件SIZE设置
-    ...mapGetters(["tablebtnSize", "searchSize", "size"]),
-    powers() {
-      const tran =
-        this.$store.getters.btnList.find(
-          item => item.menu_route == "expressSettings"
-        ) || {};
-      const { action } = tran ?? {};
-      return action ?? [];
-    }
-  },
-  data() {
-    return {
-      actionTypes,
-      roleLevel: roleLevel,
-      loading: true,
-      showModel: false,
-      type: "",
-      statusList: [
-        {
-          label: "启用",
-          value: "1"
-        },
-        {
-          label: "禁用",
-          value: "0"
-        }
-      ],
-      sitem: {},
-      parmValue: {
-        page: 1, // 页码
-        size: 15 // 每页显示条数
-      },
-      // 状态
-      statusOptions: [
-        { id: "0", label: "禁用" },
-        { id: "1", label: "启用" }
-      ],
-      // 表格 - 数据
-      tableData: [],
-      // 表格 - 参数
-      table: {
-        stripe: true,
-        border: true,
-        _defaultHeader_: ["setcol"]
-      },
-      // 表格 - 分页
-      pageInfo: {
-        size: 15,
-        curr: 1,
-        total: 0
-      },
-      // 表格 - 列参数
-      columns: [
-        {
-          prop: "id",
-          label: "快递类型名称"
-        },
-        {
-          prop: "parameter_name",
-          label: "快递名称"
-        },
-        {
-          prop: "parameter_name",
-          label: "快递简称"
-        },
-        {
-          prop: "status",
-          label: "快递英文",
-          _slot_: "status"
-        },
-        {
-          prop: "",
-          label: "操作",
-          fixed: "right",
-          _noset_: true,
-          _slot_: "operation"
-        }
-      ]
-    };
-  },
-  mounted() {
-    this.searchList();
-  },
-  methods: {
-    restSearch() {
-      // 表格 - 分页
-      this.pageInfo = {
-        size: 15,
-        curr: 1,
-        total: 0
-      };
-      this.parmValue = {
-        page: 1, // 页码
-        size: 15, // 每页显示条数
-      };
-      this.searchList();
-    },
-    /**
-     * 启用/禁用
-     * @param {String} id id
-     * @param {String} status 0-禁用 1-启用
-     */
-    async changeStatus(id, status) {
-      await this.$confirm(`确定要改为${status === "1" ? "禁用" : "启用"}?`, {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      })
-        .then(async () => {
-          this.loading = true;
-          const model = {
-            id: id,
-            status: status === "1" ? "0" : "1"
-          };
-          const res = await asyncRequest.status(model);
-          if (res && res.code === 0) {
-            this.loading = false;
-            this.$notify.success({
-              title: "状态修改成功!",
-              message: ""
-            });
-            await this.searchList();
-          } else if (res && res.code >= 100 && res.code <= 104) {
-            await this.logout();
-          } else {
-            this.loading = false;
-            this.$message.warning(res.message);
-          }
-        })
-        .catch(() => {
-          console.log("取消");
-        });
-    },
-    // 刷新表格
-    async searchList() {
-      this.loading = true;
-      const res = await asyncRequest.list(this.parmValue);
-      if (res && res.code === 0 && res.data) {
-        //todo:可能是list下
-        this.tableData = res.data;
-        this.pageInfo.total = Number(res.data.count);
-      } else if (res && res.code >= 100 && res.code <= 104) {
-        await this.logout();
-      } else {
-        this.tableData = [];
-        this.pageInfo.total = 0;
-      }
-      this.loading = false;
-    }
-  }
-};
-</script>
-
-<style lang="scss" scoped>
-</style>

+ 5 - 6
src/views/system/menuOperator/index.vue

@@ -64,8 +64,9 @@
 import mixinPage from "@/mixins/elPaginationHandle";
 import asyncRequest from "@/apis/service/system/menu";
 import addEdit from "@/views/system/menuOperator/addEdit";
-import { mapGetters } from "vuex";
 import resToken from "@/mixins/resToken";
+import { mapGetters } from "vuex";
+
 export default {
   name: "MenuOperator",
   components: {
@@ -75,10 +76,8 @@ export default {
   computed: {
     ...mapGetters(["tablebtnSize", "searchSize", "size"]),
     powers() {
-      const tran =
-        this.$store.getters.btnList.find(
-          (item) => item.menu_route == "menuOperator"
-        ) || {};
+      const { btnList } = this.$store.getters;
+      const tran = btnList.find((item) => item.menu_route == "menuOperator") || {};
       const { action } = tran ?? {};
       return action ?? [];
     },
@@ -328,4 +327,4 @@ export default {
     }
   }
 }
-</style>
+</style>

+ 272 - 77
src/views/system/operationAccount/addEdit.vue

@@ -4,8 +4,8 @@
     :title="title"
     :center="true"
     align="left"
-    top="18vh"
-    width="500px"
+    top="10vh"
+    width="750px"
     :close-on-click-modal="false"
     :visible.sync="showModelThis"
     element-loading-text="拼命加载中"
@@ -13,69 +13,158 @@
     element-loading-background="rgba(0, 0, 0, 0.8)"
     @close="showModelThis = false"
   >
-    <el-card style="margin: -20px 0 0 0">
+    <el-card style="margin-top: -20px">
       <el-row :gutter="10">
         <el-col :span="24">
           <el-form
             ref="ruleForm"
             :model="ruleForm"
             status-icon
+            :size="'mini'"
             :rules="rulesThis"
             label-width="80px"
             class="demo-ruleForm"
-            :disabled="type === actionTypes.PREVIEW"
           >
-            <el-form-item label="真实姓名" prop="parameter_name">
-              <el-input
-                v-model="ruleForm.parameter_name"
-                placeholder="请输入真实姓名"
-                maxlength="20"
-              />
-            </el-form-item>
-
-            <el-form-item label="手机号" prop="parameter_name">
-              <el-input
-                v-model="ruleForm.parameter_name"
-                placeholder="请输入手机号"
-                maxlength="20"
-              />
-            </el-form-item>
+            <el-row style="margin-bottom:20px">
+              <el-col :span="24">
+                <el-form-item label="真实姓名" prop="nickname">
+                  <el-input
+                    v-model="ruleForm.nickname"
+                    :placeholder="'真实姓名'"
+                    :disabled="isDetail"
+                    maxlength="100"
+                  />
+                </el-form-item>
+              </el-col>
+              
+              <el-col :span="24">
+                <el-form-item label="手机号" prop="mobile">
+                  <el-input
+                    v-model="ruleForm.mobile"
+                    :placeholder="'手机号'"
+                    maxlength="11"
+                    :disabled="isDetail"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
           </el-form>
         </el-col>
-        <el-col :span="24" style="text-align: right">
-          <el-button type="primary" @click="submitForm" v-if="type !== actionTypes.PREVIEW"
+        <el-col :span="6" class="bottom-btn">
+          <el-button v-if="!isDetail" type="primary" @click="submitForm" :size="'mini'"
             >保 存
           </el-button>
-          <el-button @click="showModelThis = false">关 闭</el-button>
+          <el-button @click="showModelThis = false" :size="'mini'">{{
+            isDetail ? "关 闭" : "取 消"
+          }}</el-button>
         </el-col>
       </el-row>
     </el-card>
   </el-dialog>
 </template>
 <script>
-import asyncRequest from "@/apis/service/serviceParam/parameter";
-import { actionTypes } from "@/utils/actionType";
+import asyncRequest from "@/apis/service/system/operationAccount";
 import resToken from "@/mixins/resToken";
-
+import {
+  isnumber,
+  isMobile,
+  validEmail,
+  isAlphanumeric,
+  isChinese,
+  isEmoticon,
+  validAlphabets,
+} from "@/utils/validate";
 export default {
-  name: "parameter",
-  props: ["showModel", "sitem", "type"],
+  name: "Account",
+  props: ["showModel", "id", "isDetail"],
   mixins: [resToken],
   data() {
+    const validateusername = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("账号不能为空!"));
+      } else {
+        if (value.length < 6 || value.length > 18) {
+          callback(new Error("账号规则为6~18位数字与字母组合!"));
+        } else {
+          if (isnumber(value)) {
+            callback(new Error("账号规则为6~18位数字与字母组合!"));
+          } else if (validAlphabets(value)) {
+            callback(new Error("账号规则为6~18位数字与字母组合!"));
+          } else if (!isAlphanumeric(value)) {
+            callback(new Error("账号规则为6~18位数字与字母组合!"));
+          } else {
+            callback();
+          }
+        }
+      }
+    };
+
+    const validatename = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("真实姓名不能为空!"));
+      } else {
+        if (value.length < 2 || value.length > 12) {
+          callback(new Error("真实姓名规则为2~12位!"));
+        } else {
+          if (isEmoticon(value)) {
+            callback(new Error("真实姓名规则为2~12位!"));
+          } else {
+            callback();
+          }
+        }
+      }
+    };
+
+    const validatemobile = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("手机号不能为空!"));
+      } else {
+        if (!isMobile(value)) {
+          callback(new Error("手机号格式不正确!"));
+        } else {
+          callback();
+        }
+      }
+    };
+
     return {
-      actionTypes,
+      roleList: [],
       loading: false,
-      title: "添加系统参数",
+      title: "添加账号",
+      organizeList: [],
       showModelThis: this.showModel,
-      select: "1",
-      activeOptions: [],
-      actionList: [],
+      coptions: [],
+      is_mainoptions: [],
+      isIndeterminate: false,
       ruleForm: {
-        id: "",
-        parameter_name: "",
+        nickname: "", // 真实姓名
+        mobile: "", //手机号
+        role_id: "", //角色id
       },
+      platformoptions: [],
       rulesThis: this.rules,
       rules: {
+        nickname: [
+          {
+            required: true,
+            validator: validatename,
+            trigger: "blur",
+          },
+        ],
+        mobile: [
+          {
+            required: true,
+            validator: validatemobile,
+            trigger: "blur",
+          },
+        ],
+        role_id: [
+          {
+            required: true,
+            message: "请选择角色",
+            trigger: "change",
+          },
+        ],
       },
     };
   },
@@ -92,66 +181,165 @@ export default {
       }
     },
   },
+  mounted() {},
   methods: {
+    itemidChange(e) {
+      this.ruleForm.itemid = e;
+      this.$refs.ruleForm.validateField("itemid");
+    },
     async initForm() {
       this.loading = true;
-      if (this.type === actionTypes.CREATE) {
-        this.title = "添加运营账号";
-        this.rulesThis = this.rules;
-      } else if (this.type === actionTypes.UPDATE) {
-        this.title = "修改运营账号";
+
+      if (this.id === "add") {
+        await this.resetForm();
+      } else {
+        await this.initData();
+      }
+      if (this.id === "add") {
+        this.title = "添加账号";
         this.rulesThis = this.rules;
       } else {
-        this.title = "运营账号详情";
-        this.rulesThis = {};
+        if (this.isDetail) {
+          this.title = "账号详情";
+          this.rulesThis = {};
+        } else {
+          this.title = "修改账号";
+          this.rulesThis = this.rules;
+        }
       }
-      await this.resetForm();
       this.loading = false;
     },
-    async resetForm() {
+
+    async getClist() {
+      this.organizeList = [];
+      const { code, data, message } = await asyncRequest.getClist({
+        size: 10000,
+      });
+      if (code === 0) {
+        this.organizeList = data;
+        this.recursion(this.organizeList);
+      } else if (code >= 100 && code <= 104) {
+        await this.logout();
+      } else {
+        this.$message.warning(message);
+      }
+    },
+    handleCheckedCitiesChange(value) {
+      console.log(value);
+      let checkedCount = value.length;
+      this.ruleForm.is_all = checkedCount === this.coptions.length;
+      this.isIndeterminate = checkedCount > 0 && checkedCount < this.coptions.length;
+    },
+    recursion(list) {
+      list.map((v) => {
+        if (v && Array.isArray(v.child)) {
+          v.value = v.id + "";
+          v.label = v.name;
+          if (v.child.length === 0) {
+            delete v["child"];
+          } else {
+            this.recursion(v.child);
+          }
+        }
+        return v;
+      });
+    },
+    async getRole() {
+      const model = {
+        status: "", // 状态
+        level: "", // 姓名
+        role_name: "",
+      };
+      const res = await asyncRequest.getRole(model);
+      if (res && res.code === 0 && res.data) {
+        this.roleList = res.data;
+        this.roleList.map((v1) => {
+          v1.id += "";
+          v1.status += "";
+          return v1;
+        });
+      }
+    },
+    async initData() {
+      const { code, data, message } = await asyncRequest.detail({
+        id: this.id,
+      });
+      if (code === 0) {
+        await this.resetForm(data);
+      } else if (code >= 100 && code <= 104) {
+        await this.logout();
+      } else {
+        this.$message.warning(message);
+      }
+    },
+    async resetForm(sitem) {
       // 重置
       await this.$nextTick(() => {
         if (this.$refs.ruleForm) {
           this.$refs.ruleForm.resetFields();
           this.$refs.ruleForm.clearValidate();
-          const { id, parameter_name } = this.sitem;
-          this.ruleForm = {
-            id: id || "",
-            parameter_name: parameter_name || "",
-          };
+          if (sitem) {
+            const {
+              nickname,
+              mobile,
+              id
+            } = sitem;
+
+            this.ruleForm = {
+              id,
+              nickname: nickname || "",
+              mobile: mobile || ""
+            };
+
+          } else {
+            this.ruleForm = {
+              nickname: "", // 真实姓名
+              mobile: ""
+            };
+          }
         }
       });
     },
     async submitForm() {
       await this.$refs.ruleForm.validate(async (valid) => {
         if (valid) {
-          if (this.loading) {
-            return;
-          }
-          this.loading = true;
-          let model = JSON.parse(JSON.stringify(this.ruleForm));
-          let res = {};
-          
-          if (this.id === "003") {
-            delete model["id"];
-            res = await asyncRequest.add(model);
-          } else {
-            res = await asyncRequest.update(model);
-          }
-          this.loading = false;
-          if (res && res.code === 0) {
-            const title = this.id === "add" ? "添加成功!" : "修改成功!";
-            this.$notify.success({
-              title,
-              message: "",
-            });
-            this.showModelThis = false;
-            // 刷新
-            this.$emit("refresh");
-          } else if (res && res.code >= 100 && res.code <= 104) {
-            await this.logout();
-          } else {
-            this.$message.warning(res.message);
+          if (!this.loading) {
+            this.loading = true;
+            const {
+              nickname,
+              mobile,
+              id
+            } = JSON.parse(JSON.stringify(this.ruleForm));
+
+
+            const model = {
+              nickname,
+              mobile,
+              id
+            };
+
+            let res = {};
+            if (this.id === "add") {
+              delete model["id"];
+              res = await asyncRequest.add(model);
+            } else {
+              res = await asyncRequest.update(model);
+            }
+            this.loading = false;
+            if (res && res.code === 0) {
+              const title = this.id === "add" ? "添加成功" : "修改成功";
+              this.$notify.success({
+                title,
+                message: "",
+              });
+              this.showModelThis = false;
+              // 刷新
+              this.$emit("refresh");
+            } else if (res && res.code >= 100 && res.code <= 104) {
+              await this.logout();
+            } else {
+              this.$message.warning(res.message);
+            }
           }
         } else {
           console.log("error submit!!");
@@ -163,7 +351,14 @@ export default {
 };
 </script>
 
-   <style lang="scss" scoped>
-.parameter {
+<style lang="scss" scoped>
+.account {
+  .bottom-btn {
+    position: absolute;
+    bottom: 0px;
+    right: 0;
+    text-align: right;
+    z-index: 2;
+  }
 }
 </style>

+ 301 - 249
src/views/system/operationAccount/index.vue

@@ -1,255 +1,301 @@
 <template>
-  <div class="parameter pagePadding">
-    <ex-table
-      v-loading="loading"
-      v-if=" powers.some((i) => i == '001')"
-      :table="table"
-      :data="tableData"
-      :columns="columns"
-      :page="pageInfo"
-      :size="size"
-      @page-curr-change="handlePageChange"
-      @page-size-change="handleSizeChange"
-      @screen-reset="
-        pageInfo.curr = 1;
-        parmValue.page = 1;
-        searchList();
-      "
-      @screen-submit="
-        pageInfo.curr = 1;
-        parmValue.page = 1;
-        searchList();
-      "
-    >
-      <template #table-header="{}">
-        <div style="width: 100%">
-          <el-row style="padding: 0 0 10px 80px">
-            <el-col :span="4" style="width: 160px;margin-right:10px">
-              <el-select
-                v-model="parmValue.status"
-                clearable
-                :size="searchSize"
-                placeholder="当前状态"
-                style="width: 100%"
-                @change="
-                  pageInfo.curr = 1;
-                  parmValue.page = 1;
-                  searchList();
-                "
-              >
-                <el-option
-                  v-for="item in statusList"
-                  :key="'status' + item.value"
-                  :label="item.label"
-                  :value="item.value"
-                />
-              </el-select>
-            </el-col>
+  <div class="account pagePadding">
+    <div v-if=" powers.some((i) => i == '001')">
+      <ex-table
+        v-loading="loading"
+        :table="table"
+        :data="tableData"
+        :columns="columns"
+        :page="pageInfo"
+        :size="size"
+        @page-curr-change="handlePageChange"
+        @page-size-change="handleSizeChange"
+        @screen-reset="
+          pageInfo.curr = 1;
+          parmValue.page = 1;
+          searchList();
+        "
+        @screen-submit="
+          pageInfo.curr = 1;
+          parmValue.page = 1;
+          searchList();
+        "
+      >
+        <template #table-header="{}">
+          <div style="width: 100%">
+            <el-row style="padding: 0 0 0 80px">
+              <el-col :span="24">
+                <el-col :span="4" style="width: 120px">
+                  <el-select
+                    :size="searchSize"
+                    v-model="parmValue.status"
+                    filterable
+                    clearable
+                    placeholder="账号状态"
+                    style="width: 100%"
+                    @change="
+                      pageInfo.curr = 1;
+                      parmValue.page = 1;
+                      searchList();
+                    "
+                  >
+                    <el-option
+                      v-for="item in statusList"
+                      :key="'status' + item.code"
+                      :label="item.name"
+                      :value="item.code"
+                    />
+                  </el-select>
+                </el-col>
+                <el-col :span="4" style="width: 150px; padding: 0 0 0 10px">
+                  <el-input
+                    :size="searchSize"
+                    v-model="parmValue.name"
+                    :maxlength="40"
+                    placeholder="业务员姓名"
+                  />
+                </el-col>
+                <el-col :span="4" style="width: 160px; padding: 0 0 0 10px">
+                  <el-input
+                    :size="searchSize"
+                    v-model="parmValue.username"
+                    :maxlength="40"
+                    placeholder="手机号"
+                  />
+                </el-col>
+                <el-col :span="4" style="width: 54px">
+                  <el-button
+                    :size="searchSize"
+                    type="primary"
+                    class="fr"
+                    icon="el-icon-search"
+                    @click="searchList"
+                /></el-col>
+                <el-col :span="4" style="width: 66px">
+                  <el-button
+                    type="warning"
+                    class="fr"
+                    :size="searchSize"
+                    @click="restSearch"
+                  >
+                    重置
+                  </el-button>
+                </el-col>
+                <el-col :span="3" style="width: 66px; float: right">
+                  <el-button
+                    :size="searchSize"
+                    type="primary"
+                    style="float: right; margin-left: 5px"
+                    @click="searchList"
+                  >
+                    刷新
+                  </el-button>
+                </el-col>
+              </el-col>
+            </el-row>
+          </div>
+        </template>
 
-            <el-col :span="4" style="margin-right:10px">
-              <el-input
-                :size="searchSize"
-                placeholder="用户名或姓名"
-                @blur="pageInfo.curr = 1;
-                  parmValue.page = 1;
-                  searchList();"
-              />
-            </el-col>
+        <template #depart_info="{ scope }">
+          <el-tag
+            style="margin: 0 3px 0 0"
+            :size="tablebtnSize"
+            type="''"
+            v-for="(ditem, dindex) in scope.row.depart_info"
+            :key="ditem + dindex"
+          >
+            <span v-for="(cItem, cindex) in ditem" :key="cItem + dindex + cindex">
+              <span v-show="cindex > 0">/</span><span>{{ cItem }}</span>
+            </span>
+            {{ ditem.name }}</el-tag
+          >
+        </template>
+        <template #status="{ scope }">
+          <el-tag
+            :size="tablebtnSize"
+            :type="scope.row.status == '0' ? 'warning' : ''"
+            v-text="
+              (statusOptions.find((item) => item.id == String(scope.row.status)) || {}).label ||
+              '--'
+            "
+          ></el-tag>
+        </template>
+        <template #operation="{ scope }">
+          <!-- <el-tooltip
+            v-if="powers.some((i) => i == '002')"
+            effect="dark"
+            content="重置密码"
+            placement="top"
+          >
+            <i
+              class="el-icon-refresh-left tb-icon"
+              @click="openPasswordModal(scope.row.id, false)"
+            ></i>
+          </el-tooltip> -->
+          <el-tooltip
+            v-if="powers.some((i) => i == '007')"
+            effect="dark"
+            content="详情"
+            placement="top"
+          >
+            <i
+              class="el-icon-view tb-icon"
+              @click="openModal(scope.row.id, true, scope.row)"
+            ></i>
+          </el-tooltip>
+          <!-- <el-tooltip
+            v-if="powers.some((i) => i == '005')"
+            effect="dark"
+            content="修改"
+            placement="top"
+          >
+            <i
+              class="el-icon-edit tb-icon"
+              @click="openModal(scope.row.id, false, scope.row)"
+            ></i>
+          </el-tooltip> -->
+          <!-- <el-tooltip
+            v-if="powers.some((i) => i == '004') && scope.row.status === '1'"
+            effect="dark"
+            content="禁用"
+            placement="top"
+          >
+            <i
+              class="el-icon-video-pause tb-icon"
+              @click="statusConfirm(scope.row.id, scope.row.status)"
+            ></i>
+          </el-tooltip>
+          <el-tooltip
+            v-if="powers.some((i) => i == '004') && scope.row.status === '0'"
+            effect="dark"
+            content="启用"
+            placement="top"
+          >
+            <i
+              class="el-icon-video-play tb-icon"
+              @click="statusConfirm(scope.row.id, scope.row.status)"
+            ></i> -->
+          <!-- </el-tooltip> -->
+        </template>
+      </ex-table>
+      <add-edit
+        :id="modelId"
+        :sitem="sitem"
+        :show-model="showModel"
+        :is-detail="isDetail"
+        @refresh="searchList"
+        @cancel="showModel = false"
+      />
 
-            <el-col :span="4">
-              <el-input
-                :size="searchSize"
-                placeholder="业务员名称"
-                @blur="pageInfo.curr = 1;
-                  parmValue.page = 1;
-                  searchList();"
-              />
-            </el-col>
-
-            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
-              <el-button type="primary" :size="searchSize" @click="searchList">刷新</el-button>
-            </el-col>
-            <el-col :span="3" class="fr" style="width: 66px; padding: 0 0 0 10px">
-              <el-button type="warning" :size="searchSize" @click="restSearch">重置</el-button>
-            </el-col>
-          </el-row>
-
-          <el-row  v-if=" powers.some((i) => i == '003')">
-            <el-col :span="12" class="fr" style="width: 66px; padding: 0 0 0 10px">
-              <el-button type="primary" :size="searchSize" @click="openModal({}, actionTypes.CREATE)">添加</el-button>
-            </el-col>
-          </el-row>
-        </div>
-      </template>
-      <template #status="{ scope }">
-        <el-tag
-          :size="tablebtnSize"
-          :type="scope.row.status == '0' ? 'warning' : ''"
-          v-text="
-            (statusOptions.find((item) => item.id == scope.row.status) || {})
-              .label || '--'
-          "
-        ></el-tag>
-      </template>
-
-      <template #operation="{ scope }">
-        <el-tooltip
-          v-if="powers.some((i) => i == '007')"
-          effect="dark"
-          content="详情"
-          placement="top"
-        >
-          <i class="el-icon-view tb-icon" @click="openModal(scope.row, actionTypes.PREVIEW)"></i>
-        </el-tooltip>
-        <el-tooltip
-          v-if="powers.some((i) => i == '005')"
-          effect="dark"
-          content="修改"
-          placement="top"
-        >
-          <i class="el-icon-edit tb-icon" @click="openModal(scope.row, actionTypes.UPDATE)"></i>
-        </el-tooltip>
-        <el-tooltip
-          v-if="
-            powers.some((i) => i == '004') && scope.row.status === '1'
-          "
-          effect="dark"
-          content="禁用"
-          placement="top"
-        >
-          <i
-            class="el-icon-video-pause tb-icon"
-            @click="changeStatus(scope.row.id, scope.row.status)"
-          ></i>
-        </el-tooltip>
-        <el-tooltip
-          v-if="
-            powers.some((i) => i == '004') && scope.row.status === '0'
-          "
-          effect="dark"
-          content="启用"
-          placement="top"
-        >
-          <i
-            class="el-icon-video-play tb-icon"
-            @click="changeStatus(scope.row.id, scope.row.status)"
-          ></i>
-        </el-tooltip>
-        <el-tooltip
-          v-if="powers.some((i) => i == '006')"
-          effect="dark"
-          content="删除"
-          placement="top"
-        >
-          <i class="el-icon-delete tb-icon" @click="deleteItem(scope.row.id)"></i>
-        </el-tooltip>
-      </template>
-    </ex-table>
-    <no-auth v-else></no-auth>
-    <!-- 弹窗 新增/修改 -->
-    <add-edit
-      :type="modelId"
-      :show-model="showModel"
-      :sitem="sitem"
-      @refresh="searchList"
-      @cancel="showModel = false"
-    />
+      <reset-password
+        :id="passwordModelId"
+        :show-model="passwordModel"
+        :is-detail="isPasswordDetail"
+        @refresh="searchList"
+        @cancel="passwordModel = false"
+      />
+    </div>
+    <div v-else>
+      <no-auth></no-auth>
+    </div>
   </div>
 </template>
 <script>
-import addEdit from "./addEdit";
 import asyncRequest from "@/apis/service/system/operationAccount";
-import roleLevel from "@/assets/js/roleLevel";
 import mixinPage from "@/mixins/elPaginationHandle";
-import { mapGetters } from "vuex";
+import { statusList } from "@/assets/js/statusList"
+import resetPassword from "./resetPassword";
 import resToken from "@/mixins/resToken";
-import { actionTypes } from "@/utils/actionType";
+import { mapGetters } from "vuex";
+import addEdit from "./addEdit";
+
 export default {
-  name: "parameter",
-  mixins: [mixinPage, resToken],
+  name: "operationAccount",
   components: {
-    addEdit
+    addEdit,
+    resetPassword,
   },
+  mixins: [mixinPage, resToken],
   computed: {
-    //组件SIZE设置
     ...mapGetters(["tablebtnSize", "searchSize", "size"]),
     powers() {
-      const tran =
-        this.$store.getters.btnList.find(
-          item => item.menu_route == "operationAccount"
-        ) || {};
+      const { btnList } = this.$store.getters;
+      const tran = btnList.find((i) => i.menu_route == "operationAccount") || {};
       const { action } = tran ?? {};
       return action ?? [];
-    }
+    },
   },
   data() {
     return {
-      actionTypes,
-      roleLevel: roleLevel,
+      sitem: null,
+      // 状态
+      statusOptions: [
+        { id: "0", label: "禁用" },
+        { id: "1", label: "启用" },
+      ],
+      statusList: statusList,
       loading: true,
       showModel: false,
-      type: "",
-      statusList: [
-        {
-          label: "启用",
-          value: "1"
-        },
-        {
-          label: "禁用",
-          value: "0"
-        }
-      ],
-      sitem: {},
+      isDetail: false,
+      modelId: 0,
       parmValue: {
+        name: "", // 业务员名字
+        username: "", // 账号
+        status: "", //
         page: 1, // 页码
-        size: 15 // 每页显示条数
+        size: 15, // 每页显示条数
       },
-      // 状态
-      statusOptions: [
-        { id: "0", label: "禁用" },
-        { id: "1", label: "启用" }
-      ],
+      tableData: [],
+      passwordModel: false,
+      passwordModelId: 0,
+      isPasswordDetail: false,
       // 表格 - 数据
       tableData: [],
       // 表格 - 参数
       table: {
         stripe: true,
         border: true,
-        _defaultHeader_: ["setcol"]
+        _defaultHeader_: ["setcol"],
       },
       // 表格 - 分页
       pageInfo: {
         size: 15,
         curr: 1,
-        total: 0
+        total: 0,
       },
       // 表格 - 列参数
       columns: [
         {
-          prop: "id",
-          label: "序号"
-        },
-        {
-          prop: "parameter_name",
-          label: "用户名"
+          prop: "nickname",
+          label: "真实姓名",
+          // width: "110px",
         },
         {
-          prop: "parameter_name",
-          label: "姓名"
+          prop: "mobile",
+          label: "联系电话",
+          // width: "110px",
         },
         {
           prop: "status",
           label: "状态",
-          _slot_: "status"
+          _slot_: "status",
+          width: "70px",
+        },
+        {
+          prop: "addtime",
+          label: "创建时间",
+          sortable: true,
+          // width: "140px",
         },
         {
           prop: "",
           label: "操作",
           fixed: "right",
           _noset_: true,
-          _slot_: "operation"
-        }
-      ]
+          width: "80px",
+          _slot_: "operation",
+        },
+      ],
     };
   },
   mounted() {
@@ -257,53 +303,57 @@ export default {
   },
   methods: {
     restSearch() {
+      this.parmValue = {
+        name: "", // 业务员名字
+        username: "", // 账号
+        status: "", //
+        page: 1, // 页码
+        size: 15, // 每页显示条数
+      };
       // 表格 - 分页
       this.pageInfo = {
         size: 15,
         curr: 1,
-        total: 0
-      };
-      this.parmValue = {
-        page: 1, // 页码
-        size: 15, // 每页显示条数
+        total: 0,
       };
       this.searchList();
     },
-    // 新建/编辑/详情
-    openModal(row, type) {
-      this.sitem = row;
-      this.modelId = type;
+
+    openModal(id, isDetail, sitem) {
       this.showModel = true;
+      this.modelId = id;
+      this.isDetail = isDetail;
+      this.sitem = sitem;
     },
-    /**
-     * 启用/禁用
-     * @param {String} id id
-     * @param {String} status 0-禁用 1-启用
-     */
-    async changeStatus(id, status) {
-      await this.$confirm(`确定要改为${status === "1" ? "禁用" : "启用"}?`, {
+
+    openPasswordModal(id, isDetail) {
+      this.passwordModel = true;
+      this.passwordModelId = id;
+      this.isPasswordDetail = isDetail;
+    },
+
+    async deleteById(id, status) {
+      await this.$confirm("确定要删除?", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       })
         .then(async () => {
-          this.loading = true;
           const model = {
             id: id,
-            status: status === "1" ? "0" : "1"
+            status: status === "1" ? "0" : "1",
           };
+
           const res = await asyncRequest.status(model);
           if (res && res.code === 0) {
-            this.loading = false;
             this.$notify.success({
-              title: "状态修改成功!",
-              message: ""
+              title: "删除成功",
+              message: "",
             });
-            await this.searchList();
+            this.searchList();
           } else if (res && res.code >= 100 && res.code <= 104) {
             await this.logout();
           } else {
-            this.loading = false;
             this.$message.warning(res.message);
           }
         })
@@ -311,23 +361,40 @@ export default {
           console.log("取消");
         });
     },
-    async deleteItem(id) {
-      await this.$confirm("确定要删除?", {
+    async searchList() {
+      this.loading = true;
+      const res = await asyncRequest.list(this.parmValue);
+      if (res && res.code === 0 && res.data) {
+        this.tableData = res.data.list;
+        this.pageInfo.total = Number(res.data.count);
+      } else if (res && res.code >= 100 && res.code <= 104) {
+        await this.logout();
+      } else {
+        this.tableData = [];
+        this.pageInfo.total = 0;
+      }
+      this.loading = false;
+    },
+    async statusConfirm(id, status) {
+      await this.$confirm(`确定要改为${status === "1" ? "禁用" : "启用"}?`, {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       })
         .then(async () => {
+          this.loading = true;
           const model = {
-            id: id
+            id: id,
+            status: status === "1" ? "0" : "1",
           };
-          const res = await asyncRequest.delete(model);
+          const res = await asyncRequest.status(model);
           if (res && res.code === 0) {
+            this.loading = false;
             this.$notify.success({
-              title: "删除成功",
-              message: ""
+              title: "状态修改成功!",
+              message: "",
             });
-            this.searchList();
+            await this.searchList();
           } else if (res && res.code >= 100 && res.code <= 104) {
             await this.logout();
           } else {
@@ -338,25 +405,10 @@ export default {
           console.log("取消");
         });
     },
-    // 刷新表格
-    async searchList() {
-      this.loading = true;
-      const res = await asyncRequest.list(this.parmValue);
-      if (res && res.code === 0 && res.data) {
-        //todo:可能是list下
-        this.tableData = res.data;
-        this.pageInfo.total = Number(res.data.count);
-      } else if (res && res.code >= 100 && res.code <= 104) {
-        await this.logout();
-      } else {
-        this.tableData = [];
-        this.pageInfo.total = 0;
-      }
-      this.loading = false;
-    }
-  }
+  },
 };
 </script>
 
 <style lang="scss" scoped>
+.account {}
 </style>

+ 193 - 0
src/views/system/operationAccount/resetPassword.vue

@@ -0,0 +1,193 @@
+<template>
+  <el-dialog
+    v-loading="loading"
+    :title="title"
+    :center="true"
+    align="left"
+    top="5vh"
+    width="600px"
+    :close-on-click-modal="false"
+    :visible.sync="showModelThis"
+    element-loading-text="拼命加载中"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)"
+    @close="showModelThis = false"
+  >
+    <el-card>
+      <el-row :gutter="10">
+        <el-col :span="24">
+          <el-form
+            ref="ruleForm"
+            :model="ruleForm"
+            status-icon
+            :rules="rulesThis"
+            label-width="110px"
+            class="demo-ruleForm"
+          >
+            <el-form-item prop="password" label="新密码:">
+              <el-input
+                ref="password"
+                v-model="ruleForm.password"
+                placeholder="新密码"
+                name="password"
+                type="password"
+                tabindex="1"
+                maxlength="50"
+                autocomplete="on"
+              />
+            </el-form-item>
+            <el-form-item prop="confirmPassword" label="确认密码:">
+              <el-input
+                ref="confirmPassword"
+                v-model="ruleForm.confirmPassword"
+                placeholder="确认密码"
+                name="confirmPassword"
+                type="password"
+                tabindex="1"
+                maxlength="50"
+                autocomplete="on"
+              />
+            </el-form-item>
+          </el-form>
+        </el-col>
+        <el-col :span="24" style="text-align: right">
+          <el-button type="primary" @click="submitForm">保 存 </el-button>
+          <el-button @click="showModelThis = false">{{
+            isDetail ? "关 闭" : "取 消"
+          }}</el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+  </el-dialog>
+</template>
+<script>
+import asyncRequest from "@/apis/service/interest/account";
+import { isnumber, isAlphanumeric, validAlphabets } from "@/utils/validate";
+import resToken from "@/mixins/resToken";
+export default {
+  name: "Account",
+  props: ["showModel", "id", "isDetail"],
+  mixins: [resToken],
+  data() {
+    const validateNewPassword = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("新密码不能为空!"));
+      } else {
+        if (!isAlphanumeric(value)) {
+          callback(new Error("新密码为6-16位数字字母组合!"));
+        } else if (value.length < 6 || value.length > 16) {
+          callback(new Error("新密码为6-16位数字字母组合!"));
+        } else if (isnumber(value)) {
+          callback(new Error("新密码不能为纯数字!"));
+        } else if (validAlphabets(value)) {
+          callback(new Error("新密码不能为纯字母!"));
+        } else {
+          callback();
+        }
+      }
+    };
+    const validateConfirmPassword = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("确认密码不能为空!"));
+      } else {
+        if (this.ruleForm.password !== value) {
+          callback(new Error("确认密码与新密码不一致!"));
+        } else {
+          callback();
+        }
+      }
+    };
+    return {
+      roleList: [],
+      loading: false,
+      title: "重置密码",
+      showModelThis: this.showModel,
+      ruleForm: {
+        id: this.id,
+        password: "",
+        confirmPassword: "",
+      },
+      rulesThis: this.rules,
+      rules: {
+        password: [
+          { required: true, trigger: "blur", validator: validateNewPassword },
+        ],
+        confirmPassword: [
+          {
+            required: true,
+            trigger: "blur",
+            validator: validateConfirmPassword,
+          },
+        ],
+      },
+    };
+  },
+  watch: {
+    showModel: function (val) {
+      this.showModelThis = val;
+      if (val) {
+        this.initForm();
+      }
+    },
+    showModelThis(val) {
+      if (!val) {
+        this.$emit("cancel");
+      }
+    },
+  },
+  methods: {
+    async initForm() {
+      this.rulesThis = this.rules;
+      await this.resetForm();
+    },
+
+    async resetForm() {
+      // 重置
+      await this.$nextTick(() => {
+        if (this.$refs.ruleForm) {
+          this.$refs.ruleForm.resetFields();
+          this.$refs.ruleForm.clearValidate();
+          this.ruleForm = {
+            id: this.id,
+            password: "",
+            confirmPassword: "",
+          };
+        }
+      });
+    },
+    async submitForm() {
+      await this.$refs.ruleForm.validate(async (valid) => {
+        if (valid) {
+          if (!this.loading) {
+            this.loading = true;
+            const obj = JSON.parse(JSON.stringify(this.ruleForm));
+            const res = await asyncRequest.setpwd(obj);
+            this.loading = false;
+            if (res && res.code === 0) {
+              this.$notify.success({
+                title: "密码修改成功!",
+                message: "",
+              });
+              this.showModelThis = false;
+              // 刷新
+              this.$emit("refresh");
+            } else if (res && res.code >= 100 && res.code <= 104) {
+              await this.logout();
+            } else {
+              this.$message.warning(res.message);
+            }
+          }
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+  },
+};
+</script>
+
+   <style lang="scss" scoped>
+.account {
+}
+</style>

+ 0 - 0
src/views/system/operationAccount/运营账号管理