问卷调整
This commit is contained in:
parent
2a6fb3d916
commit
904471d156
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<!-- 版本号:每次发布时自动更新 -->
|
<!-- 版本号:每次发布时自动更新 -->
|
||||||
<meta name="version" content="20251219-120015">
|
<meta name="version" content="20251223-185504">
|
||||||
<!-- HTML文件不缓存,但允许静态资源缓存 -->
|
<!-- HTML文件不缓存,但允许静态资源缓存 -->
|
||||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||||||
<meta http-equiv="Pragma" content="no-cache">
|
<meta http-equiv="Pragma" content="no-cache">
|
||||||
@ -14,7 +14,7 @@
|
|||||||
document.write(
|
document.write(
|
||||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||||
log=false
|
var log = false;
|
||||||
|
|
||||||
// 版本检查:如果检测到新版本,清除缓存并刷新
|
// 版本检查:如果检测到新版本,清除缓存并刷新
|
||||||
(function() {
|
(function() {
|
||||||
|
|||||||
@ -78,6 +78,10 @@ export const findAllZw = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
:mode="attrs.componentProps.mode"
|
:mode="attrs.componentProps.mode"
|
||||||
:title="attrs.label"
|
:title="attrs.label"
|
||||||
:value="newValue ? newValue : undefined"
|
:value="newValue ? newValue : undefined"
|
||||||
|
:onPopupChange="handlePopupChange"
|
||||||
@confirm="confirm"
|
@confirm="confirm"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
@ -94,4 +95,14 @@ function confirm(e: any) {
|
|||||||
attrs.componentProps.ok(e, attrs);
|
attrs.componentProps.ok(e, attrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理弹窗状态变化
|
||||||
|
function handlePopupChange(e: any) {
|
||||||
|
if (
|
||||||
|
attrs.componentProps.onPopupChange &&
|
||||||
|
typeof attrs.componentProps.onPopupChange === "function"
|
||||||
|
) {
|
||||||
|
attrs.componentProps.onPopupChange(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
v-model="pickerKey"
|
v-model="pickerKey"
|
||||||
@ok="ok"
|
@ok="ok"
|
||||||
@change="change"
|
@change="change"
|
||||||
|
@popupChange="handlePopupChange"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -161,6 +162,16 @@ function change(e: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理弹窗状态变化
|
||||||
|
function handlePopupChange(e: any) {
|
||||||
|
if (
|
||||||
|
attrs.componentProps.onPopupChange &&
|
||||||
|
typeof attrs.componentProps.onPopupChange === "function"
|
||||||
|
) {
|
||||||
|
attrs.componentProps.onPopupChange(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const pickerValue = ref<any>("");
|
const pickerValue = ref<any>("");
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
:rangeKey="rangeKey"
|
:rangeKey="rangeKey"
|
||||||
:title="'选择'+ attrs.label"
|
:title="'选择'+ attrs.label"
|
||||||
@confirm="confirm"
|
@confirm="confirm"
|
||||||
v-bind="attrs.componentProps"
|
:onPopupChange="handlePopupChange"
|
||||||
|
v-bind="treeProps"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -60,6 +61,12 @@
|
|||||||
const rangeKey = ref(attrs.componentProps && attrs.componentProps.rangeKey || '')
|
const rangeKey = ref(attrs.componentProps && attrs.componentProps.rangeKey || '')
|
||||||
const savaKey = ref(attrs.componentProps && attrs.componentProps.savaKey || '')
|
const savaKey = ref(attrs.componentProps && attrs.componentProps.savaKey || '')
|
||||||
|
|
||||||
|
// 过滤掉 onPopupChange,避免重复传递
|
||||||
|
const treeProps = computed(() => {
|
||||||
|
const { onPopupChange, ...rest } = attrs.componentProps || {}
|
||||||
|
return rest
|
||||||
|
})
|
||||||
|
|
||||||
const range = computed({
|
const range = computed({
|
||||||
get() {
|
get() {
|
||||||
if (attrs.componentProps && attrs.componentProps.range) {
|
if (attrs.componentProps && attrs.componentProps.range) {
|
||||||
@ -106,6 +113,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理弹窗状态变化
|
||||||
|
function handlePopupChange(e: any) {
|
||||||
|
if (
|
||||||
|
attrs.componentProps.onPopupChange &&
|
||||||
|
typeof attrs.componentProps.onPopupChange === "function"
|
||||||
|
) {
|
||||||
|
attrs.componentProps.onPopupChange(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function hx(rangeData: any, data: any) {
|
function hx(rangeData: any, data: any) {
|
||||||
let valueList = data.split(',')
|
let valueList = data.split(',')
|
||||||
for (const key in rangeData) {
|
for (const key in rangeData) {
|
||||||
|
|||||||
@ -81,6 +81,11 @@ const props = defineProps({
|
|||||||
type: Array,
|
type: Array,
|
||||||
default: [0],
|
default: [0],
|
||||||
},
|
},
|
||||||
|
// 支持通过 props 传递弹窗状态变化回调
|
||||||
|
onPopupChange: {
|
||||||
|
type: Function,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits([
|
const emits = defineEmits([
|
||||||
@ -132,6 +137,14 @@ function ok() {
|
|||||||
|
|
||||||
function popupChange(e) {
|
function popupChange(e) {
|
||||||
emits("popupChange", e);
|
emits("popupChange", e);
|
||||||
|
// 如果传递了回调函数,调用它
|
||||||
|
if (props.onPopupChange) {
|
||||||
|
try {
|
||||||
|
props.onPopupChange(e);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[BasicPicker] 调用 onPopupChange 失败:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({ open, close });
|
defineExpose({ open, close });
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<uni-popup ref="popup" background-color="#fff" class="popup">
|
<uni-popup ref="popup" background-color="#fff" class="popup" @change="popupChange">
|
||||||
<view class="center flex-col wh-full">
|
<view class="center flex-col wh-full">
|
||||||
<view class="flex-row justify-between p-15">
|
<view class="flex-row justify-between p-15">
|
||||||
<view @click="close">
|
<view @click="close">
|
||||||
@ -115,6 +115,11 @@ export default {
|
|||||||
defaultIndex: {
|
defaultIndex: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
|
},
|
||||||
|
// 支持通过 props 传递弹窗状态变化回调
|
||||||
|
onPopupChange: {
|
||||||
|
type: Function,
|
||||||
|
default: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -156,6 +161,16 @@ export default {
|
|||||||
emits: ['close', 'canel', 'confirm', 'change'],
|
emits: ['close', 'canel', 'confirm', 'change'],
|
||||||
// #endif
|
// #endif
|
||||||
methods: {
|
methods: {
|
||||||
|
popupChange(e) {
|
||||||
|
// 如果传递了回调函数,调用它
|
||||||
|
if (this.onPopupChange) {
|
||||||
|
try {
|
||||||
|
this.onPopupChange(e)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[DatetimePicker] 调用 onPopupChange 失败:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
init() {
|
init() {
|
||||||
this.innerValue = this.correctValue(this.value)
|
this.innerValue = this.correctValue(this.value)
|
||||||
this.updateColumnValue(this.innerValue)
|
this.updateColumnValue(this.innerValue)
|
||||||
|
|||||||
@ -118,6 +118,11 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
// 支持通过 props 传递弹窗状态变化回调
|
||||||
|
onPopupChange: {
|
||||||
|
type: Function,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -130,9 +135,25 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
_show() {
|
_show() {
|
||||||
this.showTree = true
|
this.showTree = true
|
||||||
|
// 触发弹窗打开事件
|
||||||
|
if (this.onPopupChange && typeof this.onPopupChange === 'function') {
|
||||||
|
try {
|
||||||
|
this.onPopupChange({ show: true, type: 'bottom' })
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[BasicTree] 调用 onPopupChange 失败:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_hide() {
|
_hide() {
|
||||||
this.showTree = false
|
this.showTree = false
|
||||||
|
// 触发弹窗关闭事件
|
||||||
|
if (this.onPopupChange && typeof this.onPopupChange === 'function') {
|
||||||
|
try {
|
||||||
|
this.onPopupChange({ show: false, type: 'bottom' })
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[BasicTree] 调用 onPopupChange 失败:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_cancel() {
|
_cancel() {
|
||||||
this._hide()
|
this._hide()
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<text class="loading-text">{{ loadingText }}</text>
|
<text class="loading-text">{{ loadingText }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y class="form-scroll" :enable-back-to-top="false">
|
<scroll-view scroll-y class="form-scroll" :class="{ 'full-height': hideBottomBtn }" :enable-back-to-top="false">
|
||||||
<view class="form-container">
|
<view class="form-container">
|
||||||
<!-- 积分标准区域 -->
|
<!-- 积分标准区域 -->
|
||||||
<view class="section">
|
<view class="section">
|
||||||
@ -148,13 +148,11 @@
|
|||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<template #bottom>
|
<view class="bottom-btn-area" :class="{ 'hide-bottom': hideBottomBtn }">
|
||||||
<view class="fixed-bottom">
|
<button class="save-button" @click="handleSubmit" :disabled="submitting">
|
||||||
<button class="submit-btn" @click="handleSubmit" :disabled="submitting">
|
{{ submitting ? '保存中...' : '保存' }}
|
||||||
{{ submitting ? '保存中...' : '保存' }}
|
</button>
|
||||||
</button>
|
</view>
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</BasicLayout>
|
</BasicLayout>
|
||||||
<view v-else class="edit-content-wrapper">
|
<view v-else class="edit-content-wrapper">
|
||||||
<view v-if="loading" class="loading-mask">
|
<view v-if="loading" class="loading-mask">
|
||||||
@ -326,6 +324,15 @@ import CertificateUpload from "@/components/CertificateUpload/index.vue";
|
|||||||
// 独立页面使用;可根据参数隐藏保存按钮(查看模式)
|
// 独立页面使用;可根据参数隐藏保存按钮(查看模式)
|
||||||
const showSaveButton = ref(true);
|
const showSaveButton = ref(true);
|
||||||
|
|
||||||
|
// 是否隐藏底部按钮
|
||||||
|
const hideBottomBtn = ref(false);
|
||||||
|
|
||||||
|
// 处理选择器弹窗状态变化
|
||||||
|
const handlePickerPopupChange = (e: any) => {
|
||||||
|
// e.show 为 true 表示弹窗打开,false 表示关闭
|
||||||
|
hideBottomBtn.value = e.show;
|
||||||
|
};
|
||||||
|
|
||||||
const formData = reactive<any>({
|
const formData = reactive<any>({
|
||||||
id: '',
|
id: '',
|
||||||
jfTypeId: '',
|
jfTypeId: '',
|
||||||
@ -1092,7 +1099,8 @@ const formSchema = computed(() => {
|
|||||||
selectParent: false,
|
selectParent: false,
|
||||||
defaultExpandLevel: 0,
|
defaultExpandLevel: 0,
|
||||||
confirmColor: "#3b82f6",
|
confirmColor: "#3b82f6",
|
||||||
ok: handleJfTypeTreeConfirm
|
ok: handleJfTypeTreeConfirm,
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1150,7 +1158,8 @@ const assessmentSchema = computed(() => {
|
|||||||
range: hjlxOptions.value,
|
range: hjlxOptions.value,
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择获奖类型'
|
placeholder: '请选择获奖类型',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1174,7 +1183,8 @@ const assessmentSchema = computed(() => {
|
|||||||
mode: "date",
|
mode: "date",
|
||||||
minDate: dayjs('1950-01-01').valueOf(),
|
minDate: dayjs('1950-01-01').valueOf(),
|
||||||
maxDate: dayjs().valueOf(),
|
maxDate: dayjs().valueOf(),
|
||||||
placeholder: '请选择获奖时间'
|
placeholder: '请选择获奖时间',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 根据 showStudentAward 动态添加获奖名单和获奖人数字段
|
// 根据 showStudentAward 动态添加获奖名单和获奖人数字段
|
||||||
@ -1206,6 +1216,7 @@ const assessmentSchema = computed(() => {
|
|||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择类别',
|
placeholder: '请选择类别',
|
||||||
|
onPopupChange: handlePickerPopupChange,
|
||||||
ok: () => {
|
ok: () => {
|
||||||
if (formData.category && scoreConfig.value) {
|
if (formData.category && scoreConfig.value) {
|
||||||
checkGradeFieldVisibility(scoreConfig.value, formData.category);
|
checkGradeFieldVisibility(scoreConfig.value, formData.category);
|
||||||
@ -1222,7 +1233,8 @@ const assessmentSchema = computed(() => {
|
|||||||
range: defaultLevels,
|
range: defaultLevels,
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择级别'
|
placeholder: '请选择级别',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -1241,7 +1253,8 @@ const assessmentSchema = computed(() => {
|
|||||||
],
|
],
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择等级'
|
placeholder: '请选择等级',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1754,8 +1767,13 @@ onLoad(async (options: any) => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.form-scroll {
|
.form-scroll {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: calc(100vh - 120rpx);
|
height: calc(100vh - 140rpx);
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
|
transition: height 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-scroll.full-height {
|
||||||
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-content-wrapper {
|
.edit-content-wrapper {
|
||||||
@ -1809,38 +1827,46 @@ onLoad(async (options: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-bottom {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
.bottom-btn-area {
|
||||||
left: 0;
|
padding: 20rpx 30rpx;
|
||||||
right: 0;
|
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
|
||||||
background: #ffffff;
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||||
padding: 24rpx;
|
background: #fff;
|
||||||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
|
border-top: 1rpx solid #e5e5e5;
|
||||||
z-index: 100;
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&.hide-bottom {
|
||||||
|
display: none !important;
|
||||||
|
height: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
border: none !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit-btn {
|
.save-button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 88rpx;
|
height: 80rpx;
|
||||||
line-height: 88rpx;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
background: #3b82f6;
|
color: #fff;
|
||||||
color: #ffffff;
|
font-size: 30rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
border-radius: 40rpx;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 16rpx;
|
display: flex;
|
||||||
font-size: 32rpx;
|
align-items: center;
|
||||||
font-weight: 600;
|
justify-content: center;
|
||||||
box-shadow: 0 4rpx 16rpx rgba(59, 130, 246, 0.3);
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background: #9ca3af;
|
opacity: 0.6;
|
||||||
box-shadow: none;
|
background: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active:not(:disabled) {
|
&:active:not(:disabled) {
|
||||||
transform: scale(0.98);
|
opacity: 0.8;
|
||||||
background: #1d4ed8;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<text class="loading-text">{{ loadingText }}</text>
|
<text class="loading-text">{{ loadingText }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y class="form-scroll">
|
<scroll-view scroll-y class="form-scroll" :class="{ 'full-height': hideBottomBtn }" :enable-back-to-top="false">
|
||||||
<view class="form-container">
|
<view class="form-container">
|
||||||
<!-- 积分标准区域 -->
|
<!-- 积分标准区域 -->
|
||||||
<view class="section">
|
<view class="section">
|
||||||
@ -165,7 +165,7 @@
|
|||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<!-- 固定在底部的按钮组 -->
|
<!-- 固定在底部的按钮组 -->
|
||||||
<view class="fixed-bottom">
|
<view class="fixed-bottom" :class="{ 'hide-bottom': hideBottomBtn }">
|
||||||
<view class="button-group">
|
<view class="button-group">
|
||||||
<button class="save-btn" @click="handleSave" :disabled="saving || submitting">
|
<button class="save-btn" @click="handleSave" :disabled="saving || submitting">
|
||||||
{{ saving ? '保存中...' : '暂存' }}
|
{{ saving ? '保存中...' : '暂存' }}
|
||||||
@ -250,6 +250,7 @@ const loading = ref(false); // 页面加载状态
|
|||||||
const loadingText = ref('加载中...'); // 加载提示文本
|
const loadingText = ref('加载中...'); // 加载提示文本
|
||||||
const isResubmit = ref(false); // 是否为重新提交模式
|
const isResubmit = ref(false); // 是否为重新提交模式
|
||||||
const jfId = ref(''); // 积分ID(重新提交时使用)
|
const jfId = ref(''); // 积分ID(重新提交时使用)
|
||||||
|
const hideBottomBtn = ref(false); // 控制底部按钮区域显示/隐藏
|
||||||
// 用于强制更新表单的 key
|
// 用于强制更新表单的 key
|
||||||
const formSchemaKey = ref(0);
|
const formSchemaKey = ref(0);
|
||||||
// 用于强制更新获奖情况表单的 key
|
// 用于强制更新获奖情况表单的 key
|
||||||
@ -537,6 +538,12 @@ function findNodeById(nodes: any[], id: string, path: string[] = []): { node: an
|
|||||||
// 选中的业绩类别显示文本(用于回显)
|
// 选中的业绩类别显示文本(用于回显)
|
||||||
const selectedJfTypeText = ref('');
|
const selectedJfTypeText = ref('');
|
||||||
|
|
||||||
|
// 处理选择器弹窗状态变化
|
||||||
|
const handlePickerPopupChange = (e: any) => {
|
||||||
|
// e.show 为 true 表示弹窗打开,false 表示关闭
|
||||||
|
hideBottomBtn.value = e.show;
|
||||||
|
};
|
||||||
|
|
||||||
// 初始化回显:根据 formData.jfTypeId 设置显示文本
|
// 初始化回显:根据 formData.jfTypeId 设置显示文本
|
||||||
const initJfTypeDisplay = () => {
|
const initJfTypeDisplay = () => {
|
||||||
if (formData.jfTypeId && jfTypeTree.value.length > 0) {
|
if (formData.jfTypeId && jfTypeTree.value.length > 0) {
|
||||||
@ -1018,7 +1025,8 @@ const formSchema = computed(() => {
|
|||||||
selectParent: false, // 只能选择叶子节点
|
selectParent: false, // 只能选择叶子节点
|
||||||
defaultExpandLevel: 0, // 默认不展开
|
defaultExpandLevel: 0, // 默认不展开
|
||||||
confirmColor: "#3b82f6",
|
confirmColor: "#3b82f6",
|
||||||
ok: handleJfTypeTreeConfirm
|
ok: handleJfTypeTreeConfirm,
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1067,7 +1075,8 @@ const assessmentSchema = computed(() => {
|
|||||||
range: hjlxOptions.value,
|
range: hjlxOptions.value,
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择获奖类型'
|
placeholder: '请选择获奖类型',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1091,7 +1100,8 @@ const assessmentSchema = computed(() => {
|
|||||||
mode: "date",
|
mode: "date",
|
||||||
minDate: dayjs('1950-01-01').valueOf(),
|
minDate: dayjs('1950-01-01').valueOf(),
|
||||||
maxDate: dayjs().valueOf(),
|
maxDate: dayjs().valueOf(),
|
||||||
placeholder: '请选择获奖时间'
|
placeholder: '请选择获奖时间',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 根据 showStudentAward 动态添加获奖名单和获奖人数字段
|
// 根据 showStudentAward 动态添加获奖名单和获奖人数字段
|
||||||
@ -1123,6 +1133,7 @@ const assessmentSchema = computed(() => {
|
|||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择类别',
|
placeholder: '请选择类别',
|
||||||
|
onPopupChange: handlePickerPopupChange,
|
||||||
ok: () => {
|
ok: () => {
|
||||||
// 选择类别后,检查是否需要显示等级字段
|
// 选择类别后,检查是否需要显示等级字段
|
||||||
if (formData.category && scoreConfig.value) {
|
if (formData.category && scoreConfig.value) {
|
||||||
@ -1140,7 +1151,8 @@ const assessmentSchema = computed(() => {
|
|||||||
range: defaultLevels,
|
range: defaultLevels,
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择级别'
|
placeholder: '请选择级别',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -1160,7 +1172,8 @@ const assessmentSchema = computed(() => {
|
|||||||
],
|
],
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择等级'
|
placeholder: '请选择等级',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1903,6 +1916,10 @@ onLoad(async (options: any) => {
|
|||||||
.form-scroll {
|
.form-scroll {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: calc(100vh - 120rpx);
|
height: calc(100vh - 120rpx);
|
||||||
|
|
||||||
|
&.full-height {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-container {
|
.form-container {
|
||||||
@ -1952,6 +1969,12 @@ onLoad(async (options: any) => {
|
|||||||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
&.hide-bottom {
|
||||||
|
display: none !important;
|
||||||
|
height: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.button-group {
|
.button-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 24rpx;
|
gap: 24rpx;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasicLayout v-if="showSaveButton">
|
<BasicLayout v-if="showSaveButton">
|
||||||
<scroll-view scroll-y class="form-scroll" :enable-back-to-top="false">
|
<scroll-view scroll-y class="form-scroll" :class="{ 'full-height': hideBottomBtn }" :enable-back-to-top="false">
|
||||||
<view class="form-container">
|
<view class="form-container">
|
||||||
<!-- 积分标准区域 -->
|
<!-- 积分标准区域 -->
|
||||||
<view class="section">
|
<view class="section">
|
||||||
@ -134,7 +134,7 @@
|
|||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<view class="fixed-bottom">
|
<view class="fixed-bottom" :class="{ 'hide-bottom': hideBottomBtn }">
|
||||||
<button class="submit-btn" @click="handleSubmit" :disabled="submitting">
|
<button class="submit-btn" @click="handleSubmit" :disabled="submitting">
|
||||||
{{ submitting ? '保存中...' : '保存' }}
|
{{ submitting ? '保存中...' : '保存' }}
|
||||||
</button>
|
</button>
|
||||||
@ -310,6 +310,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'saved'): void;
|
(e: 'saved'): void;
|
||||||
(e: 'loaded'): void;
|
(e: 'loaded'): void;
|
||||||
|
(e: 'popup-change', show: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 表单数据(暴露给父组件访问)
|
// 表单数据(暴露给父组件访问)
|
||||||
@ -365,6 +366,16 @@ const formSchemaKey = ref(0);
|
|||||||
const assessmentSchemaKey = ref(0);
|
const assessmentSchemaKey = ref(0);
|
||||||
// 证书上传组件引用
|
// 证书上传组件引用
|
||||||
const certificateUploadRef = ref<any>(null);
|
const certificateUploadRef = ref<any>(null);
|
||||||
|
// 控制底部按钮区域显示/隐藏
|
||||||
|
const hideBottomBtn = ref(false);
|
||||||
|
|
||||||
|
// 处理选择器弹窗状态变化
|
||||||
|
const handlePickerPopupChange = (e: any) => {
|
||||||
|
// e.show 为 true 表示弹窗打开,false 表示关闭
|
||||||
|
hideBottomBtn.value = e.show;
|
||||||
|
// 向父组件发送弹窗状态变化事件
|
||||||
|
emit('popup-change', e.show);
|
||||||
|
};
|
||||||
|
|
||||||
// 防抖更新表单 key
|
// 防抖更新表单 key
|
||||||
let updateSchemaKeyTimer: any = null;
|
let updateSchemaKeyTimer: any = null;
|
||||||
@ -1043,7 +1054,8 @@ const assessmentSchema = computed(() => {
|
|||||||
range: hjlxOptions.value,
|
range: hjlxOptions.value,
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择获奖类型'
|
placeholder: '请选择获奖类型',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1067,7 +1079,8 @@ const assessmentSchema = computed(() => {
|
|||||||
mode: "date",
|
mode: "date",
|
||||||
minDate: dayjs('1950-01-01').valueOf(),
|
minDate: dayjs('1950-01-01').valueOf(),
|
||||||
maxDate: dayjs().valueOf(),
|
maxDate: dayjs().valueOf(),
|
||||||
placeholder: '请选择获奖时间'
|
placeholder: '请选择获奖时间',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 根据 showStudentAward 动态添加获奖名单和获奖人数字段
|
// 根据 showStudentAward 动态添加获奖名单和获奖人数字段
|
||||||
@ -1099,6 +1112,7 @@ const assessmentSchema = computed(() => {
|
|||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择类别',
|
placeholder: '请选择类别',
|
||||||
|
onPopupChange: handlePickerPopupChange,
|
||||||
ok: () => {
|
ok: () => {
|
||||||
if (formData.category && scoreConfig.value) {
|
if (formData.category && scoreConfig.value) {
|
||||||
checkGradeFieldVisibility(scoreConfig.value, formData.category);
|
checkGradeFieldVisibility(scoreConfig.value, formData.category);
|
||||||
@ -1115,7 +1129,8 @@ const assessmentSchema = computed(() => {
|
|||||||
range: defaultLevels,
|
range: defaultLevels,
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择级别'
|
placeholder: '请选择级别',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -1134,7 +1149,8 @@ const assessmentSchema = computed(() => {
|
|||||||
],
|
],
|
||||||
rangeKey: "label",
|
rangeKey: "label",
|
||||||
savaKey: "value",
|
savaKey: "value",
|
||||||
placeholder: '请选择等级'
|
placeholder: '请选择等级',
|
||||||
|
onPopupChange: handlePickerPopupChange
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1683,6 +1699,10 @@ defineExpose({
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
height: calc(100vh - 120rpx);
|
height: calc(100vh - 120rpx);
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
|
|
||||||
|
&.full-height {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-content-wrapper {
|
.edit-content-wrapper {
|
||||||
@ -1745,6 +1765,12 @@ defineExpose({
|
|||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
|
&.hide-bottom {
|
||||||
|
display: none !important;
|
||||||
|
height: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit-btn {
|
.submit-btn {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasicLayout>
|
<BasicLayout>
|
||||||
<!-- 统一的滚动容器,包含编辑组件和流程组件 -->
|
<!-- 统一的滚动容器,包含编辑组件和流程组件 -->
|
||||||
<scroll-view scroll-y class="unified-scroll">
|
<scroll-view scroll-y class="unified-scroll" :class="{ 'full-height': hideBottomBtn }">
|
||||||
<!-- 引入编辑组件(不包含滚动) -->
|
<!-- 引入编辑组件(不包含滚动) -->
|
||||||
<JfEdit v-if="isLoginReady" ref="jfEditRef" :jf-id="jfId" @saved="handleDataSaved" @loaded="handleJfEditLoaded" />
|
<JfEdit v-if="isLoginReady" ref="jfEditRef" :jf-id="jfId" @saved="handleDataSaved" @loaded="handleJfEditLoaded" @popup-change="handlePickerPopupChange" />
|
||||||
|
|
||||||
<!-- 审批流程展示 -->
|
<!-- 审批流程展示 -->
|
||||||
<view class="flow-section" v-if="jfId">
|
<view class="flow-section" v-if="jfId">
|
||||||
@ -12,26 +12,28 @@
|
|||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<YwConfirm
|
<view :class="{ 'hide-bottom': hideBottomBtn }">
|
||||||
v-if="showButton"
|
<YwConfirm
|
||||||
:spApi="wrappedJfSpApi"
|
v-if="showButton"
|
||||||
:stopApi="wrappedJfStopApi"
|
:spApi="wrappedJfSpApi"
|
||||||
:transferApi="wrappedJfTransferApi"
|
:stopApi="wrappedJfStopApi"
|
||||||
:params="spParams"
|
:transferApi="wrappedJfTransferApi"
|
||||||
:autoToMessage="false"
|
:params="spParams"
|
||||||
:showXt="false"
|
:autoToMessage="false"
|
||||||
:showReject="!isYiban"
|
:showXt="false"
|
||||||
:showTransfer="false"
|
:showReject="!isYiban"
|
||||||
:showApprove="!isYiban"
|
:showTransfer="false"
|
||||||
:showReturn="false"
|
:showApprove="!isYiban"
|
||||||
:showStop="true"
|
:showReturn="false"
|
||||||
:showXtDk="false"
|
:showStop="true"
|
||||||
approveText="通过"
|
:showXtDk="false"
|
||||||
@submit="handleSubmit"
|
approveText="通过"
|
||||||
@reject="handleReject"
|
@submit="handleSubmit"
|
||||||
@transfer="handleTransfer"
|
@reject="handleReject"
|
||||||
@stop="handleStop"
|
@transfer="handleTransfer"
|
||||||
/>
|
@stop="handleStop"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 遮罩层 -->
|
<!-- 遮罩层 -->
|
||||||
@ -64,6 +66,8 @@ const showButton = ref<boolean>(false);
|
|||||||
const isLoginReady = ref<boolean>(false); // 登录是否准备就绪
|
const isLoginReady = ref<boolean>(false); // 登录是否准备就绪
|
||||||
// 编辑组件的引用,用于获取表单数据
|
// 编辑组件的引用,用于获取表单数据
|
||||||
const jfEditRef = ref<any>(null);
|
const jfEditRef = ref<any>(null);
|
||||||
|
// 控制底部按钮区域显示/隐藏
|
||||||
|
const hideBottomBtn = ref(false);
|
||||||
// 遮罩层状态
|
// 遮罩层状态
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
const loadingText = ref<string>("处理中...");
|
const loadingText = ref<string>("处理中...");
|
||||||
@ -401,6 +405,11 @@ const wrappedJfStopApi = async (params: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理选择器弹窗状态变化
|
||||||
|
const handlePickerPopupChange = (show: boolean) => {
|
||||||
|
hideBottomBtn.value = show;
|
||||||
|
};
|
||||||
|
|
||||||
// 处理编辑组件数据加载完成
|
// 处理编辑组件数据加载完成
|
||||||
const handleJfEditLoaded = () => {
|
const handleJfEditLoaded = () => {
|
||||||
jfEditLoaded.value = true;
|
jfEditLoaded.value = true;
|
||||||
@ -553,6 +562,10 @@ onLoad(async (options: any) => {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
height: calc(100vh - 120rpx);
|
height: calc(100vh - 120rpx);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&.full-height {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-section {
|
.flow-section {
|
||||||
@ -626,5 +639,12 @@ onLoad(async (options: any) => {
|
|||||||
0% { transform: rotate(0deg); }
|
0% { transform: rotate(0deg); }
|
||||||
100% { transform: rotate(360deg); }
|
100% { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 隐藏底部按钮区域
|
||||||
|
.hide-bottom {
|
||||||
|
display: none !important;
|
||||||
|
height: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@ -300,7 +300,7 @@
|
|||||||
<view v-if="analysisResult" class="analysis-result">
|
<view v-if="analysisResult" class="analysis-result">
|
||||||
<view class="analysis-header">
|
<view class="analysis-header">
|
||||||
<u-icon name="file-text" size="20" color="#409EFF"></u-icon>
|
<u-icon name="file-text" size="20" color="#409EFF"></u-icon>
|
||||||
<text class="analysis-title">AI分析报告</text>
|
<text class="analysis-title">AI数字分析</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="analysis-content">
|
<view class="analysis-content">
|
||||||
<text class="analysis-text">{{ analysisResult }}</text>
|
<text class="analysis-text">{{ analysisResult }}</text>
|
||||||
|
|||||||
@ -306,7 +306,7 @@
|
|||||||
<view v-if="analysisResult" class="analysis-result">
|
<view v-if="analysisResult" class="analysis-result">
|
||||||
<view class="analysis-header">
|
<view class="analysis-header">
|
||||||
<u-icon name="file-text" size="20" color="#409EFF"></u-icon>
|
<u-icon name="file-text" size="20" color="#409EFF"></u-icon>
|
||||||
<text class="analysis-title">AI分析报告</text>
|
<text class="analysis-title">AI数字分析</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="analysis-content">
|
<view class="analysis-content">
|
||||||
<text class="analysis-text">{{ analysisResult }}</text>
|
<text class="analysis-text">{{ analysisResult }}</text>
|
||||||
|
|||||||
@ -284,29 +284,12 @@
|
|||||||
<text class="success-time">{{ formatTime(new Date()) }}</text>
|
<text class="success-time">{{ formatTime(new Date()) }}</text>
|
||||||
<text class="success-tip">您已成功提交问卷</text>
|
<text class="success-tip">您已成功提交问卷</text>
|
||||||
|
|
||||||
<!-- 添加AI分析按钮 -->
|
<!-- 查看AI分析报告按钮 -->
|
||||||
<button v-if="!analysisResult && !analyzing" @click="analyzeWithAI" class="ai-analyze-btn">
|
<button @click="viewAIAnalysisReport" class="ai-analyze-btn">
|
||||||
<u-icon name="file-text" size="18" color="#fff" style="margin-right: 8rpx;"></u-icon>
|
<u-icon name="file-text" size="18" color="#fff" style="margin-right: 8rpx;"></u-icon>
|
||||||
AI智能分析
|
查看AI分析报告
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- 分析中状态 -->
|
|
||||||
<view v-if="analyzing" class="analyzing-container">
|
|
||||||
<u-loading-icon mode="spinner" size="24" color="#409EFF"></u-loading-icon>
|
|
||||||
<text class="analyzing-text">AI分析中,请稍候...</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 分析结果 -->
|
|
||||||
<view v-if="analysisResult" class="analysis-result">
|
|
||||||
<view class="analysis-header">
|
|
||||||
<u-icon name="file-text" size="20" color="#409EFF"></u-icon>
|
|
||||||
<text class="analysis-title">AI分析报告</text>
|
|
||||||
</view>
|
|
||||||
<view class="analysis-content">
|
|
||||||
<text class="analysis-text">{{ analysisResult }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<button @click="goBack" class="back-btn">返回</button>
|
<button @click="goBack" class="back-btn">返回</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -327,6 +310,13 @@
|
|||||||
<u-icon name="info-circle" size="80" color="#409EFF"></u-icon>
|
<u-icon name="info-circle" size="80" color="#409EFF"></u-icon>
|
||||||
<text class="already-filled-title">已填写</text>
|
<text class="already-filled-title">已填写</text>
|
||||||
<text class="already-filled-subtitle">您已经填写过此问卷</text>
|
<text class="already-filled-subtitle">您已经填写过此问卷</text>
|
||||||
|
|
||||||
|
<!-- 查看AI分析报告按钮 -->
|
||||||
|
<button @click="viewAIAnalysisReport" class="ai-analyze-btn">
|
||||||
|
<u-icon name="file-text" size="18" color="#fff" style="margin-right: 8rpx;"></u-icon>
|
||||||
|
查看AI分析报告
|
||||||
|
</button>
|
||||||
|
|
||||||
<button @click="goBack" class="back-btn">返回</button>
|
<button @click="goBack" class="back-btn">返回</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -351,8 +341,7 @@ import {
|
|||||||
questionnaireCheckPermissionApi,
|
questionnaireCheckPermissionApi,
|
||||||
questionnaireQuestionFindPageApi,
|
questionnaireQuestionFindPageApi,
|
||||||
questionnaireAnswerSaveApi,
|
questionnaireAnswerSaveApi,
|
||||||
questionnaireAnswerFindByUserApi,
|
questionnaireAnswerFindByUserApi
|
||||||
questionnaireAnalyzeWithAIApi
|
|
||||||
} from '@/api/base/wjApi';
|
} from '@/api/base/wjApi';
|
||||||
import { useUserStore } from '@/store/modules/user';
|
import { useUserStore } from '@/store/modules/user';
|
||||||
import { attachmentUpload } from '@/api/system/upload';
|
import { attachmentUpload } from '@/api/system/upload';
|
||||||
@ -363,6 +352,7 @@ const userStore = useUserStore();
|
|||||||
// 页面参数
|
// 页面参数
|
||||||
const options = ref<any>({});
|
const options = ref<any>({});
|
||||||
const questionnaireId = ref('');
|
const questionnaireId = ref('');
|
||||||
|
const xxtsId = ref<string>(""); // 消息推送表ID(用于更新待办状态)
|
||||||
const openId = ref<string>(""); // 微信 openId
|
const openId = ref<string>(""); // 微信 openId
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const submitting = ref(false); // 提交中状态
|
const submitting = ref(false); // 提交中状态
|
||||||
@ -392,9 +382,8 @@ const fileUploadData = reactive<Record<string, {
|
|||||||
// 压缩配置
|
// 压缩配置
|
||||||
const compressConfig = ref(COMPRESS_PRESETS.high);
|
const compressConfig = ref(COMPRESS_PRESETS.high);
|
||||||
|
|
||||||
// AI分析相关
|
// 提交批次ID,用于查看AI分析报告
|
||||||
const analyzing = ref(false);
|
const submitId = ref<string>('');
|
||||||
const analysisResult = ref('');
|
|
||||||
|
|
||||||
// 签名组件相关
|
// 签名组件相关
|
||||||
const signCompRef = ref<any>(null);
|
const signCompRef = ref<any>(null);
|
||||||
@ -406,6 +395,7 @@ const currentSignatureQuestionId = ref<string>(""); // 当前正在签名的题
|
|||||||
onLoad(async (params) => {
|
onLoad(async (params) => {
|
||||||
options.value = params;
|
options.value = params;
|
||||||
openId.value = params?.openId || '';
|
openId.value = params?.openId || '';
|
||||||
|
xxtsId.value = params?.id || ''; // 获取 xxts 表的 id
|
||||||
|
|
||||||
// 如果有 openId,先进行认证
|
// 如果有 openId,先进行认证
|
||||||
if (openId.value) {
|
if (openId.value) {
|
||||||
@ -1062,10 +1052,20 @@ const doSubmitQuestionnaire = async () => {
|
|||||||
submitParams.signatureImage = sign_file.value;
|
submitParams.signatureImage = sign_file.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 xxtsId,添加到提交参数中(用于更新待办状态)
|
||||||
|
if (xxtsId.value) {
|
||||||
|
submitParams.xxtsId = xxtsId.value;
|
||||||
|
}
|
||||||
|
|
||||||
// 提交答案
|
// 提交答案
|
||||||
const result = await questionnaireAnswerSaveApi(submitParams);
|
const result = await questionnaireAnswerSaveApi(submitParams);
|
||||||
|
|
||||||
if (result && result.resultCode === 1) {
|
if (result && result.resultCode === 1) {
|
||||||
|
// 保存 submitId(从返回结果中获取)
|
||||||
|
const resultData = result.result || result.data || {};
|
||||||
|
if (resultData.submitId) {
|
||||||
|
submitId.value = resultData.submitId;
|
||||||
|
}
|
||||||
currentStep.value = 'success';
|
currentStep.value = 'success';
|
||||||
} else {
|
} else {
|
||||||
throw new Error(result?.message || '提交失败');
|
throw new Error(result?.message || '提交失败');
|
||||||
@ -1094,69 +1094,14 @@ const formatTime = (time: string | Date) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// AI分析函数
|
// 查看AI分析报告
|
||||||
const analyzeWithAI = async () => {
|
const viewAIAnalysisReport = () => {
|
||||||
try {
|
// 获取当前用户ID(参考 wjDetail.vue)
|
||||||
analyzing.value = true;
|
const currentUserId = userStore.userdata?.id || userStore.userdata?.userId || '';
|
||||||
analysisResult.value = '';
|
// 跳转到 wjEvaluatedl.vue,传递 questionnaireId 和 userId(参考 wjDetail.vue)
|
||||||
|
uni.navigateTo({
|
||||||
// 构造发送给AI的问卷数据,包含所有分页的题目
|
url: `/pages/view/routine/wj/wjEvaluatedl?questionnaireId=${questionnaireId.value}&userId=${currentUserId}`
|
||||||
const allQuestions: any[] = [];
|
});
|
||||||
pageList.value.forEach(page => {
|
|
||||||
allQuestions.push(...page.questions);
|
|
||||||
});
|
|
||||||
|
|
||||||
const questionnaireData = {
|
|
||||||
questionnaireId: questionnaireId.value,
|
|
||||||
title: questionnaireInfo.value?.title,
|
|
||||||
description: questionnaireInfo.value?.description,
|
|
||||||
questions: allQuestions.map((q: any) => {
|
|
||||||
let answerValue = answers[q.id]?.value;
|
|
||||||
|
|
||||||
// 处理不同类型的答案格式
|
|
||||||
if (q.questionType === 'CHECKBOX' && Array.isArray(answerValue)) {
|
|
||||||
answerValue = answerValue.join(',');
|
|
||||||
} else if (q.questionType === 'FILE') {
|
|
||||||
const uploadData = fileUploadData[q.id];
|
|
||||||
const imageUrls = (uploadData?.imageList || []).filter(img => img.url).map(img => img.url);
|
|
||||||
const fileUrls = (uploadData?.fileList || []).filter(file => file.url).map(file => file.url);
|
|
||||||
answerValue = [...imageUrls, ...fileUrls].join(',');
|
|
||||||
} else if (q.questionType === 'VIDEO') {
|
|
||||||
const uploadData = fileUploadData[q.id];
|
|
||||||
const videoUrls = (uploadData?.videoList || []).filter(video => video.url).map(video => video.url);
|
|
||||||
answerValue = videoUrls.join(',');
|
|
||||||
} else if (q.questionType === 'SIGNATURE') {
|
|
||||||
answerValue = answerValue ? '[已签名]' : '[未签名]';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取分页名称和排序
|
|
||||||
const pageName = q.pageName || '第一部分';
|
|
||||||
const pageSortOrder = q.pageSortOrder !== undefined ? q.pageSortOrder : 0;
|
|
||||||
|
|
||||||
return {
|
|
||||||
content: q.questionContent,
|
|
||||||
type: q.questionType,
|
|
||||||
answer: answerValue || '[未填写]',
|
|
||||||
pageName: pageName,
|
|
||||||
pageSortOrder: pageSortOrder
|
|
||||||
};
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
// 调用后端AI分析接口
|
|
||||||
const response = await questionnaireAnalyzeWithAIApi(questionnaireData);
|
|
||||||
|
|
||||||
if (response && response.resultCode === 1) {
|
|
||||||
analysisResult.value = response.result || response.data || '分析完成';
|
|
||||||
} else {
|
|
||||||
throw new Error(response?.message || 'AI分析失败');
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('AI分析失败:', error);
|
|
||||||
uni.showToast({ title: error.message || 'AI分析失败,请稍后重试', icon: 'none', duration: 2000 });
|
|
||||||
} finally {
|
|
||||||
analyzing.value = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -1687,57 +1632,6 @@ const analyzeWithAI = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.analyzing-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
padding: 30rpx;
|
|
||||||
background: #f5f7fa;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
|
|
||||||
.analyzing-text {
|
|
||||||
margin-left: 20rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #409EFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.analysis-result {
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
padding: 30rpx;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
text-align: left;
|
|
||||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
.analysis-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
padding-bottom: 16rpx;
|
|
||||||
border-bottom: 2rpx solid #eee;
|
|
||||||
|
|
||||||
.analysis-title {
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
margin-left: 12rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.analysis-content {
|
|
||||||
.analysis-text {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #666;
|
|
||||||
line-height: 1.8;
|
|
||||||
word-break: break-word;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-btn {
|
.back-btn {
|
||||||
width: 300rpx;
|
width: 300rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
|
|||||||
@ -168,7 +168,7 @@
|
|||||||
<view class="bottom-button-container">
|
<view class="bottom-button-container">
|
||||||
<button class="evaluate-btn" @click="handleEvaluate">
|
<button class="evaluate-btn" @click="handleEvaluate">
|
||||||
<u-icon name="file-text" size="18" color="#fff" style="margin-right: 8rpx;"></u-icon>
|
<u-icon name="file-text" size="18" color="#fff" style="margin-right: 8rpx;"></u-icon>
|
||||||
<text>问卷评估</text>
|
<text>AI数字问卷</text>
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@ -461,6 +461,33 @@ const convertHTMLToUrl = (html: string): string => {
|
|||||||
// 在 HTML 中添加脚本,自动向父窗口发送高度信息
|
// 在 HTML 中添加脚本,自动向父窗口发送高度信息
|
||||||
let processedHtml = html;
|
let processedHtml = html;
|
||||||
|
|
||||||
|
// 替换 CDN 地址为国内可用的 CDN
|
||||||
|
processedHtml = processedHtml.replace(
|
||||||
|
/https:\/\/cdn\.jsdelivr\.net\/npm\/chart\.js/g,
|
||||||
|
'https://cdn.bootcdn.net/ajax/libs/Chart.js/3.9.1/chart.min.js'
|
||||||
|
);
|
||||||
|
|
||||||
|
// 添加 CDN 加载失败的备用方案(使用字符编码避免 Vue 解析错误)
|
||||||
|
const headEndTag = [60, 47, 104, 101, 97, 100, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
|
if (processedHtml.includes(headEndTag)) {
|
||||||
|
// 构建脚本标签
|
||||||
|
const scriptOpen = [60, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
|
const scriptClose = [60, 47, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
|
|
||||||
|
// 第一段:错误标志
|
||||||
|
const script1 = scriptOpen + 'window.chartLoadError=false;' + scriptClose;
|
||||||
|
|
||||||
|
// 第二段:加载主 CDN 并设置错误标志
|
||||||
|
const script2 = '<script src="https://cdn.bootcdn.net/ajax/libs/Chart.js/3.9.1/chart.min.js" onerror="window.chartLoadError=true;"><' + '/script>';
|
||||||
|
|
||||||
|
// 第三段:备用加载逻辑
|
||||||
|
const script3Content = 'setTimeout(function(){if(window.chartLoadError||typeof Chart==="undefined"){var s=document.createElement("script");s.src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js";s.onerror=function(){var s2=document.createElement("script");s2.src="https://unpkg.com/chart.js@3.9.1/dist/chart.min.js";document.head.appendChild(s2);};document.head.appendChild(s);}},2000);';
|
||||||
|
const script3 = scriptOpen + script3Content + scriptClose;
|
||||||
|
|
||||||
|
const fallbackScript = script1 + script2 + script3;
|
||||||
|
processedHtml = processedHtml.replace(headEndTag, fallbackScript + headEndTag);
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否已经包含自动调整高度的脚本
|
// 检查是否已经包含自动调整高度的脚本
|
||||||
if (!processedHtml.includes('postMessage')) {
|
if (!processedHtml.includes('postMessage')) {
|
||||||
// 构建脚本内容(使用字符编码避免 Vue 编译器解析)
|
// 构建脚本内容(使用字符编码避免 Vue 编译器解析)
|
||||||
@ -468,7 +495,8 @@ const convertHTMLToUrl = (html: string): string => {
|
|||||||
const scriptClose = [60, 47, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
const scriptClose = [60, 47, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
// 优化脚本:只在初始加载和图表渲染完成后发送一次高度,避免循环更新
|
// 优化脚本:只在初始加载和图表渲染完成后发送一次高度,避免循环更新
|
||||||
// 完全禁用 resize 事件监听,防止循环
|
// 完全禁用 resize 事件监听,防止循环
|
||||||
const scriptContent = '(function(){let hasSent=false;let sentHeight=0;function sendHeightOnce(){try{if(hasSent)return;const h=Math.max(document.body.scrollHeight||0,document.documentElement.scrollHeight||0);if(h>100&&h!==sentHeight&&window.parent&&window.parent!==window){sentHeight=h;hasSent=true;window.parent.postMessage({type:"iframe-height",height:h},"*");}}catch(e){}}function sendWithDelay(){setTimeout(sendHeightOnce,800);}if(document.readyState==="complete"){sendWithDelay();}else{window.addEventListener("load",sendWithDelay);}if(typeof Chart!=="undefined"){const o=Chart;Chart=function(...a){const c=new o(...a);sendWithDelay();return c;};}})();';
|
// 延长等待时间到 1500ms,添加延迟检测 Chart 对象
|
||||||
|
const scriptContent = '(function(){let hasSent=false;let sentHeight=0;function sendHeightOnce(){try{if(hasSent)return;const h=Math.max(document.body.scrollHeight||0,document.documentElement.scrollHeight||0);if(h>100&&h!==sentHeight&&window.parent&&window.parent!==window){sentHeight=h;hasSent=true;window.parent.postMessage({type:"iframe-height",height:h},"*");}}catch(e){}}function sendWithDelay(){setTimeout(sendHeightOnce,1500);}if(document.readyState==="complete"){sendWithDelay();}else{window.addEventListener("load",sendWithDelay);}if(typeof Chart!=="undefined"){const o=Chart;Chart=function(...a){const c=new o(...a);sendWithDelay();return c;};}else{setTimeout(function(){if(typeof Chart!=="undefined"){const o=Chart;Chart=function(...a){const c=new o(...a);sendWithDelay();return c;};}},3000);}})();';
|
||||||
const autoResizeScript = scriptOpen + scriptContent + scriptClose;
|
const autoResizeScript = scriptOpen + scriptContent + scriptClose;
|
||||||
|
|
||||||
// 构建 body 结束标签
|
// 构建 body 结束标签
|
||||||
|
|||||||
@ -500,6 +500,33 @@ const convertHTMLToUrl = (html: string): string => {
|
|||||||
// 在 HTML 中添加脚本,自动向父窗口发送高度信息
|
// 在 HTML 中添加脚本,自动向父窗口发送高度信息
|
||||||
let processedHtml = html;
|
let processedHtml = html;
|
||||||
|
|
||||||
|
// 替换 CDN 地址为国内可用的 CDN
|
||||||
|
processedHtml = processedHtml.replace(
|
||||||
|
/https:\/\/cdn\.jsdelivr\.net\/npm\/chart\.js/g,
|
||||||
|
'https://cdn.bootcdn.net/ajax/libs/Chart.js/3.9.1/chart.min.js'
|
||||||
|
);
|
||||||
|
|
||||||
|
// 添加 CDN 加载失败的备用方案(使用字符编码避免 Vue 解析错误)
|
||||||
|
const headEndTag = [60, 47, 104, 101, 97, 100, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
|
if (processedHtml.includes(headEndTag)) {
|
||||||
|
// 构建脚本标签
|
||||||
|
const scriptOpen = [60, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
|
const scriptClose = [60, 47, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
|
|
||||||
|
// 第一段:错误标志
|
||||||
|
const script1 = scriptOpen + 'window.chartLoadError=false;' + scriptClose;
|
||||||
|
|
||||||
|
// 第二段:加载主 CDN 并设置错误标志
|
||||||
|
const script2 = '<script src="https://cdn.bootcdn.net/ajax/libs/Chart.js/3.9.1/chart.min.js" onerror="window.chartLoadError=true;"><' + '/script>';
|
||||||
|
|
||||||
|
// 第三段:备用加载逻辑
|
||||||
|
const script3Content = 'setTimeout(function(){if(window.chartLoadError||typeof Chart==="undefined"){var s=document.createElement("script");s.src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js";s.onerror=function(){var s2=document.createElement("script");s2.src="https://unpkg.com/chart.js@3.9.1/dist/chart.min.js";document.head.appendChild(s2);};document.head.appendChild(s);}},2000);';
|
||||||
|
const script3 = scriptOpen + script3Content + scriptClose;
|
||||||
|
|
||||||
|
const fallbackScript = script1 + script2 + script3;
|
||||||
|
processedHtml = processedHtml.replace(headEndTag, fallbackScript + headEndTag);
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否已经包含自动调整高度的脚本
|
// 检查是否已经包含自动调整高度的脚本
|
||||||
if (!processedHtml.includes('postMessage')) {
|
if (!processedHtml.includes('postMessage')) {
|
||||||
// 构建脚本内容(使用字符编码避免 Vue 编译器解析)
|
// 构建脚本内容(使用字符编码避免 Vue 编译器解析)
|
||||||
@ -507,7 +534,7 @@ const convertHTMLToUrl = (html: string): string => {
|
|||||||
const scriptClose = [60, 47, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
const scriptClose = [60, 47, 115, 99, 114, 105, 112, 116, 62].map(c => String.fromCharCode(c)).join('');
|
||||||
// 优化脚本:只在初始加载和图表渲染完成后发送一次高度,避免循环更新
|
// 优化脚本:只在初始加载和图表渲染完成后发送一次高度,避免循环更新
|
||||||
// 完全禁用 resize 事件监听,防止循环
|
// 完全禁用 resize 事件监听,防止循环
|
||||||
const scriptContent = '(function(){let hasSent=false;let sentHeight=0;function sendHeightOnce(){try{if(hasSent)return;const h=Math.max(document.body.scrollHeight||0,document.documentElement.scrollHeight||0);if(h>100&&h!==sentHeight&&window.parent&&window.parent!==window){sentHeight=h;hasSent=true;window.parent.postMessage({type:"iframe-height",height:h},"*");}}catch(e){}}function sendWithDelay(){setTimeout(sendHeightOnce,800);}if(document.readyState==="complete"){sendWithDelay();}else{window.addEventListener("load",sendWithDelay);}if(typeof Chart!=="undefined"){const o=Chart;Chart=function(...a){const c=new o(...a);sendWithDelay();return c;};}})();';
|
const scriptContent = '(function(){let hasSent=false;let sentHeight=0;function sendHeightOnce(){try{if(hasSent)return;const h=Math.max(document.body.scrollHeight||0,document.documentElement.scrollHeight||0);if(h>100&&h!==sentHeight&&window.parent&&window.parent!==window){sentHeight=h;hasSent=true;window.parent.postMessage({type:"iframe-height",height:h},"*");}}catch(e){}}function sendWithDelay(){setTimeout(sendHeightOnce,1500);}if(document.readyState==="complete"){sendWithDelay();}else{window.addEventListener("load",sendWithDelay);}if(typeof Chart!=="undefined"){const o=Chart;Chart=function(...a){const c=new o(...a);sendWithDelay();return c;};}else{setTimeout(function(){if(typeof Chart!=="undefined"){const o=Chart;Chart=function(...a){const c=new o(...a);sendWithDelay();return c;};}},3000);}})();';
|
||||||
const autoResizeScript = scriptOpen + scriptContent + scriptClose;
|
const autoResizeScript = scriptOpen + scriptContent + scriptClose;
|
||||||
|
|
||||||
// 构建 body 结束标签
|
// 构建 body 结束标签
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user