This commit is contained in:
Teo
2025-08-29 18:56:36 +08:00
50 changed files with 2032 additions and 477 deletions

View File

@ -6,13 +6,15 @@ VITE_APP_ENV = 'development'
# 开发环境
# 李陈杰 209
VITE_APP_BASE_API = 'http://192.168.110.209:8899'
VITE_APP_BASE_API = 'http://192.168.110.210:8899'
# 曾涛
# VITE_APP_BASE_API = 'http://192.168.110.180:8899'
# 罗成
# VITE_APP_BASE_API = 'http://192.168.110.188:8899'
# 朱银
# VITE_APP_BASE_API = 'http://192.168.110.180:8899'
# VITE_APP_BASE_API = 'http://192.168.110.149:8899'
#曾涛
# VITE_APP_BASE_API = 'http://192.168.110.171:8899'
# 无人机接口地址

View File

@ -31,6 +31,7 @@
"await-to-js": "3.0.0",
"axios": "1.7.8",
"crypto-js": "4.2.0",
"date-fns": "^4.1.0",
"diagram-js": "12.3.0",
"didi": "9.0.2",
"echarts": "5.5.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
public/assets/demo/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/assets/demo/rain.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/assets/demo/sb1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
public/assets/demo/sb2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
public/assets/demo/sb3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
public/assets/demo/sb4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
public/assets/demo/sbi1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
public/assets/demo/sbi2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/assets/demo/wcl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
public/assets/demo/ycl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
public/assets/demo/yin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
public/assets/demo/zzcl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/assets/demo/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
src/assets/demo/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
src/assets/demo/gaojing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/assets/demo/rain.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/assets/demo/wcl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/assets/demo/yichuli.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
src/assets/demo/zzcl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,12 +1,15 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="模板类型" prop="projectType">
<el-select v-model="queryParams.projectType" placeholder="请选择模板类型" clearable filterable @change="selectType">
<el-option v-for="item in projectTypeOptions" :key="item.name" :label="item.name" :value="item.name"> </el-option>
<el-select v-model="queryParams.projectType" placeholder="请选择模板类型" clearable filterable
@change="selectType">
<el-option v-for="item in projectTypeOptions" :key="item.name" :label="item.name" :value="item.name">
</el-option>
</el-select>
</el-form-item>
<!-- <el-form-item>
@ -21,9 +24,8 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAdd" v-hasPermi="['quality:qualityInspection:add']"
>新增</el-button
>
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAdd"
v-hasPermi="['quality:qualityInspection:add']">新增</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['quality:qualityInspection:edit']"
@ -31,15 +33,8 @@
>
</el-col> -->
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['quality:qualityInspection:remove']"
>删除</el-button
>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
v-hasPermi="['quality:qualityInspection:remove']">删除</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['quality:qualityInspection:export']">导出</el-button>
@ -49,7 +44,8 @@
</template>
<!-- card body -->
<Notice @selection-change="handleSelectionChange" :data="tableData"></Notice>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<el-dialog title="新增模板" v-model="dialogVisible" width="800">
@ -60,12 +56,14 @@
<div>
<el-form-item label="检查类型" prop="checkType">
<el-select v-model="form.checkType" placeholder="请选择检查类型">
<el-option v-for="dict in safety_inspection_check_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option v-for="dict in safety_inspection_check_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="违章类型" prop="violationType">
<el-select v-model="form.violationType" placeholder="请选择违章类型">
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="巡检结果" prop="inspectionResult">
@ -73,7 +71,8 @@
</el-form-item>
<el-form-item label="整改班组" prop="teamId">
<el-select v-model="form.teamId" placeholder="请选择整改班组">
<el-option v-for="item in teamOpt" :key="item.value" :label="item.label" :value="item.value" @click="changeForeman(item.value)" />
<el-option v-for="item in teamOpt" :key="item.value" :label="item.label" :value="item.value"
@click="changeForeman(item.value)" />
</el-select>
</el-form-item>
<el-form-item label="整改人" prop="correctorId">
@ -88,13 +87,16 @@
<el-input v-model="form.measure" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="要求整改期限" prop="rectificationDeadline">
<el-date-picker clearable v-model="form.rectificationDeadline" type="date" value-format="YYYY-MM-DD" placeholder="选择要求整改期限" />
<el-date-picker clearable v-model="form.rectificationDeadline" type="date" value-format="YYYY-MM-DD"
placeholder="选择要求整改期限" />
</el-form-item>
<el-form-item label="检查附件" prop="checkFile">
<file-upload v-model="form.checkFile" :file-size="20" :file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
<file-upload v-model="form.checkFile" :file-size="20"
:file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
</el-form-item>
<el-form-item label="整改附件" prop="rectificationFile">
<file-upload v-model="form.rectificationFile" :file-size="20" :file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
<file-upload v-model="form.rectificationFile" :file-size="20"
:file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
@ -251,8 +253,8 @@ const changeForeman = (value: string | number) => {
form.value.correctorId = '';
};
const handleQuery = () => {};
const resetQuery = () => {};
const handleQuery = () => { };
const resetQuery = () => { };
const getList = async () => {
if (!queryParams.value.projectType) {
const res = await listContactTypeformtemplate(queryParams.value);
@ -287,7 +289,7 @@ const handleDelete = async (id?: string) => {
getList();
}
};
const handleUpdate = () => {};
const handleUpdate = () => { };
/** 多选框选中数据 */
const handleSelectionChange = (selection: any) => {

View File

@ -1,80 +1,79 @@
<template>
<div class="container">
<el-steps style="max-width: 100%" :active="active" finish-status="success" align-center>
<el-step title="选择合同类型" />
<el-step title="修改合同内容" />
<el-step title="修改收款方式" />
</el-steps>
<div class="content">
<template v-if="active == 1">
<h1>修改收入合同</h1>
<el-form ref="incomeContractFormRef" :model="form" :rules="incomeContractFormRules" label-width="80px">
<el-form-item label="合同编号" prop="contractCode">
<el-input v-model="form.contractCode" placeholder="请输入合同编号" />
</el-form-item>
<el-form-item label="合同类型" prop="contractType">
<el-select v-model="form.contractType" placeholder="请选择合同类型">
<el-option v-for="item in income_contract_type" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="业主单位" prop="contractOwner">
<el-input v-model="form.contractOwner" placeholder="请输入业主单位" disabled />
</el-form-item>
<el-form-item label="承包内容" v-if="contract_type !== 'income'">
<editor v-model="form.contractedContent" :min-height="192" />
</el-form-item>
<el-form-item label="合同内容" v-else>
<editor v-model="form.contractedContent" :min-height="192" />
</el-form-item>
<el-form-item label="合同金额" prop="amount">
<el-input
v-model="form.amount"
placeholder="请输入合同金额"
oninput="value=value.replace(/[^0-9.]/g,'').replace(/\.{2,}/g,'.').replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3')"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="附件">
<FileUpload :multiple="true" :fileType="['pdf']" :onUploadSuccess="onUploadSuccess" :ref="fileRef" :defaultFileList="tempFileList" />
</el-form-item>
</el-form>
<div>
<el-button type="primary" @click="next">下一步</el-button>
<div class="container">
<el-steps style="max-width: 100%" :active="active" finish-status="success" align-center>
<el-step title="选择合同类型" />
<el-step title="修改合同内容" />
<el-step title="修改收款方式" />
</el-steps>
<div class="content">
<template v-if="active == 1">
<h1>修改收入合同</h1>
<el-form ref="incomeContractFormRef" :model="form" :rules="incomeContractFormRules" label-width="80px">
<el-form-item label="合同编号" prop="contractCode">
<el-input v-model="form.contractCode" placeholder="请输入合同编号" />
</el-form-item>
<el-form-item label="合同类型" prop="contractType">
<el-select v-model="form.contractType" placeholder="请选择合同类型">
<el-option v-for="item in income_contract_type" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="业主单位" prop="contractOwner">
<el-input v-model="form.contractOwner" placeholder="请输入业主单位" disabled />
</el-form-item>
<el-form-item label="承包内容" v-if="contract_type !== 'income'">
<editor v-model="form.contractedContent" :min-height="192" />
</el-form-item>
<el-form-item label="合同内容" v-else>
<editor v-model="form.contractedContent" :min-height="192" />
</el-form-item>
<el-form-item label="合同金额" prop="amount">
<el-input v-model="form.amount" placeholder="请输入合同金额"
oninput="value=value.replace(/[^0-9.]/g,'').replace(/\.{2,}/g,'.').replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3')" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="附件">
<FileUpload :multiple="true" :fileType="['pdf']" :onUploadSuccess="onUploadSuccess"
:ref="fileRef" :defaultFileList="tempFileList" />
</el-form-item>
</el-form>
<div>
<el-button type="primary" @click="next">下一步</el-button>
</div>
</template>
<template v-else-if="active == 2">
<h1>修改收入合同</h1>
<el-form :model="form" :rules="payMentRules" label-width="150" ref="payMentRef">
<el-form-item label="支付方式" placeholder="请选择支付方式" prop="payType">
<el-select v-model="form.payType">
<el-option :value="1" label="月结算">月结算</el-option>
<el-option :value="2" label="形象节点">形象节点</el-option>
</el-select>
</el-form-item>
<el-form-item label="预付款比例(%" prop="advancePayRatio">
<el-input-number v-model="form.advancePayRatio" :max="100" :min="0" />
</el-form-item>
<el-form-item label="尾款比例(%" prop="balancePayRatio">
<el-input-number v-model="form.balancePayRatio" :max="100" :min="0" />
</el-form-item>
<el-form-item label="质保金比例(%" prop="assuranceDepositRatio">
<el-input-number v-model="form.assuranceDepositRatio" :max="100" :min="0" />
</el-form-item>
<el-form-item label="付款比例(%" prop="payRatio">
<el-input-number v-model="payRatioComputed" disabled />
</el-form-item>
<el-form-item>
<div>
<el-button @click="back(false)">上一步</el-button>
<el-button type="success" @click="submitForm">提交</el-button>
</div>
</el-form-item>
</el-form>
</template>
</div>
</template>
<template v-else-if="active == 2">
<h1>修改收入合同</h1>
<el-form :model="form" :rules="payMentRules" label-width="150" ref="payMentRef">
<el-form-item label="支付方式" placeholder="请选择支付方式" prop="payType">
<el-select v-model="form.payType">
<el-option :value="1" label="月结算">月结算</el-option>
<el-option :value="2" label="形象节点">形象节点</el-option>
</el-select>
</el-form-item>
<el-form-item label="预付款比例(%" prop="advancePayRatio">
<el-input-number v-model="form.advancePayRatio" :max="100" :min="0" />
</el-form-item>
<el-form-item label="尾款比例(%" prop="balancePayRatio">
<el-input-number v-model="form.balancePayRatio" :max="100" :min="0" />
</el-form-item>
<el-form-item label="质保金比例(%" prop="assuranceDepositRatio">
<el-input-number v-model="form.assuranceDepositRatio" :max="100" :min="0" />
</el-form-item>
<el-form-item label="付款比例(%" prop="payRatio">
<el-input-number v-model="payRatioComputed" disabled />
</el-form-item>
<el-form-item>
<div>
<el-button @click="back(false)">上一步</el-button>
<el-button type="success" @click="submitForm">提交</el-button>
</div>
</el-form-item>
</el-form>
</template>
</div>
</div>
</template>
<script setup>
import FileUpload from '@/components/FileUpload';
@ -96,131 +95,140 @@ const incomeContractFormRef = ref(null);
const expensesContractFormRef = ref(null);
const payMentRef = ref(null);
const incomeContractFormRules = {
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
contractOwner: [{ required: true, message: '请输入业主单位', trigger: 'blur' }],
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
contractOwner: [{ required: true, message: '请输入业主单位', trigger: 'blur' }],
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
};
const expensesContractFormRules = {
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
contractSupplier: [{ required: true, message: '请输入供应商', trigger: 'blur' }],
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
tenderId: [{ required: true, message: '请选择招标计划', trigger: 'blur' }],
contractSupplier: [{ required: true, message: '请输入供应商', trigger: 'blur' }],
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
tenderId: [{ required: true, message: '请选择招标计划', trigger: 'blur' }],
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
};
const payMentRules = {
payType: [{ required: true, message: '请选择支付方式', trigger: 'change' }],
advancePayRatio: [{ required: true, message: '请输入预付款比例', trigger: 'blur' }],
balancePayRatio: [{ required: true, message: '请输入尾款比例', trigger: 'blur' }],
assuranceDepositRatio: [{ required: true, message: '请输入质保金比例', trigger: 'blur' }]
payType: [{ required: true, message: '请选择支付方式', trigger: 'change' }],
advancePayRatio: [{ required: true, message: '请输入预付款比例', trigger: 'blur' }],
balancePayRatio: [{ required: true, message: '请输入尾款比例', trigger: 'blur' }],
assuranceDepositRatio: [{ required: true, message: '请输入质保金比例', trigger: 'blur' }]
};
const project = computed(() => {
return JSON.parse(localStorage.getItem('selectedProject'));
return JSON.parse(localStorage.getItem('selectedProject'));
});
const payRatioComputed = computed({
get: () => {
const { advancePayRatio = 0, balancePayRatio = 0, assuranceDepositRatio = 0 } = form.value;
const total = 100 - (advancePayRatio + balancePayRatio + assuranceDepositRatio);
// form.value.payRatio = total;
return total;
},
// 只读
set: () => {}
get: () => {
const { advancePayRatio = 0, balancePayRatio = 0, assuranceDepositRatio = 0 } = form.value;
const total = 100 - (advancePayRatio + balancePayRatio + assuranceDepositRatio);
// form.value.payRatio = total;
return total;
},
// 只读
set: () => { }
});
const onUploadSuccess = (data) => {
fileList.value = data;
fileList.value = data;
};
const next = async () => {
if (contract_type.value === 'income') {
await incomeContractFormRef.value.validate((valid) => {
if (valid) {
active.value++;
} else {
ElMessage.error('请填写完整的收入合同信息');
}
});
} else if (contract_type.value === 'expenses') {
await expensesContractFormRef.value.validate((valid) => {
if (valid) {
active.value++;
} else {
ElMessage.error('请填写完整的支出合同信息');
}
});
}
console.log(active.value);
if (contract_type.value === 'income') {
await incomeContractFormRef.value.validate((valid) => {
if (valid) {
active.value++;
} else {
ElMessage.error('请填写完整的收入合同信息');
}
});
} else if (contract_type.value === 'expenses') {
await expensesContractFormRef.value.validate((valid) => {
if (valid) {
active.value++;
} else {
ElMessage.error('请填写完整的支出合同信息');
}
});
}
console.log(active.value);
form.value.step = active.value;
form.value.step = active.value;
};
const submitForm = async () => {
await payMentRef.value.validate(async (valid) => {
if (valid) {
if (payRatioComputed.value < 0) {
ElMessage.error('四项付款比例之和必须等于100%');
return;
}
form.value.payRatio = payRatioComputed.value;
await payMentRef.value.validate(async (valid) => {
if (valid) {
if (payRatioComputed.value < 0) {
ElMessage.error('四项付款比例之和必须等于100%');
return;
}
form.value.payRatio = payRatioComputed.value;
// 提交付款信息逻辑
console.log('提交付款信息', form.value, fileList.value);
// 这里可以调用API提交数据
form.value.projectId = project.value.id;
form.value.fileList = fileList.value.map((data) => {
return {
...data,
fileName: data.name,
fileUrl: data.url
};
});
if (contract_type.value === 'income') {
await updateIncomeContract({ ...form.value });
}
ElMessage.success('合同修改成功');
} else {
ElMessage.error('请填写完整的付款信息');
}
});
// 提交付款信息逻辑
console.log('提交付款信息', form.value, fileList.value);
// 这里可以调用API提交数据
form.value.projectId = project.value.id;
form.value.fileList = fileList.value.map((data) => {
return {
...data,
fileName: data.name,
fileUrl: data.url
};
});
if (contract_type.value === 'income') {
await updateIncomeContract({ ...form.value });
}
ElMessage.success('合同修改成功');
} else {
ElMessage.error('请填写完整的付款信息');
}
});
};
const handleChoose = async () => {
if (!form.value.contractType) {
ElMessage.error('请先选择合同类型');
return;
}
const formData = {
projectId: userStore.selectedProject.id,
dictName: form.value.contractType,
status: 1
};
const { data } = await getTenderPlan(formData);
if (data.length === 0) {
ElMessage.warning('当前没有招标计划,请先创建招标计划');
return;
}
planList.value = data;
dialogVisible.value = true;
if (!form.value.contractType) {
ElMessage.error('请先选择合同类型');
return;
}
const formData = {
projectId: userStore.selectedProject.id,
dictName: form.value.contractType,
status: 1
};
const { data } = await getTenderPlan(formData);
if (data.length === 0) {
ElMessage.warning('当前没有招标计划,请先创建招标计划');
return;
}
planList.value = data;
dialogVisible.value = true;
};
onMounted(async () => {});
onMounted(async () => {
const id = route.query.id;
if (id) {
const { data } = await getIncomeContract(id);
form.value.id = data.id;
form.value.contractOwner = data.contractOwner
} else {
router.push('/ctr/incomeContract');
}
})
</script>
<style scoped lang="scss">
.container {
padding: 20px;
padding: 20px;
.content {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 30px;
flex-direction: column;
}
.content {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 30px;
flex-direction: column;
}
}
</style>

View File

@ -0,0 +1,128 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入图标(这里用的是阿里图标库示例,实际可替换成自己的图标资源) -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_4245527_xxxxxx.css">
<!-- <link rel="stylesheet" href="style.css"> -->
<style>
/* 初始化样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #eef5ff;
font-family: sans-serif;
}
/* 时间轴容器 */
.weather-timeline {
display: flex;
align-items: center;
background: #fff;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow-x: auto;
/* 适配小屏幕横向滚动 */
}
/* 每个时间项 */
.time-item {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 12px;
min-width: 80px;
/* 保证 item 最小宽度 */
}
/* 当前时间项特殊样式 */
.time-item.current {
background: #e3f0ff;
border-radius: 8px;
padding: 10px;
transform: scale(1.1);
/* 稍微放大突出 */
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
/* 时间文本 */
.time {
font-size: 14px;
color: #333;
margin-bottom: 4px;
}
/* 温度文本 */
.temp {
font-size: 16px;
color: #666;
margin-bottom: 8px;
}
/* 图标样式(基于阿里图标库,可替换成自己的图标字体或图片) */
.iconfont {
font-size: 24px;
color: #f9b115;
/* 太阳/主色调 */
}
.icon-rain {
color: #9ec8f2;
/* 雨/蓝色系 */
}
.icon-cloud-moon {
color: #c9d6e5;
/* 多云 moon/浅灰蓝 */
}
</style>
<title>天气时间轴</title>
</head>
<body>
<div class="weather-timeline">
<div class="time-item">
<div class="time">16:00</div>
<div class="temp">30°C</div>
<i class="iconfont icon-sun"></i> <!-- 太阳图标 -->
</div>
<div class="time-item">
<div class="time">17:00</div>
<div class="temp">29°C</div>
<i class="iconfont icon-sun"></i>
</div>
<div class="time-item">
<div class="time">18:00</div>
<div class="temp">25°C</div>
<i class="iconfont icon-rain"></i> <!-- 小雨图标 -->
</div>
<div class="time-item current">
<div class="time">现在</div>
<div class="temp">25°C</div>
<i class="iconfont icon-rain"></i>
</div>
<div class="time-item">
<div class="time">20:00</div>
<div class="temp">25°C</div>
<i class="iconfont icon-cloud-moon"></i> <!-- 多云 moon 图标 -->
</div>
<div class="time-item">
<div class="time">21:00</div>
<div class="temp">20°C</div>
<i class="iconfont icon-cloud-moon"></i>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,311 @@
<template>
<div class="chart-container">
<!-- 图表标题和时间范围选择器 -->
<div class="chart-header">
<h2>功率与效率趋势</h2>
<div class="chart-actions">
<button @click="timeRange = 'day'" :class="{ active: timeRange === 'day' }">今日</button>
<button @click="timeRange = 'week'" :class="{ active: timeRange === 'week' }">本周</button>
<button @click="timeRange = 'month'" :class="{ active: timeRange === 'month' }">本月</button>
</div>
</div>
<!-- 图表内容区域 -->
<div ref="chartRef" class="chart-content"></div>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import * as echarts from 'echarts';
// 图表DOM引用
const chartRef = ref(null);
// 时间范围状态
const timeRange = ref('day');
// 图表实例
let chartInstance = null;
// 定义颜色常量
const POWER_COLOR = 'rgba(42, 130, 228, 1)';
const EFFICIENCY_COLOR = 'rgba(67, 207, 124, 1)';
// 生成指定范围内的随机数(用于模拟数据)
const getRandomValue = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
// 生成指定范围内的随机浮点数(用于效率数据)
const getRandomFloat = (min, max, decimalPlaces = 1) => {
const value = Math.random() * (max - min) + min;
return parseFloat(value.toFixed(decimalPlaces));
};
// 获取当前月份的天数
const getDaysInCurrentMonth = () => {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1; // 月份从0开始所以+1
return new Date(year, month, 0).getDate();
};
// 根据时间范围返回对应的数据
const getChartData = () => {
if (timeRange.value === 'day') {
return {
xAxis: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'],
powerData: [320, 380, 350, 420, 580, 630, 550, 480],
efficiencyData: [85.2, 86.5, 87.1, 88.3, 89.5, 89.2, 88.7, 88.1]
};
} else if (timeRange.value === 'week') {
return {
xAxis: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
powerData: [4200, 4800, 5100, 4900, 5300, 3800, 3200],
efficiencyData: [86.2, 87.5, 88.1, 87.8, 89.0, 88.5, 87.9]
};
} else {
// 本月数据 - 按天显示
const daysInMonth = getDaysInCurrentMonth();
const xAxis = [];
const powerData = [];
const efficiencyData = [];
// 生成每天的数据
for (let i = 1; i <= daysInMonth; i++) {
xAxis.push(`${i}`);
// 生成合理范围内的功率数据10000-25000之间
powerData.push(getRandomValue(10000, 25000));
// 生成合理范围内的效率数据85-90之间保留1位小数
efficiencyData.push(getRandomFloat(85, 90));
}
return {
xAxis,
powerData,
efficiencyData
};
}
};
// 初始化图表
const initChart = () => {
if (chartRef.value && !chartInstance) {
chartInstance = echarts.init(chartRef.value);
}
const data = getChartData();
const option = {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross' }
},
legend: {
data: ['总功率(kW)', '平均效率(%)'],
top: 0
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: data.xAxis,
// 当月天数较多时优化X轴标签显示
axisLabel: {
interval: timeRange.value === 'month' ? 'auto' : 0,
rotate: timeRange.value === 'month' ? 45 : 0
}
},
yAxis: [
{
type: 'value',
name: '总功率(kW)',
axisLabel: {
formatter: '{value}'
}
},
{
type: 'value',
name: '平均效率(%)',
min: 80,
max: 95,
axisLabel: {
formatter: '{value}%'
}
}
],
series: [
{
name: '总功率(kW)',
type: 'line',
data: data.powerData,
smooth: true,
lineStyle: {
width: 3,
color: POWER_COLOR
},
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: POWER_COLOR
},
markPoint: {
data: [
{ type: 'max', name: '最大值' },
{ type: 'min', name: '最小值' }
],
itemStyle: {
color: POWER_COLOR
}
}
},
{
name: '平均效率(%)',
type: 'line',
yAxisIndex: 1,
data: data.efficiencyData,
smooth: true,
lineStyle: {
width: 3,
type: 'dashed',
color: EFFICIENCY_COLOR
},
symbol: 'diamond',
symbolSize: 8,
itemStyle: {
color: EFFICIENCY_COLOR
},
markPoint: {
data: [
{ type: 'max', name: '最大值' },
{ type: 'min', name: '最小值' }
],
itemStyle: {
color: EFFICIENCY_COLOR
}
}
}
]
};
chartInstance.setOption(option);
};
// 响应窗口大小变化
const handleResize = () => {
if (chartInstance) {
chartInstance.resize();
}
};
// 生命周期钩子
onMounted(() => {
initChart();
window.addEventListener('resize', handleResize);
// 清理函数
return () => {
window.removeEventListener('resize', handleResize);
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
};
});
// 监听时间范围变化,更新图表
watch(timeRange, () => {
initChart();
});
</script>
<style scoped>
.chart-container {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
overflow: hidden;
height: 400px;
width: 100%;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
border-bottom: 1px solid #f0f0f0;
}
.chart-header h2 {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 0;
}
.chart-actions button {
background: none;
border: 1px solid #e0e0e0;
padding: 5px 12px;
border-radius: 4px;
margin-left: 8px;
cursor: pointer;
font-size: 12px;
transition: all 0.2s ease;
}
.chart-actions button.active {
background-color: #1890ff;
color: white;
border-color: #1890ff;
}
.chart-content {
width: 100%;
height: calc(100% - 54px);
padding: 10px;
}
@media (max-width: 768px) {
.chart-container {
height: 350px;
}
}
@media (max-width: 480px) {
.chart-container {
height: 300px;
}
.chart-header {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.chart-actions {
width: 100%;
display: flex;
justify-content: space-between;
}
.chart-actions button {
margin: 0;
flex: 1;
margin-right: 5px;
}
.chart-actions button:last-child {
margin-right: 0;
}
}
.model {
padding: 20px;
background-color: rgba(242, 248, 252, 1);
}
</style>

View File

@ -0,0 +1,30 @@
<template>
<el-row>
<el-col>
<div style="color: rgba(0, 30, 59, 1);;font-family: 'Alibaba-PuHuiTi-Bold';margin: 10px 0 0 0;"
:style="{ fontSize: fontLevelMap[props.fontLevel] }">
{{ props.title }}
</div>
</el-col>
<el-col>
<p style="color: rgba(154, 154, 154, 1);font-size: 14px;">
{{ props.subtitle }}
</p>
</el-col>
</el-row>
</template>
<script setup>
const props = defineProps({
title: String,
subtitle: String,
fontLevel: {
type: Number,
default: 1
}
})
const fontLevelMap = {
1: "24px",
2: "18px"
}
</script>

View File

@ -0,0 +1,210 @@
<template>
<el-card shadow="never" style="border-radius: 10px;">
<div style="margin-bottom: 20px;display: flex;align-items: center;justify-content: right;">
<span style="margin-right: 5px;color: rgba(113, 128, 150, 1);font-size: 14px;">
查看全部告警信息
</span>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8" height="8"
viewBox="0 0 8 8" fill="none">
<path
d="M5.94575 4.15722C5.94975 4.14947 5.95624 4.14298 5.95975 4.13497C6.0285 3.99197 6.00599 3.81697 5.88425 3.70197L3.1245 1.09172C2.97399 0.949466 2.73676 0.956216 2.59425 1.10648C2.45199 1.25698 2.4585 1.49422 2.60901 1.63673L5.08526 3.97922L2.61875 6.35647C2.46975 6.50021 2.46525 6.73746 2.60901 6.88672C2.6825 6.96321 2.78076 7.00148 2.87901 7.00148C2.97276 7.00148 3.06651 6.96648 3.13926 6.89648L5.87401 4.26073C5.87927 4.25547 5.88125 4.24823 5.88651 4.24274C5.89052 4.23899 5.89476 4.23623 5.89875 4.23224C5.92 4.20997 5.93124 4.18272 5.94575 4.15722Z"
fill="#718096">
</path>
</svg>
</div>
<div class="notice">
<div class="item">
<div class="icon">
<img src="/assets/demo/zgjxx.png" alt="">
</div>
<div class="content">
<p>总告警信息</p>
<p style="color: rgba(42, 130, 228, 1);">1,921</p>
</div>
</div>
<div class="item">
<div class="icon">
<img src="/assets/demo/ycl.png" alt="">
</div>
<div class="content">
<p>已处理</p>
<p style="color:rgba(0, 184, 122, 1);">500</p>
</div>
</div>
<div class="item">
<div class="icon">
<img src="/assets/demo/zzcl.png" alt="">
</div>
<div class="content">
<p>正在处理</p>
<p style="color: rgba(255, 141, 26, 1);">200</p>
</div>
</div>
<div class="item">
<div class="icon">
<img src="/assets/demo/wcl.png" alt="">
</div>
<div class="content">
<p>未处理</p>
<p style="color: rgba(227, 39, 39, 1);">1,221</p>
</div>
</div>
</div>
<div class="content">
<div class="list">
<div class="item waring">
<div class="left">
<p class="title">
逆变器温度过高
</p>
<p class="text">INV-2023-003 温度达到52超过阈值48</p>
</div>
<div class="right">
<div class="time">
10分钟前
</div>
<el-text type="warning" size="small">正在处理</el-text>
</div>
</div>
<div class="item danger">
<div class="left">
<p class="title">
通信中断
</p>
<p class="text">INV-2023-003 与监控系统通信中断</p>
</div>
<div class="right">
<div class="time">
20分钟前
</div>
<el-text type="primary" size="small">查看详情</el-text>
</div>
</div>
<div class="item danger">
<div class="left">
<p class="title">
通信中断
</p>
<p class="text">INV-2023-003 与监控系统通信中断</p>
</div>
<div class="right">
<div class="time">
1小时前
</div>
<el-text type="primary" size="small">查看详情</el-text>
</div>
</div>
<div class="item grey">
<div class="left">
<p class="title">
逆变器温度过高
</p>
<p class="text">INV-2023-003 温度达到52超过阈值48</p>
</div>
<div class="right">
<div class="time">
2小时前
</div>
<!-- <el-text type="primary" size="small">查看详情</el-text> -->
<el-button type="info" size="small" disabled>已处理</el-button>
</div>
</div>
</div>
</div>
</el-card>
</template>
<style scoped lang="scss">
.notice {
display: flex;
justify-content: space-between;
border-bottom: 1px solid rgba(32, 32, 32, 0.05);
padding-bottom: 20px;
.item {
display: flex;
}
p {
padding: 0;
margin: 0;
}
.icon {
width: 50px;
height: 50px;
margin-right: 10px;
img {
display: block;
width: 100%;
height: 100%;
}
}
.content p:nth-child(2) {
font-size: 14px;
margin-top: 5px;
}
}
.content {
.item {
border-radius: 10px;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
.text {
color: rgba(125, 133, 146, 1);
font-size: 12px;
}
.title {
font-size: 16px;
}
.right {
font-size: 12px;
color: rgba(125, 133, 146, 1);
.time {
margin-bottom: 5px;
}
}
}
.waring {
background-color: #FFFCE6;
border: 1px solid #FFF0E1;
.title {
color: #FFA408;
}
}
.danger {
background-color: #FFE9E5;
border: 1px solid #FFEFEB;
.title {
color: rgba(255, 87, 51, 1);
}
}
.grey {
background-color: #F3F3F3;
border: 1px solid #FCFCFC;
.right {
text-align: right;
}
.title {
color: rgba(102, 102, 102, 1);
}
}
}
</style>
<script setup></script>

View File

@ -0,0 +1,224 @@
<template>
<div class="cardItem">
<el-card>
<div class="tianqi"
style="display: flex;flex-direction: column;align-items: center;background-color: #FAFAFA;border-radius: 10px;padding-bottom: 40px;">
<div>
<img src="/assets/demo/Sunny.png" style="display: block; width: 100px;height: 100px;" alt="">
</div>
<div style="font-family: 'Alibaba-PuHuiTi-Bold';font-size: 24px;">
31
</div>
<div>晴朗</div>
<div style="color: rgba(154, 154, 154, 1);font-size: 14px;">
紫外线强度<span></span>
</div>
<div class="tianqi2">
<div class="item">
<div>
<img src="/assets/demo/shidu.png" alt="">
</div>
<div class="text">相对湿度 <span>45%</span></div>
</div>
<div class="item">
<div>
<img src="/assets/demo/qiangdu.png" alt="">
</div>
<div class="text">光照强度 <span>45%</span></div>
</div>
<div class="item">
<div>
<img src="/assets/demo/fengshu.png" alt="">
</div>
<div class="text">风速 <span>2.3m/s</span></div>
</div>
<div class="item">
<div>
<img src="/assets/demo/riluo.png" alt="">
</div>
<div class="text">日落时间 <span>19.45</span></div>
</div>
</div>
</div>
<div class="weather-timeline">
<div class="time-box">
<div class="time-item">
<div class="time">16:00</div>
<div class="temp">30°C</div>
<div class="img-box">
<img src="/assets/demo/sunny_s.png" alt="">
</div>
</div>
<div class="time-item">
<div class="time">17:00</div>
<div class="temp">29°C</div>
<div class="img-box">
<img src="/assets/demo/sunny_s.png" alt="">
</div>
</div>
<div class="time-item">
<div class="child">
<div class="time">18:00</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/rain.png" alt="">
</div>
</div>
</div>
<div class="time-item show">
<div class="time">现在</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/rain_show.png" alt="">
</div>
</div>
<div class="time-item">
<div class="time">20:00</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/yin.png" alt="">
</div>
</div>
<div class="time-item">
<div class="time">21:00</div>
<div class="temp">20°C</div>
<div class="img-box">
<img src="/assets/demo/yin.png" alt="">
</div>
</div>
</div>
</div>
</el-card>
</div>
</template>
<style scoped lang="scss">
.cardItem {
padding: -20px !important;
}
.tianqi2 {
width: 100%;
display: flex;
justify-content: space-around;
margin-top: 50px;
img {
width: 40px;
height: 40x;
display: block;
}
.item {
display: flex;
flex-direction: column;
align-items: center;
font-size: 14px;
.text {
margin-top: 10px;
}
}
}
.weather-timeline {
text-align: center;
color: #fff;
font-size: 14px;
margin: 15px 0;
.time {
margin: 10px 0;
}
.img-box {
width: 40px;
height: 40px;
margin: 10px 0;
}
img {
width: 100%;
height: 100%;
display: block;
}
// img[src*='Sunny'] {
// width: 50px;
// height: 50px;
// }
// img[src*='rain'] {
// width: 60px;
// height: 60px;
// }
padding: 15px;
background: linear-gradient(to right, #D6E2FF, #DEEBFF);
border-radius: 15px;
.time-box {
background: linear-gradient(to right, #447BFF, #67A3FD);
display: flex;
justify-content: space-between;
border-radius: 10px;
padding: 10px 20px;
align-items: center;
}
.time-item.show {
color: rgba(24, 109, 245, 1);
position: relative;
// z-index: 888;
background-color: #fff;
padding: 0 5px;
}
.show::after {
// color: rgba(24, 109, 245, 1);
// position: relative;
// z-index: 888;
// background-color: #fff;
content: '';
position: absolute;
width: 100%;
height: 25px;
// background-color: red;
background-color: #fff;
left: 0;
border-radius: 0 0 25px 25px;
}
.show::before {
// color: rgba(24, 109, 245, 1);
// position: relative;
// z-index: 888;
// background-color: #fff;
content: '';
position: absolute;
width: 100%;
height: 25px;
// background-color: red;
background-color: #fff;
left: 0;
top: -25px;
border-radius: 25px 25px 0 0;
}
// .show::after {
// content: '';
// position: absolute;
// height: 155px;
// background-color: #fff;
// z-index: 999;
// width: 100%;
// top: -25px;
// left: 0;
// border-radius: 20px;
// }
}
</style>
<script setup>
</script>

View File

@ -0,0 +1,107 @@
<template>
<el-card shadow="never" style="border-radius: 10px;">
<el-form :inline="true" :model="formInline" label-width="120" style="display: flex; justify-content: center;">
<el-form-item label="规则编号">
<el-input v-model="formInline.user" placeholder="请输入规则编号" clearable />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="formInline.region" placeholder="请输入状态" clearable>
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="更新时间">
<el-date-picker v-model="formInline.date" type="date" placeholder="请选择时间" clearable />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="onSubmit">搜索</el-button>
</el-form-item>
<el-form-item>
<el-button icon="refresh" type="default" @click="onSubmit">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="listData" @selection-change="handleSelectionChange">
<!-- <el-table-column type="index" width="50" label="序号" /> -->
<el-table-column label="逆变器编号" align="center" prop="id" />
<!-- <el-table-column label="合同类型" align="center" prop="contractType">
<template #default="scope">
<dict-tag :options="income_contract_type" :value="scope.row.contractType" />
</template>
</el-table-column> -->
<el-table-column label="输出功率" align="center" prop="shuchu" />
<el-table-column label="效率" align="center" prop="xiaolv" />
<el-table-column label="温度" align="center" prop="wendu" />
<el-table-column label="今日发电量" align="center" prop="fadian" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<!-- <el-button link type="primary">详情</el-button>
<el-button link type="danger">处理</el-button>
<el-button link type="warning">维护记录</el-button> -->
<el-tag :type="statusMap[scope.row.status].type">{{ statusMap[scope.row.status].label }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template #default="scope">
<el-button link type="primary">详情</el-button>
<el-button link type="danger">处理</el-button>
<el-button link type="warning">维护记录</el-button>
</template>
</el-table-column>
</el-table>
<!-- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" /> -->
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</el-card>
</template>
<script setup>
const formInline = ref({})
const total = ref(0);
const loading = ref(false);
const listData = [
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 1 },
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 1 },
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 2 },
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 2 },
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 3 },
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 3 }
]
const statusMap = {
1: {
label: "正常运行",
type: "success"
},
2: {
label: "异常",
type: "danger"
},
3: {
label: "维护中",
type: "warning"
}
}
const initFormData = {
};
const data = reactive({
form: { ...initFormData },
queryParams: {
},
});
const { queryParams, form, rules } = toRefs(data);
/** 多选框选中数据 */
const handleSelectionChange = (selection) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
const getList = async () => {
// loading.value = true;
// const res = await listIncomeContract(queryParams.value);
// incomeContractList.value = res.rows;
// total.value = res.total;
// loading.value = false;
};
</script>

File diff suppressed because one or more lines are too long

226
src/views/demo/index.vue Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,186 @@
<template>
<el-card>
<div class="container">
<div class="item">
<div class="top">
<div class="icon">
<img src="/assets/demo/sb1.png" alt="">
</div>
<div class="content">
<p class="t1">运行中</p>
<p class="t2">当前状态</p>
</div>
</div>
<div class="bottom">
<span class="icon"><svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="17.4462890625" height="4.361663818359375"
viewBox="0 0 17.4462890625 4.361663818359375" fill="none">
<path
d="M14.43 2.05L14.43 0.4C14.43 0.32495 14.5049 0.25 14.58 0.25L14.66 0.25L17.14 2.05C17.2151 2.12505 17.2151 2.20495 17.14 2.28L14.66 4.08C14.585 4.15505 14.505 4.08 14.43 4.08L14.43 2.5L0.55 2.5C0.399897 2.6501 0.25 2.4301 0.25 2.28C0.25 2.12988 0.399897 1.98 0.55 1.98L14.43 1.98L14.43 2.05Z"
stroke="rgba(67, 207, 124, 1)" stroke-width="0.5" fill="#43CF7C">
</path>
</svg>
</span>
<span class="t1">平稳运行</span>
<span class="t2">(30 days)</span>
</div>
</div>
<div class="item">
<div class="top">
<div class="icon">
<img src="/assets/demo/sb2.png" alt="">
</div>
<div class="content">
<p class="t1">128小时</p>
<p class="t2">运行时长</p>
</div>
</div>
<div class="bottom">
<span class="icon"><svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="17.4462890625" height="4.361663818359375"
viewBox="0 0 17.4462890625 4.361663818359375" fill="none">
<path
d="M14.43 2.05L14.43 0.4C14.43 0.32495 14.5049 0.25 14.58 0.25L14.66 0.25L17.14 2.05C17.2151 2.12505 17.2151 2.20495 17.14 2.28L14.66 4.08C14.585 4.15505 14.505 4.08 14.43 4.08L14.43 2.5L0.55 2.5C0.399897 2.6501 0.25 2.4301 0.25 2.28C0.25 2.12988 0.399897 1.98 0.55 1.98L14.43 1.98L14.43 2.05Z"
stroke="rgba(67, 207, 124, 1)" stroke-width="0.5" fill="#43CF7C">
</path>
</svg>
</span>
<span class="t1">平稳运行</span>
<span class="t2">(30 days)</span>
</div>
</div>
<div class="item">
<div class="top">
<div class="icon">
<img src="/assets/demo/sb3.png" alt="">
</div>
<div class="content">
<p class="t1">5/8</p>
<p class="t2">已完成步骤</p>
</div>
</div>
<div class="bottom">
<span class="icon"><svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="12.393798828125" height="7.42498779296875"
viewBox="0 0 12.393798828125 7.42498779296875" fill="none">
<path
d="M12.2438 0.225L12.2438 0.150012L12.2438 0.0750058L12.1688 0.0750058C12.1688 0.0750058 12.0937 0.0750058 12.0188 0L8.34376 0C7.96876 0 7.66876 0.300006 7.66876 0.675C7.66876 1.05001 7.96876 1.35 8.34376 1.35L10.2188 1.35L6.61876 4.95L4.81876 3.15C4.44375 2.775 3.69376 2.775 3.31875 3.15L0.16875 6.3C-0.05625 6.525 -0.05625 6.975 0.16875 7.2C0.318762 7.35001 0.468756 7.425 0.61875 7.425C0.768762 7.425 0.918756 7.425 1.06875 7.2L3.99375 4.275L5.79375 6.075C6.16876 6.45001 6.91875 6.45001 7.29376 6.075L11.0438 2.32501L11.0438 4.20001C11.0438 4.575 11.3438 4.87501 11.7188 4.87501C12.0937 4.87501 12.3938 4.575 12.3938 4.20001L12.3938 0.825011L12.3938 0.600011L12.2438 0.225Z"
fill="#00B87A">
</path>
</svg>
</span>
<span class="t1">完成率98%</span>
<span class="t2">(30 days)</span>
</div>
</div>
<div class="item">
<div class="top">
<div class="icon">
<img src="/assets/demo/sb4.png" alt="">
</div>
<div class="content">
<p class="t1" style="color: rgba(255, 153, 0, 1);">2</p>
<p class="t2">告警信息</p>
</div>
</div>
<div class="bottom">
<span class="icon"><svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="12.393798828125" height="7.42498779296875"
viewBox="0 0 12.393798828125 7.42498779296875" fill="none">
<path
d="M12.2438 0.225L12.2438 0.150012L12.2438 0.0750058L12.1688 0.0750058C12.1688 0.0750058 12.0937 0.0750058 12.0188 0L8.34376 0C7.96876 0 7.66876 0.300006 7.66876 0.675C7.66876 1.05001 7.96876 1.35 8.34376 1.35L10.2188 1.35L6.61876 4.95L4.81876 3.15C4.44375 2.775 3.69376 2.775 3.31875 3.15L0.16875 6.3C-0.05625 6.525 -0.05625 6.975 0.16875 7.2C0.318762 7.35001 0.468756 7.425 0.61875 7.425C0.768762 7.425 0.918756 7.425 1.06875 7.2L3.99375 4.275L5.79375 6.075C6.16876 6.45001 6.91875 6.45001 7.29376 6.075L11.0438 2.32501L11.0438 4.20001C11.0438 4.575 11.3438 4.87501 11.7188 4.87501C12.0937 4.87501 12.3938 4.575 12.3938 4.20001L12.3938 0.825011L12.3938 0.600011L12.2438 0.225Z"
fill="#00B87A">
</path>
</svg>
</span>
<span class="t1">4%</span>
<span class="t2">(30 days)</span>
</div>
</div>
<div class="back">
<span>34522</span>
<span>已安全运行</span>
</div>
</div>
</el-card>
</template>
<style scoped lang="scss">
.content {
font-family: "Alibaba-PuHuiTi-Bold";
}
.container {
display: flex;
justify-content: space-around;
}
.item {
background-color: rgba(240, 249, 255, 1);
padding: 20px 40px 20px 20px;
border-radius: 20px;
text-align: center;
.top {
display: flex;
align-items: center;
text-align: left;
.icon {
img {
width: 100%;
height: 100%;
display: block;
margin-top: -20px;
}
width: 50px;
height: 50px;
margin-right: 20px;
}
.t1 {
font-size: 26px;
}
.t2 {
font-size: 18px;
color: rgba(62, 73, 84, 1);
}
p {
margin: 10px 0;
}
}
.bottom {
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
.icon {
display: flex;
align-items: center;
}
.t1 {
color: rgba(0, 184, 122, 1);
margin: 0 5px;
}
.t2 {
color: rgba(150, 155, 160, 1);
}
}
}
.back {
position: relative;
}
</style>
<script setup>
</script>

23
src/views/demo1/index.vue Normal file
View File

@ -0,0 +1,23 @@
<template>
<div style="padding: 20px;">
<el-row>
<el-col :span="15">
<TitleComponent title="设备情况" subtitle="电站一次监控数据" />
<sbqk />
</el-col>
<el-col :span="8">
</el-col>
</el-row>
</div>
</template>
<style scoped>
.el-card {
border-radius: 10px;
}
</style>
<script setup>
import TitleComponent from '@/views/demo/components/TitleComponent.vue';
import sbqk from './components/sbqk.vue';
</script>

View File

@ -5,23 +5,19 @@
<el-form :model="param" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col :span="2">
<el-button
type="success"
v-auth="'/zm/api/v1/system/document/templateRecycleBin'"
:disabled="multiple"
@click="onRecyclingStation(null, true)"
>
<el-icon><RefreshRight /></el-icon>批量恢复
<el-button type="success" v-auth="'/zm/api/v1/system/document/templateRecycleBin'" :disabled="multiple"
@click="onRecyclingStation(null, true)" v-hasPermi="['quality:knowledgeDocument:recovery']">
<el-icon>
<RefreshRight />
</el-icon>批量恢复
</el-button>
</el-col>
<el-col :span="2">
<el-button
type="danger"
v-auth="'/zm/api/v1/system/document/templateRecycleBin'"
:disabled="multiple"
@click="onRecyclingStation(null, false)"
>
<el-icon><DeleteFilled /></el-icon>批量删除
<el-button type="danger" v-auth="'/zm/api/v1/system/document/templateRecycleBin'" :disabled="multiple"
@click="onRecyclingStation(null, false)">
<el-icon>
<DeleteFilled />
</el-icon>批量删除
</el-button>
</el-col>
</el-row>
@ -40,14 +36,18 @@
<el-table-column label="操作" align="center" class-name="small-padding" min-width="80px" fixed="right">
<template #default="scope">
<div>
<el-button type="success" v-auth="'/zm/api/v1/system/document/templateRecycleBin'" link @click="onRecyclingStation(scope.row, true)">
<el-icon><RefreshRight /></el-icon>恢复
<el-button type="success" v-auth="'/zm/api/v1/system/document/templateRecycleBin'" link
@click="onRecyclingStation(scope.row, true)">
<el-icon>
<RefreshRight />
</el-icon>恢复
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="param.pageNum" v-model:limit="param.pageSize" @pagination="getDocumentDataList" />
<pagination v-show="total > 0" :total="total" v-model:page="param.pageNum" v-model:limit="param.pageSize"
@pagination="getDocumentDataList" />
</el-card>
</div>
</template>
@ -139,7 +139,7 @@ const onRecyclingStation = (row: any, flag: boolean) => {
});
}
})
.catch(() => {});
.catch(() => { });
};
const filterfilenPath = (val: string): string => {
@ -155,6 +155,7 @@ defineExpose({
.colBlock {
display: block;
}
.colNone {
display: none;
}

View File

@ -5,48 +5,39 @@
<div class="box_info">
<div class="tree_left1" id="tree_left1">
<div class="file_upload check_select">
<div class="box_btn" v-auth="'/zm/api/v1/system/documentData/add'">
<file-upload
v-model="state.paramsQuery.file"
:limit="100"
:uploadUrl="uploadUrl"
:params="uploadParams"
:on-upload-success="uploadFile"
>
<div class="box_btn" v-auth="'/zm/api/v1/system/documentData/add'"
v-hasPermi="['quality:knowledgeDocument:file']">
<file-upload v-model="state.paramsQuery.file" :limit="100" :uploadUrl="uploadUrl" :params="uploadParams"
:on-upload-success="uploadFile">
<el-button type="primary" style="float: left" :disabled="!state.parentPid">
<el-icon size="small"><Plus /></el-icon>上传文件
<el-icon size="small">
<Plus />
</el-icon>上传文件
</el-button>
</file-upload>
</div>
<el-button
type="primary"
v-auth="'/zm/api/v1/system/documentProject/dataCompressedDownload'"
:disabled="!state.parentPid"
@click="onExport"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="primary" @click="onBook" v-auth="'/zm/api/v1/system/documentData/dataFileQuery'"
><el-icon><View /></el-icon>查看全项目文件</el-button
>
<el-button type="primary" v-auth="'/zm/api/v1/system/documentProject/dataCompressedDownload'"
v-hasPermi="['quality:knowledgeDocument:fileList']" :disabled="!state.parentPid"
@click="onExport"><el-icon>
<Download />
</el-icon>下载</el-button>
<el-button type="primary" @click="onBook"
v-auth="'/zm/api/v1/system/documentData/dataFileQuery'"><el-icon>
<View />
</el-icon>查看全项目文件</el-button>
</div>
<div class="file_upload check_select">
<el-input class="input_left" v-model="filterText" size="small" placeholder="请输入文件名称" />
</div>
<el-tree
ref="treeRef"
highlight-current
:default-expand-all="state.checked"
:filter-node-method="filterFolder"
:data="state.treeList"
node-key="id"
accordion
:expand-on-click-node="false"
@node-click="handleNodeClick"
:current-node-key="state.selectedNodeId"
>
<el-tree ref="treeRef" highlight-current :default-expand-all="state.checked"
:filter-node-method="filterFolder" :data="state.treeList" node-key="id" accordion
:expand-on-click-node="false" @node-click="handleNodeClick" :current-node-key="state.selectedNodeId">
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon color="#f1a81a"><FolderOpened /></el-icon>
<el-icon color="#f1a81a">
<FolderOpened />
</el-icon>
<span>{{ node.label }}</span>
</span>
</template>
@ -59,22 +50,18 @@
<el-row>
<el-col :span="7" class="colBlock">
<el-form-item label="文件名称" prop="fileName">
<el-input
v-model="state.paramsQuery.fileName"
placeholder="请输入文件名称"
clearable
@keyup.enter.native="getdocumentDataList"
/>
<el-input v-model="state.paramsQuery.fileName" placeholder="请输入文件名称" clearable
@keyup.enter.native="getdocumentDataList" />
</el-form-item>
</el-col>
<el-col :span="6" class="m-l10">
<el-form-item>
<el-button type="primary" @click="searchInfo"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery"
><el-icon><Refresh /></el-icon>重置</el-button
>
<el-button type="primary" @click="searchInfo"><el-icon>
<Search />
</el-icon>搜索</el-button>
<el-button @click="resetQuery"><el-icon>
<Refresh />
</el-icon>重置</el-button>
</el-form-item>
</el-col>
<!-- <el-col :span="4">
@ -97,44 +84,38 @@
<el-table-column label="上传时间" align="center" prop="createTime"> </el-table-column>
<el-table-column label="操作" align="center" width="300">
<template #default="scope">
<el-button
type="primary"
v-auth="'/zm/api/v1/system/documentData/get'"
v-if="acceptType.includes(scope.row.fileSuffix)"
link
@click="handleView(scope.row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button
type="primary"
v-auth="'/zm/api/v1/system/documentData/complaintBoxAdd'"
v-if="state.wordType.includes(scope.row.fileSuffix)"
link
@click="updataView(scope.row)"
><el-icon><EditPen /></el-icon>修改文件</el-button
>
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/uniFolderDownload'" link @click="onExportView(scope.row)"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="success" v-auth="'/zm/api/v1/system/documentData/edit'" link @click="updateName(scope.row)"
><el-icon><EditPen /></el-icon>修改名称</el-button
>
<el-button type="danger" v-auth="'/zm/api/v1/system/documentData/delete'" link @click="handleDelete(scope.row)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
>
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/get'"
v-if="acceptType.includes(scope.row.fileSuffix)" link @click="handleView(scope.row)"><el-icon>
<View />
</el-icon>查看</el-button>
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/complaintBoxAdd'"
v-hasPermi="['quality:knowledgeDocument:file']" v-if="state.wordType.includes(scope.row.fileSuffix)"
link @click="updataView(scope.row)"><el-icon>
<EditPen />
</el-icon>修改文件</el-button>
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/uniFolderDownload'" link
v-hasPermi="['quality:knowledgeDocument:file']" @click="onExportView(scope.row)"><el-icon>
<Download />
</el-icon>下载</el-button>
<el-button type="success" v-auth="'/zm/api/v1/system/documentData/edit'" link
@click="updateName(scope.row)" v-hasPermi="['quality:knowledgeDocument:file']"><el-icon>
<EditPen />
</el-icon>修改名称</el-button>
<el-button type="danger" v-auth="'/zm/api/v1/system/documentData/delete'" link
@click="handleDelete(scope.row)"><el-icon>
<DeleteFilled />
</el-icon>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
:total="state.total"
v-model:page="state.paramsQuery.pageNum"
v-model:limit="state.paramsQuery.pageSize"
@pagination="getdocumentDataList"
/>
<pagination :total="state.total" v-model:page="state.paramsQuery.pageNum"
v-model:limit="state.paramsQuery.pageSize" @pagination="getdocumentDataList" />
</div>
</div>
<documentsDeailsVue ref="documentDetailRef" v-if="state.showDocumentDetail" @onClose="onClose"></documentsDeailsVue>
<documentsEdit ref="documentDataEditRef" v-if="state.showdocumentDataEdit" @onClose="onCloseEdit"></documentsEdit>
<documentsDeailsVue ref="documentDetailRef" v-if="state.showDocumentDetail" @onClose="onClose">
</documentsDeailsVue>
<documentsEdit ref="documentDataEditRef" v-if="state.showdocumentDataEdit" @onClose="onCloseEdit">
</documentsEdit>
<!-- <uploadFileder
ref="uploadFilederRef"
v-if="state.showUploadFileder"
@ -154,15 +135,8 @@
</template>
</el-dialog>
</div>
<el-image-viewer
ref="imageRef"
style="width: 100%; height: 100%"
:url-list="[imgUrl]"
v-if="imgUrl"
show-progress
fit="cover"
@close="imgUrl = ''"
/>
<el-image-viewer ref="imageRef" style="width: 100%; height: 100%" :url-list="[imgUrl]" v-if="imgUrl" show-progress
fit="cover" @close="imgUrl = ''" />
</el-tab-pane>
<el-tab-pane label="回收站" name="second">
<RecyclingStation ref="recylingRef"></RecyclingStation>
@ -472,7 +446,7 @@ const delFile = (msg, data, cb) => {
}
});
})
.catch(() => {});
.catch(() => { });
};
const editName = (data, title, type) => {
ElMessageBox.prompt(title, '温馨提示', {
@ -502,7 +476,7 @@ const editName = (data, title, type) => {
}
});
})
.catch(() => {});
.catch(() => { });
};
const onExport = () => {
getUniFolderDownloadList(state.paramsQuery.folderId).then((res: any) => {
@ -535,30 +509,37 @@ onMounted(() => {
<style lang="scss" scoped>
.profile_engin {
height: 80vh;
.set-tool {
display: none;
}
.el-tree-node__content:hover,
.el-tree-node__content:active {
.set-tool {
display: inline-block;
}
}
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
background-color: #354e67 !important;
color: #fff;
}
.box_info {
display: flex;
justify-content: space-between;
}
.pagination-container {
padding: 10px 0 !important;
}
> div {
>div {
height: 100%;
width: 100%;
}
.tree_left1 {
width: 30%;
background-color: #fff;
@ -569,6 +550,7 @@ onMounted(() => {
min-width: 26%;
border-right: 6px solid;
border-right-color: rgba(204, 230, 255, 0);
.resize-handle-right {
top: 0;
width: 6px;
@ -578,6 +560,7 @@ onMounted(() => {
position: absolute;
z-index: 999;
}
.check_select {
display: flex;
align-items: center;
@ -585,43 +568,52 @@ onMounted(() => {
// justify-content: space-between;
padding: 4px;
border-bottom: 1px solid #f1f1f1;
.box_btn {
margin: 0 10px 0 20px;
position: relative;
> span {
>span {
padding: 4px 10px;
background: #67c23a;
color: #fff;
border-radius: 2px;
}
.btn {
position: absolute;
left: 20%;
display: none;
top: -2px;
width: 220px;
.el-button {
float: left;
}
}
}
.box_btn:hover,
.box_btn:active {
cursor: pointer;
.btn {
display: block;
}
}
}
.file_upload {
margin: 2px 0;
}
.input_left {
padding: 6px;
box-sizing: border-box;
// border-bottom: 1px solid #cbcbcb;
}
}
.list_right {
width: 69.5%;
background: white;
@ -629,11 +621,13 @@ onMounted(() => {
padding: 10px;
box-sizing: border-box;
}
.el-tree {
height: calc(80vh - 160px);
width: 100%;
overflow: auto !important;
}
// .el-tree-node__children {
// overflow: visible !important;
// }

View File

@ -1,6 +1,7 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
@ -12,23 +13,19 @@
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="角色状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
<el-date-picker v-model="dateRange" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button type="primary" icon="Search" @click="handleQuery"
v-hasPermi="['system:role:query']">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
@ -40,18 +37,9 @@
<el-col :lg="4" :xs="24" style="">
<el-card shadow="hover">
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
ref="deptTreeRef"
class="mt-2"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
default-expand-all
@node-click="handleNodeClick"
/>
<el-tree ref="deptTreeRef" class="mt-2" node-key="id" :data="deptOptions"
:props="{ label: 'label', children: 'children' }" :expand-on-click-node="false"
:filter-node-method="filterNode" highlight-current default-expand-all @node-click="handleNodeClick" />
</el-card>
</el-col>
<el-col :lg="20" :xs="24">
@ -59,20 +47,20 @@
<template #header>
<el-row :gutter="10">
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
<el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus"
@click="handleAdd()">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()"
>修改</el-button
>
<el-button v-hasPermi="['system:role:edit']" type="success" plain :disabled="single" icon="Edit"
@click="handleUpdate()">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:delete']" type="danger" plain :disabled="ids.length === 0" @click="handleDelete()"
>删除</el-button
>
<el-button v-hasPermi="['system:role:delete']" type="danger" plain :disabled="ids.length === 0"
@click="handleDelete()">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
<el-button v-hasPermi="['system:role:export']" type="warning" plain icon="Download"
@click="handleExport">导出</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
@ -86,7 +74,8 @@
<el-table-column label="显示顺序" prop="roleSort" width="100" />
<el-table-column label="状态" align="center" width="100">
<template #default="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1"
@change="handleStatusChange(scope.row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
@ -98,28 +87,27 @@
<el-table-column fixed="right" label="操作" width="180">
<template #default="scope">
<el-tooltip v-if="scope.row.roleId !== 1" content="修改" placement="top">
<el-button v-hasPermi="['system:role:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
<el-button v-hasPermi="['system:role:edit']" link type="primary" icon="Edit"
@click="handleUpdate(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.roleId !== 1" content="删除" placement="top">
<el-button v-hasPermi="['system:role:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
<el-button v-hasPermi="['system:role:remove']" link type="primary" icon="Delete"
@click="handleDelete(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.roleId !== 1" content="数据权限" placement="top">
<el-button v-hasPermi="['system:role:edit']" link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)"></el-button>
<el-button v-hasPermi="['system:role:edit']" link type="primary" icon="CircleCheck"
@click="handleDataScope(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.roleId !== 1" content="分配用户" placement="top">
<el-button v-hasPermi="['system:role:edit']" link type="primary" icon="User" @click="handleAuthUser(scope.row)"></el-button>
<el-button v-hasPermi="['system:role:edit']" link type="primary" icon="User"
@click="handleAuthUser(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination
v-if="total > 0"
v-model:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-if="total > 0" v-model:total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
</el-col>
</el-row>
@ -127,16 +115,8 @@
<el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
<el-form ref="roleFormRef" :model="form" :rules="rules" label-width="110px">
<el-form-item label="所属部门" prop="deptId">
<el-cascader
:options="deptOptions"
v-model="form.deptId"
placeholder="请选择所属部门"
clearable
filterable
:show-all-levels="false"
:props="{ value: 'id', emitPath: false, checkStrictly: true }"
@change=""
>
<el-cascader :options="deptOptions" v-model="form.deptId" placeholder="请选择所属部门" clearable filterable
:show-all-levels="false" :props="{ value: 'id', emitPath: false, checkStrictly: true }" @change="">
</el-cascader>
</el-form-item>
<el-form-item label="角色名称" prop="roleName">
@ -158,26 +138,23 @@
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label
}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="菜单权限">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand(Boolean($event), 'menu')">展开/折叠</el-checkbox>
<el-checkbox v-model="menuExpand"
@change="handleCheckedTreeExpand(Boolean($event), 'menu')">展开/折叠</el-checkbox>
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
<el-tree
ref="menuRef"
class="tree-border"
:data="menuOptions"
show-checkbox
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中请稍候"
:props="{ label: 'label', children: 'children' }"
></el-tree>
<el-checkbox v-model="form.menuCheckStrictly"
@change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
<el-tree ref="menuRef" class="tree-border" :data="menuOptions" show-checkbox node-key="id"
:check-strictly="!form.menuCheckStrictly" empty-text="加载中请稍候"
:props="{ label: 'label', children: 'children' }"></el-tree>
</el-form-item>
<el-form-item label="是否为特殊角色">
<el-switch v-model="form.isSpecial" active-value="1" inactive-value="0" active-text="是" inactive-text="否"> </el-switch>
<el-switch v-model="form.isSpecial" active-value="1" inactive-value="0" active-text="是" inactive-text="否">
</el-switch>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
@ -202,24 +179,19 @@
</el-form-item>
<el-form-item label="权限范围">
<el-select v-model="form.dataScope" @change="dataScopeSelectChange">
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item v-show="form.dataScope === '2'" label="数据权限">
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand(Boolean($event), 'dept')">展开/折叠</el-checkbox>
<el-checkbox v-model="deptExpand"
@change="handleCheckedTreeExpand(Boolean($event), 'dept')">展开/折叠</el-checkbox>
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
<el-tree
ref="deptRef"
class="tree-border"
:data="deptOptions"
show-checkbox
default-expand-all
node-key="id"
:check-strictly="!form.deptCheckStrictly"
empty-text="加载中请稍候"
:props="{ label: 'label', children: 'children' }"
></el-tree>
<el-checkbox v-model="form.deptCheckStrictly"
@change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
<el-tree ref="deptRef" class="tree-border" :data="deptOptions" show-checkbox default-expand-all node-key="id"
:check-strictly="!form.deptCheckStrictly" empty-text="加载中请稍候"
:props="{ label: 'label', children: 'children' }"></el-tree>
</el-form-item>
</el-form>
<template #footer>

View File

@ -5,22 +5,14 @@
<el-col :lg="4" :xs="24" style="">
<el-card shadow="hover">
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
ref="deptTreeRef"
class="mt-2"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
default-expand-all
@node-click="handleNodeClick"
/>
<el-tree ref="deptTreeRef" class="mt-2" node-key="id" :data="deptOptions"
:props="{ label: 'label', children: 'children' }" :expand-on-click-node="false"
:filter-node-method="filterNode" highlight-current default-expand-all @node-click="handleNodeClick" />
</el-card>
</el-col>
<el-col :lg="20" :xs="24">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
@ -28,27 +20,25 @@
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="用户状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
<el-date-picker v-model="dateRange" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button type="primary" icon="Search" @click="handleQuery"
@v-has-permi="['system:user:query']">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
@ -60,15 +50,18 @@
<template #header>
<el-row :gutter="10">
<el-col :span="1.5">
<el-button v-has-permi="['system:user:add']" type="primary" plain icon="Plus" @click="handleAdd()"> 新增 </el-button>
<el-button v-has-permi="['system:user:add']" type="primary" plain icon="Plus" @click="handleAdd()"> 新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-has-permi="['system:user:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()">
<el-button v-has-permi="['system:user:edit']" type="success" plain :disabled="single" icon="Edit"
@click="handleUpdate()">
修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-has-permi="['system:user:remove']" type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()">
<el-button v-has-permi="['system:user:remove']" type="danger" plain :disabled="multiple" icon="Delete"
@click="handleDelete()">
删除
</el-button>
</el-col>
@ -83,26 +76,34 @@
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>
<el-dropdown-item v-has-permi="['system:user:import']" icon="Top" @click="handleImport">导入数据 </el-dropdown-item>
<el-dropdown-item v-has-permi="['system:user:export']" icon="Download" @click="handleExport"> 导出数据 </el-dropdown-item>
<el-dropdown-item v-has-permi="['system:user:import']" icon="Top" @click="handleImport">导入数据
</el-dropdown-item>
<el-dropdown-item v-has-permi="['system:user:export']" icon="Download" @click="handleExport"> 导出数据
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<right-toolbar v-model:show-search="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar>
<right-toolbar v-model:show-search="showSearch" :columns="columns" :search="true"
@query-table="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column v-if="columns[0].visible" key="userId" label="用户编号" align="center" prop="userId" />
<el-table-column v-if="columns[1].visible" key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
<el-table-column v-if="columns[2].visible" key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column v-if="columns[3].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
<el-table-column v-if="columns[4].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" />
<el-table-column v-if="columns[1].visible" key="userName" label="用户名称" align="center" prop="userName"
:show-overflow-tooltip="true" />
<el-table-column v-if="columns[2].visible" key="nickName" label="用户昵称" align="center" prop="nickName"
:show-overflow-tooltip="true" />
<el-table-column v-if="columns[3].visible" key="deptName" label="部门" align="center" prop="deptName"
:show-overflow-tooltip="true" />
<el-table-column v-if="columns[4].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber"
width="120" />
<el-table-column v-if="columns[5].visible" key="status" label="状态" align="center">
<template #default="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1"
@change="handleStatusChange(scope.row)"></el-switch>
</template>
</el-table-column>
@ -115,24 +116,30 @@
<el-table-column label="操作" fixed="right" width="230" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip v-if="scope.row.userId !== 1" content="修改" placement="top">
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Edit"
@click="handleUpdate(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.userId !== 1" content="删除" placement="top">
<el-button v-hasPermi="['system:user:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
<el-button v-hasPermi="['system:user:remove']" link type="primary" icon="Delete"
@click="handleDelete(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.userId !== 1" content="重置密码" placement="top">
<el-button v-hasPermi="['system:user:resetPwd']" link type="primary" icon="Key" @click="handleResetPwd(scope.row)"></el-button>
<el-button v-hasPermi="['system:user:resetPwd']" link type="primary" icon="Key"
@click="handleResetPwd(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.userId !== 1" content="分配角色" placement="top">
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)"></el-button>
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="CircleCheck"
@click="handleAuthRole(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.userId !== 1" content="编辑关联项目" placement="top">
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Edit" @click="handleUpdateProject(scope.row)"></el-button>
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Edit"
@click="handleUpdateProject(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.userId !== 1" content="上传证书目录" placement="top">
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Upload" @click="handleUploadCert(scope.row)"></el-button>
<el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Upload"
@click="handleUploadCert(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
@ -141,19 +148,15 @@
<shuttle-frame :userId="selectedUserId" @close="shuttleVisible = false" />
</el-dialog>
<pagination
v-show="total > 0"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="getList"
/>
<pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
:total="total" @pagination="getList" />
</el-card>
</el-col>
</el-row>
<!-- 添加或修改用户配置对话框 -->
<el-dialog ref="formDialogRef" v-model="dialog.visible" :title="dialog.title" width="600px" append-to-body @close="closeDialog">
<el-dialog ref="formDialogRef" v-model="dialog.visible" :title="dialog.title" width="600px" append-to-body
@close="closeDialog">
<el-form ref="userFormRef" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="12">
@ -163,15 +166,9 @@
</el-col>
<el-col :span="12">
<el-form-item label="归属部门" prop="deptId">
<el-tree-select
v-model="form.deptId"
:data="enabledDeptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
value-key="id"
placeholder="请选择归属部门"
check-strictly
@change="handleDeptChange"
/>
<el-tree-select v-model="form.deptId" :data="enabledDeptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }" value-key="id" placeholder="请选择归属部门"
check-strictly @change="handleDeptChange" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -197,20 +194,16 @@
<el-col :span="12">
<el-form-item label="用户性别">
<el-select v-model="form.sex" placeholder="请选择">
<el-option v-for="dict in sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option v-for="dict in sys_user_sex" :key="dict.value" :label="dict.label"
:value="dict.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="岗位">
<el-select v-model="form.postIds" multiple placeholder="请选择">
<el-option
v-for="item in postOptions"
:key="item.postId"
:label="item.postName"
:value="item.postId"
:disabled="item.status == '1'"
></el-option>
<el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId"
:disabled="item.status == '1'"></el-option>
</el-select>
</el-form-item>
</el-col>
@ -219,20 +212,16 @@
<el-col :span="11" :offset="0">
<el-form-item label="项目列表">
<el-select v-model="item.projectId" placeholder="请选择">
<el-option v-for="dict in projectOptions" :key="dict.id" :label="dict.shortName" :value="dict.id"></el-option>
<el-option v-for="dict in projectOptions" :key="dict.id" :label="dict.shortName"
:value="dict.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="11" :offset="0">
<el-form-item label="角色">
<el-select v-model="item.roleIds" filterable multiple placeholder="请选择">
<el-option
v-for="item in roleOptions"
:key="item.roleId"
:label="item.roleName"
:value="item.roleId"
:disabled="item.status == '1'"
></el-option>
<el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName"
:value="item.roleId" :disabled="item.status == '1'"></el-option>
</el-select>
</el-form-item>
</el-col>
@ -245,7 +234,8 @@
<el-col :span="12">
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }} </el-radio>
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
@ -266,18 +256,9 @@
<!-- 用户导入对话框 -->
<el-dialog draggable v-model="upload.open" :title="upload.title" width="400px" append-to-body>
<el-upload
ref="uploadRef"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<el-icon class="el-icon--upload">
<i-ep-upload-filled />
</el-icon>
@ -289,7 +270,8 @@
是否更新已经存在的用户数据
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板 </el-link>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline"
@click="importTemplate">下载模板 </el-link>
</div>
</template>
</el-upload>