<template>
|
<view class="container">
|
<view class="content">
|
<!-- 动态表单区域 -->
|
<view id="divid" class="form-container">
|
<!-- 动态生成的表单内容 -->
|
<view class="uni-form" v-if="formData.length > 0">
|
<block v-for="(item, index) in formData" :key="index">
|
<!-- 文本输入框 -->
|
<view class="form-item" v-if="(item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '3'">
|
<text class="form-label">{{ item[1] }}</text>
|
<view class="scan-input-container">
|
<input
|
:id="item[0]"
|
:disabled="item[3] === '1'"
|
:readonly="item[3] === '1'"
|
type="text"
|
class="form-input"
|
:class="{'readonly': item[3] === '1'}"
|
v-model="formValues[item[0]]"
|
:placeholder="'请输入'+item[1]"
|
@keyup="(e) => handleKeyUp(e, item[7], item[8], item[0], item[9], item[10])"
|
@confirm="() => enterSearch({keyCode: 13}, item[7], item[8], item[0], item[9], item[10])"
|
:focus="autoFocusId === item[0]"
|
/>
|
<!-- 添加扫码图标,根据item[13]决定是否显示 -->
|
<view
|
v-if="item[3] === '0'"
|
class="scan-icon-btn"
|
@tap="() => scanQRCode(item[0])"
|
>
|
<uni-icons type="scan" size="20" color="#5677fc"></uni-icons>
|
</view>
|
</view>
|
</view>
|
<!-- 下拉选择框 -->
|
<view class="form-item" v-else-if="(item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '2'">
|
<text class="form-label">{{ item[1] }}</text>
|
<view class="select-wrapper">
|
<input
|
type="text"
|
:id="'selectList-'+item[0]+'-'+item[1]"
|
class="form-input select-input"
|
readonly
|
placeholder="请点击选择"
|
@tap="() => openList(item[0], item[1])"
|
/>
|
<view class="select-icon">
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
</view>
|
</view>
|
</view>
|
|
|
<!-- 扫描选择框 -->
|
<view class="form-item" v-else-if="(item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '4'">
|
<text class="form-label">{{ item[1] }}</text>
|
<!-- 移除这个隐藏的input,不再需要 -->
|
<!-- <input :id="item[0]" v-model="formValues[item[0]]" type="hidden"> -->
|
<view class="scan-select-container">
|
<input
|
type="text"
|
class="form-input scan-input"
|
:id="item[0]"
|
v-model="formValues[item[0]]"
|
@keyup="(e) => handleScanKeyUp(e, item[8], item[0], item[10], item[7])"
|
@confirm="() => enterScanSelect({keyCode: 13}, item[8], item[0], item[10], item[7])"
|
:placeholder="'请选择/扫描'+item[1]"
|
/>
|
<picker
|
:id="'select-'+item[0]"
|
:range="selectOptions[item[0]] || []"
|
@change="(e) => getCheckItem(item[8], item[0], item[10], item[7], e)"
|
>
|
<view class="select-btn">
|
<uni-icons type="down" size="18" color="#fff"></uni-icons>
|
</view>
|
</picker>
|
</view>
|
</view>
|
|
<!-- 照片按钮 -->
|
<view class="form-item button-item" v-else-if="(item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '9'">
|
<view class="action-button photo-btn" @tap="() => photoButton(item)">
|
<uni-icons type="camera" size="18" color="#fff" style="margin-right: 5px;"></uni-icons>
|
<text>{{ item[1] }}</text>
|
</view>
|
</view>
|
|
<!-- 列表按钮 -->
|
<view class="form-item button-item" v-else-if="(item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '11'">
|
<view class="action-button list-btn" @tap="() => listButton(item)">
|
<uni-icons type="list" size="18" color="#fff" style="margin-right: 5px;"></uni-icons>
|
<text>{{ item[1] }}</text>
|
</view>
|
</view>
|
|
<!-- 打印按钮 -->
|
<view class="form-item button-item" v-else-if="(item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '13'">
|
<view class="action-button print-btn" @tap="() => clickPrintBtn(item)">
|
<uni-icons type="paperplane" size="18" color="#fff" style="margin-right: 5px;"></uni-icons>
|
<text>{{ item[1] }}</text>
|
</view>
|
</view>
|
|
<!-- 开关 -->
|
<view class="form-item switch-item" v-else-if="(item[2] === 'VARCHAR2' || item[2] === 'VARCHAR')">
|
<text class="form-label">{{ item[1] }}</text>
|
<input :id="item[0]" v-model="formValues[item[0]]" type="hidden">
|
<switch
|
:id="item[0]+'-switch'"
|
:data-href="item[0]"
|
@change="(e) => switchChange(e, item[0])"
|
color="#5677fc"
|
class="custom-switch"
|
/>
|
</view>
|
|
<!-- 文本域 -->
|
<view class="form-item" v-else-if="item[2] === 'MEMO'">
|
<text class="form-label">{{ item[1] }}</text>
|
<textarea
|
:id="item[0]"
|
v-model="formValues[item[0]]"
|
class="form-textarea"
|
:disabled="item[3] === '1'"
|
:readonly="item[3] === '1'"
|
:class="{'readonly': item[3] === '1'}"
|
:style="{'height': item[14]+'px'}"
|
></textarea>
|
</view>
|
|
<!-- 按钮 -->
|
<view class="form-item button-item" v-else-if="item[2] === 'BUTTON'">
|
<view class="action-button normal-btn" @tap="() => clickButton(item)">
|
<text>{{ item[1] }}</text>
|
</view>
|
</view>
|
|
<!-- 多选编辑 -->
|
<view class="form-item button-item" v-else-if="item[2] === 'EDIT' && item[4] === '11'">
|
<view class="action-button list-btn" @tap="() => listButton(item)">
|
<uni-icons type="list" size="18" color="#fff" style="margin-right: 5px;"></uni-icons>
|
<text>{{ item[1] }}</text>
|
</view>
|
</view>
|
|
<!-- 多选扫描 -->
|
<view class="form-item" v-else-if="item[2] === 'EDIT' && item[4] === '4'">
|
<text class="form-label">{{ item[1] }}</text>
|
<input :id="item[0]" v-model="formValues[item[0]]" type="hidden">
|
<view class="scan-select-container">
|
<input
|
type="text"
|
class="form-input scan-input"
|
:id="'scanSelect-mul'+item[0]"
|
v-model="scanValues['mul'+item[0]]"
|
@keyup="(e) => enterScanSelect(e, item[8], item[0], item[10], item[7])"
|
:placeholder="'请选择/扫描'+item[1]"
|
/>
|
<picker
|
mode="multiSelector"
|
:id="'select-mul'+item[0]"
|
:range="selectOptions['mul'+item[0]] || []"
|
@change="(e) => getCheckMultiItem(item[8], item[0], item[10], item[7], e)"
|
>
|
<view class="select-btn">
|
<uni-icons type="down" size="18" color="#fff"></uni-icons>
|
</view>
|
</picker>
|
</view>
|
</view>
|
</block>
|
</view>
|
</view>
|
|
|
<!-- 表格区域 -->
|
<view id="tableDiv" class="table-container" v-if="showTable">
|
<view class="table-header">
|
<text class="table-title">查询结果</text>
|
</view>
|
<scroll-view scroll-y class="table-scroll">
|
<view class="table">
|
<!-- 表头 -->
|
<view class="thead">
|
<view class="tr">
|
<view
|
class="th"
|
v-for="(col, colIndex) in tableColumns"
|
:key="colIndex"
|
:style="getColumnStyle(col)"
|
>
|
{{ getColumnName(col) }}
|
</view>
|
</view>
|
|
<!-- 搜索行 -->
|
<view class="tr search-row">
|
<view
|
class="td search-cell"
|
v-for="(col, colIndex) in tableColumns"
|
:key="colIndex"
|
:style="getColumnStyle(col)"
|
>
|
<input
|
type="text"
|
class="search-input"
|
v-model="searchValues[colIndex]"
|
:placeholder="'搜索...'"
|
@input="filterTableData"
|
/>
|
</view>
|
</view>
|
</view>
|
|
<!-- 表格内容 -->
|
<view class="tbody">
|
<view
|
class="tr"
|
v-for="(row, rowIndex) in filteredTableData"
|
:key="rowIndex"
|
:class="{'tr-alter': rowIndex % 2 === 1}"
|
@tap="() => handleRowTap(row)"
|
>
|
<view
|
class="td"
|
v-for="(col, colIndex) in tableColumns"
|
:key="colIndex"
|
:style="getColumnStyle(col)"
|
@longpress="() => showFullContent(row[colIndex])"
|
>
|
<rich-text :nodes="formatCellContent(row[colIndex])"></rich-text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</scroll-view>
|
</view>
|
|
|
</view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
data() {
|
return {
|
title: 'MES移动终端',
|
username: '',
|
formData: [],
|
formValues: {},
|
scanValues: {},
|
selectOptions: {},
|
tableColumns: [],
|
tableData: [],
|
searchValues: {}, // 存储每列的搜索值
|
filteredTableData: [], // 过滤后的表格数据
|
showTable: false,
|
isCommitted: false, // 请求是否已提交标识
|
bluetoothSocket: null,
|
device: null,
|
autoFocusId: '' // 用于自动聚焦的ID
|
};
|
},
|
onReady(){
|
this.username = this.setUsrCode();
|
this.title = uni.getStorageSync("functionName") || 'MES移动终端';
|
uni.setNavigationBarTitle({
|
title: this.title
|
});
|
},
|
onLoad() {
|
this.getData();
|
// 初始化蓝牙打印机
|
if (this.$store.state.serverInfo.Bluetooth === 'true') {
|
this.initBluetooth();
|
}
|
},
|
methods: {
|
// 返回上一页
|
goBack() {
|
uni.navigateBack();
|
},
|
// 获取用户代码
|
setUsrCode() {
|
return uni.getStorageSync("code") || '';
|
},
|
|
// 获取表单数据
|
getData() {
|
uni.showLoading({
|
title: '加载中...'
|
});
|
|
uni.request({
|
url: this.$store.state.serverInfo.serverAPI + '/modules/getRfSetup',
|
data: {
|
functionName: uni.getStorageSync("functionName")
|
},
|
method: 'POST',
|
timeout: 60000,
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.data.status === 0 && res.data.data && res.data.data.setupData) {
|
let fData = res.data.data.setupData;
|
console.log("原始数据:", fData);
|
|
// 处理回车符号
|
if (typeof fData === 'string') {
|
while (fData.indexOf('\\r\\n') !== -1) {
|
fData = fData.replace("\\r\\n", " ");
|
}
|
|
// 解析字符串为表单数据数组
|
try {
|
// 按方括号分割字段
|
const fieldsStr = fData.split('[');
|
const formFields = [];
|
|
// 从索引1开始,因为第一个元素是空的或前缀
|
for (let i = 1; i < fieldsStr.length; i++) {
|
// 去掉结尾的方括号并按#分割属性
|
const fieldStr = fieldsStr[i].replace(']', '');
|
const fieldProps = fieldStr.split('#');
|
formFields.push(fieldProps);
|
}
|
|
this.formData = formFields;
|
console.log("解析后的表单数据:", this.formData);
|
|
// 初始化表单值
|
this.formData.forEach(item => {
|
if (item[12]) {
|
this.$set(this.formValues, item[0], item[12]);
|
} else {
|
this.$set(this.formValues, item[0], '');
|
}
|
|
// 初始化扫描值
|
if (item[4] === '4') {
|
this.$set(this.scanValues, item[0], '');
|
}
|
});
|
|
// 聚焦第一个输入框
|
this.$nextTick(() => {
|
// 找到第一个输入框并聚焦
|
const firstInput = this.formData.find(item => item[4] === '3' || item[4] === '4');
|
if (firstInput) {
|
setTimeout(() => {
|
this.focusInput(firstInput[0]);
|
}, 300);
|
}
|
});
|
|
// 初始化下拉框数据
|
this.getSelectData();
|
// 执行SQL语句的默认值
|
this.getExcuteSql();
|
} catch (error) {
|
console.error("解析表单数据出错:", error);
|
uni.showToast({
|
title: '解析表单数据出错',
|
content: "解析表单数据出错: " + err.errMsg,
|
icon: 'none'
|
});
|
}
|
} else {
|
console.error("setupData不是字符串类型");
|
uni.showToast({
|
title: '数据格式错误',
|
icon: 'none'
|
});
|
}
|
} else {
|
uni.showToast({
|
title: res.data.message || '获取数据失败',
|
content: res.data.message || '获取数据失败',
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
console.error("请求失败:", err);
|
uni.showToast({
|
title: "服务器断开",
|
icon: 'none'
|
});
|
},
|
complete: () => {
|
uni.hideLoading();
|
}
|
});
|
},
|
// 扫描二维码
|
scanQRCode(fieldId) {
|
// #ifdef APP-PLUS
|
// 调用原生扫码功能
|
uni.scanCode({
|
scanType: ['qrCode', 'barCode'], // 同时支持二维码和条形码
|
success: (res) => {
|
console.log('扫码成功:', res);
|
// 将扫码结果设置到对应的输入框
|
this.formValues[fieldId] = res.result;
|
|
// 查找当前字段的配置
|
const fieldConfig = this.formData.find(item => item[0] === fieldId);
|
if (fieldConfig) {
|
// 如果有配置的回车事件,则触发
|
if (fieldConfig[7] !== 'N') {
|
this.doProByFile8(fieldConfig[8], fieldId);
|
}
|
|
// 如果有配置的跳转字段,则聚焦到下一个字段
|
if (fieldConfig[10] !== '') {
|
this.formValues[fieldConfig[10]] = '';
|
this.focusInput(fieldConfig[10]);
|
}
|
}
|
},
|
fail: (err) => {
|
console.error('扫码失败:', err);
|
uni.showToast({
|
title: '扫码失败',
|
icon: 'none'
|
});
|
}
|
});
|
// #endif
|
|
// #ifdef H5
|
uni.showToast({
|
title: 'H5环境不支持扫码功能',
|
icon: 'none'
|
});
|
// #endif
|
},
|
formatCellContent(content) {
|
if (content === undefined || content === null) {
|
return '';
|
}
|
|
// 将字符串转换为字符串
|
const strContent = String(content);
|
|
// 检查是否包含<br>标签
|
if (strContent.includes('<br>')) {
|
return strContent;
|
} else {
|
return strContent;
|
}
|
},
|
|
// 显示完整内容
|
showFullContent(content) {
|
if (!content) return;
|
|
uni.showModal({
|
title: '完整内容',
|
content: String(content).replace(/<br>/g, '\n'),
|
showCancel: false,
|
confirmText: '关闭'
|
});
|
},
|
// 聚焦输入框
|
// focusInput(id) {
|
// setTimeout(() => {
|
// // 使用uni-app的原生API
|
// uni.createSelectorQuery()
|
// .select('#' + id)
|
// .boundingClientRect(data => {
|
// if (data) {
|
// // 元素存在,尝试聚焦
|
// uni.createSelectorQuery()
|
// .select('#' + id)
|
// .fields({
|
// context: true
|
// }, res => {
|
// if (res && res.context) {
|
// res.context.focus();
|
// } else {
|
// console.log('无法获取元素上下文:', id);
|
// }
|
// })
|
// .exec();
|
// } else {
|
// console.log('未找到元素:', id);
|
// }
|
// })
|
// .exec();
|
// }, 500); // 增加延迟时间
|
// },
|
// 聚焦输入框 - 简化版
|
focusInput(id) {
|
console.log('尝试聚焦元素:', id);
|
|
// 设置一个临时变量,用于自动聚焦
|
this.autoFocusId = id;
|
|
// 使用nextTick确保DOM已更新
|
this.$nextTick(() => {
|
setTimeout(() => {
|
// 重置自动聚焦ID,触发视图更新
|
this.autoFocusId = '';
|
|
// 再次设置,触发自动聚焦
|
setTimeout(() => {
|
this.autoFocusId = id;
|
}, 100);
|
}, 200);
|
});
|
},
|
// 处理键盘按键事件
|
handleKeyUp(e, file7, str, fileId, file9, file10) {
|
// 只有在按下回车键(13)或Tab键(9)时才触发
|
if (e.keyCode === 13 || e.keyCode === 9) {
|
// 添加延迟,确保输入完成
|
setTimeout(() => {
|
this.enterSearch(e, file7, str, fileId, file9, file10);
|
}, 100);
|
}
|
},
|
|
// 处理扫描输入键盘事件
|
handleScanKeyUp(e, file8, fileId, file10, file7) {
|
// 只有在按下回车键(13)或Tab键(9)时才触发
|
if (e.keyCode === 13 || e.keyCode === 9) {
|
// 添加延迟,确保输入完成
|
setTimeout(() => {
|
this.enterScanSelect(e, file8, fileId, file10, file7);
|
}, 100);
|
}
|
},
|
// 回车搜索
|
enterSearch(e, file7, str, fileId, file9, file10) {
|
// 检查是否有 keyCode,如果没有则默认为回车键
|
const keyCode = e.keyCode || e.which || 13;
|
|
if (keyCode == 13 || keyCode == 9) {
|
console.log('触发回车搜索:', fileId, file7, str);
|
|
// 判断是否需要调用存储过程
|
if (file7 != 'N') {
|
this.doProByFile8(str, fileId);
|
}
|
|
// 判断跳转字段
|
if (file9 == '1') {
|
// 回车自动跳至下一非只读字段
|
this.focusNextInput(fileId);
|
}
|
if (file9 == '0' && file10 == '') {
|
// 回车后就停留在本字段,本字段内容先清空
|
this.formValues[fileId] = '';
|
this.focusInput(fileId);
|
}
|
if (file10 != '') {
|
// 跳至指定字段,当要求跳到指定字段时,这个指定字段及后面顺序的字段框内容均需要清空
|
this.formValues[file10] = '';
|
this.focusInput(file10);
|
}
|
}
|
},
|
focusNextInput(currentId) {
|
// 找到当前字段在 formData 中的索引
|
const currentIndex = this.formData.findIndex(item => item[0] === currentId);
|
if (currentIndex === -1) return;
|
|
// 从当前字段之后查找第一个非只读的输入字段
|
for (let i = currentIndex + 1; i < this.formData.length; i++) {
|
const item = this.formData[i];
|
// 检查是否是可输入字段且非只读
|
if ((item[4] === '3' || item[4] === '4') && item[3] !== '1') {
|
this.focusInput(item[0]);
|
return;
|
}
|
}
|
},
|
|
// 扫描选择框回车事件
|
enterScanSelect(e, file8, fileId, file10, file7) {
|
const keyCode = e.keyCode || e.which || 13;
|
|
if (keyCode == 13 || keyCode == 9) {
|
console.log('触发扫描选择回车:', fileId, file7, file8);
|
const value = this.formValues[fileId]; // 直接使用formValues
|
|
if (value == '') {
|
uni.showToast({
|
title: '请扫描',
|
icon: 'none'
|
});
|
return false;
|
}
|
|
// 不再需要这一行,因为已经直接绑定到formValues
|
// this.formValues[fileId] = value;
|
|
if (file7 != 'N') {
|
this.doProByFile8(file8, fileId);
|
}
|
|
if (file10 != '') {
|
this.focusInput(file10);
|
}
|
}
|
},
|
|
// 下拉框选择事件
|
getCheckItem(file8, fileId, file10, file7, e) {
|
const index = e.detail.value;
|
const value = this.selectOptions[fileId][index];
|
|
if (!value) {
|
uni.showToast({
|
title: '请选择',
|
icon: 'none'
|
});
|
this.formValues[fileId] = '';
|
return false;
|
}
|
|
// 不再需要scanValues
|
// this.scanValues[fileId] = value;
|
this.formValues[fileId] = value;
|
|
if (file7 != 'N') {
|
this.doProByFile8(file8, fileId);
|
}
|
|
if (file10 != '') {
|
this.formValues[file10] = '';
|
this.focusInput(file10);
|
}
|
},
|
|
// 多选框选择事件
|
getCheckMultiItem(file8, fileId, file10, file7, e) {
|
const indexes = e.detail.value;
|
const values = indexes.map(index => this.selectOptions['mul' + fileId][index]);
|
|
if (values.length === 0) {
|
uni.showToast({
|
title: '请选择',
|
icon: 'none'
|
});
|
this.scanValues['mul' + fileId] = '';
|
this.formValues[fileId] = '';
|
return false;
|
}
|
|
const str = values.join('@');
|
|
this.scanValues['mul' + fileId] = str;
|
this.formValues[fileId] = str;
|
|
if (file7 != 'N') {
|
this.doProByFile8(file8, fileId);
|
}
|
|
if (file10 != '') {
|
this.formValues[file10] = '';
|
this.focusInput(file10);
|
}
|
},
|
|
// 过滤表格数据
|
filterTableData() {
|
// 如果没有搜索条件,显示全部数据
|
if (Object.keys(this.searchValues).length === 0 ||
|
Object.values(this.searchValues).every(v => !v)) {
|
this.filteredTableData = this.tableData;
|
return;
|
}
|
|
// 根据搜索条件过滤数据
|
this.filteredTableData = this.tableData.filter(row => {
|
// 检查每一列是否符合搜索条件
|
return Object.keys(this.searchValues).every(colIndex => {
|
const searchValue = this.searchValues[colIndex];
|
// 如果该列没有搜索值,则视为符合条件
|
if (!searchValue) return true;
|
|
const cellValue = String(row[colIndex] || '').toLowerCase();
|
return cellValue.includes(searchValue.toLowerCase());
|
});
|
});
|
},
|
|
// 处理表格数据变化时更新过滤结果
|
updateFilteredData() {
|
this.searchValues = {}; // 重置搜索条件
|
this.filteredTableData = this.tableData; // 重置过滤结果
|
},
|
|
// 开关切换事件
|
switchChange(e, fileId) {
|
this.formValues[fileId] = e.detail.value ? "1" : "0";
|
},
|
|
// 获取下拉框数据
|
getSelectData() {
|
this.formData.forEach(item => {
|
if ((item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '4') {
|
this.getExcProc(item[0], uni.getStorageSync("code") + '[_N', '', 'select');
|
} else if (item[2] === 'EDIT' && item[4] === '4') {
|
this.getExcProc(item[0], uni.getStorageSync("code") + '[_N', '', 'select');
|
}
|
});
|
},
|
|
// 执行SQL语句的默认值
|
getExcuteSql() {
|
this.formData.forEach(item => {
|
if (item[3] === '1' && (item[2] === 'VARCHAR2' || item[2] === 'VARCHAR') && item[4] === '3') {
|
let upperValue = item[12] ? item[12].toUpperCase() : '';
|
|
// 过滤数据库关键词
|
const reg = new RegExp(/INSERT|DELETE|UPDATE|DROP|TRUNCATE/);
|
if (reg.test(upperValue)) {
|
return;
|
}
|
|
upperValue = upperValue.replace('{USERCODE}', uni.getStorageSync("code"));
|
if (upperValue.substring(0, 6) === "SELECT") {
|
this.getExcuteSqlData(upperValue, item[0]);
|
}
|
}
|
});
|
},
|
|
// 执行SQL查询语句
|
getExcuteSqlData(str, inputId) {
|
uni.request({
|
url: this.$store.state.serverInfo.serverAPI + '/getExcuteSql',
|
data: {
|
str: str
|
},
|
method: 'POST',
|
timeout: 30000,
|
success: (res) => {
|
if (res.data.result) {
|
this.formValues[inputId] = res.data.data[0];
|
} else {
|
uni.showToast({
|
title: res.data.message,
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: '失败!失败类型是:' + err.errMsg,
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
// 打开列表页面
|
openList(fileId, fileName) {
|
uni.navigateTo({
|
url: '/pages/BasePage/select_search_list?file_name=' + fileId + '&title_name=' + fileName
|
});
|
},
|
|
// 执行存储过程
|
doProByFile8(file8, fileId) {
|
if (this.isCommitted === false) {
|
this.isCommitted = true;
|
this.doProByFile8Prc(file8, fileId);
|
} else {
|
return false;
|
}
|
},
|
|
// 执行存储过程处理
|
doProByFile8Prc(file8, fileId) {
|
try {
|
const date = file8.substring(1, file8.length - 1);
|
const a = date.split("}{");
|
const iput = a[0].split(',');
|
|
let fileValue = uni.getStorageSync("code") + '[';
|
for (let i = 0; i < iput.length; i++) {
|
let fv = this.formValues[iput[i]] || '';
|
fv = fv.trim();
|
fileValue += fv + '[';
|
}
|
fileValue = fileValue.substring(0, fileValue.length - 1);
|
console.log(12);
|
if (a[1]) {
|
const input = a[1].split(',');
|
if (input[input.length - 1] === 'FVIEW') {
|
this.getExcProc(fileId, fileValue, a[1], 'cursor+proc');
|
} else {
|
this.getExcProc(fileId, fileValue, a[1], 'proc');
|
}
|
} else {
|
this.getExcProc(fileId, fileValue, a[1], 'proc');
|
}
|
} catch (e) {
|
uni.showModal({
|
title: '错误',
|
content: "功能发生异常,请联系IT人员",
|
showCancel: false
|
});
|
this.isCommitted = false;
|
return false;
|
}
|
},
|
|
// 执行存储过程API
|
// 执行存储过程API
|
getExcProc(fileName, fileValue, outFiles, stype) {
|
const fileId = fileName;
|
fileName = fileName.replace(/\s+/g, "");
|
|
uni.request({
|
url: this.$store.state.serverInfo.serverAPI + '/modules/getExcProc',
|
data: {
|
functionName: uni.getStorageSync("functionName"),
|
fileName: fileName,
|
pmachtype: '',
|
fileValue: fileValue,
|
outFiles: outFiles
|
},
|
method: 'POST',
|
timeout: 60000,
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
console.log(JSON.stringify(res.data));
|
if (res.data.data) {
|
if (stype.indexOf('proc') !== -1) {
|
const msg_1 = res.data.message;
|
if (msg_1 && msg_1.indexOf('999!*') !== -1) {
|
uni.showModal({
|
title: '警告提醒',
|
content: res.data.message,
|
showCancel: false
|
});
|
} else {
|
console.log(1);
|
this.afterProc(res.data);
|
}
|
} else if (stype.indexOf('select') !== -1) {
|
console.log(2);
|
const t = res.data.data.split(',');
|
const options = t.filter(item => item.length > 0);
|
|
if (fileName.startsWith('mul')) {
|
this.$set(this.selectOptions, fileName, options);
|
} else {
|
this.$set(this.selectOptions, fileName, options);
|
}
|
}
|
|
if (stype.indexOf('cursor') !== -1) {
|
const valueData = res.data.data.toString();
|
const t1 = valueData.substring(valueData.indexOf(',') + 1, valueData.length);
|
const tData = t1.split(',');
|
const table = tData[tData.length - 1].split('{');
|
|
// 处理表头
|
const headerRow = table[0].split('@');
|
this.tableColumns = headerRow;
|
|
// 处理数据行
|
const rows = [];
|
for (let i = 1; i < table.length; i++) {
|
if (table[i].length > 0) {
|
rows.push(table[i].split('@'));
|
}
|
}
|
this.tableData = rows;
|
this.filteredTableData = rows; // 初始化过滤后的数据
|
this.searchValues = {}; // 重置搜索条件
|
this.showTable = true;
|
}
|
|
if (stype.indexOf('print') !== -1) {
|
const da = res.data.data[0];
|
if (da && da.length > 0) {
|
da.splice(0, 1);
|
this.printByIds(da.toString());
|
}
|
}
|
} else {
|
this.playerNo();
|
uni.showModal({
|
title: '提示',
|
content: res.data.message,
|
showCancel: false,
|
success: () => {
|
this.formValues[fileId] = "";
|
this.focusInput(fileId);
|
}
|
});
|
}
|
this.isCommitted = false;
|
},
|
fail: (err) => {
|
this.isCommitted = false;
|
uni.showToast({
|
title: "请求失败: " + err.errMsg,
|
content: "请求失败: " + err.errMsg,
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
// 处理存储过程返回结果
|
afterProc(data) {
|
this.playerYes();
|
console.log('处理返回数据:', JSON.stringify(data));
|
|
// 检查数据格式
|
if (!data.data || !Array.isArray(data.data)) {
|
console.error('返回数据格式不正确:', data);
|
return;
|
}
|
|
// 遍历数据数组
|
for (let i = 0; i < data.data.length; i++) {
|
const t = data.data[i];
|
|
// 检查数组元素是否有效
|
if (!Array.isArray(t) || t.length < 2) {
|
console.warn('数据项格式不正确:', t);
|
continue;
|
}
|
|
const fieldId = t[0];
|
const fieldValue = t[1];
|
|
// 检查字段ID是否存在于表单值中
|
if (this.formValues.hasOwnProperty(fieldId)) {
|
if (typeof fieldValue === 'string' && fieldValue.indexOf("{") === -1) {
|
this.formValues[fieldId] = fieldValue;
|
} else if (typeof fieldValue === 'string') {
|
const a = fieldValue.split('{');
|
this.setSelect(a, fieldId);
|
} else {
|
console.warn('字段值类型不正确:', fieldValue);
|
}
|
} else {
|
console.warn('表单中不存在字段:', fieldId);
|
}
|
}
|
},
|
|
// 设置下拉框选项
|
setSelect(t, fileName) {
|
const options = t.filter(item => item.length > 0);
|
this.$set(this.selectOptions, fileName, options);
|
this.formValues[fileName] = '';
|
},
|
|
// 点击按钮
|
clickButton(item) {
|
const file10 = item[10];
|
const file8 = item[8];
|
|
this.doProByFile8(file8, item[0]);
|
|
if (file10 !== '') {
|
this.formValues[file10] = '';
|
this.focusInput(file10);
|
}
|
},
|
|
// 点击拍照按钮
|
photoButton(item) {
|
uni.navigateTo({
|
url: '/pages/BasePage/ftp/pictrue_add'
|
});
|
},
|
|
// 点击列表按钮
|
listButton(item) {
|
const file8 = item[8];
|
this.doProByFile8Cursor(file8, item[0], item[2]);
|
},
|
|
// 执行列表查询
|
doProByFile8Cursor(file8, fileId, fileType) {
|
const date = file8.substring(1, file8.length - 1);
|
const a = date.split("}{");
|
const iput = a[0].split(',');
|
|
let fileValue = uni.getStorageSync("code") + '[';
|
for (let i = 0; i < iput.length; i++) {
|
let fv = this.formValues[iput[i]] || '';
|
fv = fv.trim();
|
fileValue += fv + '[';
|
}
|
fileValue = fileValue.substring(0, fileValue.length - 1);
|
|
if (fileType === 'EDIT') {
|
this.getCursor(fileId, fileValue, a[1], 'cursor');
|
} else {
|
this.getExcProc(fileId, fileValue, a[1], 'cursor');
|
}
|
},
|
|
// 获取游标数据
|
// 获取游标数据
|
getCursor(fileName, fileValue, outFiles, stype) {
|
const fileId = fileName;
|
fileName = fileName.replace(/\s+/g, "");
|
|
uni.request({
|
url: this.$store.state.serverInfo.serverAPI + '/getCursor',
|
data: {
|
functionName: uni.getStorageSync("functionName"),
|
fileName: fileName,
|
pmachtype: '',
|
fileValue: encodeURIComponent(fileValue),
|
outFiles: outFiles
|
},
|
method: 'POST',
|
timeout: 60000,
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.data.result) {
|
if (res.data.data[0]) {
|
uni.showModal({
|
title: '错误',
|
content: "功能发生异常,请联系IT人员",
|
showCancel: false
|
});
|
} else {
|
const tdata = res.data.data[2];
|
const col = res.data.data[3];
|
|
this.tableColumns = col;
|
this.tableData = tdata.map(item => Object.values(item));
|
this.filteredTableData = this.tableData; // 初始化过滤后的数据
|
this.searchValues = {}; // 重置搜索条件
|
this.showTable = true;
|
}
|
} else {
|
uni.showToast({
|
title: res.data.message,
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: "请求失败: " + err.errMsg,
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
// 点击打印按钮
|
clickPrintBtn(item) {
|
try {
|
const file8 = item[8];
|
const file10 = item[10];
|
const fileId = item[0];
|
|
const date = file8.substring(1, file8.length - 1);
|
const a = date.split("}{");
|
const iput = a[0].split(',');
|
|
let fileValue = uni.getStorageSync("code") + '[';
|
for (let i = 0; i < iput.length; i++) {
|
let fv = this.formValues[iput[i]] || '';
|
fileValue += fv + '[';
|
}
|
fileValue = fileValue.substring(0, fileValue.length - 1);
|
|
// 先清空字段
|
if (file10 !== '') {
|
this.formValues[file10] = '';
|
this.focusInput(file10);
|
}
|
|
setTimeout(() => {
|
if (a[1]) {
|
const input = a[1].split(',');
|
if (input[input.length - 1] === 'FVIEW') {
|
this.getExcProc(fileId, fileValue, a[1], 'cursor+print');
|
} else {
|
this.getExcProc(fileId, fileValue, a[1], 'print');
|
}
|
}
|
}, 100);
|
} catch (e) {
|
uni.showModal({
|
title: '错误',
|
content: "功能发生异常,请联系IT人员",
|
showCancel: false
|
});
|
}
|
},
|
|
// 初始化蓝牙打印机
|
initBluetooth() {
|
// #ifdef APP-PLUS
|
try {
|
const main = plus.android.runtimeMainActivity();
|
const BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
|
const UUID = plus.android.importClass("java.util.UUID");
|
|
const uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
const BAdapter = BluetoothAdapter.getDefaultAdapter();
|
BAdapter.cancelDiscovery(); // 停止扫描
|
|
const address_mac = uni.getStorageSync("printMac") || "DC:1D:30:3F:D2:50";
|
this.device = BAdapter.getRemoteDevice(address_mac);
|
plus.android.importClass(this.device);
|
|
this.bluetoothSocket = this.device.createInsecureRfcommSocketToServiceRecord(uuid);
|
plus.android.importClass(this.bluetoothSocket);
|
} catch (err) {
|
console.log(err);
|
uni.showToast({
|
title: "蓝牙连接异常!",
|
icon: 'none'
|
});
|
}
|
// #endif
|
},
|
|
// 打印标签
|
printByIds(ids) {
|
// #ifdef APP-PLUS
|
try {
|
if (!this.bluetoothSocket) {
|
uni.showToast({
|
title: "蓝牙未连接",
|
icon: 'none'
|
});
|
return;
|
}
|
|
uni.request({
|
url: this.$store.state.serverInfo.serverAPI + '/getPrintData',
|
data: {
|
ids: ids
|
},
|
method: 'POST',
|
timeout: 60000,
|
success: (res) => {
|
if (res.data.result) {
|
const printData = res.data.data;
|
this.doPrint(printData);
|
} else {
|
uni.showToast({
|
title: res.data.msg,
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: "请求失败: " + err.errMsg,
|
content: "请求失败: " + err.errMsg,
|
icon: 'none'
|
});
|
}
|
});
|
} catch (e) {
|
uni.showToast({
|
title: "打印异常: " + e.message,
|
icon: 'none'
|
});
|
}
|
// #endif
|
},
|
|
// 执行打印
|
doPrint(printData) {
|
// #ifdef APP-PLUS
|
try {
|
this.bluetoothSocket.connect();
|
const outputStream = this.bluetoothSocket.getOutputStream();
|
plus.android.importClass(outputStream);
|
|
for (let i = 0; i < printData.length; i++) {
|
const item = printData[i];
|
const template = item.template;
|
const data = item.data;
|
|
// 这里可以根据模板和数据生成打印内容
|
const printContent = this.generatePrintContent(template, data);
|
|
outputStream.write(plus.android.newByteArray(printContent));
|
outputStream.flush();
|
}
|
|
outputStream.close();
|
this.bluetoothSocket.close();
|
|
uni.showToast({
|
title: "打印成功",
|
icon: 'success'
|
});
|
} catch (e) {
|
uni.showToast({
|
title: "打印失败: " + e.message,
|
icon: 'none'
|
});
|
}
|
// #endif
|
},
|
|
// 生成打印内容
|
generatePrintContent(template, data) {
|
// 根据模板和数据生成打印内容
|
// 这里需要根据实际打印机和模板格式进行实现
|
return new Uint8Array([0x1B, 0x40]); // 示例: 打印机初始化命令
|
},
|
|
// 播放成功提示音
|
playerYes() {
|
// #ifdef APP-PLUS
|
try {
|
const context = plus.audio.createPlayer('static/audio/yes.mp3');
|
context.play();
|
} catch (e) {
|
console.log('播放提示音失败:', e);
|
}
|
// #endif
|
},
|
|
// 播放失败提示音
|
playerNo() {
|
// #ifdef APP-PLUS
|
try {
|
const context = plus.audio.createPlayer('static/audio/no.mp3');
|
context.play();
|
} catch (e) {
|
console.log('播放提示音失败:', e);
|
}
|
// #endif
|
},
|
|
// 获取列宽样式
|
getColumnStyle(col) {
|
if (col.indexOf('_') !== -1) {
|
const tArr = col.split('_');
|
return { width: tArr[1] + '%' };
|
}
|
return {};
|
},
|
|
// 获取列名
|
getColumnName(col) {
|
if (col.indexOf('_') !== -1) {
|
const tArr = col.split('_');
|
return tArr[0];
|
}
|
return col;
|
}
|
}
|
};
|
</script>
|
|
<style>
|
/* 页面容器 */
|
.container {
|
display: flex;
|
flex-direction: column;
|
height: 100vh;
|
background-color: #f5f7fa;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
}
|
|
/* 内容区域 */
|
.content {
|
flex: 1;
|
overflow-y: auto;
|
padding: 8px;
|
}
|
|
/* 表单容器 */
|
.form-container {
|
margin-bottom: 12px;
|
}
|
|
/* 表单项 */
|
.form-item {
|
display: flex;
|
align-items: center;
|
margin-bottom: 8px;
|
background-color: #fff;
|
border-radius: 6px;
|
padding: 0 10px;
|
min-height: 44px;
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
}
|
|
.form-label {
|
width: 80px;
|
font-size: 14px;
|
color: #333;
|
font-weight: 500;
|
padding-right: 10px;
|
flex-shrink: 0;
|
}
|
|
.form-input {
|
flex: 1;
|
height: 44px;
|
padding: 0 10px;
|
font-size: 14px;
|
border: none;
|
background-color: transparent;
|
}
|
|
.form-input.readonly {
|
color: #999;
|
background-color: #f5f5f5;
|
border-radius: 4px;
|
|
}
|
|
.form-textarea {
|
flex: 1;
|
padding: 10px;
|
font-size: 14px;
|
border: none;
|
background-color: transparent;
|
min-height: 60px;
|
}
|
|
.form-textarea.readonly {
|
color: #999;
|
background-color: #f5f5f5;
|
border-radius: 4px;
|
|
}
|
|
/* 下拉选择框 */
|
.select-wrapper {
|
flex: 1;
|
position: relative;
|
}
|
|
.select-icon {
|
position: absolute;
|
right: 10px;
|
top: 50%;
|
transform: translateY(-50%);
|
pointer-events: none;
|
}
|
|
/* 扫描选择框 */
|
.scan-select-container {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
}
|
|
.scan-input {
|
flex: 1;
|
}
|
|
.select-btn {
|
width: 36px;
|
height: 36px;
|
background: linear-gradient(135deg, #5677fc, #8a9ffc);
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
border-radius: 4px;
|
margin-left: 8px;
|
}
|
|
.select-btn.readonly-btn {
|
background: linear-gradient(135deg, #e0e0e0, #d0d0d0);
|
cursor: not-allowed;
|
}
|
|
/* 按钮样式 */
|
.button-item {
|
justify-content: center;
|
padding: 6px 0;
|
}
|
|
.action-button {
|
width: 100%;
|
height: 40px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
border-radius: 6px;
|
color: #fff;
|
font-size: 14px;
|
font-weight: 500;
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
}
|
|
.normal-btn {
|
background: linear-gradient(135deg, #5677fc, #8a9ffc);
|
}
|
|
.photo-btn {
|
background: linear-gradient(135deg, #52c41a, #95de64);
|
}
|
|
.list-btn {
|
background: linear-gradient(135deg, #fa8c16, #ffc53d);
|
}
|
|
.print-btn {
|
background: linear-gradient(135deg, #13c2c2, #5cdbd3);
|
}
|
|
/* 开关样式 */
|
.switch-item {
|
justify-content: space-between;
|
}
|
|
.custom-switch {
|
transform: scale(0.8);
|
}
|
|
/* 表格样式 */
|
.table-container {
|
background-color: #fff;
|
border-radius: 6px;
|
overflow: hidden;
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
margin-top: 8px;
|
}
|
|
.table-header {
|
padding: 10px;
|
background-color: #f9fafc;
|
border-bottom: 1px solid #edf0f7;
|
}
|
|
.table-title {
|
font-size: 14px;
|
font-weight: 600;
|
color: #333;
|
}
|
|
.table-scroll {
|
max-height: 300px;
|
}
|
|
.table {
|
width: 100%;
|
table-layout: fixed;
|
}
|
|
.tr {
|
display: flex;
|
border-bottom: 1px solid #edf0f7;
|
min-height: 44px;
|
}
|
|
.tr-alter {
|
background-color: #f9fafc;
|
}
|
|
.th, .td {
|
flex: 1;
|
padding: 10px 6px;
|
text-align: center;
|
font-size: 13px;
|
word-break: break-word;
|
white-space: normal;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.td {
|
min-height: 44px;
|
position: relative;
|
}
|
|
.th {
|
background-color: #f5f7fa;
|
color: #333;
|
font-weight: 600;
|
position: sticky;
|
top: 0;
|
z-index: 2;
|
}
|
|
/* 表格搜索行样式 */
|
.search-row {
|
background-color: #f0f2f5;
|
border-bottom: 1px solid #ddd;
|
}
|
|
.search-cell {
|
padding: 5px 3px;
|
}
|
|
.search-input {
|
width: 100%;
|
height: 30px;
|
border: 1px solid #ddd;
|
border-radius: 4px;
|
padding: 0 5px;
|
font-size: 12px;
|
background-color: #fff;
|
}
|
|
/* 确保表头固定在顶部 */
|
.thead {
|
position: sticky;
|
top: 0;
|
z-index: 10;
|
}
|
|
/* 适配小屏幕 */
|
@media screen and (max-width: 320px) {
|
.form-label {
|
width: 70px;
|
font-size: 13px;
|
}
|
|
.form-input, .form-textarea {
|
font-size: 13px;
|
}
|
|
.action-button {
|
font-size: 13px;
|
}
|
}
|
.scan-input-container {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
position: relative;
|
}
|
|
/* 扫码图标按钮 */
|
.scan-icon-btn {
|
width: 36px;
|
height: 36px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
position: absolute;
|
right: 0;
|
top: 50%;
|
transform: translateY(-50%);
|
z-index: 1;
|
}
|
|
/* 调整带扫码图标的输入框内边距 */
|
.scan-input-container .form-input {
|
padding-right: 36px;
|
}
|
</style>
|