8月10日的bug的修改
This commit is contained in:
Binary file not shown.
BIN
dist 9091.zip
BIN
dist 9091.zip
Binary file not shown.
BIN
dist 9092.zip
BIN
dist 9092.zip
Binary file not shown.
BIN
dist716回归测试.zip
BIN
dist716回归测试.zip
Binary file not shown.
Binary file not shown.
BIN
dist8月4.zip
BIN
dist8月4.zip
Binary file not shown.
BIN
dist8月6日.zip
BIN
dist8月6日.zip
Binary file not shown.
BIN
dist9091.zip
BIN
dist9091.zip
Binary file not shown.
@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div class="sidebar-container">
|
||||||
<a-menu
|
<a-menu
|
||||||
v-model:selectedKeys="selectedKeys"
|
v-model:selectedKeys="selectedKeys"
|
||||||
mode="inline"
|
mode="inline"
|
||||||
@ -32,16 +33,16 @@
|
|||||||
<!-- <a-menu-item key="/project">接单管理</a-menu-item>-->
|
<!-- <a-menu-item key="/project">接单管理</a-menu-item>-->
|
||||||
<!-- </a-sub-menu>-->
|
<!-- </a-sub-menu>-->
|
||||||
|
|
||||||
<a-sub-menu>
|
<!-- <a-sub-menu>-->
|
||||||
<template #title>
|
<!-- <template #title>-->
|
||||||
<span>
|
<!-- <span>-->
|
||||||
<CommentOutlined />
|
<!-- <CommentOutlined />-->
|
||||||
<span>结算管理</span>
|
<!-- <span>结算管理</span>-->
|
||||||
</span>
|
<!-- </span>-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
<a-menu-item key="/applicationRecord">推广码申请记录</a-menu-item>
|
<!-- <a-menu-item key="/applicationRecord">推广码申请记录</a-menu-item>-->
|
||||||
<a-menu-item key="/withdrawalApplicationRecord">提现申请记录</a-menu-item>
|
<!-- <a-menu-item key="/withdrawalApplicationRecord">提现申请记录</a-menu-item>-->
|
||||||
</a-sub-menu>
|
<!-- </a-sub-menu>-->
|
||||||
<a-sub-menu>
|
<a-sub-menu>
|
||||||
<template #title>
|
<template #title>
|
||||||
<span>
|
<span>
|
||||||
@ -74,12 +75,19 @@
|
|||||||
<a-menu-item key="/employeePerformanceRanking">员工绩效排行</a-menu-item>
|
<a-menu-item key="/employeePerformanceRanking">员工绩效排行</a-menu-item>
|
||||||
|
|
||||||
</a-sub-menu>
|
</a-sub-menu>
|
||||||
<a-menu-item key="/employeeApplication">
|
<a-sub-menu>
|
||||||
<CommentOutlined />
|
<template #title>
|
||||||
<span>员工申请管理</span>
|
<span>
|
||||||
</a-menu-item>
|
<FieldTimeOutlined />
|
||||||
</a-menu>
|
<span>申请管理</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<a-menu-item key="/employeeApplication">员工申请管理</a-menu-item>
|
||||||
|
<a-menu-item key="/applicationInstructions">员工申请须知</a-menu-item>
|
||||||
|
|
||||||
|
</a-sub-menu>
|
||||||
|
</a-menu>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -109,6 +117,29 @@ const handleClick = (item: any) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.sidebar-container {
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: #ffe7ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义滚动条样式 */
|
||||||
|
.sidebar-container::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.ant-menu-item),
|
:deep(.ant-menu-item),
|
||||||
:deep(.ant-menu-submenu-title) {
|
:deep(.ant-menu-submenu-title) {
|
||||||
|
@ -177,6 +177,11 @@ export const routes = [
|
|||||||
name:'员工绩效排行',
|
name:'员工绩效排行',
|
||||||
component: ()=> import("../view/performance/employeePerformanceRanking.vue")
|
component: ()=> import("../view/performance/employeePerformanceRanking.vue")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path:'/applicationInstructions',
|
||||||
|
name:'员工申请须知',
|
||||||
|
component: ()=> import("../view/employeeApplication/applicationInstructions.vue")
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
]
|
]
|
@ -2,7 +2,7 @@
|
|||||||
<div id="login">
|
<div id="login">
|
||||||
<form>
|
<form>
|
||||||
<div class="box" @submit.prevent>
|
<div class="box" @submit.prevent>
|
||||||
<h2>欢迎登录青橙校园管理端</h2>
|
<h2>欢迎登录丁香花校园管理端</h2>
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
|
|
||||||
<input type="text" placeholder="账号" v-model="userAccount"/>
|
<input type="text" placeholder="账号" v-model="userAccount"/>
|
||||||
|
@ -741,7 +741,7 @@ const handlePriceInput = (value: number, field: keyof CourseDetail) => {
|
|||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
max-height: 500px;
|
max-height: 2000px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: white;
|
background: white;
|
||||||
|
@ -504,4 +504,10 @@ const showDetails = (id: string) => {
|
|||||||
background-color: #ff4d4f !important;
|
background-color: #ff4d4f !important;
|
||||||
border-color: #ff4d4f !important;
|
border-color: #ff4d4f !important;
|
||||||
}
|
}
|
||||||
|
:deep(.custom-search .ant-input:focus),
|
||||||
|
:deep(.custom-search .ant-input:hover),
|
||||||
|
:deep(.custom-search .ant-input-focused) {
|
||||||
|
border-color: #ffa940 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 169, 64, 0.2) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -82,6 +82,7 @@
|
|||||||
v-if="record.orderStatus === '交易成功'"
|
v-if="record.orderStatus === '交易成功'"
|
||||||
size="small"
|
size="small"
|
||||||
primary
|
primary
|
||||||
|
@click="showRefundConfirm(record)"
|
||||||
>
|
>
|
||||||
退款
|
退款
|
||||||
</a-button>
|
</a-button>
|
||||||
@ -94,9 +95,48 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import myAxios from "../../api/myAxios.ts";
|
import myAxios from "../../api/myAxios.ts";
|
||||||
import { message} from "ant-design-vue";
|
import { message,Modal} from "ant-design-vue";
|
||||||
import {downLoadImage} from "../../api/ImageUrl.ts";
|
import {downLoadImage} from "../../api/ImageUrl.ts";
|
||||||
|
const handleRefund = async (orderId: number) => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const storedToken = localStorage.getItem('token');
|
||||||
|
if (!storedToken) throw new Error('未找到登录信息');
|
||||||
|
|
||||||
|
const res: any = await myAxios.post(
|
||||||
|
"/courseOrder/refund",
|
||||||
|
{ id: orderId },
|
||||||
|
{ headers: { Authorization: storedToken } }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.code === 1 && res.data === true) {
|
||||||
|
message.success('退款成功');
|
||||||
|
// 刷新订单列表
|
||||||
|
await getOrderList();
|
||||||
|
} else {
|
||||||
|
message.error(res.message || '退款失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("退款失败:", error);
|
||||||
|
message.error('退款操作失败');
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示退款确认弹窗
|
||||||
|
const showRefundConfirm = (record: Order) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认退款',
|
||||||
|
content: `确定要对订单 ${record.orderNumber} 执行退款操作吗?`,
|
||||||
|
okText: '确认退款',
|
||||||
|
cancelText: '取消',
|
||||||
|
centered: true,
|
||||||
|
onOk() {
|
||||||
|
return handleRefund(record.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const selectedRowKeys = ref<number[]>([]); // 存储选中的行ID
|
const selectedRowKeys = ref<number[]>([]); // 存储选中的行ID
|
||||||
|
|
||||||
@ -109,7 +149,7 @@ const searchParams = ref({
|
|||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
sortField: "id",
|
sortField: "id",
|
||||||
sortOrder: "ascend",
|
sortOrder: "descend",
|
||||||
orderNumber: "",
|
orderNumber: "",
|
||||||
orderStatus: ""
|
orderStatus: ""
|
||||||
});
|
});
|
||||||
@ -252,7 +292,7 @@ const handleTableChange = (pag: any, _filters: any, sorter: any) => {
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
searchParams.value.sortField = "id";
|
searchParams.value.sortField = "id";
|
||||||
searchParams.value.sortOrder = "ascend";
|
searchParams.value.sortOrder = "descend";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同步到分页组件
|
// 同步到分页组件
|
||||||
@ -306,7 +346,7 @@ const reset = () => {
|
|||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
sortField: "id",
|
sortField: "id",
|
||||||
sortOrder: "ascend",
|
sortOrder: "descend",
|
||||||
orderNumber: "",
|
orderNumber: "",
|
||||||
orderStatus: ""
|
orderStatus: ""
|
||||||
};
|
};
|
||||||
@ -347,4 +387,11 @@ const reset = () => {
|
|||||||
background-color: #ffa940;
|
background-color: #ffa940;
|
||||||
border-color: #ffa940;
|
border-color: #ffa940;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.custom-search .ant-input:focus),
|
||||||
|
:deep(.custom-search .ant-input:hover),
|
||||||
|
:deep(.custom-search .ant-input-focused) {
|
||||||
|
border-color: #ffa940 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 169, 64, 0.2) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
307
src/view/employeeApplication/applicationInstructions.vue
Normal file
307
src/view/employeeApplication/applicationInstructions.vue
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
<template>
|
||||||
|
<form @submit.prevent="handleSubmit" class="modern-form">
|
||||||
|
<h2 class="form-title">员工账号申请须知</h2>
|
||||||
|
|
||||||
|
<!-- 富文本编辑器区域 - 修改为50%宽度 -->
|
||||||
|
<div class="rich-text-container">
|
||||||
|
<div class="rich-text-columns">
|
||||||
|
<div class="rich-text-group">
|
||||||
|
<span class="label-text">须知详情</span>
|
||||||
|
<RichTextEditor
|
||||||
|
v-model="formData.detail"
|
||||||
|
:disable="false"
|
||||||
|
@content-change="(html:any) => formData.detail = html"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="submit-button">
|
||||||
|
<span>立即创建</span>
|
||||||
|
<div class="button-sparkles"></div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import RichTextEditor from '../components/RichTextEditor.vue';
|
||||||
|
import '@vueup/vue-quill/dist/vue-quill.snow.css';
|
||||||
|
import myAxios from "../../api/myAxios.ts";
|
||||||
|
|
||||||
|
|
||||||
|
interface CourseForm {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
image: string;
|
||||||
|
detail: string;
|
||||||
|
promoCodeDesc: string;
|
||||||
|
originPrice: number;
|
||||||
|
discountPrice: number;
|
||||||
|
firstLevelRate: number;
|
||||||
|
secondLevelRate: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName = ref('');
|
||||||
|
// 新增价格错误状态
|
||||||
|
const priceError = ref('');
|
||||||
|
|
||||||
|
const formData = reactive<CourseForm>({
|
||||||
|
name: '',
|
||||||
|
type: '',
|
||||||
|
image: '',
|
||||||
|
detail: '',
|
||||||
|
promoCodeDesc: '',
|
||||||
|
originPrice: 0,
|
||||||
|
discountPrice: 0,
|
||||||
|
firstLevelRate: 0,
|
||||||
|
secondLevelRate: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const encode64 = (text: string): string => {
|
||||||
|
return btoa(
|
||||||
|
encodeURIComponent(text).replace(
|
||||||
|
/%([0-9A-F]{2})/g,
|
||||||
|
(_, p1) => String.fromCharCode(parseInt(p1, 16))
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
|
const encryptValue = (value: any, key: string): any => {
|
||||||
|
// 数值型字段直接返回,不加密
|
||||||
|
if (key === 'originPrice' || key === 'discountPrice' ||
|
||||||
|
key === 'image' || key ==='name'||key === 'type') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const valueString = typeof value === 'object'
|
||||||
|
? JSON.stringify(value)
|
||||||
|
: String(value);
|
||||||
|
return encode64(valueString);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Base64编码失败:', error);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
// 重置错误状态
|
||||||
|
priceError.value = '';
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const storedToken = localStorage.getItem('token');
|
||||||
|
const encryptedFormData: Record<string, any> = {};
|
||||||
|
|
||||||
|
Object.entries(formData).forEach(([key, value]) => {
|
||||||
|
if (value === null || value === undefined || value === '') return;
|
||||||
|
encryptedFormData[key] = encryptValue(value, key);
|
||||||
|
});
|
||||||
|
|
||||||
|
const res: any = await myAxios.post(`/course/add`, encryptedFormData, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': storedToken
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.code === 1) {
|
||||||
|
alert('须知创建成功!');
|
||||||
|
Object.assign(formData, {
|
||||||
|
name: '',
|
||||||
|
type: '',
|
||||||
|
image: '',
|
||||||
|
detail: '',
|
||||||
|
promoCodeDesc: '',
|
||||||
|
originPrice: 0,
|
||||||
|
discountPrice: 0,
|
||||||
|
firstLevelRate: 0,
|
||||||
|
secondLevelRate: 0
|
||||||
|
});
|
||||||
|
fileName.value = '';
|
||||||
|
} else {
|
||||||
|
alert(`创建失败:${res.message}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('请求失败:', error);
|
||||||
|
alert('提交失败,请检查控制台获取详细信息');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.modern-form {
|
||||||
|
max-width: 90%;
|
||||||
|
margin: 2rem auto;
|
||||||
|
padding: 2.5rem;
|
||||||
|
background: white;
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||||
|
font-family: 'Segoe UI', system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
color: #2c3e50;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.label-text {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
color: #4a5568;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-wrapper:focus-within .select-arrow {
|
||||||
|
transform: translateY(-50%) rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 下拉选项样式 */
|
||||||
|
.select-field option {
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: white;
|
||||||
|
color: #4a5568;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-field option:hover {
|
||||||
|
background: #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-field option:checked {
|
||||||
|
background: #6366f1;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.submit-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 8px 20px rgba(99, 102, 241, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-sparkles {
|
||||||
|
position: absolute;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background: rgba(255,255,255,0.4);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: sparkle 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sparkle {
|
||||||
|
0% { transform: scale(0) translate(0,0); }
|
||||||
|
50% { transform: scale(1) translate(100px, -50px); }
|
||||||
|
100% { transform: scale(0) translate(200px, -100px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.form-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modern-form {
|
||||||
|
padding: 1.5rem;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.rich-text-container {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.rich-text-group {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 2px solid #e2e8f0;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
min-height: 320px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.rich-text-columns {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rich-text-group:focus-within {
|
||||||
|
border-color: #6366f1;
|
||||||
|
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rich-text-group .label-text {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #3b4151;
|
||||||
|
padding: 12px 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.phone-section-content * {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-section-content img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-section-content h1,
|
||||||
|
.phone-section-content h2,
|
||||||
|
.phone-section-content h3 {
|
||||||
|
color: #2c3e50;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-section-content p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-section-content ul,
|
||||||
|
.phone-section-content ol {
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, onMounted, h } from "vue";
|
import { ref, reactive, onMounted, h ,nextTick} from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
import type { TableProps } from 'ant-design-vue';
|
import type { TableProps } from 'ant-design-vue';
|
||||||
@ -21,8 +21,7 @@ const columns = [
|
|||||||
key: 'name',
|
key: 'name',
|
||||||
width: 120,
|
width: 120,
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
align: 'center',
|
align: 'center'
|
||||||
sorter: true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '手机号',
|
title: '手机号',
|
||||||
@ -255,6 +254,50 @@ onMounted(() => {
|
|||||||
fetchAdvancementData();
|
fetchAdvancementData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleNameInput = (event: Event) => {
|
||||||
|
const input = event.target as HTMLInputElement;
|
||||||
|
const originalValue = input.value;
|
||||||
|
|
||||||
|
// 过滤掉所有非中文字符(包括全角字符)
|
||||||
|
const filteredValue = originalValue.replace(/[^\u4e00-\u9fa5]/g, '');
|
||||||
|
|
||||||
|
// 更新输入框的值
|
||||||
|
if (originalValue !== filteredValue) {
|
||||||
|
searchName.value = filteredValue;
|
||||||
|
// 强制更新输入框值(解决某些情况下显示残留问题)
|
||||||
|
nextTick(() => {
|
||||||
|
input.value = filteredValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handlePaste = (event: ClipboardEvent) => {
|
||||||
|
const clipboardData = event.clipboardData || (window as any).clipboardData;
|
||||||
|
const pastedText = clipboardData.getData('text');
|
||||||
|
|
||||||
|
// 检查粘贴内容是否包含非中文字符
|
||||||
|
if (/[^\u4e00-\u9fa5]/.test(pastedText)) {
|
||||||
|
event.preventDefault();
|
||||||
|
message.warning('只能粘贴中文字符');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const filterPhoneInput = (e: Event) => {
|
||||||
|
const input = e.target as HTMLInputElement;
|
||||||
|
let value = input.value;
|
||||||
|
|
||||||
|
// 1. 移除非数字字符
|
||||||
|
value = value.replace(/\D/g, '');
|
||||||
|
|
||||||
|
// 2. 限制最多11位数字
|
||||||
|
if (value.length > 11) {
|
||||||
|
value = value.slice(0, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新输入框值
|
||||||
|
input.value = value;
|
||||||
|
searchPhone.value = value;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -265,12 +308,14 @@ onMounted(() => {
|
|||||||
<a-form-item label="申请人姓名">
|
<a-form-item label="申请人姓名">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
style="width: 300px"
|
style="width: 300px"
|
||||||
placeholder="请输入姓名"
|
placeholder="请输入姓名(仅中文)"
|
||||||
class="custom-search"
|
class="custom-search"
|
||||||
enter-button
|
enter-button
|
||||||
v-model:value="searchName"
|
v-model:value="searchName"
|
||||||
@pressEnter="handleSearch"
|
@pressEnter="handleSearch"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
|
@input="handleNameInput"
|
||||||
|
@paste="handlePaste"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="手机号">
|
<a-form-item label="手机号">
|
||||||
@ -282,6 +327,7 @@ onMounted(() => {
|
|||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
enter-button
|
enter-button
|
||||||
class="custom-search"
|
class="custom-search"
|
||||||
|
@input="filterPhoneInput"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-button @click="reset">重置</a-button>
|
<a-button @click="reset">重置</a-button>
|
||||||
@ -379,38 +425,11 @@ onMounted(() => {
|
|||||||
border-right-color: #ffa940;
|
border-right-color: #ffa940;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 审核人选择弹窗样式 */
|
:deep(.custom-search .ant-input:focus),
|
||||||
.supervisor-list {
|
:deep(.custom-search .ant-input:hover),
|
||||||
max-height: 400px;
|
:deep(.custom-search .ant-input-focused) {
|
||||||
overflow-y: auto;
|
border-color: #ffa940 !important;
|
||||||
padding: 10px;
|
box-shadow: 0 0 0 2px rgba(255, 169, 64, 0.2) !important;
|
||||||
}
|
|
||||||
|
|
||||||
.radio-group {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.supervisor-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 8px 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.supervisor-info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-left: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.supervisor-id {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.supervisor-name {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.ant-list-item) {
|
:deep(.ant-list-item) {
|
||||||
@ -427,17 +446,4 @@ onMounted(() => {
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 操作按钮样式 */
|
|
||||||
.action-btn {
|
|
||||||
margin: 0 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-btn.primary {
|
|
||||||
color: #1890ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-btn.danger {
|
|
||||||
color: #ff4d4f;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
@ -124,6 +124,7 @@
|
|||||||
:ok-text="'确认驳回'"
|
:ok-text="'确认驳回'"
|
||||||
:cancel-text="'取消'"
|
:cancel-text="'取消'"
|
||||||
okType="danger"
|
okType="danger"
|
||||||
|
class="reject-modal"
|
||||||
>
|
>
|
||||||
<a-alert type="warning" show-icon class="reject-alert">
|
<a-alert type="warning" show-icon class="reject-alert">
|
||||||
<template #message>
|
<template #message>
|
||||||
@ -135,18 +136,19 @@
|
|||||||
</a-alert>
|
</a-alert>
|
||||||
|
|
||||||
<div class="reject-form">
|
<div class="reject-form">
|
||||||
<a-form layout="vertical">
|
<div class="reject-header">
|
||||||
<a-form-item label="驳回原因" required>
|
<h4 class="reject-title">* 驳回原因</h4>
|
||||||
|
<div class="char-counter">
|
||||||
|
{{ rejectReason.length }} / 200
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<a-textarea
|
<a-textarea
|
||||||
v-model:value="rejectReason"
|
v-model:value="rejectReason"
|
||||||
placeholder="请输入详细的驳回原因..."
|
placeholder="请输入详细的驳回原因..."
|
||||||
:rows="4"
|
:rows="4"
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
show-count
|
|
||||||
class="reject-reason"
|
class="reject-reason"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
@ -632,7 +634,11 @@ const submitReject = async () => {
|
|||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 驳回弹窗样式 */
|
/* 驳回弹窗样式优化 */
|
||||||
|
.reject-modal :deep(.ant-modal-body) {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.reject-alert {
|
.reject-alert {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -645,8 +651,37 @@ const submitReject = async () => {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.reject-form {
|
.reject-form {
|
||||||
padding: 10px;
|
padding: 0 10px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reject-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reject-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-counter {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reject-reason {
|
.reject-reason {
|
||||||
@ -655,6 +690,8 @@ const submitReject = async () => {
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reject-reason:focus {
|
.reject-reason:focus {
|
||||||
@ -662,6 +699,13 @@ const submitReject = async () => {
|
|||||||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
/* 空状态样式 */
|
/* 空状态样式 */
|
||||||
:deep(.ant-empty) {
|
:deep(.ant-empty) {
|
||||||
margin: 40px 0;
|
margin: 40px 0;
|
||||||
|
@ -294,6 +294,7 @@ const updateProportionRate = async () => {
|
|||||||
// 修复语法错误:移除命名参数
|
// 修复语法错误:移除命名参数
|
||||||
proportionRate.value = parseFloat(rateValue.toFixed(2)).toString();
|
proportionRate.value = parseFloat(rateValue.toFixed(2)).toString();
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
|
fetchEmployeePerformance();
|
||||||
} else {
|
} else {
|
||||||
message.error(response.message || "更新抽成比例失败");
|
message.error(response.message || "更新抽成比例失败");
|
||||||
}
|
}
|
||||||
@ -525,4 +526,5 @@ const filterRateInput = (e: Event) => {
|
|||||||
background-color: #ffa940;
|
background-color: #ffa940;
|
||||||
border-color: #ffa940;
|
border-color: #ffa940;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -167,6 +167,33 @@ const handleDateChange = (_: any, dateStrings: [string, string]) => {
|
|||||||
queryParams.startDate = dateStrings[0] || '';
|
queryParams.startDate = dateStrings[0] || '';
|
||||||
queryParams.endDate = dateStrings[1] || '';
|
queryParams.endDate = dateStrings[1] || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleSearchPhoneInput = (e: any) => {
|
||||||
|
let value = e.target.value;
|
||||||
|
|
||||||
|
// 只允许输入数字,并截取前11位
|
||||||
|
const newValue = value.replace(/[^0-9]/g, '').slice(0, 11);
|
||||||
|
|
||||||
|
// 直接更新 queryParams.phoneNumber
|
||||||
|
queryParams.phoneNumber = newValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增 onKeyDown 事件处理函数
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
const allowedKeys = [
|
||||||
|
'Backspace',
|
||||||
|
'Delete',
|
||||||
|
'ArrowLeft',
|
||||||
|
'ArrowRight',
|
||||||
|
'Tab',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 只允许输入数字和控制键
|
||||||
|
if (!/[0-9]/.test(e.key) && !allowedKeys.includes(e.key)) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -212,6 +239,9 @@ const handleDateChange = (_: any, dateStrings: [string, string]) => {
|
|||||||
placeholder="手机号"
|
placeholder="手机号"
|
||||||
style="width: 180px; margin-right: 10px;"
|
style="width: 180px; margin-right: 10px;"
|
||||||
allow-clear
|
allow-clear
|
||||||
|
:maxlength="11"
|
||||||
|
@input="handleSearchPhoneInput"
|
||||||
|
@keydown="handleKeyDown"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
@ -25,7 +25,7 @@ const columns = [
|
|||||||
align: 'center'
|
align: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '主管姓名',
|
title: '学校名称',
|
||||||
dataIndex: 'nickName',
|
dataIndex: 'nickName',
|
||||||
key: 'nickName',
|
key: 'nickName',
|
||||||
width: 100,
|
width: 100,
|
||||||
@ -290,6 +290,7 @@ const updateProportionRate = async () => {
|
|||||||
message.success("抽成比例更新成功");
|
message.success("抽成比例更新成功");
|
||||||
proportionRate.value = rateValue.toFixed(2);
|
proportionRate.value = rateValue.toFixed(2);
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
|
fetchManagerPerformance()
|
||||||
} else {
|
} else {
|
||||||
message.error(response.message || "更新抽成比例失败");
|
message.error(response.message || "更新抽成比例失败");
|
||||||
}
|
}
|
||||||
@ -414,11 +415,11 @@ const settlement = async () => {
|
|||||||
<!-- 搜索框 -->
|
<!-- 搜索框 -->
|
||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-space>
|
<div class="flex-container">
|
||||||
<a-form-item label="主管姓名">
|
<a-form-item label="学校名称">
|
||||||
<a-input
|
<a-input
|
||||||
style="width: 300px;border: 1px solid #ffa940;"
|
style="width: 300px;border: 1px solid #ffa940;"
|
||||||
placeholder="请输入主管姓名"
|
placeholder="请输入学校名称"
|
||||||
v-model:value="searchName"
|
v-model:value="searchName"
|
||||||
@click="handleSearch"
|
@click="handleSearch"
|
||||||
@input="filterNameInput"
|
@input="filterNameInput"
|
||||||
@ -434,12 +435,18 @@ const settlement = async () => {
|
|||||||
@input="filterPhoneInput"
|
@input="filterPhoneInput"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-button @click="handleSearch" style="margin-right: 10px" class="custom-button">搜索</a-button>
|
|
||||||
<a-button @click="reset">重置</a-button>
|
<!-- 将按钮和标签包裹在button-group中 -->
|
||||||
|
<div class="button-group">
|
||||||
|
<a-button @click="handleSearch" class="custom-button">搜索</a-button>
|
||||||
|
<a-button @click="reset" class="custom-button">重置</a-button>
|
||||||
|
<div class="proportion-tag">
|
||||||
抽成占比<a-tag color="orange">{{ proportionRate }}</a-tag>
|
抽成占比<a-tag color="orange">{{ proportionRate }}</a-tag>
|
||||||
<a-button @click="openRateModal" style="margin-left: 10px" class="custom-button">修改比例</a-button>
|
</div>
|
||||||
<a-button @click="settlement" style="margin-left: 10px" class="custom-button">一键结算</a-button>
|
<a-button @click="openRateModal" class="custom-button">修改比例</a-button>
|
||||||
</a-space>
|
<a-button @click="settlement" class="custom-button">一键结算</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
<!-- 修改比例弹窗 -->
|
<!-- 修改比例弹窗 -->
|
||||||
@ -505,6 +512,45 @@ const settlement = async () => {
|
|||||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 使用弹性盒子布局并允许换行 */
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单行样式 */
|
||||||
|
.search-box .ant-form-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮组容器 */
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1 1 100%; /* 默认占据整行 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 抽成比例标签容器 */
|
||||||
|
.proportion-tag {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 在中等屏幕以上时调整按钮组布局 */
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.button-group {
|
||||||
|
flex: 0 1 auto; /* 根据内容自适应宽度 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 搜索框输入框聚焦和悬浮状态边框为橙色 */
|
/* 搜索框输入框聚焦和悬浮状态边框为橙色 */
|
||||||
.search-box .custom-search :deep(.ant-input:hover),
|
.search-box .custom-search :deep(.ant-input:hover),
|
||||||
.search-box .custom-search :deep(.ant-input:focus) {
|
.search-box .custom-search :deep(.ant-input:focus) {
|
||||||
@ -517,6 +563,7 @@ const settlement = async () => {
|
|||||||
background-color: #ffa940;
|
background-color: #ffa940;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border: 1px solid #ffa940;
|
border: 1px solid #ffa940;
|
||||||
|
white-space: nowrap; /* 防止按钮文字换行 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-button:hover,
|
.custom-button:hover,
|
||||||
@ -542,4 +589,21 @@ const settlement = async () => {
|
|||||||
.custom-search :deep(.ant-input) {
|
.custom-search :deep(.ant-input) {
|
||||||
border-right-color: #ffa940;
|
border-right-color: #ffa940;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 响应式调整 */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.search-box .ant-form-item {
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.search-box .ant-form-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box .ant-input {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -67,7 +67,7 @@ const total = ref(0);
|
|||||||
|
|
||||||
// 表格列定义
|
// 表格列定义
|
||||||
const columns = [
|
const columns = [
|
||||||
{ title: '用户昵称', dataIndex: 'nickName', key: 'nickName' },
|
{ title: '学校名称', dataIndex: 'nickName', key: 'nickName' },
|
||||||
{ title: '手机号', dataIndex: 'phoneNumber', key: 'phoneNumber' },
|
{ title: '手机号', dataIndex: 'phoneNumber', key: 'phoneNumber' },
|
||||||
{ title: '员工数量', dataIndex: 'empCount', key: 'empCount' },
|
{ title: '员工数量', dataIndex: 'empCount', key: 'empCount' },
|
||||||
{ title: '推广人数', dataIndex: 'promoCount', key: 'promoCount' },
|
{ title: '推广人数', dataIndex: 'promoCount', key: 'promoCount' },
|
||||||
@ -154,6 +154,10 @@ const resetSearch = () => {
|
|||||||
queryParams.endDate = '';
|
queryParams.endDate = '';
|
||||||
queryParams.sortField = '';
|
queryParams.sortField = '';
|
||||||
queryParams.sortOrder = '';
|
queryParams.sortOrder = '';
|
||||||
|
|
||||||
|
// 重置当前页码为1
|
||||||
|
queryParams.current = 1;
|
||||||
|
|
||||||
fetchPerformanceRank();
|
fetchPerformanceRank();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -162,6 +166,40 @@ const handleDateChange = (_: any, dateStrings: [string, string]) => {
|
|||||||
queryParams.startDate = dateStrings[0] || '';
|
queryParams.startDate = dateStrings[0] || '';
|
||||||
queryParams.endDate = dateStrings[1] || '';
|
queryParams.endDate = dateStrings[1] || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理搜索操作(新增方法)
|
||||||
|
const handleSearch = () => {
|
||||||
|
// 重置当前页码为1
|
||||||
|
queryParams.current = 1;
|
||||||
|
fetchPerformanceRank();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearchPhoneInput = (e: any) => {
|
||||||
|
let value = e.target.value;
|
||||||
|
|
||||||
|
// 只允许输入数字,并截取前11位
|
||||||
|
const newValue = value.replace(/[^0-9]/g, '').slice(0, 11);
|
||||||
|
|
||||||
|
// 直接更新 queryParams.phoneNumber
|
||||||
|
queryParams.phoneNumber = newValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增 onKeyDown 事件处理函数
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
const allowedKeys = [
|
||||||
|
'Backspace',
|
||||||
|
'Delete',
|
||||||
|
'ArrowLeft',
|
||||||
|
'ArrowRight',
|
||||||
|
'Tab',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 只允许输入数字和控制键
|
||||||
|
if (!/[0-9]/.test(e.key) && !allowedKeys.includes(e.key)) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -204,6 +242,9 @@ const handleDateChange = (_: any, dateStrings: [string, string]) => {
|
|||||||
v-model:value="queryParams.phoneNumber"
|
v-model:value="queryParams.phoneNumber"
|
||||||
placeholder="手机号"
|
placeholder="手机号"
|
||||||
style="width: 150px; margin-right: 10px;"
|
style="width: 150px; margin-right: 10px;"
|
||||||
|
:maxlength="11"
|
||||||
|
@input="handleSearchPhoneInput"
|
||||||
|
@keydown="handleKeyDown"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
@ -219,7 +260,8 @@ const handleDateChange = (_: any, dateStrings: [string, string]) => {
|
|||||||
style="margin-right: 10px; width: 350px;"
|
style="margin-right: 10px; width: 350px;"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button type="primary" @click="fetchPerformanceRank" style="margin-right: 10px;">
|
<!-- 修改这里:使用新的handleSearch方法 -->
|
||||||
|
<Button type="primary" @click="handleSearch" style="margin-right: 10px;">
|
||||||
搜索
|
搜索
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
@ -265,12 +307,11 @@ const handleDateChange = (_: any, dateStrings: [string, string]) => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
/* 原有样式保持不变 */
|
||||||
.performance-container {
|
.performance-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
/* 温馨的乳白色背景,带一点暖色调 */
|
|
||||||
background: #fffaf0;
|
background: #fffaf0;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
/* 轻柔的暖色阴影 */
|
|
||||||
box-shadow: 0 4px 12px rgba(255, 164, 64, 0.2);
|
box-shadow: 0 4px 12px rgba(255, 164, 64, 0.2);
|
||||||
transition: transform 0.3s;
|
transition: transform 0.3s;
|
||||||
}
|
}
|
||||||
@ -288,7 +329,6 @@ const handleDateChange = (_: any, dateStrings: [string, string]) => {
|
|||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
/* 使用主题色 */
|
|
||||||
color: #ffa940;
|
color: #ffa940;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -297,7 +337,6 @@ h2 {
|
|||||||
.filter-container {
|
.filter-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
/* 柔和的卡片背景 */
|
|
||||||
background: #fff5e6;
|
background: #fff5e6;
|
||||||
border: 1px solid #ffd591;
|
border: 1px solid #ffd591;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -326,8 +365,6 @@ h2 {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* 单元格边框去掉横线,更显高级 */
|
/* 单元格边框去掉横线,更显高级 */
|
||||||
:deep(.ant-table-cell) {
|
:deep(.ant-table-cell) {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="头像" name="userAvatar" required>
|
<a-form-item label="头像" name="userAvatar">
|
||||||
<a-upload
|
<a-upload
|
||||||
name="file"
|
name="file"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
@ -216,7 +216,7 @@
|
|||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="头像" name="userAvatar" required>
|
<a-form-item label="头像" name="userAvatar">
|
||||||
<a-upload
|
<a-upload
|
||||||
name="file"
|
name="file"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
@ -339,7 +339,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref,computed } from "vue";
|
import { onMounted, ref,computed,nextTick } from "vue";
|
||||||
import myAxios from "../../api/myAxios.ts";
|
import myAxios from "../../api/myAxios.ts";
|
||||||
import { message, Modal } from "ant-design-vue";
|
import { message, Modal } from "ant-design-vue";
|
||||||
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue';
|
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue';
|
||||||
@ -381,19 +381,19 @@ const handleUpload = async ({ file }: { file: File }) => {
|
|||||||
uploadLoading.value = true;
|
uploadLoading.value = true;
|
||||||
const storedToken = localStorage.getItem('token');
|
const storedToken = localStorage.getItem('token');
|
||||||
|
|
||||||
|
|
||||||
const res:any = await myAxios.post('/file/upload?biz=avatar', form, {
|
const res:any = await myAxios.post('/file/upload?biz=avatar', form, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: storedToken,
|
Authorization: storedToken,
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log(res)
|
|
||||||
|
|
||||||
if (res.code === 1) {
|
if (res.code === 1) {
|
||||||
formData.value.userAvatar = res.data;
|
formData.value.userAvatar = res.data;
|
||||||
previewImage.value = URL.createObjectURL(file);
|
previewImage.value = URL.createObjectURL(file);
|
||||||
message.success('上传成功');
|
message.success('上传成功');
|
||||||
|
|
||||||
|
// 关键:清除整个表单的校验状态
|
||||||
|
formRef.value?.clearValidate();
|
||||||
} else {
|
} else {
|
||||||
message.error(res.message || '上传失败');
|
message.error(res.message || '上传失败');
|
||||||
}
|
}
|
||||||
@ -500,6 +500,13 @@ const formRules = {
|
|||||||
},
|
},
|
||||||
trigger: ['input', 'blur']
|
trigger: ['input', 'blur']
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
userAvatar: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传头像',
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,6 +702,13 @@ const editFormRules = {
|
|||||||
},
|
},
|
||||||
trigger: ['input', 'blur']
|
trigger: ['input', 'blur']
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
userAvatar: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传头像',
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -844,7 +858,8 @@ const handlePhoneSearch = async () => {
|
|||||||
{
|
{
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
phoneNumber: searchPhone.value
|
phoneNumber: searchPhone.value,
|
||||||
|
userRole: "admin"
|
||||||
},
|
},
|
||||||
{ headers: { Authorization: storedToken } }
|
{ headers: { Authorization: storedToken } }
|
||||||
);
|
);
|
||||||
@ -1012,7 +1027,7 @@ const editForm = ref({
|
|||||||
userAccount: '',
|
userAccount: '',
|
||||||
userPassword: '',
|
userPassword: '',
|
||||||
invitationCode: '',
|
invitationCode: '',
|
||||||
userRole: '',
|
userRole: 'admin',
|
||||||
parentUserId: 0,
|
parentUserId: 0,
|
||||||
SuperUserList: ''
|
SuperUserList: ''
|
||||||
});
|
});
|
||||||
@ -1040,6 +1055,9 @@ const handleEditUpload = async ({ file }: { file: File }) => {
|
|||||||
editForm.value.userAvatar = res.data;
|
editForm.value.userAvatar = res.data;
|
||||||
editPreviewImage.value = URL.createObjectURL(file);
|
editPreviewImage.value = URL.createObjectURL(file);
|
||||||
message.success('头像更新成功');
|
message.success('头像更新成功');
|
||||||
|
|
||||||
|
// 关键:清除整个编辑表单的校验状态
|
||||||
|
editFormRef.value?.clearValidate();
|
||||||
} else {
|
} else {
|
||||||
message.error(res.message || '头像上传失败');
|
message.error(res.message || '头像上传失败');
|
||||||
}
|
}
|
||||||
@ -1050,6 +1068,9 @@ const handleEditUpload = async ({ file }: { file: File }) => {
|
|||||||
editUploadLoading.value = false;
|
editUploadLoading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const showDrawer = (record: any) => {
|
const showDrawer = (record: any) => {
|
||||||
selectedUser.value = record;
|
selectedUser.value = record;
|
||||||
editForm.value = {
|
editForm.value = {
|
||||||
@ -1162,6 +1183,7 @@ const formRef = ref();
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const showModal = () => {
|
const showModal = () => {
|
||||||
openUser.value = true;
|
openUser.value = true;
|
||||||
formData.value = {
|
formData.value = {
|
||||||
@ -1173,6 +1195,9 @@ const showModal = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
previewImage.value = '';
|
previewImage.value = '';
|
||||||
|
nextTick(() => {
|
||||||
|
formRef.value?.clearValidate();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = (e: MouseEvent) => {
|
const handleOk = (e: MouseEvent) => {
|
||||||
@ -1497,4 +1522,11 @@ const handleSubmit = async () => {
|
|||||||
:deep(.ant-checkbox-wrapper-disabled) {
|
:deep(.ant-checkbox-wrapper-disabled) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.custom-search .ant-input:focus),
|
||||||
|
:deep(.custom-search .ant-input:hover),
|
||||||
|
:deep(.custom-search .ant-input-focused) {
|
||||||
|
border-color: #ffa940 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 169, 64, 0.2) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -743,4 +743,10 @@ const showDrawer = (record: any) => {
|
|||||||
:deep(.ant-checkbox-wrapper-disabled) {
|
:deep(.ant-checkbox-wrapper-disabled) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
:deep(.custom-search .ant-input:focus),
|
||||||
|
:deep(.custom-search .ant-input:hover),
|
||||||
|
:deep(.custom-search .ant-input-focused) {
|
||||||
|
border-color: #ffa940 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 169, 64, 0.2) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -804,4 +804,11 @@ const showDrawer = (record: any) => {
|
|||||||
:deep(.ant-checkbox-wrapper-disabled) {
|
:deep(.ant-checkbox-wrapper-disabled) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.custom-search .ant-input:focus),
|
||||||
|
:deep(.custom-search .ant-input:hover),
|
||||||
|
:deep(.custom-search .ant-input-focused) {
|
||||||
|
border-color: #ffa940 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 169, 64, 0.2) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -695,4 +695,11 @@ const handleTableChange = (pag: any, _: any, sorter: any) => {
|
|||||||
:deep(.ant-checkbox-wrapper-disabled) {
|
:deep(.ant-checkbox-wrapper-disabled) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.custom-search .ant-input:focus),
|
||||||
|
:deep(.custom-search .ant-input:hover),
|
||||||
|
:deep(.custom-search .ant-input-focused) {
|
||||||
|
border-color: #ffa940 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 169, 64, 0.2) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -1 +1 @@
|
|||||||
{"root":["./src/main.ts","./src/vite-env.d.ts","./src/api/imageurl.ts","./src/api/myaxios.ts","./src/router/index.ts","./src/router/routes.ts","./src/store/index.ts","./src/store/userstore.ts","./src/types/wangeditor.d.ts","./src/app.vue","./src/layout/managelayout.vue","./src/layout/manage/manageheader.vue","./src/layout/manage/managesidebar.vue","./src/view/index.vue","./src/view/login.vue","./src/view/test.vue","./src/view/components/richtexteditor.vue","./src/view/course/addcourse.vue","./src/view/course/chapterdetail.vue","./src/view/course/coursedetail.vue","./src/view/course/coursemanagement.vue","./src/view/course/courseorder.vue","./src/view/employeeapplication/employeeapplication.vue","./src/view/employeeapplication/employeedetail.vue","./src/view/performance/customerdetail.vue","./src/view/performance/customerorder.vue","./src/view/performance/employeeperformaince.vue","./src/view/performance/employeeperformanceranking.vue","./src/view/performance/performancemanagement.vue","./src/view/performance/supervisorperformanceranking.vue","./src/view/project/addproject.vue","./src/view/project/addprojectnotice.vue","./src/view/project/moneydetail.vue","./src/view/project/noticedetail.vue","./src/view/project/project.vue","./src/view/project/projectdetail.vue","./src/view/project/projectnotice.vue","./src/view/project/promotioncode.vue","./src/view/settlement/applicationrecord.vue","./src/view/settlement/moneyrecord.vue","./src/view/settlement/withdrawalapplicationrecord.vue","./src/view/userlist/adminlist.vue","./src/view/userlist/managerinformation.vue","./src/view/userlist/stafflist.vue","./src/view/userlist/supervisorlist.vue","./src/view/userlist/userlist.vue","./src/view/work/workdetail.vue","./src/view/work/worklist.vue"],"version":"5.6.3"}
|
{"root":["./src/main.ts","./src/vite-env.d.ts","./src/api/imageurl.ts","./src/api/myaxios.ts","./src/router/index.ts","./src/router/routes.ts","./src/store/index.ts","./src/store/userstore.ts","./src/types/wangeditor.d.ts","./src/app.vue","./src/layout/managelayout.vue","./src/layout/manage/manageheader.vue","./src/layout/manage/managesidebar.vue","./src/view/index.vue","./src/view/login.vue","./src/view/test.vue","./src/view/components/richtexteditor.vue","./src/view/course/addcourse.vue","./src/view/course/chapterdetail.vue","./src/view/course/coursedetail.vue","./src/view/course/coursemanagement.vue","./src/view/course/courseorder.vue","./src/view/employeeapplication/applicationinstructions.vue","./src/view/employeeapplication/employeeapplication.vue","./src/view/employeeapplication/employeedetail.vue","./src/view/performance/customerdetail.vue","./src/view/performance/customerorder.vue","./src/view/performance/employeeperformaince.vue","./src/view/performance/employeeperformanceranking.vue","./src/view/performance/performancemanagement.vue","./src/view/performance/supervisorperformanceranking.vue","./src/view/project/addproject.vue","./src/view/project/addprojectnotice.vue","./src/view/project/moneydetail.vue","./src/view/project/noticedetail.vue","./src/view/project/project.vue","./src/view/project/projectdetail.vue","./src/view/project/projectnotice.vue","./src/view/project/promotioncode.vue","./src/view/settlement/applicationrecord.vue","./src/view/settlement/moneyrecord.vue","./src/view/settlement/withdrawalapplicationrecord.vue","./src/view/userlist/adminlist.vue","./src/view/userlist/managerinformation.vue","./src/view/userlist/stafflist.vue","./src/view/userlist/supervisorlist.vue","./src/view/userlist/userlist.vue","./src/view/work/workdetail.vue","./src/view/work/worklist.vue"],"version":"5.6.3"}
|
Reference in New Issue
Block a user