2 Commits 3280f2ad6a ... b0cada9922

Author SHA1 Message Date
  cm b0cada9922 解决冲突 1 year ago
  cm 7ef75a7082 GMFront 1 year ago

+ 159 - 0
src/api/player.ts

@@ -0,0 +1,159 @@
+import request from './request'
+
+
+export default {
+    queryPlayerInfo(data) {
+        return request({
+            url: '/player/info',
+            method: 'post',
+            data
+        });
+    },
+    editPlayerInfo(data) {
+        return request({
+            url: '/player/editInfo',
+            method: 'post',
+            data
+        });
+    },
+    editPlayerItem(data) {
+        return request({
+            url: '/player/editItem',
+            method: 'post',
+            data
+        });
+    },
+    delPlayerItem(data) {
+        return request({
+            url: '/player/delItem',
+            method: 'post',
+            data
+        });
+    },
+    addPlayerItem(data) {
+        return request({
+            url: '/player/addItem',
+            method: 'post',
+            data
+        });
+    },
+    resetMsa(data) {
+        return request({
+            url: '/player/resetMsa',
+            method: 'post',
+            data
+        });
+    },
+    completeMsa(data) {
+        return request({
+            url: '/player/completeMsa',
+            method: 'post',
+            data
+        });
+    },
+    delMsa(data) {
+        return request({
+            url: '/player/delMsa',
+            method: 'post',
+            data
+        });
+    },
+    addMsa(data) {
+        return request({
+            url: '/player/addMsa',
+            method: 'post',
+            data
+        });
+    },
+    delHrs(data) {
+        return request({
+            url: '/player/delHrs',
+            method: 'post',
+            data
+        });
+    },
+    addHrs(data) {
+        return request({
+            url: '/player/addHrs',
+            method: 'post',
+            data
+        });
+    },
+    editHrs(data) {
+        return request({
+            url: '/player/editHrs',
+            method: 'post',
+            data
+        });
+    },
+    addBps(data) {
+        return request({
+            url: '/player/addBps',
+            method: 'post',
+            data
+        });
+    },
+    delBps(data) {
+        return request({
+            url: '/player/delBps',
+            method: 'post',
+            data
+        });
+    },
+    makeBps(data) {
+        return request({
+            url: '/player/makeBps',
+            method: 'post',
+            data
+        });
+    },
+    getPart(data) {
+        return request({
+            url: '/player/getPart',
+            method: 'post',
+            data
+        });
+    },
+    saveRdm(data) {
+        return request({
+            url: '/player/saveRdm',
+            method: 'post',
+            data
+        });
+    },
+    delRls(data) {
+        return request({
+            url: '/player/delRls',
+            method: 'post',
+            data
+        });
+    },
+    getRls(data) {
+        return request({
+            url: '/player/getRls',
+            method: 'post',
+            data
+        });
+    },
+    rlsChangeLv(data) {
+        return request({
+            url: '/player/rlsChangeLv',
+            method: 'post',
+            data
+        });
+    },
+    addRelic(data) {
+        return request({
+            url: '/player/addRelic',
+            method: 'post',
+            data
+        });
+    },
+    editRelic(data) {
+        return request({
+            url: '/player/editRelic',
+            method: 'post',
+            data
+        });
+    },
+}

+ 22 - 0
src/common/date.js

@@ -0,0 +1,22 @@
+export function formatDate (date, fmt) {
+    if (/(y+)/.test(fmt)) {
+    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
+    }
+    let o = {
+    'M+': date.getMonth() + 1,
+    'd+': date.getDate(),
+    'h+': date.getHours(),
+    'm+': date.getMinutes(),
+    's+': date.getSeconds()
+    };
+    for (let k in o) {
+    if (new RegExp(`(${k})`).test(fmt)) {
+    let str = o[k] + '';
+    fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
+    }
+    }
+    return fmt;
+    };
+    function padLeftZero (str) {
+    return ('00' + str).substr(str.length);
+    };

+ 0 - 0
src/components/SearchForm/playerForm/index.vue


+ 358 - 0
src/components/player/BPInfo/index.vue

@@ -0,0 +1,358 @@
+<template>
+    <div class="container">
+        <!-- 搜索框 -->
+        <el-input v-model="search" placeholder="输入关键字" :maxlength="20" />
+
+        <el-button class="searchButton" @click="tableData()" type="primary">搜索</el-button>
+        <el-button class="addButton" @click="addBps()" type="primary">添加图纸</el-button>
+    </div>
+
+    <el-table :data="tableData()" class="table-container" :border="true">
+        <el-table-column prop="id" label="ID" class="centered-content" align="center" />
+        <el-table-column prop="bid" label="图纸ID" class="centered-content" align="center" />
+        <el-table-column prop="biId" label="道具ID" class="centered-content" align="center" />
+        <el-table-column prop="bty" label="图纸类型" class="centered-content" align="center">
+            <template #default="scope">
+                <span>{{ bpsTyeps[scope.row.bty] }}</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="btr" label="研发状态" class="centered-content" align="center">
+            <template #default="scope">
+                <span v-if="scope.row.btr">已研发</span>
+                <span v-else>未研发</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="btl" label="最后研发图纸" class="centered-content" align="center" />
+
+        <el-table-column label="操作" width="180" align="center">
+            <template #default="scope">
+                <span class="con">
+                    <el-button @click="editBps(scope.row)" @mouseenter="showText" @mouseleave="hideText" type="primary"
+                        :icon="Edit" class="button-container">
+                        <i class="icon"></i>
+                        <span class="text">制造</span>
+                    </el-button>
+
+                    <el-button @click="delBps(scope.row)" type="danger" :icon="Delete" class="button-container"
+                        @mouseenter="showText" @mouseleave="hideText">
+                        <i class="ic, resultPropson"></i>
+                        <span class="text">删除图纸</span>
+                    </el-button>
+                </span>
+
+            </template>
+        </el-table-column>
+    </el-table>
+
+    <el-pagination style="margin: auto;" class="pagination-container" background layout="prev, pager, next ,total,sizes"
+        :total="state.total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
+
+    <!-- 模态框 -->
+    <el-dialog :title="dialogTitle" v-model="showModal" @close="closeModal" width="350px">
+
+        <el-form-item label="图纸ID">
+            <el-input v-model="bpsId" placeholder="输入图纸ID" :maxlength="5" :disabled="!addDisabled"
+                style="width: 200px;position: relative; left: 41.219px;" />
+        </el-form-item>
+        <el-form-item label="研发状态">
+            <el-input v-model="bpsLv" placeholder="研发状态" :disabled="addDisabled" :maxlength="5"
+                style="width: 200px;position: relative; left: 28px;" />
+        </el-form-item>
+        <el-form-item label="最后研发图纸">
+            <el-input v-model="bpsAlv" placeholder="最后研发图纸" :disabled="addDisabled" :maxlength="5" style="width: 200px" />
+        </el-form-item>
+
+
+        <span slot="footer" class="dialog-footer" style="position: absolute; right: 20px; bottom: 10px;">
+            <el-button type="primary" @click="saveBps">保存</el-button>
+            <el-button @click="closeModal">关闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+<script lang="ts" setup>
+import { ElMessageBox, ElMessage, rowContextKey } from 'element-plus';
+import { reactive, ref, } from 'vue'
+import { Edit, Check, Close, Delete } from '@element-plus/icons-vue'
+import playerApi from '@/api/player'
+import { id } from 'element-plus/es/locale';
+
+const props = defineProps({
+    bps: Array,
+    ruleForm: Object,
+    callback: {
+        type: Function,
+        required: true
+    },
+    callback1: {
+        type: Function,
+        required: true
+    }
+});
+
+let dialogTitle = ref<string>('');
+
+const showModal = ref<Boolean>(false);
+const addDisabled = ref<Boolean>(true);
+const search = ref("");
+const bpsId = ref("");
+const bpsName = ref("");
+const bpsLv = ref<Number>();
+const bpsAlv = ref<Number>();
+
+const state = reactive({
+    page: 1,
+    limit: 10,
+    total: props.bps.length
+});
+
+const bpsTyeps = ['', '短柄', '长柄', '盾牌', '圣物', '法器', '弓箭', '枪炮', '', '', '', '秘石', '神器'];
+
+const tableData = () => {
+    let bps: any = [];
+    if (search.value == "") {
+        state.total = props.bps.length;
+        bps = props.bps;
+    } else {
+        const regex = new RegExp(search.value, 'i');
+        bps = props.bps.filter(
+            (item: { id: string, bid: String, biId: String }, index) => {
+                return regex.test(item.id) || regex.test(item.bid) || regex.test(item.biId);
+            }
+        );
+        state.total = bps.length;
+    }
+
+    return bps.filter(
+        (item, index) =>
+            index < state.page * state.limit &&
+            index >= state.limit * (state.page - 1)
+    );
+};
+
+const showText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'block';
+}
+
+const hideText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'none';
+}
+
+const closeModal = () => {
+    bpsId.value = null
+    bpsLv.value = null
+    bpsAlv.value = null
+    showModal.value = false;
+    dialogTitle.value = "添加图纸";
+}
+
+const addBps = () => {
+    dialogTitle.value = "添加图纸";
+    addDisabled.value = true;
+    showModal.value = true;
+}
+
+// 制造图纸
+const editBps = (row: any) => {
+    let data = {
+        playerId: props.ruleForm.id,
+        bluePrintId: row.bid
+    }
+
+    playerApi.makeBps(data).then((resp) => {
+        if (resp.data.result === '制造成功') {
+            ElMessage({
+                message: "制造成功",
+                type: 'success',
+                duration: 3000
+            });
+        } else {
+            ElMessage({
+                message: "制造失败",
+                type: 'error',
+                duration: 3000
+            });
+        }
+    });
+}
+
+// 保存
+const saveBps = () => {
+    if (addDisabled.value) { //默认添加图纸
+        let data = {
+            playerId: props.ruleForm.id,
+            bluePrintId: bpsId.value
+        }
+
+        playerApi.addBps(data).then((resp) => {
+            let data = resp.data.result;
+            props.callback(data);
+            ElMessage({
+                message: "添加成功",
+                type: 'success',
+                duration: 3000
+            });
+        });
+    } else {  // 修改英雄
+        let data = {
+            playerId: props.ruleForm.id,
+            heroID: hrsId.value,
+            heroLv: hrsLv.value,
+            heroAlv: hrsAlv.value
+        }
+
+        playerApi.editHrs(data).then((resp) => {
+            let result = resp.data.result;
+            if (result === '修改成功') {
+                props.callback1(data);
+                ElMessage({
+                    message: "修改成功",
+                    type: 'success',
+                    duration: 3000
+                });
+            } else {
+                ElMessage({
+                    message: "修改失败",
+                    type: 'error',
+                    duration: 3000
+                });
+            }
+        });
+    }
+    showModal.value = false;
+}
+
+// 删除图纸
+const delBps = (row: any) => {
+    ElMessageBox.confirm('确定要删除该图纸吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        let data = {
+            playerId: props.ruleForm.id,
+            bluePrintId: row.bid
+        }
+
+        playerApi.delBps(data).then((resp) => {
+            console.log(resp);
+
+            if (resp.data.result === '删除成功') {
+                ElMessage({
+                    message: "删除成功",
+                    type: 'success',
+                    duration: 3000
+                });
+                let index = props.bps.indexOf(row);
+                props.bps.splice(index, 1);
+            } else {
+                ElMessage({
+                    message: "删除失败",
+                    type: 'error',
+                    duration: 3000
+                });
+            }
+        });
+
+
+
+    }).catch(() => { });
+}
+
+// 分页
+
+const handleCurrentChange = (e) => {
+    state.page = e;
+};
+
+const handleSizeChange = (e) => {
+    state.limit = e;
+};
+
+</script>
+
+<style>
+.con {
+    display: flex;
+    align-items: center;
+}
+
+.button-container {
+    position: relative;
+    left: 10px;
+    transform: translateY(1%);
+    border-radius: 50%;
+    width: 30px;
+    height: 28px;
+}
+
+.input-container {
+    display: flex;
+    align-items: center;
+}
+
+.addButton {
+    position: absolute;
+    right: 5%;
+}
+
+.searchButton {
+    margin-right: 20px;
+    /* 调整搜索按钮的右侧间距 */
+}
+
+
+.button-container:hover {
+    border-radius: 10px;
+    width: 100px;
+}
+
+.button-container el-button {
+    margin-right: 10px;
+}
+
+.button-container el-button:last-child {
+    margin-right: 0;
+}
+
+.container {
+    display: flex;
+    align-items: center;
+    width: 200px;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.container .el-input {
+    margin-right: 10px;
+    /* 调整输入框的右边距 */
+}
+
+.edit-button {
+    position: absolute;
+    top: 50%;
+    left: 120px;
+    transform: translateY(-50%);
+}
+
+.table-container {
+    text-align: center;
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+}
+
+.pagination-container {
+    display: flex;
+    justify-content: center;
+}
+
+.centered-content {
+    text-align: center;
+}
+
+.text {
+    display: none;
+}
+</style>

+ 337 - 0
src/components/player/heroInfo/index.vue

@@ -0,0 +1,337 @@
+<template>
+    <div class="container">
+        <!-- 搜索框 -->
+        <el-input v-model="search" placeholder="输入关键字" :maxlength="20" />
+
+        <el-button class="searchButton" @click="tableData()" type="primary">搜索</el-button>
+        <el-button class="addButton" @click="addHrs()" type="primary">添加英雄</el-button>
+    </div>
+
+
+    <el-table :data="tableData()" class="table-container" :border="true">
+        <el-table-column prop="id" label="ID" class="centered-content" align="center" />
+        <!-- <el-table-column prop="name" label="英雄名称" class="centered-content" align="center"/> -->
+        <el-table-column prop="lv" label="英雄等级" class="centered-content" align="center" />
+        <el-table-column prop="alv" label="英雄星级" class="centered-content" align="center" />
+
+        <el-table-column label="操作" width="180" align="center">
+            <template #default="scope" >
+                <span class="con">
+                    <el-button @click="editHrs(scope.row)" @mouseenter="showText" @mouseleave="hideText" type="primary"
+                        :icon="Edit" class="button-container">
+                        <i class="icon"></i>
+                        <span class="text">修改英雄</span>
+                    </el-button>
+
+                    <el-button @click="delHrs(scope.row)" type="danger" :icon="Delete" class="button-container"
+                        @mouseenter="showText" @mouseleave="hideText">
+                        <i class="ic, resultPropson"></i>
+                        <span class="text">删除英雄</span>
+                    </el-button>
+                </span>
+
+            </template>
+        </el-table-column>
+    </el-table>
+
+    <el-pagination style="margin: auto;" class="pagination-container" background layout="prev, pager, next ,total,sizes"
+        :total="state.total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
+
+    <!-- 模态框 -->
+    <el-dialog :title="dialogTitle" v-model="showModal" @close="closeModal" width="350px">
+
+        <el-form-item label="英雄ID">
+            <el-input v-model="hrsId" placeholder="输入英雄ID" :maxlength="5" :disabled="!addDisabled"
+                style="width: 200px;position: relative; left: 41.219px;" />
+        </el-form-item>
+        <!-- <el-form-item label="英雄名称">
+            <el-input v-model="hrsName" placeholder="输入英雄名称" :disabled="true" :maxlength="5"
+                style="width: 200px;position: relative; left: 28px;" />
+        </el-form-item> -->
+        <el-form-item label="英雄等级">
+            <el-input v-model="hrsLv" placeholder="输入英雄等级" :disabled="addDisabled" :maxlength="5"
+                style="width: 200px;position: relative; left: 28px;" />
+        </el-form-item>
+        <el-form-item label="英雄觉醒等级">
+            <el-input v-model="hrsAlv" placeholder="输入英雄觉醒等级" :disabled="addDisabled" :maxlength="5" style="width: 200px" />
+        </el-form-item>
+
+
+        <span slot="footer" class="dialog-footer" style="position: absolute; right: 20px; bottom: 10px;">
+            <el-button type="primary" @click="saveHrs">保存</el-button>
+            <el-button @click="closeModal">关闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+<script lang="ts" setup>
+import { ElMessageBox, ElMessage, rowContextKey } from 'element-plus';
+import { reactive, ref, } from 'vue'
+import { Edit, Check, Close, Delete } from '@element-plus/icons-vue'
+import playerApi from '@/api/player'
+import { id } from 'element-plus/es/locale';
+
+const props = defineProps({
+    hrs: Array,
+    ruleForm: Object,
+    callback: {
+        type: Function,
+        required: true
+    },
+    callback1: {
+        type: Function,
+        required: true
+    }
+});
+
+let dialogTitle = ref<string>('');
+
+const showModal = ref<Boolean>(false);
+const addDisabled = ref<Boolean>(true);
+const search = ref("");
+
+const hrsId = ref("");
+const hrsName = ref("");
+const hrsLv = ref<Number>();
+const hrsAlv = ref<Number>();
+
+const state = reactive({
+    page: 1,
+    limit: 10,
+    total: props.hrs.length
+});
+
+
+
+const tableData = () => {
+    let hrs: any = [];
+    if (search.value == "") {
+        state.total = props.hrs.length;
+        hrs = props.hrs;
+    } else {
+        const regex = new RegExp(search.value, 'i');
+        hrs = props.hrs.filter(
+            (item: { id: string }, index) => {
+                return regex.test(item.id);
+            }
+        );
+        state.total = hrs.length;
+
+    }
+
+    return hrs.filter(
+        (item, index) =>
+            index < state.page * state.limit &&
+            index >= state.limit * (state.page - 1)
+    );
+};
+
+const showText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'block';
+}
+
+const hideText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'none';
+}
+
+
+const closeModal = () => {
+    hrsId.value = null
+    hrsLv.value = null
+    hrsAlv.value = null
+    showModal.value = false;
+    dialogTitle.value = "添加英雄";
+}
+
+const addHrs = () => {
+    dialogTitle.value = "添加英雄";
+    addDisabled.value = true;
+    showModal.value = true;
+}
+
+// 修改英雄
+const editHrs = (row: any) => {
+    dialogTitle.value = "修改英雄";
+    addDisabled.value = false;
+    showModal.value = true;
+
+    hrsId.value = row.id;
+    hrsLv.value = row.lv;
+    hrsAlv.value = row.alv;
+}
+
+// 保存
+const saveHrs = () => {
+    if (addDisabled.value) { //默认添加英雄
+        let data = {
+            playerId: props.ruleForm.id,
+            heroID: hrsId.value
+        }
+
+        playerApi.addHrs(data).then((resp) => {
+            console.log(resp);
+            let data = resp.data.result;
+            props.callback(data);
+            ElMessage({
+                message: "添加成功",
+                type: 'success',
+                duration: 3000
+            });
+        });
+    } else {  // 修改英雄
+        let data = {
+            playerId: props.ruleForm.id,
+            heroID: hrsId.value,
+            heroLv: hrsLv.value,
+            heroAlv: hrsAlv.value
+        }
+
+        playerApi.editHrs(data).then((resp) => {
+            let result = resp.data.result;
+            if (result === '修改成功') {
+                props.callback1(data);
+                ElMessage({
+                    message: "修改成功",
+                    type: 'success',
+                    duration: 3000
+                });
+            } else {
+                ElMessage({
+                    message: "修改失败",
+                    type: 'error',
+                    duration: 3000
+                });
+            }
+        });
+    }
+    showModal.value = false;
+}
+
+// 删除英雄
+const delHrs = (row: any) => {
+    ElMessageBox.confirm('确定要删除该英雄吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        let data = {
+            playerId: props.ruleForm.id,
+            heroID: row.id
+        }
+
+        playerApi.delHrs(data).then((resp) => {
+            if (resp.data.result === '删除成功') {
+                ElMessage({
+                    message: "删除成功",
+                    type: 'success',
+                    duration: 3000
+                });
+                let index = props.hrs.indexOf(row);
+                props.hrs.splice(index, 1);
+            } else {
+                ElMessage({
+                    message: "删除失败",
+                    type: 'error',
+                    duration: 3000
+                });
+            }
+        });
+
+
+
+    }).catch(() => { });
+}
+
+
+// 分页
+
+const handleCurrentChange = (e) => {
+    state.page = e;
+};
+
+const handleSizeChange = (e) => {
+    state.limit = e;
+};
+
+</script>
+
+<style>
+.con {
+    display: flex;
+    align-items: center;
+}
+
+.button-container {
+    position: relative;
+    left: 10px;
+    transform: translateY(1%);
+    border-radius: 50%;
+    width: 30px;
+    height: 28px;
+}
+
+.input-container {
+    display: flex;
+    align-items: center;
+}
+
+.addButton {
+    position: absolute;
+    right: 5%;
+}
+
+.searchButton {
+    margin-right: 20px;
+    /* 调整搜索按钮的右侧间距 */
+}
+
+
+.button-container:hover {
+    border-radius: 10px;
+    width: 100px;
+}
+
+.button-container el-button {
+    margin-right: 10px;
+}
+
+.button-container el-button:last-child {
+    margin-right: 0;
+}
+
+.container {
+    display: flex;
+    align-items: center;
+    width: 200px;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.edit-button {
+    position: absolute;
+    top: 50%;
+    left: 120px;
+    transform: translateY(-50%);
+}
+
+.table-container {
+    text-align: center;
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+}
+
+.pagination-container {
+    display: flex;
+    justify-content: center;
+}
+
+.centered-content {
+    text-align: center;
+}
+
+.text {
+    display: none;
+}
+</style>

+ 262 - 0
src/components/player/itemInfo/index.vue

@@ -0,0 +1,262 @@
+<template>
+    <div class="container">
+        <!-- 搜索框 -->
+        <el-input v-model="search" placeholder="输入关键字" :maxlength="20" />
+        <el-button class="searchButton" @Click="tableData()" type="primary">搜索</el-button>
+
+        <el-button class="addButton" @click="addItem()" type="primary">添加道具</el-button>
+    </div>
+
+    <el-table :data="tableData()" class="table-container" :border="true">
+        <el-table-column prop="id" label="ID" align="center" />
+        <el-table-column prop="bagTab" label="道具类型" align="center" />
+        <el-table-column prop="name" label="道具名称" align="center" />
+        <el-table-column prop="count" label="数量" align="center">
+            <template #default="scope">
+                <template v-if="!scope.row.editing">
+                    <span>{{ scope.row.count }}</span>
+                    <el-button @click="handlEditClick(scope.row)" type="primary" :icon="Edit" circle class="edit-button" />
+                </template>
+                <template v-else>
+                    <div class="con">
+                        <div class="input-container">
+                            <el-input v-model="scope.row.count" placeholder="count" />
+                        </div>
+                        <div class="button-container">
+                            <el-button @click="handleSaveClick(scope.row)" type="success" :icon="Check" circle />
+                            <el-button @click="handleCancelClick(scope.row)" type="danger" :icon="Close" circle />
+                        </div>
+                    </div>
+                </template>
+            </template>
+        </el-table-column>
+        <el-table-column label="操作" width="180" align="center">
+            <template #default="scope">
+                <el-button @click="editItem(scope.row)" type="danger" :icon="Delete">删除道具</el-button>
+            </template>
+        </el-table-column>
+    </el-table>
+
+    <el-pagination style="margin: auto;" class="pagination-container" background layout="prev, pager, next ,total,sizes"
+        :total="state.total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
+
+    <!-- 模态框 -->
+    <el-dialog :title="dialogTitle" v-model="showModal" @close="closeModal" width="350px">
+
+        <el-form-item label="道具ID">
+            <el-input v-model="itemId" placeholder="输入道具ID" :maxlength="5"
+                style="width: 200px;position: relative; left: 41.219px;" />
+        </el-form-item>
+        <el-form-item label="道具数量">
+            <el-input v-model="itemNum" placeholder="请输入道具数量" :maxlength="5"
+                style="width: 200px;position: relative; left: 28px;" />
+        </el-form-item>
+
+        <span slot="footer" class="dialog-footer" style="position: absolute; right: 20px; bottom: 10px;">
+            <el-button type="primary" @click="saveItem">保存</el-button>
+            <el-button @click="closeModal">关闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+<script lang="ts" setup>
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { reactive, ref, toRefs, defineComponent } from 'vue'
+import { Edit, Check, Close, Delete } from '@element-plus/icons-vue'
+import playerApi from '@/api/player'
+
+const props = defineProps({
+    its: Array,
+    ruleForm: Object,
+    callback: {
+        type: Function,
+        required: true
+    }
+});
+
+
+let dialogTitle = ref<string>('');
+
+const showModal = ref<Boolean>(false);
+const itemId = ref("");
+const itemNum = ref<Number>(1);
+const search = ref("");
+
+const state = reactive({
+    page: 1,
+    limit: 10,
+    total: props.its.length
+});
+
+const tableData = () => {
+    let its: any = [];
+    if (search.value == "") {
+        state.total = props.its.length;
+        its = props.its;
+    } else {
+        const regex = new RegExp(search.value, 'i');
+        its = props.its.filter(
+            (item: { id: string, name: string }, index) => {
+                return regex.test(item.id) || regex.test(item.name);
+            }
+        );
+        state.total = its.length;
+
+    }
+    
+    return its.filter(
+        (item, index) =>
+            index < state.page * state.limit &&
+            index >= state.limit * (state.page - 1)
+    );
+};
+
+// 分页
+// 删除道具
+const editItem = (row: any) => {
+    ElMessageBox.confirm('确定要删除该道具吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        let data = {
+            playerId: props.ruleForm.id,
+            itemId: row.id,
+            itemNum: row.count
+        }
+
+        let resp = playerApi.delPlayerItem(data);
+
+        ElMessage({
+            message: "删除成功",
+            type: 'info',
+            duration: 3000
+        });
+        let index = props.its.indexOf(row);
+        props.its.splice(index, 1);
+    }).catch(() => { });
+}
+
+const addItem = () => {
+    dialogTitle.value = "添加道具";
+    showModal.value = true;
+}
+
+const closeModal = () => {
+    itemId.value = null;
+    itemNum.value = 1;
+    showModal.value = false;
+    dialogTitle.value = "添加图纸";
+}
+
+// 保存
+const saveItem = () => {
+    let data = {
+        playerId: props.ruleForm.id,
+        itemId: itemId.value,
+        itemNum: itemNum.value
+    }
+
+    playerApi.addPlayerItem(data).then((resp) => {
+        let data = resp.data.result;
+        if (data === '道具添加失败') {
+            ElMessage({
+                message: "道具添加失败",
+                type: 'error',
+                duration: 3000
+            });
+        } else {
+            props.callback(data)
+        }
+    });
+
+    showModal.value = false;
+}
+
+const handleCurrentChange = (e) => {
+    state.page = e;
+};
+
+const handleSizeChange = (e) => {
+    state.limit = e;
+};
+
+
+// 道具修改
+const handlEditClick = (row: any) => {
+    row.editing = true;
+};
+
+const handleSaveClick = (row: any) => {
+    // row.editing = false;
+
+    ElMessageBox.confirm('确定要修改道具数量吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        row.editing = false;
+        let data = {
+            playerId: props.ruleForm.id,
+            itemId: row.id,
+            itemNum: row.count
+        }
+
+        let resp = playerApi.editPlayerItem(data);
+
+        ElMessage({
+            message: "修改成功",
+            type: 'info',
+            duration: 3000
+        });
+    }).catch(() => { });
+};
+
+const handleCancelClick = (row: any) => {
+    row.editing = false;
+};
+</script>
+
+<style>
+.con {
+    display: flex;
+    align-items: center;
+}
+
+.input-container {
+    align-items: center;
+    width: 200px;
+}
+
+
+.searchButton {
+    margin-right: 10px;
+}
+
+.button-container {
+    position: relative;
+    left: 10px;
+    transform: translateY(-8%);
+}
+
+.container {
+    display: flex;
+    align-items: center;
+    width: 200px;
+    margin-bottom: 20px;
+}
+
+.edit-button {
+    position: absolute;
+    top: 50%;
+    left: 400px;
+    transform: translateY(-50%);
+}
+
+.table-container {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+}
+
+.pagination-container {
+    display: flex;
+    justify-content: center;
+}
+</style>

+ 328 - 0
src/components/player/msaInfo/index.vue

@@ -0,0 +1,328 @@
+<template>
+    <div class="container">
+        <!-- 搜索框 -->
+        <el-input v-model="search" placeholder="输入关键字" :maxlength="20" />
+
+        <el-button class="searchButton" @click="tableData()" type="primary">搜索</el-button>
+        <el-button class="addButton" @click="showModal = true" type="primary">添加关卡</el-button>
+    </div>
+
+
+    <el-table :data="tableData()" class="table-container" :border="true">
+        <el-table-column prop="id" label="ID" class="centered-content" align="center" />
+        <el-table-column prop="msIc" label="关卡通过" class="centered-content" align="center">
+            <template #default="scope">
+                <span v-if="scope.row.msIc === true">通关</span>
+                <span v-else>未通关</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="msLc" label="关卡生命次数" class="centered-content" align="center" />
+        <el-table-column prop="sty" label="关卡类型" class="centered-content" align="center">
+            <template #default="scope">
+                <span v-if="scope.row.sty === 1">主线关卡</span>
+                <span v-else>支线关卡</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="msi" label="关卡道具" class="centered-content" align="center">
+            <template #default="scope">
+                <span v-if="scope.column.property === 'msi'">
+                    {{ JSON.stringify(scope.row[scope.column.property]) }}
+                </span>
+                <span v-else>{{ scope.row[scope.column.property] }}</span>
+            </template>
+        </el-table-column>
+        <el-table-column label="操作" width="280" align="center">
+            <template #default="scope" class="con">
+                <el-button @click="completeMsa(scope.row)" type="success" :icon="Check" class="button-container"
+                    @mouseenter="showText" @mouseleave="hideText">
+                    <i class="ic, resultPropson"></i>
+                    <span class="text">完成关卡</span>
+                </el-button>
+                <el-button @click="resetMsa(scope.row)" @mouseenter="showText" @mouseleave="hideText" type="primary"
+                    :icon="Refresh" class="button-container">
+                    <i class="icon"></i>
+                    <span class="text">重置关卡</span>
+                </el-button>
+                <el-button @click="delMsa(scope.row)" type="danger" :icon="Delete" class="button-container"
+                    @mouseenter="showText" @mouseleave="hideText">
+                    <i class="ic, resultPropson"></i>
+                    <span class="text">删除关卡</span>
+                </el-button>
+            </template>
+
+        </el-table-column>
+    </el-table>
+
+    <el-pagination style="margin: auto;" class="pagination-container" background layout="prev, pager, next ,total,sizes"
+        :total="state.total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
+
+    <!-- 模态框 -->
+    <el-dialog title="添加关卡" v-model="showModal" @close="closeModal" width="350px">
+        <el-form-item label="关卡ID">
+            <el-input v-model="msaId" placeholder="输入关卡ID" :maxlength="5"
+                style="width: 200px;position: relative; left: 41.219px;" />
+
+        </el-form-item>
+    
+        <span slot="footer" class="dialog-footer" style="position: absolute; right: 20px; bottom: 10px;">
+            <el-button type="primary" @click="addUsa">保存</el-button>
+            <el-button @click="closeModal">关闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+<script lang="ts" setup>
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { reactive, ref, toRefs, defineComponent, defineEmits, computed } from 'vue'
+import { Edit, Check, Close, Delete, Refresh } from '@element-plus/icons-vue'
+import playerApi from '@/api/player'
+
+const props = defineProps({
+    msa: Array,
+    ruleForm: Object,
+    callback: {
+        type: Function,
+        required: true
+    },
+    callback1: {
+        type: Function,
+        required: true
+    }
+});
+
+const showModal = ref<Boolean>(false);
+
+const search = ref("");
+
+const msaId = ref("");
+
+const state = reactive({
+    page: 1,
+    limit: 10,
+    total: props.msa.length
+});
+
+
+
+const tableData = () => {
+    let msa: any = [];
+    if (search.value == "") {
+        state.total = props.msa.length;
+        msa = props.msa;
+    } else {
+        const regex = new RegExp(search.value, 'i');
+        msa = props.msa.filter(
+            (item: { id: string }, index) => {
+                return regex.test(item.id);
+            }
+        );
+        state.total = msa.length;
+
+    }
+
+    return msa.filter(
+        (item, index) =>
+            index < state.page * state.limit &&
+            index >= state.limit * (state.page - 1)
+    );
+};
+
+const showText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'block';
+}
+
+const hideText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'none';
+}
+
+
+const closeModal = () => {
+    msaId.value = null
+    showModal.value = false;
+}
+
+const addUsa = () => {
+    let uhs = msaId.value;
+    if (uhs != "" || uhs != null) {
+        let data = {
+            playerId: props.ruleForm.id,
+            uhs: uhs
+        }
+
+        playerApi.addMsa(data).then((resp) => {
+            let data = resp.data.result;
+            props.callback(data);
+        });
+
+        ElMessage({
+            message: "添加成功",
+            type: 'success',
+            duration: 3000
+        });
+
+        msaId.value = null
+        showModal.value = false;
+    }
+}
+
+// 完成关卡
+const completeMsa = (row: any) => {
+    ElMessageBox.confirm('确定要完成该关卡吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        let data = {
+            playerId: props.ruleForm.id,
+            msaId: row.id
+        }
+
+        let resp = playerApi.completeMsa(data);
+        props.callback1(row);
+        ElMessage({
+            message: "完成关卡成功",
+            type: 'success',
+            duration: 3000
+        });
+        // let index = props.msa.indexOf(row);
+        // props.msa.splice(index, 1);
+    }).catch(() => { });
+}
+
+// 分页
+// 重置关卡
+const resetMsa = (row: any) => {
+    ElMessageBox.confirm('确定要重置该关卡吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        let data = {
+            playerId: props.ruleForm.id,
+            uhs: row.id
+        }
+
+        let resp = playerApi.resetMsa(data);
+        props.callback1(row);
+        ElMessage({
+            message: "重置成功",
+            type: 'success',
+            duration: 3000
+        });
+        // let index = props.msa.indexOf(row);
+        // props.msa.splice(index, 1);
+    }).catch(() => { });
+}
+
+// 删除关卡
+const delMsa = (row: any) => {
+    ElMessageBox.confirm('确定要删除该关卡吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        let data = {
+            playerId: props.ruleForm.id,
+            index: row.id
+        }
+
+        let resp = playerApi.delMsa(data);
+
+        ElMessage({
+            message: "删除成功",
+            type: 'success',
+            duration: 3000
+        });
+        let index = props.msa.indexOf(row);
+        props.msa.splice(index, 1);
+    }).catch(() => { });
+}
+
+const handleCurrentChange = (e) => {
+    state.page = e;
+};
+
+const handleSizeChange = (e) => {
+    state.limit = e;
+};
+
+</script>
+
+<style>
+.con {
+    display: flex;
+    align-items: center;
+}
+
+.button-container {
+    position: relative;
+    left: 10px;
+    transform: translateY(1%);
+    border-radius: 50%;
+    width: 30px;
+    height: 28px;
+}
+
+.input-container {
+    display: flex;
+    align-items: center;
+}
+
+.addButton {
+    position: absolute;
+    right: 5%;
+}
+
+.searchButton {
+    margin-right: 20px;
+    /* 调整搜索按钮的右侧间距 */
+}
+
+
+.button-container:hover {
+    border-radius: 10px;
+    width: 100px;
+}
+
+.button-container el-button {
+    margin-right: 10px;
+}
+
+.button-container el-button:last-child {
+    margin-right: 0;
+}
+
+.container {
+    display: flex;
+    align-items: center;
+    width: 200px;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.edit-button {
+    position: absolute;
+    top: 50%;
+    left: 120px;
+    transform: translateY(-50%);
+}
+
+.table-container {
+    text-alugn: center;
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+}
+
+.pagination-container {
+    display: flex;
+    justify-content: center;
+}
+
+.centered-content {
+    text-align: center;
+}
+
+.text {
+    display: none;
+}
+</style>

+ 110 - 0
src/components/player/playerInfo/index.vue

@@ -0,0 +1,110 @@
+<template>
+    <div style="max-width: 1700px;">
+        <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="70px" class="demo-ruleForm"
+            :size="formSize">
+            <el-form-item :inline="true">
+                <el-form-item label="玩家ID" prop="id">
+                    <el-input v-model="ruleForm.id" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="账号ID" prop="aId">
+                    <el-input v-model="ruleForm.aId" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="角色名" prop="nm">
+                    <el-input v-model="ruleForm.nm" style="width: 120px;" />
+                </el-form-item>
+
+                <el-form-item label="游戏服" prop="gId">
+                    <el-input v-model="ruleForm.gId" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="等级" prop="lv">
+                    <el-input v-model="ruleForm.lv" style="width: 120px;" />
+                </el-form-item>
+
+                <el-form-item label="vip等级" prop="vLv">
+                    <el-input v-model="ruleForm.vLv" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="战斗力" prop="tmp">
+                    <el-input v-model="ruleForm.tmp" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="总充值" prop="atu">
+                    <el-input v-model="ruleForm.atu" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+            </el-form-item>
+
+            <el-form-item :inline="true">
+                <el-form-item label="公会" prop="gld">
+                    <el-input v-model="ruleForm.gld" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="封号截至" prop="btm">
+                    <el-input v-model="ruleForm.btm" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="封号理由" prop="btn">
+                    <el-input v-model="ruleForm.btn" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="禁言截止" prop="stm">
+                    <el-input v-model="ruleForm.stm" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="禁言理由" prop="stn">
+                    <el-input v-model="ruleForm.stn" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="深渊层数" prop="aby">
+                    <el-input v-model="ruleForm.aby" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="注册时间" prop="ctm">
+                    <el-input v-model="ruleForm.ctm" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+                <el-form-item label="最近登录" prop="llTm">
+                    <el-input v-model="ruleForm.llTm" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+            </el-form-item>
+
+            <el-form-item :inline="true">
+                <el-form-item label="最近登出" prop="luTm">
+                    <el-input v-model="ruleForm.luTm" style="width: 120px;" :disabled="true" />
+                </el-form-item>
+
+            </el-form-item>
+
+            <el-form-item>
+                <el-button type="primary" style="" @click="submitForm()" round>保存信息</el-button>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+
+<script lang="ts" setup name="inline-table">
+import { reactive, ref } from 'vue'
+import playerApi from '@/api/player'
+
+const rules = reactive({
+
+});
+
+let props = defineProps({
+    ruleForm: Object
+});
+
+const submitForm = () => {
+    let data = {
+        playerId: props.ruleForm.id,
+        name: props.ruleForm.nm,
+        playerLv: props.ruleForm.lv
+    }
+    playerApi.editPlayerInfo(data);
+}
+
+const formSize = ref('default')
+
+</script>

+ 1053 - 0
src/components/player/relicInfo/index.vue

@@ -0,0 +1,1053 @@
+<template>
+    <div class="container">
+        <!-- 搜索框 -->
+        <el-input v-model="search" placeholder="输入关键字" :maxlength="20" />
+
+        <el-button class="searchButton" @click="tableData()" type="primary">搜索</el-button>
+        <el-button class="addButton" @click="addrls()" type="primary">添加遗物</el-button>
+    </div>
+
+    <el-table :data="tableData()" class="table-container" :border="true">
+        <el-table-column prop="id" label="ID" class="centered-content" align="center" />
+        <el-table-column prop="iId" label="道具ID" class="centered-content" align="center" />
+        <el-table-column label="遗物名称" class="centered-content" align="center">
+            <template #default="scope">
+                <span>{{ scope.row.iId }}</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="pId" label="属性ID" class="centered-content" align="center" />
+        <el-table-column prop="rsi" label="套装ID" class="centered-content" align="center" />
+        <el-table-column prop="etp" label="遗物类型" class="centered-content" align="center">
+            <template #default="scope">
+                <span>{{ rlsTyeps[scope.row.etp] }}</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="rat" label="主属性" class="centered-content" align="center">
+            <template #default="scope">
+                <span>{{ attrJson[scope.row.rat] }}</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="ratValue" label="主属性值" class="centered-content" align="center" />
+        <el-table-column prop="qua" label="遗物品质" class="centered-content" align="center" />
+        <el-table-column prop="lv" label="遗物等级" class="centered-content" align="center" />
+        <el-table-column prop="sar" label="遗物星级" class="centered-content" align="center" />
+        <el-table-column prop="onr" label="装备英雄" class="centered-content" align="center">
+            <template #default="scope">
+                <span>{{ heroJson[scope.row.onr] }}</span>
+            </template>
+        </el-table-column>
+        <el-table-column prop="exp" label="exp" class="centered-content" align="center" />
+        <el-table-column prop="rdm" label="副词条1" class="centered-content" align="center">
+            <template #default="scope">
+                <span>
+                    <span v-for="(item, index) in scope.row.rdm" :key="item">
+                        <span v-if="index == 0">
+                            <a href="#" @click="openModal(scope.row, item, index, $event)" style="text-decoration: none">{{
+                                attrJson[item.typ] }}</a>
+                        </span>
+                    </span>
+                </span>
+            </template>
+        </el-table-column>
+
+        <el-table-column prop="rdm" label="副词条2" class="centered-content" align="center">
+            <template #default="scope">
+                <span>
+                    <span v-for="(item, index) in scope.row.rdm" :key="item">
+                        <span v-if="index == 1">
+                            <a href="#" @click="openModal(scope.row, item, index, $event)" style="text-decoration: none">{{
+                                attrJson[item.typ] }}</a>
+                        </span>
+                    </span>
+                </span>
+            </template>
+        </el-table-column>
+
+        <el-table-column prop="rdm" label="副词条3" class="centered-content" align="center">
+            <template #default="scope">
+                <span>
+                    <span v-for="(item, index) in scope.row.rdm" :key="item">
+                        <span v-if="index == 2">
+                            <a href="#" @click="openModal(scope.row, item, index, $event)" style="text-decoration: none">{{
+                                attrJson[item.typ] }}</a>
+                        </span>
+                    </span>
+                </span>
+            </template>
+        </el-table-column>
+
+        <el-table-column prop="rdm" label="副词条4" class="centered-content" align="center">
+            <template #default="scope">
+                <span>
+                    <span v-for="(item, index) in scope.row.rdm" :key="item">
+                        <span v-if="index == 3">
+                            <a href="#" @click="openModal(scope.row, item, index, $event)" style="text-decoration: none">{{
+                                attrJson[item.typ] }}</a>
+                        </span>
+                    </span>
+                </span>
+            </template>
+        </el-table-column>
+
+        <el-table-column label="操作" width="100px" align="center">
+            <template #default="scope">
+                <span class="con">
+                    <el-button @click="editrls(scope.row)" @mouseenter="showText" @mouseleave="hideText" type="primary"
+                        :icon="Edit" class="button-container">
+                        <i class="icon"></i>
+                        <span class="text">修改遗物</span>
+                    </el-button>
+
+                    <el-button @click="delRls(scope.row)" type="danger" :icon="Delete" class="button-container"
+                        @mouseenter="showText" @mouseleave="hideText">
+                        <i class="ic, resultPropson"></i>
+                        <span class="text">删除遗物</span>
+                    </el-button>
+                </span>
+            </template>
+        </el-table-column>
+    </el-table>
+
+    <el-pagination style="margin: auto;" class="pagination-container" background layout="prev, pager, next ,total,sizes"
+        :total="state.total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
+
+    <!-- 模态框 -->
+    <el-dialog :title="dialogTitle" v-model="showModal" @close="closeModal" width="800px">
+        <el-row>
+            <el-col :span="20">
+                <span v-if="editAddFlag">
+                    <el-form-item label="遗物数量" label-width="100px" class="label-left">
+                        <el-input v-model="rlsCount" placeholder="添加同类型遗物数量" :maxlength="10" style="width: 200px" />
+                    </el-form-item>
+                </span>
+                <span v-else>
+                    <el-form-item label="遗物ID" label-width="100px" class="label-left">
+                        <el-input v-model="rlsId" placeholder="遗物ID" disabled="disabled" :maxlength="10"
+                            style="width: 200px" />
+                    </el-form-item>
+                </span>
+            </el-col>
+            <el-col :span="4">
+                <el-button @click="openRlsModal()" type="primary" style="">添加词条</el-button>
+            </el-col>
+        </el-row>
+        <el-row style="margin-bottom: 20px;"></el-row>
+        <el-form>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="遗物道具" label-width="100px" class="label-left">
+                        <el-input v-model="rlsiId" placeholder="输入道具ID" :maxlength="10" :disabled="!addDisabled"
+                            style="width: 200px;" @change="inputChange" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="遗物名称" label-width="100px" class="label-left">
+                        <el-input v-model="rlsName" placeholder="遗物名称" :disabled="addDisabled" :maxlength="10"
+                            style="width: 200px;" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="基础属性" label-width="100px" class="label-left">
+                        <el-input v-model="rlsPid" placeholder="基础属性ID" :disabled="addDisabled" :maxlength="10"
+                            style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="遗物类型" label-width="100px" class="label-left">
+                        <el-select v-model="rlsTyp" placeholder="遗物类型" :disabled="addDisabled" style="width: 200px">
+                            <el-option v-for="option in typeOptions" :key="option.value" :label="option.label"
+                                :value="option.value"></el-option>
+                        </el-select>
+
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="主属性类型" label-width="100px" class="label-left">
+                        <el-select v-model="rlsAttr" placeholder="请选择主属性类型" style="width: 200px" :rules="rlsAttrRules"
+                            show-error>
+                            <el-option v-for="option in attrOptions" :key="option.value" :label="option.label"
+                                :value="option.value"></el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="主属性值" label-width="100px" class="label-left">
+                        <el-input v-model="rlsAttrV" placeholder="主属性值" :maxlength="10" style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="套装ID" label-width="100px" class="label-left">
+                        <el-input v-model="rsi" placeholder="套装ID" :disabled="addDisabled" :maxlength="10"
+                            style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="遗物品质" label-width="100px" class="label-left">
+                        <el-input v-model="rlsqua" placeholder="遗物品质" :disabled="addDisabled" :maxlength="10"
+                            style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="遗物等级" label-width="100px" class="label-left">
+                        <el-input v-model="rlsLv" placeholder="遗物等级" @change="lvChange" :maxlength="10"
+                            style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="遗物星级" label-width="100px" class="label-left">
+                        <el-input v-model="rlsStar" placeholder="遗物星级" :disabled="addDisabled" :maxlength="10"
+                            style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+
+                    <el-form-item label="装备英雄" label-width="100px" class="label-left">
+                        <el-input v-model="rlsOwn" placeholder="装备英雄" :maxlength="10" style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+
+                    <el-form-item label="遗物经验值" label-width="100px" class="label-left">
+                        <el-input v-model="rlsExp" placeholder="遗物经验值" :maxlength="10" style="width: 200px" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12" :class="{ 'hidden': !rdm1Dis }">
+                    <el-form-item label="副词条1 " label-width="100px" class="label-left">
+                        <el-input v-model="rdm1" placeholder="副词条1" :maxlength="10" style="width: 200px" />
+                        <el-button @click="editRdm1" icon="Edit" type="primary" round></el-button>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12" :class="{ 'hidden': !rdm2Dis }">
+                    <el-form-item label="副词条2 " label-width="100px" class="label-left">
+                        <el-input v-model="rdm2" placeholder="副词条2" :maxlength="10" style="width: 200px" />
+                        <el-button @click="editRdm2" icon="Edit" type="primary" round></el-button>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12" :class="{ 'hidden': !rdm3Dis }">
+                    <el-form-item label="副词条3 " label-width="100px" class="label-left">
+                        <el-input v-model="rdm3" placeholder="副词条3" :maxlength="10" style="width: 200px" />
+                        <el-button @click="editRdm3" icon="Edit" type="primary" round></el-button>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12" :class="{ 'hidden': !rdm4Dis }">
+                    <el-form-item label="副词条4 " label-width="100px" class="label-left">
+                        <el-input v-model="rdm4" placeholder="副词条4" :maxlength="10" style="width: 200px" />
+                        <el-button @click="editRdm4" icon="Edit" type="primary" round></el-button>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row style="margin-bottom: 20px;"></el-row>
+
+
+            <span slot="footer" class="dialog-footer" style="position: absolute; right: 20px; bottom: 10px;">
+                <el-button type="primary" @click="saverls">保存</el-button>
+                <el-button @click="closeModal">关闭</el-button>
+            </span>
+
+        </el-form>
+    </el-dialog>
+
+    <el-dialog title="副词条" v-model="rdmModal" @close="closeRdmModal" width="300px">
+        <el-form-item label="词条类型">
+            <el-select v-model="rdmTyp" placeholder="请选择词条类型" style="width: 200px" @change="rdmChange">
+                <el-option v-for="option in rdmOptions" :key="option.value" :label="option.label"
+                    :value="option.value"></el-option>
+            </el-select>
+        </el-form-item>
+        <el-form-item label="词条数值">
+            <el-input v-model="rdmVal" placeholder="请输入词条数值" :maxlength="5" style="width: 200px" />
+        </el-form-item>
+        <el-form-item label="强化次数">
+            <el-input v-model="rdmsTs" placeholder="请输入强化次数" :maxlength="5" style="width: 200px" />
+        </el-form-item>
+
+        <span slot="footer" class="dialog-footer" style="position: absolute; right: 20px; bottom: 10px;">
+            <el-button type="primary" @click="saveRdm">保存</el-button>
+            <el-button @click="closeRdmModal">关闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+<script lang="ts" setup>
+import { ElMessageBox, ElMessage, rowContextKey } from 'element-plus';
+import { reactive, ref } from 'vue'
+import { Edit, Check, Close, Delete } from '@element-plus/icons-vue'
+import playerApi from '@/api/player'
+import { id } from 'element-plus/es/locale';
+
+const props = defineProps({
+    rls: Array,
+    ruleForm: Object,
+    callback: {
+        type: Function,
+        required: true
+    },
+    callback1: {
+        type: Function,
+        required: true
+    }
+});
+
+let dialogTitle = ref<string>('');
+
+const showModal = ref<Boolean>(false);
+const rdmModal = ref<Boolean>(false);
+const addDisabled = ref<Boolean>(true);
+const editAddFlag = ref<Boolean>(true);  // 遗物新增  删除标志位
+
+const search = ref("");
+const rlsId = ref("");
+const rlsName = ref("");
+const rlsAlv = ref<Number>();
+const rlsiId = ref<Number>();   // 遗物道具Id
+const rlsPid = ref<Number>(); // 基础属性ID
+const rlsTyp = ref<Number>();  // 遗物类型
+const rlsAttr = ref<Number>();  // 遗物主属性
+const rlsAttrV = ref<Number>(0);  // 主属性值
+const rsi = ref<Number>(); // 套装ID
+const rlsqua = ref<Number>(); // 遗物品质
+const rlsLv = ref<Number>(0); // 遗物等级
+const rlsStar = ref<Number>(); // 遗物星级
+const rlsOwn = ref<Number>(0); // 装备英雄
+const rlsExp = ref<Number>(0);  // 经验
+const rlsCount = ref<Number>(1); // 添加数量
+const attrOptions = reactive([]);
+const rdm1 = ref(""); // 副词条1
+const rdm2 = ref(""); // 副词条2
+const rdm3 = ref(""); // 副词条3
+const rdm4 = ref(""); // 副词条4
+
+const rdm1Dis = ref<Boolean>(false); // 隐藏
+const rdm2Dis = ref<Boolean>(false); // 副词条2
+const rdm3Dis = ref<Boolean>(false); // 副词条3
+const rdm4Dis = ref<Boolean>(false); // 副词条4
+const rdmOpenType = ref<Number>(0);
+const existRdm = reactive([]);  // 已存在的副词条属性
+
+const rdmTyp = ref("");
+const rdmVal = ref<Number>(0);
+const rdmsTs = ref<Number>(0);
+const rdmOptions = reactive([]);
+const rdmIndex = ref<Number>();
+const rdmId = ref();
+
+const rlsAttrRules = [
+    { required: true, message: '请选择主属性类型', trigger: 'change' }
+];
+
+const state = reactive({
+    page: 1,
+    limit: 10,
+    total: props.rls.length
+});
+
+const rlsTyeps = ['', '部件A', '部件B', '部件C', '部件D'];
+
+const typeOptions = [
+    {
+        'label': "部位1",
+        'value': 1
+    }, {
+        'label': "部位2",
+        'value': 2
+    }, {
+        'label': "部位3",
+        'value': 3
+    }, {
+        'label': "部位4",
+        'value': 4
+    }
+];
+
+const attrJson = {
+    101: "生命",
+    102: "攻击",
+    103: "威力",
+    104: "防御",
+    201: "暴击几率",
+    202: "攻击加成",
+    203: "威力加成",
+    204: "攻击速度",
+    301: "生命加成",
+    302: "防御加成",
+    303: "治疗效果",
+    304: "护盾精通",
+    401: "充能速度",
+    402: "施法速度",
+    403: "跌落抗性",
+    404: "召唤精通"
+};
+
+const heroJson = {
+    0: "无",
+    101: "莱格拉斯",
+    102: "米娅",
+    104: "霍夫曼",
+    105: "米洛",
+    201: "凡妮莎",
+    202: "内迪",
+    205: "糕点师",
+    206: "艾尔莎",
+    301: "船长",
+    303: "男主",
+    304: "兔盾",
+    401: "烧烤奶",
+    402: "艾丽西亚",
+    403: "占星师",
+    501: "维维安",
+    502: "沙拉曼",
+    601: "彩虹箭",
+    602: "大卫",
+    603: "指挥官",
+    702: "双枪",
+    703: "消防员"
+};
+
+const tableData = () => {
+    let rls: any = [];
+    if (search.value == "") {
+        state.total = props.rls.length;
+        rls = props.rls;
+    } else {
+        const regex = new RegExp(search.value, 'i');
+        rls = props.rls.filter(
+            (item: { id: string, bid: String, biId: String }, index) => {
+                return regex.test(item.id) || regex.test(item.bid) || regex.test(item.biId);
+            }
+        );
+        state.total = rls.length;
+    }
+
+    return rls.filter(
+        (item, index) =>
+            index < state.page * state.limit &&
+            index >= state.limit * (state.page - 1)
+    );
+};
+
+const inputChange = (val) => {
+    let data = {
+        itemID: val + ""
+    }
+
+    playerApi.getRls(data).then((resp) => {
+        let result = resp.data.result;
+        if (result == '') {
+            ElMessage({
+                message: "遗物道具不存在",
+                type: 'error',
+                duration: 3000
+            });
+        } else {
+            let jsonData = JSON.parse(result);
+            rlsName.value = jsonData.itemId;
+            rlsPid.value = jsonData.pId;
+            rlsStar.value = jsonData.star;
+            rsi.value = jsonData.rsi;
+            rlsLv.value = jsonData.lv;
+            rlsqua.value = jsonData.qua;
+            rlsTyp.value = jsonData.type;
+
+            for (let index = 0; index < jsonData.attr.length; index++) {
+                let key = jsonData.attr[index];
+                let option = {
+                    'label': attrJson[key],
+                    'value': key
+                };
+                attrOptions.push(option);
+            }
+
+            for (let index = 0; index < jsonData.rdm.length; index++) {
+                let key = jsonData.rdm[index];
+                let option = {
+                    'label': attrJson[key],
+                    'value': key
+                };
+                rdmOptions.push(option);
+            }
+        }
+    });
+}
+
+const lvChange = (val) => {
+    let data = {
+        itemID: rlsiId.value,
+        changeLv: val + ""
+    }
+    if (val > 0) {
+        playerApi.rlsChangeLv(data).then((resp) => {
+            let result = resp.data.result;
+            let jsonData = JSON.parse(result);
+            if (jsonData.pId == 0) {
+                ElMessage({
+                    message: "超出最大等级",
+                    type: 'error',
+                    duration: 3000
+                });
+            } else {
+                rlsPid.value = jsonData.pId;
+            }
+
+        });
+    }
+}
+
+const openModal = (row, item, index, event) => {
+    event.preventDefault();
+    rdmOpenType.value = 1;
+    rdmModal.value = true;
+    rdmTyp.value = item.typ;
+    rdmVal.value = item.val;
+    rdmsTs.value = item.sTs;
+    rdmIndex.value = index;
+    rlsId.value = row.id
+    existRdm.splice(0, existRdm.length);
+    rdmOptions.splice(0, rdmOptions.length);
+    // 获取部位能选择的参数
+    let data = {
+        partType: row.etp
+    }
+
+    // 移除已经存在的词条
+    let rdms = row.rdm;
+    for (let i = 0; i < rdms.length; i++) {
+        if (i == index) {
+            continue;
+        }
+        const element = rdms[i];
+        existRdm.push(element.typ);
+    }
+
+    playerApi.getPart(data).then((resp) => {
+        let data = resp.data.result;
+        const jsonFun = new Function('return ' + data);
+        const jsonData = jsonFun();
+
+        for (let index = 0; index < jsonData.rdm.length; index++) {
+            let key = jsonData.rdm[index];
+            if (!existRdm.includes(key)) {
+                let option = {
+                    'label': attrJson[key],
+                    'value': key
+                };
+                rdmOptions.push(option);
+            }
+        }
+    });
+}
+
+const editRdm1 = () => {
+    rdmOpenType.value = 1;
+    rdmIndex.value = 0;
+    let s = rdm1.value;
+    let item = s.split(":");
+    rdmModal.value = true;
+
+    rdmTyp.value = parseInt(item[0]);
+    rdmVal.value = item[1];
+    rdmsTs.value = item[2];
+    let option = {
+        'label': attrJson[rdmTyp.value],
+        'value': rdmTyp.value
+    };
+
+    if (!existRdm.includes(rdmTyp.value)) {
+        rdmOptions.push(option);
+        existRdm.push(rdmTyp.value);
+    }
+}
+
+const editRdm2 = () => {
+    rdmOpenType.value = 1;
+    rdmIndex.value = 1;
+    let s = rdm2.value;
+    let item = s.split(":");
+    rdmModal.value = true;
+
+    rdmTyp.value = parseInt(item[0]);
+    rdmVal.value = item[1];
+    rdmsTs.value = item[2];
+}
+
+const editRdm3 = () => {
+    rdmOpenType.value = 1;
+    rdmIndex.value = 2;
+    let s = rdm3.value;
+    let item = s.split(":");
+    rdmModal.value = true;
+
+    rdmTyp.value = parseInt(item[0]);
+    rdmVal.value = item[1];
+    rdmsTs.value = item[2];
+}
+
+const editRdm4 = () => {
+    rdmOpenType.value = 1;
+    rdmIndex.value = 3;
+    let s = rdm4.value;
+    let item = s.split(":");
+    rdmModal.value = true;
+    console.log(item);
+
+    rdmTyp.value = parseInt(item[0]);
+    rdmVal.value = item[1];
+    rdmsTs.value = item[2];
+}
+
+const openRlsModal = () => {
+    let count = 0;
+    if (rdm1.value != "") {
+        count++;
+    }
+    if (rdm2.value != "") {
+        count++;
+    }
+    if (rdm3.value != "") {
+        count++;
+    }
+    if (rdm4.value != "") {
+        count++;
+    }
+
+    if (count < rlsStar.value - 1) {
+        rdmModal.value = true;
+        rdmTyp.value = null;
+        rdmVal.value = 0;
+        rdmsTs.value = 0;
+        rdmOpenType.value = 2;
+    } else {
+        let rdmCount = rlsStar.value - 1
+        let msg = "该星级最大词条数" + rdmCount;
+        ElMessage({
+            message: msg,
+            type: 'error',
+            duration: 3000
+        });
+    }
+}
+
+const rdmChange = (val) => {
+    if (existRdm.includes(val)) {
+        ElMessage({
+            message: "该词条已存在,请重新选择",
+            type: 'error',
+            duration: 3000
+        });
+    }
+}
+
+const saveRdm = () => {
+    let data = {
+        playerId: props.ruleForm.id,
+        rdmType: rdmTyp.value,
+        rdmVal: rdmVal.value,
+        rdmsTs: rdmsTs.value,
+        rlsId: rlsId.value,
+        rdmIndex: rdmIndex.value
+    }
+
+    if (rdmOpenType.value == 1) {
+        playerApi.saveRdm(data).then((resp) => {
+            props.callback(data);
+            rdmModal.value = false;
+            switch (rdmIndex.value) {
+                case 0:
+                    rdm1.value = data.rdmType + ":" + data.rdmVal + ":" + data.rdmsTs
+                    break;
+                case 1:
+                    rdm2.value = data.rdmType + ":" + data.rdmVal + ":" + data.rdmsTs
+                    break;
+                case 2:
+                    rdm3.value = data.rdmType + ":" + data.rdmVal + ":" + data.rdmsTs
+                    break;
+                case 3:
+                    rdm4.value = data.rdmType + ":" + data.rdmVal + ":" + data.rdmsTs
+                    break;
+                default:
+                    break;
+            }
+        });
+    } else if (rdmOpenType.value == 2) {
+        let d = rdmTyp.value + ":" + rdmVal.value + ":" + rdmsTs.value;
+        if (rdm1.value == "") {
+            rdm1.value = d;
+            rdm1Dis.value = true;
+        } else if (rdm2.value == "") {
+            rdm2.value = d;
+            rdm2Dis.value = true;
+        } else if (rdm3.value == "") {
+            rdm3.value = d;
+            rdm3Dis.value = true;
+        } else if (rdm4.value == "") {
+            rdm4.value = d;
+            rdm4Dis.value = true;
+        }
+    }
+
+    rdmModal.value = false;
+}
+
+const showText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'block';
+}
+
+const hideText = (event) => {
+    const button = event.target;
+    const text = button.querySelector('.text');
+    text.style.display = 'none';
+}
+
+const closeModal = () => {
+    rlsId.value = null
+    rlsiId.value = null
+    rlsLv.value = null
+    rlsAlv.value = null
+    rdm1.value = null;
+    rdm2.value = null;
+    rdm3.value = null;
+    rdm4.value = null;
+    rdm1Dis.value = false;
+    rdm2Dis.value = false;
+    rdm3Dis.value = false;
+    rdm4Dis.value = false;
+    showModal.value = false;
+    dialogTitle.value = "添加遗物";
+}
+
+const closeRdmModal = () => {
+    rdmTyp.value = null
+    rdmVal.value = null
+    rdmsTs.value = null
+    rdmModal.value = false;
+}
+
+const addrls = () => {
+    editAddFlag.value = true;
+    dialogTitle.value = "添加遗物";
+    addDisabled.value = true;
+    showModal.value = true;
+    rlsName.value = null;
+    rlsPid.value = 0;
+    rlsStar.value = null;
+    rsi.value = null;
+    rlsLv.value = 0;
+    rlsqua.value = null;
+    rlsTyp.value = null;
+    rlsCount.value = 1;
+    attrOptions.splice(0, attrOptions.length);
+    rdmOptions.splice(0, rdmOptions.length);
+}
+
+// 修改图纸
+const editrls = (row: any) => {
+    dialogTitle.value = "修改遗物";
+    showModal.value = true;
+    editAddFlag.value = false;
+
+    rlsId.value = row.id;
+    rlsiId.value = row.iId;
+    rlsLv.value = row.lv;
+    rlsOwn.value = row.onr;
+    rlsqua.value = row.qua;
+    rlsStar.value = row.sar;
+    rlsAttr.value = parseInt(row.rat);
+    rlsAttrV.value = row.ratValue;
+    rsi.value = row.rsi;
+    rlsPid.value = row.pId;
+    rlsExp.value = row.exp;
+    rlsTyp.value = row.etp;
+    existRdm.splice(0, existRdm.length);
+
+    for (let index = 0; index < row.rdm.length; index++) {
+        const element = row.rdm[index];
+        switch (index) {
+            case 0:
+                rdm1Dis.value = true;
+                rdm1.value = element.typ + ":" + element.val + ":" + element.sTs
+                break;
+            case 1:
+                rdm2Dis.value = true;
+                rdm2.value = element.typ + ":" + element.val + ":" + element.sTs
+                break;
+            case 2:
+                rdm3Dis.value = true;
+                rdm3.value = element.typ + ":" + element.val + ":" + element.sTs
+                break;
+            case 3:
+                rdm4Dis.value = true;
+                rdm4.value = element.typ + ":" + element.val + ":" + element.sTs
+                break;
+            default:
+                break;
+        }
+        existRdm.push(element.typ);
+    }
+
+    let data = {
+        partType: row.etp
+    }
+
+    playerApi.getPart(data).then((resp) => {
+        let data = resp.data.result;
+        let jsonData = JSON.parse(data);
+        for (let index = 0; index < jsonData.attr.length; index++) {
+            let key = jsonData.attr[index];
+            let option = {
+                'label': attrJson[key],
+                'value': key
+            };
+            attrOptions.push(option);
+        }
+
+        for (let index = 0; index < jsonData.rdm.length; index++) {
+            let key = jsonData.rdm[index];
+
+            let option = {
+                'label': attrJson[key],
+                'value': key
+            };
+            rdmOptions.push(option);
+        }
+    });
+
+}
+
+// 保存
+const saverls = () => {
+    let flag = editAddFlag.value;
+    console.log(rlsAttr.value);
+
+    if (flag) {
+        if (rlsAttr.value == undefined) {
+            ElMessage({
+                message: "请选择主属性",
+                type: 'error',
+                duration: 3000
+            });
+        } else {
+            let data = {
+                playerId: props.ruleForm.id,
+                pbId: rlsPid.value,
+                itemId: rlsiId.value,
+                attrType: rlsAttr.value,
+                attrVal: rlsAttrV.value,
+                lv: rlsLv.value,
+                exp: rlsExp.value,
+                heroId: rlsOwn.value,
+                rdm1: rdm1.value,
+                rdm2: rdm2.value,
+                rdm3: rdm3.value,
+                rdm4: rdm4.value,
+                relicNum: rlsCount.value
+            }
+
+            playerApi.addRelic(data).then((resp) => {
+                let data = resp.data.result;
+
+                if (data === '添加失败') {
+                    ElMessage({
+                        message: "添加失败",
+                        type: 'error',
+                        duration: 3000
+                    });
+                } else {
+                    let jsonArray = JSON.parse(data);
+                    props.callback1(jsonArray);
+                }
+            });
+
+        }
+    } else {
+        let data = {
+            relicId: rlsId.value,
+            playerId: props.ruleForm.id,
+            pbId: rlsPid.value,
+            attrType: rlsAttr.value,
+            attrVal: rlsAttrV.value,
+            lv: rlsLv.value,
+            exp: rlsExp.value,
+            heroId: rlsOwn.value,
+            rdm1: rdm1.value,
+            rdm2: rdm2.value,
+            rdm3: rdm3.value,
+            rdm4: rdm4.value
+        }
+
+        playerApi.editRelic(data).then((resp) => {
+            let data = resp.data.result;
+
+            if (data === '修改失败') {
+                ElMessage({
+                    message: "修改失败",
+                    type: 'error',
+                    duration: 3000
+                });
+            } else {
+                let jsonArray = JSON.parse(data);
+                props.callback1(jsonArray);
+            }
+        });
+    }
+
+
+    showModal.value = false;
+}
+
+// 删除遗物
+const delRls = (row: any) => {
+    ElMessageBox.confirm('确定要删除该遗物吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+    }).then(() => {
+        let data = {
+            playerId: props.ruleForm.id,
+            relicId: row.id
+        }
+
+        playerApi.delRls(data).then((resp) => {
+            console.log(resp);
+
+            if (resp.data.result === '删除成功') {
+                ElMessage({
+                    message: "删除成功",
+                    type: 'success',
+                    duration: 3000
+                });
+                let index = props.rls.indexOf(row);
+                props.rls.splice(index, 1);
+            } else {
+                ElMessage({
+                    message: "删除失败",
+                    type: 'error',
+                    duration: 3000
+                });
+            }
+        });
+
+
+
+    }).catch(() => { });
+}
+
+// 分页
+
+const handleCurrentChange = (e) => {
+    state.page = e;
+};
+
+const handleSizeChange = (e) => {
+    state.limit = e;
+};
+
+</script>
+
+<style>
+.hidden {
+    display: none;
+}
+
+.con {
+    display: flex;
+    align-items: center;
+}
+
+.button-container {
+    position: relative;
+    left: 10px;
+    transform: translateY(1%);
+    border-radius: 50%;
+    width: 30px;
+    height: 28px;
+}
+
+.input-container {
+    display: flex;
+    align-items: center;
+}
+
+.addButton {
+    position: absolute;
+    right: 5%;
+}
+
+.searchButton {
+    margin-right: 20px;
+    /* 调整搜索按钮的右侧间距 */
+}
+
+.button-container:hover {
+    border-radius: 10px;
+    width: 100px;
+}
+
+.button-container el-button {
+    margin-right: 10px;
+}
+
+.button-container el-button:last-child {
+    margin-right: 0;
+}
+
+.container {
+    display: flex;
+    align-items: center;
+    width: 200px;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.container .el-input {
+    margin-right: 10px;
+    /* 调整输入框的右边距 */
+}
+
+.edit-button {
+    position: absolute;
+    top: 50%;
+    left: 120px;
+    transform: translateY(-50%);
+}
+
+.table-container {
+    text-align: center;
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+}
+
+.pagination-container {
+    display: flex;
+    justify-content: center;
+}
+
+.centered-content {
+    text-align: center;
+}
+
+.text {
+    display: none;
+}
+
+.label-left {
+    text-align: left;
+}
+
+.label-left .el-input {
+    margin-right: 10px;
+    /* 调整输入框的右边距 */
+}
+</style>

+ 1 - 1
src/layout/LayoutColumns/index.vue

@@ -26,7 +26,7 @@
 
     <div class="layout-columns-sub" :style="{ width: isCollapse ? '60px' : '210px' }">
       <div class="logo flex-center">
-        <span v-show="subMenus.length">{{ isCollapse ? "Vue" : "Vue Admin Perfect" }}</span>
+        <span v-show="subMenus.length">{{ isCollapse ? "Vue" : "010GM" }}</span>
       </div>
       <el-scrollbar >
         <el-menu

+ 1 - 1
src/layout/components/Footer/index.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="footer-layout">
-		<span href="/" target="_blank"> 2022 © VUE-ADMIN-PERFECT By ZB Technology. </span>
+		<span href="/" target="_blank"> 2023 © FORT23 AS 010GM. </span>
 	</div>
 </template>
 

+ 27 - 13
src/routers/index.ts

@@ -16,27 +16,41 @@ import othersRouter from './modules/other'
 import externalLink from './modules/externalLink'
 import formRouter from './modules/form'
 import functionPageRouter from './modules/functionPage'
+
+import playerInfo from './modules/player'
+
 import serverRouter from './modules/server'
 import operationRouter from './modules/operation'
 
 
+
 // 异步组件
+// export const asyncRoutes = [
+//     ...dataScreenRouter,
+//     ...echartsRouter,
+//     ...tableRouter,
+//     ...formRouter,
+//     ...othersRouter,
+//     ...functionPageRouter,
+//     ...chatRouter,
+//     ...nestedRouter,
+//     ...excelRouter,
+//     ...externalLink,
+//     ...systemRouter,
+//     ...playerInfo,
+// ]
+
 export const asyncRoutes = [
-    ...dataScreenRouter,
-    ...echartsRouter,
-    ...tableRouter,
-    ...formRouter,
-    ...othersRouter,
-    ...functionPageRouter,
-    ...chatRouter,
-    ...nestedRouter,
-    ...excelRouter,
-    ...externalLink,
-    ...systemRouter,
-    ...serverRouter,
-    ...operationRouter,
+
+  ...playerInfo,
+  ...dataScreenRouter,
+  ...systemRouter,
+  ...serverRouter,
+  ...operationRouter,
+
 ]
 
+
 /**
  * path ==> 路由路径
  * name ==> 路由名称

+ 24 - 0
src/routers/modules/player.ts

@@ -0,0 +1,24 @@
+/** When your routing table is too long, you can split it into small modules**/
+
+import Layout from "@/layout/index.vue";
+
+const chartsRouter = [{
+    path: '/player',
+    component: Layout,
+    redirect: '/player/index',
+    name: 'player',
+    meta: {
+        title: '玩家信息',
+        icon: 'chat-square'
+    },
+    children: [
+        {
+            path: '/player/index',
+            component: () => import('@/views/player/index.vue'),
+            name: 'chatBox',
+            meta: { title: '玩家信息', icon: 'chat-square'  }
+        }
+    ]
+}]
+
+export default chartsRouter

+ 286 - 0
src/views/player/index.vue

@@ -0,0 +1,286 @@
+<template>
+  <div class="app-container">
+    <div class="header">
+      <el-form :inline="true" :model="formInline1">
+        <el-form-item label="玩家Id">
+          <el-input v-model="formInline1.playerId" placeholder="请输入玩家ID" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="footer">
+      <el-collapse v-model="collapse" accordion>
+        <el-collapse-item name="0" title="基本信息" :class="{ 'active-item': collapse === '0' }">
+          <playerInfo :ruleForm="ruleForm"></playerInfo>
+        </el-collapse-item>
+        <el-collapse-item name="1" title="道具信息">
+          <itemInfo :its="its" :ruleForm="ruleForm" :callback="addItem"></itemInfo>
+        </el-collapse-item>
+        <el-collapse-item name="2" title="关卡信息">
+          <msaInfo :msa="msa" :ruleForm="ruleForm" :callback="handleCustomEvent" :callback1="resetMsa"></msaInfo>
+        </el-collapse-item>
+        <el-collapse-item name="3" title="英雄信息">
+          <heroInfo :hrs="hrs" :ruleForm="ruleForm" :callback="hrsEvent" :callback1="hrsEditEvent"></heroInfo>
+        </el-collapse-item>
+        <el-collapse-item name="4" title="图纸信息">
+          <bpInfo :bps="bps" :ruleForm="ruleForm" :callback="bpsEvent" :callback1="bpsEditEvent"></bpInfo>
+        </el-collapse-item>
+        <el-collapse-item name="5" title="遗物信息">
+          <relicInfo :rls="rls" :ruleForm="ruleForm" :callback="rdmEvent" :callback1="relicEvent"></relicInfo>
+        </el-collapse-item>
+      </el-collapse>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup name="inline-table">
+import playerInfo from "@/components/player/playerInfo/index.vue"
+import itemInfo from "@/components/player/itemInfo/index.vue"
+import msaInfo from "@/components/player/msaInfo/index.vue"
+import heroInfo from "@/components/player/heroInfo/index.vue"
+import bpInfo from "@/components/player/BPInfo/index.vue"
+import relicInfo from "@/components/player/relicInfo/index.vue"
+import { reactive, ref, toRefs, defineEmits } from 'vue'
+import { FormInstance } from 'element-plus'
+import playerApi from '@/api/player'
+import { formatDate } from '../../common/date'
+
+const formInline1 = reactive({
+  playerId: '',
+})
+
+const collapse = ref('0');
+
+const ruleForm = reactive({
+  id: '',
+  aId: '',
+  nm: '',
+  gId: '',
+  lv: '',
+  vLv: '',
+  tmp: '',
+  atu: '',
+  gld: '',
+  btm: '',
+  btn: '',
+  stm: '',
+  stn: '',
+  aby: '',
+  ctm: '',
+  llTm: '',
+  luTm: ''
+});
+
+// const page = ref(1);
+const its = reactive([]);
+
+const msa = reactive([]);
+
+const hrs = reactive([]);
+
+const bps = reactive([]);
+
+const rls = reactive([]);
+
+const onSubmit = async () => {
+  let resp = playerApi.queryPlayerInfo(formInline1);
+
+  let data = (await resp).data.result;
+
+  let jsonData = JSON.parse(data);
+  if (data != '未找到此角色') {
+    ruleForm.id = jsonData.id;
+    ruleForm.aId = jsonData.aId;
+    ruleForm.nm = jsonData.nm;
+    ruleForm.gId = jsonData.gId;
+    ruleForm.lv = jsonData.lv;
+    ruleForm.vLv = jsonData.vLv;
+    ruleForm.tmp = jsonData.tmp == null ? 0 : jsonData.tmp;
+    ruleForm.atu = jsonData.atu;
+    ruleForm.gld = jsonData.gld == null ? '无' : jsonData.gld;
+    ruleForm.btm = jsonData.btm == null ? '无' : formatDate(new Date(jsonData.btm * 1000), 'yyyy-MM-dd hh:mm:ss');
+    ruleForm.btn = jsonData.btn == null ? '无' : jsonData.btn;
+    ruleForm.stm = jsonData.stm == null ? '无' : formatDate(new Date(jsonData.stm * 1000), 'yyyy-MM-dd hh:mm:ss');
+    ruleForm.stn = jsonData.stn == null ? '无' : jsonData.stn;
+    ruleForm.aby = jsonData.aby == null ? 0 : jsonData.aby;
+    ruleForm.ctm = jsonData.ctm == null ? '无' : formatDate(new Date(jsonData.ctm * 1000), 'yyyy-MM-dd hh:mm:ss');
+    ruleForm.llTm = jsonData.llTm == null ? '无' : formatDate(new Date(jsonData.llTm * 1000), 'yyyy-MM-dd hh:mm:ss');
+    ruleForm.luTm = jsonData.luTm == null ? '无' : formatDate(new Date(jsonData.luTm * 1000), 'yyyy-MM-dd hh:mm:ss');
+
+    const itemKeys = Object.keys(jsonData.its);
+    for (let i = 0; i < itemKeys.length; i++) {
+      const json = jsonData.its[itemKeys[i]];
+      json['editing'] = false;
+      json['id'] = itemKeys[i];
+    }
+    console.log(jsonData);
+
+    its.splice(0, its.length);
+    its.push(...Object.values(jsonData.its));
+
+    msa.splice(0, msa.length);
+    msa.push(...Object.values(jsonData.msa));
+
+    hrs.splice(0, hrs.length);
+    hrs.push(...Object.values(jsonData.hrs));
+
+    const bluePrintKeys = Object.keys(jsonData.bps);
+    for (let i = 0; i < bluePrintKeys.length; i++) {
+      const json = jsonData.bps[bluePrintKeys[i]];
+      json['id'] = bluePrintKeys[i];
+    }
+
+    bps.splice(0, bps.length);
+    bps.push(...Object.values(jsonData.bps));
+
+    const relicKeys = Object.keys(jsonData.rls);
+    for (let i = 0; i < relicKeys.length; i++) {
+      const json = jsonData.rls[relicKeys[i]];
+      const rat = json['rat'];
+      const ratValue = rat[Object.keys(rat) + '']
+      json['rat'] = Object.keys(rat)[0];
+      json['ratValue'] = ratValue;
+      json['id'] = relicKeys[i];
+    }
+
+    rls.splice(0, rls.length);
+    rls.push(...Object.values(jsonData.rls));
+    console.log(rls);
+
+  }
+}
+
+const handleCustomEvent = (data: string) => {
+  msa.push(JSON.parse(data));
+}
+
+const addItem = (data: any) => {
+  let jsonData = JSON.parse(data);
+  its.push(jsonData);
+  console.log(jsonData);
+}
+
+const bpsEvent = (data: string) => {
+  bps.push(JSON.parse(data));
+}
+
+const bpsEditEvent = (data: any) => {
+  let regex = new RegExp(data.heroID, "i");
+  let index = hrs.map((hero: { id: string }, index) => {
+    if (regex.test(hero.id)) {
+      return index;
+    }
+  }).filter(index => index !== undefined);
+
+  hrs[index[0]].lv = data.heroLv;
+  hrs[index[0]].alv = data.heroAlv;
+}
+
+const rdmEvent = (data: any) => {
+  let regex = new RegExp(data.rlsId, "i");
+  let index = rls.map((relic: { id: string }, index) => {
+    if (regex.test(relic.id)) {
+      return index;
+    }
+  }).filter(index => index !== undefined);
+
+  rls[index[0]].rdm[data.rdmIndex].typ = data.rdmType;
+  rls[index[0]].rdm[data.rdmIndex].val = data.rdmVal;
+  rls[index[0]].rdm[data.rdmIndex].sTs = data.rdmsTs;
+}
+
+const relicEvent = (data: any) => {
+  for (let index = 0; index < data.length; index++) {
+    const element = JSON.parse(data[index]);
+
+    let regex = new RegExp(element.id, "i");
+    let index2 = rls.map((relic: { id: string }, index2) => {
+      if (regex.test(relic.id)) {
+        return index2;
+      }
+    }).filter(index2 => index2 !== undefined);
+
+    const rat = element['rat'];
+    const ratValue = rat[Object.keys(rat) + '']
+    element['rat'] = Object.keys(rat)[0];
+    element['ratValue'] = ratValue;
+    const exp = element['exp'];
+    element['exp'] = exp['$numberLong']
+
+
+    if (index2.length > 0) {
+      rls[index2[0]] = element;
+    } else {
+      rls.push(element);
+    }
+  }
+}
+
+
+const hrsEvent = (data: string) => {
+  hrs.push(JSON.parse(data));
+}
+
+const hrsEditEvent = (data: any) => {
+  let regex = new RegExp(data.heroID, "i");
+  let index = hrs.map((hero: { id: string }, index) => {
+    if (regex.test(hero.id)) {
+      return index;
+    }
+  }).filter(index => index !== undefined);
+
+  hrs[index[0]].lv = data.heroLv;
+  hrs[index[0]].alv = data.heroAlv;
+}
+
+const resetMsa = (data: any) => {
+  let regex = new RegExp(data.id, "i");
+  let index = msa.map((stage: { id: string }, index) => {
+    if (regex.test(stage.id)) {
+      return index;
+    }
+  }).filter(index => index !== undefined);
+
+  msa[index[0]].msIc = !data.msIc;
+  msa[index[0]].msLc = data.msLc;
+  msa[index[0]].msi = data.msi;
+}
+
+
+const submitForm = async (formEl: FormInstance | undefined) => {
+  console.log('--FORM---', ruleForm)
+  if (!formEl) return
+
+}
+
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.resetFields()
+}
+
+</script>
+
+<style scoped lang="scss">
+.header {
+  display: flex;
+  padding: 16px 16px 0px 16px;
+  margin-bottom: 16px;
+  border-radius: 4px;
+  background: white;
+  box-shadow: 0 0 12px rgb(0 0 0 / 5%);
+}
+
+.footer {
+  flex: 1;
+  display: flex;
+  padding: 16px;
+  flex-direction: column;
+  border-radius: 4px;
+  overflow: hidden;
+  background: white;
+  box-shadow: 0 0 12px rgb(0 0 0 / 5%);
+}
+</style>