From 35968630a8702fcd0092757436f20751f51d3387 Mon Sep 17 00:00:00 2001
From: yaowanxin <3588231647@qq.com>
Date: 星期四, 18 九月 2025 14:03:17 +0800
Subject: [PATCH] Merge branch 'ywx' into dev
---
src/views/collaborativeApproval/enterpriseBook/index.vue | 802 +++++++++++++++++++
src/api/collaborativeApproval/enterpriseBook.js | 67 +
src/views/equipmentManagement/spareParts/index.vue | 417 +++++++++
src/views/collaborativeApproval/rulesRegulationsManagement/index.vue | 746 +++++++++++++++++
src/api/equipmentManagement/spareParts.js | 58 +
src/api/equipmentManagement/defectManagement.js | 44 +
src/views/equipmentManagement/defectManagement/index.vue | 221 +++++
src/views/inventoryManagement/stockManagement/index.vue | 25
src/views/collaborativeApproval/knowledgeBase/index.vue | 19
src/views/collaborativeApproval/sealManagement/index.vue | 74
10 files changed, 2,425 insertions(+), 48 deletions(-)
diff --git a/src/api/collaborativeApproval/enterpriseBook.js b/src/api/collaborativeApproval/enterpriseBook.js
new file mode 100644
index 0000000..2140b89
--- /dev/null
+++ b/src/api/collaborativeApproval/enterpriseBook.js
@@ -0,0 +1,67 @@
+import request from '@/utils/request'
+
+// 鏌ヨ涓汉閫氳褰�
+// 涓汉閫氳褰曢�氬父鏄敤鎴锋敹钘忔垨棰戠箒鑱旂郴鐨勪汉鍛�
+export function getPersonalContacts(page,query) {
+ return request({
+ url: '/staffContactsPersonal/getList',
+ method: 'get',
+ params: {
+ ...page,
+ ...query
+ }
+ })
+}
+
+// 娣诲姞鑱旂郴浜哄埌涓汉閫氳褰�
+export function addPersonalContact(data) {
+ return request({
+ url: '/staffContactsPersonal/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 浠庝釜浜洪�氳褰曠Щ闄よ仈绯讳汉
+export function removePersonalContact(id) {
+ return request({
+ url: '/staffContactsPersonal/delete/' + id,
+ method: 'delete'
+ })
+}
+
+// 鏌ヨ鍏叡閫氳褰�
+// 鍏叡閫氳褰曢�氬父鏄墍鏈夊憳宸ュ彲瑙佺殑鑱旂郴鏂瑰紡
+export function getPublicContacts(query) {
+ return request({
+ url: '/staff/contacts/public/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ鍗曚綅閫氳褰�
+// 鍗曚綅閫氳褰曢�氬父鎸夐儴闂ㄧ粍缁囩殑鍛樺伐鑱旂郴鏂瑰紡
+export function getCompanyContacts(query) {
+ return request({
+ url: '/staff/contacts/company/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ閮ㄩ棬閫氳褰曟爲缁撴瀯
+export function getDepartmentTree() {
+ return request({
+ url: '/staff/contacts/department/tree',
+ method: 'get'
+ })
+}
+
+// 鑾峰彇鍛樺伐璇︾粏淇℃伅
+export function getEmployeeDetail(employeeId) {
+ return request({
+ url: '/staff/staffOnJob/' + employeeId,
+ method: 'get'
+ })
+}
\ No newline at end of file
diff --git a/src/api/equipmentManagement/defectManagement.js b/src/api/equipmentManagement/defectManagement.js
new file mode 100644
index 0000000..c52eff9
--- /dev/null
+++ b/src/api/equipmentManagement/defectManagement.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request';
+
+// 鐧昏缂洪櫡
+export function registerDefect(data) {
+ return request({
+ url: '/defect/add',
+ method: 'post',
+ data
+ });
+}
+
+// 鑾峰彇缂洪櫡鍒楄〃
+export function getDefectList() {
+ return request({
+ url: '/defect/page',
+ method: 'get'
+ });
+}
+
+// 娑堥櫎缂洪櫡-淇敼鐘舵��
+export function eliminateDefect(data) {
+ return request({
+ url: '/defect/update',
+ method: 'post',
+ data
+ });
+}
+//鍒犻櫎
+export function deleteDefect(id) {
+ return request({
+ url: '/defect/delete',
+ method: 'delete',
+ id
+ });
+}
+
+
+// 鑾峰彇缂洪櫡璁惧鍙拌处
+export function getDefectLedger(deviceLedgerId) {
+ return request({
+ url: '/defect//find/' + deviceLedgerId,
+ method: 'get'
+ });
+}
\ No newline at end of file
diff --git a/src/api/equipmentManagement/spareParts.js b/src/api/equipmentManagement/spareParts.js
new file mode 100644
index 0000000..2b64689
--- /dev/null
+++ b/src/api/equipmentManagement/spareParts.js
@@ -0,0 +1,58 @@
+import request from "@/utils/request";
+/**
+ * 澶囦欢鍒嗙被-鏍戝垪琛�
+ */
+export const getSparePartsTree = (params) => {
+ return request({
+ url: "/spareParts/getTree",
+ method: "get",
+ params,
+ });
+};
+/**
+ * 澶囦欢鍒嗙被-鍒嗛〉鏌ヨ鍒楄〃
+ */
+export const getSparePartsList = (params) => {
+ return request({
+ url: "/spareParts/listPage",
+ method: "get",
+ params,
+ });
+};
+
+/**
+ * @desc 鏂板
+ */
+export const addSparePart = (data) => {
+ return request({
+ url: "/spareParts/add",
+ method: "post",
+ data,
+ });
+};
+
+/**
+ * @desc 缂栬緫
+ */
+export const editSparePart = (data) => {
+ return request({
+ url: "/spareParts/update",
+ method: "post",
+ data,
+ });
+};
+
+/**
+ * @desc 鍒犻櫎鎶ヤ慨
+ * @param {缂栧彿} ids
+ * @returns
+ */
+export const delSparePart = (id) => {
+ return request({
+ url: '/spareParts/delete/'+id,
+ method: "delete",
+
+ });
+};
+
+
diff --git a/src/views/collaborativeApproval/enterpriseBook/index.vue b/src/views/collaborativeApproval/enterpriseBook/index.vue
new file mode 100644
index 0000000..a451762
--- /dev/null
+++ b/src/views/collaborativeApproval/enterpriseBook/index.vue
@@ -0,0 +1,802 @@
+<template>
+ <div class="app-container">
+ <!-- 澶撮儴瀵艰埅 -->
+ <!-- <div class="header">
+ <h2>浼佷笟閫氳褰曠鐞�</h2>
+ <p>绠$悊涓汉銆佸叕鍏卞拰鍗曚綅鐨勮仈绯绘柟寮�</p>
+ </div> -->
+
+ <!-- 鏍囩椤靛垏鎹� -->
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange" type="border-card">
+ <el-tab-pane label="涓汉閫氳褰�" name="personal">
+ <div class="tab-content">
+ <!-- 鎼滅储妗� -->
+ <el-input
+ v-model="personalSearch.staffName"
+ placeholder="鎼滅储鑱旂郴浜�"
+ clearable
+ prefix-icon="Search"
+ class="search-input"
+ @keyup.enter="getPersonalContactsList"
+ />
+ <el-button style="margin: 0 0 20px 20px;" type="primary" @click="showAddContactDialog=true">娣诲姞鑱旂郴浜�</el-button>
+ <!-- 鑱旂郴浜哄垪琛� -->
+ <div class="contact-list">
+ <div
+ v-for="contact in personalContacts"
+ :key="contact.id"
+ class="contact-card"
+ @click="showContactDetail(contact)"
+ >
+ <div class="contact-avatar">{{ contact.staffName.charAt(0) }}</div>
+ <div class="contact-info">
+ <h4>{{ contact.staffName }}</h4>
+ <p>{{ contact.profession }} - {{ contact.postJob }}</p>
+ <div class="contact-phone">{{ contact.phone }}</div>
+ </div>
+ <div class="contact-actions">
+ <!-- <el-button
+ type="text"
+ icon="Phone"
+ @click.stop="callContact(contact)"
+ ></el-button> -->
+ <el-button
+ type="text"
+ icon="Message"
+ @click.stop="messageContact(contact)"
+ ></el-button>
+ <el-button
+ type="text"
+ icon="Delete"
+ @click.stop="removeFromPersonalContacts(contact.id)"
+ ></el-button>
+ </div>
+ </div>
+
+ <!-- 绌虹姸鎬�
+ <div v-if="personalContacts.length === 0 && !loading" class="empty-state">
+ <el-empty description="鏆傛棤鑱旂郴浜�" />
+ <el-button type="primary" @click="showAddContactDialog=true">娣诲姞鑱旂郴浜�</el-button>
+ </div> -->
+ </div>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane label="鍏叡閫氳褰�" name="public">
+ <div class="tab-content">
+ <!-- 鎼滅储妗� -->
+ <el-input
+ v-model="publicSearch.staffName"
+ placeholder="鎼滅储鍏叡鑱旂郴浜�"
+ clearable
+ prefix-icon="Search"
+ class="search-input"
+ @keyup.enter="getPublicContactsList"
+ />
+
+ <!-- 鑱旂郴浜哄垪琛� publicContacts-->
+ <div class="contact-list">
+ <div
+ v-for="contact in EmployeeList"
+ :key="contact.id"
+ class="contact-card"
+ @click="showContactDetail(contact)"
+ >
+ <div class="contact-avatar">{{ contact.staffName.charAt(0) }}</div>
+ <div class="contact-info">
+ <h4>{{ contact.staffName }}</h4>
+ <p>{{ contact.postJob }} - {{ contact.profession }}</p>
+ <div class="contact-phone">{{ contact.phone }}</div>
+ </div>
+ <div class="contact-actions">
+ <!-- <el-button
+ type="text"
+ icon="Phone"
+ @click.stop="callContact(contact)"
+ ></el-button> -->
+ <el-button
+ type="text"
+ icon="Message"
+ @click.stop="messageContact(contact)"
+ ></el-button>
+ <el-button
+ type="text"
+ icon="Delete"
+ :type="isInPersonalContacts(contact.id) ? 'primary' : ''"
+ @click.stop="togglePersonalContact(contact)"
+ ></el-button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane label="鍗曚綅閫氳褰�" name="company">
+ <div class="tab-content">
+ <div class="company-contacts-layout">
+ <!-- 宸︿晶閮ㄩ棬鏍� -->
+ <div class="department-tree">
+ <!-- <h3>閮ㄩ棬缁撴瀯</h3>
+ <el-tree
+ :data="departmentTree"
+ :props="{ label: 'deptName', children: 'children' }"
+ node-key="deptId"
+ ref="departmentTreeRef"
+ highlight-current
+ default-expand-all
+ @node-click="handleDepartmentClick"
+ /> -->
+ <el-col >
+ <div class="head-container">
+ <el-input
+ v-model="deptName"
+ placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�"
+ clearable
+ prefix-icon="Search"
+ style="margin-bottom: 20px"
+ />
+ </div>
+ <div class="head-container">
+ <el-tree
+ :data="departmentTree"
+ :props="{ label: 'label', children: 'children' }"
+ :expand-on-click-node="false"
+ :filter-node-method="filterNode"
+ ref="deptTreeRef"
+ node-key="id"
+ highlight-current
+ default-expand-all
+ @node-click="handleDepartmentClick"
+ />
+ </div>
+ </el-col>
+ </div>
+
+ <!-- 鍙充晶閮ㄩ棬鎴愬憳 -->
+ <div class="department-members">
+ <h3>{{ currentDepartment?.label || '鍏ㄩ儴鎴愬憳' }}</h3>
+ <el-input
+ v-model="companySearch.staffName"
+ placeholder="鎼滅储閮ㄩ棬鎴愬憳"
+ clearable
+ prefix-icon="Search"
+ class="search-input"
+ @keyup.enter="getCompanyContactsList"
+ />
+
+ <div class="contact-list">
+ <div
+ v-for="contact in companyContacts"
+ :key="contact.id"
+ class="contact-card"
+ @click="showContactDetail(contact)"
+ >
+ <div class="contact-avatar">{{ contact.staffName.charAt(0) }}</div>
+ <div class="contact-info">
+ <h4>{{ contact.staffName }}</h4>
+ <p>{{ contact.profession }}</p>
+ <div class="contact-phone">{{ contact.phone }}</div>
+ </div>
+ <div class="contact-actions">
+
+ <el-button
+ type="text"
+ icon="Message"
+ @click.stop="messageContact(contact)"
+ ></el-button>
+ <el-button
+ type="text"
+ icon="Delete"
+ :type="isInPersonalContacts(contact.id) ? 'primary' : ''"
+ @click.stop="togglePersonalContact(contact)"
+ ></el-button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </el-tab-pane>
+ </el-tabs>
+
+ <!-- 鑱旂郴浜鸿鎯呭脊绐� -->
+ <el-dialog
+ v-model="showDetailDialog"
+ title="鑱旂郴浜鸿鎯�"
+ width="400px"
+ >
+ <div v-if="selectedContact" class="contact-detail">
+ <div class="detail-avatar">{{ selectedContact.staffName?.charAt(0) }}</div>
+ <h3>{{ selectedContact.staffName }}</h3>
+ <p class="detail-position">{{ selectedContact.profession }} - {{ selectedContact.postJob }}</p>
+
+ <div class="detail-info">
+ <div class="info-item">
+ <span class="label">缂栧彿锛�</span>
+ <span class="value">{{ selectedContact.staffNo }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">鎵嬫満鍙风爜锛�</span>
+ <span class="value">{{ selectedContact.phone }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">閭锛�</span>
+ <span class="value">{{ selectedContact.sex }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">浣忓潃锛�</span>
+ <span class="value">{{ selectedContact.adress || '鏆傛棤' }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">韬唤璇佸彿锛�</span>
+ <span class="value">{{ selectedContact.identityCard || '鏆傛棤' }}</span>
+ </div>
+ </div>
+ </div>
+ <template #footer>
+ <el-button @click="showDetailDialog = false">鍏抽棴</el-button>
+ <el-button
+ type="primary"
+ v-if="activeTab !== 'personal'"
+ @click="togglePersonalContact(selectedContact); showDetailDialog = false"
+ >
+ {{ isInPersonalContacts(selectedContact?.id) ? '浠庝釜浜洪�氳褰曠Щ闄�' : '娣诲姞鍒颁釜浜洪�氳褰�' }}
+ </el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 娣诲姞鑱旂郴浜哄脊绐� -->
+ <el-dialog
+ v-model="showAddContactDialog"
+ title="娣诲姞鑱旂郴浜�"
+ width="500px"
+ >
+ <el-form :model="addContactForm" ref="addContactFormRef" label-width="80px">
+ <!-- <el-form-item label="濮撳悕" prop="name">
+ <el-input v-model="addContactForm.name" placeholder="璇疯緭鍏ュ鍚�" />
+ </el-form-item>
+ <el-form-item label="鎵嬫満鍙风爜" prop="phone">
+ <el-input v-model="addContactForm.phone" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" />
+ </el-form-item>
+ <el-form-item label="閭" prop="email">
+ <el-input v-model="addContactForm.email" placeholder="璇疯緭鍏ラ偖绠�" />
+ </el-form-item>
+ <el-form-item label="閮ㄩ棬" prop="department">
+ <el-input v-model="addContactForm.department" placeholder="璇疯緭鍏ラ儴闂�" />
+ </el-form-item> -->
+ <el-form-item label="濮撳悕" prop="name">
+ <!-- <select v-model="addContactForm.contactId">
+ <option v-for="item in EmployeeList" :key="item.id" :value="item.id">{{ item.staffName }}</option>
+ </select> -->
+ <el-select v-model="addContactForm.contactId" placeholder="璇烽�夋嫨" style="width: 100%">
+ <el-option
+ v-for="option in EmployeeList"
+ :key="option.id"
+ :label="option.staffName"
+ :value="option.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button @click="showAddContactDialog = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="addContact">纭畾</el-button>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, reactive, computed } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import {
+ getPersonalContacts,
+ addPersonalContact,
+ removePersonalContact,
+ getPublicContacts,
+ getCompanyContacts,
+ getDepartmentTree,
+ getEmployeeDetail
+} from '@/api/collaborativeApproval/enterpriseBook.js'
+import { getUserProfile } from '@/api/system/user.js'
+import {staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
+import {
+ changeUserStatus,
+ listUser,
+ resetUserPwd,
+ delUser,
+ getUser,
+ updateUser,
+ addUser,
+ deptTreeSelect,
+} from "@/api/system/user";
+
+// 鏍囩椤电姸鎬�
+const activeTab = ref('personal')
+const loading = ref(false)
+const EmployeeList = ref([])
+const page = reactive({
+ pageNum: 1,
+ pageSize: 10,
+ total: 0,
+})
+// 涓汉閫氳褰曟暟鎹�
+const personalContacts = ref([])
+const personalSearch = ref({
+ staffName: '',
+})
+
+// 鍏叡閫氳褰曟暟鎹�
+const publicContacts = ref([])
+const publicSearch = ref({
+ staffName: '',
+ staffState: 1
+})
+
+// 鍗曚綅閫氳褰曟暟鎹�
+const companyContacts = ref([])
+const companySearch = ref({
+ staffName: '',
+ staffState: 1
+})
+const departmentTree = ref([])
+const departmentTreeRef = ref(null)
+const currentDepartment = ref(null)
+
+// 寮圭獥鐘舵��
+const showDetailDialog = ref(false)
+const showAddContactDialog = ref(false)
+const selectedContact = ref(null)
+
+// 娣诲姞鑱旂郴浜鸿〃鍗�
+const addContactForm = reactive({
+ contactId: '',
+ name: '',
+ phone: '',
+ email: '',
+ department: '',
+ position: ''
+})
+const addContactFormRef = ref(null)
+
+// 鍒濆鍖栨暟鎹�
+onMounted(() => {
+ getEmployeeList()
+ getPersonalContactsList()
+ if (activeTab.value === 'public') {
+ getPublicContactsList()
+ } else if (activeTab.value === 'company') {
+ getDepartmentTreeData()
+ getCompanyContactsList()
+ }
+})
+
+// 澶勭悊鏍囩椤靛垏鎹�
+const handleTabChange = (tabName) => {
+ if (tabName === 'public') {
+ getPublicContactsList()
+ } else if (tabName === 'company') {
+ getDepartmentTreeData()
+ getCompanyContactsList()
+ }
+}
+
+// 鑾峰彇涓汉閫氳褰曞垪琛�
+const getPersonalContactsList = async () => {
+ loading.value = true
+ getPersonalContacts(page,personalSearch.value).then(res => {
+ personalContacts.value = res.data.records
+ })
+ loading.value = false
+}
+
+// 鑾峰彇鍏叡閫氳褰曞垪琛�
+const getPublicContactsList = async () => {
+ loading.value = true
+ getEmployeeList()
+ // publicContacts.value = generateMockPublicContacts()
+ loading.value = false
+}
+ //鑾峰彇鍛樺伐鍒楄〃
+const getEmployeeList = async () => {
+ staffJoinListPage(publicSearch.value).then(res => {
+ console.log(res.data.records)
+ EmployeeList.value = res.data.records
+ }).catch(err => {})
+}
+// 鑾峰彇鍗曚綅閫氳褰曞垪琛�
+const getCompanyContactsList = async () => {
+ loading.value = true
+ staffJoinListPage(companySearch.value).then(res => {
+ // console.log(res.data.records)
+ companyContacts.value = res.data.records
+ }).catch(err => {})
+
+ loading.value = false
+ loading.value = false
+ // }
+}
+
+// 鑾峰彇閮ㄩ棬鏍戠粨鏋�
+const getDepartmentTreeData = async () => {
+ deptTreeSelect().then((response) => {
+ // console.log("Tree",response.data)
+ departmentTree.value = response.data;
+ // enabledDeptOptions.value = filterDisabledDept(
+ // JSON.parse(JSON.stringify(response.data))
+ // );
+ });
+}
+// /** 杩囨护绂佺敤鐨勯儴闂� */
+// function filterDisabledDept(deptList) {
+// return deptList.filter((dept) => {
+// if (dept.disabled) {
+// return false;
+// }
+// if (dept.children && dept.children.length) {
+// dept.children = filterDisabledDept(dept.children);
+// }
+// return true;
+// });
+// }
+// 澶勭悊閮ㄩ棬鐐瑰嚮
+const handleDepartmentClick = (data) => {
+ // console.log("鐐瑰嚮",data)
+ companySearch.value = {
+ ...companySearch.value,
+ deptId: data.id,
+ }
+ // currentDepartment.value = data.id
+ // 鑾峰彇璇ラ儴闂ㄧ殑鎴愬憳鍒楄〃
+
+ getCompanyContactsList()
+}
+
+// 鏄剧ず鑱旂郴浜鸿鎯�
+const showContactDetail = async (contact) => {
+ selectedContact.value = contact
+ showDetailDialog.value = true
+}
+
+// 鎷ㄦ墦鐢佃瘽
+const callContact = (contact) => {
+ ElMessage.info(`姝e湪鎷ㄦ墦 ${contact.name} 鐨勭數璇�: ${contact.phone}`)
+}
+
+// 鍙戦�佹秷鎭�
+const messageContact = (contact) => {
+ ElMessage.info(`姝e湪鍙戦�佹秷鎭粰 ${contact.name}`)
+}
+
+
+// 娣诲姞鑱旂郴浜�
+const addContact = async () => {
+
+ try {
+ // 琛ㄥ崟楠岃瘉
+ // if (!addContactForm.name || !addContactForm.phone) {
+ // ElMessage.warning('璇峰~鍐欏鍚嶅拰鎵嬫満鍙风爜')
+ // return
+ // }
+
+ const res = await addPersonalContact(addContactForm)
+ if (res.code === 200) {
+ ElMessage.success('娣诲姞鎴愬姛')
+ showAddContactDialog.value = false
+ getPersonalContactsList()
+ // 閲嶇疆琛ㄥ崟
+ Object.keys(addContactForm).forEach(key => {
+ addContactForm[key] = ''
+ })
+ }
+ } catch (error) {
+ ElMessage.error('娣诲姞澶辫触')
+ // 妯℃嫙娣诲姞鎴愬姛
+ personalContacts.value.push({
+ ...addContactForm,
+ id: Date.now(),
+ createTime: new Date().toISOString()
+ })
+ ElMessage.success('娣诲姞鎴愬姛')
+ showAddContactDialog.value = false
+ // 閲嶇疆琛ㄥ崟
+ Object.keys(addContactForm).forEach(key => {
+ addContactForm[key] = ''
+ })
+ }
+}
+
+// 浠庝釜浜洪�氳褰曠Щ闄�
+const removeFromPersonalContacts = async (contactId) => {
+ ElMessageBox.confirm(
+ '纭畾瑕佷粠涓汉閫氳褰曚腑绉婚櫎璇ヨ仈绯讳汉鍚楋紵',
+ '鎻愮ず',
+ {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }
+ ).then(async () => {
+ try {
+ const res = await removePersonalContact(contactId)
+ if (res.code === 200) {
+ ElMessage.success('绉婚櫎鎴愬姛')
+ getPersonalContactsList()
+ }
+ } catch (error) {
+ ElMessage.error('绉婚櫎澶辫触')
+ // 妯℃嫙绉婚櫎鎴愬姛
+ // personalContacts.value = personalContacts.value.filter(item => item.id !== contactId)
+ ElMessage.success('绉婚櫎鎴愬姛')
+ }
+ })
+}
+
+// 鍒囨崲涓汉閫氳褰�
+const togglePersonalContact = async (contact) => {
+ const isInPersonal = isInPersonalContacts(contact.id)
+ const contactId = contact.id
+ if (isInPersonal) {
+ // 浠庝釜浜洪�氳褰曠Щ闄�
+ //鏍规嵁contactId鏌ユ壘personalContacts涓搴旂殑椤癸紝鐒跺悗鍒犻櫎璇ラ」
+ const index = personalContacts.value.findIndex(item => item.contactId === contactId)
+ const personId = personalContacts.value[index].id
+ // console.log(personId)
+ await removeFromPersonalContacts(personId)
+ } else {
+ // 娣诲姞鍒颁釜浜洪�氳褰�
+ try {
+ const res = await addPersonalContact({contactId: contactId})
+ if (res.code === 200) {
+ ElMessage.success('娣诲姞鎴愬姛')
+ getPersonalContactsList()
+ }
+ } catch (error) {
+ ElMessage.error('娣诲姞澶辫触')
+ // 妯℃嫙娣诲姞鎴愬姛
+ // personalContacts.value.push({
+ // ...contact,
+ // id: contact.id || Date.now(),
+ // createTime: new Date().toISOString()
+ // })
+ // ElMessage.success('娣诲姞鎴愬姛')
+ }
+ }
+}
+
+// 妫�鏌ユ槸鍚﹀湪涓汉閫氳褰曚腑
+const isInPersonalContacts = (contactId) => {
+ return personalContacts.value.some(item => item.contactId === contactId)
+}
+
+// 鐢熸垚妯℃嫙閮ㄩ棬鏍戞暟鎹�
+const generateMockDepartmentTree = () => {
+ return [
+ {
+ deptId: 1,
+ deptName: '鎶�鏈儴',
+ children: [
+ {
+ deptId: 101,
+ deptName: '鍓嶇缁�'
+ },
+ {
+ deptId: 102,
+ deptName: '鍚庣缁�'
+ },
+ {
+ deptId: 103,
+ deptName: '娴嬭瘯缁�'
+ }
+ ]
+ },
+ {
+ deptId: 2,
+ deptName: '浜у搧閮�'
+ },
+ {
+ deptId: 3,
+ deptName: '浜轰簨閮�'
+ },
+ {
+ deptId: 4,
+ deptName: '璐㈠姟閮�'
+ }
+ ]
+}
+
+// 鐢熸垚妯℃嫙鍗曚綅閫氳褰曟暟鎹�
+// const generateMockCompanyContacts = (deptName) => {
+// const allContacts = getEmployeeList()
+
+// if (deptName) {
+// return allContacts.filter(contact => contact.postJob === deptName)
+// }
+// return allContacts
+// }
+
+</script>
+
+<style scoped>
+.header {
+ margin-bottom: 20px;
+ padding: 15px;
+ background: #f5f7fa;
+ border-radius: 8px;
+}
+
+.header h2 {
+ margin: 0 0 5px 0;
+ color: #303133;
+}
+
+.header p {
+ margin: 0;
+ color: #909399;
+ font-size: 14px;
+}
+
+.tab-content {
+ padding: 15px;
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.search-input {
+ margin-bottom: 20px;
+ width: 300px;
+}
+
+.contact-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 15px;
+}
+
+.contact-card {
+ display: flex;
+ align-items: center;
+ padding: 15px;
+ width: 500px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.3s;
+}
+
+.contact-card:hover {
+ background: #e9ecef;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+}
+
+.contact-avatar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 48px;
+ height: 48px;
+ background: #409eff;
+ color: #fff;
+ font-size: 20px;
+ font-weight: bold;
+ border-radius: 50%;
+ margin-right: 15px;
+}
+
+.contact-info {
+ flex: 1;
+}
+
+.contact-info h4 {
+ margin: 0 0 5px 0;
+ color: #303133;
+ font-size: 16px;
+}
+
+.contact-info p {
+ margin: 0 0 5px 0;
+ color: #606266;
+ font-size: 14px;
+}
+
+.contact-phone {
+ color: #409eff;
+ font-size: 14px;
+}
+
+.contact-actions {
+ display: flex;
+ gap: 5px;
+}
+
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 60px 20px;
+ color: #909399;
+}
+
+.company-contacts-layout {
+ display: flex;
+ gap: 20px;
+}
+
+.department-tree {
+ width: 250px;
+ padding: 15px;
+ background: #f8f9fa;
+ border-radius: 8px;
+}
+
+.department-tree h3 {
+ margin: 0 0 15px 0;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #e4e7ed;
+ color: #303133;
+ font-size: 16px;
+}
+
+.department-members {
+ flex: 1;
+}
+
+.department-members h3 {
+ margin: 0 0 15px 0;
+ color: #303133;
+ font-size: 16px;
+}
+
+.contact-detail {
+ text-align: center;
+}
+
+.detail-avatar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 80px;
+ height: 80px;
+ background: #409eff;
+ color: #fff;
+ font-size: 32px;
+ font-weight: bold;
+ border-radius: 50%;
+ margin: 0 auto 20px;
+}
+
+.contact-detail h3 {
+ margin: 0 0 10px 0;
+ color: #303133;
+ font-size: 20px;
+}
+
+.detail-position {
+ margin: 0 0 30px 0;
+ color: #606266;
+ font-size: 14px;
+}
+
+.detail-info {
+ text-align: left;
+}
+
+.info-item {
+ margin-bottom: 15px;
+}
+
+.info-item .label {
+ display: inline-block;
+ width: 100px;
+ color: #909399;
+ font-size: 14px;
+}
+
+.info-item .value {
+ color: #303133;
+ font-size: 14px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index 0839c16..68441c5 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -233,7 +233,7 @@
import { onMounted, ref, reactive, toRefs } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
-import { listKnowledgeBase, delKnowledgeBaseBatch,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
+import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
// 琛ㄥ崟楠岃瘉瑙勫垯
const rules = {
@@ -729,17 +729,14 @@
cancelButtonText: "鍙栨秷",
type: "warning",
}).then(() => {
- // 浠巑ockData涓垹闄ら�変腑鐨勯」
- selectedIds.value.forEach(id => {
- const index = mockData.findIndex(item => item.id === id);
- if (index !== -1) {
- mockData.splice(index, 1);
+ // console.log(selectedIds.value);
+ delKnowledgeBase(selectedIds.value).then(res => {
+ if(res.code == 200){
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ selectedIds.value = [];
+ getList();
}
- });
-
- ElMessage.success("鍒犻櫎鎴愬姛");
- selectedIds.value = [];
- getList();
+ })
}).catch(() => {
// 鐢ㄦ埛鍙栨秷
});
diff --git a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
new file mode 100644
index 0000000..27ee209
--- /dev/null
+++ b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
@@ -0,0 +1,746 @@
+<template>
+ <div class="app-container">
+
+ <!-- 瑙勭珷鍒跺害绠$悊-->
+ <el-card class="box-card">
+ <template #header>
+ <div class="card-header">
+ <span>瑙勭珷鍒跺害鍙戝竷</span>
+ </div>
+ </template>
+ <div class="tab-content">
+ <el-row :gutter="20" class="mb-20">
+ <span class="ml-10">鍒跺害鏍囬锛�</span>
+ <el-col :span="6">
+ <el-input v-model="regulationSearchForm.title" placeholder="璇疯緭鍏ュ埗搴︽爣棰�" clearable />
+ </el-col>
+ <span class="search_title">鍒跺害鍒嗙被锛�</span>
+ <el-col :span="4">
+ <el-select v-model="regulationSearchForm.category" placeholder="鍒跺害鍒嗙被" clearable>
+ <el-option label="浜轰簨鍒跺害" value="hr" />
+ <el-option label="璐㈠姟鍒跺害" value="finance" />
+ <el-option label="瀹夊叏鍒跺害" value="safety" />
+ <el-option label="鎶�鏈埗搴�" value="tech" />
+ </el-select>
+ </el-col>
+ <el-col :span="8">
+ <el-button type="primary" @click="searchRegulations">鎼滅储</el-button>
+ <el-button @click="resetRegulationSearch">閲嶇疆</el-button>
+ <el-button type="success" @click="handleAdd">
+ 鍙戝竷鍒跺害
+ </el-button>
+ </el-col>
+ </el-row>
+
+ <el-table :data="regulations" border v-loading="tableLoading" style="width: 100%">
+ <el-table-column prop="regulationNum" label="鍒跺害缂栧彿" width="120" />
+ <el-table-column prop="title" label="鍒跺害鏍囬" min-width="150" />
+ <el-table-column prop="category" label="鍒嗙被" width="120">
+ <template #default="scope">
+ <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="version" label="鐗堟湰" width="120" />
+ <el-table-column prop="createUserName" label="鍙戝竷浜�" width="120" />
+ <el-table-column prop="createTime" label="鍙戝竷鏃堕棿" width="180" />
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+ {{ scope.row.status === 'active' ? '鐢熸晥涓�' : '宸插簾姝�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="readCount" label="宸茶浜烘暟" width="100" />
+ <el-table-column label="鎿嶄綔" width="250" fixed="right">
+ <template #default="scope">
+ <el-button link @click="viewRegulation(scope.row)">鏌ョ湅</el-button>
+ <el-button link type="primary" @click="handleEdit(scope.row)">缂栬緫</el-button>
+ <el-button link type="danger" @click="repealEdit(scope.row)">搴熷純</el-button>
+ <el-button link type="success" @click="viewVersionHistory(scope.row)">鐗堟湰鍘嗗彶</el-button>
+ <el-button link type="warning" @click="viewReadStatus(scope.row)">闃呰鐘舵��</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </el-card>
+
+ <!-- 鐢ㄥ嵃鐢宠瀵硅瘽妗� -->
+ <!-- <el-dialog v-model="showSealApplyDialog" title="鐢宠鐢ㄥ嵃" width="600px">
+ <el-form :model="sealForm" :rules="sealRules" ref="sealFormRef" label-width="100px">
+ <el-form-item label="鐢宠缂栧彿" prop="applicationNum">
+ <el-input v-model="sealForm.applicationNum" placeholder="璇疯緭鍏ョ敵璇风紪鍙�" />
+ </el-form-item>
+ <el-form-item label="鐢宠鏍囬" prop="title">
+ <el-input v-model="sealForm.title" placeholder="璇疯緭鍏ョ敵璇锋爣棰�" />
+ </el-form-item>
+ <el-form-item label="鐢ㄥ嵃绫诲瀷" prop="sealType">
+ <el-select v-model="sealForm.sealType" placeholder="璇烽�夋嫨鐢ㄥ嵃绫诲瀷" style="width: 100%">
+ <el-option label="鍏珷" value="official" />
+ <el-option label="鍚堝悓涓撶敤绔�" value="contract" />
+ <el-option label="璐㈠姟涓撶敤绔�" value="finance" />
+ <el-option label="娉曚汉绔�" value="legal" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鐢宠鍘熷洜" prop="reason">
+ <el-input v-model="sealForm.reason" type="textarea" :rows="4" placeholder="璇疯缁嗚鏄庣敤鍗板師鍥�" />
+ </el-form-item>
+ <el-form-item label="绱ф�ョ▼搴�" prop="urgency">
+ <el-radio-group v-model="sealForm.urgency">
+ <el-radio label="normal">鏅��</el-radio>
+ <el-radio label="urgent">绱ф��</el-radio>
+ <el-radio label="very-urgent">鐗规��</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="showSealApplyDialog = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="submitSealApplication">鎻愪氦鐢宠</el-button>
+ </span>
+ </template>
+ </el-dialog> -->
+
+ <!-- 瑙勭珷鍒跺害鍙戝竷瀵硅瘽妗� -->
+ <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '鍙戝竷鍒跺害' : '缂栬緫鍒跺害'" width="800px">
+ <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
+ <el-form-item label="鍒跺害缂栧彿" prop="regulationNum">
+ <el-input v-model="regulationForm.regulationNum" placeholder="璇疯緭鍏ュ埗搴︾紪鍙�" />
+ </el-form-item>
+ <el-form-item label="鍒跺害鏍囬" prop="title">
+ <el-input v-model="regulationForm.title" placeholder="璇疯緭鍏ュ埗搴︽爣棰�" />
+ </el-form-item>
+ <el-form-item label="鍒跺害鍒嗙被" prop="category">
+ <el-select v-model="regulationForm.category" placeholder="璇烽�夋嫨鍒跺害鍒嗙被" style="width: 100%">
+ <el-option label="浜轰簨鍒跺害" value="hr" />
+ <el-option label="璐㈠姟鍒跺害" value="finance" />
+ <el-option label="瀹夊叏鍒跺害" value="safety" />
+ <el-option label="鎶�鏈埗搴�" value="tech" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍒跺害鍐呭" prop="content">
+ <el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="璇疯緭鍏ュ埗搴﹁缁嗗唴瀹�" />
+ </el-form-item>
+ <el-form-item label="鍒跺害鐗堟湰" prop="version">
+ <el-input v-model="regulationForm.version" placeholder="璇疯緭鍏ュ埗搴︾増鏈�" />
+ </el-form-item>
+ <el-form-item label="鐢熸晥鏃堕棿" prop="effectiveTime">
+ <el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss" placeholder="閫夋嫨鐢熸晥鏃堕棿" style="width: 100%" />
+ </el-form-item>
+ <el-form-item label="閫傜敤鑼冨洿" prop="scope">
+ <el-checkbox-group v-model="regulationForm.scope">
+ <el-checkbox label="all">鍏ㄤ綋鍛樺伐</el-checkbox>
+ <el-checkbox label="manager">绠$悊灞�</el-checkbox>
+ <el-checkbox label="hr">浜轰簨閮ㄩ棬</el-checkbox>
+ <el-checkbox label="finance">璐㈠姟閮ㄩ棬</el-checkbox>
+ <el-checkbox label="tech">鎶�鏈儴闂�</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="鏄惁闇�瑕佺‘璁�" prop="requireConfirm">
+ <el-switch v-model="regulationForm.requireConfirm" />
+ <span class="ml-10">寮�鍚悗鍛樺伐闇�瑕侀槄璇荤‘璁�</span>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="showRegulationDialog = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="submitRegulation">鍙戝竷鍒跺害</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 鐢ㄥ嵃璇︽儏瀵硅瘽妗� -->
+ <!-- <el-dialog v-model="showSealDetailDialog" title="鐢ㄥ嵃鐢宠璇︽儏" width="700px">
+ <div v-if="currentSealDetail" class="mb10">
+ <el-descriptions :column="2" border>
+ <el-descriptions-item label="鐢宠缂栧彿">{{ currentSealDetail.id }}</el-descriptions-item>
+ <el-descriptions-item label="鐢宠鏍囬">{{ currentSealDetail.title }}</el-descriptions-item>
+ <el-descriptions-item label="鐢宠浜�">{{ currentSealDetail.createUserName }}</el-descriptions-item>
+ <el-descriptions-item label="鎵�灞為儴闂�">{{ currentSealDetail.department }}</el-descriptions-item>
+ <el-descriptions-item label="鐢ㄥ嵃绫诲瀷">{{ getSealTypeText(currentSealDetail.sealType) }}</el-descriptions-item>
+ <el-descriptions-item label="鐢宠鏃堕棿">{{ currentSealDetail.createTime }}</el-descriptions-item>
+ <el-descriptions-item label="鐘舵��">
+ <el-tag :type="getStatusType(currentSealDetail.status)">
+ {{ getStatusText(currentSealDetail.status) }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="鐢宠鍘熷洜" :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
+ </el-descriptions>
+ </div>
+ </el-dialog> -->
+
+ <!-- 瑙勭珷鍒跺害璇︽儏瀵硅瘽妗� -->
+ <el-dialog v-model="showRegulationDetailDialog" title="瑙勭珷鍒跺害璇︽儏" width="800px">
+ <div v-if="currentRegulationDetail">
+ <el-descriptions :column="2" border>
+ <el-descriptions-item label="鍒跺害缂栧彿">{{ currentRegulationDetail.id }}</el-descriptions-item>
+ <el-descriptions-item label="鍒跺害鏍囬">{{ currentRegulationDetail.title }}</el-descriptions-item>
+ <el-descriptions-item label="鍒嗙被">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item>
+ <el-descriptions-item label="鐗堟湰">{{ currentRegulationDetail.version }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戝竷浜�">{{ currentRegulationDetail.createUserName }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戝竷鏃堕棿">{{ currentRegulationDetail.createTime }}</el-descriptions-item>
+ </el-descriptions>
+ <div class="mt-20">
+ <h4>鍒跺害鍐呭</h4>
+ <div class="regulation-content">{{ currentRegulationDetail.content }}</div>
+ </div>
+ <!-- 濡傛灉tableData>0 鏄剧ず -->
+ <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" >
+ <el-button type="success" @click="resetForm(currentRegulationDetail)">纭鏌ョ湅</el-button>
+ </div>
+ </div>
+ </el-dialog>
+
+ <!-- 鐗堟湰鍘嗗彶瀵硅瘽妗� -->
+ <el-dialog v-model="showVersionHistoryDialog" title="鐗堟湰鍘嗗彶" width="800px">
+ <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
+ <el-table-column prop="version" label="鐗堟湰鍙�" width="100" />
+ <el-table-column prop="updateTime" label="鏇存柊鏃堕棿" width="180" />
+ <el-table-column prop="createUserName" label="鏇存柊浜�" width="120" />
+ <el-table-column prop="changeLog" label="鍙樻洿璇存槑">
+ <template #default="scope">
+ <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+ {{ scope.row.status === 'active' ? '鐢熸晥涓�' : '宸插簾姝�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-dialog>
+
+ <!-- 闃呰鐘舵�佸璇濇 -->
+ <el-dialog v-model="showReadStatusDialog" title="闃呰鐘舵��" width="800px">
+ <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
+ <el-table-column prop="employee" label="鍛樺伐濮撳悕" width="120" />
+ <el-table-column prop="department" label="鎵�灞為儴闂�" width="150" />
+ <el-table-column prop="createTime" label="闃呰鏃堕棿" width="180" />
+ <el-table-column prop="confirmTime" label="纭鏃堕棿" width="180" />
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'">
+ {{ scope.row.status === 'confirmed' ? '宸茬‘璁�' : '鏈‘璁�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Plus } from '@element-plus/icons-vue'
+import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus } from '@/api/collaborativeApproval/sealManagement.js'
+import { el } from 'element-plus/es/locales.mjs'
+import { getUserProfile } from '@/api/system/user.js'
+import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
+import useUserStore from '@/store/modules/user'
+import { userLoginFacotryList } from "@/api/system/user.js"
+
+// 鍝嶅簲寮忔暟鎹�
+const currentUser = ref(null)
+const activeTab = ref('seal')
+const operationType = ref('add')
+const tableData = ref([])
+// 鐢ㄥ嵃鐢宠鐩稿叧
+const userStore = useUserStore()
+const showSealApplyDialog = ref(false)
+const tableLoading = ref(false)
+const showSealDetailDialog = ref(false)
+const currentSealDetail = ref(null)
+const sealFormRef = ref()
+const sealForm = reactive({
+ applicationNum: '',
+ title: '',
+ sealType: '',
+ reason: '',
+ urgency: 'normal',
+ status: 'pending'
+})
+
+const sealRules = {
+ applicationNum: [{ required: true, message: '璇疯緭鍏ョ敵璇风紪鍙�', trigger: 'blur' }],
+ title: [{ required: true, message: '璇疯緭鍏ョ敵璇锋爣棰�', trigger: 'blur' }],
+ sealType: [{ required: true, message: '璇烽�夋嫨鐢ㄥ嵃绫诲瀷', trigger: 'change' }],
+ reason: [{ required: true, message: '璇疯緭鍏ョ敵璇峰師鍥�', trigger: 'blur' }]
+}
+
+const sealSearchForm = reactive({
+ title: '',
+ status: ''
+})
+// 鍒嗛〉鍙傛暟
+const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0
+})
+// 瑙勭珷鍒跺害鐩稿叧
+const showRegulationDialog = ref(false)
+const showRegulationDetailDialog = ref(false)
+const showVersionHistoryDialog = ref(false)
+const showReadStatusDialog = ref(false)
+const currentRegulationDetail = ref(null)
+const regulationFormRef = ref()
+const regulationForm = reactive({
+ id: '',
+ regulationNum: '',
+ title: '',
+ category: '',
+ content: '',
+ version: '',
+ status: 'active',
+ readCount: 0,
+ effectiveTime: '',
+ scope: [],
+ requireConfirm: false
+})
+
+const readStatus = ref({
+ id: '',
+ ruleId: '',
+ employee: '',
+ department: '',
+ createTime: '',
+ confirmTime: '',
+ status: 'unconfirmed'
+})
+
+const regulationRules = {
+ title: [{ required: true, message: '璇疯緭鍏ュ埗搴︽爣棰�', trigger: 'blur' }],
+ category: [{ required: true, message: '璇烽�夋嫨鍒跺害鍒嗙被', trigger: 'change' }],
+ content: [{ required: true, message: '璇疯緭鍏ュ埗搴﹀唴瀹�', trigger: 'blur' }],
+ effectiveTime: [{ required: true, message: '璇烽�夋嫨鐢熸晥鏃堕棿', trigger: 'change' }],
+ scope: [{ required: true, message: '璇烽�夋嫨閫傜敤鑼冨洿', trigger: 'change' }]
+}
+
+const regulationSearchForm = reactive({
+ title: '',
+ category: ''
+})
+
+// 鍋囨暟鎹�
+const sealApplications = ref([])
+
+const regulations = ref([])
+
+const versionHistory = ref([])
+
+const readStatusList = ref([])
+ // { employee: '闄堝織寮�', department: '閿�鍞儴', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' },
+ // { employee: '鍒橀泤濠�', department: '鎶�鏈儴', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' },
+ // { employee: '鐜嬪缓鍥�', department: '璐㈠姟閮�', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' }
+
+// 鐢ㄥ嵃鐢宠鐘舵��
+const getStatusType = (status) => {
+ const statusMap = {
+ pending: 'warning',
+ approved: 'success',
+ rejected: 'danger'
+ }
+ return statusMap[status] || 'info'
+}
+// 鍒跺害鐘舵��
+const getStatusText = (status) => {
+ const statusMap = {
+ pending: '寰呭鎵�',
+ approved: '宸查�氳繃',
+ rejected: '宸叉嫆缁�'
+ }
+ return statusMap[status] || '鏈煡'
+}
+// 鐢ㄥ嵃绫诲瀷
+const getSealTypeText = (sealType) => {
+ const sealTypeMap = {
+ official: '鍏珷',
+ contract: '鍚堝悓涓撶敤绔�',
+ finance: '璐㈠姟涓撶敤绔�',
+ tegal: '鎶�鏈笓鐢ㄧ珷'
+ }
+ return sealTypeMap[sealType] || '鏈煡'
+}
+// 鍒跺害鍒嗙被
+const getCategoryText = (category) => {
+ const categoryMap = {
+ hr: '浜轰簨鍒跺害',
+ finance: '璐㈠姟鍒跺害',
+ safety: '瀹夊叏鍒跺害',
+ tech: '鎶�鏈埗搴�'
+ }
+ return categoryMap[category] || '鏈煡'
+}
+// 鎼滅储鍗扮珷鐢宠
+const searchSealApplications = () => {
+ page.current=1
+ getSealApplicationList()
+
+ // ElMessage.success('鎼滅储瀹屾垚')
+}
+// 閲嶇疆鍗扮珷鐢宠鎼滅储
+const resetSealSearch = () => {
+ sealSearchForm.title = ''
+ sealSearchForm.status = ''
+ searchSealApplications()
+}
+// 鎼滅储鍒跺害
+const searchRegulations = () => {
+ page.current=1
+ getRegulationList()
+}
+// 閲嶇疆鍒跺害鎼滅储
+const resetRegulationSearch = () => {
+ regulationSearchForm.title = ''
+ regulationSearchForm.category = ''
+ searchRegulations()
+}
+// 鎻愪氦鐢ㄥ嵃鐢宠
+const submitSealApplication = async () => {
+ try {
+ await sealFormRef.value.validate()
+ addSealApplication(sealForm).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鐢宠鎻愪氦鎴愬姛')
+ showSealApplyDialog.value = false
+ getSealApplicationList()
+ Object.assign(sealForm, {
+ applicationNum: '',
+ title: '',
+ sealType: '',
+ reason: '',
+ urgency: 'normal',
+ status: 'pending'
+ })
+ }
+ }).catch(err => {
+ ElMessage.error(err.msg)
+ })
+
+ } catch (error) {
+ ElMessage.error('璇峰畬鍠勭敵璇蜂俊鎭�')
+ }
+}
+// 鏂板
+const handleAdd = () => {
+ operationType.value = 'add'
+ resetRegulationForm()
+ showRegulationDialog.value = true
+}
+
+// 缂栬緫
+const handleEdit = (row) => {
+ operationType.value = 'edit'
+ Object.assign(regulationForm, row)
+ showRegulationDialog.value = true
+}
+// 搴熷純
+const repealEdit = (row) => {
+ operationType.value = 'edit'
+ Object.assign(regulationForm, row)
+ regulationForm.status = 'repealed'
+ ElMessageBox.confirm('纭搴熷純璇ュ埗搴︼紵', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }).then(() => {
+ updateRuleManagement(regulationForm).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鍒跺害搴熷純鎴愬姛')
+ // showRegulationDialog.value = false
+ getRegulationList()
+ resetRegulationForm()
+ }
+ })
+ }).catch(() => {
+ ElMessage({
+ type: 'info',
+ message: '宸插彇娑堝簾寮�'
+ })
+ })
+}
+// 鍙戝竷鍒跺害
+const submitRegulation = async () => {
+ try {
+ await regulationFormRef.value.validate()
+ if(operationType.value == 'add'){
+ addRuleManagement(regulationForm).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鍒跺害鍙戝竷鎴愬姛')
+ showRegulationDialog.value = false
+ getRegulationList()
+ resetRegulationForm()
+ }
+ })
+ }else{
+ updateRuleManagement(regulationForm).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鍒跺害缂栬緫鎴愬姛')
+ showRegulationDialog.value = false
+ resetRegulationForm()
+ getRegulationList()
+ }})}
+ }catch(err){
+ ElMessage.error(err.msg)
+ }
+}
+//閲嶇疆鍒跺害琛ㄥ崟
+const resetRegulationForm = () => {
+ Object.assign(regulationForm, {
+ id: '',
+ regulationNum: '',
+ title: '',
+ category: '',
+ content: '',
+ version: '',
+ status: 'active',
+ readCount: 0,
+ effectiveTime: '',
+ scope: [],
+ requireConfirm: false
+})
+}
+
+
+// 鏌ョ湅鐢ㄥ嵃鐢宠璇︽儏
+const viewSealDetail = (row) => {
+ currentSealDetail.value = row
+ showSealDetailDialog.value = true
+}
+// 瀹℃壒鐢ㄥ嵃鐢宠
+const approveSeal = (row) => {
+ console.log(row)
+ ElMessageBox.confirm('纭閫氳繃璇ョ敤鍗扮敵璇凤紵', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }).then(() => {
+ row.status = 'approved'
+ updateSealApplication(row).then(res => {
+ if(res.code == 200){
+ ElMessage.success('瀹℃壒閫氳繃')
+ }
+ })
+ })
+}
+// 鎷掔粷鐢ㄥ嵃鐢宠
+const rejectSeal = (row) => {
+ ElMessageBox.prompt('璇疯緭鍏ユ嫆缁濆師鍥�', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ inputPattern: /\S+/,
+ inputErrorMessage: '鎷掔粷鍘熷洜涓嶈兘涓虹┖'
+ }).then(({ value }) => {
+ row.status = 'rejected'
+ updateSealApplication(row).then(res => {
+ if(res.code == 200){
+ ElMessage.success('瀹℃壒鎷掔粷')
+ }
+ })
+ ElMessage.success('宸叉嫆缁濈敵璇�')
+ })
+}
+// 鑾峰彇鍦ㄨ亴鍛樺伐鍒楄〃
+const getList = () => {
+ tableLoading.value = true;
+ //鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛淇℃伅
+ getUserProfile().then(res => {
+ if(res.code == 200){
+ console.log(res.data.userName)
+ currentUser.value = res.data.userName
+ }
+ })
+ staffJoinListPage({staffState: 1}).then(res => {
+ tableLoading.value = false;
+ // tableData.value = res.data.records
+ // //绛涢�夊嚭鍜宑urrentUser鍚屽悕鐨勪汉鍛�
+ tableData.value = res.data.records.filter(item => item.staffName === currentUser.value)
+ console.log("tableData",tableData.value)
+ page.total = res.data.total;
+
+ if(tableData.value.length == 0){
+ ElMessage.error('褰撳墠鐢ㄦ埛鏈姞鍏ヤ换浣曢儴闂�')
+ }
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+
+
+};
+
+// 鏌ョ湅鍒跺害鐗堟湰鍘嗗彶
+const viewVersionHistory = (row) => {
+ showVersionHistoryDialog.value = true
+ const params = {
+
+ category: row.category
+ }
+ listRuleManagement(page,params).then(res => {
+ if(res.code == 200){
+ versionHistory.value = res.data.records
+ }
+ })
+}
+// 鏌ョ湅鍒跺害璇︽儏
+const viewRegulation = (row) => {
+ getList()
+ currentRegulationDetail.value = row
+ showRegulationDetailDialog.value = true
+ getReadingStatusByRuleId(row.id).then(res => {
+ if(res.code == 200){
+ readStatusList.value = res.data
+ if(readStatusList.value.length==0 && tableData.value.length>0){
+ const params = {
+ ruleId: row.id,
+ employee: tableData.value[0].staffName,
+ department: tableData.value[0].postJob,
+ status: 'unconfirmed'
+ }
+ addReadingStatus(params).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鍒跺害闃呰鎴愬姛')
+ }
+ })
+ }
+ }
+ })
+
+}
+// 鏌ョ湅鍒跺害闃呰鐘舵��
+const viewReadStatus = (row) => {
+ showReadStatusDialog.value = true
+ //鏌ョ湅闃呰鐘舵�佸垪琛�
+ getReadingStatusByRuleId(row.id).then(res => {
+ if(res.code == 200){
+ readStatusList.value = res.data
+ }
+ })
+}
+
+//纭鏌ョ湅
+const resetForm = (row) => {
+ console.log("row",row)
+ row.readCount = row.readCount + 1
+
+ updateRuleManagement(row).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鏌ョ湅鏁伴噺淇敼鎴愬姛')
+ //淇敼闃呰鐘舵��
+ //鏍规嵁鍒跺害id鍜屽綋鍓嶇櫥褰曠殑鍛樺伐寰楀埌闃呰鐘舵��
+ // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName )
+ // if(item.length>0){
+ // item[0].status = 'confirmed',
+ // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
+ // }
+ // 绛涢�夊綋鍓嶅憳宸ュ搴旇鍒跺害鐨勯槄璇荤姸鎬佽褰�
+ let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id);
+
+ if (statusItem) {
+ // 濡傛灉鎵惧埌璁板綍锛屾洿鏂扮姸鎬佸拰纭鏃堕棿
+ statusItem.status = 'confirmed';
+ // 鏍煎紡鍖栨椂闂翠负"YYYY-MM-DD HH:mm:ss"鏍煎紡
+ const now = new Date();
+ statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
+ // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
+
+ updateReadingStatus(statusItem).then(res => {
+ if(res.code == 200){
+ ElMessage.success('鍒跺害闃呰鐘舵�佷慨鏀规垚鍔�')
+ }
+ })
+ }
+
+ }
+ })
+}
+
+// 鑾峰彇鍗扮珷鐢宠鍒楄〃鏁版嵁
+const getSealApplicationList = async () => {
+ tableLoading.value = true
+ listSealApplication(page,sealSearchForm)
+ .then(res => {
+ //鑾峰彇褰撳墠鐧诲綍鐨勯儴闂ㄤ俊鎭�
+// 鑾峰彇褰撳墠鐧诲綍鐨勯儴闂ㄤ俊鎭苟杩囨护鏁版嵁
+ const currentFactoryName = userStore.currentFactoryName
+ if (currentFactoryName) {
+ // 鏍规嵁currentFactoryName杩囨护鍑篸epartment鐩稿悓鐨勬暟鎹�
+ sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName)
+ // 鏇存柊杩囨护鍚庣殑鎬绘暟
+ page.value.total = sealApplications.value.length
+ } else {
+ // 濡傛灉娌℃湁currentFactoryName锛屽垯鏄剧ず鎵�鏈夋暟鎹�
+ sealApplications.value = res.data.records
+ page.value.total = res.data.total
+ }
+ // sealApplications.value = res.data.records
+ // page.value.total = res.data.total;
+ tableLoading.value = false;
+
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+}
+// 鑾峰彇瑙勭珷鍒跺害鍒楄〃鏁版嵁
+const getRegulationList = async () => {
+ tableLoading.value = true
+ listRuleManagement(page,regulationSearchForm)
+ .then(res => {
+
+ regulations.value = res.data.records
+ // 杩囨护鎺夊凡搴熷純鐨勫埗搴�
+ // regulations.value = res.data.records.filter(item => item.status !== 'repealed')
+ page.value.total = res.data.total;
+ tableLoading.value = false;
+
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+}
+
+onMounted(() => {
+ // 鍒濆鍖�
+ getSealApplicationList()
+ getRegulationList()
+})
+</script>
+
+<style scoped>
+.app-container {
+ padding: 20px;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.tab-content {
+ padding: 20px 0;
+}
+
+.mb-20 {
+ margin-bottom: 20px;
+}
+
+.mt-20 {
+ margin-top: 20px;
+}
+
+.ml-10 {
+ margin-left: 10px;
+}
+
+.regulation-content {
+ background-color: #f5f5f5;
+ padding: 15px;
+ border-radius: 4px;
+ line-height: 1.6;
+ white-space: pre-wrap;
+ height: 200px;
+}
+
+.dialog-footer {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/sealManagement/index.vue b/src/views/collaborativeApproval/sealManagement/index.vue
index 4cf5a14..42d3ecf 100644
--- a/src/views/collaborativeApproval/sealManagement/index.vue
+++ b/src/views/collaborativeApproval/sealManagement/index.vue
@@ -3,22 +3,19 @@
<el-card class="box-card">
<template #header>
<div class="card-header">
- <span>鐢ㄥ嵃绠$悊涓庤绔犲埗搴﹀彂甯�</span>
- <el-button type="primary" @click="showSealApplyDialog = true">
- <el-icon><Plus /></el-icon>
- 鐢宠鐢ㄥ嵃
- </el-button>
+ <span>鐢ㄥ嵃绠$悊鍙戝竷</span>
</div>
</template>
- <el-tabs v-model="activeTab" type="border-card">
- <!-- 鐢ㄥ嵃鐢宠绠$悊 -->
- <el-tab-pane label="鐢ㄥ嵃鐢宠绠$悊" name="seal">
- <div class="tab-content">
- <el-row :gutter="20" class="mb-20">
+
+ <!-- 鐢ㄥ嵃鐢宠绠$悊 -->
+ <div class="tab-content">
+ <el-row :gutter="20" class="mb-20 ">
+ <span class="ml-10">鐢ㄥ嵃鏍囬锛�</span>
<el-col :span="6">
<el-input v-model="sealSearchForm.title" placeholder="璇疯緭鍏ョ敵璇锋爣棰�" clearable />
</el-col>
+ <span class="search_title">瀹℃壒鐘舵�侊細</span>
<el-col :span="4">
<el-select v-model="sealSearchForm.status" placeholder="瀹℃壒鐘舵��" clearable>
<el-option label="寰呭鎵�" value="pending" />
@@ -29,6 +26,8 @@
<el-col :span="4">
<el-button type="primary" @click="searchSealApplications">鎼滅储</el-button>
<el-button @click="resetSealSearch">閲嶇疆</el-button>
+ <el-button type="primary" @click="showSealApplyDialog = true">鐢宠鐢ㄥ嵃
+ </el-button>
</el-col>
</el-row>
@@ -72,12 +71,16 @@
</template>
</el-table-column>
</el-table>
- </div>
- </el-tab-pane>
+ </div>
+ </el-card>
+
+
+
+
<!-- 瑙勭珷鍒跺害绠$悊 -->
- <el-tab-pane label="瑙勭珷鍒跺害绠$悊" name="regulations">
- <div class="tab-content">
+
+ <!-- <div class="tab-content">
<el-row :gutter="20" class="mb-20">
<el-col :span="6">
<el-input v-model="regulationSearchForm.title" placeholder="璇疯緭鍏ュ埗搴︽爣棰�" clearable />
@@ -128,19 +131,9 @@
</template>
</el-table-column>
</el-table>
- <!-- 鍒嗛〉
- <pagination
- v-show="total > 0"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="page.current"
- :limit="page.size"
- @pagination="paginationChange"
- /> -->
- </div>
- </el-tab-pane>
- </el-tabs>
- </el-card>
+
+ </div> -->
+
<!-- 鐢ㄥ嵃鐢宠瀵硅瘽妗� -->
<el-dialog v-model="showSealApplyDialog" title="鐢宠鐢ㄥ嵃" width="600px">
@@ -179,7 +172,7 @@
</el-dialog>
<!-- 瑙勭珷鍒跺害鍙戝竷瀵硅瘽妗� -->
- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '鍙戝竷鍒跺害' : '缂栬緫鍒跺害'" width="800px">
+ <!-- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '鍙戝竷鍒跺害' : '缂栬緫鍒跺害'" width="800px">
<el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
<el-form-item label="鍒跺害缂栧彿" prop="regulationNum">
<el-input v-model="regulationForm.regulationNum" placeholder="璇疯緭鍏ュ埗搴︾紪鍙�" />
@@ -225,7 +218,7 @@
<el-button type="primary" @click="submitRegulation">鍙戝竷鍒跺害</el-button>
</span>
</template>
- </el-dialog>
+ </el-dialog> -->
<!-- 鐢ㄥ嵃璇︽儏瀵硅瘽妗� -->
<el-dialog v-model="showSealDetailDialog" title="鐢ㄥ嵃鐢宠璇︽儏" width="700px">
@@ -312,6 +305,8 @@
import { el } from 'element-plus/es/locales.mjs'
import { getUserProfile } from '@/api/system/user.js'
import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
+import useUserStore from '@/store/modules/user'
+import { userLoginFacotryList } from "@/api/system/user.js"
// 鍝嶅簲寮忔暟鎹�
const currentUser = ref(null)
@@ -319,6 +314,7 @@
const operationType = ref('add')
const tableData = ref([])
// 鐢ㄥ嵃鐢宠鐩稿叧
+const userStore = useUserStore()
const showSealApplyDialog = ref(false)
const tableLoading = ref(false)
const showSealDetailDialog = ref(false)
@@ -727,16 +723,26 @@
})
}
-
-
// 鑾峰彇鍗扮珷鐢宠鍒楄〃鏁版嵁
const getSealApplicationList = async () => {
tableLoading.value = true
listSealApplication(page,sealSearchForm)
.then(res => {
-
- sealApplications.value = res.data.records
- page.value.total = res.data.total;
+ //鑾峰彇褰撳墠鐧诲綍鐨勯儴闂ㄤ俊鎭�
+// 鑾峰彇褰撳墠鐧诲綍鐨勯儴闂ㄤ俊鎭苟杩囨护鏁版嵁
+ const currentFactoryName = userStore.currentFactoryName
+ if (currentFactoryName) {
+ // 鏍规嵁currentFactoryName杩囨护鍑篸epartment鐩稿悓鐨勬暟鎹�
+ sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName)
+ // 鏇存柊杩囨护鍚庣殑鎬绘暟
+ page.value.total = sealApplications.value.length
+ } else {
+ // 濡傛灉娌℃湁currentFactoryName锛屽垯鏄剧ず鎵�鏈夋暟鎹�
+ sealApplications.value = res.data.records
+ page.value.total = res.data.total
+ }
+ // sealApplications.value = res.data.records
+ // page.value.total = res.data.total;
tableLoading.value = false;
}).catch(err => {
diff --git a/src/views/equipmentManagement/defectManagement/index.vue b/src/views/equipmentManagement/defectManagement/index.vue
new file mode 100644
index 0000000..f35454f
--- /dev/null
+++ b/src/views/equipmentManagement/defectManagement/index.vue
@@ -0,0 +1,221 @@
+<template>
+ <div class="defect-management">
+ <!-- 鎿嶄綔鎸夐挳 -->
+ <div class="actions">
+ <el-button type="primary" @click="showRegisterDialog = true">鐧昏缂洪櫡</el-button>
+ </div>
+
+ <!-- 缂洪櫡鍒楄〃 -->
+ <el-table :data="defectList" style="width: 100%; margin-top: 10px;" border>
+ <el-table-column prop="deviceName" label="璁惧鍚嶇О" width="180"></el-table-column>
+ <el-table-column prop="defectDescription" label="缂洪櫡鎻忚堪" win-width="300"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��" width="220">
+ <template #default="{ row }">
+ <el-tag :type="row.status === '涓ラ噸缂洪櫡' ? 'danger' : 'success'">
+ {{ row.status }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="220">
+ <template #default="{ row }">
+ <el-button
+ v-if="row.status === '涓ラ噸缂洪櫡' || row.status === '涓�鑸己闄�'"
+ type="text"
+ @click="eliminateDefect(row)"
+ >
+ 娑堥櫎缂洪櫡
+ </el-button>
+ <!-- <el-button
+ v-if="row.status === '涓ラ噸缂洪櫡'"
+ type="text"
+ @click="transferToRepairOrder(row.id)"
+ >
+ 杞淮淇崟
+ </el-button> -->
+ <el-button type="text" @click="getLedger(row.deviceLedgerId)">
+ 鏌ョ湅鍙拌处
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 缂洪櫡鐧昏瀵硅瘽妗� -->
+ <el-dialog title="鐧昏璁惧缂洪櫡" v-model="showRegisterDialog" width="50%">
+ <el-form :model="defectForm" :rules="defectRules" ref="defectFormRef" label-width="100px">
+ <el-form-item label="璁惧鍚嶇О" prop="deviceName">
+ <el-select v-model="defectForm.deviceLedgerId" @change="setDeviceModel">
+ <el-option
+ v-for="(item, index) in deviceOptions"
+ :key="index"
+ :label="item.deviceName"
+ :value="item.id"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="缂洪櫡鎻忚堪" prop="defectDescription">
+ <el-input type="textarea" v-model="defectForm.defectDescription"></el-input>
+ </el-form-item>
+ <el-form-item label="璁惧鐘舵��" prop="status">
+ <el-radio-group v-model="defectForm.status">
+ <el-radio label="姝e父">姝e父</el-radio>
+ <el-radio label="涓�鑸己闄�">涓�鑸己闄�</el-radio>
+ <el-radio label="涓ラ噸缂洪櫡">涓ラ噸缂洪櫡</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="showRegisterDialog = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="submitDefectForm">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 缂洪櫡璁惧鍙拌处瀵硅瘽妗� -->
+ <el-dialog title="缂洪櫡璁惧鍙拌处" v-model="showLedgerDialog" width="80%">
+ <el-table :data="ledgerList" style="width: 100%; margin-top: 10px;" border>
+ <el-table-column prop="deviceName" label="璁惧鍚嶇О"></el-table-column>
+ <el-table-column prop="defectDescription" label="缂洪櫡鎻忚堪"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��"></el-table-column>
+ <el-table-column prop="eliminateTime" label="娑堢己鏃堕棿"></el-table-column>
+ </el-table>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive } from 'vue';
+import { ElMessage } from 'element-plus';
+import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
+// 鍋囪浠ヤ笅鏄悗绔帴鍙�
+import {
+ registerDefect,
+ getDefectList,
+ eliminateDefect as apiEliminateDefect,
+ getDefectLedger,
+ deleteDefect
+} from '@/api/equipmentManagement/defectManagement';
+
+// 缂洪櫡鍒楄〃
+const defectList = ref([]);
+// 鐧昏瀵硅瘽妗嗘樉绀虹姸鎬�
+const showRegisterDialog = ref(false);
+// 鍙拌处瀵硅瘽妗嗘樉绀虹姸鎬�
+const showLedgerDialog = ref(false);
+// 缂洪櫡琛ㄥ崟
+const defectForm = reactive({
+ deviceLedgerId: '',
+ defectDescription: '',
+ status: '',
+});
+const deviceOptions = ref([]);
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const defectRules = reactive({
+ deviceLedgerId: [{ required: true, message: '璇疯緭鍏ヨ澶囧悕绉�', trigger: 'blur' }],
+ defectDescription: [{ required: true, message: '璇疯緭鍏ョ己闄锋弿杩�', trigger: 'blur' }]
+});
+// 琛ㄥ崟寮曠敤
+const defectFormRef = ref(null);
+// 鍙拌处鍒楄〃
+const ledgerList = ref([]);
+
+const loadDeviceName = async () => {
+ const { data } = await getDeviceLedger();
+ // console.log(data);
+ deviceOptions.value = data;
+};
+
+// 鑾峰彇缂洪櫡鍒楄〃
+const fetchDefectList = async () => {
+ try {
+ const res = await getDefectList();
+ if (res.code === 200) {
+ defectList.value = res.data.records;
+ } else {
+ ElMessage.error(res.message || '鑾峰彇缂洪櫡鍒楄〃澶辫触');
+ }
+ } catch (error) {
+ ElMessage.error('鑾峰彇缂洪櫡鍒楄〃澶辫触');
+ }
+};
+
+// 鎻愪氦缂洪櫡鐧昏琛ㄥ崟
+const submitDefectForm = async () => {
+ if (!defectFormRef.value) return;
+ try {
+ await defectFormRef.value.validate();
+ const res = await registerDefect(defectForm);
+ if (res.code === 200) {
+ ElMessage.success('缂洪櫡鐧昏鎴愬姛');
+ showRegisterDialog.value = false;
+ fetchDefectList();
+ } else {
+ ElMessage.error(res.message || '缂洪櫡鐧昏澶辫触');
+ }
+ } catch (error) {
+ ElMessage.error('璇峰~鍐欏畬鏁磋〃鍗曚俊鎭�');
+ }
+};
+
+// 娑堥櫎缂洪櫡
+const eliminateDefect = async (row) => {
+
+ try {
+ const res = await apiEliminateDefect(row);
+ if (res.code === 200) {
+ ElMessage.success('缂洪櫡娑堥櫎鎴愬姛');
+ fetchDefectList();
+ } else {
+ ElMessage.error(res.message || '缂洪櫡娑堥櫎澶辫触');
+ }
+ } catch (error) {
+ ElMessage.error('缂洪櫡娑堥櫎澶辫触');
+ }
+};
+
+// // 杞淮淇伐鍗�
+// const transferToRepairOrder = async (id) => {
+// try {
+// const res = await transferToRepair(id);
+// if (res.code === 200) {
+// ElMessage.success('杞淮淇伐鍗曟垚鍔�');
+// } else {
+// ElMessage.error(res.message || '杞淮淇伐鍗曞け璐�');
+// }
+// } catch (error) {
+// ElMessage.error('杞淮淇伐鍗曞け璐�');
+// }
+// };
+
+// 鑾峰彇缂洪櫡璁惧鍙拌处
+const getLedger = async (deviceLedgerId) => {
+ try {
+ const res = await getDefectLedger(deviceLedgerId);
+ if (res.code === 200) {
+ ledgerList.value = res.data.records;
+ showLedgerDialog.value = true;
+ } else {
+ ElMessage.error(res.message || '鑾峰彇缂洪櫡璁惧鍙拌处澶辫触');
+ }
+ } catch (error) {
+ ElMessage.error('鑾峰彇缂洪櫡璁惧鍙拌处澶辫触');
+ }
+};
+
+// 缁勪欢鎸傝浇鏃惰幏鍙栫己闄峰垪琛�
+const onMounted = () => {
+ fetchDefectList();
+ loadDeviceName();
+};
+onMounted();
+</script>
+
+<style scoped>
+.defect-management {
+ padding: 20px;
+}
+
+.actions {
+ margin-bottom: 10px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/equipmentManagement/spareParts/index.vue b/src/views/equipmentManagement/spareParts/index.vue
new file mode 100644
index 0000000..f91d76f
--- /dev/null
+++ b/src/views/equipmentManagement/spareParts/index.vue
@@ -0,0 +1,417 @@
+<template>
+ <div class="spare-part-category">
+ <div class="table_list">
+ <div class="actions">
+ <el-text class="mx-1" size="large">璁惧鍒嗙被</el-text>
+ <div>
+ <el-button @click="fetchTreeData" :loading="loading">鍒锋柊</el-button>
+ <el-button type="primary" @click="addCategory" >鏂板</el-button>
+ </div>
+ </div>
+ <el-table
+ v-loading="loading"
+ :data="renderTableData"
+ style="width: 100%; margin-top: 10px;"
+ border
+ row-key="id"
+ :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+ >
+ <el-table-column prop="name" label="鍒嗙被鍚嶇О" width="450">
+ <template #default="{ row }">
+ <span :style="{ paddingLeft: getIndentation(row) + 'px' }">
+ {{ row.name }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="sparePartsNo" label="鍒嗙被缂栧彿" width="200"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="{ row }">
+ <el-tag type="success" size="small">{{ row.status }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="description" label="鎻忚堪" win-width="330"></el-table-column>
+ <el-table-column label="鎿嶄綔" width="180" fixed="right">
+ <template #default="{ row }">
+ <el-button
+ type="text"
+ size="small"
+ @click="() => editCategory(row)"
+ :disabled="loading"
+ >
+ 缂栬緫
+ </el-button>
+ <el-button
+ type="text"
+ size="small"
+ @click="() => deleteCategory(row.id)"
+ style="color: #f56c6c;"
+ :disabled="loading"
+ >
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <el-dialog title="鍒嗙被绠$悊" v-model="dialogVisible" width="60%">
+ <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
+ <el-form-item label="鍒嗙被鍚嶇О" prop="name">
+ <el-input v-model="form.name"></el-input>
+ </el-form-item>
+ <el-form-item label="鍒嗙被缂栧彿" prop="sparePartsNo">
+ <el-input v-model="form.sparePartsNo"></el-input>
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select v-model="form.status" placeholder="璇烽�夋嫨鐘舵��">
+ <el-option label="姝e父" value="姝e父"></el-option>
+ <el-option label="绂佺敤" value="绂佺敤"></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鎻忚堪" prop="description">
+ <el-input v-model="form.description"></el-input>
+ </el-form-item>
+ <el-form-item label="涓婄骇鍒嗙被" prop="parentId">
+ <el-select v-model="form.parentId" placeholder="璇烽�夋嫨涓婄骇鍒嗙被">
+ <el-option label="鏃犱笂绾у垎绫�" :value="null"></el-option>
+ <el-option
+ v-for="(item, index) in categories"
+ :key="index"
+ :label="item.name"
+ :value="item.id"
+
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false" :disabled="formLoading">鍙栨秷</el-button>
+ <el-button type="primary" @click="submitForm" :loading="formLoading">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, reactive, watch } from 'vue';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { getSparePartsList, addSparePart, editSparePart, delSparePart,getSparePartsTree } from "@/api/equipmentManagement/spareParts";
+
+// 鍔犺浇鐘舵��
+const loading = ref(false);
+const formLoading = ref(false);
+// 瀵硅瘽妗嗘樉绀虹姸鎬�
+const dialogVisible = ref(false);
+// 缂栬緫 ID
+const editId = ref(null);
+// 琛ㄦ牸鏁版嵁
+const categories = ref([]);
+// 娓叉煋鐢ㄧ殑琛ㄦ牸鏁版嵁
+// const renderTableData = computed(() => buildTree(categories.value));
+const renderTableData = ref([]);
+const operationType = ref('add')
+// 琛ㄥ崟寮曠敤
+const formRef = ref(null);
+// 琛ㄥ崟鏁版嵁
+const form = reactive({
+ id:'',
+ name: '',
+ sparePartsNo: '',
+ status: '',
+ description: '',
+ parentId: null
+});
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = reactive({
+ name: [
+ { required: true, message: '璇疯緭鍏ュ垎绫诲悕绉�', trigger: 'blur' }
+ ],
+ sparePartsNo: [
+ { required: true, message: '璇疯緭鍏ュ垎绫荤紪鍙�', trigger: 'blur' }
+ ],
+ status: [
+ { required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }
+ ]
+});
+// 鑾峰彇缂╄繘閲�
+const getIndentation = (row) => {
+ // 杩欓噷绠�鍗曡繑鍥� 20锛屽彲鏍规嵁瀹為檯闇�姹傚疄鐜板眰绾х缉杩涢�昏緫
+ return 20;
+};
+// 瀹氫箟 buildTree 鍑芥暟
+const buildTree = (flatData) => {
+ const map = {};
+ const result = [];
+ if(flatData){
+ return result;
+ }
+ flatData.forEach(item => {
+ map[item.id] = { ...item, children: [] };
+ });
+ flatData.forEach(item => {
+ if (item.parentId === null || !map[item.parentId]) {
+ result.push(map[item.id]);
+ } else {
+ map[item.parentId].children.push(map[item.id]);
+ }
+ });
+ return result;
+};
+//鑾峰彇鏍戝舰缁撴瀯
+const fetchTreeData = async () => {
+ fetchCategories();
+ try {
+ const res = await getSparePartsTree();
+ if (res.code === 200) {
+ renderTableData.value = res.data;
+ } else {
+ ElMessage.error(res.message || '鑾峰彇鍒嗙被鍒楄〃澶辫触');
+ }
+ }catch (error) {
+ ElMessage.error('鑾峰彇鍒嗙被鍒楄〃澶辫触');
+ }
+}
+
+// 鑾峰彇鍒嗙被鍒楄〃
+const fetchCategories = async () => {
+ loading.value = true;
+ try {
+ const res = await getSparePartsList();
+ if (res.code === 200) {
+ categories.value = res.data.records;
+ } else {
+ ElMessage.error(res.message || '鑾峰彇鍒嗙被鍒楄〃澶辫触');
+ }
+ } catch (error) {
+ ElMessage.error('鑾峰彇鍒嗙被鍒楄〃澶辫触');
+ } finally {
+ loading.value = false;
+ }
+};
+
+// 鏂板鍒嗙被
+const addCategory = () => {
+ form.id = '';
+ form.name = '';
+ form.sparePartsNo = '';
+ form.status = '';
+ form.description = '';
+ form.parentId = null;
+ operationType.value = 'add'
+ dialogVisible.value = true;
+ console.log('dialogVisible 鏇存柊涓�', dialogVisible.value);
+};
+
+// 缂栬緫鍒嗙被
+const editCategory = (row) => {
+ Object.assign(form, row);
+ operationType.value = 'edit'
+ dialogVisible.value = true;
+};
+
+// 鍒犻櫎鍒嗙被
+const deleteCategory = async (id) => {
+ try {
+ await ElMessageBox.confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ュ垎绫伙紝鏄惁缁х画?', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ });
+ loading.value = true;
+ const res = await delSparePart(id);
+ if (res.code === 200) {
+ ElMessage.success('鍒犻櫎鎴愬姛');
+ fetchTreeData();
+ } else {
+ ElMessage.error(res.message || '鍒犻櫎澶辫触');
+ }
+ } catch (error) {
+ if (error !== 'cancel') {
+ ElMessage.error('鍒犻櫎澶辫触');
+ }
+ } finally {
+ loading.value = false;
+ }
+};
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+ if (!formRef.value) return;
+ try {
+ await formRef.value.validate();
+ formLoading.value = true;
+ if (operationType.value === 'edit') {
+ let res = await editSparePart(form);
+ if (res.code === 200) {
+ ElMessage.success('缂栬緫鎴愬姛');
+ dialogVisible.value = false;
+ fetchTreeData();
+ }
+ } else {
+ let res = await addSparePart(form);
+ if (res.code === 200) {
+ ElMessage.success('缂栬緫鎴愬姛');
+ dialogVisible.value = false;
+ fetchTreeData();
+ }
+ }
+ } catch (error) {
+ ElMessage.error('璇峰~鍐欏畬鏁磋〃鍗曚俊鎭�');
+ } finally {
+ formLoading.value = false;
+ }
+};
+
+// 缁勪欢鎸傝浇鏃惰幏鍙栧垎绫诲垪琛�
+onMounted(() => {
+ fetchCategories();
+ fetchTreeData();
+});
+</script>
+
+<style scoped>
+.spare-part-category {
+ padding: 20px;
+}
+.table_list {
+ margin-top: unset;
+}
+.actions {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 10px;
+ align-items: center;
+}
+
+/* 宓屽鏍戝舰缁撴瀯鏍峰紡 */
+.nested-tree-node {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ padding: 0 4px;
+ height: 30px;
+ line-height: 30px;
+}
+
+.category-code {
+ color: #606266;
+ font-size: 12px;
+ margin-left: 8px;
+}
+
+.tree-actions {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-left: auto;
+}
+
+/* 琛ㄦ牸鏍峰紡璋冩暣 */
+.el-table {
+ font-size: 14px;
+}
+
+.el-table__header-wrapper th {
+ background-color: #f5f7fa;
+ font-weight: 600;
+}
+
+.el-table__row:hover > td {
+ background-color: #fafafa;
+}
+
+/* 宓屽鏍戝舰缁撴瀯鐗瑰畾鏍峰紡 */
+.nested-tree {
+ background-color: transparent;
+}
+
+.nested-tree .el-tree-node__content {
+ height: auto;
+ background-color: transparent;
+}
+
+/* 鎼滅储妗嗘牱寮忚皟鏁� */
+.actions .el-input {
+ margin-right: 10px;
+ width: 200px;
+}
+
+/* 鎸夐挳缁勬牱寮� */
+.actions > div {
+ display: flex;
+ gap: 10px;
+}
+
+/* 纭繚琛ㄦ牸涓殑鎿嶄綔鎸夐挳涓嶄細琚埅鏂� */
+.el-table-column--fixed-right .el-button {
+ margin: 0 2px;
+}
+
+/* 鏍戝舰鑺傜偣鍐呭鏍峰紡 */
+.nested-tree .el-tree-node__expand-icon {
+ font-size: 12px;
+ margin-right: 4px;
+}
+
+/* 绌虹姸鎬佹牱寮� */
+.el-table .cell:empty::before {
+ content: '-';
+ color: #c0c4cc;
+}
+
+/* 灞曞紑/鎶樺彔鍔熻兘鏍峰紡 */
+.expand-icon {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ text-align: center;
+ line-height: 20px;
+ cursor: pointer;
+ font-size: 12px;
+ color: #909399;
+}
+
+.expand-icon.expanded {
+ color: #409eff;
+}
+
+/* 灞曞紑鍐呭鏍峰紡 */
+.expand-content {
+ padding: 10px 20px;
+}
+
+/* 瀛愮骇鍐呭鏍峰紡 */
+.child-content {
+ padding-left: 40px;
+}
+
+/* 鏃犲瓙鍒嗙被鎻愮ず鏍峰紡 */
+.no-children {
+ padding: 10px 20px;
+ color: #909399;
+ font-size: 14px;
+}
+
+/* 纭繚灞曞紑鐨勮〃鏍兼牱寮忔纭� */
+.el-table .el-table__expanded-cell {
+ background-color: #fafafa;
+}
+
+/* 灞曞紑鐨勫瓙琛ㄦ牸鏍峰紡 */
+.el-table .el-table {
+ border-top: none;
+ border-bottom: none;
+}
+
+/* 灞曞紑鐨勫瓙琛ㄦ牸鍗曞厓鏍兼牱寮� */
+.expand-content .el-table__body-wrapper .el-table__row {
+ background-color: #ffffff;
+}
+
+.expand-content .el-table__body-wrapper .el-table__row:hover > td {
+ background-color: #fafafa;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/inventoryManagement/stockManagement/index.vue b/src/views/inventoryManagement/stockManagement/index.vue
index b4a29eb..59dd74c 100644
--- a/src/views/inventoryManagement/stockManagement/index.vue
+++ b/src/views/inventoryManagement/stockManagement/index.vue
@@ -115,7 +115,6 @@
</el-col>
</el-row>
<el-row :gutter="30">
-
<el-col :span="12">
<el-form-item label="鍑哄簱浜猴細" prop="entryPerson">
<el-select v-model="form.createUser" placeholder="璇烽�夋嫨" clearable>
@@ -123,6 +122,11 @@
</el-select>
</el-form-item>
</el-col>
+ <el-col :span="12">
+ <el-form-item label="鏈�浣庡簱瀛橈細" prop="minStock">
+ <el-input v-model="form.minStock" placeholder="璇疯緭鍏ユ渶浣庡簱瀛�" clearable />
+ </el-form-item>
+ </el-col>
</el-row>
</el-form>
<template #footer>
@@ -149,7 +153,8 @@
exportStockManage
} from "@/api/inventoryManagement/stockManage.js";
import {
- updateManagement
+ updateManagement,
+
} from "@/api/inventoryManagement/stockIn.js";
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
@@ -194,6 +199,7 @@
inboundBatch: '',
stockQuantity: '',
boundTime: '',
+ minStock: '', // 鏂板鏈�浣庡簱瀛樺瓧娈�
},
rules: {
supplierName: [{ required: true, message: '璇疯緭鍏ヤ緵搴斿晢鍚嶇О', trigger: 'blur' }],
@@ -207,7 +213,8 @@
taxExclusiveTotalPrice: [{ required: true, message: '璇疯緭鍏ヤ笉鍚◣鎬讳环', trigger: 'blur' }],
boundTime: [{ required: true, message: '璇烽�夋嫨搴撳瓨鏃堕棿', trigger: 'change' }],
inboundTime: [{ required: true, message: '璇烽�夋嫨鍏ュ簱鏃堕棿', trigger: 'change' }],
- inboundPerson: [{ required: true, message: '璇烽�夋嫨鍑哄簱浜�', trigger: 'change' }]
+ inboundPerson: [{ required: true, message: '璇烽�夋嫨鍑哄簱浜�', trigger: 'change' }],
+ minStock: [{ required: true, message: '璇疯緭鍏ユ渶浣庡簱瀛�', trigger: 'blur' }],
}
})
const { searchForm, form, rules } = toRefs(data)
@@ -310,10 +317,21 @@
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛")
closeDia()
getList()
+ // 鎻愪氦鍚庢鏌ュ簱瀛樺苟灏濊瘯鍒涘缓璇疯喘鍗�
+ checkStockAndAutoCreatePurchase();
})
}
})
}
+// 妫�鏌ュ簱瀛樺苟鑷姩鍒涘缓璇疯喘鍗�
+const checkStockAndAutoCreatePurchase = async () => {
+ try {
+ await checkStockAndCreatePurchase();
+ } catch (error) {
+ console.error('鑷姩琛ヨ揣澶辫触:', error);
+ proxy.$modal.msgError('鑷姩琛ヨ揣澶辫触锛岃鎵嬪姩澶勭悊');
+ }
+};
// 鍏抽棴寮规
const closeDia = () => {
proxy.resetForm("formRef")
@@ -376,6 +394,7 @@
}
onMounted(() => {
getList()
+ checkStockAndAutoCreatePurchase();
})
</script>
--
Gitblit v1.9.3