ソースを参照

添加会员管理

asd123a20 3 年 前
コミット
88115619f2

admin-vip/.browserslistrc → admin-client-vip/.browserslistrc


admin-vip/.editorconfig → admin-client-vip/.editorconfig


admin-vip/.env → admin-client-vip/.env


admin-vip/.eslintignore → admin-client-vip/.eslintignore


admin-vip/.eslintrc.js → admin-client-vip/.eslintrc.js


admin-vip/.gitignore → admin-client-vip/.gitignore


admin-vip/README.md → admin-client-vip/README.md


admin-vip/babel.config.js → admin-client-vip/babel.config.js


admin-vip/package-lock.json → admin-client-vip/package-lock.json


+ 1 - 1
admin-vip/package.json

@@ -1,5 +1,5 @@
 {
-  "name": "admin-user",
+  "name": "admin-client-vip",
   "version": "0.1.0",
   "private": true,
   "scripts": {

admin-vip/public/favicon.ico → admin-client-vip/public/favicon.ico


admin-vip/public/index.html → admin-client-vip/public/index.html


admin-vip/src/App.vue → admin-client-vip/src/App.vue


admin-vip/src/assets/logo.png → admin-client-vip/src/assets/logo.png


+ 1 - 1
admin-vip/src/main.js

@@ -20,7 +20,7 @@ let instance = null;
 function render (props = {}) {
   const { container } = props;
   router = new VueRouter({
-    base: window.__POWERED_BY_QIANKUN__ ? '/admin/adminUser/' : '/',
+    base: window.__POWERED_BY_QIANKUN__ ? '/admin/clientVip/' : '/',
     mode: 'history',
     routes
   });

admin-vip/src/public-path.js → admin-client-vip/src/public-path.js


admin-vip/src/router/index.js → admin-client-vip/src/router/index.js


+ 110 - 0
admin-client-vip/src/store/index.js

@@ -0,0 +1,110 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import $axios from '@lib/axios.js';
+const api = {
+  vipCreate: '/api/clientVip/vip/create',
+  vipUpdate: '/api/clientVip/vip/update',
+  vipDelete: '/api/clientVip/vip/delete',
+  vipQuery: '/api/clientVip/vip/query',
+  dictQuery: '/api/code/dictionary/query',
+  contentsQuery: '/api/cms/contents/query',
+  intactQuery: '/api/journal/intact/query',
+  powerCreate: '/api/clientVip/power/create',
+  powerupdate: '/api/clientVip/power/update'
+};
+Vue.use(Vuex);
+const state = () => ({
+  Total: 0,
+  vipList: [],
+  dict: {},
+  contentList: [],
+  intactList: [],
+  LIST: [],
+  tabList: []
+});
+
+const actions = {
+  async powerCreate ({ commit }, payload) {
+    const res = await $axios.post(api.powerCreate, payload);
+    return res;
+  },
+  async powerupdate ({ commit }, payload) {
+    const res = await $axios.post(api.powerupdate, { ...payload, id: payload._id });
+    return res;
+  },
+  async vipCreate ({ commit }, payload) {
+    const res = await $axios.post(api.vipCreate, payload);
+    return res;
+  },
+  async vipUpdate ({ commit }, payload) {
+    const res = await $axios.post(api.vipUpdate, { ...payload, id: payload._id });
+    return res;
+  },
+  async vipDelete ({ commit }, { id }) {
+    const res = await $axios.delete(`${api.vipDelete}/${id}`);
+    return res;
+  },
+  async vipQuery ({ commit }, { filter, paging } = {}) {
+    const res = await $axios.get(api.vipQuery, { ...filter, skip: paging.page, limit: paging.size });
+    commit('vipQuery', res);
+    return res;
+  },
+  async statusQuery ({ commit }) {
+    const res = await $axios.get(api.dictQuery, { parentCode: 'vipStatus' });
+    commit('statusQuery', res);
+    return res;
+  },
+  async tabQuery ({ commit }) {
+    const res = await $axios.get(api.dictQuery, { parentCode: 'vipTab' });
+    commit('tabQuery', res);
+    return res;
+  },
+  async typeQuery ({ commit }) {
+    const res = await $axios.get(api.dictQuery, { parentCode: 'vipBindType' });
+    commit('typeQuery', res);
+    return res;
+  },
+  async contentsQuery ({ commit }) {
+    const res = await $axios.get(api.contentsQuery);
+    commit('contentsQuery', res);
+    return res;
+  },
+  async intactQuery ({ commit }) {
+    const res = await $axios.get(api.intactQuery);
+    commit('intactQuery', res);
+    return res;
+  }
+};
+
+const mutations = {
+  vipQuery(state, payload) {
+    state.vipList = payload.data;
+    state.Total = payload.total;
+  },
+  contentsQuery(state, payload) {
+    state.contentList = payload.data;
+    // state.list = payload.data;
+  },
+  intactQuery(state, payload) {
+    state.intactList = payload.data;
+    // state.list = payload.data;
+  },
+  statusQuery(state, payload) {
+    state.dict.vipStatus = payload.data;
+  },
+  typeQuery(state, payload) {
+    state.dict.vipBindType = payload.data;
+    state.typeList = payload.data;
+  },
+  tabQuery(state, payload) {
+    state.dict.vipTab = payload.data;
+    state.tabList = payload.data;
+  }
+};
+
+export default new Vuex.Store({
+  state,
+  actions,
+  mutations,
+  modules: {}
+});

+ 258 - 0
admin-client-vip/src/views/home.vue

@@ -0,0 +1,258 @@
+<template>
+  <div class="box">
+    <el-card class="box-card">
+      <div slot="header" class="clearfix">
+        <span>vip管理</span>
+        <el-button style="float: right; padding: 3px 0" type="text" @click="addvip">添加vip</el-button>
+      </div>
+      <div class="main">
+        <filterList ref="filterList" :tableData="vipList" :filed="filed" @edit="filtereEdit" @delete="filterDelete" @query="filterQuery" :total="Total"></filterList>
+      </div>
+    </el-card>
+    <dialogAndDrawer :width="'35%'" :title="title" :visibleSync="visibleSync" v-if="visibleSync" @close="visibleSync = false">
+      <template v-slot:windowMain>
+        <formData ref="formData" :filed="formfiled" :data="formdata" :rules="formrules" @save="formSave">
+          <template v-slot:formItem="{ item, formdata }">
+            <!-- 标识 -->
+            <el-select v-if="item.name == 'vipTab'" v-model="formdata[item.name]" placeholder="请选择" @change="tabChange">
+              <el-option
+                v-for="item in tabList"
+                :key="item.code"
+                :label="item.name"
+                :value="item.code">
+              </el-option>
+            </el-select>
+            <!-- 绑定类型 -->
+            <el-select v-if="item.name == 'type'" v-model="formdata[item.name]" placeholder="请选择" @change="typeChange">
+              <el-option
+                v-for="item in typeList"
+                :key="item.code"
+                :label="item.name"
+                :value="item.code">
+              </el-option>
+            </el-select>
+            <!-- idList -->
+            <el-select v-if="item.name == 'list'" multiple v-model="formdata[item.name]" placeholder="请选择">
+              <el-option
+                v-for="item in list"
+                :key="item._id"
+                :label="item.name || item.title"
+                :value="item._id">
+              </el-option>
+            </el-select>
+            <!-- 缩略图 -->
+            <el-upload
+              v-if="item.name == 'thumbnail'"
+              class="avatar-uploader"
+              action="/api/files/avatar/upload"
+              :show-file-list="false"
+              :headers="myHeaders"
+              :on-success="handleAvatarSuccess"
+              :before-upload="beforeAvatarUpload">
+              <img v-if="formdata[item.name] && formdata[item.name] !== ''" :src="formdata[item.name]" class="avatar">
+              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+            </el-upload>
+          </template>
+        </formData>
+      </template>
+    </dialogAndDrawer>
+  </div>
+</template>
+<script>
+import filterList from '@components/filterList/index.vue';
+import dialogAndDrawer from '@components/dialogAndDrawer.vue';
+import formData from '@components/formData/index.vue';
+import { mapState, mapActions } from 'vuex';
+const token = sessionStorage.getItem('token');
+export default {
+  components: {
+    filterList,
+    dialogAndDrawer,
+    formData
+  },
+  data() {
+    return {
+      list: [],
+      myHeaders: { Authorization: token },
+      title: '',
+      visibleSync: false,
+      filed: [
+        { name: 'name', label: '姓名', filter: true },
+        { name: 'vipTab', label: 'vip标识', formater: 'dict:vipTab' },
+        { name: 'status', label: 'vip状态', filter: true, formater: 'dict:vipStatus' },
+        { name: 'phone', label: '电话', filter: true }
+      ],
+      formdata: {},
+      formfiled: [
+        { name: 'thumbnail', label: '头像', formater: 'slot' },
+        { name: 'name', label: '姓名' },
+        { name: 'vipTab', label: 'vip标识', formater: 'slot' },
+        { name: 'status', label: 'vip状态', formater: 'dict:vipStatus' },
+        { name: 'phone', label: '电话' },
+        { name: 'company', label: '单位' },
+        { name: 'openid', label: 'openid' }
+      ],
+      formrules: {
+        thumbnail: [
+          { required: true, message: '请上传头像', trigger: 'change' }
+        ],
+        name: [
+          { required: true, message: '请输入姓名', trigger: 'blur' }
+        ],
+        vipTab: [
+          { required: true, message: '请选择标识', trigger: 'change' }
+        ],
+        status: [
+          { required: true, message: '请选择状态', trigger: 'change' }
+        ],
+        phone: [
+          { required: true, message: '请输入手机号', trigger: 'blur' }
+        ],
+        openid: [
+          { required: true, message: '请输入openid', trigger: 'blur' }
+        ],
+        type: [
+          { required: true, message: '请选择绑定类型', trigger: 'change' }
+        ],
+        list: [
+          { required: true, message: '请选择绑定内容', trigger: 'change' }
+        ]
+      },
+      vipInfo: {},
+      values: []
+    };
+  },
+  computed: {
+    ...mapState(['vipList', 'Total', 'dict', 'intactList', 'contentList', 'tabList', 'typeList'])
+  },
+  async mounted() {
+    await this.tabQuery();
+    await this.statusQuery();
+    await this.filterQuery();
+  },
+  methods: {
+    ...mapActions(['vipQuery', 'vipCreate', 'vipUpdate', 'vipDelete', 'statusQuery', 'tabQuery', 'contentsQuery', 'intactQuery', 'typeQuery', 'powerCreate', 'powerupdate']),
+    // 标识改变
+    async tabChange(e) {
+      await this.typeQuery();
+      if (e == 'vip') {
+        this.formfiled.push({ name: 'type', label: '绑定类型', formater: 'slot' });
+      }
+    },
+    async typeChange(e) {
+      if (e == 0) {
+        await this.intactQuery();
+        this.list = this.intactList;
+      } else {
+        await this.contentsQuery();
+        this.list = this.contentList;
+      }
+      const label = e == 0 ? '绑定期刊' : '绑定文章';
+      this.formfiled = this.formfiled.filter(e => e.name !== 'list');
+      this.formfiled.push({ name: 'list', label, formater: 'slot' });
+    },
+    // 添加
+    addvip () {
+      this.formdata = {};
+      this.title = '添加vip';
+      this.visibleSync = true;
+    },
+    // 修改
+    filtereEdit (e) {
+      this.formdata = e;
+      this.title = '修改vip';
+      this.visibleSync = true;
+    },
+    // 删除
+    async filterDelete (e) {
+      const res = await this.vipDelete({ id: e?._id });
+      this.$resChange(res, '删除成功');
+      this.filterQuery();
+    },
+    // 查询
+    async filterQuery ({ filter = {}, paging = { page: 0, size: 10 } } = {}) {
+      await this.vipQuery({ filter, paging });
+    },
+    // 表单保存
+    async formSave (e) {
+      console.log(e);
+      if (e.isRevise && e?.isRevise == false) {
+        this.$message.warning('未作修改');
+        return;
+      }
+      this.$delete(e, 'isRevise');
+      let res, msg;
+      // 修改
+      if (e._id) {
+        res = await this.vipUpdate(e);
+        if (e.vipTab == 'vip') await this.powerupdate(e);
+        msg = 'vip修改成功';
+      } else {
+        res = await this.vipCreate(e);
+        if (e.vipTab == 'vip') await this.powerCreate(e);
+        msg = 'vip添加成功';
+      }
+      this.$resChange(res, msg);
+      this.filterQuery();
+      this.visibleSync = false;
+      this.formfiled = this.formfiled.filter(e => e.name !== 'list' && e.name !== 'type');
+    },
+    // 缩略图上传
+    handleAvatarSuccess(res, file) {
+      this.$refs.formData.setForm('thumbnail', res.data.filePath);
+    },
+    // 缩略图上传限制
+    beforeAvatarUpload(file) {
+      const isJPG = file.type === 'image/jpeg';
+      const isLt2M = file.size / 1024 / 1024 < 2;
+
+      if (!isJPG) {
+        this.$message.error('上传头像图片只能是 JPG 格式!');
+      }
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 2MB!');
+      }
+      return isJPG && isLt2M;
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.box {
+  width: 100%;
+  height: 100%;
+  .box-card {
+    height: 100%;
+    .el-card__body {
+      height: 100%;
+    }
+  }
+}
+.el-dialog {
+  .avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 120px;
+    height: 120px;
+    line-height: 120px;
+    text-align: center;
+  }
+  .avatar {
+    width: 120px;
+    height: 120px;
+    display: block;
+  }
+}
+</style>
+<style>
+.el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+.el-upload:hover {
+  border-color: #409EFF;
+}
+</style>

+ 1 - 1
admin-vip/vue.config.js

@@ -5,7 +5,7 @@ module.exports = {
   publicPath: `/${packageName}/`,
   outputDir: path.join(frameSrc, `../../admin-web/${packageName}/`),
   devServer: {
-    port: 3003,
+    port: 3020,
     headers: {
       'Access-Control-Allow-Origin': '*'
     },

+ 6 - 0
admin-frame/lib/apps.js

@@ -122,5 +122,11 @@ export default [
     entry: config.dev ? '//localhost:3019/admin-contribution/' : 'admin-contribution',
     container: config.tabs ? '#contribution' : '#content',
     activeRule: '/admin/contribution'
+  },
+  {
+    name: 'admin-client-vip',
+    entry: config.dev ? '//localhost:3020/admin-client-vip/' : 'admin-client-vip',
+    container: config.tabs ? '#clientVip' : '#content',
+    activeRule: '/admin/clientVip'
   }
 ];

+ 0 - 78
admin-vip/src/store/index.js

@@ -1,78 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import $axios from '@lib/axios.js';
-const api = {
-  userCreate: '/api/naf/adminUser/create',
-  userUpdate: '/api/naf/adminUser/update',
-  userDelete: '/api/naf/adminUser/delete',
-  userQuery: '/api/naf/adminUser/query',
-  queryBind: '/api/naf/userBindRole/queryBind',
-  roleQuery: '/api/naf/role/query',
-  batchBind: '/api/naf/userBindRole/batchBind',
-  batchUnBind: '/api/naf/userBindRole/batchUnBind'
-};
-Vue.use(Vuex);
-const state = () => ({
-  Total: 0,
-  userList: [],
-  bindList: [],
-  roleList: []
-});
-
-const actions = {
-  async batchUnBind ({ commit }, payload) {
-    const res = await $axios.post(api.batchUnBind, payload);
-    return res;
-  },
-  async batchBind ({ commit }, payload) {
-    const res = await $axios.post(api.batchBind, payload);
-    return res;
-  },
-  async queryBind ({ commit }, payload) {
-    const res = await $axios.get(api.queryBind, payload);
-    commit('queryBind', res);
-    return res;
-  },
-  async roleQuery ({ commit }) {
-    const res = await $axios.get(api.roleQuery);
-    commit('roleQuery', res);
-    return res;
-  },
-  async userCreate ({ commit }, payload) {
-    const res = await $axios.post(api.userCreate, payload);
-    return res;
-  },
-  async userUpdate ({ commit }, payload) {
-    const res = await $axios.post(api.userUpdate, { ...payload, id: payload._id });
-    return res;
-  },
-  async userDelete ({ commit }, { id }) {
-    const res = await $axios.delete(`${api.userDelete}/${id}`);
-    return res;
-  },
-  async userQuery ({ commit }, { filter, paging } = {}) {
-    const res = await $axios.get(api.userQuery, { ...filter, skip: paging.page, limit: paging.size });
-    commit('userQuery', res);
-    return res;
-  }
-};
-
-const mutations = {
-  userQuery(state, payload) {
-    state.userList = payload.data;
-    state.Total = payload.total;
-  },
-  queryBind(state, payload) {
-    state.bindList = payload.data;
-  },
-  roleQuery(state, payload) {
-    state.roleList = payload.data;
-  }
-};
-
-export default new Vuex.Store({
-  state,
-  actions,
-  mutations,
-  modules: {}
-});

+ 0 - 168
admin-vip/src/views/home.vue

@@ -1,168 +0,0 @@
-<template>
-  <div class="box">
-    <el-card class="box-card">
-      <div slot="header" class="clearfix">
-        <span>用户管理</span>
-        <el-button style="float: right; padding: 3px 0" type="text" @click="addUser">添加用户</el-button>
-      </div>
-      <div class="main">
-        <filterList ref="filterList" :operation="operation" :tableData="userList" :filed="filed" @bind="bindRole" @edit="filtereEdit" @delete="filterDelete" @query="filterQuery" :total="Total"></filterList>
-      </div>
-    </el-card>
-    <dialogAndDrawer :width="'35%'" :title="title" :visibleSync="visibleSync" v-if="visibleSync" @close="visibleSync = false">
-      <template v-slot:windowMain>
-        <formData v-if="!bind" :filed="formfiled" :data="formdata" :rules="formrules" @save="formSave"></formData>
-        <transfer v-else :data="roleList" :values="values" @change="transferChage"></transfer>
-      </template>
-    </dialogAndDrawer>
-  </div>
-</template>
-<script>
-import filterList from '@components/filterList/index.vue';
-import dialogAndDrawer from '@components/dialogAndDrawer.vue';
-import formData from '@components/formData/index.vue';
-import transfer from '@components/transfer.vue';
-import { mapState, mapActions } from 'vuex';
-export default {
-  components: {
-    filterList,
-    dialogAndDrawer,
-    formData,
-    transfer
-  },
-  data() {
-    return {
-      operation: [
-        { name: 'bind', label: '绑定角色', icon: 'el-icon-user' },
-        { name: 'edit', label: '修改', icon: 'el-icon-edit' },
-        { name: 'delete', label: '删除', icon: 'el-icon-delete' }
-      ],
-      title: '',
-      visibleSync: false,
-      bind: false,
-      filed: [
-        { name: 'name', label: '姓名', filter: true },
-        { name: 'userName', label: '用户名', filter: true },
-        { name: 'phone', label: '电话', filter: true }
-      ],
-      formdata: {},
-      formfiled: [
-        { name: 'name', label: '姓名' },
-        { name: 'userName', label: '用户名' },
-        { name: 'password', label: '密码' },
-        { name: 'phone', label: '电话' }
-      ],
-      formrules: {
-        name: [
-          { required: true, message: '请输入名称', trigger: 'blur' }
-        ],
-        userName: [
-          { required: true, message: '请输入用户名', trigger: 'blur' }
-        ],
-        password: [
-          { required: true, message: '请输入密码', trigger: 'blur' }
-        ]
-      },
-      userInfo: {},
-      values: []
-    };
-  },
-  computed: {
-    ...mapState(['userList', 'Total', 'roleList', 'bindList'])
-  },
-  async mounted() {
-    await this.filterQuery();
-  },
-  methods: {
-    ...mapActions(['userQuery', 'userCreate', 'userUpdate', 'userDelete', 'batchBind', 'queryBind', 'roleQuery', 'batchUnBind']),
-    // 添加
-    addUser () {
-      this.formdata = {};
-      this.title = '添加用户';
-      this.visibleSync = true;
-      this.bind = false;
-    },
-    // 修改
-    filtereEdit (e) {
-      this.formdata = e;
-      this.title = '修改用户';
-      this.visibleSync = true;
-      this.bind = false;
-    },
-    // 删除
-    async filterDelete (e) {
-      const res = await this.userDelete({ id: e?._id });
-      this.$resChange(res, '删除成功');
-      this.filterQuery();
-    },
-    // 查询
-    async filterQuery ({ filter = {}, paging = { page: 0, size: 10 } } = {}) {
-      await this.userQuery({ filter, paging });
-    },
-    // 表单保存
-    async formSave (e) {
-      if (e.isRevise && e?.isRevise == false) {
-        this.$message.warning('未作修改');
-        return;
-      }
-      this.$delete(e, 'isRevise');
-      let res, msg;
-      // 修改
-      if (e._id) {
-        res = await this.userUpdate(e);
-        msg = '用户修改成功';
-      } else {
-        res = await this.userCreate(e);
-        msg = '用户修改成功';
-      }
-      this.$resChange(res, msg);
-      this.filterQuery();
-      this.visibleSync = false;
-    },
-    // 点击绑定角色
-    async bindRole (e) {
-      this.userInfo = e;
-      this.title = '绑定角色';
-      this.visibleSync = true;
-      this.bind = true;
-      await this.roleQuery();
-      await this.queryBind({ userId: this.userInfo._id });
-      this.values = this.bindList.map(e => e.roleCode);
-    },
-    // 穿梭框改变
-    async transferChage (e) {
-      const userId = this.userInfo._id;
-      // 解绑
-      e.filter(i => {
-        this.values = this.values.filter(k => k !== i);
-      });
-      if (this.values.length > 0) {
-        const unbind = await this.batchUnBind({ userId, ids: this.values });
-        this.$resChange(unbind, '解绑成功');
-      }
-      // 绑定
-      this.values.filter(y => {
-        e = e.filter(z => z == y);
-      });
-      if (e.length > 0) {
-        const res = await this.batchBind({ userId, ids: e });
-        this.$resChange(res, '绑定成功');
-      }
-      await this.queryBind({ userId: this.userInfo._id });
-      this.values = this.bindList.map(e => e.roleCode);
-    }
-  }
-};
-</script>
-<style lang="scss" scoped>
-.box {
-  width: 100%;
-  height: 100%;
-  .box-card {
-    height: 100%;
-    .el-card__body {
-      height: 100%;
-    }
-  }
-}
-</style>

+ 1 - 1
xms.code-workspace

@@ -58,7 +58,7 @@
 			"path": "admin-contribution"
 		},
 		{
-			"path": "admin-vip"
+			"path": "admin-client-vip"
 		},
 	],
 	"settings": {}