新大宝股票管理后台
李凌
4 days ago 0dca2cc0ba3a58728d86ca0af07c92eab2b44c48
Merge branch '2.10' of http://124.156.157.155:8060/r/dg/dabao-admin-new into 2.10
11 files modified
2 files added
537 ■■■■■ changed files
.env.development 2 ●●● patch | view | raw | blame | history
.env.preview 4 ●●●● patch | view | raw | blame | history
src/api/capital.js 30 ●●●●● patch | view | raw | blame | history
src/api/managesettings.js 34 ●●●●● patch | view | raw | blame | history
src/config/router.config.js 12 ●●●●● patch | view | raw | blame | history
src/locales/lang/en-US/account/settings.js 1 ●●●● patch | view | raw | blame | history
src/locales/lang/zh-CN/account/settings.js 1 ●●●● patch | view | raw | blame | history
src/mock/services/user.js 11 ●●●●● patch | view | raw | blame | history
src/views/account/settings/Index.vue 5 ●●●●● patch | view | raw | blame | history
src/views/account/settings/googleAuthCode.vue 233 ●●●●● patch | view | raw | blame | history
src/views/capital/payOption.vue 187 ●●●●● patch | view | raw | blame | history
src/views/capital/withdrawallist.vue 2 ●●● patch | view | raw | blame | history
src/views/user/Login.vue 15 ●●●●● patch | view | raw | blame | history
.env.development
@@ -9,4 +9,4 @@
# VUE_APP_API_BASE_URL=https://api.ispentagon-institution.com/
# VUE_APP_API_BASE_URL= https://www.prudentcapitals.net/
# VUE_APP_API_BASE_URL=https://api.guosen.org/
VUE_APP_API_BASE_URL = https://api.nalandacapital.icu/
VUE_APP_API_BASE_URL = https://api.nalandacapital.icu/
.env.preview
@@ -2,6 +2,6 @@
VUE_APP_PREVIEW=true
VUE_APP_API_BASE_URL=https://api.durocapital.top/
VUE_APP_API_BASE_URL=https://api.nalandacapital.cyou/
# VUE_APP_API_BASE_URL=http://192.168.10.11:8091/
# VUE_APP_API_BASE_URL=http://192.168.10.4:8091/
src/api/capital.js
@@ -12,6 +12,9 @@
  cashlist: '/admin/cash/list.do', // 资金记录
  logtransList: '/admin/log/transList.do', // 资金互转记录
  moneylog: '/admin/moneylog/moneylogAll.do', // 资金互转记录
  payOptionList: '/admin/payOption/list.do', // 支付设置列表
  payOptionUpdateSort: '/admin/payOption/updateSort.do', // 支付设置排序
  payOptionSetEnabled: '/admin/payOption/setEnabled.do', // 支付设置开启/关闭
}
/**
@@ -115,3 +118,30 @@
    data: qs.stringify(parameter),
  })
}
export function payOptionList(parameter) {
  return request({
    url: userApi.payOptionList,
    method: 'post',
    data: qs.stringify(parameter || {}),
  })
}
export function payOptionUpdateSort(parameter) {
  return request({
    url: userApi.payOptionUpdateSort,
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
    },
    data: parameter,
  })
}
export function payOptionSetEnabled(parameter) {
  return request({
    url: userApi.payOptionSetEnabled,
    method: 'post',
    data: qs.stringify(parameter),
  })
}
src/api/managesettings.js
@@ -4,7 +4,11 @@
    adminlist: '/admin/list.do', // 管理列表
    adminupdateLock: '/admin/updateLock.do', // 管理锁定 解锁
    adminadd: '/admin/add.do', // 添加管理员
    adminupdate: '/admin/update.do' // 修改管理员密码
    adminupdate: '/admin/update.do' ,// 修改管理员密码
    getAdmin: '/api/admin/getAdmin',//获取当前管理用户信息
    getLoginGoogleAuthSecret: '/api/admin/getLoginGoogleAuthSecret',//生成秘钥二维码
    bindGoogleAuth: '/api/admin/bindGoogleAuth',//获取当前管理验证码
    unbindingGoogleAuth:'/api/admin/unbindingGoogleAuth',//解绑
}
/**
@@ -18,6 +22,34 @@
 * @param parameter
 * @returns {*}
 */
export function unbindingGoogleAuth (parameter) {
    return request({
        url: userApi.unbindingGoogleAuth,
        method: 'post',
        data: qs.stringify(parameter)
    })
}
export function getLoginGoogleAuthSecret (parameter) {
    return request({
        url: userApi.getLoginGoogleAuthSecret,
        method: 'get',
        data: qs.stringify(parameter)
    })
}
export function bindGoogleAuth (parameter) {
    return request({
        url: userApi.bindGoogleAuth,
        method: 'post',
        data: qs.stringify(parameter)
    })
}
export function getAdmin (parameter) {
    return request({
        url: userApi.getAdmin,
        method: 'get',
        data: qs.stringify(parameter)
    })
}
export function adminlist (parameter) {
    return request({
        url: userApi.adminlist,
src/config/router.config.js
@@ -231,6 +231,12 @@
            component: () => import('@/views/capital/withdrawallist'),
            meta: { title: '提现列表', keepAlive: true, permission: ['withdrawallist'] },
          },
          {
            path: '/capital/payOption',
            name: 'payOption',
            component: () => import('@/views/capital/payOption.vue'),
            meta: { title: '支付设置', keepAlive: true, permission: ['rechargelist'] },
          },
          // {
          //   path: '/capital/fundrecords',
          //   name: 'fundrecords',
@@ -606,6 +612,12 @@
                  permission: ['user'],
                },
              },
              {
                path: '/account/settings/googleAuthCode',
                name: 'GoogleAuthCode',
                component: () => import('@/views/account/settings/googleAuthCode'),
                meta: { title: 'account.settings.menuMap.googleAuthCode', hidden: true, keepAlive: true, permission: ['user'] },
              },
            ],
          },
        ],
src/locales/lang/en-US/account/settings.js
@@ -1,6 +1,7 @@
export default {
  'account.settings.menuMap.basic': '基本设置',
  'account.settings.menuMap.security': '安全设置',
  'account.settings.menuMap.googleAuthCode': '绑定谷歌验证器',
  'account.settings.menuMap.custom': '个性化',
  'account.settings.menuMap.binding': '账号绑定',
  'account.settings.menuMap.notification': '新消息通知',
src/locales/lang/zh-CN/account/settings.js
@@ -1,6 +1,7 @@
export default {
  'account.settings.menuMap.basic': '基本设置',
  'account.settings.menuMap.security': '安全设置',
  'account.settings.menuMap.googleAuthCode': '绑定谷歌验证器',
  'account.settings.menuMap.custom': '个性化',
  'account.settings.menuMap.binding': '账号绑定',
  'account.settings.menuMap.notification': '新消息通知',
src/mock/services/user.js
@@ -869,6 +869,17 @@
      component: 'SecuritySettings'
    },
    {
      name: 'GoogleAuthCode',
      path: '/account/settings/googleAuthCode',
      parentId: 10030,
      id: 10033,
      meta: {
        title: 'account.settings.menuMap.googleAuthCode',
        show: false
      },
      component: 'GoogleAuthCode'
    },
    {
      name: 'CustomSettings',
      path: '/account/settings/custom',
      parentId: 10030,
src/views/account/settings/Index.vue
@@ -19,6 +19,11 @@
                {{ $t('account.settings.menuMap.security') }}
              </router-link>
            </a-menu-item>
            <a-menu-item key="/account/settings/googleAuthCode">
              <router-link :to="{ name: 'GoogleAuthCode' }">
                {{ $t('account.settings.menuMap.googleAuthCode') }}
              </router-link>
            </a-menu-item>
            <!-- <a-menu-item key="/account/settings/custom">
              <router-link :to="{ name: 'CustomSettings' }">
                {{ $t('account.settings.menuMap.custom') }}
src/views/account/settings/googleAuthCode.vue
New file
@@ -0,0 +1,233 @@
<template>
  <div class="account-settings-info-view">
    <a-form layout="vertical" :form="addUserform" ref="addUserform" v-if="!googleAuthBind">
      <a-row :gutter="16" type="flex" justify="center">
        <a-col :order="isMobile ? 2 : 1" :md="24" :lg="16">
          <a-form-item label="秘钥">
            <a-input
              placeholder="请点击右侧 生成秘钥和二维码"
              readonly
              @click="handleCopy"
              :addonAfter="addonContent"
              v-decorator="['secret', { rules: [{ required: false, message: '请输入您的昵称' }] }]"
            />
            <img v-if="googleAuthimg" style="width: 100px;margin-top:10px;" :src="googleAuthimg"/>
          </a-form-item>
          <a-form-item label="谷歌验证码">
            <a-input
              placeholder="请输入谷歌验证码"
              v-decorator="['googleAuthCode', { rules: [{ required: true, message: '请输入谷歌验证码' }] }]"
            />
          </a-form-item>
          <!-- <a-form-item label="超级谷歌验证码">
            <a-input
              placeholder="请输入超级谷歌验证码"
              v-decorator="['rootGoogleAuthCode', { rules: [{ required: true, message: '请输入超级谷歌验证码' }] }]"
            />
          </a-form-item> -->
          <a-form-item>
            <a-button type="primary" @click="saveinfo">绑定</a-button>
          </a-form-item>
        </a-col>
      </a-row>
    </a-form>
    <div v-else style="">
      <div style="margin-bottom: 20px;">已绑定</div>
      <a-form-item label="谷歌验证码">
        <a-input
          placeholder="请输入谷歌验证码"
          v-model="ggyzm"
          v-decorator="['googleAuthCode', { rules: [{ required: true, message: '请输入谷歌验证码' }] }]"
        />
      </a-form-item>
      <a-button type="primary" @click="adskille">解绑</a-button>
    </div>
    <avatar-modal ref="modal" @ok="setavatar" />
  </div>
</template>
<script>
import AvatarModal from './AvatarModal'
import { baseMixin } from '@/store/app-mixin'
import { adminlist, adminupdate,bindGoogleAuth,getLoginGoogleAuthSecret,getAdmin,unbindingGoogleAuth } from '@/api/managesettings'
import pick from 'lodash.pick'
export default {
  mixins: [baseMixin],
  components: {
    AvatarModal,
  },
  data() {
    return {
      // cropper
      addonContent: (
              <a
                onClick={this.handleGenerate} // 这里是点击事件
              >
                生成秘钥和二维码
              </a>
      ),
      preview: {},
      googleAuthimg:'',
      ggyzm:'',
      userid:'',
      googleAuthBind:'',
      option: {
        img: '/avatar2.jpg',
        info: true,
        size: 1,
        outputType: 'jpeg',
        canScale: false,
        autoCrop: true,
        // 只有自动截图开启 宽度高度才生效
        autoCropWidth: 180,
        autoCropHeight: 180,
        fixedBox: true,
        // 开启宽度和高度比例
        fixed: true,
        fixedNumber: [1, 1],
      },
      settingdetail: {},
      addUserform: this.$form.createForm(this),
      fields: ['googleAuthCode', 'secret','id'],
    }
  },
  mounted() {
    this.getnowuser()
  },
  methods: {
    adskille(){
          var values ={}
          values.rootGoogleAuthCode = this.ggyzm
          values.id = this.userid
          unbindingGoogleAuth(values).then((res) => {
            if (res.status == 0) {
              this.getnowuser()
              this.$message.success({ content: '解绑成功', duration: 2 });
              form.resetFields();
            } else {
              this.$message.error(res.msg);
            }
          });
    },
    getnowuser() {
      getAdmin().then((res) => {
        if(res.status==0){
          this.userid = res.data.id
          this.googleAuthBind = res.data.googleAuthBind
        }
        console.log(res);
      })
    },
    setavatar(url) {
      this.option.img = url
    },
    handleCopy() {
          // 使用浏览器的 execCommand 来实现复制功能
          const input = document.createElement('input');
          input.value = this.addUserform.getFieldValue('secret');  // 这里用你的秘钥变量
          document.body.appendChild(input);
          input.select();
          document.execCommand('copy');
          document.body.removeChild(input);
          this.$message.success('秘钥已复制');
     },
    handleGenerate() {
      getLoginGoogleAuthSecret().then((res) => {
        if (res.status == 0) {
          // this.$set(this.$refs.addUserform.form, 'secret', res.data.googleAuthSecret);
          this.addUserform.setFieldsValue({
            secret: res.data.googleAuthSecret,
          })
          this.googleAuthimg = res.data.googleAuthImg;
        } else {
          this.$message.error(res.msg);
        }
      });
    },
    saveinfo() {
      const form = this.$refs.addUserform.form;
      form.validateFields((errors, values) => {
        if (!errors) {
          values.id = this.userid
          bindGoogleAuth(values).then((res) => {
            if (res.status == 0) {
              this.getnowuser()
              this.$message.success({ content: '绑定成功', duration: 2 });
              form.resetFields();
              this.getnowuser();
            } else {
              this.$message.error(res.msg);
            }
          });
        }
      });
    }
  },
}
</script>
<style lang="less" scoped>
.avatar-upload-wrapper {
  height: 200px;
  width: 100%;
}
.ant-upload-preview {
  position: relative;
  margin: 0 auto;
  width: 100%;
  max-width: 180px;
  border-radius: 50%;
  box-shadow: 0 0 4px #ccc;
  .upload-icon {
    position: absolute;
    top: 0;
    right: 10px;
    font-size: 1.4rem;
    padding: 0.5rem;
    background: rgba(222, 221, 221, 0.7);
    border-radius: 50%;
    border: 1px solid rgba(0, 0, 0, 0.2);
  }
  .mask {
    opacity: 0;
    position: absolute;
    background: rgba(0, 0, 0, 0.4);
    cursor: pointer;
    transition: opacity 0.4s;
    &:hover {
      opacity: 1;
    }
    i {
      font-size: 2rem;
      position: absolute;
      top: 50%;
      left: 50%;
      margin-left: -1rem;
      margin-top: -1rem;
      color: #d6d6d6;
    }
  }
  img,
  .mask {
    width: 100%;
    max-width: 180px;
    height: 100%;
    border-radius: 50%;
    overflow: hidden;
  }
}
</style>
<style>
</style>
src/views/capital/payOption.vue
New file
@@ -0,0 +1,187 @@
<template>
  <page-header-wrapper>
    <a-card :bordered="false">
      <a-table
        bordered
        :loading="loading"
        :columns="columns"
        :data-source="datalist"
        :pagination="false"
        rowKey="id"
        :customRow="customRow"
      >
        <span slot="enabled" slot-scope="text, record">
          <a-tag :color="record.enabled === 1 ? 'green' : 'red'">
            {{ record.enabled === 1 ? '开启' : '关闭' }}
          </a-tag>
        </span>
        <template slot="action" slot-scope="text, record">
          <a-button
            type="link"
            size="small"
            @click="toggleEnabled(record)"
            :loading="record._loading"
          >
            {{ record.enabled === 1 ? '关闭' : '开启' }}
          </a-button>
        </template>
        <span slot="dragHandle" class="drag-handle">
          <a-icon type="menu" />
        </span>
      </a-table>
    </a-card>
  </page-header-wrapper>
</template>
<script>
import { payOptionList, payOptionUpdateSort, payOptionSetEnabled } from '@/api/capital'
export default {
  name: 'PayOption',
  data() {
    return {
      columns: [
        {
          title: '排序',
          key: 'sort',
          width: 60,
          align: 'center',
          scopedSlots: { customRender: 'dragHandle' },
        },
        {
          title: '名称',
          dataIndex: 'name',
          align: 'center',
        },
        {
          title: '排序序号',
          dataIndex: 'sortOrder',
          align: 'center',
          width: 120,
        },
        {
          title: '状态',
          dataIndex: 'enabled',
          align: 'center',
          width: 100,
          scopedSlots: { customRender: 'enabled' },
        },
        {
          title: '操作',
          key: 'action',
          align: 'center',
          width: 120,
          scopedSlots: { customRender: 'action' },
        },
      ],
      loading: false,
      datalist: [],
      dragIndex: null,
    }
  },
  created() {
    this.getList()
  },
  methods: {
    getList() {
      this.loading = true
      payOptionList()
        .then((res) => {
          this.loading = false
          if (res.status === 0 && Array.isArray(res.data)) {
            this.datalist = (res.data || [])
              .slice()
              .sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))
          } else {
            this.datalist = []
          }
        })
        .catch(() => {
          this.loading = false
          this.datalist = []
        })
    },
    customRow(record, index) {
      return {
        attrs: {
          draggable: true,
        },
        on: {
          dragstart: (e) => this.onDragStart(e, index),
          dragover: (e) => this.onDragOver(e, index),
          drop: (e) => this.onDrop(e, index),
        },
      }
    },
    onDragStart(e, index) {
      this.dragIndex = index
      e.dataTransfer.effectAllowed = 'move'
      e.dataTransfer.setData('text/plain', index)
      try {
        e.target.classList.add('drag-over')
      } catch (_) {}
    },
    onDragOver(e, index) {
      e.preventDefault()
      e.dataTransfer.dropEffect = 'move'
    },
    onDrop(e, dropIndex) {
      e.preventDefault()
      try {
        e.target.classList.remove('drag-over')
      } catch (_) {}
      const dragIndex = this.dragIndex
      if (dragIndex == null || dragIndex === dropIndex) return
      const list = this.datalist.slice()
      const [item] = list.splice(dragIndex, 1)
      list.splice(dropIndex, 0, item)
      this.datalist = list
      this.dragIndex = null
      const orderedIds = list.map((i) => i.id)
      // console.log(orderedIds, 'orderedIds');
      // return
      payOptionUpdateSort(orderedIds)
        .then((res) => {
          if (res.status === 0) {
            this.$message.success('排序已更新')
          } else {
            this.$message.error(res.msg || '排序更新失败')
            this.getList()
          }
        })
        .catch(() => {
          this.$message.error('排序更新失败')
          this.getList()
        })
    },
    toggleEnabled(record) {
      const enabled = record.enabled === 1 ? 0 : 1
      this.$set(record, '_loading', true)
      payOptionSetEnabled({ id: record.id, enabled })
        .then((res) => {
          this.$set(record, '_loading', false)
          if (res.status === 0) {
            record.enabled = enabled
            this.$message.success(enabled === 1 ? '已开启' : '已关闭')
          } else {
            this.$message.error(res.msg || '操作失败')
          }
        })
        .catch(() => {
          this.$set(record, '_loading', false)
          this.$message.error('操作失败')
        })
    },
  },
}
</script>
<style scoped>
.drag-handle {
  cursor: move;
  color: #999;
}
.drag-handle:hover {
  color: #1890ff;
}
</style>
src/views/capital/withdrawallist.vue
@@ -128,7 +128,7 @@
        <a-button type="primary" style="background-color: " @click="OkeditOrderdialog(3)">驳回</a-button>
        <a-button type="primary" @click="OkeditOrderdialog(2)">通过</a-button>
        <a-button type="primary" @click="OkeditOrderdialog(1)">代付1</a-button>
        <!-- <a-button type="primary" @click="OkeditOrderdialog(4)">代付2</a-button> -->
        <a-button type="primary" @click="OkeditOrderdialog(4)">代付2</a-button>
      </div>
    </a-modal>
  </page-header-wrapper>
src/views/user/Login.vue
@@ -36,6 +36,18 @@
              <a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }" />
            </a-input-password>
          </a-form-item>
          <a-form-item>
            <a-input
              size="large"
              type="number"
              placeholder="请输入谷歌验证码"
              v-decorator="[
                'googleAuthCode',
                { rules: [], validateTrigger: 'change' }
              ]">
            </a-input>
          </a-form-item>
        </a-tab-pane>
        <!-- <a-tab-pane key="tab2" :tab="$t('user.login.tab-login-mobile')">
          <a-form-item>
@@ -174,7 +186,7 @@
      state.loginBtn = true
      const validateFieldsKey = customActiveKey === 'tab1' ? ['username', 'password'] : ['mobile', 'captcha']
      const validateFieldsKey = customActiveKey === 'tab1' ? ['username', 'password' ,'googleAuthCode'] : ['mobile', 'captcha']
      validateFields(validateFieldsKey, { force: true }, (err, values) => {
        if (!err) {
@@ -183,6 +195,7 @@
          const loginParams = {}
          loginParams.adminPhone = values.username
          loginParams.adminPwd = values.password
          loginParams.googleAuthCode = values.googleAuthCode
          loginParams.verifyCode = 1234
          Login(loginParams)
            .then((res) => this.loginSuccess(res))