deploy
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 若依管理系统
|
||||
VITE_APP_TITLE = 口袋九章
|
||||
|
||||
# 开发环境配置
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
# 若依管理系统/开发环境
|
||||
# 口袋九章/开发环境
|
||||
VITE_APP_BASE_API = '/dev-api'
|
||||
|
@ -1,10 +1,10 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 若依管理系统
|
||||
VITE_APP_TITLE = 口袋九章
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'production'
|
||||
|
||||
# 若依管理系统/生产环境
|
||||
# 口袋九章/生产环境
|
||||
VITE_APP_BASE_API = '/api'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
|
@ -1,10 +1,10 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 若依管理系统
|
||||
VITE_APP_TITLE = 口袋九章
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'staging'
|
||||
|
||||
# 若依管理系统/生产环境
|
||||
# 口袋九章/生产环境
|
||||
VITE_APP_BASE_API = '/stage-api'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
|
@ -7,7 +7,7 @@
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<title>若依管理系统</title>
|
||||
<title>口袋九章</title>
|
||||
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
|
||||
<style>
|
||||
html,
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ruoyi",
|
||||
"version": "3.8.5",
|
||||
"description": "若依管理系统",
|
||||
"description": "口袋九章",
|
||||
"author": "若依",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@ -18,8 +18,11 @@
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "2.0.10",
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@vueup/vue-quill": "1.1.0",
|
||||
"@vueup/vue-quill": "^1.2.0",
|
||||
"@vueuse/core": "9.5.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"ant-design-vue": "4.x",
|
||||
"axios": "0.27.2",
|
||||
"echarts": "5.4.0",
|
||||
"element-plus": "2.2.27",
|
||||
@ -32,6 +35,7 @@
|
||||
"nprogress": "0.2.0",
|
||||
"pinia": "2.0.22",
|
||||
"pinia-plugin-persistedstate": "^3.1.0",
|
||||
"quill-image-uploader": "^1.3.0",
|
||||
"v3-infinite-loading": "^1.2.2",
|
||||
"vue": "3.2.45",
|
||||
"vue-cropper": "1.0.3",
|
||||
|
70
src/api/employee/employee.js
Normal file
70
src/api/employee/employee.js
Normal file
@ -0,0 +1,70 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
// 查询员工列表
|
||||
export function listEmployee(query) {
|
||||
return request({
|
||||
url: "/employee/employee/list",
|
||||
method: "get",
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询员工详细
|
||||
export function getEmployee(userId) {
|
||||
return request({
|
||||
url: "/employee/employee/" + userId,
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
// 新增员工
|
||||
export function addEmployee(data) {
|
||||
return request({
|
||||
url: "/employee/employee",
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// 修改员工
|
||||
export function updateEmployee(data) {
|
||||
return request({
|
||||
url: "/employee/employee",
|
||||
method: "put",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除员工
|
||||
export function delEmployee(userId) {
|
||||
return request({
|
||||
url: "/employee/employee/" + userId,
|
||||
method: "delete",
|
||||
});
|
||||
}
|
||||
|
||||
export const downloadEmployeeTemplate = () =>
|
||||
request({
|
||||
url: "/employee/employee/importTemplate",
|
||||
method: "GET",
|
||||
responseType: "blob",
|
||||
});
|
||||
|
||||
/**
|
||||
* 修改员工积分
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const updateEmployeePoint = (data) =>
|
||||
request({
|
||||
url: "/employee/employee/updatePoint",
|
||||
method: "PUT",
|
||||
data,
|
||||
});
|
||||
|
||||
export const updateEmployeeStatus = (data) =>
|
||||
request({
|
||||
url: "/employee/employee/changeStatus",
|
||||
method: "PUT",
|
||||
data,
|
||||
});
|
14
src/api/finance/detail.js
Normal file
14
src/api/finance/detail.js
Normal file
@ -0,0 +1,14 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export const financeDetailList = (params) =>
|
||||
request({ url: "/finance/detail/list", method: "GET", params });
|
||||
|
||||
export const deleteFinanceDetail = (financeIds) =>
|
||||
request({ url: `/finance/detail/${financeIds}`, method: "DELETE" });
|
||||
|
||||
export const getFinanceDetail = (financeId) =>
|
||||
request({ url: `/finance/detail/${financeId}`, method: "GET" });
|
||||
export const addFinanceDetail = (data) =>
|
||||
request({ url: `/finance/detail`, method: "POST", data });
|
||||
export const updateFinanceDetail = (data) =>
|
||||
request({ url: `/finance/detail`, method: "PUT", data });
|
@ -71,4 +71,3 @@ export const getRouters = () => {
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
|
||||
|
106
src/api/product/product.js
Normal file
106
src/api/product/product.js
Normal file
@ -0,0 +1,106 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
// 查询产品列表
|
||||
export function listProduct(query) {
|
||||
return request({
|
||||
url: "/product/product/list",
|
||||
method: "get",
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询产品详细
|
||||
export function getProduct(productId) {
|
||||
return request({
|
||||
url: "/product/product/" + productId,
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
// 新增产品
|
||||
export function addProduct(data) {
|
||||
return request({
|
||||
url: "/product/product",
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// 修改产品
|
||||
export function updateProduct(data) {
|
||||
return request({
|
||||
url: "/product/product",
|
||||
method: "put",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除产品
|
||||
export function delProduct(productId) {
|
||||
return request({
|
||||
url: "/product/product/" + productId,
|
||||
method: "delete",
|
||||
});
|
||||
}
|
||||
|
||||
// 添加型号
|
||||
export const addModel = (data) =>
|
||||
request({
|
||||
url: "/product/model",
|
||||
method: "POST",
|
||||
data,
|
||||
});
|
||||
|
||||
export const modelList = (params) =>
|
||||
request({
|
||||
url: "/product/model/list",
|
||||
method: "GET",
|
||||
params,
|
||||
});
|
||||
export const getModel = (modelId) =>
|
||||
request({
|
||||
url: `/product/model/${modelId}`,
|
||||
method: "GET",
|
||||
});
|
||||
export const updateModel = (data) =>
|
||||
request({
|
||||
url: "/product/model",
|
||||
method: "PUT",
|
||||
data,
|
||||
});
|
||||
export const deleteModel = (modelIds) =>
|
||||
request({
|
||||
url: `/product/model/${modelIds}`,
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
export const addSpec = (data) =>
|
||||
request({
|
||||
url: "/product/spec",
|
||||
method: "POST",
|
||||
data,
|
||||
});
|
||||
|
||||
export const listSpec = (params) =>
|
||||
request({
|
||||
url: "/product/spec/list",
|
||||
method: "GET",
|
||||
params,
|
||||
});
|
||||
export const getSpec = (specId) =>
|
||||
request({
|
||||
url: `/product/spec/${specId}`,
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
export const updateSpec = (data) =>
|
||||
request({
|
||||
url: "/product/spec",
|
||||
method: "PUT",
|
||||
data,
|
||||
});
|
||||
export const deleteSpec = (modelIds) =>
|
||||
request({
|
||||
url: `/product/spec/${modelIds}`,
|
||||
method: "DELETE",
|
||||
});
|
15
src/api/product/stock.js
Normal file
15
src/api/product/stock.js
Normal file
@ -0,0 +1,15 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export const loadStockLogList = (params) =>
|
||||
request({
|
||||
url: "/product/stocklog/list",
|
||||
method: "GET",
|
||||
params,
|
||||
});
|
||||
|
||||
export const loadStockList = (params) =>
|
||||
request({
|
||||
url: "/product/stock/list",
|
||||
method: "GET",
|
||||
params,
|
||||
});
|
@ -1,166 +1,170 @@
|
||||
<template>
|
||||
<div class="editor">
|
||||
<quill-editor
|
||||
v-model:content="content"
|
||||
contentType="html"
|
||||
@textChange="(e) => $emit('update:modelValue', content)"
|
||||
:options="options"
|
||||
:style="styles"
|
||||
<div
|
||||
:class="{
|
||||
disabled: readOnly,
|
||||
}"
|
||||
:style="`border: 1px solid #ccc; width: ${width}px`"
|
||||
>
|
||||
<Toolbar
|
||||
:defaultConfig="toolbarConfig"
|
||||
:editor="editorRef"
|
||||
:mode="mode"
|
||||
style="border-bottom: 1px solid #ccc"
|
||||
/>
|
||||
<Editor
|
||||
v-model="valueHtml"
|
||||
:defaultConfig="editorConfig"
|
||||
:mode="mode"
|
||||
:style="`min-height: ${minHeight}px; height: ${height}px;
|
||||
overflow-y: hidden`"
|
||||
@onBlur="emitBlur"
|
||||
@onChange="handleChange"
|
||||
@onCreated="handleCreated"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { QuillEditor } from "@vueup/vue-quill";
|
||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||
<script>
|
||||
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { onBeforeUnmount, ref, shallowRef, toRefs, watch } from "vue";
|
||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
|
||||
|
||||
const props = defineProps({
|
||||
/* 编辑器的内容 */
|
||||
modelValue: {
|
||||
type: String,
|
||||
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
||||
export default {
|
||||
components: { Editor, Toolbar },
|
||||
props: {
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "请输入内容",
|
||||
},
|
||||
minHeight: {
|
||||
type: [String, Number],
|
||||
default: 300,
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 300,
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 820,
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: "default", // or 'simple'
|
||||
},
|
||||
},
|
||||
/* 高度 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 最小高度 */
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 只读 */
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
setup(props, context) {
|
||||
// 编辑器实例,必须用 shallowRef
|
||||
const editorRef = shallowRef();
|
||||
|
||||
const options = ref({
|
||||
theme: "snow",
|
||||
bounds: document.body,
|
||||
debug: "warn",
|
||||
modules: {
|
||||
// 工具栏配置
|
||||
toolbar: [
|
||||
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
||||
["blockquote", "code-block"], // 引用 代码块
|
||||
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
||||
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
||||
[{ align: [] }], // 对齐方式
|
||||
["clean"], // 清除文本格式
|
||||
["link", "image", "video"], // 链接、图片、视频
|
||||
],
|
||||
},
|
||||
placeholder: "请输入内容",
|
||||
readOnly: props.readOnly,
|
||||
theme: "snow",
|
||||
});
|
||||
// 内容 HTML
|
||||
const valueHtml = ref("");
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
valueHtml.value = val ?? "";
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
const { height } = toRefs(props);
|
||||
|
||||
const styles = computed(() => {
|
||||
let style = {};
|
||||
if (props.minHeight) {
|
||||
style.minHeight = `${props.minHeight}px`;
|
||||
}
|
||||
if (props.height) {
|
||||
style.height = `${props.height}px`;
|
||||
}
|
||||
return style;
|
||||
});
|
||||
const toolbarConfig = {
|
||||
excludeKeys: [],
|
||||
};
|
||||
const editorConfig = {
|
||||
placeholder: props.placeholder,
|
||||
readOnly: props.readOnly,
|
||||
MENU_CONF: {
|
||||
uploadImage: {
|
||||
server: `${baseUrl}/file/upload`,
|
||||
// 自定义增加 http header
|
||||
fieldName: "file",
|
||||
headers: {
|
||||
Authorization: `Bearer ${getToken()}`,
|
||||
},
|
||||
customInsert(res, insertFn) {
|
||||
// res 即服务端的返回结果
|
||||
// console.log(res);
|
||||
// 从 res 中找到 url alt href ,然后插图图片
|
||||
insertFn(`${baseUrl}${res.url}`, null, null);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const content = ref("");
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(v) => {
|
||||
if (v !== content.value) {
|
||||
content.value = v === undefined ? "<p></p>" : v;
|
||||
}
|
||||
const isEmpty = () => {
|
||||
return editorRef.value.isEmpty();
|
||||
};
|
||||
|
||||
// 组件销毁时,也及时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value;
|
||||
if (editor == null) return;
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
const handleCreated = (editor) => {
|
||||
editorRef.value = editor; // 记录 editor 实例,重要!
|
||||
};
|
||||
const handleChange = (editor) => {
|
||||
if (editor.isEmpty()) {
|
||||
context.emit("update:modelValue", "");
|
||||
} else {
|
||||
context.emit("update:modelValue", editor.getHtml());
|
||||
}
|
||||
};
|
||||
context.expose({ isEmpty });
|
||||
|
||||
const emitBlur = (editor) => {
|
||||
// context.emit("blur", editorRef.value);
|
||||
if (editor.isEmpty()) {
|
||||
context.emit("blur", "");
|
||||
} else {
|
||||
context.emit("blur", editor.getHtml());
|
||||
}
|
||||
// editorRef.value.emit("blur");
|
||||
};
|
||||
|
||||
return {
|
||||
editorRef,
|
||||
valueHtml,
|
||||
mode: "default", // 或 'simple'
|
||||
toolbarConfig,
|
||||
editorConfig,
|
||||
height,
|
||||
handleCreated,
|
||||
handleChange,
|
||||
// isEmpty,
|
||||
emitBlur,
|
||||
};
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.disabled {
|
||||
background-color: #f5f7fa;
|
||||
cursor: not-allowed;
|
||||
|
||||
<style>
|
||||
.editor,
|
||||
.ql-toolbar {
|
||||
white-space: pre-wrap !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
.quill-img {
|
||||
display: none;
|
||||
}
|
||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
||||
content: "请输入链接地址:";
|
||||
}
|
||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||
border-right: 0px;
|
||||
content: "保存";
|
||||
padding-right: 0px;
|
||||
}
|
||||
:deep(.w-e-text-container) {
|
||||
background-color: inherit;
|
||||
// color: green;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
||||
content: "请输入视频地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||
content: "14px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
||||
content: "10px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
||||
content: "18px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
||||
content: "32px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||
content: "文本";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||
content: "标题1";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||
content: "标题2";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||
content: "标题3";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||
content: "标题4";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||
content: "标题5";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||
content: "标题6";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: "标准字体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
||||
content: "衬线字体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
||||
content: "等宽字体";
|
||||
:deep(.w-e-toolbar) {
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
184
src/components/Editor/indexco.vue
Normal file
184
src/components/Editor/indexco.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<div class="editor">
|
||||
<quill-editor
|
||||
v-model:content="content"
|
||||
contentType="html"
|
||||
@textChange="(e) => $emit('update:modelValue', content)"
|
||||
:options="options"
|
||||
:style="styles"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { QuillEditor } from "@vueup/vue-quill";
|
||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||
import ImageUploader from "quill-image-uploader";
|
||||
|
||||
import "quill-image-uploader/dist/quill.imageUploader.min.css";
|
||||
import request from "@/utils/request";
|
||||
|
||||
// Quill.register("modules/imageUploader", ImageUploader);
|
||||
const props = defineProps({
|
||||
/* 编辑器的内容 */
|
||||
modelValue: {
|
||||
type: String,
|
||||
},
|
||||
/* 高度 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 最小高度 */
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 只读 */
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const options = ref({
|
||||
theme: "snow",
|
||||
bounds: document.body,
|
||||
debug: "warn",
|
||||
modules: {
|
||||
// 工具栏配置
|
||||
toolbar: [
|
||||
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
||||
["blockquote", "code-block"], // 引用 代码块
|
||||
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
||||
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
||||
[{ align: [] }], // 对齐方式
|
||||
["clean"], // 清除文本格式
|
||||
["link", "image", "video"], // 链接、图片、视频
|
||||
],
|
||||
},
|
||||
placeholder: "请输入内容",
|
||||
readOnly: props.readOnly,
|
||||
});
|
||||
|
||||
const styles = computed(() => {
|
||||
let style = {};
|
||||
if (props.minHeight) {
|
||||
style.minHeight = `${props.minHeight}px`;
|
||||
}
|
||||
if (props.height) {
|
||||
style.height = `${props.height}px`;
|
||||
}
|
||||
return style;
|
||||
});
|
||||
|
||||
const content = ref("");
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(v) => {
|
||||
if (v !== content.value) {
|
||||
content.value = v === undefined ? "<p></p>" : v;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.editor,
|
||||
.ql-toolbar {
|
||||
white-space: pre-wrap !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.quill-img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
||||
content: "请输入链接地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||
border-right: 0px;
|
||||
content: "保存";
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
||||
content: "请输入视频地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||
content: "14px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
||||
content: "10px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
||||
content: "18px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
||||
content: "32px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||
content: "文本";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||
content: "标题1";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||
content: "标题2";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||
content: "标题3";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||
content: "标题4";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||
content: "标题5";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||
content: "标题6";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: "标准字体";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
||||
content: "衬线字体";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
||||
content: "等宽字体";
|
||||
}
|
||||
</style>
|
@ -4,11 +4,14 @@
|
||||
fit="cover"
|
||||
:style="`width:${realWidth};height:${realHeight};`"
|
||||
:preview-src-list="realSrcList"
|
||||
preview-teleported
|
||||
append-to-body="true"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<el-icon><picture-filled /></el-icon>
|
||||
<el-icon>
|
||||
<picture-filled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
@ -72,13 +75,16 @@ const realHeight = computed(() =>
|
||||
border-radius: 5px;
|
||||
background-color: #ebeef5;
|
||||
box-shadow: 0 0 5px 1px #ccc;
|
||||
|
||||
:deep(.el-image__inner) {
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.image-slot) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -153,7 +153,7 @@ function handleExceed() {
|
||||
// 上传成功回调
|
||||
function handleUploadSuccess(res, file) {
|
||||
if (res.code === 200) {
|
||||
uploadList.value.push({ name: res.fileName, url: res.fileName });
|
||||
uploadList.value.push({ name: res.fileName, url: res.url });
|
||||
uploadedSuccessfully();
|
||||
} else {
|
||||
number.value--;
|
||||
|
@ -60,7 +60,7 @@ defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const title = ref("若依管理系统");
|
||||
const title = ref("口袋九章");
|
||||
const settingsStore = useSettingsStore();
|
||||
const sideTheme = computed(() => settingsStore.sideTheme);
|
||||
</script>
|
||||
|
@ -9,6 +9,7 @@ import hljsVuePlugin from "@highlightjs/vue-plugin";
|
||||
import ElementPlus from "element-plus";
|
||||
import locale from "element-plus/lib/locale/lang/zh-cn"; // 中文语言
|
||||
import "@/assets/styles/index.scss"; // global css
|
||||
import "ant-design-vue/dist/reset.css";
|
||||
import App from "./App";
|
||||
import store from "./store";
|
||||
import router from "./router";
|
||||
|
@ -92,7 +92,6 @@ const useUserStore = defineStore("user", {
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
|
22
src/utils/dict.js
Normal file
22
src/utils/dict.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { getDicts } from "@/api/system/dict/data";
|
||||
|
||||
/**
|
||||
* 获取字典数据
|
||||
*/
|
||||
export function useDict(...args) {
|
||||
const res = ref({});
|
||||
return (() => {
|
||||
args.forEach((d, index) => {
|
||||
res.value[d] = [];
|
||||
getDicts(d).then((resp) => {
|
||||
res.value[d] = resp.data.map((p) => ({
|
||||
label: p.dictLabel,
|
||||
value: p.dictValue,
|
||||
elTagType: p.listClass,
|
||||
elTagClass: p.cssClass,
|
||||
}));
|
||||
});
|
||||
});
|
||||
return toRefs(res.value);
|
||||
})();
|
||||
}
|
533
src/views/employee/employee/index.vue
Normal file
533
src/views/employee/employee/index.vue
Normal file
@ -0,0 +1,533 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryRef"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<!-- <el-form-item label="用户ID" prop="userId">
|
||||
<el-input
|
||||
v-model="queryParams.userId"
|
||||
placeholder="请输入用户ID"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>-->
|
||||
<el-form-item label="用户名称" prop="nickname">
|
||||
<el-input
|
||||
v-model="queryParams.nickname"
|
||||
placeholder="请输入用户名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input
|
||||
v-model="queryParams.phone"
|
||||
placeholder="请输入手机号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['employee:employee:add']"
|
||||
>新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleImport"
|
||||
>导入员工
|
||||
</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="Edit"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
v-hasPermi="['employee:employee:edit']"
|
||||
>修改
|
||||
</el-button>
|
||||
</el-col>-->
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['employee:employee:remove']"
|
||||
>删除
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
@queryTable="getList"
|
||||
></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
@row-click="handleCancelEditPoint"
|
||||
v-loading="loading"
|
||||
:data="employeeList"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="用户ID" align="center" prop="userId"/>-->
|
||||
<el-table-column label="用户名称" align="center" prop="nickname" />
|
||||
<el-table-column label="手机号码" align="center" prop="phone" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
@click="handleUpdateStatus(row)"
|
||||
inactive-value="0"
|
||||
active-value="1"
|
||||
:model-value="row.status"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总积分" align="center" prop="point" width="240">
|
||||
<template #default="{ row }">
|
||||
<el-row
|
||||
justify="center"
|
||||
v-if="pointEditing && form.userId === row.userId"
|
||||
align="middle"
|
||||
>
|
||||
<el-col :span="12">
|
||||
<el-input-number
|
||||
style="width: 100%"
|
||||
@click.stop
|
||||
size="small"
|
||||
v-model="form.point"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-button
|
||||
link
|
||||
@click.stop="submitPoint"
|
||||
icon="Check"
|
||||
type="success"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-else>
|
||||
<el-col :span="12">
|
||||
<div style="text-align: center">{{ row.point }}</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-button
|
||||
link
|
||||
icon="Edit"
|
||||
@click.stop="handleUpdatePoint($event, row)"
|
||||
type="primary"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['employee:employee:edit']">修改
|
||||
</el-button>-->
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['employee:employee:remove']"
|
||||
>删除
|
||||
</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"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改员工对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form
|
||||
ref="employeeRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="用户名称" prop="nickname">
|
||||
<el-input v-model="form.nickname" placeholder="请输入用户名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phone">
|
||||
<el-input v-model="form.phone" placeholder="请输入手机号码" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 员工导入对话框 -->
|
||||
<el-dialog
|
||||
draggable
|
||||
v-model="upload.open"
|
||||
:title="upload.title"
|
||||
append-to-body
|
||||
width="400px"
|
||||
>
|
||||
<div v-show="upload.isUploading" class="upload-progress">
|
||||
<el-progress type="circle" :percentage="50" :show-text="false" />
|
||||
<p>正在导入员工数据,请耐心等待......</p>
|
||||
</div>
|
||||
<el-upload
|
||||
v-show="!upload.isUploading"
|
||||
ref="uploadRef"
|
||||
:action="upload.url"
|
||||
:auto-upload="false"
|
||||
:disabled="upload.isUploading"
|
||||
:headers="upload.headers"
|
||||
:limit="1"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess"
|
||||
accept=".xlsx, .xls"
|
||||
drag
|
||||
>
|
||||
<el-icon class="el-icon--upload">
|
||||
<upload-filled />
|
||||
</el-icon>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<ol style="text-align: start; margin-left: 20px">
|
||||
<!-- <li>(*)为必填项</li>-->
|
||||
<!-- <li>部门,角色,岗位请填数字编号</li>-->
|
||||
<!-- <li>角色,岗位若存在多个,请以英文逗号隔开</li>-->
|
||||
<!-- <li>禁止任何的换行或空格</li>-->
|
||||
<!-- <li style="color: #f00; font-size: 13px">-->
|
||||
<!-- 请手动更改单元格格式为文本格式-->
|
||||
<!-- </li>-->
|
||||
<li>
|
||||
<span>仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
type="primary"
|
||||
@click="importTemplate"
|
||||
>下载模板
|
||||
</el-link>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Employee">
|
||||
import {
|
||||
listEmployee,
|
||||
getEmployee,
|
||||
delEmployee,
|
||||
addEmployee,
|
||||
updateEmployee,
|
||||
downloadEmployeeTemplate,
|
||||
updateEmployeePoint,
|
||||
updateEmployeeStatus,
|
||||
} from "@/api/employee/employee";
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { saveAs } from "file-saver";
|
||||
import modal from "@/plugins/modal";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const employeeList = ref([]);
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const title = ref("");
|
||||
const pointEditing = ref(false);
|
||||
const data = reactive({
|
||||
form: {},
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userId: null,
|
||||
nickname: null,
|
||||
point: null,
|
||||
},
|
||||
rules: {
|
||||
userId: [{ required: true, message: "用户ID不能为空", trigger: "blur" }],
|
||||
nickname: [
|
||||
{ required: true, message: "用户名称不能为空", trigger: "blur" },
|
||||
],
|
||||
point: [{ required: true, message: "总积分不能为空", trigger: "blur" }],
|
||||
},
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
/*** 用户导入参数 */
|
||||
const upload = reactive({
|
||||
// 是否显示弹出层(用户导入)
|
||||
open: false,
|
||||
// 弹出层标题(用户导入)
|
||||
title: "",
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
// 是否更新已经存在的用户数据
|
||||
updateSupport: 0,
|
||||
// 设置上传的请求头部
|
||||
headers: { Authorization: "Bearer " + getToken() },
|
||||
// 上传的地址
|
||||
url: import.meta.env.VITE_APP_BASE_API + "/employee/employee/importData",
|
||||
});
|
||||
|
||||
/** 查询员工列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
listEmployee(queryParams.value).then((response) => {
|
||||
employeeList.value = response.rows;
|
||||
total.value = response.total;
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
function cancel() {
|
||||
open.value = false;
|
||||
reset();
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
function reset() {
|
||||
form.value = {
|
||||
userId: null,
|
||||
nickname: null,
|
||||
point: null,
|
||||
phone: null,
|
||||
status: "0",
|
||||
};
|
||||
proxy.resetForm("employeeRef");
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
proxy.resetForm("queryRef");
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
// 多选框选中数据
|
||||
function handleSelectionChange(selection) {
|
||||
ids.value = selection.map((item) => item.userId);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd() {
|
||||
reset();
|
||||
open.value = true;
|
||||
title.value = "添加员工";
|
||||
}
|
||||
|
||||
/** 导入按钮操作 */
|
||||
function handleImport() {
|
||||
upload.title = "员工导入";
|
||||
upload.open = true;
|
||||
}
|
||||
|
||||
const importTemplate = async () => {
|
||||
const blob = await downloadEmployeeTemplate();
|
||||
saveAs(blob, `employee_${new Date().getTime()}.xlsx`);
|
||||
};
|
||||
|
||||
/**文件上传中处理 */
|
||||
const handleFileUploadProgress = (event, file, fileList) => {
|
||||
upload.isUploading = true;
|
||||
};
|
||||
/** 文件上传成功处理 */
|
||||
const handleFileSuccess = (response, file, fileList) => {
|
||||
upload.open = false;
|
||||
upload.isUploading = false;
|
||||
proxy.$refs["uploadRef"].handleRemove(file);
|
||||
proxy.$alert(
|
||||
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
|
||||
response.msg +
|
||||
"</div>",
|
||||
"导入结果",
|
||||
{ dangerouslyUseHTMLString: true }
|
||||
);
|
||||
getList();
|
||||
};
|
||||
|
||||
/** 提交上传文件 */
|
||||
function submitFileForm() {
|
||||
proxy.$refs["uploadRef"].submit();
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
function handleUpdate(row) {
|
||||
reset();
|
||||
const _userId = row.userId || ids.value;
|
||||
getEmployee(_userId).then((response) => {
|
||||
form.value = response.data;
|
||||
open.value = true;
|
||||
title.value = "修改员工";
|
||||
});
|
||||
}
|
||||
|
||||
const handleUpdatePoint = (event, row) => {
|
||||
event.stopPropagation();
|
||||
reset();
|
||||
form.value.userId = row.userId;
|
||||
form.value.point = row.point;
|
||||
pointEditing.value = true;
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
proxy.$refs["employeeRef"].validate((valid) => {
|
||||
if (valid) {
|
||||
if (form.value.userId != null) {
|
||||
updateEmployee(form.value).then((response) => {
|
||||
proxy.$modal.msgSuccess("修改成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
} else {
|
||||
addEmployee(form.value).then((response) => {
|
||||
proxy.$modal.msgSuccess("新增成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const _userIds = row.userId || ids.value;
|
||||
proxy.$modal
|
||||
.confirm('是否确认删除员工编号为"' + _userIds + '"的数据项?')
|
||||
.then(function () {
|
||||
return delEmployee(_userIds);
|
||||
})
|
||||
.then(() => {
|
||||
getList();
|
||||
proxy.$modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
const handleUpdateStatus = (row) => {
|
||||
modal.confirm("是否确定要更改状态?").then(async () => {
|
||||
let status;
|
||||
if (row.status === "1") {
|
||||
status = "0";
|
||||
} else {
|
||||
status = "1";
|
||||
}
|
||||
await updateEmployeeStatus({
|
||||
userId: row.userId,
|
||||
status,
|
||||
});
|
||||
getList();
|
||||
modal.msgSuccess("修改状态成功");
|
||||
});
|
||||
};
|
||||
|
||||
const submitPoint = () => {
|
||||
updateEmployeePoint({
|
||||
userId: form.value.userId,
|
||||
point: form.value.point,
|
||||
})
|
||||
.then(() => {
|
||||
modal.msgSuccess("修改积分成功");
|
||||
})
|
||||
.finally(() => {
|
||||
pointEditing.value = false;
|
||||
getList();
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancelEditPoint = () => {
|
||||
reset();
|
||||
pointEditing.value = false;
|
||||
};
|
||||
getList();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload-progress {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
aspect-ratio: 360/185;
|
||||
|
||||
& > p {
|
||||
text-align: center;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
:deep(.el-progress-circle svg) {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
259
src/views/finance/detail/index.vue
Normal file
259
src/views/finance/detail/index.vue
Normal file
@ -0,0 +1,259 @@
|
||||
<script setup>
|
||||
import {
|
||||
addFinanceDetail,
|
||||
deleteFinanceDetail,
|
||||
financeDetailList,
|
||||
getFinanceDetail,
|
||||
updateFinanceDetail,
|
||||
} from "@/api/finance/detail";
|
||||
import {useDict} from "@/utils/dict";
|
||||
import DictTag from "@/components/DictTag/index.vue";
|
||||
import {dayjs} from "element-plus";
|
||||
import modal from "@/plugins/modal";
|
||||
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
const total = ref(0);
|
||||
const showSearch = ref(true);
|
||||
const queryRef = ref();
|
||||
const title = ref("");
|
||||
const formRef = ref();
|
||||
const ids = ref([]);
|
||||
const financeList = ref([]);
|
||||
const data = reactive({
|
||||
form: {},
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
rules: {
|
||||
event: [{required: true, message: "事项不能为空", trigger: "blur"}],
|
||||
type: [{required: true, message: "类型不能为空", trigger: "change"}],
|
||||
date: [{required: true, message: "日期不能为空", trigger: "change"}],
|
||||
oppositeCompany: [{required: true, message: "对方账户不能为空", trigger: "blur"}],
|
||||
amount: [{required: true, message: "金额不能为空", trigger: "blur"}],
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
const {form, queryParams, rules} = toRefs(data);
|
||||
const {finance_type} = useDict("finance_type");
|
||||
const getList = () => {
|
||||
loading.value = true;
|
||||
financeDetailList().then((resp) => {
|
||||
financeList.value = resp.rows;
|
||||
total.value = resp.total;
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
queryRef.value?.resetFields();
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
function reset() {
|
||||
form.value = {
|
||||
financeId: null,
|
||||
date: null,
|
||||
type: null,
|
||||
event: null,
|
||||
amount: null,
|
||||
oppositeCompany: null,
|
||||
};
|
||||
formRef.value?.resetFields();
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd(row) {
|
||||
reset();
|
||||
title.value = "添加事项";
|
||||
open.value = true;
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const _financeIds = row.financeId || ids.value;
|
||||
modal
|
||||
.confirm('是否确认删除编号为"' + _financeIds + '"的数据项?')
|
||||
.then(function () {
|
||||
return deleteFinanceDetail(_financeIds);
|
||||
})
|
||||
.then(() => {
|
||||
getList();
|
||||
modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {
|
||||
});
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
function handleUpdate(row) {
|
||||
reset();
|
||||
const _financeId = row.financeId || ids.value;
|
||||
getFinanceDetail(_financeId).then((response) => {
|
||||
form.value = response.data;
|
||||
open.value = true;
|
||||
title.value = "修改事项";
|
||||
});
|
||||
}
|
||||
|
||||
const submitForm = () => {
|
||||
formRef.value?.validate((valid) => {
|
||||
if (valid) {
|
||||
if (form.value.financeId != null) {
|
||||
updateFinanceDetail(form.value).then((response) => {
|
||||
modal.msgSuccess("修改成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
} else {
|
||||
addFinanceDetail(form.value).then((response) => {
|
||||
modal.msgSuccess("新增成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
open.value = false;
|
||||
reset();
|
||||
};
|
||||
|
||||
getList();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryRef"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="事项" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入事项"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery"
|
||||
>搜索
|
||||
</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd"
|
||||
>新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
@queryTable="getList"
|
||||
></right-toolbar>
|
||||
</el-row>
|
||||
<el-table :data="financeList">
|
||||
<el-table-column align="center" label="事项" prop="event"/>
|
||||
<el-table-column align="center" label="类别">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :options="finance_type" :value="row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="日期">
|
||||
<template #default="{ row }">
|
||||
{{ dayjs(row.date).format("YYYY-MM-DD") }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="对方账户" prop="oppositeCompany"/>
|
||||
<el-table-column align="center" label="金额" prop="amount"/>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
icon="edit"
|
||||
@click="handleUpdate(row)"
|
||||
link
|
||||
size="small"
|
||||
type="primary"
|
||||
>修改
|
||||
</el-button
|
||||
>
|
||||
<el-button
|
||||
icon="delete"
|
||||
@click="handleDelete(row)"
|
||||
link
|
||||
size="small"
|
||||
type="primary"
|
||||
>删除
|
||||
</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"
|
||||
/>
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="事项" prop="event">
|
||||
<el-input v-model="form.event" placeholder="请输入事项"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="form.type">
|
||||
<el-option
|
||||
v-for="option in finance_type"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="日期" prop="date">
|
||||
<el-date-picker
|
||||
v-model="form.date"
|
||||
type="date"
|
||||
placeholder="请选择日期"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="对方账户" prop="oppositeCompany">
|
||||
<el-input
|
||||
v-model="form.oppositeCompany"
|
||||
placeholder="请输入对方账户"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="金额" prop="amount">
|
||||
<el-input-number v-model="form.amount" placeholder="请输入金额"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
1967
src/views/index.vue
1967
src/views/index.vue
File diff suppressed because it is too large
Load Diff
@ -3,87 +3,87 @@
|
||||
<div class="login-card">
|
||||
<div class="login-banner">
|
||||
<!-- 主标题 -->
|
||||
<!-- <h2 class="title">若依后台管理系统</h2>-->
|
||||
<!-- <h2 class="title">若依后台管理系统</h2>-->
|
||||
<!-- 副标题 -->
|
||||
<!-- <p class="sub-title">前后端分离的后台管理系统架构</p>-->
|
||||
<el-image class="banner-image" :src="loginLeftBanner"/>
|
||||
<!-- <p class="sub-title">前后端分离的后台管理系统架构</p>-->
|
||||
<el-image class="banner-image" :src="loginLeftBanner" />
|
||||
</div>
|
||||
<el-form
|
||||
ref="loginRef"
|
||||
:model="loginForm"
|
||||
:rules="loginRules"
|
||||
class="login-form"
|
||||
ref="loginRef"
|
||||
:model="loginForm"
|
||||
:rules="loginRules"
|
||||
class="login-form"
|
||||
>
|
||||
<h3 class="title">管理系统</h3>
|
||||
<el-form-item prop="username">
|
||||
<el-input
|
||||
v-model="loginForm.username"
|
||||
auto-complete="off"
|
||||
placeholder="账号"
|
||||
size="large"
|
||||
type="text"
|
||||
v-model="loginForm.username"
|
||||
auto-complete="off"
|
||||
placeholder="账号"
|
||||
size="large"
|
||||
type="text"
|
||||
>
|
||||
<template #prefix>
|
||||
<svg-icon class="el-input__icon input-icon" icon-class="user"/>
|
||||
<svg-icon class="el-input__icon input-icon" icon-class="user" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
v-model="loginForm.password"
|
||||
auto-complete="off"
|
||||
placeholder="密码"
|
||||
size="large"
|
||||
type="password"
|
||||
@keyup.enter="handleLogin"
|
||||
v-model="loginForm.password"
|
||||
auto-complete="off"
|
||||
placeholder="密码"
|
||||
size="large"
|
||||
type="password"
|
||||
@keyup.enter="handleLogin"
|
||||
>
|
||||
<template #prefix>
|
||||
<svg-icon
|
||||
class="el-input__icon input-icon"
|
||||
icon-class="password"
|
||||
class="el-input__icon input-icon"
|
||||
icon-class="password"
|
||||
/>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="captchaEnabled" prop="code">
|
||||
<el-input
|
||||
v-model="loginForm.code"
|
||||
auto-complete="off"
|
||||
placeholder="验证码"
|
||||
size="large"
|
||||
style="width: 63%"
|
||||
@keyup.enter="handleLogin"
|
||||
v-model="loginForm.code"
|
||||
auto-complete="off"
|
||||
placeholder="验证码"
|
||||
size="large"
|
||||
style="width: 63%"
|
||||
@keyup.enter="handleLogin"
|
||||
>
|
||||
<template #prefix>
|
||||
<svg-icon
|
||||
class="el-input__icon input-icon"
|
||||
icon-class="validCode"
|
||||
class="el-input__icon input-icon"
|
||||
icon-class="validCode"
|
||||
/>
|
||||
</template>
|
||||
</el-input>
|
||||
<div class="login-code">
|
||||
<img :src="codeUrl" class="login-code-img" @click="getCode"/>
|
||||
<img :src="codeUrl" class="login-code-img" @click="getCode" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-checkbox
|
||||
v-model="loginForm.rememberMe"
|
||||
style="margin: 0px 0px 25px 0px"
|
||||
>记住密码
|
||||
v-model="loginForm.rememberMe"
|
||||
style="margin: 0px 0px 25px 0px"
|
||||
>记住密码
|
||||
</el-checkbox>
|
||||
<el-form-item style="width: 100%">
|
||||
<el-button
|
||||
:loading="loading"
|
||||
size="large"
|
||||
style="width: 100%"
|
||||
type="primary"
|
||||
@click.prevent="handleLogin"
|
||||
:loading="loading"
|
||||
size="large"
|
||||
style="width: 100%"
|
||||
type="primary"
|
||||
@click.prevent="handleLogin"
|
||||
>
|
||||
<span v-if="!loading">登 录</span>
|
||||
<span v-else>登 录 中...</span>
|
||||
</el-button>
|
||||
<div v-if="register" style="float: right">
|
||||
<router-link :to="'/register'" class="link-type"
|
||||
>立即注册
|
||||
>立即注册
|
||||
</router-link>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@ -99,29 +99,29 @@
|
||||
|
||||
<script setup>
|
||||
import loginLeftBanner from "@/assets/images/login-left-banner.png";
|
||||
import {getCodeImg} from "@/api/login";
|
||||
import { getCodeImg } from "@/api/login";
|
||||
import Cookies from "js-cookie";
|
||||
import {decrypt, encrypt} from "@/utils/jsencrypt";
|
||||
import { decrypt, encrypt } from "@/utils/jsencrypt";
|
||||
import useUserStore from "@/store/modules/user";
|
||||
import {getCurrentInstance, ref} from "vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import { getCurrentInstance, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
const {proxy} = getCurrentInstance();
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const loginForm = ref({
|
||||
username: "admin",
|
||||
password: "admin123",
|
||||
username: "",
|
||||
password: "",
|
||||
rememberMe: false,
|
||||
code: "",
|
||||
uuid: "",
|
||||
});
|
||||
|
||||
const loginRules = {
|
||||
username: [{required: true, trigger: "blur", message: "请输入您的账号"}],
|
||||
password: [{required: true, trigger: "blur", message: "请输入您的密码"}],
|
||||
code: [{required: true, trigger: "change", message: "请输入验证码"}],
|
||||
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
|
||||
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
|
||||
code: [{ required: true, trigger: "change", message: "请输入验证码" }],
|
||||
};
|
||||
const codeUrl = ref("");
|
||||
const loading = ref(false);
|
||||
@ -137,11 +137,11 @@ function handleLogin() {
|
||||
loading.value = true;
|
||||
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
||||
if (loginForm.value.rememberMe) {
|
||||
Cookies.set("username", loginForm.value.username, {expires: 30});
|
||||
Cookies.set("username", loginForm.value.username, { expires: 30 });
|
||||
Cookies.set("password", encrypt(loginForm.value.password), {
|
||||
expires: 30,
|
||||
});
|
||||
Cookies.set("rememberMe", loginForm.value.rememberMe, {expires: 30});
|
||||
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
|
||||
} else {
|
||||
// 否则移除
|
||||
Cookies.remove("username");
|
||||
@ -150,17 +150,17 @@ function handleLogin() {
|
||||
}
|
||||
// 调用action的登录方法
|
||||
userStore
|
||||
.login(loginForm.value)
|
||||
.then(() => {
|
||||
router.push({path: redirect.value || "/"});
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
// 重新获取验证码
|
||||
if (captchaEnabled.value) {
|
||||
getCode();
|
||||
}
|
||||
});
|
||||
.login(loginForm.value)
|
||||
.then(() => {
|
||||
router.push({ path: redirect.value || "/" });
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
// 重新获取验证码
|
||||
if (captchaEnabled.value) {
|
||||
getCode();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -168,7 +168,7 @@ function handleLogin() {
|
||||
function getCode() {
|
||||
getCodeImg().then((res) => {
|
||||
captchaEnabled.value =
|
||||
res.captchaEnabled === undefined ? true : res.captchaEnabled;
|
||||
res.captchaEnabled === undefined ? true : res.captchaEnabled;
|
||||
register.value = res.register === undefined ? true : res.register;
|
||||
if (captchaEnabled.value) {
|
||||
codeUrl.value = "data:image/gif;base64," + res.img;
|
||||
@ -184,13 +184,12 @@ function getCookie() {
|
||||
loginForm.value = {
|
||||
username: username === undefined ? loginForm.value.username : username,
|
||||
password:
|
||||
password === undefined ? loginForm.value.password : decrypt(password),
|
||||
password === undefined ? loginForm.value.password : decrypt(password),
|
||||
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
getCode()
|
||||
getCode();
|
||||
getCookie();
|
||||
</script>
|
||||
|
||||
@ -216,7 +215,7 @@ getCookie();
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1),
|
||||
0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
|
||||
.login-banner {
|
||||
padding: 0 20px 0;
|
||||
|
558
src/views/product/product/index.vue
Normal file
558
src/views/product/product/index.vue
Normal file
@ -0,0 +1,558 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryRef"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['product:product:add']"
|
||||
>新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="Edit"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
v-hasPermi="['product:product:edit']"
|
||||
>修改
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['product:product:remove']"
|
||||
>删除
|
||||
</el-button>
|
||||
</el-col>-->
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
@queryTable="getList"
|
||||
></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- <el-table row-key="rowKey"
|
||||
ref="tableRef"
|
||||
lazy
|
||||
:load="loadChildren"
|
||||
v-loading="loading"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
:data="productList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center"/>
|
||||
<el-table-column label="名称" prop="name">
|
||||
<!– <template #default="{row}">
|
||||
<el-button link @click="loadChildren(row)" icon="ArrowRight"/>
|
||||
{{ row.name }}
|
||||
</template>–>
|
||||
</el-table-column>
|
||||
<el-table-column label="图片" align="center" prop="pic" width="100">
|
||||
<template #default="{row}">
|
||||
<image-preview v-if="row.specId" :src="row.pic" :width="50" :height="50"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark"/>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="{row}">
|
||||
<el-button v-if="!row.specId" link type="primary" icon="Plus" @click="handleAdd(row)"
|
||||
v-hasPermi="['product:product:add']">新增{{
|
||||
row.modelId ? "规格" : row.productId ? "型号" : "规格"
|
||||
}}
|
||||
</el-button>
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(row)"
|
||||
v-hasPermi="['product:product:edit']">修改
|
||||
</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(row)"
|
||||
v-hasPermi="['product:product:remove']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>-->
|
||||
<a-table
|
||||
:columns="[
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '图片',
|
||||
dataIndex: 'pic',
|
||||
key: 'pic',
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'remark',
|
||||
key: 'remark',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
width: '260px',
|
||||
},
|
||||
]"
|
||||
@expand="handleExpandTable"
|
||||
:data-source="productList"
|
||||
>
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="column.dataIndex === 'pic'">
|
||||
<image-preview
|
||||
v-if="record.specId"
|
||||
:src="record.pic"
|
||||
:width="50"
|
||||
:height="50"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'">
|
||||
<el-button
|
||||
v-if="!record.specId"
|
||||
link
|
||||
type="primary"
|
||||
icon="Plus"
|
||||
@click="handleAdd(record)"
|
||||
v-hasPermi="['product:product:add']"
|
||||
>新增{{
|
||||
record.modelId ? "规格" : record.productId ? "型号" : "规格"
|
||||
}}
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Edit"
|
||||
@click="handleUpdate(record)"
|
||||
v-hasPermi="['product:product:edit']"
|
||||
>修改
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Delete"
|
||||
@click="handleDelete(record)"
|
||||
v-hasPermi="['product:product:remove']"
|
||||
>删除
|
||||
</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改产品对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="productRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="
|
||||
(editMode === 1 && form.specId) || (editMode === 0 && form.modelId)
|
||||
"
|
||||
label="图片"
|
||||
prop="pic"
|
||||
>
|
||||
<image-upload v-model="form.pic" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
placeholder="请输入内容"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Product">
|
||||
import {
|
||||
listProduct,
|
||||
getProduct,
|
||||
delProduct,
|
||||
addProduct,
|
||||
updateProduct,
|
||||
addModel,
|
||||
modelList,
|
||||
addSpec,
|
||||
listSpec,
|
||||
updateSpec,
|
||||
updateModel,
|
||||
getModel,
|
||||
getSpec,
|
||||
deleteSpec,
|
||||
deleteModel,
|
||||
} from "@/api/product/product";
|
||||
import { handleTree } from "@/utils/ruoyi";
|
||||
import { nextTick } from "vue";
|
||||
import { Table as ATable } from "ant-design-vue";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const productList = ref([]);
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const title = ref("");
|
||||
const editMode = ref(0); // 0 新增, 1 修改
|
||||
const tableRef = ref();
|
||||
const parentRow = ref();
|
||||
const data = reactive({
|
||||
form: {},
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
productId: null,
|
||||
name: null,
|
||||
parentId: null,
|
||||
pic: null,
|
||||
createUser: null,
|
||||
createTime: null,
|
||||
updateUser: null,
|
||||
updateTime: null,
|
||||
remark: null,
|
||||
},
|
||||
rules: {
|
||||
productId: [{ required: true, message: "不能为空", trigger: "blur" }],
|
||||
name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
|
||||
parentId: [{ required: true, message: "父ID不能为空", trigger: "blur" }],
|
||||
pic: [{ required: true, message: "图片不能为空", trigger: "blur" }],
|
||||
createUser: [
|
||||
{ required: true, message: "创建者不能为空", trigger: "blur" },
|
||||
],
|
||||
createTime: [
|
||||
{ required: true, message: "创建时间不能为空", trigger: "blur" },
|
||||
],
|
||||
updateUser: [
|
||||
{ required: true, message: "更新者不能为空", trigger: "blur" },
|
||||
],
|
||||
updateTime: [
|
||||
{ required: true, message: "更新时间不能为空", trigger: "blur" },
|
||||
],
|
||||
remark: [],
|
||||
},
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
const handleExpandTable = (expanded, record) => {
|
||||
expanded && loadChildren(record);
|
||||
};
|
||||
|
||||
const loadChildren = (row) => {
|
||||
console.log(tableRef.value);
|
||||
if (row.modelId) {
|
||||
/*加载规格*/
|
||||
listSpec({ modelId: row.modelId }).then(({ rows }) => {
|
||||
row.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.specId,
|
||||
}));
|
||||
});
|
||||
} else if (row.productId) {
|
||||
/*加载型号*/
|
||||
modelList({
|
||||
productId: row.productId,
|
||||
}).then(({ rows }) => {
|
||||
row.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.modelId,
|
||||
children: [],
|
||||
}));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/** 查询产品列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
listProduct(queryParams.value).then((response) => {
|
||||
productList.value = response.rows.map((el) => ({
|
||||
...el,
|
||||
key: el.productId,
|
||||
children: [],
|
||||
}));
|
||||
total.value = response.total;
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
function cancel() {
|
||||
open.value = false;
|
||||
reset();
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
function reset() {
|
||||
form.value = {
|
||||
productId: null,
|
||||
name: null,
|
||||
parentId: null,
|
||||
pic: null,
|
||||
};
|
||||
proxy.resetForm("productRef");
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
proxy.resetForm("queryRef");
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
// 多选框选中数据
|
||||
function handleSelectionChange(selection) {
|
||||
ids.value = selection.map((item) => item.productId);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
}
|
||||
|
||||
function findInTreeByKey(tree, key) {
|
||||
for (const node of tree) {
|
||||
if (node.key === key) {
|
||||
return node;
|
||||
}
|
||||
if (node.children) {
|
||||
const result = findInTreeByKey(node.children, key);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd(row) {
|
||||
editMode.value = 0;
|
||||
reset();
|
||||
if (row.modelId) {
|
||||
/*添加规格*/
|
||||
title.value = "添加规格";
|
||||
form.value.modelId = row.modelId;
|
||||
form.value.productId = row.productId;
|
||||
} else if (row.productId) {
|
||||
/*添加型号*/
|
||||
title.value = "添加型号";
|
||||
form.value.productId = row.productId;
|
||||
} else {
|
||||
/*添加产品*/
|
||||
title.value = "添加产品";
|
||||
}
|
||||
open.value = true;
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
async function handleUpdate(row) {
|
||||
editMode.value = 1;
|
||||
reset();
|
||||
if (row.specId) {
|
||||
form.value = (await getSpec(row.specId)).data;
|
||||
title.value = "修改规格";
|
||||
} else if (row.modelId) {
|
||||
form.value = (await getModel(row.modelId)).data;
|
||||
title.value = "修改型号";
|
||||
} else {
|
||||
form.value = (await getProduct(row.productId)).data;
|
||||
title.value = "修改产品";
|
||||
}
|
||||
open.value = true;
|
||||
}
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
proxy.$refs["productRef"].validate((valid) => {
|
||||
if (valid) {
|
||||
if (editMode.value) {
|
||||
if (form.value.specId) {
|
||||
/*修改规格*/
|
||||
updateSpec(form.value).then(() => {
|
||||
proxy.$modal.msgSuccess("修改规格成功");
|
||||
open.value = false;
|
||||
listSpec({ modelId: form.value.modelId }).then(({ rows }) => {
|
||||
const model = findInTreeByKey(
|
||||
productList.value,
|
||||
form.value.modelId
|
||||
);
|
||||
if (model) {
|
||||
model.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.specId,
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (form.value.modelId) {
|
||||
/*修改型号*/
|
||||
updateModel(form.value).then(() => {
|
||||
proxy.$modal.msgSuccess("修改型号成功");
|
||||
open.value = false;
|
||||
modelList({ productId: form.value.productId }).then(({ rows }) => {
|
||||
const product = findInTreeByKey(
|
||||
productList.value,
|
||||
form.value.productId
|
||||
);
|
||||
if (product) {
|
||||
product.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.modelId,
|
||||
children: [],
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
updateProduct(form.value).then((response) => {
|
||||
proxy.$modal.msgSuccess("修改产品成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (form.value.modelId) {
|
||||
addSpec(form.value).then(() => {
|
||||
proxy.$modal.msgSuccess("规格新增成功");
|
||||
open.value = false;
|
||||
listSpec({ modelId: form.value.modelId }).then(({ rows }) => {
|
||||
const model = findInTreeByKey(
|
||||
productList.value,
|
||||
form.value.modelId
|
||||
);
|
||||
if (model) {
|
||||
model.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.specId,
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (form.value.productId) {
|
||||
/*新增型号*/
|
||||
addModel(form.value).then(() => {
|
||||
proxy.$modal.msgSuccess("型号新增成功");
|
||||
open.value = false;
|
||||
modelList({ productId: form.value.productId }).then(({ rows }) => {
|
||||
const product = findInTreeByKey(
|
||||
productList.value,
|
||||
form.value.productId
|
||||
);
|
||||
if (product) {
|
||||
product.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.modelId,
|
||||
children: [],
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
addProduct(form.value).then(() => {
|
||||
proxy.$modal.msgSuccess("产品新增成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const _productIds = row.specId || row.modelId || row.productId || ids.value;
|
||||
proxy.$modal
|
||||
.confirm('是否确认删除编号为"' + _productIds + '"的数据项?')
|
||||
.then(function () {
|
||||
if (row.specId) {
|
||||
return deleteSpec(_productIds);
|
||||
} else if (row.modelId) {
|
||||
return deleteModel(_productIds);
|
||||
} else {
|
||||
return delProduct(_productIds);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (row.specId) {
|
||||
listSpec({ modelId: form.value.modelId }).then(({ rows }) => {
|
||||
const model = findInTreeByKey(productList.value, form.value.modelId);
|
||||
if (model) {
|
||||
model.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.specId,
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else if (row.modelId) {
|
||||
modelList({ productId: form.value.productId }).then(({ rows }) => {
|
||||
const product = findInTreeByKey(
|
||||
productList.value,
|
||||
form.value.productId
|
||||
);
|
||||
if (product) {
|
||||
product.children = rows.map((el) => ({
|
||||
...el,
|
||||
key: el.modelId,
|
||||
children: [],
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
getList();
|
||||
}
|
||||
proxy.$modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
getList();
|
||||
</script>
|
126
src/views/product/stock/index.vue
Normal file
126
src/views/product/stock/index.vue
Normal file
@ -0,0 +1,126 @@
|
||||
<script setup>
|
||||
import { loadStockList, loadStockLogList } from "@/api/product/stock";
|
||||
import { reactive, toRefs } from "vue";
|
||||
import { dayjs } from "element-plus";
|
||||
import ImagePreview from "@/components/ImagePreview/index.vue";
|
||||
|
||||
const queryRef = ref();
|
||||
const showSearch = ref(false);
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
type: 1,
|
||||
},
|
||||
});
|
||||
const total = ref(0);
|
||||
const { queryParams } = toRefs(data);
|
||||
|
||||
const stockLogList = ref([]);
|
||||
const getStockList = () => {
|
||||
if (queryParams.value.type === 0) {
|
||||
loadStockList(queryParams.value).then((resp) => {
|
||||
total.value = resp.total;
|
||||
stockLogList.value = resp.rows;
|
||||
});
|
||||
} else {
|
||||
loadStockLogList(queryParams.value).then((resp) => {
|
||||
total.value = resp.total;
|
||||
stockLogList.value = resp.rows;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
getStockList();
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
queryRef.value?.resetFields();
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
getStockList();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryRef"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="queryParams.type">
|
||||
<el-option label="库存" :value="0" />
|
||||
<el-option label="入库" :value="1" />
|
||||
<el-option label="出库" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-radio-group @change="handleQuery" v-model="queryParams.type">
|
||||
<el-radio-button :label="0">库存</el-radio-button>
|
||||
<el-radio-button :label="1">入库</el-radio-button>
|
||||
<el-radio-button :label="2">出库</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-col>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
@queryTable="getStockList"
|
||||
></right-toolbar>
|
||||
</el-row>
|
||||
<el-table :data="stockLogList">
|
||||
<el-table-column align="center" label="产品" prop="productName" />
|
||||
<el-table-column align="center" label="型号" prop="modelName" />
|
||||
<el-table-column align="center" label="规格" prop="specName" />
|
||||
<el-table-column
|
||||
align="center"
|
||||
v-if="queryParams.type === 0"
|
||||
label="库存"
|
||||
prop="stock"
|
||||
/>
|
||||
<el-table-column align="center" v-else label="数量" prop="total" />
|
||||
<el-table-column
|
||||
v-if="queryParams.type > 0"
|
||||
align="center"
|
||||
label="图片"
|
||||
prop="date"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<image-preview :width="50" :height="50" :src="row.provePic" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="queryParams.type > 0"
|
||||
align="center"
|
||||
label="日期"
|
||||
prop="date"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row.date ? dayjs(row.date).format("YYYY-MM-DD") : "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getStockList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@ -6,7 +6,7 @@
|
||||
:rules="registerRules"
|
||||
class="register-form"
|
||||
>
|
||||
<h3 class="title">若依后台管理系统</h3>
|
||||
<h3 class="title">口袋九章</h3>
|
||||
<el-form-item prop="username">
|
||||
<el-input
|
||||
v-model="registerForm.username"
|
||||
|
@ -27,7 +27,7 @@ export default defineConfig(({ mode, command }) => {
|
||||
server: {
|
||||
port: 80,
|
||||
host: true,
|
||||
open: true,
|
||||
open: false,
|
||||
proxy: {
|
||||
// https://cn.vitejs.dev/config/#server-proxy
|
||||
"/dev-api": {
|
||||
|
Reference in New Issue
Block a user