2025-05-10 10:18:06 +08:00

612 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import {ElNotification} from "element-plus";
import {resourceDelete, resourceList, resourcePost, resourcePut, resourceGetAllItems} from "@/api/resource.js";
import {ref, toRaw} from "vue";
import {useRoute} from 'vue-router';
import LocalCache from "@/stores/localCache.js";
import empty from '@/components/restful/empty.vue';
import {getWhereConditionDesc} from "@/utils/string.js";
const cachedResource = LocalCache.getCache("resource");
const listRsp = ref({fields_desc: [], rows: []})
const listDataOK = ref(false)
const projectId = cachedResource.meta.projectId
const resource_raw_node = cachedResource;
const hasListPermit = resource_raw_node.meta.methods.get !== undefined && resource_raw_node.meta.methods.get === true;
const resource_url = cachedResource.meta.resource_url;
const fieldsDescInfo = ref([])
const whereFieldsDescInfo = ref([])
const calcElColSpan = ref(0)
const rows = ref([])
const rules = ref({})
const current_page = ref(1)
const page_size = ref(10)
const pageSizes = [10, 20, 50, 100]
const totalRowCount = ref(0)
const item = ref({
id: '',
number: 1,
})
// console.log("enter table, resource:", cachedResource)
const listData = async () => {
try {
let listParams = {
page_no: current_page.value,
page_len: page_size.value,
where_conditions: "",
}
console.log(`查询页:${listParams.page_no},查询页大小:${listParams.page_len}`)
let whereReqConditions = {
conditions: []
}
whereFieldsDescInfo.value.forEach((field) => {
if (field.value1) {
whereReqConditions.conditions.push({
key: field.key,
op: field.where,
value1: field.value1,
value2: field.value2,
})
}
})
listParams.where_conditions = JSON.stringify(whereReqConditions)
// console.log("list params:", listParams)
const rspData = await resourceList(resource_url, listParams);
listRsp.value = rspData;
if (listRsp.value.code !== 200) throw new Error("请求失败,错误码:", listRsp.code);
fieldsDescInfo.value = listRsp.value.data.fields_desc
totalRowCount.value = listRsp.value.data.total_count
rows.value = listRsp.value.data.rows
for (let i = 0; i < fieldsDescInfo.value.length; i++) {
var field = fieldsDescInfo.value[i]
dialogObjectForm.value[field.key] = ''
if (field.required == true) {
rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
}
if (field.type == "items") {
dialogObjectForm.value[field.key] = []
for (let j = 0; j < rows.value.length; j++) {
rows.value[j].jsonValue = JSON.stringify(rows.value[j][field.key])
}
}
if (field.where !== "") {
field.value1 = ""
field.value2 = ""
field.whereDesc = getWhereConditionDesc(field.where)
let find = false
for (let i = 0; i < whereFieldsDescInfo.value.length; i++) {
let whereField = whereFieldsDescInfo.value[i]
if (whereField.key === field.key) {
whereFieldsDescInfo.value[i].type = field.type
whereFieldsDescInfo.value[i].where = field.where
whereFieldsDescInfo.value[i].whereDesc = getWhereConditionDesc(field.where)
find = true
break
}
}
if (!find) {
whereFieldsDescInfo.value.push(field)
}
}
}
calcElColSpan.value = 0
// 计算el-col占用24格子的span数量
let calcElColSpanTmp = 2
whereFieldsDescInfo.value.forEach((field) => {
if (field.where === "range") {
calcElColSpanTmp += 2
} else {
calcElColSpanTmp += 1
}
})
calcElColSpan.value = 24 / calcElColSpanTmp
// console.log("where fields:", whereFieldsDescInfo.value)
// console.log('await list rsp:', listRsp.value, fieldsDescInfo.value, toRaw(rows.value), toRaw(rules.value))
listDataOK.value = true
} catch (err) {
console.log(err)
} finally {
}
}
onMounted(() => {
listData();
})
const dialogAddVisible = ref(false)
const dialogEditVisible = ref(false)
const dialogAddFormRef = ref(null)
const dialogEditFormRef = ref(null)
const dialogObjectForm = ref({
ServerIDs: [],
Attach: [],
})
const submitAdd = async () => {
try {
await dialogAddFormRef.value.validate(valid => {
if (valid) {
console.log("commit add form:", dialogObjectForm.value)
resourcePost(resource_url, dialogObjectForm.value).then((res) => {
ElNotification({
title: "添加结果通知",
message: "添加成功!如果页面没有变化,刷新一下!",
type: 'success',
duration: 4000,
"show-close": true,
})
rows.value.push(res.data.dto)
dialogAddVisible.value = false
handleCloseDialog()
}, (err) => {
console.log("添加报错:", err)
})
console.log("提交数据:", dialogObjectForm.value)
}
})
} catch (error) {
console.log("校验失败:", error)
}
}
const submitEdit = async () => {
try {
await dialogEditFormRef.value.validate(valid => {
if (valid) {
const oldIndex = dialogObjectForm.value.oldIndex
const oldData = dialogObjectForm.value.oldData
// 这两句必须因为上一步点击编辑按钮把value = row然后把value.oldIndex = index
// 貌似会引起类字段循环引用,然后发送时候序列化造成死循环
delete dialogObjectForm.value.oldIndex
delete dialogObjectForm.value.oldData
resourcePut(resource_url, dialogObjectForm.value).then((res) => {
ElNotification({
title: "编辑结果通知",
message: "编辑成功!如果页面没有变化,刷新一下!",
type: 'success',
duration: 4000,
"show-close": true,
})
dialogEditVisible.value = false
rows.value[oldIndex] = res.data.dto
handleCloseDialog()
}, (err) => {
console.log("添加报错:", err)
})
console.log("提交数据:", dialogObjectForm.value)
}
})
} catch (error) {
console.log("校验失败:", error)
}
}
const handleEdit = (index, row) => {
dialogObjectForm.value = row
dialogObjectForm.value.oldData = row
dialogObjectForm.value.oldIndex = index
console.log("edit data:", row)
dialogEditVisible.value = true
}
const handleDelete = (index, row) => {
ElMessageBox.confirm("确定要删除吗?").then(() => {
resourceDelete(resource_url, {id: row.ID}).then((res) => {
ElNotification({
title: "删除结果通知",
message: "删除数据[" + row.ID + "]成功!如果页面没有变化,刷新一下!",
type: 'success',
duration: 4000,
"show-close": true,
})
rows.value.splice(index, 1)
}, (err) => {
console.log("delet error:", err)
})
}).catch(() => {
})
}
function addItem(fieldDescInfo) {
if (item.value.id == null || item.value.id == '' || item.value.id < 0) {
ElMessage('请选择道具!')
return;
}
if (item.value.num == null || item.value.num == '' || item.value.num <= 0) {
ElMessage('请输入有效道具数量!')
return;
}
let d = {id: item.value.id, num: Number(item.value.num), desc: item.value.desc, item_type: item.value.item_type};
console.log("add item:", d)
if (typeof dialogObjectForm.value.Attach === typeof "") {
dialogObjectForm.value.Attach = [];
}
dialogObjectForm.value.Attach.push(d);
}
function deleteItem(row) {
// 移除该对象
let number = dialogObjectForm.value.Attach.findIndex(item => item === row);
dialogObjectForm.value.Attach.splice(number, 1);
}
const handleCloseDialog = () => {
console.log("关闭添加/编辑弹窗")
dialogAddVisible.value = false
dialogEditVisible.value = false
dialogObjectForm.value = {
Attach: [],
}
item.value.desc = ''
}
const loadingRemoteItems = ref(false)
const itemChoices = ref({})
const handleItemOnSelect = (itemOption) => {
console.log("选中:", itemOption)
item.value.id = itemOption.value
item.value.desc = itemOption.desc
}
const handleQueryItem = (itemQueryStr) => {
if (!itemQueryStr) {
itemChoices.value = []
return
}
loadingRemoteItems.value = true
itemQueryStr = itemQueryStr.replace(/[\s\u3000]/g, "")
resourceGetAllItems(projectId).then((res) => {
console.log("获取所有道具返回:", res.data)
console.log("查询字符串:[" + itemQueryStr + "]")
itemChoices.value = res.data.items.filter((item) => {
return item.desc.includes(itemQueryStr)
})
loadingRemoteItems.value = false
}, (err) => {
itemChoices.value = []
})
}
const resetConditionSearch = () => {
for (let i = 0; i < whereFieldsDescInfo.value.length; i++) {
let field = whereFieldsDescInfo.value[i]
field.value1 = null
field.value2 = null
}
}
const handlePaginationSizeChange = (val) => {
// console.log(`${val} 大小改变`)
if (totalRowCount.value <= 0) {
return
}
if (page_size.value * current_page.value > totalRowCount.value) {
// 当总数据少于页数乘以页大小,就拒绝请求
return
}
// console.log(`${page_size.value} 大小改变`)
listData()
}
const handlePaginationCurChange = (val) => {
// console.log(`${val} 页面改变`)
listData()
}
</script>
<template>
<template v-if="!hasListPermit">
<component :is="empty"></component>
</template>
<template v-else>
<el-container v-if="listDataOK">
<el-header style="margin-bottom: 10px">
<el-row :gutter="20" v-if="(whereFieldsDescInfo.length !== 0)">
<template v-for="fieldDescInfo in whereFieldsDescInfo">
<template v-if="(fieldDescInfo.where === 'range')">
<el-col :span="calcElColSpan">
<el-date-picker v-model="fieldDescInfo.value1" type="datetime"
:placeholder="(fieldDescInfo.name + '起始')" format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
</el-col>
<el-col :span="calcElColSpan">
<el-date-picker v-model="fieldDescInfo.value2" type="datetime"
:placeholder="(fieldDescInfo.name + '结束')" format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
</el-col>
</template>
<template v-else>
<el-col :span="calcElColSpan">
<el-select v-model="fieldDescInfo.value1"
:placeholder="(fieldDescInfo.multi_choice === true ? '--' + fieldDescInfo.name + '--' : '--' + fieldDescInfo.name + '--')"
style="width: 150px"
filterable v-if="(fieldDescInfo.choices.length > 0)">
<el-option v-for="choice in fieldDescInfo.choices" :key="choice.value" :label="choice.desc"
:value="choice.value"></el-option>
</el-select>
<el-input v-model="fieldDescInfo.value1"
:placeholder="(fieldDescInfo.name + fieldDescInfo.whereDesc)"
style="width: 150px" v-else></el-input>
</el-col>
</template>
</template>
<el-col :span="calcElColSpan">
<el-button @click="listData" type="primary">条件搜索</el-button>
</el-col>
<el-col :span="calcElColSpan">
<el-button @click="resetConditionSearch">清空条件</el-button>
</el-col>
</el-row>
<el-row style="margin-top: 10px">
<el-button @click="dialogAddVisible = true" size="large" type="primary"
v-if="(resource_raw_node.meta.methods.post === true)">
添加
</el-button>
</el-row>
</el-header>
<el-main>
<el-table :data="rows" style="width: 100%" table-layout="auto" stripe>
<template v-for="fieldDescInfo in fieldsDescInfo">
<el-table-column prop="jsonValue" :label="fieldDescInfo.name" show-overflow-tooltip
v-if="(fieldDescInfo.type === 'items')"></el-table-column>
<el-table-column :prop="fieldDescInfo.key" :label="fieldDescInfo.name"
v-else></el-table-column>
</template>
<el-table-column prop="func" label="功 能">
<template #default="scope">
<el-button size="default" type="success" @click="handleEdit( scope.$index, scope.row)"
v-if="(resource_raw_node.meta.methods.put === true)">
<el-icon style="vertical-align: middle">
<Edit/>
</el-icon>
<span>编辑</span>
</el-button>
<el-button size="default" type="danger" @click="handleDelete( scope.$index, scope.row)"
v-if="(resource_raw_node.meta.methods.delete === true)">
<el-icon style="vertical-align: middle">
<Delete/>
</el-icon>
<span>删除</span>
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 表格数据分页 -->
<div class="demo-pagination-block">
<div class="demonstration"></div>
<el-pagination
v-model:current-page="current_page"
v-model:page-size="page_size"
:page-sizes="pageSizes"
layout="total, sizes, prev, pager, next, jumper"
:total="totalRowCount"
@size-change="handlePaginationSizeChange"
@current-change="handlePaginationCurChange"
/>
</div>
<el-dialog v-model="dialogAddVisible" :mask="true" title="添加" :modal="true" :before-close="handleCloseDialog"
destroy-on-close>
<el-form ref="dialogAddFormRef" :model="dialogObjectForm" :rules="rules" label-position="right"
label-width="130px">
<template v-for="fieldDescInfo in fieldsDescInfo">
<!--如何是items类型就是物品下拉框+道具组合-->
<template v-if="(fieldDescInfo.type === 'items')">
<el-form :inline="true" :model="item" label-position="right">
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key" label-width="130px">
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
<el-select v-model="item" placeholder="--搜索道具--" style="width: 150px"
filterable remote
:remote-method="handleQueryItem"
:loading="loadingRemoteItems"
value-key="value"
@change="handleItemOnSelect"
>
<el-option v-for="info in itemChoices" :key="info.value" :label="info.desc"
:value="info"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
<el-form-item label="数量" prop="num">
<el-input type="number" v-model="item.num" placeholder="请输入数量" style="width: 150px"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addItem(fieldDescInfo)">添加</el-button>
</el-form-item>
</el-form>
<el-form-item label="奖励列表" prop="Attach">
<el-table :data="dialogObjectForm.Attach" border>
<el-table-column label="道具id" prop="id"/>
<el-table-column label="数量" prop="num"/>
<el-table-column label="道具名" prop="desc"/>
<el-table-column label="操作">
<template #default="scope">
<el-button type="danger" size="small" @click="deleteItem(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</template>
<template v-else-if="(fieldDescInfo.readonly !== true)">
<!-- 有可选项的字段,走下拉框或者多选框 -->
<template v-if="(fieldDescInfo.choices !== undefined && fieldDescInfo.choices.length > 0)">
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
<el-select :placeholder="(fieldDescInfo.multi_choice === true ? '--多选--' : '--单选--')"
v-model="dialogObjectForm[fieldDescInfo.key]" style="width: 150px"
:multiple="(fieldDescInfo.multi_choice === true)">
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
:value="info.value"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</template>
<!-- 时间戳字段,展示时间选择器 -->
<template v-else-if="(fieldDescInfo.type === 'Time')">
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-date-picker v-model="dialogObjectForm[fieldDescInfo.key]" type="datetime"
placeholder="选个时间" format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
</el-form-item>
</template>
<!-- 否则就是普通字段 -->
<template v-else>
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-input v-model="dialogObjectForm[fieldDescInfo.key]"
:placeholder="fieldDescInfo.help_text"></el-input>
</el-form-item>
</template>
</template>
</template>
<el-form-item>
<el-button @click="submitAdd(dialogAddFormRef)" size="large" type="primary">提交</el-button>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog v-model="dialogEditVisible" :mask="true" title="编辑" :modal="true" :before-close="handleCloseDialog"
destroy-on-close>
<el-form ref="dialogEditFormRef" :model="dialogObjectForm" :rules="rules" class="operation_form"
label-width="130px">
<template v-for="fieldDescInfo in fieldsDescInfo">
<!--如果是items类型就是物品下拉框+道具组合-->
<template v-if="(fieldDescInfo.type === 'items')">
<el-form :inline="true" :model="item" label-position="right"
label-width="130px">
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
<el-select placeholder="--搜索道具--" v-model="item" style="width: 150px"
filterable remote :remote-method="handleQueryItem"
:loading="loadingRemoteItems"
value-key="value"
>
<el-option v-for="info in itemChoices" :key="info.value" :label="info.desc"
:value="info"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
<el-form-item label="数量" prop="number">
<el-input type="number" v-model="item.num" placeholder="请输入数量" style="width: 150px"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addItem(fieldDescInfo)">添加</el-button>
</el-form-item>
</el-form>
<el-form-item label="奖励列表" prop="attachmentsList">
<el-table :data="dialogObjectForm.Attach" border>
<el-table-column label="道具id" prop="id"/>
<el-table-column label="数量" prop="num"/>
<el-table-column label="道具名" prop="desc"/>
<el-table-column label="操作">
<template #default="scope">
<el-button type="danger" size="small" @click="deleteItem(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</template>
<template v-else-if="(fieldDescInfo.readonly !== true)">
<template v-if="(fieldDescInfo.uneditable !== true)">
<!-- 有可选项的字段走下拉框或者多选框 -->
<template v-if="(fieldDescInfo.choices !== undefined && fieldDescInfo.choices.length > 0)">
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
<el-select :placeholder="(fieldDescInfo.multi_choice === true ? '--多选--' : '--单选--')"
v-model="dialogObjectForm[fieldDescInfo.key]" style="width: 150px"
:multiple="(fieldDescInfo.multi_choice === true)">
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
:value="info.value"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</template>
<!-- 时间戳字段展示时间选择器 -->
<template v-else-if="(fieldDescInfo.type === 'Time')">
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-date-picker v-model="dialogObjectForm[fieldDescInfo.key]" type="datetime"
placeholder="选个时间" format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
</el-form-item>
</template>
<!-- 否则就是普通字段 -->
<template v-else>
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-input v-model="dialogObjectForm[fieldDescInfo.key]"
:placeholder="fieldDescInfo.help_text"></el-input>
</el-form-item>
</template>
</template>
<template v-else>
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
<el-input v-model="dialogObjectForm[fieldDescInfo.key]"
:placeholder="fieldDescInfo.help_text" disabled></el-input>
</el-form-item>
</template>
</template>
<!-- <el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">-->
<!-- <el-input v-model="dialogEditForm[fieldDescInfo.key]"></el-input>-->
<!-- </el-form-item>-->
</template>
<el-form-item>
<el-button @click="submitEdit(dialogEditFormRef)" size="large" type="primary">提交</el-button>
</el-form-item>
</el-form>
</el-dialog>
</el-main>
</el-container>
</template>
</template>
<style scoped lang="scss">
.demo-pagination-block {
margin-top: 10px;
.el-pagination {
right: 40px;
position: absolute;
}
}
</style>