This commit is contained in:
zmj 2024-05-25 16:49:50 +08:00
parent 31b52910c1
commit ba2e038e2f
8 changed files with 741 additions and 579 deletions

View File

@ -0,0 +1,109 @@
<template>
<el-form ref="formRef" :model="formData" label-width="90px" :rules="formRules">
<el-row>
<el-col :span="8" v-for="(item, index) in config" :key="index">
<el-form-item :label="item.label" v-if="item.type == 0" :prop="item.isRequired ? item.value : ''">
<el-input v-model="formData[item.value]" clearable :placeholder="'请输入' + item.label" />
</el-form-item>
<el-form-item :label="item.label" v-if="item.type == 1" :prop="item.isRequired ? item.value : ''">
<el-date-picker class="flex-1 !flex" v-model="formData[item.value]" clearable type="date"
value-format="YYYY-MM-DD" :placeholder="'请选择' + item.label">
</el-date-picker>
</el-form-item>
<el-form-item :label="item.label" v-if="item.type == 2" :prop="item.isRequired ? item.value : ''">
<el-select v-model="formData[item.value]" :placeholder="'请选择' + item.label" class="flex-1">
<el-option :label="item.name" :value="item.id" v-for="item in deptList">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="item.label" v-if="item.type == 3" :prop="item.isRequired ? item.value : ''">
<el-input v-model="formData[item.value + '_name']" readonly :placeholder="'点击选择' + item.label"
@click="userclick(item.value)" />
</el-form-item>
<el-form-item :label="item.label" v-if="item.type == 4" :prop="item.isRequired ? item.value : ''">
<el-input v-model="formData[item.value]" clearable type="textarea" :placeholder="'请输入' + item.label" />
</el-form-item>
<el-form-item :label="item.label" v-if="item.type == 5" :prop="item.isRequired ? item.value : ''">
<uploadAnnex :form-data="formData"></uploadAnnex>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div v-if="showPerDialog">
<personnelselector ref="personnel" @confirm="submituser" type="1">
</personnelselector>
</div>
</template>
<script setup >
import uploadAnnex from './../uploadAnnex/index.vue'
import { ref, reactive } from 'vue'
import { deptLists } from "@/api/org/department";
const props = defineProps({
config: {
type: Array,
required: true
},
})
const deptList = ref([])
const getDeptList = async () => {
const res = await deptLists()
deptList.value = res.lists
}
getDeptList()
const formData = reactive({})
//
const formRules = reactive({
});
const setRules = () => {
props.config.forEach(item => {
if (item.isRequired) {
formRules[item.value] = [
{
required: true,
message: "请输入" + item.label,
trigger: ["blur"],
},
]
}
})
}
setRules()
const showPerDialog = ref(false)
const personnel = ref(null)
let value
const userclick = async (val) => {
showPerDialog.value = true
value = val
await nextTick()
personnel.value.open()
}
const submituser = (e) => {
formData[value + '_name'] = e.name
formData[value] = e.id
showPerDialog.value = false
}
</script>

127
src/utils/pinyin.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,14 @@
import { isObject } from '@vue/shared'
import { cloneDeep } from 'lodash'
import { isObject } from "@vue/shared";
import { cloneDeep } from "lodash";
/**
* @description
* @param {String | Number} value 100
* @param {String} unit px em rem
*/
export const addUnit = (value: string | number, unit = 'px') => {
return !Object.is(Number(value), NaN) ? `${value}${unit}` : value
}
export const addUnit = (value: string | number, unit = "px") => {
return !Object.is(Number(value), NaN) ? `${value}${unit}` : value;
};
/**
* @description
@ -16,8 +16,8 @@ export const addUnit = (value: string | number, unit = 'px') => {
* @return {Boolean}
*/
export const isEmpty = (value: unknown) => {
return value == null && typeof value == 'undefined'
}
return value == null && typeof value == "undefined";
};
/**
* @description 广
@ -25,22 +25,22 @@ export const isEmpty = (value: unknown) => {
* @param {Object} props `{ children: 'children' }`
*/
export const treeToArray = (data: any[], props = { children: 'children' }) => {
data = cloneDeep(data)
const { children } = props
const newData = []
const queue: any[] = []
data.forEach((child: any) => queue.push(child))
while (queue.length) {
const item: any = queue.shift()
if (item[children]) {
item[children].forEach((child: any) => queue.push(child))
delete item[children]
}
newData.push(item)
export const treeToArray = (data: any[], props = { children: "children" }) => {
data = cloneDeep(data);
const { children } = props;
const newData = [];
const queue: any[] = [];
data.forEach((child: any) => queue.push(child));
while (queue.length) {
const item: any = queue.shift();
if (item[children]) {
item[children].forEach((child: any) => queue.push(child));
delete item[children];
}
return newData
}
newData.push(item);
}
return newData;
};
/**
* @description
@ -49,40 +49,40 @@ export const treeToArray = (data: any[], props = { children: 'children' }) => {
*/
export const arrayToTree = (
data: any[],
props = { id: 'id', parentId: 'pid', children: 'children' }
data: any[],
props = { id: "id", parentId: "pid", children: "children" }
) => {
data = cloneDeep(data)
const { id, parentId, children } = props
const result: any[] = []
const map = new Map()
data.forEach((item) => {
map.set(item[id], item)
const parent = map.get(item[parentId])
if (parent) {
parent[children] = parent[children] ?? []
parent[children].push(item)
} else {
result.push(item)
}
})
return result
}
data = cloneDeep(data);
const { id, parentId, children } = props;
const result: any[] = [];
const map = new Map();
data.forEach((item) => {
map.set(item[id], item);
const parent = map.get(item[parentId]);
if (parent) {
parent[children] = parent[children] ?? [];
parent[children].push(item);
} else {
result.push(item);
}
});
return result;
};
/**
* @description
* @param {String} path
*/
export function getNormalPath(path: string) {
if (path.length === 0 || !path || path == 'undefined') {
return path
}
const newPath = path.replace('//', '/')
const length = newPath.length
if (newPath[length - 1] === '/') {
return newPath.slice(0, length - 1)
}
return newPath
if (path.length === 0 || !path || path == "undefined") {
return path;
}
const newPath = path.replace("//", "/");
const length = newPath.length;
if (newPath[length - 1] === "/") {
return newPath.slice(0, length - 1);
}
return newPath;
}
/**
@ -91,25 +91,25 @@ export function getNormalPath(path: string) {
* @return {string} Query语法
*/
export function objectToQuery(params: Record<string, any>): string {
let query = ''
for (const props of Object.keys(params)) {
const value = params[props]
const part = encodeURIComponent(props) + '='
if (!isEmpty(value)) {
if (isObject(value)) {
for (const key of Object.keys(value)) {
if (!isEmpty(value[key])) {
const params = props + '[' + key + ']'
const subPart = encodeURIComponent(params) + '='
query += subPart + encodeURIComponent(value[key]) + '&'
}
}
} else {
query += part + encodeURIComponent(value) + '&'
}
let query = "";
for (const props of Object.keys(params)) {
const value = params[props];
const part = encodeURIComponent(props) + "=";
if (!isEmpty(value)) {
if (isObject(value)) {
for (const key of Object.keys(value)) {
if (!isEmpty(value[key])) {
const params = props + "[" + key + "]";
const subPart = encodeURIComponent(params) + "=";
query += subPart + encodeURIComponent(value[key]) + "&";
}
}
} else {
query += part + encodeURIComponent(value) + "&";
}
}
return query.slice(0, -1)
}
return query.slice(0, -1);
}
/**
@ -119,36 +119,36 @@ export function objectToQuery(params: Record<string, any>): string {
* @return { string }
*/
// yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合
export const timeFormat = (dateTime: number, fmt = 'yyyy-mm-dd') => {
// 如果为null,则格式化当前时间
if (!dateTime) {
dateTime = Number(new Date())
export const timeFormat = (dateTime: number, fmt = "yyyy-mm-dd") => {
// 如果为null,则格式化当前时间
if (!dateTime) {
dateTime = Number(new Date());
}
// 如果dateTime长度为10或者13则为秒和毫秒的时间戳如果超过13位则为其他的时间格式
if (dateTime.toString().length == 10) {
dateTime *= 1000;
}
const date = new Date(dateTime);
let ret;
const opt: any = {
"y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"h+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"s+": date.getSeconds().toString(), // 秒
};
for (const k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(
ret[1],
ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0")
);
}
// 如果dateTime长度为10或者13则为秒和毫秒的时间戳如果超过13位则为其他的时间格式
if (dateTime.toString().length == 10) {
dateTime *= 1000
}
const date = new Date(dateTime)
let ret
const opt: any = {
'y+': date.getFullYear().toString(), // 年
'm+': (date.getMonth() + 1).toString(), // 月
'd+': date.getDate().toString(), // 日
'h+': date.getHours().toString(), // 时
'M+': date.getMinutes().toString(), // 分
's+': date.getSeconds().toString() // 秒
}
for (const k in opt) {
ret = new RegExp('(' + k + ')').exec(fmt)
if (ret) {
fmt = fmt.replace(
ret[1],
ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
)
}
}
return fmt
}
}
return fmt;
};
/**
* @description id
@ -156,10 +156,10 @@ export const timeFormat = (dateTime: number, fmt = 'yyyy-mm-dd') => {
* @return { String } id
*/
export const getNonDuplicateID = (length = 8) => {
let idStr = Date.now().toString(36)
idStr += Math.random().toString(36).substring(3, length)
return idStr
}
let idStr = Date.now().toString(36);
idStr += Math.random().toString(36).substring(3, length);
return idStr;
};
/**
*
@ -167,183 +167,175 @@ export const getNonDuplicateID = (length = 8) => {
*/
export const toChinesNum = (money: any) => {
// 汉字的数字
const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
// 基本单位
const cnIntRadice = ['', '拾', '佰', '仟']
// 对应整数部分扩展单位
const cnIntUnits = ['', '万', '亿', '兆']
// 对应小数部分单位
const cnDecUnits = ['角', '分', '毫', '厘']
// 整数金额时后面跟的字符
const cnInteger = '整'
// 整型完以后的单位
const cnIntLast = '元'
// 最大处理的数字
const maxNum = 999999999999999.9999
// 金额整数部分
let integerNum
// 金额小数部分
let decimalNum
// 输出的中文金额字符串
let chineseStr = ''
// 分离金额后用的数组,预定义
let parts
if (money == '') {
return ''
}
money = parseFloat(money)
if (money >= maxNum) {
// 超出最大处理数字
return ''
}
if (money == 0) {
chineseStr = cnNums[0] + cnIntLast + cnInteger
return chineseStr
}
// 转换为字符串
money = money.toString()
if (money.indexOf('.') == -1) {
integerNum = money
decimalNum = ''
} else {
parts = money.split('.')
integerNum = parts[0]
decimalNum = parts[1].substr(0, 4)
}
// 获取整型部分转换
if (parseInt(integerNum, 10) > 0) {
let zeroCount = 0
const IntLen = integerNum.length
for (let i = 0; i < IntLen; i++) {
const n = integerNum.substr(i, 1)
const p = IntLen - i - 1
const q = p / 4
const m = p % 4
if (n == '0') {
zeroCount++
} else {
if (zeroCount > 0) {
chineseStr += cnNums[0]
}
// 归零
zeroCount = 0
chineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
}
if (m == 0 && zeroCount < 4) {
chineseStr += cnIntUnits[q]
}
// 汉字的数字
const cnNums = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
// 基本单位
const cnIntRadice = ["", "拾", "佰", "仟"];
// 对应整数部分扩展单位
const cnIntUnits = ["", "万", "亿", "兆"];
// 对应小数部分单位
const cnDecUnits = ["角", "分", "毫", "厘"];
// 整数金额时后面跟的字符
const cnInteger = "整";
// 整型完以后的单位
const cnIntLast = "元";
// 最大处理的数字
const maxNum = 999999999999999.9999;
// 金额整数部分
let integerNum;
// 金额小数部分
let decimalNum;
// 输出的中文金额字符串
let chineseStr = "";
// 分离金额后用的数组,预定义
let parts;
if (money == "") {
return "";
}
money = parseFloat(money);
if (money >= maxNum) {
// 超出最大处理数字
return "";
}
if (money == 0) {
chineseStr = cnNums[0] + cnIntLast + cnInteger;
return chineseStr;
}
// 转换为字符串
money = money.toString();
if (money.indexOf(".") == -1) {
integerNum = money;
decimalNum = "";
} else {
parts = money.split(".");
integerNum = parts[0];
decimalNum = parts[1].substr(0, 4);
}
// 获取整型部分转换
if (parseInt(integerNum, 10) > 0) {
let zeroCount = 0;
const IntLen = integerNum.length;
for (let i = 0; i < IntLen; i++) {
const n = integerNum.substr(i, 1);
const p = IntLen - i - 1;
const q = p / 4;
const m = p % 4;
if (n == "0") {
zeroCount++;
} else {
if (zeroCount > 0) {
chineseStr += cnNums[0];
}
chineseStr += cnIntLast
// 归零
zeroCount = 0;
chineseStr += cnNums[parseInt(n)] + cnIntRadice[m];
}
if (m == 0 && zeroCount < 4) {
chineseStr += cnIntUnits[q];
}
}
// 小数部分
if (decimalNum != '') {
const decLen = decimalNum.length
for (let i = 0; i < decLen; i++) {
const n = decimalNum.substr(i, 1)
if (n != '0') {
chineseStr += cnNums[Number(n)] + cnDecUnits[i]
}
}
chineseStr += cnIntLast;
}
// 小数部分
if (decimalNum != "") {
const decLen = decimalNum.length;
for (let i = 0; i < decLen; i++) {
const n = decimalNum.substr(i, 1);
if (n != "0") {
chineseStr += cnNums[Number(n)] + cnDecUnits[i];
}
}
if (chineseStr == '') {
chineseStr += cnNums[0] + cnIntLast + cnInteger
} else if (decimalNum == '') {
chineseStr += cnInteger
}
return chineseStr
}
}
if (chineseStr == "") {
chineseStr += cnNums[0] + cnIntLast + cnInteger;
} else if (decimalNum == "") {
chineseStr += cnInteger;
}
return chineseStr;
};
// 转换每个小节的函数
function convertSection(section) {
const cnNums = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
const cnIntUnits = ["", "拾", "佰", "仟"];
const cnNums = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
const cnIntUnits = ["", "拾", "佰", "仟"];
let sectionStr = "";
let unitPos = 0; // 记录当前位置的单位
let zero = true; // 连续的零
let sectionStr = "";
let unitPos = 0; // 记录当前位置的单位
let zero = true; // 连续的零
while (section > 0) {
let num = section % 10;
if (num === 0) {
if (!zero) {
zero = true;
sectionStr = cnNums[num] + sectionStr;
}
} else {
zero = false;
sectionStr = cnNums[num] + cnIntUnits[unitPos] + sectionStr;
while (section > 0) {
let num = section % 10;
if (num === 0) {
if (!zero) {
zero = true;
sectionStr = cnNums[num] + sectionStr;
}
section = Math.floor(section / 10);
unitPos++;
} else {
zero = false;
sectionStr = cnNums[num] + cnIntUnits[unitPos] + sectionStr;
}
return sectionStr;
section = Math.floor(section / 10);
unitPos++;
}
return sectionStr;
}
/**
*
* @params num
*/
export const convertToChinese = (num: any) => {
const cnNums = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
const cnIntUnits = ["", "拾", "佰", "仟"];
const cnDecUnits = ["角", "分"];
const cnInteger = "整";
const cnIntLast = "元";
const cnIntWan = "万";
const cnIntYi = "亿";
let integerNum = Math.floor(num); // 整数部分
let decimalNum = Math.round((num - integerNum) * 100); // 小数部分
let cnIntStr = ""; // 中文整数字符串
let cnDecStr = ""; // 中文小数字符串
// 处理亿位
let yuan = Math.floor(integerNum / 100000000);
if (yuan > 0) {
cnIntStr += convertSection(yuan) + cnIntYi;
integerNum %= 100000000;
}
// 处理万位
let wan = Math.floor(integerNum / 10000);
if (wan > 0) {
cnIntStr += convertSection(wan) + cnIntWan;
integerNum %= 10000;
}
// 处理其他部分
if (integerNum === 0) {
cnIntStr += cnNums[0];
} else {
cnIntStr += convertSection(integerNum);
}
// 处理小数部分
if (decimalNum === 0) {
cnDecStr = cnInteger;
} else {
let decIndex = 0;
while (decimalNum > 0 && decIndex < cnDecUnits.length) {
let num = decimalNum % 10;
if (num !== 0) {
cnDecStr += cnNums[num] + cnDecUnits[decIndex];
}
decimalNum = Math.floor(decimalNum / 10);
decIndex++;
const cnNums = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
const cnIntUnits = ["", "拾", "佰", "仟"];
const cnDecUnits = ["角", "分"];
const cnInteger = "整";
const cnIntLast = "元";
const cnIntWan = "万";
const cnIntYi = "亿";
let integerNum = Math.floor(num); // 整数部分
let decimalNum = Math.round((num - integerNum) * 100); // 小数部分
let cnIntStr = ""; // 中文整数字符串
let cnDecStr = ""; // 中文小数字符串
// 处理亿位
let yuan = Math.floor(integerNum / 100000000);
if (yuan > 0) {
cnIntStr += convertSection(yuan) + cnIntYi;
integerNum %= 100000000;
}
// 处理万位
let wan = Math.floor(integerNum / 10000);
if (wan > 0) {
cnIntStr += convertSection(wan) + cnIntWan;
integerNum %= 10000;
}
// 处理其他部分
if (integerNum === 0) {
cnIntStr += cnNums[0];
} else {
cnIntStr += convertSection(integerNum);
}
// 处理小数部分
if (decimalNum === 0) {
cnDecStr = cnInteger;
} else {
let decIndex = 0;
while (decimalNum > 0 && decIndex < cnDecUnits.length) {
let num = decimalNum % 10;
if (num !== 0) {
cnDecStr += cnNums[num] + cnDecUnits[decIndex];
}
decimalNum = Math.floor(decimalNum / 10);
decIndex++;
}
return cnIntStr + cnIntLast + cnDecStr;
}
}
return cnIntStr + cnIntLast + cnDecStr;
};

View File

@ -1,201 +1,6 @@
<!-- <template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="60vw" @confirm="handleSubmit"
@close="handleClose">
<el-form ref="formRef" :model="formData" label-width="120px" :rules="formRules">
<el-form-item label="审批流名称" prop="name">
<el-input v-model="formData.name" clearable placeholder="请输入审批流名称" />
</el-form-item>
<el-form-item label="流程类型" prop="check_type">
<el-select v-model="formData.check_type" clearable placeholder="请选择流程类型" class="flex-1">
<el-option label="可回退的审批流" :value="3" />
<el-option label="自由审批流" :value="2" />
<el-option label="固定审批流" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="应用模块" prop="type">
<el-input v-model="formData.type" clearable placeholder="请输入应用模块" />
</el-form-item>
<el-form-item label="应用审批类型id" prop="flow_cate">
<el-input v-model="formData.flow_cate" clearable placeholder="请输入应用审批类型id" />
</el-form-item>
<el-form-item label="应用部门">
<el-select v-model="formData.department_ids" multiple placeholder="请选择应用部门" class="flex-1">
<el-option :label="item.name" :value="parseInt(item.id)" v-for="item in deptList">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="抄送人" prop="copy_uids">
<el-input v-model="formData.copy_names" clearable placeholder="点击选择抄送人" @click="userclick" />
</el-form-item>
<el-form-item label="流程说明" prop="remark">
<el-input v-model="formData.remark" clearable placeholder="请输入流程说明" type="textarea" />
</el-form-item>
<el-form-item label="审批流程" prop="flow_list">
<el-input v-model="formData.flow_list" clearable placeholder="审批流程" />
</el-form-item>
</el-form>
<div v-if="showDialog">
<personnelselector ref="personnel" @confirm="submituser" type="2">
</personnelselector>
</div>
</popup>
</div>
</template>
<script lang="ts" setup name="oaFlowEdit">
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import { apiOaFlowAdd, apiOaFlowEdit, apiOaFlowDetail } from '@/api/oa_flow'
import { timeFormat } from '@/utils/util'
import type { PropType } from 'vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
},
deptList: Array
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
const showDialog = ref(false)
const personnel = ref(null)
//
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑审批流程表' : '新增审批流程表'
})
//
const formData = reactive({
id: '',
name: '',
check_type: '',
type: '',
flow_cate: '',
department_ids: '',
copy_uids: '',
copy_names: '',
remark: '',
flow_list: '',
})
const userclick = async () => {
showDialog.value = true
await nextTick()
personnel.value.open()
}
const submituser = (e: any) => {
formData.copy_uids = e.map((item: any) => {
return item.id
}).join(',')
formData.copy_names = e.map((item: any) => {
return item.name
}).join(',')
showDialog.value = false
}
//
const formRules = reactive<any>({
name: [{
required: true,
message: '请输入审批流名称',
trigger: ['blur']
}],
check_type: [{
required: true,
message: '请输入流程类型',
trigger: ['blur']
}],
type: [{
required: true,
message: '请输入应用模块',
trigger: ['blur']
}],
flow_cate: [{
required: true,
message: '请输入应用审批类型id',
trigger: ['blur']
}],
department_ids: [{
required: true,
message: '请输入应用部门ID',
trigger: ['blur']
}],
copy_uids: [{
required: true,
message: '请选择抄送人',
trigger: ['change']
}],
remark: [{
required: true,
message: '请输入流程说明',
trigger: ['blur']
}]
})
//
const setFormData = async (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
formData.department_ids = formData.department_ids.split(",").map(Number);
}
const getDetail = async (row: Record<string, any>) => {
const data = await apiOaFlowDetail({
id: row.id
})
setFormData(data)
}
//
const handleSubmit = async () => {
await formRef.value?.validate()
const data = { ...formData, }
data.department_ids = data.department_ids.join(",");
mode.value == 'edit'
? await apiOaFlowEdit(data)
: await apiOaFlowAdd(data)
popupRef.value?.close()
emit('success')
}
//
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
//
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData,
getDetail
})
</script> -->
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="80vw" @confirm="handleSubmit"
@close="handleClose">
<popup ref="popupRef" :title="popupTitle" :async="true" width="80vw" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
<el-row>
<el-col :span="8">
@ -205,7 +10,7 @@ defineExpose({
</el-col>
<el-col :span="8">
<el-form-item label="应用模块" prop="type">
<el-select v-model="formData.type" clearable placeholder="请选择所属分类" class="flex-1">
<el-select v-model="formData.type" clearable placeholder="请选择应用模块" class="flex-1">
<el-option v-for="item in dictData.oa_approve_cate" :key="item.value" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
@ -219,7 +24,9 @@ defineExpose({
</el-col>
<el-col :span="8">
<el-form-item label="应用部门">
<el-select v-model="formData.department_ids" multiple placeholder="请选择应用部门" class="flex-1">
<el-select v-model="formData.department_ids" multiple placeholder="请选择应用部门,不选默认为全公司"
class="flex-1">
<el-option label="全公司" :value="parseInt(0)"></el-option>
<el-option :label="item.name" :value="parseInt(item.id)" v-for="item in deptList">
</el-option>
</el-select>
@ -240,39 +47,38 @@ defineExpose({
</el-form-item>
</el-col>
</el-row>
<p v-if="formData.check_type == 1">
<div v-if="formData.check_type == 1">
<el-row v-for="(item, index) in formData.flow_list">
<el-col :span="8">
<el-form-item label="审批流程类型">
<el-select v-model="item.flow_type" clearable placeholder="请选择流程类型" class="flex-1">
<el-option label="当前部门负责人" :value="1" />
<el-option label="上一级部门负责人" :value="2" />
<el-option label="指定人员(多人或签)" :value="3" />
<el-option label="指定人员(多人会签)" :value="4" />
<el-option label="当前部门负责人" value="1" />
<el-option label="指定人员(多人或签)" value="2" />
<el-option label="指定人员(多人会签)" value="3" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" v-if="item.flow_type == '3' || item.flow_type == '4'">
<el-form-item label="指定人员">
<el-tag v-for="(tag, i) in item.flow_uids" @close="item.flow_user.splice(i, 1)"
:key="tag.id" class="mx-1" closable>
{{ tag.name }}
</el-tag>
<el-button type="primary" @click="openDialog(index)">
选择人员
</el-button>
<el-button @click="formData.flow_list.splice(index, 1)" class="ml-[5px]">
删除
</el-button>
</el-form-item>
</el-col>
<el-form-item label="指定人员" v-if="item.flow_type == '3' || item.flow_type == '2'">
<el-tag v-for="(tag, i) in item.flow_uids" @close="item.flow_uids.splice(i, 1)" :key="tag.id"
class="mx-1" closable>
{{ tag.name }}
</el-tag>
<el-button type="primary" @click="openDialog(index)">
选择人员
</el-button>
</el-form-item>
<el-form-item label="" label-width="45px">
<el-button @click="formData.flow_list.splice(index, 1)" class="ml-[5px]">
删除
</el-button>
</el-form-item>
</el-row>
<el-col :span="24">
<el-form-item>
<el-button type="primary" @click="handAdd">其他联系人</el-button>
</el-form-item>
</el-col>
</p>
</div>
<el-row v-if="formData.check_type == 2">
<el-col :span="12">
<el-form-item label="">
@ -280,7 +86,7 @@ defineExpose({
</el-form-item>
</el-col>
</el-row>
<p v-if="formData.check_type == 3">
<div v-if="formData.check_type == 3">
<el-row v-for="(item, index) in formData.flow_list">
<el-col :span="8">
<el-form-item label="审批流程">
@ -288,30 +94,25 @@ defineExpose({
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="指定人员">
<el-tag v-for="(tag, i) in item.flow_uids" @close="item.flow_user.splice(i, 1)"
:key="tag.id" class="mx-1" closable>
{{ tag.name }}
</el-tag>
<el-button type="primary" @click="openDialog(index)">
选择人员
</el-button>
</el-form-item>
</el-col>
<el-col :span="4">
<el-button @click="formData.flow_list.splice(index, 1)">
删除
<el-form-item label="指定人员">
<el-tag v-for="(tag, i) in item.flow_uids" @close="item.flow_uids.splice(i, 1)" :key="tag.id"
class="mx-1" closable>
{{ tag.name }}
</el-tag>
<el-button type="primary" @click="openDialog(index)">
选择人员
</el-button>
</el-col>
</el-form-item>
<el-button @click="formData.flow_list.splice(index, 1)" class="ml-[5px]">
删除
</el-button>
</el-row>
<el-col :span="24">
<el-form-item>
<el-button type="primary" @click="handAdd">其他联系人</el-button>
</el-form-item>
</el-col>
</p>
</div>
<el-form-item label="抄送人" prop="copy_unames">
<el-tag v-for="(tag, index) in formData.copy_uids" @close="formData.copy_uids.splice(index, 1)"
:key="tag.id" class="mx-1" closable>
@ -327,21 +128,18 @@ defineExpose({
<dialogTable :config="oa_flow_type" @customEvent="customEvent" :query="{ type: formData.type }">
</dialogTable>
</el-dialog>
<personnelSelector v-if="showDiolg" ref="personnel" @confirm="submituser" />
<personnelSelector v-if="showPersonnel" ref="personnel" @confirm="submituser" />
</div>
</template>
<script lang="ts" setup name="flowEdit">
import type { FormInstance } from "element-plus";
import Popup from "@/components/popup/index.vue";
import { apiFlowAdd, apiFlowEdit } from "@/api/flow";
import { apiFlowTypeLists } from '@/api/flow_type'
import personnelSelector from '@/components/personnelselector/index.vue'
import { ref } from "vue"
import type { PropType } from "vue";
import { oa_flow_type } from "@/components/dialogTable/dialogTableConfig.ts"
import { apiOaFlowAdd, apiOaFlowEdit, apiOaFlowDetail } from '@/api/oa_flow'
import { apiOaFlowAdd, apiOaFlowEdit } from '@/api/oa_flow'
defineProps({
dictData: {
@ -357,7 +155,7 @@ const emit = defineEmits(["success", "close"]);
const formRef = shallowRef<FormInstance>();
const popupRef = shallowRef<InstanceType<typeof Popup>>();
const mode = ref("add");
const showDiolg = ref(false)
const showPersonnel = ref(false)
const showDialog = ref(false)
//
@ -387,7 +185,6 @@ const formData = reactive({
});
const customEvent = (e) => {
console.log(e)
formData.flow_cate = e.id
formData.flow_cate_name = e.title
showDialog.value = false
@ -404,18 +201,6 @@ const handAdd = () => {
}
//
const flowTypeList = reactive([])
const getFlowTypeList = async () => {
if (!formData.flow_type) return
let res = await apiFlowTypeLists({
type: formData.flow_type,
status: 2
})
Object.assign(flowTypeList, res.lists)
}
//
const checkTypeFn = () => {
@ -441,26 +226,32 @@ const setRules = () => {
}
})
}
setRules()
// setRules()
//
const setFormData = async (data: Record<any, any>) => {
if (data.department_ids == '0') {
data.department_ids = ''
} else {
data.department_ids = data.department_ids?.split(',').map(Number)
}
data.copy_uids = data.copy_uids?.split(',').map((item, i) => ({ id: item, name: data.copy_user_names?.split(',')[i] }))
if (data.flow_list) {
data.flow_list.forEach(item => {
item.flow_uids = item.flow_uids?.split(',').map((items, i) => ({ id: items, name: item.flow_user_names?.split(',')[i] }))
})
}
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key];
}
}
await getFlowTypeList()
formData.check_type = Number(formData.check_type)
formData.flow_type = Number(formData.flow_type)
};
//
const handleSubmit = async () => {
await formRef.value?.validate();
let data = { ...formData }
data.department_ids = data.department_ids.join(",")
data.copy_uids = formData.copy_uids.map(item => item.id).join(',')
@ -476,17 +267,22 @@ const handleSubmit = async () => {
emit("success");
};
// selectIndex-1,flow_list
let selectIndex: nmber;
const openDialog = async (index) => {
showPersonnel.value = true
await nextTick()
personnel.value?.open()
selectIndex = index
}
const submituser = (e) => {
if (selectIndex == -1) {
formData.copy_uids = e.map(item => ({ id: item.id, name: item.name }))
} else {
formData.flow_list[selectIndex].flow_uids = e.map(item => ({ id: item.id, name: item.name }))
}
showDiolg.value = false
}
const clearFlowUser = (index) => {
formData.flow_list[index].flow_user = []
showPersonnel.value = false
}
//
@ -500,14 +296,7 @@ const handleClose = () => {
emit("close");
};
// selectIndex-1,flow_list
let selectIndex: nmber;
const openDialog = async (index) => {
showDiolg.value = true
await nextTick()
personnel.value?.open()
selectIndex = index
}
defineExpose({
open,

View File

@ -6,10 +6,17 @@
<el-input class="w-[280px]" v-model="queryParams.name" clearable placeholder="请输入审批流名称" />
</el-form-item>
<el-form-item label="流程类型" prop="check_type">
<el-input class="w-[280px]" v-model="queryParams.check_type" clearable placeholder="请输入流程类型" />
<el-select class="w-[280px]" v-model="queryParams.check_type" clearable placeholder="请选择流程类型">
<el-option label="固定审批" :value="1" />
<el-option label="自由审批人" :value="2" />
<el-option label="可回退审批" :value="3" />
</el-select>
</el-form-item>
<el-form-item label="应用模块" prop="type">
<el-input class="w-[280px]" v-model="queryParams.type" clearable placeholder="请输入应用模块" />
<el-form-item label=" 应用模块" prop="type">
<el-select v-model="queryParams.type" clearable placeholder="请选择应用模块" class="flex-1">
<el-option v-for="item in dictData.oa_approve_cate" :key="item.value" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
@ -32,17 +39,15 @@
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="审批流名称" prop="name" show-overflow-tooltip />
<el-table-column label="流程类型" prop="check_type" show-overflow-tooltip />
<el-table-column label="应用模块" prop="type" show-overflow-tooltip />
<el-table-column label="应用审批类型id" prop="flow_cate" show-overflow-tooltip />
<el-table-column label="应用部门ID0为全部1,2,3" prop="department_ids" show-overflow-tooltip />
<el-table-column label="抄送人ID" prop="copy_uids" show-overflow-tooltip />
<el-table-column label="流程说明" prop="remark" show-overflow-tooltip />
<el-table-column label="流程数据序列化" prop="flow_list" show-overflow-tooltip />
<el-table-column label="流程类型" prop="check_type_text" show-overflow-tooltip />
<el-table-column label="应用模块" prop="type_text" show-overflow-tooltip />
<el-table-column label="应用审批类型" prop="flow_cate_name" show-overflow-tooltip />
<el-table-column label="应用部门" prop="department_names" show-overflow-tooltip />
<el-table-column label="抄送人" prop="copy_user_names" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button v-perms="['works.bgsp.oa_flow/edit']" type="primary" link
@click="handleEdit(row)">
@click="handleEdit(row.id)">
编辑
</el-button>
<el-button v-perms="['works.bgsp.oa_flow/delete']" type="danger" link
@ -65,8 +70,7 @@
<script lang="ts" setup name="oaFlowLists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { apiOaFlowLists, apiOaFlowDelete } from '@/api/oa_flow'
import { timeFormat } from '@/utils/util'
import { apiOaFlowLists, apiOaFlowDelete, apiOaFlowDetail } from '@/api/oa_flow'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
import { deptLists } from "@/api/org/department";
@ -108,11 +112,12 @@ const handleAdd = async () => {
}
//
const handleEdit = async (data: any) => {
const handleEdit = async (id: number) => {
let res = await apiOaFlowDetail({ id })
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
editRef.value?.setFormData(res)
}
//

View File

@ -1,36 +1,100 @@
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="550px" @confirm="handleSubmit" @close="handleClose">
<popup ref="popupRef" :title="popupTitle" :async="true" width="60vw" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" label-width="90px" :rules="formRules">
<el-form-item label="所属分类" prop="type">
<el-select v-model="formData.type" clearable placeholder="请选择所属分类" class="flex-1">
<el-option v-for="item in dictData.oa_approve_cate" :key="item.value" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
<el-form-item label="审批名称" prop="title">
<el-input v-model="formData.title" clearable placeholder="请输入审批名称" />
</el-form-item>
<el-form-item label="审批标识" prop="name">
<el-input v-model="formData.name" clearable placeholder="请输入审批标识" />
</el-form-item>
<el-form-item label="图标">
<icon-picker class="flex-1" v-model="formData.icon" />
</el-form-item>
<el-form-item label="应用部门">
<el-select v-model="formData.department_ids" multiple placeholder="请选择应用部门" class="flex-1">
<el-option :label="item.name" :value="parseInt(item.id)" v-for="item in deptList">
</el-option>
</el-select>
</el-form-item>
<el-card>
<template #header>
审批类型
</template>
<el-row>
<el-col :span="8">
<el-form-item label="所属分类" prop="type">
<el-select v-model="formData.type" clearable placeholder="请选择所属分类" class="flex-1">
<el-option v-for="item in dictData.oa_approve_cate" :key="item.value" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="审批名称" prop="title">
<el-input v-model="formData.title" clearable placeholder="请输入审批名称" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="审批标识" prop="name">
<el-input v-model="formData.name" clearable placeholder="请输入审批标识" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="图标">
<icon-picker class="flex-1" v-model="formData.icon" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="应用部门">
<el-select v-model="formData.department_ids" multiple placeholder="请选择应用部门" class="flex-1">
<el-option :label="item.name" :value="parseInt(item.id)" v-for="item in deptList">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-card>
<el-card>
<template #header>
审批内容 <span style="color:#FF8F4A;font-size:12px">(该项用于指定审批所需要填写的具体内容)</span>
</template>
<el-col class="mb-5">
<el-button @click="handAdd" type="primary">
添加
</el-button>
<el-button @click="previewFn">
预览
</el-button>
</el-col>
<el-row v-for="(item, index) in formData.data" :key="index">
<el-col :span="8">
<el-form-item label="类型">
<el-select v-model="item.type" clearable placeholder="请选择所属类型" class="flex-1">
<el-option label="文本框" :value="parseInt(0)" />
<el-option label="日期选择框" :value="parseInt(1)" />
<el-option label="部门选择器" :value="parseInt(2)" />
<el-option label="人员选择器" :value="parseInt(3)" />
<el-option label="文本域" :value="parseInt(4)" />
<el-option label="文件上传" :value="parseInt(5)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="名称">
<el-input v-model="item.label" clearable placeholder="请输入名称" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="是否必填">
<el-switch v-model="item.isRequired"></el-switch>
</el-form-item>
</el-col>
<el-col :span="4">
<el-button @click="formData.data.splice(index, 1)">
删除
</el-button>
</el-col>
</el-row>
</el-card>
</el-form>
</popup>
<el-dialog v-if="showDialog" v-model="showDialog" title="预览审批内容" width="70%">
<generateForm :config="formData.data"></generateForm>
</el-dialog>
</div>
</template>
<script lang="ts" setup name="oaFlowTypeEdit">
import generateForm from './../../components/generateForm/index.vue'
import type { FormInstance } from "element-plus";
import Popup from "@/components/popup/index.vue";
import Pinyin from "@/utils/pinyin"
import {
apiOaFlowTypeAdd,
apiOaFlowTypeEdit,
@ -46,10 +110,13 @@ defineProps({
deptList: Array
});
// console.log(Pinyin.getCamelChars(""))
const emit = defineEmits(["success", "close"]);
const formRef = shallowRef<FormInstance>();
const popupRef = shallowRef<InstanceType<typeof Popup>>();
const mode = ref("add");
const showDialog = ref(false)
//
const popupTitle = computed(() => {
@ -64,6 +131,49 @@ const formData = reactive({
name: "",
icon: "",
department_ids: "",
data: [
{
"type": 0,
"label": "请假类型",
"value": "DZFS",
isRequired: true,
},
{
"type": 1,
"label": "开始时间",
"value": "SD",
isRequired: true,
},
{
"type": 1,
"label": "结束时间",
"value": "DSFSD",
isRequired: true,
},
{
"type": 0,
"label": "请假天数",
"value": "DSF",
isRequired: false,
},
{
"type": 4,
"label": "请假事由",
"value": "SDS",
isRequired: true,
},
{
"type": 5,
"label": "附件",
"value": "DZFS",
isRequired: false,
},
]
});
@ -124,6 +234,24 @@ const getDetail = async (row: Record<string, any>) => {
setFormData(data);
};
const previewFn = () => {
formData.data.forEach((item: any) => {
item.value = Pinyin.getCamelChars(item.label)
});
showDialog.value = true;
}
const handAdd = () => {
formData.data.push({
"type": 0,
"label": "",
"value": "",
isRequired: false,
})
}
//
const handleSubmit = async () => {
await formRef.value?.validate();

View File

@ -31,6 +31,7 @@
@click="handleDelete(selectData)">
删除
</el-button>
<div class="mt-4">
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
@ -38,13 +39,11 @@
<el-table-column label="审批名称" prop="title" show-overflow-tooltip />
<el-table-column label="审批标识" prop="name" show-overflow-tooltip />
<el-table-column label="图标" prop="icon" show-overflow-tooltip>
<template #default="{ row, $index }">
<!-- <template #default="{ row, $index }">
<el-icon :size="20" :id="'test' + $index">
<Edit />
<!-- {{ 'test' + $index"}} -->
<!-- {{ 'test' + $index }} -->
</el-icon>
</template>
</template> -->
</el-table-column>
<el-table-column label="应用部门" prop="department_names" show-overflow-tooltip>
<template #default="{ row }">
@ -77,7 +76,7 @@
<script lang="ts" setup name="oaFlowTypeLists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { apiOaFlowTypeLists, apiOaFlowTypeDelete } from '@/api/oa_flow_type'
import { apiOaFlowTypeLists, apiOaFlowTypeDelete, apiOaFlowTypeDetail } from '@/api/oa_flow_type'
import { timeFormat } from '@/utils/util'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
@ -88,6 +87,8 @@ const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const showEdit = ref(false)
const test = "<el-icon :size='20'> <Edit /> </el-icon>"
//
const queryParams = reactive({
type: '',
@ -121,10 +122,11 @@ const handleAdd = async () => {
//
const handleEdit = async (data: any) => {
let res = await apiOaFlowTypeDetail({ id: data.id })
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
editRef.value?.setFormData(res)
}
//

View File

@ -1,7 +1,7 @@
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="550px" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
<el-form ref="formRef" :model="formData" label-width="100px" :rules="formRules">
<el-form-item label="组织" prop="org_id">
<el-select clearable v-model="formData.org_id" placeholder="请选择组织" @change="area_change" class="flex-1">
<el-option v-for="(item, index) in orglist" :key="index" :label="item.name" :value="item.id" />
@ -13,6 +13,9 @@
<el-form-item label="联系电话" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="部门负责人" prop="leader_name">
<el-input v-model="formData.leader_name" placeholder="请选择部门负责人" @click="openDialog" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<div>
<el-input-number v-model="formData.sort" :min="0" :max="9999" />
@ -50,7 +53,7 @@ const formData = reactive({
id: '',
org_id: '' as string | number,
name: '',
leader: '',
leader_id: '',
leader_name: '',
mobile: '',
status: 1,
@ -58,7 +61,7 @@ const formData = reactive({
})
const submituser = (e) => {
formData.leader = e.id
formData.leader_id = e.id
formData.leader_name = e.name
showDiolg.value = false
}
@ -93,6 +96,13 @@ const formRules = {
trigger: ['blur']
}
],
leader_name: [
{
required: true,
message: '请输入部门名称',
trigger: ['change']
}
],
mobile: [
{