master
lynn 1 year ago
parent de00a1c07a
commit 147d26a76e

@ -14,7 +14,7 @@
<!-- Pre-payment Form -->
<div v-if="currentForm === 'pre'" class="payment-form">
<div v-if="getBeforeForms" v-html="getBeforeForms"></div>
<div v-else class="no-form-message">暂无事前支付表格内容</div>
<div v-else class="no-form-message">暂无事前审批表格内容</div>
</div>
<!-- Post-payment Form -->
@ -65,16 +65,98 @@ export default {
this.$Message.error('获取付款详情失败')
}
},
replaceControls(element) {
// 替换所有输入框(文本、数字、日期)为纯文本
const inputs = element.getElementsByTagName('input')
Array.from(inputs).forEach(input => {
const span = document.createElement('span')
let displayText = input.value || ''
// 处理不同类型的输入框
if (input.type === 'checkbox' || input.type === 'radio') {
// 获取当前选中的值
const checkedInput = element.querySelector(`input[name="${input.name}"]:checked`)
if (checkedInput) {
// 获取显示文本(如果有label,使用label的文本)
const label = element.querySelector(`label[for="${checkedInput.id}"]`)
displayText = label ? label.textContent : checkedInput.value || ''
} else {
displayText = ''
}
} else if (input.type === 'date') {
displayText = input.value ? new Date(input.value).toLocaleDateString() : ''
}
span.textContent = displayText
// 复制原始输入框的样式
span.style.cssText = window.getComputedStyle(input).cssText
span.style.display = 'inline-block'
span.style.width = input.offsetWidth + 'px'
span.style.height = input.offsetHeight + 'px'
span.style.border = 'none'
span.style.backgroundColor = 'transparent'
input.parentNode.replaceChild(span, input)
})
// 替换所有下拉框为纯文本
const selects = element.getElementsByTagName('select')
Array.from(selects).forEach(select => {
const span = document.createElement('span')
span.textContent = select.options[select.selectedIndex]?.text || ''
// 复制原始下拉框的样式
span.style.cssText = window.getComputedStyle(select).cssText
span.style.display = 'inline-block'
span.style.width = select.offsetWidth + 'px'
span.style.height = select.offsetHeight + 'px'
span.style.border = 'none'
span.style.backgroundColor = 'transparent'
select.parentNode.replaceChild(span, select)
})
// 替换所有文本域为纯文本
const textareas = element.getElementsByTagName('textarea')
Array.from(textareas).forEach(textarea => {
const span = document.createElement('span')
span.textContent = textarea.value || ''
// 复制原始文本域的样式
span.style.cssText = window.getComputedStyle(textarea).cssText
span.style.display = 'inline-block'
span.style.width = textarea.offsetWidth + 'px'
span.style.height = textarea.offsetHeight + 'px'
span.style.border = 'none'
span.style.backgroundColor = 'transparent'
textarea.parentNode.replaceChild(span, textarea)
})
},
async print() {
try {
const canvas = await html2canvas(this.$refs['printtable'], {
// 创建临时打印容器
const tempContainer = document.createElement('div')
tempContainer.style.position = 'absolute'
tempContainer.style.left = '-9999px'
tempContainer.style.top = '-9999px'
document.body.appendChild(tempContainer)
// 复制原始内容到临时容器
const originalContent = this.$refs['printtable'].cloneNode(true)
tempContainer.appendChild(originalContent)
// 在临时容器中替换控件
this.replaceControls(tempContainer)
// 使用临时容器进行打印
const canvas = await html2canvas(tempContainer, {
backgroundColor: null,
useCORS: true,
})
// 打印完成后移除临时容器
document.body.removeChild(tempContainer)
printJS({
printable: canvas.toDataURL(),
type: 'image',
documentTitle: `苏州市河道管理处${this.currentForm === 'pre' ? '事前' : '事后'}支付表格`,
documentTitle: `苏州市河道管理处${this.currentForm === 'pre' ? '事前审批表格' : '事后支付表格'}`,
style: '@page{margin:auto;}'
})
} catch (error) {

@ -3,6 +3,34 @@
<lx-header icon="md-apps" style="margin-bottom: 10px; border: 0px; margin-top: 15px" text="合同列表">
<div slot="content"></div>
<slot>
<!-- 修改为新增合同按钮 -->
<div class="category-buttons">
<Button
type="primary"
size="large"
class="category-button"
@click="handleAddContractByCategory('contract')"
>
新增合同类
</Button>
<Button
type="primary"
size="large"
class="category-button"
@click="handleAddContractByCategory('reimbursement')"
>
新增报销类
</Button>
<Button
type="primary"
size="large"
class="category-button"
@click="handleAddContractByCategory('other')"
>
新增其他支出类
</Button>
</div>
<div class="selects">
<div>
<span style="padding: 0 6px;word-break: keep-all;">关键字</span>
@ -140,7 +168,6 @@
</Select>
</div>
<Button style="margin-left: 10px" type="primary" @click="handleAddContract">新增</Button>
<Button style="margin-left: 10px" type="primary" @click="getContracts">查询</Button>
<Button ghost style="margin-left: 10px" type="primary"
@click=" select = {showDatePicker:'',ageIndex:1,startDate:'',endDate:'',type:'',department:'',purchaseModality:'',purchaseMethods:'',priceMin:null,priceMax:null,status:''}">
@ -281,7 +308,7 @@
<div v-show="currentStep === 1" class="step-content">
<div class="form-group" v-if="categoryOptions && categoryOptions.length > 0">
<label class="form-label">分类</label>
<Select v-model="form.category" @on-change="handleCategoryChange" placeholder="请选择分类" class="form-input">
<Select v-model="form.category" @on-change="handleCategoryChange" placeholder="请选择分类" class="form-input" disabled>
<Option v-for="item in categoryOptions" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
@ -817,6 +844,7 @@ export default {
}
return {
selectedCategory: 'contract', // 添加选中的分类
userList: ["liuxiangyu", "zhushulan", "admin", "jiangjiao"],
window: {
width: 0,
@ -3240,6 +3268,53 @@ export default {
}
this.showPaymentFormPreview = false;
},
// 添加分类选择处理方法
handleCategorySelect(category) {
this.selectedCategory = category;
// 根据分类筛选数据
this.select.category = category;
this.getContracts();
},
// 添加按分类新增合同的方法
async handleAddContractByCategory(category) {
// 先设置 loading 状态
this.loading = true;
try {
// 显示弹窗
this.isShowAdd = true;
this.isEditMode = false;
this.isFromPayment = false;
// 等待获取分类配置
await this.getCategoryOptions();
// 重置表单
this.resetForm();
// 根据分类自动选择对应的选项
if (this.categoryOptions && this.categoryOptions.length > 0) {
// 找到对应分类的选项
const categoryOption = this.categoryOptions.find(item => {
const name = item.name || item.value || '';
return name.includes(category === 'contract' ? '合同' :
category === 'reimbursement' ? '报销' : '其他支出');
});
if (categoryOption) {
this.form.category = categoryOption.id;
// 触发分类变更,自动选择后续选项
this.handleCategoryChange();
}
}
} catch (error) {
console.error('加载数据失败:', error);
this.$message.error('加载数据失败');
} finally {
// 无论成功失败都关闭 loading
this.loading = false;
}
},
},
mounted() {
this.window.width = screen.availWidth * 0.95
@ -3689,6 +3764,38 @@ export default {
}
}
}
// 添加分类按钮样式
.category-buttons {
display: flex;
justify-content: center;
gap: 20px;
margin-bottom: 20px;
padding: 10px 0;
.category-button {
min-width: 180px;
height: 48px;
font-size: 16px;
font-weight: 500;
border-radius: 8px;
transition: all 0.3s ease;
background: #2d8cf0;
border-color: #2d8cf0;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
background: #2b85e4;
border-color: #2b85e4;
}
&:active {
transform: translateY(0);
box-shadow: none;
}
}
}
</style>
<style scoped lang="scss">

@ -4,6 +4,33 @@
<div slot="content"></div>
<slot>
<div class="selects">
<div>
<span style="padding: 0 6px;word-break: keep-all;">
合同分类
</span>
<Select v-model="select.contract_category" @on-change="handleCategoryChange" disabled placeholder="请选择合同分类" style="width:140px;">
<Option v-for="item in categoryOptions" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">
事务类型
</span>
<Select v-model="select.work_type" @on-change="handleTransactionTypeChange" multiple clearable placeholder="请选择事务类型" style="width:140px;">
<Option v-for="item in transactionTypes" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">
合同类型
</span>
<Select v-model="select.contract_type" @on-change="handleContractTypeChange" multiple clearable placeholder="请选择合同类型" style="width:140px;">
<Option v-for="item in contractTypes" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">关键字</span>
<span>
@ -411,6 +438,7 @@
import {
getInfo
} from '@/api/user.js'
import { getContractCategoryTemplateBaseConfig } from "@/api/businessConfig/businessConfig"
import editor from "./components/editorContract"
import detail from "./components/detailContract"
@ -489,7 +517,10 @@
showDatePickerBao: "",
start_assurance_expire: "",
end_assurance_expire: "",
is_contract: ''
is_contract: '',
contract_category: '',
work_type: '',
contract_type: ''
},
types: [{
label: '服务',
@ -982,6 +1013,11 @@
plansPageIndex: 1,
isShowEditor: false,
contractCategories: [], // 合同分类
transactionTypes: [], // 事务类型
contractTypes: [], // 合同类型
categoryOptions: [], // 分类选项
purchaseMethodsMap: {}, // 采购方式映射
}
},
created() {
@ -1509,33 +1545,136 @@
});
});
}
},
// 获取分类选项
async getCategoryOptions() {
try {
// 获取分类配置
const res = await getContractCategoryTemplateBaseConfig()
if (res.errcode !== undefined) {
this.$message.error(res.errmsg || '获取分类配置失败')
return
}
// 保存采购方式映射
this.purchaseMethodsMap = res.purchase_methods || {}
// 设置分类选项 - 从第二级开始(合同类、报销类、其他支出类)
this.categoryOptions = res.map?.[0]?.children || []
// 递归处理每一层的 children,确保所有层级都被正确解析
const processChildren = (items) => {
if (!items) return
items.forEach(item => {
if (item.children) {
// 确保每个子项都有正确的 id 和 name/value
item.children = item.children.map(child => ({
id: child.id,
name: child.name || child.value, // 添加对 value 字段的支持
value: child.value || child.name, // 保留原始的 value 字段
children: child.children || []
}))
processChildren(item.children)
}
})
}
// 处理所有层级的 children
processChildren(this.categoryOptions)
// 更新下拉框数据
this.updateDropdownOptions()
} catch (error) {
console.error('获取分类配置失败:', error)
this.$message.error('获取分类配置失败')
}
},
// 更新下拉框选项
updateDropdownOptions() {
// 重置所有选项
this.transactionTypes = []
this.contractTypes = []
// 获取当前选中的分类
const selectedCategory = this.categoryOptions.find(item => item.id === this.select.contract_category)
if (!selectedCategory) return
// 更新事务类型选项
this.transactionTypes = selectedCategory.children || []
// 如果是初始化,默认全选事务类型
if (!this.select.work_type || this.select.work_type.length === 0) {
this.select.work_type = this.transactionTypes.map(item => item.id)
}
// 获取所有选中事务类型的合同类型
const selectedTransactionTypes = this.transactionTypes.filter(item =>
this.select.work_type.includes(item.id)
)
// 合并所有选中事务类型的合同类型
this.contractTypes = selectedTransactionTypes.reduce((acc, curr) => {
return [...acc, ...(curr.children || [])]
}, [])
// 如果是初始化,选择除了"无合同"(id=140)之外的所有合同类型
if (!this.select.contract_type || this.select.contract_type.length === 0) {
this.select.contract_type = this.contractTypes
.filter(item => item.id !== 140) // 排除"无合同"选项
.map(item => item.id)
}
},
// 处理分类变更
handleCategoryChange() {
// 清空选择,让 updateDropdownOptions 重新初始化
this.select.work_type = []
this.select.contract_type = []
this.updateDropdownOptions()
},
// 处理事务类型变更
handleTransactionTypeChange() {
// 清空合同类型选择,让 updateDropdownOptions 重新初始化
this.select.contract_type = []
this.updateDropdownOptions()
},
// 处理合同类型变更
handleContractTypeChange() {
this.updateDropdownOptions()
},
},
mounted() {
this.window.width = screen.availWidth * 0.95
this.window.height = screen.availHeight * 0.95
this.window.top = (window.screen.height - 30 - this.window.height) / 2
this.window.left = (window.screen.width - 10 - this.window.width) / 2
this.window.width = screen.availWidth * 0.95;
this.window.height = screen.availHeight * 0.95;
this.window.top = (window.screen.height - 30 - this.window.height) / 2;
this.window.left = (window.screen.width - 10 - this.window.width) / 2;
let that = this;
getInfo().then(response => {
console.log(response)
console.log(response);
this.user = response;
if (that.userList.indexOf(response.username) != -1) {
that.hasEdit = true;
}
}).catch(error => {})
this.getPurchaseType()
this.getContracts()
this.getDepartment()
this.getPurchaseWay()
this.getMoneyWay()
}).catch(error => {});
this.getPurchaseType();
this.getContracts();
this.getDepartment();
this.getPurchaseWay();
this.getMoneyWay();
// 获取分类数据
this.getCategoryOptions().then(() => {
// 设置默认选择第一个分类
if (this.categoryOptions && this.categoryOptions.length > 0) {
this.select.contract_category = this.categoryOptions[0].id;
this.handleCategoryChange();
}
});
//页面激活后刷新合同列表
window.onfocus = () => {
this.getContracts()
}
this.getContracts();
};
},
destroyed() {
window.onfocus = null
@ -1601,4 +1740,4 @@
content: '(元)'
}
}
</style>
</style>

@ -40,6 +40,15 @@
ghost>下级部门</Button>
<Button type="error" @click="del(scope.row)" size="small" style="margin-left: 10px;" ghost>删除</Button>
<Button type="primary" @click="edit(scope.row)" size="small" style="margin-left: 10px;" ghost>编辑</Button>
<Button
:type="scope.row.status === 1 ? 'warning' : 'success'"
@click="toggleStatus(scope.row)"
size="small"
style="margin-left: 10px;"
ghost
>
{{ scope.row.status === 1 ? '禁用' : '启用' }}
</Button>
</template>
</el-table-column>
</el-table>
@ -81,7 +90,8 @@
import {
listdept,
save,
del
del,
updateStatus
} from "../../api/system/department.js";
import {
listuser
@ -110,7 +120,8 @@
leader: "",
sortnumber: 0,
icon: "",
pname: "上级部门"
pname: "上级部门",
status: 1 // 添加状态字段,1-启用,0-禁用
},
rules: {
name: [{
@ -239,6 +250,31 @@
});
}
},
// 切换部门状态
toggleStatus(row) {
const newStatus = row.status === 1 ? 0 : 1;
const actionText = newStatus === 1 ? '启用' : '禁用';
this.$confirm(`确认要${actionText}该部门?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: newStatus === 1 ? 'success' : 'warning',
center: true
}).then(() => {
const params = {
id: row.id,
status: newStatus
};
save(params).then(response => {
this.$message.success('操作成功');
this.load();
}).catch(error => {
this.$message.error('操作失败');
});
}).catch(() => {
// 取消
});
},
}
};
</script>
</script>

Loading…
Cancel
Save