|
@@ -1,30 +1,97 @@
|
|
|
<template>
|
|
|
- <m-dialog ref="dialog" :title="itemData.title + ' 规则配置'" width="1000px" @sure="onSure">
|
|
|
- <el-form ref="form" :model="formQuery" v-loading="loading">
|
|
|
- <m-table
|
|
|
- shadow="naver"
|
|
|
- :items="formQuery.items"
|
|
|
- :headers="headers"
|
|
|
- >
|
|
|
- <template #name="scope">
|
|
|
- <el-form-item
|
|
|
- :prop="`items.${scope.$index}.name`"
|
|
|
- >
|
|
|
- {{scope.row.name}}
|
|
|
+ <m-dialog ref="dialog" title="规则配置" width="1000px" @sure="onSure">
|
|
|
+ <el-form ref="form" v-loading="loading" label-width="100px">
|
|
|
+ <el-form-item label="名称">
|
|
|
+ <el-tag color="primary">{{ itemData.title }}</el-tag>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="参数">
|
|
|
+ <m-card shadow="never">
|
|
|
+ <el-form-item label="参数分类">
|
|
|
+ <el-select v-model="paramsActive" placeholder="请选择参数分类">
|
|
|
+ <el-option
|
|
|
+ v-for="category in categories"
|
|
|
+ :key="category"
|
|
|
+ :label="category"
|
|
|
+ :value="category"
|
|
|
+ >
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
</el-form-item>
|
|
|
- </template>
|
|
|
- <template #value="scope">
|
|
|
- <el-form-item
|
|
|
- :prop="`items.${scope.$index}.value`"
|
|
|
- :rules="{ required: true, message: '请填写配置数值', trigger: 'blur' }"
|
|
|
- >
|
|
|
- <el-input
|
|
|
- v-model="formQuery.items[scope.$index].value"
|
|
|
- placeholder="配置数值"
|
|
|
- ></el-input>
|
|
|
+ <el-form-item label="参数配置" class="mt-3">
|
|
|
+ <template #label>
|
|
|
+ <span>参数配置</span>
|
|
|
+ <el-tooltip class="item" effect="dark" content="复选框勾选代表启用项" placement="right">
|
|
|
+ <span class="el-icon-info"></span>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+ <m-table
|
|
|
+ shadow="never"
|
|
|
+ ref="table"
|
|
|
+ :items="paramsList"
|
|
|
+ :headers="headers"
|
|
|
+ >
|
|
|
+ <template #status-header>
|
|
|
+ <el-checkbox @change="onSelectAllChange"></el-checkbox>
|
|
|
+ 启用
|
|
|
+ </template>
|
|
|
+ <template #status="{ row }">
|
|
|
+ <el-checkbox v-model="row.status" @change="onSelectChange($event, row)"></el-checkbox>
|
|
|
+ </template>
|
|
|
+ <template #header>
|
|
|
+ <div class="tools">
|
|
|
+ <el-popover
|
|
|
+ placement="top"
|
|
|
+ width="500"
|
|
|
+ trigger="click"
|
|
|
+ >
|
|
|
+ <m-table
|
|
|
+ v-if="gridData.length > 0"
|
|
|
+ style="border: unset"
|
|
|
+ shadow="never"
|
|
|
+ height="250"
|
|
|
+ :items="gridData"
|
|
|
+ :headers="[
|
|
|
+ { label: '分类', prop: 'category' },
|
|
|
+ { label: '参数名称', prop: 'name' },
|
|
|
+ { label: '数值', prop: 'value', width: 100, align: 'center' }
|
|
|
+ ]"
|
|
|
+ ></m-table>
|
|
|
+ <el-empty v-else></el-empty>
|
|
|
+ <m-button slot="reference" type="orange" size="small">查看已选 {{ gridData.length }}</m-button>
|
|
|
+ </el-popover>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #value="{ row }">
|
|
|
+ <el-input-number size="mini" v-model="row.value" placeholder="请输入数值"></el-input-number>
|
|
|
+ </template>
|
|
|
+ </m-table>
|
|
|
</el-form-item>
|
|
|
- </template>
|
|
|
- </m-table>
|
|
|
+ </m-card>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="计算公式">
|
|
|
+ <m-card shadow="never">
|
|
|
+ <el-tree
|
|
|
+ :data="formula"
|
|
|
+ node-key="uuid"
|
|
|
+ ref="formulaTreeRefs"
|
|
|
+ default-expand-all
|
|
|
+ :expand-on-click-node="false"
|
|
|
+ >
|
|
|
+ <div class="custom-tree-node" slot-scope="{ data }">
|
|
|
+ <el-input size="small" v-model="data.content" placeholder="描述文字"></el-input>
|
|
|
+ <el-button class="ml-3" size="small" @click="onInsertAfter(data)">
|
|
|
+ 同级追加
|
|
|
+ </el-button>
|
|
|
+ <el-button class="ml-3" size="small" @click="onAppend(data)">
|
|
|
+ 插入下一级
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" @click="onRemove(data)">
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </el-tree>
|
|
|
+ </m-card>
|
|
|
+ </el-form-item>
|
|
|
</el-form>
|
|
|
</m-dialog>
|
|
|
</template>
|
|
@@ -33,6 +100,7 @@
|
|
|
import {
|
|
|
saveSolution,
|
|
|
getConfigPage,
|
|
|
+ getConfigCateGories,
|
|
|
getSolutionDetails
|
|
|
} from '@/api/salary'
|
|
|
|
|
@@ -40,68 +108,177 @@ export default {
|
|
|
name: 'salary-solution-rules',
|
|
|
data () {
|
|
|
return {
|
|
|
- formQuery: {
|
|
|
- items: []
|
|
|
- },
|
|
|
+ formula: [
|
|
|
+ {
|
|
|
+ uuid: '1',
|
|
|
+ content: null
|
|
|
+ }
|
|
|
+ ],
|
|
|
headers: [
|
|
|
- { label: '参数名称', prop: 'name', align: 'right', width: '500px' },
|
|
|
+ { label: '启用', prop: 'status', width: 80 },
|
|
|
+ { label: '参数名称', prop: 'name', align: 'left' },
|
|
|
{ label: '数值', prop: 'value' }
|
|
|
],
|
|
|
itemData: {},
|
|
|
options: [],
|
|
|
- loading: false
|
|
|
+ loading: false,
|
|
|
+ categories: [], // 所有分类
|
|
|
+ allParams: [], // 所有参数
|
|
|
+ paramsCategoryItems: {}, // 整合分类列表层级
|
|
|
+ paramsActive: null, // 已选value
|
|
|
+ paramsSelection: [] // 已选参数
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ paramsList () {
|
|
|
+ if (!this.paramsCategoryItems[this.paramsActive]) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
+ return this.paramsCategoryItems[this.paramsActive]
|
|
|
+ },
|
|
|
+ gridData () {
|
|
|
+ const _allParams = Object.values(this.paramsCategoryItems).flat()
|
|
|
+ if (_allParams.length === 0) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
+ return this.paramsSelection.map(e => {
|
|
|
+ const item = _allParams.find(item => item.name === e)
|
|
|
+ return {
|
|
|
+ name: item.name,
|
|
|
+ value: item.value ?? 0,
|
|
|
+ category: item.category
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
- async open (item) {
|
|
|
+ open (item) {
|
|
|
this.itemData = item
|
|
|
this.$refs.dialog.open()
|
|
|
this.loading = true
|
|
|
- try {
|
|
|
- const { data: detail } = await getSolutionDetails({
|
|
|
- performanceSolutionId: item.performanceSolutionId
|
|
|
- })
|
|
|
- console.log(detail)
|
|
|
- const { data } = await getConfigPage({
|
|
|
- size: 999,
|
|
|
- current: 1
|
|
|
- })
|
|
|
- this.formQuery.items = data.records.map(e => {
|
|
|
- return {
|
|
|
- name: e.name,
|
|
|
- value: detail.calculateConfigurations.find(_e => _e.name === e.name)?.value ?? e.value
|
|
|
+ this.$nextTick(async () => {
|
|
|
+ try {
|
|
|
+ // 获取所有分类
|
|
|
+ const { data: categories } = await getConfigCateGories({})
|
|
|
+ this.categories = categories
|
|
|
+ this.paramsActive = categories[0]
|
|
|
+ // 获取完整列表
|
|
|
+ const { data: allParams } = await getConfigPage({
|
|
|
+ size: 9999,
|
|
|
+ current: 1
|
|
|
+ })
|
|
|
+ this.allParams = allParams.records
|
|
|
+ const { data: detail } = await getSolutionDetails({
|
|
|
+ performanceSolutionId: item.performanceSolutionId
|
|
|
+ })
|
|
|
+ if (!detail.calculateFormulas.length) {
|
|
|
+ this.formula = [
|
|
|
+ { uuid: '1', content: null, sort: null }
|
|
|
+ ]
|
|
|
+ } else {
|
|
|
+ this.formula = detail.calculateFormulas
|
|
|
}
|
|
|
+ this.paramsSelection = detail.calculateConfigurations.map(e => e.name)
|
|
|
+
|
|
|
+ // 根据分类获取参数列表
|
|
|
+ this.paramsCategoryItems = categories.reduce((res, key) => {
|
|
|
+ res[key] = allParams.records.filter(item => item.category === key).map(e => {
|
|
|
+ return {
|
|
|
+ name: e.name,
|
|
|
+ value: e.value ?? 0,
|
|
|
+ category: e.category,
|
|
|
+ status: this.paramsSelection.includes(e.name)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return res
|
|
|
+ }, {})
|
|
|
+ } catch (error) {
|
|
|
+ this.$message.error(error)
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onSelectChange (val, row) {
|
|
|
+ if (val) {
|
|
|
+ this.paramsSelection.push(row.name)
|
|
|
+ } else {
|
|
|
+ this.paramsSelection = this.paramsSelection.filter(e => e !== row.name)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onSelectAllChange (val) {
|
|
|
+ if (val) {
|
|
|
+ this.paramsSelection = this.paramsSelection.concat(this.paramsList.map(e => e.name)).flat()
|
|
|
+ } else {
|
|
|
+ this.paramsSelection = this.paramsSelection.filter(e => !this.paramsList.map(e => e.name).includes(e))
|
|
|
+ }
|
|
|
+ this.paramsList.forEach(e => {
|
|
|
+ e.status = val
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onRemove (data) {
|
|
|
+ this.$refs.formulaTreeRefs.remove(data)
|
|
|
+ },
|
|
|
+ onInsertAfter (data) {
|
|
|
+ this.$refs.formulaTreeRefs.insertAfter({
|
|
|
+ uuid: Date.now(),
|
|
|
+ content: null
|
|
|
+ }, data)
|
|
|
+ },
|
|
|
+ onAppend (data) {
|
|
|
+ this.$refs.formulaTreeRefs.append({
|
|
|
+ uuid: Date.now(),
|
|
|
+ content: null
|
|
|
+ }, data)
|
|
|
+ },
|
|
|
+ async onSure () {
|
|
|
+ if (this.paramsSelection.length === 0) {
|
|
|
+ this.$message.error('请选择参数')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const calculateFormulas = removeUuidFromArrayTree(this.formula)
|
|
|
+ function removeUuidFromArrayTree (treeArray) {
|
|
|
+ return treeArray.map(node => {
|
|
|
+ // 删除当前节点的uuid
|
|
|
+ const { uuid, children, ...rest } = node
|
|
|
+
|
|
|
+ // 如果有子节点,递归处理
|
|
|
+ const cleanedNode = { ...rest }
|
|
|
+ if (children && Array.isArray(children) && children.length > 0) {
|
|
|
+ cleanedNode.children = removeUuidFromArrayTree(children)
|
|
|
+ }
|
|
|
+ return cleanedNode
|
|
|
})
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ await saveSolution({
|
|
|
+ entity: {
|
|
|
+ performanceSolutionId: this.itemData.performanceSolutionId
|
|
|
+ },
|
|
|
+ calculateConfigurations: this.gridData,
|
|
|
+ calculateFormulas
|
|
|
+ })
|
|
|
+ this.$refs.dialog.close()
|
|
|
+ this.$emit('refresh')
|
|
|
+ this.$message.success('保存成功')
|
|
|
} catch (error) {
|
|
|
this.$message.error(error)
|
|
|
- } finally {
|
|
|
- this.loading = false
|
|
|
}
|
|
|
- },
|
|
|
- onSure () {
|
|
|
- this.$refs.form.validate(async valid => {
|
|
|
- if (valid) {
|
|
|
- const query = {
|
|
|
- entity: {
|
|
|
- performanceSolutionId: this.itemData.performanceSolutionId
|
|
|
- },
|
|
|
- calculateConfigurations: this.formQuery.items
|
|
|
- }
|
|
|
- try {
|
|
|
- await saveSolution(query)
|
|
|
- this.$refs.dialog.close()
|
|
|
- this.$emit('refresh')
|
|
|
- this.$message.success('保存成功')
|
|
|
- } catch (error) {
|
|
|
- this.$message.error(error)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-
|
|
|
+::v-deep .el-tree-node__content {
|
|
|
+ height: 40px;
|
|
|
+}
|
|
|
+.text-gray {
|
|
|
+ color: grey;
|
|
|
+}
|
|
|
+.tools {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+}
|
|
|
</style>
|