Compare commits

...

14 Commits

  1. 8
      .env.production
  2. BIN
      dist.zip
  3. 162
      package-lock.json
  4. 2
      public/index.html
  5. 25
      src/App.vue
  6. 4
      src/components/List/List.vue
  7. 34
      src/config/api.js
  8. 32
      src/router/index.js
  9. 317
      src/views/Apply/apply.vue
  10. 129
      src/views/Checked/Checked.vue
  11. 156
      src/views/Checking/Checking.vue
  12. 275
      src/views/File/File.vue
  13. BIN
      src/views/File/img/640 (1).webp
  14. BIN
      src/views/File/img/640 (2).webp
  15. BIN
      src/views/File/img/640 (3).webp
  16. BIN
      src/views/File/img/640 (4).webp
  17. BIN
      src/views/File/img/640 (5).webp
  18. BIN
      src/views/File/img/640.webp
  19. 2
      src/views/FirstPage/FirstPage.vue
  20. 221
      src/views/Pay/Pay.vue
  21. 118
      src/views/PeopleList/PeopleList.vue
  22. 0
      新建文本文档.txt

8
.env.production

@ -1,10 +1,10 @@
VUE_APP_MODE=production
VUE_APP_NODE_ENV=production
VUE_APP_SCENE=checkwork
VUE_APP_BASE_URL=https://test.tall.wiki/checkwork/
VUE_APP_API_URL=https://test.tall.wiki/checkwork/gateway
VUE_APP_SCENE=
VUE_APP_BASE_URL=https://test.tall.wiki/
VUE_APP_API_URL=https://test.tall.wiki/gateway
VUE_APP_PROXY_URL=/gateway
VUE_APP_PUBLIC_PATH=/checkwork
VUE_APP_PUBLIC_PATH=/ts
VUE_APP_MSG_URL=wss://test.tall.wiki/websocket/message/v4.0/ws
VUE_APP_TITLE=考勤管理
VUE_APP_DESCRIPTION=考勤管理

BIN
dist.zip

Binary file not shown.

162
package-lock.json

@ -1808,6 +1808,16 @@
"integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"cacache": {
"version": "13.0.1",
"resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz?cache=0&sync_timestamp=1594427999421&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-13.0.1.tgz",
@ -1840,6 +1850,34 @@
"integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=",
"dev": true
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"css-loader": {
"version": "3.6.0",
"resolved": "https://registry.npm.taobao.org/css-loader/download/css-loader-3.6.0.tgz?cache=0&sync_timestamp=1604507107408&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-loader%2Fdownload%2Fcss-loader-3.6.0.tgz",
@ -1893,6 +1931,13 @@
"universalify": "^0.1.0"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"icss-utils": {
"version": "4.1.1",
"resolved": "https://registry.npm.taobao.org/icss-utils/download/icss-utils-4.1.1.tgz?cache=0&sync_timestamp=1602527330977&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficss-utils%2Fdownload%2Ficss-utils-4.1.1.tgz",
@ -2007,6 +2052,16 @@
"minipass": "^3.1.1"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"terser-webpack-plugin": {
"version": "2.3.8",
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.3.8.tgz?cache=0&sync_timestamp=1603881757308&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-2.3.8.tgz",
@ -2023,6 +2078,32 @@
"terser": "^4.6.12",
"webpack-sources": "^1.4.3"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.1",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.1.tgz",
"integrity": "sha512-V53TJbHmzjBhCG5OYI2JWy/aYDspz4oVHKxS43Iy212GjGIG1T3EsB3+GWXFm/1z5VwjdjLmdZUFYM70y77vtQ==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
}
}
}
}
},
@ -12649,87 +12730,6 @@
}
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.5.0",
"resolved": "https://registry.nlark.com/vue-loader/download/vue-loader-16.5.0.tgz?cache=0&sync_timestamp=1628666727543&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvue-loader%2Fdownload%2Fvue-loader-16.5.0.tgz",
"integrity": "sha1-CcTgcSRmiZ40uZpoZSTxkWX7KJI=",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1618995588464&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz",
"integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.nlark.com/chalk/download/chalk-4.1.2.tgz?cache=0&sync_timestamp=1627646734234&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.2.tgz",
"integrity": "sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
"integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz",
"integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1626716095603&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
"integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz",
"integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.nlark.com/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1626703400240&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
"integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-quill-editor": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/vue-quill-editor/-/vue-quill-editor-3.0.6.tgz",

2
public/index.html

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/tailwindcss@2.2.7/dist/tailwind.min.css">
<title>考勤</title>
<title>跳绳培训</title>
</head>
<body>
<noscript>

25
src/App.vue

@ -17,19 +17,32 @@ export default {
},
async created() {
const userId = this.$route.query.uid;
const roleId = this.$route.query.rid;
const params = { userId };
var query = window.location.search.substring(1);
var vars = query.split('&');
let userId = '';
let roleId = '';
let projectId = '';
vars.forEach((item, index) => {
let items = item.split('=');
if (items[0] == 'uid') {
userId = items[1];
} else if (items[0] == 'pid') {
projectId = items[1];
} else if (items[0] == 'rid') {
roleId = items[1];
}
});
const params = { userId: userId };
await this.getUserId(params);
await this.setRoleId(roleId);
await this.getAllMembers({ projectId: this.$route.query.pid });
this.setProjectId(this.$route.query.pid);
this.setProjectId(projectId);
},
methods: {
...mapMutations('home', ['setProjectId', 'setMembers', 'setRoleId']),
...mapActions('user', ['getUserId']),
...mapActions('home', ['getAllMembers']),
},
};
</script>

4
src/components/List/List.vue

@ -1,7 +1,7 @@
<template>
<div class="mt-5">
<div>
<div class="d-flex flex-nowrap table-head">
<div class="table-head-item" style="width: 16%">姓名</div>
<div class="table-head-item" style="width: 16%">姓名1</div>
<div class="table-head-item"></div>
<div class="table-head-item"></div>
<div class="table-head-item" style="width: 30%">审核人</div>

34
src/config/api.js

@ -1,18 +1,30 @@
import axios from 'axios';
const defaultwbs = `https://test.tall.wiki/gateway/defaultwbs`;
const defaultwbs = `https://test.tall.wiki/gateway/sports`;
// 查询考勤信息
export const clockQuery = params => axios.post(`${defaultwbs}/clock/query`, params);
// 查询用户信息
export const getUserInfo = params => axios.post(`${defaultwbs}/player/info`, params);
// 查询考勤信息
export const clockPunch = params => axios.post(`${defaultwbs}/clock/punch`, params);
// 报名信息提交
export const submitSignUp = params => axios.post(`${defaultwbs}/player/apply`, params);
// 查询所有成员
export const queryChecker = params => axios.post(`${defaultwbs}/deliver/queryChecker`, params);
// 培训目标列表
export const getPositionList = params => axios.post(`${defaultwbs}/player/position`, params);
// 查询所有成员
export const clockAudit = params => axios.post(`${defaultwbs}/clock/audit`, params);
// 缴费
export const toPay = params => axios.post(`${defaultwbs}/player/savePay`, params);
// 导出考勤excel
export const clockExport = params => axios.post(`${defaultwbs}/clock/export`, params);
// 上传文件
export const uploadImg = `${defaultwbs}/file/upload`;
// 学员列表
export const studentList = params => axios.post(`${defaultwbs}/player/query`, params);
// 待审核结业申请
export const auditList = params => axios.post(`${defaultwbs}/teacher/getCompletePlayer`, params);
// 审核结业申请
export const auditApply = params => axios.post(`${defaultwbs}/teacher/auditComplete`, params);
// 发证
export const certificate = params => axios.post(`${defaultwbs}/player/certificate`, params);

32
src/router/index.js

@ -1,6 +1,6 @@
import Home from 'views/Apply/apply.vue';
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from 'views/FirstPage/FirstPage.vue';
Vue.use(VueRouter);
@ -11,6 +11,36 @@ const routes = [
name: 'Home',
component: Home,
},
{
path: '/apply',
name: 'apply',
component: () => import('views/Apply/apply.vue'),
},
{
path: '/file',
name: 'file',
component: () => import('views/File/File.vue'),
},
{
path: '/pay',
name: 'pay',
component: () => import('views/Pay/Pay.vue'),
},
{
path: '/peopleList',
name: 'peopleList',
component: () => import('views/PeopleList/PeopleList.vue'),
},
{
path: '/checking',
name: 'checking',
component: () => import('views/Checking/Checking.vue'),
},
{
path: '/checked',
name: 'checked',
component: () => import('views/Checked/Checked.vue'),
},
];
const router = new VueRouter({

317
src/views/Apply/apply.vue

@ -0,0 +1,317 @@
<template>
<div class="apply-flex">
<div class="title">个人基本信息</div>
<div class="container px-6 bg-white">
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">姓名<span class="text-red-500 ml-1 align-middle">*</span></div>
<input class="text-right outline-none" v-model="name" type="text" placeholder="请输入您的姓名" />
</div>
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">身份证号<span class="text-red-500 ml-1 align-middle">*</span></div>
<input class="text-right outline-none" v-model="idCard" type="text" placeholder="请输入您的身份证号" />
</div>
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">年龄</div>
<input class="text-right outline-none" v-model="age" type="number" placeholder="请输入您的年龄" />
</div>
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">性别</div>
<a-radio-group v-model="gender" @change="onChange">
<a-radio :value="1"> </a-radio>
<a-radio :value="0"> </a-radio>
</a-radio-group>
</div>
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">身份<span class="text-red-500 ml-1 align-middle">*</span></div>
<div class="flex justify-end items-center" @click="openMenu(1)">
<span class="mr-1 truncate">{{ positionName }}</span>
<a-icon type="right" />
</div>
</div>
</div>
<div class="title">联系方式</div>
<div class="container px-6 bg-white">
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">地址</div>
<input class="text-right outline-none" v-model="address" type="text" placeholder="请输入您的详细地址" />
</div>
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">电话<span class="text-red-500 ml-1 align-middle">*</span></div>
<input class="text-right outline-none" v-model="phone" type="text" placeholder="请输入您的电话" />
</div>
</div>
<div class="title">培训信息</div>
<div class="container px-6 bg-white">
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">培训目标<span class="text-red-500 ml-1 align-middle">*</span></div>
<div class="flex justify-end items-center" @click="openMenu(2)">
<span class="mr-1 truncate">{{ targetName }}</span>
<a-icon type="right" />
</div>
</div>
</div>
<div class="mt-14 px-6" v-if="!isApply">
<button class="bg-blue-500 text-white w-full h-10 rounded" @click="submitSignUp">立即报名</button>
</div>
<div class="fixed top-0 bottom-0 left-0 right-0 bg-black bg-opacity-60" v-if="showMenu">
<div class="target-list absolute bottom-0 w-full bg-white">
<div class="item-box text-center font-semibold border-b">{{ title }}</div>
<div class="list">
<div class="item-box text-center" v-for="(item, index) in targetList" :key="index" :id="item.id" @click="selectTarget(item)">
{{ item.name }}
</div>
</div>
<div class="bg-gray-300 h-2"></div>
<div class="item-box text-center" @click="cancel">取消</div>
</div>
</div>
<div>
<div class="w-screen h-screen fixed z-10 statusChoose bg-black bg-opacity-50" style="display: none; top: 0; left: 0">
<div class="flex flex-col absolute w-full bg-white" style="bottom: 0">
<div class="flex flex-row justify-between px-5 py-4">
<span class="text-gray-400" onclick="hide()">取消</span>
<span class="text-blue-500" onclick="choose()">确定</span>
</div>
<div class="bg-gray-200" style="width: 100%; height: 1px"></div>
<ul class="flex flex-col text-center" style="height: 240px; overflow-y: auto"></ul>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { getUserInfo, submitSignUp, getPositionList } from '@/config/api';
export default {
data() {
return {
timer: null,
name: '', //
idCard: '', //
age: '', //
gender: -1, //
genderName: '', //
positionId: 0, //
positionName: '请选择当前身份', //
address: '', //
phone: '', //
targetId: 0, //
targetName: '请选择培训目标', //
targetList: [],
showMenu: false,
isApply: 1, //
title: '',
playerId: '',
currType: 1,
};
},
computed: mapState('home', ['projectId', 'roleId']),
mounted() {
this.timer = setInterval(async () => {
if (this.projectId) {
clearInterval(this.timer);
await this.getUserInfo();
await this.getTargetList();
}
}, 300);
},
methods: {
onChange(e) {
this.gender = e.target.value;
},
async openMenu(type) {
this.currType = type;
if (type === 1) {
this.title = '当前身份';
} else {
this.title = '培训目标';
}
await this.getTargetList();
this.showMenu = true;
},
cancel() {
this.showMenu = false;
},
/**
* 选择培训目标
*/
selectTarget(item) {
this.cancel();
if (this.currType == 1) {
this.positionId = item.id;
this.positionName = item.name;
} else if (this.currType == 2) {
this.targetId = item.id;
this.targetName = item.name;
}
},
/**
* 培训目标列表
*/
async getTargetList() {
try {
const params = { param: {} };
const res = await getPositionList();
const { code, msg, data } = res.data;
if (code === 200) {
this.targetList = data;
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
/**
* 报名
*/
async submitSignUp() {
try {
if (!this.name) {
this.$message.info('请输入姓名');
return false;
}
if (!this.idCard) {
this.$message.info('请输入身份证号');
return false;
}
if (this.positionId === 0) {
this.$message.info('请选择当前身份等级');
return false;
}
if (!this.phone) {
this.$message.info('请输入手机号');
return false;
}
if (this.targetId === 0) {
this.$message.info('请选择培训目标');
return false;
}
const params = {
param: {
projectId: this.projectId,
name: this.name,
idCard: this.idCard,
age: this.age,
gender: this.gender,
positionId: this.positionId,
address: this.address,
phone: this.phone,
targetId: this.targetId,
},
};
const res = await submitSignUp(params);
const { code, msg, data } = res.data;
if (code === 200) {
window.history.back();
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
/**
* 个人信息
*/
async getUserInfo() {
try {
const params = { param: { projectId: this.projectId } };
const res = await getUserInfo(params);
const { code, msg, data } = res.data;
if (code === 200) {
if (data) {
this.isApply = 1;
this.name = data.name;
this.idCard = data.idCard;
this.age = data.age;
this.genderName = data.gender == 1 ? '男' : '女';
this.gender = data.gender;
this.positionName = data.position;
this.address = data.address;
this.phone = data.phone;
this.targetName = data.target;
} else {
this.isApply = 0;
}
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
},
};
</script>
<style lang="scss" scoped>
.apply-flex {
width: 100%;
min-height: 100vh;
background: #f3f3f3;
.title {
padding-top: 12px;
padding-left: 16px;
height: 48px;
line-height: 36px;
}
.item-box {
height: 48px;
line-height: 48px;
.item-title {
width: 80px;
flex-shrink: 0;
}
input {
height: 40px;
width: calc(100% - 80px);
}
input:disabled {
background-color: transparent;
}
div.flex {
width: calc(100% - 80px);
}
}
}
</style>

129
src/views/Checked/Checked.vue

@ -0,0 +1,129 @@
<template>
<div class="list-flex">
<div class="px-4 pb-2 bg-white">
<div class="title flex items-center justify-between border-b">
<div class="text-gray-400 text-center" style="width: 30%">ID</div>
<div class="text-gray-400 text-center" style="width: 25%">姓名</div>
<div class="text-gray-400 text-center" style="width: 40%">操作</div>
</div>
<div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 30%">123456789</div>
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center flex justify-center items-center" style="width: 40%">
<button class="btn px-2 border border-blue-500 bg-blue-500 text-white rounded-sm" @click="certificate(id)">发证</button>
</div>
</div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 30%">123456789</div>
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center flex justify-center items-center" style="width: 40%">
<button class="btn px-2 border border-blue-500 bg-blue-500 text-white rounded-sm" @click="certificate(id)">发证</button>
</div>
</div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 30%">123456789</div>
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center flex justify-center items-center" style="width: 40%">
<button class="btn px-2 border border-blue-500 bg-blue-500 text-white rounded-sm" @click="certificate(id)">发证</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
import { auditList, certificate } from '@/config/api';
export default {
data() {
return {
timer: null,
lists: [],
};
},
computed: mapState('home', ['projectId', 'roleId']),
mounted() {
this.timer = setInterval(async () => {
if (this.projectId) {
clearInterval(this.timer);
await this.getAuditList();
}
}, 300);
},
methods: {
/**
* 获取待审核结业申请列表
*/
async getAuditList() {
try {
const params = { param: { projectId: this.projectId } };
const res = await auditList();
const { code, msg, data } = res.data;
if (code === 200) {
this.lists = data;
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
/**
* 发证
*/
async certificate(playerId) {
try {
const params = {
param: {
projectId: this.projectId,
playerId: playerId,
type: type,
remark: this.remark,
},
};
const res = await certificate();
const { code, msg, data } = res.data;
if (code === 200) {
this.getAuditList();
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
},
};
</script>
<style lang="scss" scoped>
.list-flex {
width: 100%;
min-height: 100vh;
background: #f3f3f3;
.title {
height: 48px;
line-height: 48px;
}
.item {
.btn {
height: 26px;
line-height: 24px;
}
}
}
</style>

156
src/views/Checking/Checking.vue

@ -0,0 +1,156 @@
<template>
<div class="list-flex">
<div class="px-4 pb-2 bg-white">
<div class="title flex items-center justify-between border-b">
<div class="text-gray-400 text-center" style="width: 30%">ID</div>
<div class="text-gray-400 text-center" style="width: 25%">姓名</div>
<div class="text-gray-400 text-center" style="width: 40%">操作</div>
</div>
<div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 30%">123456789</div>
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center flex justify-center items-center" style="width: 40%">
<button class="btn mr-2 px-2 border border-blue-500 text-blue-500 rounded-sm" @click="rejectModal">驳回</button>
<button class="btn px-2 border border-blue-500 bg-blue-500 text-white rounded-sm" @click="auditApply(2)">通过</button>
</div>
</div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 30%">123456789</div>
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center flex justify-center items-center" style="width: 40%">
<button class="btn mr-2 px-2 border border-blue-500 text-blue-500 rounded-sm">驳回</button>
<button class="btn px-2 border border-blue-500 bg-blue-500 text-white rounded-sm">通过</button>
</div>
</div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 30%">123456789</div>
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center flex justify-center items-center" style="width: 40%">
<button class="btn mr-2 px-2 border border-blue-500 text-blue-500 rounded-sm">驳回</button>
<button class="btn px-2 border border-blue-500 bg-blue-500 text-white rounded-sm">通过</button>
</div>
</div>
</div>
</div>
<a-modal title="驳回原因" :visible="visible" @ok="handleOk" @cancel="handleCancel">
<textarea class="reject-con border border-gray-200 w-full rounded-sm p-2" v-model="modalText" placeholder="请输入驳回原因" />
</a-modal>
</div>
</template>
<script>
import { mapState } from 'vuex';
import { auditList, auditApply } from '@/config/api';
export default {
data() {
return {
timer: null,
lists: [],
playerId: '',
remark: '',
visible: false,
modalText: '',
showModal: false,
};
},
computed: mapState('home', ['projectId', 'roleId']),
mounted() {
this.timer = setInterval(async () => {
if (this.projectId) {
clearInterval(this.timer);
await this.getAuditList();
}
}, 300);
},
methods: {
//
rejectModal() {
this.visible = true;
},
handleOk(e) {
this.remark = this.modalText;
this.visible = false;
this.auditApply(3);
},
handleCancel(e) {
this.visible = false;
},
/**
* 获取待审核结业申请列表
*/
async getAuditList() {
try {
const params = { param: { projectId: this.projectId } };
const res = await auditList();
const { code, msg, data } = res.data;
if (code === 200) {
this.lists = data;
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
/**
* 审核结业申请
*/
async auditApply(type) {
try {
const params = {
param: {
projectId: this.projectId,
playerId: this.playerId,
type: type,
remark: this.remark,
},
};
const res = await auditList();
const { code, msg, data } = res.data;
if (code === 200) {
this.getAuditList();
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
},
};
</script>
<style lang="scss" scoped>
.list-flex {
width: 100%;
min-height: 100vh;
background: #f3f3f3;
.title {
height: 48px;
line-height: 48px;
}
.item {
.btn {
height: 26px;
line-height: 24px;
}
}
}
</style>

275
src/views/File/File.vue

@ -0,0 +1,275 @@
<template>
<div>
<!-- <div
data-tname="文件"
data-pid="1433332016270811136"
data-uid="1217647686598135808"
data-rid="rid333"
data-tid="tid444"
data-did="did555"
style="height: 5.375rem; width: 100%"
> -->
<div data-root="p1432643387798069248" style="height: 100%; width: 100%">
<div class="title"></div>
<ul>
<li><img src="./img/640.webp" alt="" /></li>
<li><img src="./img/640 (1).webp" alt="" /></li>
<li><img src="./img/640 (2).webp" alt="" /></li>
<li><img src="./img/640 (3).webp" alt="" /></li>
<li><img src="./img/640 (4).webp" alt="" /></li>
<li><img src="./img/640 (5).webp" alt="" /></li>
</ul>
</div>
<!-- </div> -->
</div>
</template>
<script>
// import { mapState, mapMutations } from 'vuex';
// import { clockQuery, clockPunch, clockAudit } from '@/config/api';
// const columns = [
// { title: '', dataIndex: 'memberName', key: 'memberName', align: 'center', width: '16%' },
// { title: '', dataIndex: 'morning', key: 'morning', scopedSlots: { customRender: 'morning' }, align: 'center', width: '27%' },
// { title: '', dataIndex: 'night', key: 'night', scopedSlots: { customRender: 'night' }, align: 'center', width: '27%' },
// {
// title: '',
// dataIndex: 'checkerName',
// key: 'checkerName',
// scopedSlots: { customRender: 'checkerName' },
// align: 'center',
// width: '30%',
// },
// ];
// export default {
// data() {
// return {
// columns,
// clockInfos: [],
// options: null,
// checkerId: undefined,
// placement: 'left',
// timer: null,
// chooseTime: '',
// auditOptions: null,
// morningLoading: false,
// nightLoading: false,
// today: this.$moment(new Date()).format('YYYY-MM-DD'),
// selectedDate: '', //
// };
// },
// computed: mapState('home', ['projectId', 'members', 'startTime', 'endTime', 'memberIdList', 'roleId', 'checkers']),
// mounted() {
// this.timer = setInterval(async () => {
// if (this.projectId) {
// clearInterval(this.timer);
// await this.setParams();
// //
// // document.querySelector('#scrollTo').scrollIntoView({
// // behavior: 'smooth', //
// // block: 'start', //
// // });
// }
// }, 300);
// const time = this.$moment(Date.now()).format('YYYY-MM-DD');
// if (!this.startTime) {
// this.setStartTime(this.$moment(`${time} 00:00`).format('x') - 0);
// }
// if (!this.endTime) {
// this.setEndTime(this.$moment(`${time} 23:59`).format('x') - 0);
// }
// },
// methods: {
// ...mapMutations('home', ['setStartTime', 'setEndTime', 'setMemberIdList']),
// async setParams() {
// const { projectId, startTime, endTime, memberIdList, roleId } = this;
// const params = { param: { projectId, memberIdList, startTime, endTime, roleId } };
// await this.getClockQuery(params);
// },
// /**
// *
// * @param {string} projectId
// * @param {array} memberIdList
// * @param {string} startTime
// * @param {string} endTime
// */
// async getClockQuery(params) {
// try {
// const res = await clockQuery(params);
// const { code, msg, data } = res.data;
// if (code === 200) {
// data.forEach(item => {
// item.recordList.forEach(clcok => {
// clcok.morningVisible = false;
// clcok.nightVisible = false;
// clcok.showNightTime = false;
// clcok.showMorningTime = false;
// });
// });
// this.clockInfos = [...data];
// } else {
// this.$message.error(msg || '');
// throw msg;
// }
// } catch (error) {
// throw error || '';
// }
// },
// //
// chooseChecker(value) {
// this.checkerId = value;
// },
// //
// checkTime(listIndex, index, clockType, id, memberId, checkerId, clockTime) {
// const time = Date.now();
// const selectTime = this.$moment(time).format('HH:mm');
// if (clockType === 0) {
// this.clockInfos[listIndex].recordList[index].morning = selectTime;
// } else {
// this.clockInfos[listIndex].recordList[index].night = selectTime;
// }
// const dateTime = this.$moment(`${clockTime} ${selectTime}`).format('x') - 0;
// const params = { param: { checkerId: this.checkerId || checkerId || this.checkers[0].memberId, clockType, dateTime, id, memberId } };
// this.handleClockPunch(params);
// },
// /**
// *
// * @param {string} checkerId id
// * @param {array} clockType (0-,1-)
// * @param {string} dateTime
// * @param {string} id id()
// * @param {string} memberId id
// */
// async handleClockPunch(params) {
// try {
// if (params.param.clockType === 0) {
// this.morningLoading = true;
// } else {
// this.nightLoading = true;
// }
// const res = await clockPunch(params);
// const { code, msg } = res.data;
// if (code === 200) {
// this.$message.success('');
// const options = { startTime: this.startTime, endTime: this.endTime, memberIdList: this.memberIdList };
// this.setParams(options);
// } else {
// this.$message.error(msg || '');
// throw msg;
// }
// if (params.param.clockType === 0) {
// this.morningLoading = false;
// } else {
// this.nightLoading = false;
// }
// } catch (error) {
// if (params.param.clockType === 0) {
// this.morningLoading = false;
// } else {
// this.nightLoading = false;
// }
// throw error || '';
// }
// },
// changeVisible(index, status, type) {
// if (status !== 0) {
// this.clockInfos.forEach(item => {
// item.recordList.forEach((clcok, i) => {
// if (i === index && type === 'morningVisible') {
// clcok.morningVisible = !clcok.morningVisible;
// clcok.nightVisible = false;
// } else if (i === index && type === 'nightVisible') {
// clcok.morningVisible = false;
// clcok.nightVisible = !clcok.nightVisible;
// } else {
// clcok.morningVisible = false;
// clcok.nightVisible = false;
// }
// });
// });
// }
// },
// //
// changeStatus(id, type, record, visible, show, selectedDate) {
// record[visible] = false;
// record[show] = true;
// this.selectedDate = selectedDate;
// this.auditOptions = { id, type };
// },
// //
// timeChange(time) {
// let updateTime = this.$moment(time).format('HH:mm:ss');
// let updateDate = this.selectedDate + ' ' + updateTime;
// this.chooseTime = this.$moment(updateDate).format('x');
// },
// async openChange(open, record, show, timeType) {
// if (!open && this.chooseTime) {
// this.auditOptions[timeType] = this.chooseTime;
// this.auditOptions.projectId = this.projectId;
// const params = { param: this.auditOptions };
// await this.handleClockAudit(params, record, show);
// }
// if (!open && !this.chooseTime) {
// record[show] = false;
// }
// },
// //
// async rejectStatus(id, type, timeType, time, record, show) {
// record[show] = false;
// const params = { param: { id, type, [timeType]: time, projectId: this.projectId } };
// await this.handleClockAudit(params, record, show);
// },
// //
// cancel(record, type) {
// record[type] = false;
// },
// /**
// *
// * @param {string} id id
// * @param {string} morning
// * @param {string} night
// * @param {string} projectId id
// * @param {string} type (0-,1-,2-)
// */
// async handleClockAudit(params, record, show) {
// try {
// const res = await clockAudit(params);
// const { code, msg } = res.data;
// if (code === 200) {
// this.$message.success(params.param.type === 0 ? '' : params.param.type === 1 ? '' : '');
// record[show] = false;
// this.auditOptions = null;
// this.chooseTime = '';
// const options = { startTime: this.startTime, endTime: this.endTime, memberIdList: this.memberIdList };
// this.setParams(options);
// } else {
// this.$message.error(msg || '');
// throw msg;
// }
// } catch (error) {
// throw error || '';
// }
// },
// },
// };
</script>
<style scoped>
</style>

BIN
src/views/File/img/640 (1).webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
src/views/File/img/640 (2).webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
src/views/File/img/640 (3).webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
src/views/File/img/640 (4).webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
src/views/File/img/640 (5).webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
src/views/File/img/640.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

2
src/views/FirstPage/FirstPage.vue

@ -2,7 +2,7 @@
<div>
<head-nav class="nav bg-white w-full" @searchParam="searchParam" />
<!-- 列表 -->
<List style="margin-top: 49px" ref="mychild" />
<List ref="mychild" />
</div>
</template>

221
src/views/Pay/Pay.vue

@ -0,0 +1,221 @@
<template>
<div class="pay-flex">
<div class="title">选择缴费方式</div>
<div class="container px-6 bg-white">
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">微信缴费</div>
<a-icon type="right" />
</div>
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">支付宝缴费</div>
<a-icon type="right" />
</div>
<div class="item-box flex justify-between items-center border-b">
<div class="item-title text-gray-400">兑换券缴费</div>
<a-icon type="right" />
</div>
</div>
<div class="title">其他支付凭证</div>
<div class="container px-6 pb-3 bg-white">
<div class="item-box">
<div class="text-gray-400">上传缴费凭证</div>
</div>
<a-upload
list-type="picture-card"
:action="action"
:headers="headers"
name="param"
:file-list="fileList"
@preview="handlePreview"
@change="handleChange"
>
<div v-if="fileList.length < 1">
<a-icon class="mb-2 text-xl" type="plus" />
<div class="ant-upload-text">上传照片</div>
</div>
</a-upload>
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal>
</div>
<div class="mt-14 px-6 flex justify-between items-center">
<a-button class="rounded" @click="back"> 稍后缴费 </a-button>
<a-button class="rounded" type="primary" @click="uploadPay"> 立即支付 </a-button>
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { toPay, uploadImg, getUserInfo } from '@/config/api';
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
export default {
data() {
return {
timer: null,
playerId: '',
fileId: '',
previewVisible: false,
previewImage: '',
fileList: [],
action: uploadImg,
};
},
computed: {
...mapState('home', ['projectId', 'roleId']),
headers() {
const token = sessionStorage.getItem('anyringToken');
return { Authorization: `Bearer ${token}` };
},
},
mounted() {
this.timer = setInterval(async () => {
if (this.projectId) {
clearInterval(this.timer);
await this.setParams();
}
}, 300);
},
methods: {
async setParams() {
const { projectId, roleId } = this;
const params = { param: { projectId } };
await this.getUserInfo(params);
},
/**
* 个人信息
*/
async getUserInfo() {
try {
const params = { param: { projectId: this.projectId } };
const res = await getUserInfo(params);
const { code, msg, data } = res.data;
if (code === 200 && data) {
this.playerId = data.id;
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
handleCancel() {
this.previewVisible = false;
},
async handlePreview(file) {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj);
}
this.previewImage = file.url || file.preview;
this.previewVisible = true;
},
handleChange({ fileList }) {
this.fileList = fileList;
},
async uploadPay() {
let res = {};
this.fileList.forEach((item, index) => {
if (index === 0 && item.response) {
res = item.response.data;
}
});
this.fileId = res.fileId;
if (!this.fileId) {
this.$message.info('请上传支付凭证');
return false;
}
try {
const params = {
param: {
projectId: this.projectId,
playerId: this.playerId,
fileId: this.fileId,
},
};
const res = await toPay(params);
const { code, msg, data } = res.data;
if (code === 200) {
this.back();
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
back() {
window.history.back();
},
},
};
</script>
<style lang="scss" scoped>
.pay-flex {
width: 100%;
min-height: 100vh;
background: #f3f3f3;
.title {
padding-top: 12px;
padding-left: 16px;
height: 48px;
line-height: 36px;
}
.item-box {
height: 48px;
line-height: 48px;
.item-title {
width: 80px;
flex-shrink: 0;
}
input {
height: 40px;
width: calc(100% - 80px);
}
div.flex {
width: calc(100% - 80px);
}
}
button {
width: 45%;
height: 40px;
}
}
</style>

118
src/views/PeopleList/PeopleList.vue

@ -0,0 +1,118 @@
<template>
<div class="list-flex">
<div class="px-4 pb-2 bg-white">
<div class="title flex items-center justify-around border-b">
<div class="text-gray-400 text-center" style="width: 25%">姓名</div>
<div class="text-gray-400 text-center" style="width: 15%">性别</div>
<div class="text-gray-400 text-center" style="width: 15%">年龄</div>
<div class="text-gray-400 text-center" style="width: 35%">手机号</div>
<!-- <div class="text-gray-400 text-center" style="width: 30%">目标</div> -->
<!-- <div class="text-gray-400 text-center" style="width: 20%">是否缴费</div> -->
</div>
<div>
<div class="item title flex items-center justify-around border-b" v-for="(item, index) in lists" :key="index">
<div class="text-center" style="width: 25%">{{ item.name }}</div>
<div class="text-center" style="width: 15%">{{ item.gender === 0 ? '女' : '男' }}</div>
<div class="text-center" style="width: 15%">{{ item.age }}</div>
<div class="text-center" style="width: 35%">{{ item.phone }}</div>
<!-- <div class="text-center" style="width: 30%">目标</div> -->
<!-- <div class="text-center" style="width: 20%"></div> -->
</div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center" style="width: 15%"></div>
<div class="text-center" style="width: 15%">28</div>
<div class="text-center" style="width: 35%">18435164840</div>
<!-- <div class="text-center" style="width: 30%">目标</div> -->
<!-- <div class="text-center" style="width: 20%"></div> -->
</div>
<div class="item title flex items-center justify-around border-b">
<div class="text-center" style="width: 25%">薛思男</div>
<div class="text-center" style="width: 15%"></div>
<div class="text-center" style="width: 15%">28</div>
<div class="text-center" style="width: 35%">18435164840</div>
<!-- <div class="text-center" style="width: 30%">目标</div> -->
<!-- <div class="text-center" style="width: 20%"></div> -->
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { studentList } from '@/config/api';
export default {
data() {
return {
timer: null,
lists: [],
};
},
computed: mapState('home', ['projectId', 'roleId']),
mounted() {
this.timer = setInterval(async () => {
if (this.projectId) {
clearInterval(this.timer);
await this.getStudentList();
//
// document.querySelector('#scrollTo').scrollIntoView({
// behavior: 'smooth', //
// block: 'start', //
// });
}
}, 300);
},
methods: {
async getStudentList() {
try {
const params = { param: this.fileList[0] };
const res = await studentList();
const { code, msg, data } = res.data;
if (code === 200) {
this.lists = data;
} else {
this.$message.error(msg || '获取失败');
throw msg;
}
} catch (error) {
throw error || '获取失败';
}
},
},
};
</script>
<style lang="scss" scoped>
.list-flex {
width: 100%;
min-height: 100vh;
background: #f3f3f3;
.title {
height: 48px;
line-height: 48px;
}
.item-box {
height: 48px;
line-height: 48px;
.item-title {
width: 80px;
flex-shrink: 0;
}
div.flex {
width: calc(100% - 80px);
}
}
}
</style>

0
新建文本文档.txt

Loading…
Cancel
Save