引入字体,修改封装列表,新增项目页面,封装公共Table、选择人员弹窗,
10个文件已修改
8个文件已添加
540 ■■■■■ 已修改文件
src/App.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/font/PingFangSCRegular.ttf 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/font/Source Han Sans CN Bold Bold.ttf 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/font/SourceHanSansCN-Medium.otf 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/font/font.css 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/public/close-circle-fill@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/public/headercard.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/public/search-outline@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SelectMember/index.vue 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/TableSlot/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/components/ElMenu/MenuItem.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/components/HeaderNav.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/index.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/projectList/addProject.vue 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/projectList/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue
@@ -62,11 +62,56 @@
.selected {
  color: #049C9A !important;
}
.el-button--primary {
  background-color: #009688 !important;
  border-color: #009688 !important;
}
.el-button--text {
  color: #009688 !important;
}
.el-button--default:focus,
.el-button--default:hover {
  color: #009688 !important;
  border-color: #009688 !important;
  background: #E6FFFF !important;
}
.card {
  .el-form-item__label {
    color: #222222;
    font-family: 'SourceHanSansCN-Medium';
    line-height: 14px;
  }
  .el-input__inner {
    width: 290px;
    padding: 0 12px;
    border-radius: 6px;
    border: 1px solid rgba(0, 0, 0, 0.15);
  }
}
.select-member {
  .el-dialog {
    border-radius: 16px 16px 6px 6px;
    .el-dialog__header {
      font-family: 'Source Han Sans CN Bold Bold';
      font-weight: bold;
      font-size: 20px;
      line-height: 20px;
      color: #222222;
      padding: 39px 0 36px 30px;
      border-bottom: 1px solid rgba(238, 238, 238, 1);
    }
    .el-dialog__body {
      padding: 15px 24px 33px 14px;
      overflow: hidden;
    }
  }
}
</style>
src/assets/font/PingFangSCRegular.ttf
Binary files differ
src/assets/font/Source Han Sans CN Bold Bold.ttf
Binary files differ
src/assets/font/SourceHanSansCN-Medium.otf
Binary files differ
src/assets/font/font.css
New file
@@ -0,0 +1,20 @@
@font-face {
  font-family: 'SourceHanSansCN-Medium';
  src: url('./SourceHanSansCN-Medium.otf');
  font-weight: normal;
  font-style: normal;
}
@font-face {
  font-family: 'Source Han Sans CN Bold Bold';
  src: url('./Source Han Sans CN Bold Bold.ttf');
  font-weight: normal;
  font-style: normal;
}
@font-face {
  font-family: 'PingFangSCRegular';
  src: url('./PingFangSCRegular.ttf');
  font-weight: normal;
  font-style: normal;
}
src/assets/public/close-circle-fill@2x.png
src/assets/public/headercard.png
src/assets/public/search-outline@2x.png
src/components/SelectMember/index.vue
New file
@@ -0,0 +1,239 @@
<template>
    <el-dialog class="select-member" :visible.sync="visible" width="53.33%" :close-on-click-modal="false"
        :show-close="false">
        <template #title>
            <div>选择参与人员</div>
        </template>
        <div class="select-member-content">
            <el-row :gutter="16">
                <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
                    <div class="select-member-content-left">
                        <div class="select-member-content-left-search">
                            <div class="select-member-content-left-search-input">
                                <img src="@/assets/public/search-outline@2x.png" />
                                <el-input v-model="search" placeholder="请输入" />
                                <div class="select-member-content-left-search-input-close">
                                    <img @click.stop="searchRole" v-if="search"
                                        src="@/assets/public/close-circle-fill@2x.png" />
                                </div>
                            </div>
                            <el-button type="primary">搜索</el-button>
                        </div>
                        <div class="select-member-content-left-list">
                            <div class="select-member-content-left-list-title">角色列表</div>
                            <div class="select-member-content-left-list-itemBox">
                                <div v-for="item in 10" :key="item.id"
                                    class="select-member-content-left-list-itemBox-item">
                                    实验员
                                </div>
                            </div>
                        </div>
                    </div>
                </el-col>
                <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
                    <div class="select-member-content-right">
                        <div class="select-member-content-right-header">
                            <div class="select-member-content-right-header-text">人员列表</div>
                            <div class="select-member-content-right-header-search">
                                <el-input clearable v-model="searchName" placeholder="请输入姓名" />
                                <el-button type="primary">搜索</el-button>
                            </div>
                        </div>
                        <Table :data="tableData" :total="0" @selection-change="handleSelectionChange"
                            :row-class-name="tableRowClassName">
                            <el-table-column type="selection" width="55" />
                            <el-table-column label="角色" prop="role" />
                            <el-table-column label="姓名" prop="name" />
                            <el-table-column label="创建时间" prop="createTime" />
                        </Table>
                    </div>
                </el-col>
            </el-row>
        </div>
        <div class="select-member-footer">
            <el-button @click="close" type="default">关闭</el-button>
            <el-button type="primary">确认选择</el-button>
        </div>
    </el-dialog>
</template>
<script>
import { mapState } from 'vuex'
export default {
    data() {
        return {
            visible: false,
            search: '',
            searchName: '',
            tableData: [
                {
                    name: '张三',
                    role: '实验员',
                    createTime: '2025-1-2 15:13:58'
                },
                {
                    name: '李四',
                    role: '实验员',
                    createTime: '2025-1-2 15:13:58'
                },
            ],
            selectData: []
        }
    },
    computed: {
        ...mapState(['isFold'])
    },
    methods: {
        handleSelectionChange(val) {
            this.selectData = val
        },
        searchRole() {
            this.search = ''
        },
        open() {
            this.visible = true
        },
        close() {
            this.visible = false
        },
        tableRowClassName({ row, rowIndex }) {
            if (this.selectData.findIndex(item => item.name === row.name) != -1) {
                return 'select-row';
            }
            return '';
        }
    }
}
</script>
<style scoped lang="less">
.select-member-content {
    .select-member-content-left {
        box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08);
        border-radius: 10px;
        margin-bottom: 31px;
        &-search {
            padding: 6px 7px 6px 10px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            border-bottom: 1px solid rgba(238, 238, 238, 1);
            &-input {
                display: flex;
                align-items: center;
                background: rgba(0, 0, 0, 0.04);
                border-radius: 4px;
                margin-right: 10px;
                flex: 1;
                ::v-deep .el-input__inner {
                    background-color: transparent;
                    border: none;
                    height: 36px;
                    line-height: 36px;
                    padding: 0;
                    width: 100%;
                }
                img {
                    flex-shrink: 0;
                    width: 19px;
                    height: 20px;
                    margin: 0 5px;
                }
                &-close {
                    width: 19px;
                    height: 20px;
                    margin: 0 9px;
                    flex-shrink: 0;
                    img {
                        cursor: pointer;
                    }
                }
            }
        }
        &-list {
            padding: 15px 13px;
            &-title {
                font-weight: 500;
                font-size: 16px;
                line-height: 16px;
                color: #222222;
                font-family: 'SourceHanSansCN-Medium';
                margin-bottom: 8px;
            }
            &-itemBox {
                height: 451px;
                background: #F4F6F8;
                border-radius: 10px;
                padding: 12px 10px;
                overflow-y: auto;
                &-item {
                    cursor: pointer;
                    font-weight: 400;
                    font-size: 14px;
                    line-height: 22px;
                    color: rgba(0, 0, 0, 0.88);
                    font-family: 'PingFangSCRegular';
                    background: #FFFFFF;
                    border-radius: 4px;
                    padding: 9px 15px;
                    margin-bottom: 10px;
                    &:last-child {
                        margin-bottom: 0;
                    }
                }
            }
        }
    }
    .select-member-content-right {
        margin-bottom: 31px;
        &-header {
            display: flex;
            align-items: center;
            margin-top: 5px;
            justify-content: space-between;
            margin-bottom: 21px;
            &-text {
                flex-shrink: 0;
                font-weight: 500;
                font-size: 16px;
                line-height: 16px;
                color: #222222;
                font-family: 'SourceHanSansCN-Medium';
                margin-right: 20px;
            }
            &-search {
                display: flex;
                align-items: center;
                ::v-deep .el-input {
                    margin-right: 12px;
                }
            }
        }
    }
}
.select-member-footer {
    display: flex;
    justify-content: center;
    button {
        width: 150px;
    }
}
</style>
src/components/Table/index.vue
@@ -1,6 +1,6 @@
<template>
    <div class="table-container">
        <el-table border :data="tableData" :height="height">
        <el-table border v-bind="$attrs" v-on="$listeners" :height="height">
            <slot></slot>
        </el-table>
        <div v-if="total > 0">
@@ -53,6 +53,10 @@
</script>
<style scoped lang="less">
::v-deep .select-row {
    background: #E6FFFF !important;
}
.el-table--border,
.el-table--group {
    border-radius: 8px 8px 0px 0px;
@@ -66,6 +70,26 @@
    }
}
::v-deep .el-checkbox__inner:hover {
    border-color: #049C9A !important;
}
::v-deep .el-checkbox__input.is-focus .el-checkbox__inner {
    border-color: #049C9A !important;
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
    background-color: #049C9A !important;
    border-color: #049C9A !important;
}
::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner {
    background-color: #049C9A !important;
    border-color: #049C9A !important;
}
.pagination {
    display: flex;
    justify-content: flex-end;
src/components/TableSlot/index.vue
@@ -5,7 +5,7 @@
        </div>
        <div class="table">
            <slot name="setting"></slot>
            <Table :tableData="tableData" :total="total" :queryForm="queryForm" @currentChange="handleCurrentChange" @sizeChange="handleSizeChange">
            <Table :data="tableData" :total="total" :queryForm="queryForm" @currentChange="handleCurrentChange" @sizeChange="handleSizeChange">
                <slot name="table"></slot>
            </Table>
        </div>
src/layouts/components/ElMenu/MenuItem.vue
@@ -1,7 +1,7 @@
<template>
  <!-- 判断当前页面是否显示,如果hide为true,则不渲染该菜单 -->
  <!-- <div v-if="!item.meta.hide && menus.includes(item.meta.privilege)"> -->
  <div v-if="!(item.meta && item.meta.hide)">
  <div v-if="item.meta && item.meta.title && !item.meta.hide">
    <!-- 根菜单 -->
    <MenuLink :to="resolvePath()" v-if="!item.children">
      <el-menu-item :index="resolvePath()">
src/layouts/components/HeaderNav.vue
@@ -88,6 +88,7 @@
  justify-content: space-between;
  .user-logininfo-icon {
    margin-right: 30px;
    flex: 1;
    flex-shrink: 0;
    display: flex;
src/layouts/index.vue
@@ -130,7 +130,6 @@
      padding: 0 19px;
      overflow-y: auto;
      flex: 1;
      box-shadow: 0px 3px 13px 0px rgba(94, 131, 245, 0.1);
      ::v-deep .el-menu {
        border-right: unset !important;
@@ -180,4 +179,8 @@
  }
}
::v-deep .el-menu {
  background-color: transparent !important;
}
</style>
src/main.js
@@ -1,18 +1,23 @@
import Vue from "vue";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import '@/assets/font/font.css'
import App from "./App.vue";
import router from "./router";
import store from './store'
import Table from '@/components/Table/index.vue'
import TableCustom from '@/components/TableSlot/index.vue'
import Card from '@/components/Card/index.vue'
import ShowDelConfirm from '@/components/showDelConfirm/index.vue'
import SelectMember from '@/components/SelectMember/index.vue'
Vue.config.productionTip = false;
Vue.use(ElementUI, { size: 'small' })
Vue.component('Table', Table)
Vue.component('TableCustom', TableCustom)
Vue.component('Card', Card)
Vue.component('ShowDelConfirm', ShowDelConfirm)
Vue.component('SelectMember', SelectMember)
Vue.prototype.msgsuccess = function (msg) {
  this.$message({
src/router/index.js
@@ -38,10 +38,6 @@
        component: Layouts,
        children: [
            {
                path: "",
                redirect: "/projectList/list"
            },
            {
                path: "/projectList",
                meta: {
                    title: "项目组管理",
src/views/projectList/addProject.vue
@@ -1,7 +1,36 @@
<template>
    <Card>
        <template>
            <el-form ref="form" :model="form" :rules="rules" inline label-position="top">
                <el-form-item prop="name" label="项目组名称">
                    <el-input v-model="form.name" placeholder="请输入" />
                </el-form-item>
                <el-form-item prop="description" label="项目组描述">
                    <el-input v-model="form.description" placeholder="请输入" />
                </el-form-item>
            </el-form>
            <div class="header-title">
                <div class="header-title-left">
                    <img src="@/assets/public/headercard.png" />
                    <div>项目组成员</div>
                </div>
                <el-button class="el-icon-plus" type="primary" @click="addMember"> 添加项目组成员</el-button>
            </div>
            <div class="member-list">
                <div v-for="item in 4" :key="item" class="member-list-card">
                    <div class="member-item">
                        <div class="member-title">{{ ['审批人', '工艺工程师', '实验员', '化验师'][item - 1] }}</div>
                        <div :class="item == 1 || item == 2 ? 'member-name-box' : 'member-name-box-2'">
                            <div v-for="i in memberList(item)" :key="i" class="member-name">张三</div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="add-project-footer">
                <el-button type="primary">保存</el-button>
            </div>
        </template>
        <SelectMember ref="selectMember" />
    </Card>
</template>
@@ -10,10 +39,165 @@
    name: 'AddProject',
    data() {
        return {
            form: {},
            rules: {
                name: [{ required: true, message: '请输入项目组名称', trigger: 'blur' }],
                description: [{ required: true, message: '请输入项目组描述', trigger: 'blur' }]
            }
        }
    },
    methods: {
        submitForm() {
            this.$refs.form.validate((valid) => {
                if (valid) {
                    console.log('submit!')
                }
            })
        },
        addMember() {
            this.$refs.selectMember.open()
        },
        memberList(i) {
            switch (i) {
                case 1:
                    return [1]
                case 2:
                    return [1]
                case 3:
                    return [1, 2, 3, 4, 5, 6, 7, 8]
                case 4:
                    return [1, 2, 3, 4, 5, 6, 7, 8]
                default:
                    break;
            }
        }
    }
}
</script>
<style></style>
<style scoped lang="less">
.el-form--inline .el-form-item {
    margin-right: 83px;
}
.header-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 13px;
    .header-title-left {
        display: flex;
        align-items: center;
        gap: 13px;
        img {
            width: 12px;
            height: 19px;
        }
        div {
            flex-shrink: 0;
            font-weight: bold;
            font-size: 18px;
            color: #222222;
            line-height: 27px;
            font-family: 'Source Han Sans CN Bold Bold';
            &:before {
                content: '*';
                color: #F56C6C;
                margin-right: 4px;
            }
        }
    }
}
.member-list {
    margin-top: 18px;
    display: flex;
    flex-wrap: wrap;
    gap: 28px;
    .member-list-card {
        width: 340px;
        height: 400px;
        border-radius: 8px;
        border: 1px solid #DCDFE6;
        &:nth-child(1) {
            background: linear-gradient(to bottom, rgba(4, 156, 154, 0.2) 0%, rgba(5, 242, 194, 0) 70%);
        }
        &:nth-child(2) {
            background: linear-gradient(to bottom, rgba(5, 160, 193, 0.2) 0%, rgba(5, 242, 194, 0) 70%);
        }
        &:nth-child(3) {
            background: linear-gradient(to bottom, rgba(255, 77, 79, 0.20) 0%, rgba(255, 242, 194, 0) 70%);
        }
        &:nth-child(4) {
            background: linear-gradient(to bottom, rgba(250, 199, 20, 0.21) 0%, rgba(255, 242, 194, 0) 70%);
        }
        .member-item {
            height: 100%;
            display: flex;
            flex-direction: column;
            .member-title {
                margin-top: 20px;
                width: 100%;
                font-family: 'Source Han Sans CN Bold Bold';
                font-weight: bold;
                font-size: 16px;
                color: rgba(0, 0, 0, 0.8);
                line-height: 16px;
                text-align: center;
            }
            .member-name-box {
                flex: 1;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .member-name-box-2 {
                padding: 0 20px;
                padding-top: 40px;
                display: grid;
                grid-template-columns: repeat(4, 1fr);
                align-items: flex-start;
                flex-wrap: wrap;
                gap: 20px;
                justify-content: center;
            }
            .member-name {
                width: 60px;
                height: 60px;
                background: #7D8B79;
                border-radius: 50%;
                text-align: center;
                line-height: 60px;
                font-weight: 500;
                font-size: 16px;
                color: #FFFFFF;
            }
        }
    }
}
.add-project-footer {
    margin-top: 43px;
    button {
        width: 220px;
    }
}
</style>
src/views/projectList/index.vue
@@ -1,6 +1,6 @@
<template>
    <div class="list">
        <TableCustom :queryForm="queryForm" :total="total" @currentChange="handleCurrentChange"
        <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange"
            @sizeChange="handleSizeChange">
            <template #search>
                <el-form :model="form" label-width="140px" inline>
@@ -64,6 +64,7 @@
            changeStatus: false,
            changeStatusTitle: '',
            changeStatusTip: '',
            tableData: [],
            queryForm: {
                pageSize: 10,
                pageNum: 1