修复 admin 构建门禁与类型错误,清理死代码
- tsconfig.node.json 启用 composite,让 vue-tsc --noEmit 真正生效 - 修复 24 处 antd-vue 4.x 类型错误(Table columns、Tree data、 RangePicker null、Progress format 回调等) - 删除未被引用的 axios 封装与 api 聚合(admin/utils/request.ts、 admin/api/index.ts、miniprogram/utils/request.js) - 新增 .githooks/pre-commit:admin 源码变更时自动 pnpm run build Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
f9772b99cb
commit
077495a401
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 仅当本次提交涉及 admin 源代码或配置时,运行 admin 构建(含 vue-tsc 类型检查)
|
||||||
|
# 通过检查暂存区是否有 zhican/admin/ 下的相关文件来决定
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CHANGED=$(git diff --cached --name-only --diff-filter=ACMR \
|
||||||
|
| grep -E '^zhican/admin/(src/|.*\.(json|ts|html))' || true)
|
||||||
|
|
||||||
|
if [ -z "$CHANGED" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "→ pre-commit: 检测到 admin 变更,运行 pnpm run build..."
|
||||||
|
cd "$(git rev-parse --show-toplevel)/zhican/admin"
|
||||||
|
|
||||||
|
if ! command -v pnpm >/dev/null 2>&1; then
|
||||||
|
echo "pre-commit: 未找到 pnpm,跳过构建检查(请手动运行 pnpm run build 验证)" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pnpm run build
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 绿色种采 - 土地环境
|
|
||||||
export const landEnvApi = {
|
|
||||||
list: (params?: any) => request.get('/green-planting/land-env', { params }),
|
|
||||||
detail: (id: string) => request.get(`/green-planting/land-env/${id}`),
|
|
||||||
create: (data: any) => request.post('/green-planting/land-env', data),
|
|
||||||
update: (id: string, data: any) => request.put(`/green-planting/land-env/${id}`, data),
|
|
||||||
remove: (id: string) => request.delete(`/green-planting/land-env/${id}`),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 卫生供应 - 卫生检测
|
|
||||||
export const hygieneTestApi = {
|
|
||||||
list: (params?: any) => request.get('/hygiene-supply/hygiene-test', { params }),
|
|
||||||
detail: (id: string) => request.get(`/hygiene-supply/hygiene-test/${id}`),
|
|
||||||
create: (data: any) => request.post('/hygiene-supply/hygiene-test', data),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 健康生产 - 食安监控
|
|
||||||
export const foodSafetyApi = {
|
|
||||||
list: (params?: any) => request.get('/health-production/food-safety', { params }),
|
|
||||||
detail: (id: string) => request.get(`/health-production/food-safety/${id}`),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 营养用餐 - 用户管理
|
|
||||||
export const userMgmtApi = {
|
|
||||||
list: (params?: any) => request.get('/nutrition-dining/users', { params }),
|
|
||||||
detail: (id: string) => request.get(`/nutrition-dining/users/${id}`),
|
|
||||||
create: (data: any) => request.post('/nutrition-dining/users', data),
|
|
||||||
update: (id: string, data: any) => request.put(`/nutrition-dining/users/${id}`, data),
|
|
||||||
remove: (id: string) => request.delete(`/nutrition-dining/users/${id}`),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录
|
|
||||||
export const authApi = {
|
|
||||||
login: (data: { username: string; password: string }) => request.post('/auth/login', data),
|
|
||||||
logout: () => request.post('/auth/logout'),
|
|
||||||
profile: () => request.get('/auth/profile'),
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
// ==================== 通用工具 ====================
|
// ==================== 通用工具 ====================
|
||||||
export const randomId = () => Math.random().toString(36).slice(2, 10)
|
export const randomId = () => Math.random().toString(36).slice(2, 10)
|
||||||
export const randomNum = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min
|
export const randomNum = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min
|
||||||
@@ -40,7 +38,7 @@ const supplierNames = ['绿源农业', '丰禾食品', '天然牧场', '鲜美
|
|||||||
const materialNames = ['有机大米', '土鸡蛋', '新鲜猪肉', '活鱼', '时令蔬菜', '有机牛奶', '散养鸡', '绿色面粉', '菜籽油', '食用盐']
|
const materialNames = ['有机大米', '土鸡蛋', '新鲜猪肉', '活鱼', '时令蔬菜', '有机牛奶', '散养鸡', '绿色面粉', '菜籽油', '食用盐']
|
||||||
|
|
||||||
export function genLandEnvData(n = 12) {
|
export function genLandEnvData(n = 12) {
|
||||||
return Array.from({ length: n }, (_, i) => ({
|
return Array.from({ length: n }, () => ({
|
||||||
id: randomId(),
|
id: randomId(),
|
||||||
name: pick(landNames),
|
name: pick(landNames),
|
||||||
area: randomFloat(5, 200, 0) + '亩',
|
area: randomFloat(5, 200, 0) + '亩',
|
||||||
@@ -372,8 +370,6 @@ export function genProductionStatsData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 营养用餐 ====================
|
// ==================== 营养用餐 ====================
|
||||||
const nutrientNames = ['蛋白质', '脂肪', '碳水化合物', '膳食纤维', '维生素A', '维生素C', '钙', '铁', '锌']
|
|
||||||
|
|
||||||
export function genNutritionTestData(n = 12) {
|
export function genNutritionTestData(n = 12) {
|
||||||
return Array.from({ length: n }, () => ({
|
return Array.from({ length: n }, () => ({
|
||||||
id: randomId(),
|
id: randomId(),
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import axios from 'axios'
|
|
||||||
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
|
|
||||||
import { message } from 'ant-design-vue'
|
|
||||||
|
|
||||||
const request: AxiosInstance = axios.create({
|
|
||||||
baseURL: '/api',
|
|
||||||
timeout: 15000,
|
|
||||||
})
|
|
||||||
|
|
||||||
request.interceptors.request.use(
|
|
||||||
(config) => {
|
|
||||||
const token = localStorage.getItem('token')
|
|
||||||
if (token) {
|
|
||||||
config.headers.Authorization = `Bearer ${token}`
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
},
|
|
||||||
(error) => Promise.reject(error)
|
|
||||||
)
|
|
||||||
|
|
||||||
request.interceptors.response.use(
|
|
||||||
(response: AxiosResponse) => {
|
|
||||||
const { code, msg, data } = response.data
|
|
||||||
if (code === 0) {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
message.error(msg || '请求失败')
|
|
||||||
return Promise.reject(new Error(msg))
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
if (error.response?.status === 401) {
|
|
||||||
localStorage.removeItem('token')
|
|
||||||
window.location.href = '/login'
|
|
||||||
}
|
|
||||||
message.error(error.message || '网络错误')
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export default request
|
|
||||||
@@ -245,11 +245,9 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, reactive } from 'vue'
|
import { ref, computed, reactive } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import ChartPanel from '@/components/common/ChartPanel.vue'
|
import ChartPanel from '@/components/common/ChartPanel.vue'
|
||||||
import { genDashboardData } from '@/mock/data'
|
import { genDashboardData } from '@/mock/data'
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const d = reactive(genDashboardData())
|
const d = reactive(genDashboardData())
|
||||||
const filterCanteen = ref('')
|
const filterCanteen = ref('')
|
||||||
const trendMetric = ref<'orders' | 'revenue'>('orders')
|
const trendMetric = ref<'orders' | 'revenue'>('orders')
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const relatedLinks = [
|
|||||||
|
|
||||||
const data = ref(genHarvestData(15))
|
const data = ref(genHarvestData(15))
|
||||||
const searchText = ref('')
|
const searchText = ref('')
|
||||||
const dateRange = ref<[Dayjs, Dayjs] | null>(null)
|
const dateRange = ref<[Dayjs, Dayjs]>()
|
||||||
const statusFilter = ref<string | undefined>(undefined)
|
const statusFilter = ref<string | undefined>(undefined)
|
||||||
const modalVisible = ref(false)
|
const modalVisible = ref(false)
|
||||||
const currentRecord = ref<any>(null)
|
const currentRecord = ref<any>(null)
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ const relatedLinks = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const data = ref(genProcurementData(12))
|
const data = ref(genProcurementData(12))
|
||||||
const dateRange = ref<[Dayjs, Dayjs] | null>(null)
|
const dateRange = ref<[Dayjs, Dayjs]>()
|
||||||
const statusFilter = ref<string | undefined>(undefined)
|
const statusFilter = ref<string | undefined>(undefined)
|
||||||
const modalVisible = ref(false)
|
const modalVisible = ref(false)
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ const form = ref({
|
|||||||
quantity: 100,
|
quantity: 100,
|
||||||
unit: 'kg',
|
unit: 'kg',
|
||||||
unitPrice: 0,
|
unitPrice: 0,
|
||||||
deliveryDate: null as Dayjs | null,
|
deliveryDate: undefined as Dayjs | undefined,
|
||||||
remark: '',
|
remark: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ function showModal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
form.value = { material: undefined, supplier: undefined, quantity: 100, unit: 'kg', unitPrice: 0, deliveryDate: null, remark: '' }
|
form.value = { material: undefined, supplier: undefined, quantity: 100, unit: 'kg', unitPrice: 0, deliveryDate: undefined, remark: '' }
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleApprove(record: any) {
|
function handleApprove(record: any) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
v-if="record.status !== 'done'"
|
v-if="record.status !== 'done'"
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
@click="confirmAssemble(record)"
|
@click="confirmAssemble(record as AssembleItem)"
|
||||||
>确认组配</a-button>
|
>确认组配</a-button>
|
||||||
<span v-else style="color: #999">已完成</span>
|
<span v-else style="color: #999">已完成</span>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { statusMap, randomId, randomNum, randomFloat, pick, pickMulti, randomTime } from '@/mock/data'
|
import { statusMap, randomId, randomNum, randomFloat, pickMulti, randomTime } from '@/mock/data'
|
||||||
|
|
||||||
const vegs = ['白菜', '萝卜', '番茄', '黄瓜', '茄子', '青椒', '芹菜', '菠菜']
|
const vegs = ['白菜', '萝卜', '番茄', '黄瓜', '茄子', '青椒', '芹菜', '菠菜']
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { genCookByOrderData, statusMap, canteenNames } from '@/mock/data'
|
import { genCookByOrderData, canteenNames } from '@/mock/data'
|
||||||
import StatCard from '@/components/common/StatCard.vue'
|
import StatCard from '@/components/common/StatCard.vue'
|
||||||
import RelatedModules from '@/components/common/RelatedModules.vue'
|
import RelatedModules from '@/components/common/RelatedModules.vue'
|
||||||
|
|
||||||
|
|||||||
@@ -74,12 +74,12 @@
|
|||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import type { Dayjs } from 'dayjs'
|
import type { Dayjs } from 'dayjs'
|
||||||
import { genSurplusData, statusMap } from '@/mock/data'
|
import { genSurplusData } from '@/mock/data'
|
||||||
import StatCard from '@/components/common/StatCard.vue'
|
import StatCard from '@/components/common/StatCard.vue'
|
||||||
import ChartPanel from '@/components/common/ChartPanel.vue'
|
import ChartPanel from '@/components/common/ChartPanel.vue'
|
||||||
|
|
||||||
const data = ref(genSurplusData(8))
|
const data = ref(genSurplusData(8))
|
||||||
const dateRange = ref<[Dayjs, Dayjs] | null>(null)
|
const dateRange = ref<[Dayjs, Dayjs]>()
|
||||||
const disposalFilter = ref<string | undefined>(undefined)
|
const disposalFilter = ref<string | undefined>(undefined)
|
||||||
const modalVisible = ref(false)
|
const modalVisible = ref(false)
|
||||||
const currentRecord = ref<any>(null)
|
const currentRecord = ref<any>(null)
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ import { genHygieneTestData, statusMap } from '@/mock/data'
|
|||||||
const tableData = ref(genHygieneTestData(30))
|
const tableData = ref(genHygieneTestData(30))
|
||||||
const searchText = ref('')
|
const searchText = ref('')
|
||||||
const resultFilter = ref('')
|
const resultFilter = ref('')
|
||||||
const dateRange = ref<[Dayjs, Dayjs] | null>(null)
|
const dateRange = ref<[Dayjs, Dayjs]>()
|
||||||
const drawerVisible = ref(false)
|
const drawerVisible = ref(false)
|
||||||
const currentRecord = ref<any>(null)
|
const currentRecord = ref<any>(null)
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@
|
|||||||
<a-descriptions :column="2" bordered size="small">
|
<a-descriptions :column="2" bordered size="small">
|
||||||
<a-descriptions-item label="姓名">{{ personProfile.name }}</a-descriptions-item>
|
<a-descriptions-item label="姓名">{{ personProfile.name }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="部门">{{ personProfile.dept }}</a-descriptions-item>
|
<a-descriptions-item label="部门">{{ personProfile.dept }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="日均热量">{{ personProfile.avgCalories }} kcal</a-descriptions-item>
|
<a-descriptions-item label="日均热量">{{ personProfile.calories }} kcal</a-descriptions-item>
|
||||||
<a-descriptions-item label="营养评分">
|
<a-descriptions-item label="营养评分">
|
||||||
<a-progress :percent="personProfile.score" :size="20"
|
<a-progress :percent="personProfile.score" :size="20"
|
||||||
:stroke-color="personProfile.score >= 80 ? '#52c41a' : personProfile.score >= 60 ? '#faad14' : '#f5222d'" />
|
:stroke-color="personProfile.score >= 80 ? '#52c41a' : personProfile.score >= 60 ? '#faad14' : '#f5222d'" />
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
:percent="record.score"
|
:percent="record.score"
|
||||||
:size="20"
|
:size="20"
|
||||||
:stroke-color="record.score >= 80 ? '#52c41a' : record.score >= 60 ? '#faad14' : '#f5222d'"
|
:stroke-color="record.score >= 80 ? '#52c41a' : record.score >= 60 ? '#faad14' : '#f5222d'"
|
||||||
:format="(p: number) => p + ''"
|
:format="(p?: number) => (p ?? 0) + ''"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'verdict'">
|
<template v-else-if="column.key === 'verdict'">
|
||||||
@@ -251,7 +251,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, reactive } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import ChartPanel from '@/components/common/ChartPanel.vue'
|
import ChartPanel from '@/components/common/ChartPanel.vue'
|
||||||
import { randomNum, randomFloat, pick } from '@/mock/data'
|
import { randomNum, randomFloat, pick } from '@/mock/data'
|
||||||
|
|
||||||
@@ -267,19 +267,6 @@ const drawerPerson = ref<any>(null)
|
|||||||
const personList = ['张伟', '李芳', '王娜', '刘敏', '陈强', '杨磊', '黄艳', '赵勇', '周洋', '吴军']
|
const personList = ['张伟', '李芳', '王娜', '刘敏', '陈强', '杨磊', '黄艳', '赵勇', '周洋', '吴军']
|
||||||
const deptList = ['研发部', '市场部', '财务部', '行政部']
|
const deptList = ['研发部', '市场部', '财务部', '行政部']
|
||||||
|
|
||||||
// ============ 营养标准 ============
|
|
||||||
const standards = {
|
|
||||||
calories: { min: 1800, max: 2200, recommend: 2000 },
|
|
||||||
protein: { min: 55, max: 85, recommend: 70, unit: 'g' },
|
|
||||||
fat: { min: 45, max: 75, recommend: 60, unit: 'g' },
|
|
||||||
carbs: { min: 250, max: 340, recommend: 300, unit: 'g' },
|
|
||||||
fiber: { min: 20, max: 35, recommend: 25, unit: 'g' },
|
|
||||||
calcium: { min: 700, max: 1000, recommend: 800, unit: 'mg' },
|
|
||||||
iron: { min: 10, max: 20, recommend: 15, unit: 'mg' },
|
|
||||||
vitC: { min: 80, max: 150, recommend: 100, unit: 'mg' },
|
|
||||||
sodium: { min: 1000, max: 2300, recommend: 1500, unit: 'mg' },
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============ Mock 就餐数据 ============
|
// ============ Mock 就餐数据 ============
|
||||||
function genPersonNutrition() {
|
function genPersonNutrition() {
|
||||||
return personList.map(name => {
|
return personList.map(name => {
|
||||||
@@ -457,7 +444,7 @@ const mealBalance = computed(() => {
|
|||||||
// ============ 个人营养画像 ============
|
// ============ 个人营养画像 ============
|
||||||
const personProfile = computed(() => {
|
const personProfile = computed(() => {
|
||||||
const p = allPersonData.value.find(d => d.name === filterPerson.value)
|
const p = allPersonData.value.find(d => d.name === filterPerson.value)
|
||||||
return p || { name: '', dept: '', avgCalories: 0, score: 0, consecutiveDays: 0, bmi: 0 }
|
return p || { name: '', dept: '', calories: 0, score: 0, consecutiveDays: 0, bmi: 0 }
|
||||||
})
|
})
|
||||||
|
|
||||||
const personNutrientData = computed(() => {
|
const personNutrientData = computed(() => {
|
||||||
|
|||||||
@@ -150,10 +150,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, reactive } from 'vue'
|
import { ref, computed, reactive } from 'vue'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
|
import type { ColumnsType } from 'ant-design-vue/es/table'
|
||||||
import StatCard from '@/components/common/StatCard.vue'
|
import StatCard from '@/components/common/StatCard.vue'
|
||||||
import { canteenList } from '@/mock/data'
|
import { canteenList } from '@/mock/data'
|
||||||
|
|
||||||
const columns = [
|
const columns: ColumnsType<any> = [
|
||||||
{ title: '食堂名称', dataIndex: 'name', key: 'name', width: 110 },
|
{ title: '食堂名称', dataIndex: 'name', key: 'name', width: 110 },
|
||||||
{ title: '别名', dataIndex: 'alias', key: 'alias', width: 120 },
|
{ title: '别名', dataIndex: 'alias', key: 'alias', width: 120 },
|
||||||
{ title: '地址', dataIndex: 'address', key: 'address', width: 100 },
|
{ title: '地址', dataIndex: 'address', key: 'address', width: 100 },
|
||||||
|
|||||||
@@ -145,10 +145,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, reactive } from 'vue'
|
import { ref, computed, reactive } from 'vue'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs, { type Dayjs } from 'dayjs'
|
||||||
|
import type { ColumnsType } from 'ant-design-vue/es/table'
|
||||||
import StatCard from '@/components/common/StatCard.vue'
|
import StatCard from '@/components/common/StatCard.vue'
|
||||||
|
|
||||||
const columns = [
|
const columns: ColumnsType<any> = [
|
||||||
{ title: '姓名', dataIndex: 'name', key: 'name', width: 100 },
|
{ title: '姓名', dataIndex: 'name', key: 'name', width: 100 },
|
||||||
{ title: '性别', dataIndex: 'gender', key: 'gender', width: 60 },
|
{ title: '性别', dataIndex: 'gender', key: 'gender', width: 60 },
|
||||||
{ title: '手机号', dataIndex: 'phone', key: 'phone', width: 120 },
|
{ title: '手机号', dataIndex: 'phone', key: 'phone', width: 120 },
|
||||||
@@ -183,13 +184,20 @@ const drawerVisible = ref(false)
|
|||||||
const editingId = ref('')
|
const editingId = ref('')
|
||||||
const viewingEmployee = ref<any>(null)
|
const viewingEmployee = ref<any>(null)
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive<{
|
||||||
|
name: string
|
||||||
|
gender: string
|
||||||
|
phone: string
|
||||||
|
department: string
|
||||||
|
position: string
|
||||||
|
entryDate: Dayjs | undefined
|
||||||
|
}>({
|
||||||
name: '',
|
name: '',
|
||||||
gender: '男',
|
gender: '男',
|
||||||
phone: '',
|
phone: '',
|
||||||
department: '',
|
department: '',
|
||||||
position: '',
|
position: '',
|
||||||
entryDate: null,
|
entryDate: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
const activeEmployees = computed(() => allEmployees.value.filter(e => e.status === '在职'))
|
const activeEmployees = computed(() => allEmployees.value.filter(e => e.status === '在职'))
|
||||||
@@ -227,7 +235,7 @@ function showAddModal() {
|
|||||||
form.phone = ''
|
form.phone = ''
|
||||||
form.department = ''
|
form.department = ''
|
||||||
form.position = ''
|
form.position = ''
|
||||||
form.entryDate = null
|
form.entryDate = undefined
|
||||||
modalVisible.value = true
|
modalVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +278,7 @@ function saveEmployee() {
|
|||||||
phone: form.phone,
|
phone: form.phone,
|
||||||
department: form.department,
|
department: form.department,
|
||||||
position: form.position,
|
position: form.position,
|
||||||
entryDate: form.entryDate?.format('YYYY-MM-DD'),
|
entryDate: form.entryDate?.format('YYYY-MM-DD') ?? '',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -281,7 +289,7 @@ function saveEmployee() {
|
|||||||
phone: form.phone,
|
phone: form.phone,
|
||||||
department: form.department,
|
department: form.department,
|
||||||
position: form.position,
|
position: form.position,
|
||||||
entryDate: form.entryDate?.format('YYYY-MM-DD'),
|
entryDate: form.entryDate?.format('YYYY-MM-DD') ?? '',
|
||||||
status: '试用期',
|
status: '试用期',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
/>
|
/>
|
||||||
<a-tree
|
<a-tree
|
||||||
v-model:selectedKeys="selectedOrgKeys"
|
v-model:selectedKeys="selectedOrgKeys"
|
||||||
:tree-data="orgTreeData"
|
:tree-data="(orgTreeData as any)"
|
||||||
:field-names="{ children: 'children', title: 'name', key: 'id' }"
|
:field-names="{ children: 'children', title: 'name', key: 'id' }"
|
||||||
@select="onOrgSelect"
|
@select="onOrgSelect"
|
||||||
>
|
>
|
||||||
@@ -212,9 +212,9 @@ const selectedOrgEmployees = computed(() => {
|
|||||||
return mockEmployees[selectedOrg.value.id] || []
|
return mockEmployees[selectedOrg.value.id] || []
|
||||||
})
|
})
|
||||||
|
|
||||||
function onOrgSelect(keys: string[]) {
|
function onOrgSelect(keys: Array<string | number>) {
|
||||||
if (keys.length === 0) return
|
if (keys.length === 0) return
|
||||||
const key = keys[0]
|
const key = String(keys[0])
|
||||||
const findOrg = (data: any[]): any => {
|
const findOrg = (data: any[]): any => {
|
||||||
for (const item of data) {
|
for (const item of data) {
|
||||||
if (item.id === key) return item
|
if (item.id === key) return item
|
||||||
@@ -236,11 +236,11 @@ function showAddOrgModal() {
|
|||||||
orgModalVisible.value = true
|
orgModalVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function editOrg(id: string) {
|
function editOrg(_id: string) {
|
||||||
message.info('编辑功能开发中')
|
message.info('编辑功能开发中')
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteOrg(id: string) {
|
function deleteOrg(_id: string) {
|
||||||
message.success('部门已删除')
|
message.success('部门已删除')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<a-tree
|
<a-tree
|
||||||
v-model:checkedKeys="selectedPermissions"
|
v-model:checkedKeys="selectedPermissions"
|
||||||
:tree-data="permissionTree"
|
:tree-data="(permissionTree as any)"
|
||||||
:field-names="{ children: 'children', title: 'name', key: 'id' }"
|
:field-names="{ children: 'children', title: 'name', key: 'id' }"
|
||||||
checkable
|
checkable
|
||||||
@check="onPermissionChange"
|
@check="onPermissionChange"
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
<a-form-item label="权限">
|
<a-form-item label="权限">
|
||||||
<a-tree
|
<a-tree
|
||||||
v-model:checkedKeys="roleForm.permissions"
|
v-model:checkedKeys="roleForm.permissions"
|
||||||
:tree-data="permissionTree"
|
:tree-data="(permissionTree as any)"
|
||||||
:field-names="{ children: 'children', title: 'name', key: 'id' }"
|
:field-names="{ children: 'children', title: 'name', key: 'id' }"
|
||||||
checkable
|
checkable
|
||||||
/>
|
/>
|
||||||
@@ -82,8 +82,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
|
import type { ColumnsType } from 'ant-design-vue/es/table'
|
||||||
|
|
||||||
const roleColumns = [
|
const roleColumns: ColumnsType<any> = [
|
||||||
{ title: '角色名称', dataIndex: 'name', key: 'name', width: 120 },
|
{ title: '角色名称', dataIndex: 'name', key: 'name', width: 120 },
|
||||||
{ title: '描述', dataIndex: 'description', key: 'description', width: 150, ellipsis: true },
|
{ title: '描述', dataIndex: 'description', key: 'description', width: 150, ellipsis: true },
|
||||||
{ title: '用户数', dataIndex: 'userCount', key: 'userCount', width: 60 },
|
{ title: '用户数', dataIndex: 'userCount', key: 'userCount', width: 60 },
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"lib": ["ES2023"],
|
"lib": ["ES2023"],
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
"noEmit": true,
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
const app = getApp()
|
|
||||||
|
|
||||||
const request = (options) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
wx.request({
|
|
||||||
url: app.globalData.baseUrl + options.url,
|
|
||||||
method: options.method || 'GET',
|
|
||||||
data: options.data || {},
|
|
||||||
header: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Bearer ${app.globalData.token}`,
|
|
||||||
...options.header,
|
|
||||||
},
|
|
||||||
success(res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
resolve(res.data.data)
|
|
||||||
} else if (res.data.code === 401) {
|
|
||||||
wx.navigateTo({ url: '/pages/profile/index' })
|
|
||||||
reject(new Error('未登录'))
|
|
||||||
} else {
|
|
||||||
wx.showToast({ title: res.data.msg || '请求失败', icon: 'none' })
|
|
||||||
reject(new Error(res.data.msg))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail(err) {
|
|
||||||
wx.showToast({ title: '网络错误', icon: 'none' })
|
|
||||||
reject(err)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { request }
|
|
||||||
Reference in New Issue
Block a user