Files
ks-app-employment-service/packageB/institution/trainingInstitutionMaintenance.vue
2026-02-24 10:06:48 +08:00

987 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div style="height: 90vh;overflow-y: auto;">
<view class="content">
<view class="content-input">
<view class="input-titile"><text class="input-required">*</text>机构名称</view>
<input class="input-con" v-model="fromValue.organName" placeholder="请输入机构名称" />
</view>
<view class="content-input">
<view class="input-titile"><text class="input-required">*</text>联系人</view>
<input class="input-con" v-model="fromValue.contactName" placeholder="请输入联系人" />
</view>
<view class="content-input">
<view class="input-titile">联系方式</view>
<input class="input-con" v-model="fromValue.contactPhone" placeholder="请输入您的联系方式" />
</view>
<view class="content-input">
<view class="input-titile">机构类别</view>
<input class="input-con" v-model="fromValue.organType" placeholder="请输入机构类别" />
</view>
<view class="content-input">
<view class="input-titile">机构性质</view>
<input class="input-con" v-model="fromValue.organNature" placeholder="请输入机构性质" />
</view>
<view class="content-input">
<view class="input-titile">培训级别及证书类型</view>
<input class="input-con" v-model="fromValue.trainType" placeholder="请输入培训级别及证书类型" />
</view>
<view class="content-input">
<view class="input-titile">办学许可证号/批文号</view>
<input class="input-con" v-model="fromValue.organLicense" placeholder="请输入办学许可证号/批文号" />
</view>
<view class="content-input">
<view class="input-titile">所在区域</view>
<view class="input-con">
<picker mode = 'multiSelector'
@change="onWorkTypePickerChange"
@columnchange="onWorkTypeColumnChange"
range-key="dictLabel"
:value="fromValue.organAddressArr"
:range="region.provinceData">
<view class="uni-input" v-if="isShow" style="width: 100%;">{{region.provinceData[0][region.arrayIndex[0]].dictLabel}}/{{region.provinceData[1][region.arrayIndex[1]].dictLabel}}/{{region.provinceData[2].length>0?region.provinceData[2][region.arrayIndex[2]].dictLabel:''}}</view>
<view class="uni-input" style="width: 100%;" v-else>请选择</view>
</picker>
</view>
<!-- <input class="input-con" v-model="fromValue.organAddressArr" placeholder="请选择" /> -->
</view>
<view class="content-input">
<view class="input-titile">机构地址</view>
<input class="input-con" v-model="fromValue.address" placeholder="请输入机构地址" />
</view>
<view class="content-input">
<view class="input-titile">地图定位(经纬度)</view>
<view @click="selectLocation" class="input-con">{{fromValue.location?fromValue.location:'请选择'}}</view>
</view>
<view class="content-input">
<view class="input-titile"><text class="input-required">*</text>统一社会信用代码</view>
<input class="input-con" v-model="fromValue.unifiedSocialCreditCode" placeholder="请输入统一社会信用代码" />
</view>
<view class="content-input">
<view class="input-titile">机构简介</view>
<textarea auto-height class="input-con" v-model="fromValue.introduction" placeholder="请输入机构简介" />
</view>
<view class="content-input">
<view class="input-titile">培训项目</view>
<checkbox-group @change="checkboxChange">
<view style="display: flex;flex-wrap: wrap;">
<view v-for="item in courseLabels" :key="item.dictCode" style="margin-right: 20rpx;margin-bottom: 20rpx;">
<label>
<checkbox :value="item.dictCode" :checked="item.checked" />
{{item.dictLabel}}
</label>
</view>
</view>
</checkbox-group>
</view>
<view class="content-input">
<view class="input-titile">资质证书</view>
<button class="upload-btn" type="primary" size="mini" @click="handleResumeUpload" :loading="isUploading" :disabled="isUploading">
<uni-icons type="cloud-upload" size="20"></uni-icons>
<text class="upload-text">上传</text>
</button>
<view class="uploaded-file-info" v-if="fileListss.list.length>0">
<view v-for="item in fileListss.list" :key="item.url" >
<image class="file-icon" src="/static/icons/file-icon.png" mode="widthFix"></image>
<text class="file-name">{{ item.name }}</text>
<button class="delete-file-btn" size="mini" @click.stop="handleDeleteResume(item)">删除</button>
</view>
</view>
</view>
<view class="content-input">
<view class="input-titile">机构LOGO</view>
<button class="upload-btn" type="primary" size="mini" @click="handleResumeUpload2" :loading="isUploading2" :disabled="isUploading2">
<uni-icons type="cloud-upload" size="20"></uni-icons>
<text class="upload-text">上传</text>
</button>
<view class="uploaded-file-info" style="width: 200rpx;height: 200rpx;">
<img :src="uploadedResumeUrl" alt="" />
</view>
</view>
</view>
<view class="footer">
<view class="footerBtn" @click="confirm()">保存</view>
</view>
<SelectPopup ref="selectPopupRef"></SelectPopup>
</div>
</template>
<script setup>
import { reactive, inject, watch, ref, onMounted, onUnmounted } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
const { $api, navTo, navBack, checkingPhoneRegExp,config } = inject('globalFunction');
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
import useDictStore from '@/stores/useDictStore';
import SelectPopup from '@/components/selectPopup/selectPopup.vue';
const { userInfo } = storeToRefs(useUserStore());
const { getUserResume } = useUserStore();
const dictStore = useDictStore();
const { dictLabel, oneDictData, complete: dictComplete, getDictSelectOption } = dictStore;
let fromValue = reactive({
organName: '',
contactName:'',
organType:'',
organNature:'',
trainType:'',
organLicense:'',
organAddressArr:'',
address:'',
unifiedSocialCreditCode:'',
introduction:'',
location:'',
longitude:'',
latitude:'',
education: '',
politicalAffiliation: '',
contactPhone: ''
});
const courseLabels=ref([])
let fileListss=reactive({
list:[],
})
let region=reactive({
provinceData:[
[],
[],
[]
],
arrayIndex:[0,0,0],
})
const isShow = ref(false); // 上传中状态
const isUploading = ref(false); // 上传中状态
const isUploading2 = ref(false); // 上传中状态
const uploadedResumeName = ref('');
let uploadedResumeName2 = ref('');
let uploadedResumeUrl = ref(''); // 已上传
// 在onLoad中初始化数据确保页面加载时就能获取技能信息
onLoad((options = {}) => {
getRegion(1,650000000000)
getDictionary()
setTimeout(()=>{
getDetail()
},2000)
});
// 监听页面显示,接收从技能查询页面返回的数据
onShow(() => {
let params = uni.globalParams || {}; // 从全局变量获取参数
if(params.longitude&&params.latitude){
fromValue.location=params.longitude+','+params.latitude
fromValue.longitude=params.longitude
fromValue.latitude=params.latitude
}
uni.globalParams = null; // 清除全局变量,避免重复使用
// 通过事件总线接收技能选择结果
// uni.$on('skillSelected', handleSkillSelected);
});
// 页面卸载时移除事件监听
// onUnmounted(() => {
// uni.$off('skillSelected', handleSkillSelected);
// });
// 监听字典数据加载完成,自动更新学历显示
watch(() => region.provinceData[0], (newVal) => {
if (newVal&&isShow.value==false) {
getRegion(2,region.provinceData[0][0].dictValue)
}
});
watch(() => region.provinceData[1], (newVal) => {
if (newVal&&isShow.value==false) {
getRegion(3,region.provinceData[1][0].dictValue)
}
});
function getDetail(){
// if(userInfo.userId){
$api.myRequest("/train/public/train/organ/getTrainByUnifiedSocialCreditCode", {
tags: "913700001630477270",
}, "GET", 9100, {
Authorization: `Bearer ${uni.getStorageSync('token')}`,
'Content-Type': "application/x-www-form-urlencoded"
}).then((res) => {
if (res.code === 200) {
getRegion(2,res.data.organProvince)
getRegion(3,res.data.organCity)
fromValue = {
...fromValue,
...res.data,
location: `${res.data.longitude},${res.data.latitude}`||'',
organAddressArr: [
res.data.organProvince,
res.data.organCity,
res.data.organCounty,
],
};
let courseLists=res.data.course.split(",")
courseLists.forEach(item=>{
courseLabels.value.forEach(val=>{
if(item==val.dictValue){
val.checked=true
}
})
})
isShow.value=true
uploadedResumeName2.value = res.data.logo?(JSON.parse(res.data.logo))[0].name:'';
uploadedResumeUrl.value = res.data.logo?config.trainVideoImgUrl+(JSON.parse(res.data.logo))[0].url:'';
fileListss.list = JSON.parse(res.data.zhengshu) || [];
setTimeout(()=>{
region.provinceData[0].forEach((item,index)=>{
if(item.dictValue==res.data.organProvince){
region.arrayIndex[0]=index
}
})
region.provinceData[1].forEach((item,index)=>{
if(item.dictValue==res.data.organCity){
region.arrayIndex[1]=index
}
})
region.provinceData[2].forEach((item,index)=>{
if(item.dictValue==res.data.organCounty){
region.arrayIndex[2]=index
}
})
},2000)
}
})
// }else{
// $api.msg('请先登录');
// }
}
function getDictionary(){
$api.myRequest('/system/public/dict/data/type/course_type', {},'get',9100).then((resData) => {
courseLabels.value=resData.data;
courseLabels.value.forEach(item=>{
item.checked=false;
})
});
}
function getRegion(level,value){
let header = {
'Authorization': uni.getStorageSync('token')||'',
'Content-Type': "application/x-www-form-urlencoded"
};
$api.myRequest('/system/public/dict/data/getByParentValue', {
dictType: "administrative_division",
dictParentValue: value ? value: "-1",
childFlag: (level&&level > 1) ? "0" : "1",
},'post',9100,header).then((resData) => {
if(resData.code==200){
region.provinceData[level-1]=resData.data
}
});
}
function onWorkTypePickerChange(e){
region.arrayIndex=e.detail.value;
isShow.value=true
}
function onWorkTypeColumnChange(e){
const { column, value } = e.detail;
const newIndexes = [...region.arrayIndex];
newIndexes[column] = value;
// 重置后续列的数据
if (column === 0) {
// 第一列变化,重置第二、三列
const selectedLevel1 = region.provinceData[0][value];
if (selectedLevel1) {
getRegion(2,selectedLevel1.dictValue)
region.arrayIndex[1] = 0;
region.arrayIndex[2] = 0;
}
} else if (column === 1) {
// 第二列变化,重置第三列
const selectedLevel2 = this.workTypeColumns[1][value];
if (selectedLevel2) {
getRegion(3,selectedLevel2.dictValue)
region.arrayIndex[2] = 0;
}
}
this.workTypeIndexes = newIndexes;
}
const confirm = () => {
if (!fromValue.organName) {
return $api.msg('请输入机构名称');
}
if (!fromValue.contactName) {
return $api.msg('请输入联系人');
}
if (!fromValue.contactPhone) {
return $api.msg('请输入联系方式');
}
if (!checkingPhoneRegExp(fromValue.contactPhone)) {
return $api.msg('请输入正确联系方式');
}
if (!fromValue.unifiedSocialCreditCode) {
return $api.msg('请输入统一社会信用代码');
}
fromValue.organAddressArr=[
region.provinceData[0][region.arrayIndex[0]].dictValue,
region.provinceData[1][region.arrayIndex[1]].dictValue,
region.provinceData[2][region.arrayIndex[2]].dictValue
]
let courseList=[]
courseLabels.value.forEach(item=>{
if(item.checked==true){
courseList.push(item.dictValue)
}
})
const params = {
...fromValue,
organProvince: region.provinceData[0][region.arrayIndex[0]].dictValue, // 机构所在省
organCity: region.provinceData[1][region.arrayIndex[1]].dictValue, // 机构所在市
organCounty: region.provinceData[2][region.arrayIndex[2]].dictValue, // 机构所在区县
zhengshu: JSON.stringify(fileListss.list),
course: courseList.join(","), // 培训项目
logo: JSON.stringify([{name:uploadedResumeName2.value,url:uploadedResumeUrl.value}]), // 机构logo
};
$api.myRequest('/train/public/train/organ/maintainTrainOrgan', params, 'post').then((resData) => {
if(resData.code==200){
$api.msg(resData.msg);
setTimeout(()=>{
navBack();
},2000)
}
});
};
function checkboxChange(e){
var items = courseLabels.value,
values = e.detail.value;
for (var i = 0, lenI = items.length; i < lenI; ++i) {
const item = items[i]
if(values.includes(item.value)){
this.$set(item,'checked',true)
}else{
this.$set(item,'checked',false)
}
}
}
function selectLocation(){
uni.navigateTo({
url:'/packageB/components/map?location='+fromValue.location
})
}
function handleResumeUpload(){
// 从缓存获取用户ID参考首页实现方式
// 优先从store获取如果为空则从缓存获取
const storeUserId = userInfo.value?.userId;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedUserId = cachedUserInfo.userId;
// 获取用户ID优先使用store中的userId如果store中没有使用缓存中的userId
const userId = storeUserId || cachedUserId;
if (!userId) {
$api.msg('请先登录');
return;
}
// 检查是否正在上传
if (isUploading.value) {
return;
}
// 选择文件(微信小程序使用 wx.chooseMessageFileuni-app 中对应 uni.chooseMessageFile
uni.chooseMessageFile({
count: 1, // 只能选择一个文件
type: 'file', // 选择任意文件类型
success: (res) => {
// 注意:文件路径在 res.tempFiles[0].path
const file = res.tempFiles[0];
const tempFilePath = file.path; // 获取临时文件路径
const fileName = file.name; // 获取文件名
uploadedResumeName.value=file.name
// 检查文件大小20MB = 20 * 1024 * 1024 字节)
const maxSize = 20 * 1024 * 1024;
if (file.size > maxSize) {
$api.msg('文件大小不能超过 20MB');
return;
}
// 开始上传
uploadResumeFile(tempFilePath, fileName, userId);
},
fail: (err) => {
console.error('选择文件失败:', err);
// 用户取消选择不提示错误
if (err.errMsg && !err.errMsg.includes('cancel')) {
$api.msg('选择文件失败,请重试');
}
}
});
};
// 上传简历文件到服务器(使用 wx.uploadFileuni-app 中对应 uni.uploadFile
function uploadResumeFile(filePath, fileName, userId){
// 确保 userId 存在且有效
if (!userId) {
// 如果传入的userId为空尝试从缓存再次获取
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedUserId = cachedUserInfo.userId;
if (!cachedUserId) {
$api.msg('用户ID不存在无法上传');
return;
}
// 使用缓存中的userId
userId = cachedUserId;
}
isUploading.value = true;
// 获取token从缓存获取参考首页实现方式
let Authorization = '';
const tokenValue = uni.getStorageSync('token') || '';
if (tokenValue) {
Authorization = tokenValue;
} else {
// 如果缓存中没有token尝试从store获取
const userStore = useUserStore();
if (userStore.token) {
Authorization = userStore.token;
}
}
// 根据接口文档bussinessId 应该作为 Query 参数传递,而不是 formData
// 将 bussinessId 拼接到 URL 上作为查询参数
const uploadUrl = `${config.baseUrl}/app/file/upload?bussinessId=${encodeURIComponent(String(userId))}`;
uni.uploadFile({
url: uploadUrl,
filePath: filePath,
name: 'file',
header: {
'Authorization': encodeURIComponent(Authorization)
},
// formData: {
// 'user': 'test'
// },
success: (uploadFileRes) => {
isUploading.value = false;
let resData;
if (typeof uploadFileRes.data === 'string') {
resData = JSON.parse(uploadFileRes.data);
} else {
resData = uploadFileRes.data;
}
// 判断上传是否成功
if (uploadFileRes.statusCode === 200 && resData.code === 200) {
ceshi(resData.msg)
// 上传成功,处理返回结果
$api.msg('上传成功');
} else {
// 上传失败
const errorMsg = resData.msg || resData.message || '上传失败,请重试';
$api.msg(errorMsg);
// console.error('上传失败:', resData);
}
},
fail: (err) => {
// 上传失败
console.error('上传文件失败:', err);
$api.msg('上传失败,请检查网络连接');
},
});
};
function ceshi(img){
isUploading.value = false;
let arr={name:uploadedResumeName.value,url:img || ''}
fileListss.list.push(arr)
};
// 删除已上传的简历
const handleDeleteResume = (item) => {
if (!uploadedResumeName.value) {
return;
}
uni.showModal({
title: '确认删除',
content: '确定要删除已上传的证书吗?',
success: (res) => {
if (res.confirm) {
var array = JSON.parse(JSON.stringify(fileListss.list));
var index = array.indexOf(item);
if (index > -1) {
array.splice(index, 1); // 从 index 处开始删除一个元素
}
fileListss.list=array
// 清除本地数据
uploadedResumeName.value = '';
$api.msg('已删除');
// 如果需要,可以调用后端接口删除服务器上的文件
// deleteResumeFile(userId);
}
}
});
};
function handleResumeUpload2(){
// 从缓存获取用户ID参考首页实现方式
// 优先从store获取如果为空则从缓存获取
const storeUserId = userInfo.value?.userId;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedUserId = cachedUserInfo.userId;
// 获取用户ID优先使用store中的userId如果store中没有使用缓存中的userId
const userId = storeUserId || cachedUserId;
if (!userId) {
$api.msg('请先登录');
return;
}
// 检查是否正在上传
if (isUploading2.value) {
return;
}
// 选择文件(微信小程序使用 wx.chooseMessageFileuni-app 中对应 uni.chooseMessageFile
uni.chooseMessageFile({
count: 1, // 只能选择一个文件
type: 'file', // 选择任意文件类型
success: (res) => {
// 注意:文件路径在 res.tempFiles[0].path
const file = res.tempFiles[0];
const tempFilePath = file.path; // 获取临时文件路径
const fileName = file.name; // 获取文件名
uploadedResumeName2.value=file.name
// 检查文件大小20MB = 20 * 1024 * 1024 字节)
const maxSize = 20 * 1024 * 1024;
if (file.size > maxSize) {
$api.msg('文件大小不能超过 20MB');
return;
}
// 开始上传
uploadResumeFile2(tempFilePath, fileName, userId);
},
fail: (err) => {
console.error('选择文件失败:', err);
// 用户取消选择不提示错误
if (err.errMsg && !err.errMsg.includes('cancel')) {
$api.msg('选择文件失败,请重试');
}
}
});
};
// 上传简历文件到服务器(使用 wx.uploadFileuni-app 中对应 uni.uploadFile
function uploadResumeFile2(filePath, fileName, userId){
// 确保 userId 存在且有效
if (!userId) {
// 如果传入的userId为空尝试从缓存再次获取
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedUserId = cachedUserInfo.userId;
if (!cachedUserId) {
$api.msg('用户ID不存在无法上传');
return;
}
// 使用缓存中的userId
userId = cachedUserId;
}
isUploading2.value = true;
// 获取token从缓存获取参考首页实现方式
let Authorization = '';
const tokenValue = uni.getStorageSync('token') || '';
if (tokenValue) {
Authorization = tokenValue;
} else {
// 如果缓存中没有token尝试从store获取
const userStore = useUserStore();
if (userStore.token) {
Authorization = userStore.token;
}
}
// 根据接口文档bussinessId 应该作为 Query 参数传递,而不是 formData
// 将 bussinessId 拼接到 URL 上作为查询参数
const uploadUrl = `${config.baseUrl}/app/file/upload?bussinessId=${encodeURIComponent(String(userId))}`;
uni.uploadFile({
url: uploadUrl,
filePath: filePath,
name: 'file',
header: {
'Authorization': encodeURIComponent(Authorization)
},
// formData: {
// 'user': 'test'
// },
success: (uploadFileRes) => {
isUploading2.value = false;
let resData;
if (typeof uploadFileRes.data === 'string') {
resData = JSON.parse(uploadFileRes.data);
} else {
resData = uploadFileRes.data;
}
// 判断上传是否成功
if (uploadFileRes.statusCode === 200 && resData.code === 200) {
ceshi2(resData.msg)
// 上传成功,处理返回结果
$api.msg('上传成功');
} else {
// 上传失败
const errorMsg = resData.msg || resData.message || '上传失败,请重试';
$api.msg(errorMsg);
// console.error('上传失败:', resData);
}
},
fail: (err) => {
// 上传失败
console.error('上传文件失败:', err);
$api.msg('上传失败,请检查网络连接');
},
});
};
function ceshi2(img){
isUploading2.value = false;
uploadedResumeUrl.value=img;
};
</script>
<style lang="stylus" scoped>
.btn{
margin-top: -30rpx
}
.input-required{
color: red
}
/* 上传按钮 */
.upload-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 10rpx;
padding: 0 30rpx;
background-color: #f5f7fa;
color: #1677ff;
border-radius: 8rpx;
font-size: 26rpx;
margin-top: 20rpx;
}
.upload-icon {
width: 30rpx;
height: 30rpx;
}
.reupload-text {
font-size: 22rpx;
color: #666;
}
/* 上传说明文字 */
.upload-tip {
font-size: 20rpx;
color: #999;
text-align: center;
line-height: 1.4;
}
/* 已上传文件信息 */
.uploaded-file-info>view {
display: flex;
align-items: center;
gap: 15rpx;
padding: 15rpx 20rpx;
background-color: #fafafa;
border-radius: 8rpx;
margin-top: 10rpx;
}
.file-icon {
width: 36rpx;
height: 36rpx;
}
.file-name {
font-size: 24rpx;
color: #333;
max-width: 400rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.delete-file-btn {
padding: 0 15rpx;
height: 36rpx;
line-height: 36rpx;
font-size: 22rpx;
color: #ff4d4f;
background-color: transparent;
}
.content{
padding: 28rpx;
display: flex;
flex-direction: column;
justify-content: flex-start
height: calc(100% - 120rpx)
}
.footer{
width: 100%;
height: 120rpx;
background: #fff;
position: fixed;
z-index: 10;
bottom: 0;
left: 0;
display: flex;
align-content: center;
justify-content: center;
}
.footerBtn{
width: 90%;
height: 90rpx;
line-height: 90rpx;
text-align: center
border-radius: 10rpx;
color: #fff;
background: #409EFF;
}
.content-input
margin-bottom: 52rpx
.input-titile
font-weight: 400;
font-size: 28rpx;
color: #6A6A6A
.input-con
font-weight: 400;
font-size: 32rpx;
color: #333333;
line-height: 80rpx;
height: 80rpx;
border-bottom: 2rpx solid #EBEBEB
position: relative;
.error-message
color: #ff4757;
font-size: 24rpx;
margin-top: 10rpx;
line-height: 1.4;
.success-message
color: #2ed573;
font-size: 24rpx;
margin-top: 10rpx;
line-height: 1.4;
.input-error
.input-con
border-bottom-color: #ff4757;
.triangle::before
position: absolute;
right: 20rpx;
top: calc(50% - 2rpx);
content: '';
width: 4rpx;
height: 18rpx;
border-radius: 2rpx
background: #697279;
transform: translate(0, -50%) rotate(-45deg) ;
.triangle::after
position: absolute;
right: 20rpx;
top: 50%;
content: '';
width: 4rpx;
height: 18rpx;
border-radius: 2rpx
background: #697279;
transform: rotate(45deg)
.input-nx
position: relative
border-bottom: 2rpx solid #EBEBEB
padding-bottom: 30rpx
display: flex
flex-wrap: wrap
.nx-item
padding: 16rpx 24rpx
width: fit-content
border-radius: 20rpx
border: 2rpx solid #E8EAEE
background-color: #f8f9fa
margin-right: 16rpx
margin-top: 16rpx
font-size: 28rpx
color: #333333
transition: all 0.2s ease
&:hover
background-color: #e9ecef
border-color: #256bfa
color: #256bfa
.content-sex
height: 110rpx;
display: flex
justify-content: space-between;
align-items: flex-start;
border-bottom: 2rpx solid #EBEBEB
margin-bottom: 52rpx
.sex-titile
line-height: 80rpx;
.sext-ri
display: flex
align-items: center;
.sext-box
height: 76rpx;
width: 152rpx;
text-align: center;
line-height: 80rpx;
border-radius: 12rpx 12rpx 12rpx 12rpx
border: 2rpx solid #E8EAEE;
margin-left: 28rpx
font-weight: 400;
font-size: 28rpx;
.sext-boxactive
color: #256BFA
background: rgba(37,107,250,0.1);
border: 2rpx solid #256BFA;
.next-btn
width: 100%;
height: 90rpx;
background: #256BFA;
border-radius: 12rpx 12rpx 12rpx 12rpx;
font-weight: 500;
font-size: 32rpx;
color: #FFFFFF;
text-align: center;
line-height: 90rpx
// 技能信息样式
.content-skills
margin-bottom: 52rpx
.skills-header
display: flex
justify-content: space-between
align-items: center
margin-bottom: 32rpx
.input-titile
font-weight: 400
font-size: 28rpx
color: #6A6A6A
.add-skill-btn
padding: 16rpx 32rpx
background: #256BFA
color: #FFFFFF
border-radius: 8rpx
font-size: 26rpx
font-weight: 500
transition: all 0.3s ease
&:active
background: #1a5cd9
transform: scale(0.98)
&.disabled
background: #CCCCCC
color: #999999
cursor: not-allowed
&:active
background: #CCCCCC
transform: none
.skills-list
.skill-item
background: #FFFFFF
border: 2rpx solid #E8EAEE
border-radius: 12rpx
padding: 24rpx
margin-bottom: 24rpx
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05)
transition: all 0.3s ease
&:hover
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1)
border-color: #256BFA
.skill-header
display: flex
justify-content: space-between
align-items: center
margin-bottom: 20rpx
.skill-number
font-weight: 500
font-size: 28rpx
color: #333333
.skill-actions
.action-btn
padding: 8rpx 16rpx
border-radius: 6rpx
font-size: 24rpx
font-weight: 400
transition: all 0.2s ease
&.delete-btn
background: #FF4D4F
color: #FFFFFF
&:active
background: #D9363E
transform: scale(0.95)
.skill-fields
display: flex
flex-direction: column
gap: 20rpx
.skill-field
.field-label
font-weight: 400
font-size: 26rpx
color: #6A6A6A
margin-bottom: 8rpx
.field-input
font-weight: 400
font-size: 28rpx
color: #333333
line-height: 72rpx
height: 72rpx
border: 2rpx solid #E8EAEE
border-radius: 8rpx
padding: 0 20rpx
background: #F8F9FA
transition: all 0.3s ease
&:focus
border-color: #256BFA
background: #FFFFFF
&.triangle::before
right: 30rpx
top: calc(50% - 2rpx)
&.triangle::after
right: 30rpx
top: 50%
.empty-skills
text-align: center
padding: 60rpx 0
background: #F8F9FA
border-radius: 12rpx
border: 2rpx dashed #E8EAEE
.empty-text
font-size: 28rpx
color: #999999
font-weight: 400
</style>