一般采购 支付

master
lion 7 months ago
parent 49cb46e0c2
commit 659505ad57

@ -0,0 +1,37 @@
import request from '@/utils/request'
import { MessageBox } from 'element-ui'
// 已支付物资明细情况
export function getItems(params) {
return request({
method: 'get',
url: `/api/ht/fund_log/wuzicaigou-items`,
params
})
}
//
export function fundLogSave(data) {
return request({
method: 'post',
url: `/api/ht/fund_log/store`,
data
})
}
// 获取合同详情
export function detailContract(params){
return request({
method:'get',
url:'/api/ht/contract/show',
params
})
}
// 获取 付款登记次数
export function getFundLog(params,noloading = false){
return request({
method:'get',
url:'/api/ht/fund_log/index',
params,
noloading
})
}

@ -34,10 +34,11 @@ if (process.env.NODE_ENV === 'production') {
Vue.use(ElementUI)
// vxe-table
import { VxeUI, VxeUpload, VxeDatePicker } from 'vxe-pc-ui'
import { VxeUI, VxeUpload, VxeDatePicker,VxeNumberInput } from 'vxe-pc-ui'
import 'vxe-pc-ui/lib/style.css'
Vue.use(VxeUpload)
Vue.use(VxeDatePicker)
Vue.use(VxeNumberInput)
import VxeTable from 'vxe-table'
import "vxe-table/styles/index.scss"
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx'

@ -81,6 +81,12 @@ export const constantRoutes = [
name: "detail",
component: () => import("@/views/flow/create"),
hidden: true,
},
{
path: "detailCommon",
name: "detailCommon",
component: () => import("@/views/flow/detailCommon"),
hidden: true,
}
],
},

@ -612,6 +612,7 @@ export default function formBuilder(
]);
break;
case "relation":
console.log("123",this.form[info.name])
formItem = h(
"vxe-table",
{
@ -1150,6 +1151,7 @@ export default function formBuilder(
);
}
}
if (device === "mobile") {
if (info._writeable || pWrite) {
switch (info.type) {
@ -1742,6 +1744,7 @@ export default function formBuilder(
);
break;
case "relation":
console.log("this.form[info.name]",this.form[info.name])
formItem = h("div", [
h("van-cell", {
props: {

@ -0,0 +1,370 @@
<template>
<div>
<vxe-modal :value="isShow" show-footer :z-index="zIndex" title="支付审批明细" show-zoom show-confirm-button transfer
resize :width="defaultModalSize.width" :height="defaultModalSize.height" @input="e => $emit('update:isShow',e)">
<div>
<div style="display: flex;align-items: center;justify-content: space-between;">
<div style="display: flex;align-items: center;">
<div class="xy-table-item-label">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>申请付款金额
</div>
<div class="xy-table-item-content xy-table-item-price">
<el-input clearable type="number" placeholder="请填写付款金额" v-model="fundlogForm.applyMoney"
style="width: 150px;margin-left:10px" />
</div>
</div>
<div style="display: flex;align-items: center;">
<div class="xy-table-item-label">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>款项类型
</div>
<div style="display: flex;align-items: center;">
<el-select placeholder="选择款项类型或直接录入其他类型" v-model="fundlogForm.type" style="width: 200px;margin-left:10px"
filterable allow-create clearable popper-append-to-body>
<el-option v-for="item in paymentType" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</div>
</div>
<div style="display: flex;align-items: center;">
<div class="xy-table-item-label">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>是否为最后一笔
</div>
<div class="xy-table-item-content" style="margin-left:10px">
<el-switch v-model="fundlogForm.isLast" />
<!-- @change="toggleSelection"-->
</div>
</div>
</div>
<vxe-table ref="table" stripe style="margin-top: 10px" keep-source :column-config="{ resizable: true }"
:print-config="{}" :export-config="{}" :expand-config="{
accordion: true,
padding: true,
}" :checkbox-config="{
reserve: true,
highlight: true,
range: true,
checkMethod: ({ row }) => {
return parseFloat(row.hasPayNum) < parseFloat(row.num)
}
}" :row-config="{ keyField: 'id' }" :custom-config="{ mode: 'popup' }" :data="list">
<vxe-column type="checkbox" width="50" align="center"></vxe-column>
<vxe-column title="本次报销数量" width="120" align="center" field="payNum">
<template #default="{ row }">
<vxe-number-input v-if="parseFloat(row.hasPayNum) < parseFloat(row.num)" v-model="row.payNum" placeholder="数量"></vxe-number-input>
<div v-else>-</div>
</template>
</vxe-column>
<vxe-column title="已报销数量" width="100" align="center" field="hasPayNum">
</vxe-column>
<vxe-column align="center" v-for="item in table_item" :title="item.label" :field="item.prop"></vxe-column>
</vxe-table>
</div>
<template #footer>
<div style="margin-top: 20px;display: flex;justify-content: center;">
<el-button type="primary" size="small" @click="submit"> <i class="el-icon-arrow-right"></i> </el-button>
</div>
</template>
</vxe-modal>
<!-- <Modal
:width="86"
class-name="oa-modal"
title="流程办理"
fullscreen
:mask-closable="false"
v-model="isShowOaModal"
footer-hide
>
<div style="width: 100%;height: 100%;">
<iframe style="width: 100%;height: 100%;border-radius: 0 0 6px 6px;" :src="oaUrl" frameborder="0"></iframe>
</div>
</Modal> -->
</div>
</template>
<script>
import {
view,
fieldConfig
} from '@/api/flow'
import {
getItems,
detailContract,
getFundLog
} from '@/api/flow/pay'
import {
PopupManager
} from 'element-ui/lib/utils/popup'
import {
defaultModalSize
} from "@/settings";
export default {
props: {
isShow: {
type: Boolean,
default: false,
required: true
},
},
data() {
return {
payId: '',
defaultModalSize,
zIndex: PopupManager.nextZIndex(),
list: [],
table_item: [],
flowDetail: {},
fundlogForm:{
applyMoney:0,
type:'',
isLast:false,
},
paymentType: ["进度款", "结算款", "质保金"],
oaUrl:'',
isShowOaModal:false,
}
},
methods: {
async getConfig() {
const loading = this.$loading({
lock: true,
text: "拼命加载中",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.8)",
});
try {
const res = await view(this.payId);
const {
fields
} = res?.customModel;
this.flowDetail = res?.flow
const {
data
} = res?.flow
fields.forEach((field) => {
if (field.type === 'relation') {
//
this.list = JSON.parse(data[field.name])
this.list.map(item => {
item.payNum = 0
item.hasPayNum = 0
})
this.getItemNum(this.payId)
this.getFieldConfig(field.sub_custom_model_id)
}
});
console.log("this.list", this.list)
loading.close();
} catch (err) {
console.error(err)
this.$message.error("配置失败");
loading.close();
}
},
//
async getFieldConfig(id) {
try {
const res = await fieldConfig(id)
console.log("res", res)
const fields = res?.customModel?.fields
fields.forEach((field) => {
this.table_item.push({
label: field.label,
prop: field.name
})
});
} catch (err) {
console.error(err)
}
},
//
async getItemNum(id) {
try {
const item = await getItems({
flow_id: id
})
console.log("item",item)
if(item.length>0){
const itemMap = new Map();
item.forEach(item => {
itemMap.set(item.wuzicaigou_item_id, item.total_num);
});
// list id Map total_num hasPayNum
this.list.forEach(item => {
if (itemMap.has(item.id)) {
item.hasPayNum = itemMap.get(item.id);
}
});
}
} catch (err) {
console.error(err)
}
},
async submit() {
try {
if(!this.fundlogForm.applyMoney){
this.$message({
message: '请填写本次申请付款金额',
duration: 2000,
type: 'warning'
})
return
}
if(!this.fundlogForm.type){
this.$message({
message: '请选择款项类型',
duration: 2000,
type: 'warning'
})
return
}
const records = this.$refs.table.getCheckboxRecords()
console.log("records", records)
let count = 0
let totalCount = 0
if (records.length < 1) {
this.$message({
message: '请选择需要报销的明细',
duration: 2000,
type: 'warning'
})
return
}
records.map(item => {
if (parseFloat(item.payNum) === 0 || parseFloat(item.payNum) > parseFloat(item.num)) {
count++
}
if(parseFloat(item.payNum)+parseFloat(item.hasPayNum) > parseFloat(item.num)){
totalCount++
}
})
if (count > 0) {
this.$message({
message: '报销数量不能为0或报销数量大于总数量',
duration: 2000,
type: 'warning'
})
return
}
if (totalCount > 0) {
this.$message({
message: '本次报销数量大于剩余可报销数量',
duration: 2000,
type: 'warning'
})
return
}
//wuzicaigou_items
let wuzicaigou_items = []
let zhifutitle = ''
records.map(item=>{
wuzicaigou_items.push({
flow_id:this.payId,
wuzicaigou_id:item.belongs_id,
wuzicaigou_item_id:item.id,
name:item.pinminghuofuwuxuqiu,
num:item.payNum,
total:item.num
})
zhifutitle+= item.pinminghuofuwuxuqiu+'X'+item.payNum+','
})
//
let payments = [];
const actNumsTotal = () => {
return payments.reduce((pre, cur) => {
return pre + (!!Number(cur.act_money) ? Number(cur.act_money) : 0);
}, 0);
};
let contract;
if (this.flowDetail.out_contract_id) {
contract = await detailContract({
id: this.flowDetail.out_contract_id
});
}
payments =
(
await getFundLog({
contract_id: this.flowDetail.out_contract_id,
show_type: 1
})
)?.data || [];
//
zhifutitle = zhifutitle.slice(0,-1)
zhifutitle += ""+this.flowDetail.title+''
let baseInfo = {
"oaUrl": contract?.number,
"zhifutitle": zhifutitle,
// ?contract?.name
"contract_id":contract.id,
"type":this.fundlogForm.type,
"is_end":this.fundlogForm.isLast ? 1 : 0,
"amt": this.fundlogForm.applyMoney,
// out_pay_id: row?.id,
"xiangxishuoming": zhifutitle,
"yifujine": actNumsTotal(),
"xiangmuzonge": contract.money,
"zhifucishu": contract?.sign_plan?.length,
"cishu": payments.length,
"liezhiqudao": contract?.plans.map(i => i.name)?.toString(),
"contractno": contract?.number,
"guanlianliucheng": contract?.contract_flow_links?.map(i => i.flow_id)?.toString(),
"wuzicaigou_items":wuzicaigou_items
};
console.log(baseInfo,baseInfo)
let url = `/flow/create?&module_name=oa&isSinglePage=1&module_id=75&default_json=${window.encodeURIComponent(JSON.stringify(baseInfo))}`;
this.$router.push(
url
);
// this.oaUrl = url;
// this.isShowOaModal = true;
this.$emit('update:isShow',false)
} catch (err) {
console.error(err)
}
}
},
computed: {},
watch: {
isShow(newVal) {
if (newVal) {
this.zIndex = PopupManager.nextZIndex()
if (this.payId) {
this.getConfig()
}
} else {
this.list = []
this.payId = ''
this.oaUrl = ''
this.isShowOaModal = false
this.table_item = []
this.flowDetail = {}
this.fundlogForm = {
applyMoney:0,
type:'',
isLast:false,
}
this.$refs.table.clearCheckboxRow()
}
}
}
}
</script>
<style scoped lang="scss">
::v-deep .el-checkbox-group {
font-size: inherit;
}
</style>

@ -0,0 +1,943 @@
<template>
<div class="container">
<el-card
:shadow="device === 'desktop' ? 'always' : 'never'"
class="card"
:style="{
border: device === 'desktop' ? '' : 'none',
background: device === 'desktop' ? '' : '#f7f8fa',
'min-height': device === 'desktop' ? '' : '100vh',
}"
>
<template #header>
<p>{{ config.customModel ? config.customModel.name : "办理" }}</p>
</template>
<template>
<Steps :logs="config.logs" :current-node="node"></Steps>
<div class="form-container" id="print-content">
<DesktopForm
:device="device"
ref="desktopForm"
:config="config"
:is-first-node="isFirstNode"
:sub-form="subConfig"
:fields="fields"
:original-form="form"
:readable.sync="readableFields"
:script-content="scriptContent"
:writeable.sync="writeableFields"
:rules="rules"
:sub-rules="subRules"
:logs="config.logs"
></DesktopForm>
</div>
</template>
<!-- 审批日志-->
<div v-if="/\/detail/.test($route.path)" style="margin-top: 10px">
<div>流转记录</div>
<vxe-table
style="margin-top: 10px;"
show-footer
ref="table"
stripe
class="log-table-scroll"
keep-source
show-overflow
:column-config="{ resizable: true }"
:print-config="{}"
:export-config="{}"
:custom-config="{ mode: 'popup' }"
:footer-data="footerData"
:data="config.logs || []"
@cell-dblclick="cellDblclickEvent"
>
<vxe-column
type="seq"
width="62"
align="center"
field="seq"
title="编号"
/>
<vxe-column
width="140"
title="节点名称"
align="center"
field="node.name"
:formatter="({ cellValue }) => cellValue || '节点已调整'"
></vxe-column>
<vxe-column
width="80"
align="center"
title="办理状态"
field="status"
:formatter="({ cellValue }) => myStatus.get(cellValue)"
>
<template #default="{ row }">
<el-tag
size="mini"
:type="statusColor.get(row.status)"
effect="dark"
>{{ myStatus.get(row.status) }}</el-tag
>
</template>
</vxe-column>
<vxe-column
align="center"
width="80"
title="承办人员"
field="user.name"
></vxe-column>
<vxe-column
align="center"
width="200"
title="流转时间"
field="created_at"
:formatter="
({ cellValue }) =>
$moment(cellValue).format('YYYY年MM月DD日 HH:mm:ss')
"
></vxe-column>
<vxe-column
min-width="200"
header-align="center"
title="退回原因"
field="reason"
></vxe-column>
<vxe-column
align="center"
width="200"
title="办理时间"
field="updated_at"
>
<template #default="{ row }">
<span
:style="{
color:
row.deadline &&
row.updated_at &&
$moment(row.updated_at).isAfter(
$moment(row.deadline).endOf('day')
)
? 'red'
: '',
}"
>{{
$moment(row.updated_at).format("YYYY年MM月DD日 HH:mm:ss")
}}</span
>
</template>
</vxe-column>
<vxe-column align="center" title="耗时" field="use_time" width="120">
<template #default="{ row }">
<span>{{ diffTime(row.updated_at, row.created_at) }}</span>
</template>
</vxe-column>
</vxe-table>
</div>
<div class="btns" ref="btns">
<template v-if="!/\/detail/.test($route.path)">
<el-button
v-if="$route.query.flow_id"
icon="el-icon-arrow-left"
type="danger"
size="small"
@click="isShowRollback = true"
>退回</el-button
>
<el-button
v-if="$route.query.flow_id"
icon="el-icon-caret-right"
type="primary"
plain
size="small"
@click="isShowForward = true"
>部门内转办</el-button
>
<el-button
v-if="$route.query.flow_id"
icon="el-icon-document-add"
type="info"
size="small"
@click="submit('only-submit')"
>暂存不流转</el-button
>
<el-button type="primary" size="small" @click="submit('assign')"
>保存并流转 <i class="el-icon-right"></i
></el-button>
<el-button
v-if="!$route.query.flow_id"
type="info"
size="small"
@click="$router.go(-1)"
>返回</el-button
>
</template>
<template v-else>
<el-button
v-if="$store.state.user.adminId === 1 && $route.query.flow_id"
icon="el-icon-arrow-left"
type="danger"
size="small"
@click="isShowRollback = true"
>退回</el-button
>
<el-button plain size="small" @click="$router.go(-1)"></el-button>
<el-button plain size="small" @click="print(false)"></el-button>
<el-button plain size="small" @click="print(true)">()</el-button>
<el-button plain size="small">下载附件</el-button>
</template>
</div>
</el-card>
<assign
ref="assign"
:visible.sync="isShowAssign"
:config="config"
:result="result"
></assign>
<forward
ref="forward"
:is-show.sync="isShowForward"
:flow="config.flow"
></forward>
<rollback
ref="rollback"
:is-show.sync="isShowRollback"
:flow="config.flow"
></rollback>
<el-backtop></el-backtop>
</div>
</template>
<script>
import Steps from "./components/Steps.vue";
import DesktopForm from "./DesktopForm.vue";
import MobileForm from "./MobileForm.vue";
import assign from "./components/assign.vue";
import forward from "./components/forward.vue";
import rollback from "./components/rollback.vue";
import { generateRandomString } from '@/utils'
import {
create,
deal,
fieldConfig, flowList,
preConfig,
preDeal,
updateNodeTime,
view,
} from "@/api/flow";
import { deepCopy } from "@/utils";
import { validation, validationName } from "@/utils/validate";
import { print } from "@/utils/print";
import JSONBigint from 'json-bigint'
export default {
components: {
Steps,
DesktopForm,
MobileForm,
assign,
forward,
rollback,
},
data() {
return {
printKey: 0,
isShowRollback: false,
isShowForward: false,
isShowAssign: false,
info: [],
config: {},
writeableFields: [],
readableFields: [],
subConfig: new Map(),
myStatus: new Map([
[-2, "会签退回"],
[-1, "退回"],
[0, "办理中"],
[1, "已完成"],
]),
statusColor: new Map([
[-2, "warning"],
[-1, "warning"],
[0, ""],
[1, "success"],
]),
form: {},
result: {},
fileList: {},
subFileList: {},
rules: {},
subRules: {},
flows: [],
csrf_token: '',
};
},
methods: {
// urldefault_json
handleDefaultJSON() {
console.log("123")
try {
if(!this.$route.query?.default_json) return
const res = JSON.parse(this.$route.query?.default_json)
for (let key in this.$route.query) {
if(/^out_(.*)_id/.test(key)) {
this.form[key] = this.$route.query[key]
}
if(/^borrow_id/.test(key)) {
this.form[key] = this.$route.query[key]
}
}
for (let key in res) {
try {
let jsonObj = JSON.parse(res[key]);
if (this.form.hasOwnProperty(key)) {
this.form[key] = jsonObj;
}
} catch (err) {
if (this.form.hasOwnProperty(key)) {
this.form[key] = res[key];
}
}
}
} catch (err) {
console.error(err)
}
},
async print(isLog=false) {
const _this = this
let customModelId = this.config.customModel.id || this.$route.query.module_id
const modelRes = await fieldConfig(customModelId,true)
let pickTemplate = 0
const printTemplates = [{
id: 0,
name: '基础模版',
print_format: modelRes.customModel.print_format
},...modelRes.customModel.print_formats]
const h = this.$createElement;
await this.$msgbox({
title: '打印模版选择',
message: h('div',{
class: 'print-template-radios',
key: this.printKey++
},[
h('div',{
},printTemplates.map(i => h('div',{
style: {
display: 'flex',
'align-items': 'center',
'margin-top': '4px',
}
},[
h('span',{
class: 'el-radio__input'
},[
h('span', {
class: 'el-radio__inner custom-cursor-on-hover'
}),
h('input', {
style: {
cursor: 'pointer',
opacity: 0,
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
margin: 0
},
attrs: {
//
type: "radio",
id: `print-radio-${i.id}`,
name: "Radio",
value: i.id,
checked: pickTemplate === i.id,
},
on: {
change: () => {
pickTemplate = i.id
}
}
})
]),
h('label', {
style: {
flex: 1
},
attrs: {
for: `print-radio-${i.id}`
},
class: 'el-radio__label',
}, i.name)
])))
]),
showCancelButton: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
})
const printText = printTemplates.find(i => i.id === pickTemplate)?.print_format
if(isLog) {
const res = await this.$refs['table'].exportData({
type: 'html',
download: false
})
await print.bind(this)(printText, isLog, _this.config.flow, res.content)
} else {
await print.bind(this)(printText, isLog, _this.config.flow)
}
},
generateForm(object, fields, relation = false, pname) {
fields.forEach((field) => {
if (field.rules && field.rules.length > 0 && this.writeableFields.find(i => i === field.id) && !relation) {
this.rules[field.name] = field.rules.map((rule) => {
switch (rule) {
case "required":
if (field.type === 'relation') {
return {
validator: (myRule, value, callback) => {
if (value instanceof Array && value.length > 0) {
callback()
} else {
callback(`请填写${field.label}`)
}
},
message: `请填写${field.label}`,
trigger: "blur",
};
} else {
return {
required: true,
message: `请填写${field.label}`,
trigger: "blur",
};
}
default:
return {
validator: (myRule, value, callback) => {
if (validation.get(rule).test(value) || value === '') {
callback();
} else {
callback(
new Error(
`${field.label}必须为${validationName.get(rule)}`
)
);
}
},
trigger: "blur",
message: `${field.label}必须为${validationName.get(rule)}`,
};
}
});
}
if (relation) {
this.subRules[`${pname}_rules`][field.name] = field.rules.map((rule) => {
switch (rule) {
case "required":
return {
required: true,
message: `请填写${field.label}`,
};
default:
return {
validator: this.device === 'desktop' ? ({ cellValue }) => {
return new Promise((resolve, reject) => {
if (validation.get(rule).test(cellValue) || cellValue === '') {
resolve()
} else {
reject(
new Error(
`${field.label}必须为${validationName.get(rule)}`
)
);
}
})
} : (myRule, value, callback) => {
if (validation.get(rule).test(value) || value === '') {
callback();
} else {
callback(
new Error(
`${field.label}必须为${validationName.get(rule)}`
)
);
}
},
trigger: "blur",
pattern: validation.get(rule),
message: `${field.label}必须为${validationName.get(rule)}`,
};
}
});
}
if (field.type === "relation") {
this.subRules[`${field.name}_rules`] = {}
let temp = {}
this.subConfig.get(field.sub_custom_model_id)?.customModel?.fields?.forEach(field => temp[field.name] = '')
object[field.name] = [temp];
this.generateForm(
object[field.name][0],
this.subConfig.get(field.sub_custom_model_id)?.customModel?.fields,
true,
field.name
);
} else {
if (/\/detail/.test(this.$route.path) && this.$route.query.flow_id) {
object[field.name] = "";
} else {
if (this.writeableFields.indexOf(field.id) !== -1 || this.readableFields.indexOf(field.id) !== -1) {
object[field.name] = (this.writeableFields.indexOf(field.id) !== -1 && field.default_value) ? field.default_value : (field.type === 'file' ? [] : "");
}
}
}
});
this.form['flow_title'] = this.config?.flow?.title ?? `${this.config.customModel.name}${this.$store.getters.name} ${this.$moment().format('YYYY-MM-DD HH:mm')}`
},
formatTime(time) {
const days = parseInt(time / (1000 * 60 * 60 * 24));
const hours = parseInt((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = parseInt((time % (1000 * 60 * 60)) / (1000 * 60));
const seconds = (time % (1000 * 60)) / 1000;
return `${days > 0 ? days + "天" : ""}${
hours > 0 ? hours + "时" : ""
}${minutes}分${seconds}`;
},
async getConfig() {
const loading = this.$loading({
lock: true,
text: "拼命加载中",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.8)",
});
// detail
if (/\/detail/.test(this.$route.path) && this.$route.query.flow_id) {
try {
const res = await view(this.$route.query.flow_id);
const { fields } = res?.customModel;
let subFormRequest = [];
const getSubForm = (id) => {
subFormRequest.push(fieldConfig(id));
};
fields.forEach((field) => {
if (field.sub_custom_model_id) {
getSubForm(field.sub_custom_model_id);
}
});
const subConfigs = await Promise.all(subFormRequest);
subConfigs.forEach((sub) => {
if (sub.customModel?.id) {
this.subConfig.set(sub.customModel?.id, sub);
}
});
this.config = res;
this.readableFields = /\/detail/.test(this.$route.path)
? this.fields?.map((i) => i.id)
: this.config?.currentNode?.readable || [];
this.writeableFields = this.config?.currentNode?.writeable || [];
// form
this.generateForm(this.form, fields);
// form
const { data } = res?.flow;
for (let key in data) {
try {
let jsonObj = JSON.parse(data[key]);
jsonObj.forEach(item => {
//
for (const key in item) {
if (typeof item[key] === 'string') {
try {
// JSON
const parsedValue = JSONBigint({ storeAsString: true }).parse(item[key]);
//
item[key] = parsedValue;
} catch (e) {
//
}
}
}
})
if (this.form.hasOwnProperty(key)) {
this.form[key] = jsonObj;
}
} catch (err) {
if (this.form.hasOwnProperty(key)) {
if (data[key] instanceof Array) {
if (data[key].length > 0 && data[key][0].hasOwnProperty('url')) {
this.form[key] = data[key].map(i => ({
name: i.original_name,
url: i.url,
response: i,
}))
} else {
this.form[key] = ''
}
}
this.form[key] = data[key];
}
}
}
this.form = Object.assign({}, this.form);
loading.close();
} catch (err) {
console.error(err);
this.$message.error("配置失败");
loading.close();
}
} else if (!this.$route.query.flow_id) {
//
try {
this.csrf_token = generateRandomString()
const res = await preConfig(this.$route.query.module_id);
const { fields } = res?.customModel;
let subFormRequest = [];
const getSubForm = (id) => {
subFormRequest.push(fieldConfig(id));
};
fields.forEach((field) => {
if (field.sub_custom_model_id) {
getSubForm(field.sub_custom_model_id);
}
});
const subConfigs = await Promise.all(subFormRequest);
subConfigs.forEach((sub) => {
if (sub.customModel?.id) {
this.subConfig.set(sub.customModel?.id, sub);
}
});
this.config = res;
this.readableFields = /\/detail/.test(this.$route.path)
? this.fields?.map((i) => i.id)
: this.config?.currentNode?.readable || [];
this.writeableFields = this.config?.currentNode?.writeable || [];
this.generateForm(this.form, fields);
this.handleDefaultJSON();
this.form = Object.assign({}, this.form);
loading.close();
} catch (err) {
console.error(err);
this.$message.error("配置失败");
loading.close();
}
} else {
//
try {
const res = await preDeal(this.$route.query.flow_id);
const { fields } = res?.customModel;
let subFormRequest = [];
const getSubForm = (id) => {
subFormRequest.push(fieldConfig(id));
};
fields.forEach((field) => {
if (field.sub_custom_model_id) {
getSubForm(field.sub_custom_model_id);
}
});
const subConfigs = await Promise.all(subFormRequest);
subConfigs.forEach((sub) => {
if (sub.customModel?.id) {
this.subConfig.set(sub.customModel?.id, sub);
}
});
this.config = res;
this.readableFields = /\/detail/.test(this.$route.path)
? this.fields?.map((i) => i.id)
: this.config?.currentNode?.readable || [];
this.writeableFields = this.config?.currentNode?.writeable || [];
this.generateForm(this.form, fields);
this.handleDefaultJSON();
const { data } = res?.flow;
for (let key in data) {
try {
let jsonObj = JSON.parse(data[key]);
jsonObj.forEach(item => {
//
for (const key in item) {
if (typeof item[key] === 'string') {
try {
// JSON
const parsedValue = JSONBigint({ storeAsString: true }).parse(item[key]);
//
item[key] = parsedValue;
} catch (e) {
//
}
}
}
})
if (this.form.hasOwnProperty(key)) {
this.form[key] = jsonObj;
}
} catch (err) {
if (this.form.hasOwnProperty(key)) {
if (data[key] instanceof Array) {
if (data[key].length > 0) {
this.form[key] = data[key];
} else {
this.form[key] = ''
}
}
if (data[key] && data[key] !== 'null' && data[key] !== 'undefined') {
this.form[key] = data[key];
}
}
}
}
this.form = Object.assign({}, this.form);
loading.close();
} catch (err) {
console.error(err);
this.$message.error("配置失败");
loading.close();
}
}
},
async submit(type) {
if (window.$_uploading) {
this.$message.warning("文件正在上传中")
return
}
let copyForm;
try {
await this.$refs['desktopForm'].validate()
} catch (err) {
console.warn(err)
this.$message.warning('数据校验失败')
return
}
copyForm = deepCopy(this.$refs["desktopForm"].form);
const uploadHandler = (form, fields) => {
let keys = Object.keys(form)
keys.forEach(key => {
if (form[key] instanceof Array) {
if (form[key].length > 0 && typeof form[key][0] === 'object') {
const myField = fields.find(field => field.name === key)
if (myField) {
if (myField.type === 'file') {
form[key] = form[key].map(i => i.hasOwnProperty('response') ? i.response : i)
} else {
form[key].forEach(i => {
uploadHandler(i, this.subConfig.get(myField.sub_custom_model_id)?.customModel?.fields)
})
}
}
} else if (form[key].length > 0) {
} else {
form[key] = ''
}
} else {
if (form[key] === 'null' || form[key] === 'undefined') {
form[key] = ''
}
}
})
}
console.log("copyForm",copyForm,this.fields)
console.log("this.writeableFields",this.writeableFields)
uploadHandler(copyForm, this.fields)
for (let key in copyForm) {
let myField = this.fields.find(i => i.name === key)
if (myField && this.writeableFields.indexOf(myField.id) === -1) {
delete copyForm[key]
}
}
copyForm["current_node_id"] = this.config.currentNode.id;
try {
let callback = () => {};
switch (type) {
case "only-submit":
if (this.$route.query.flow_id) {
copyForm["temporary_save"] = 1;
}
callback = () => this.$router.push("/flow/list/todo")
break;
case "assign":
if (this.$route.query.flow_id) {
copyForm["temporary_save"] = 0;
}
callback = () => (this.isShowAssign = true);
break;
}
console.log("copyForm",copyForm,this.$refs["desktopForm"].form)
// return
if (this.$route.query.flow_id) {
copyForm.id = this.$route.query.flow_id;
const { flow, is_last_handled_log } = await deal(
this.$route.query.flow_id,
copyForm
);
this.result = flow;
if (!is_last_handled_log) {
await this.$alert(
"办理成功,其他会签办理完成后,由最后办理的成员流转到下一节点。",
"提示",
{
showClose: false,
}
);
callback = () => this.$router.push("/flow/list/todo");
}
} else {
copyForm['csrf_token'] = this.csrf_token
this.result = await create(this.$route.query.module_id, copyForm);
}
callback();
} catch (err) {
console.error(err);
}
},
async cellDblclickEvent({ row, column }) {
// if(this.$store.state.user.username !== 'admin') return
if(column.field === 'created_at' || column.field === 'updated_at') {
this.$prompt('请输入时间', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^(?:19|20)[0-9][0-9]-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1])) (?:(?:[0-2][0-3])|(?:[0-1][0-9])):[0-5][0-9]:[0-5][0-9]$/,
inputErrorMessage: '时间格式不正确'
}).then(({ value }) => {
updateNodeTime({
id: row.id,
date: value,
date_type: column.field
}).then(_ => {
this.$message.success('更新成功')
this.getConfig()
})
})
}
},
},
computed: {
device() {
return this.$store.state.app.device;
},
fields() {
return this.config?.customModel?.fields || [];
},
// data
// readableFields() {
// return /\/detail/.test(this.$route.path)
// ? this.fields?.map((i) => i.id)
// : this.config?.currentNode?.readable || [];
// },
// writeableFields() {
// return this.config?.currentNode?.writeable || [];
// },
node() {
return this.config?.currentNode || {};
},
scriptContent() {
if (this.config?.customModel?.view_js && this.$route.query.flow_id && /\/detail/.test(this.$route.path)) {
return this.config?.customModel?.view_js;
} else if (this.config?.customModel?.js && !/\/detail/.test(this.$route.path)) {
return this.config?.customModel?.js;
}
},
diffTime() {
return function (end, start) {
const diff = this.$moment(end).diff(this.$moment(start));
return this.formatTime(diff);
};
},
footerData() {
const diff = this.$moment(this.config?.logs?.at(-1)?.updated_at).diff(
this.$moment(this.config?.logs?.at(0)?.created_at)
);
return [
{
seq: "总耗时",
use_time: this.formatTime(diff),
},
];
},
isFirstNode() {
return this.config?.logs?.length === 0 || this.config?.currentNode?.category === 'start'
}
},
created() {
this.getConfig();
},
mounted() {},
};
</script>
<style scoped lang="scss">
::v-deep .el-step__title {
font-size: 14px;
line-height: 1.5;
}
::v-deep .el-step__icon.is-icon {
border-radius: 100%;
box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
width: 36px;
height: 36px;
border: solid 2px;
}
::v-deep .el-step.is-center .el-step__line {
top: 50%;
}
::v-deep .el-card__header {
}
.container {
padding: 20px;
.card {
position: relative;
}
.btns {
display: flex;
justify-content: center;
margin-top: 10px;
flex-wrap: wrap;
}
}
.form-container {
}
@media (max-width: 768px) {
.container {
padding: 0;
}
.btns {
justify-content: space-evenly;
& > * {
margin: 4px 6px;
}
}
::v-deep .el-steps--horizontal {
display: flex;
flex-wrap: wrap;
}
}
</style>
<style lang="scss">
.log-table-scroll {
::-webkit-scrollbar {
height: 0;
}
}
.print-template-radios .el-radio__input:has(input[type=radio]:checked) .el-radio__inner {
border-color: var(--theme-color);
background: var(--theme-color);
&::after {
transform: translate(-50%,-50%) scale(1);
}
}
</style>

@ -452,7 +452,7 @@
<vxe-column
:visible="$store.getters.device === 'desktop'"
min-width="280"
min-width="360"
header-align="center"
field="operate"
title="操作"
@ -490,6 +490,12 @@
@click="destroy(row)"
>删除</el-button
>
<el-button
v-if="$route.params.type === 'handled' && row.custom_model_id===99 && row.status===1"
type="primary"
size="mini"
@click="toOutPay(row)"
>支付</el-button>
</template>
<template v-else>
<el-button
@ -536,6 +542,7 @@
</el-card>
<share ref="share" :is-show.sync="isShowShare" :flow="pickedFlow"></share>
<payMx ref="payMx" :is-show.sync="isShowPay" ></payMx>
<list-popover :is-show.sync="isShowListPopover" :id="listPopoverId" :pos="listPopoverPos" />
<multi-deal :is-show.sync="isShowMultiDeal" :deal-flows="multiDealFlows" @refresh="getList" />
<field-export ref="isShowFieldExport" :is-show.sync="isShowFieldExport" :select="select" />
@ -548,12 +555,15 @@ import moment from "moment/moment";
import ListPopover from "./components/ListPopover.vue";
import MultiDeal from "./components/MultiDeal.vue"
import share from "./components/share.vue";
import payMx from "./components/payMx.vue";
import FieldExport from "./components/FieldExport.vue";
import { departmentListNoAuth } from "@/api/common"
export default {
name: "flowList",
components: {
share,
payMx,
ListPopover,
MultiDeal,
FieldExport
@ -703,6 +713,7 @@ export default {
departments: [],
isShowShare: false,
isShowPay:false,
pickedFlow: {},
};
},
@ -726,6 +737,11 @@ export default {
console.error(err)
}
},
//
async toOutPay(row) {
this.$refs.payMx.payId = row.id
this.isShowPay = true
},
contextMenuClickEvent({ menu, row, column }) {
switch (menu.code) {
@ -785,6 +801,7 @@ export default {
this.isShowShare = true;
},
async toggleFav(row) {
try {
await toggleFav({

Loading…
Cancel
Save