|
@@ -0,0 +1,209 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <el-dialog v-model="stageVisible" width="1000" :before-close="beForeCancel" :show-close="false" top="10vh">
|
|
|
+ <template #header="{ close, titleId, titleClass }">
|
|
|
+ <div class="flex justify-between items-center border-b pb-3 dialog-header">
|
|
|
+ <h4 :id="titleId">阶段设置</h4>
|
|
|
+ <div>
|
|
|
+ <el-button type="primary" @click="addStage(false)">新增</el-button>
|
|
|
+ <el-button type="primary" @click="saveState()" v-loading="allLoading.saveLoading">保存</el-button>
|
|
|
+ <el-button @click="cancel()">取消</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div class="h-[60vh] flex flex-col">
|
|
|
+ <div class="flex-1 w-full overflow-hidden">
|
|
|
+ <el-table :data="stageTableList" border v-loading="allLoading.tableLoading"
|
|
|
+ style="width: 100%;height: 100%;">
|
|
|
+ <el-table-column :prop="'seq'" :label="'顺序'" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.$index + 1 }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :prop="'name'" :label="'阶段名称'"></el-table-column>
|
|
|
+ <el-table-column :prop="'plan'" :label="'进度'" width="100"></el-table-column>
|
|
|
+ <el-table-column label="操作" fixed="right" width="200">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button link type="primary" size="large" @click="addStage(scope.row)">编辑</el-button>
|
|
|
+ <el-button link type="danger" size="large" @click="deteStage(+scope.$index)">删除</el-button>
|
|
|
+ <el-button link type="primary" size="large" @click="moveStage(+scope.$index, 'up')"
|
|
|
+ v-if="scope.$index != 0">上移</el-button>
|
|
|
+ <el-button link type="primary" size="large" @click="moveStage(+scope.$index, 'down')"
|
|
|
+ v-if="scope.$index < stageTableList.length - 1">下移</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 内层弹窗 -->
|
|
|
+ <el-dialog width="700px" v-model="allVisible.editVisible" append-to-body :show-close="false">
|
|
|
+ <template #header="{ close, titleId, titleClass }">
|
|
|
+ <div class="flex justify-between items-center border-b pb-3 dialog-header">
|
|
|
+ <h4 :id="titleId">添加阶段</h4>
|
|
|
+ <div>
|
|
|
+ <el-button type="primary" @click="editState(true)">保存并新增</el-button>
|
|
|
+ <el-button type="primary" @click="editState(false)">保存</el-button>
|
|
|
+ <el-button @click="allVisible.editVisible = false">取消</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div class="h-[120px] flex flex-col pt-5">
|
|
|
+ <div class="flex flex-row w-full items-center">
|
|
|
+ <div class="w-[100px] mr-2 text-right">阶段名称:</div>
|
|
|
+ <div class="flex-1">
|
|
|
+ <el-input v-model="stageForm.name" placeholder="请输入阶段名称" clearable></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-row w-full items-center pt-3">
|
|
|
+ <div class="w-[100px] mr-2 text-right">进度:</div>
|
|
|
+ <div class="flex-1">
|
|
|
+ <el-input-number v-model="stageForm.plan" controls-position="right" :min="0"
|
|
|
+ :max="100"></el-input-number>
|
|
|
+ <span class="inline-block ml-2">%</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+import { post } from '@/utils/request';
|
|
|
+import { ref, reactive, onMounted, watch, inject } from 'vue'
|
|
|
+import { BUSIESS_GETSATE, BUSIESS_SAVESAIE } from '../api';
|
|
|
+import { List } from 'echarts';
|
|
|
+
|
|
|
+type moveStageType = 'up' | 'down';
|
|
|
+type stageFormType = {
|
|
|
+ name: string,
|
|
|
+ plan: number,
|
|
|
+ seq: number,
|
|
|
+ id?: number,
|
|
|
+ isFinish?: number
|
|
|
+}
|
|
|
+
|
|
|
+const emits = defineEmits(['closeVisible']);
|
|
|
+const globalPopup = inject<GlobalPopup>('globalPopup')
|
|
|
+const stageVisible = ref(false)
|
|
|
+const stageTableList = ref<stageFormType[]>([])
|
|
|
+const allLoading = reactive({
|
|
|
+ editLoading: false,
|
|
|
+ saveLoading: false,
|
|
|
+ tableLoading: false
|
|
|
+})
|
|
|
+const allVisible = reactive({
|
|
|
+ editVisible: false,
|
|
|
+})
|
|
|
+const stageForm = reactive<stageFormType>({
|
|
|
+ name: '',
|
|
|
+ plan: 0,
|
|
|
+ seq: 0,
|
|
|
+})
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ visibles: boolean
|
|
|
+}>()
|
|
|
+
|
|
|
+watch(() => props.visibles, (newVal) => {
|
|
|
+ stageVisible.value = newVal
|
|
|
+ if (newVal) {
|
|
|
+ getTableList()
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+function saveState() {
|
|
|
+ let newList = JSON.parse(JSON.stringify(stageTableList.value))
|
|
|
+ let data = newList.map((item: stageFormType, index: number) => {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ seq: index
|
|
|
+ }
|
|
|
+ })
|
|
|
+ allLoading.saveLoading = true
|
|
|
+ post(BUSIESS_SAVESAIE, {list: JSON.stringify(data)}).then(() => {
|
|
|
+ globalPopup?.showSuccess('保存成功')
|
|
|
+ cancel()
|
|
|
+ }).finally(() => {
|
|
|
+ allLoading.saveLoading = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function editState(flag: boolean) {
|
|
|
+ if (!stageForm.name) {
|
|
|
+ globalPopup?.showWarning('请输入阶段名称')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ stageTableList.value.push({ ...stageForm })
|
|
|
+ if (flag) {
|
|
|
+ resetStage()
|
|
|
+ }
|
|
|
+ allVisible.editVisible = flag
|
|
|
+}
|
|
|
+
|
|
|
+function addStage(item: any) {
|
|
|
+ const row = JSON.parse(JSON.stringify(item))
|
|
|
+ if (!item) {
|
|
|
+ resetStage()
|
|
|
+ } else {
|
|
|
+ Object.assign(stageForm, {
|
|
|
+ name: row.name,
|
|
|
+ plan: row.plan,
|
|
|
+ seq: row.seq
|
|
|
+ })
|
|
|
+ }
|
|
|
+ allVisible.editVisible = true
|
|
|
+}
|
|
|
+
|
|
|
+function resetStage() {
|
|
|
+ let newData = JSON.parse(JSON.stringify(stageTableList.value))
|
|
|
+ let maxnum = newData.sort((a: any, b: any) => { return b.seq - a.seq; })[0];
|
|
|
+ Object.assign(stageForm, {
|
|
|
+ name: '',
|
|
|
+ plan: 0,
|
|
|
+ seq: +maxnum + 1
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function moveStage(index: number, stageType: moveStageType) {
|
|
|
+ const tableList = stageTableList.value
|
|
|
+ if (stageType == 'up') {
|
|
|
+ stageTableList.value = tableList.slice(0, index - 1).concat(tableList[index], tableList[index - 1], tableList.slice(index + 1))
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stageType == 'down') {
|
|
|
+ stageTableList.value = tableList.slice(0, index).concat(tableList[index + 1], tableList[index], tableList.slice(index + 2))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function deteStage(index: number) {
|
|
|
+ stageTableList.value.splice(index, 1)
|
|
|
+}
|
|
|
+
|
|
|
+function getTableList() {
|
|
|
+ allLoading.tableLoading = true
|
|
|
+ post(BUSIESS_GETSATE, {}).then((res) => {
|
|
|
+ const { data } = res
|
|
|
+ let newData = data || []
|
|
|
+ stageTableList.value = newData.sort(function (a: any, b: any) {
|
|
|
+ return a.seq - b.seq;
|
|
|
+ });
|
|
|
+ }).finally(() => {
|
|
|
+ allLoading.tableLoading = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function cancel() {
|
|
|
+ emits('closeVisible', 'stageSetVisible')
|
|
|
+}
|
|
|
+
|
|
|
+function beForeCancel(done: () => void) {
|
|
|
+ emits('closeVisible', 'stageSetVisible')
|
|
|
+ done()
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+});
|
|
|
+
|
|
|
+</script>
|
|
|
+<style scoped lang="scss"></style>
|