refactor: eslint代码检查优化
Former-commit-id: 4c11b5d0cdd10f28148cf3d9b593f85e082cdc51
This commit is contained in:
@@ -18,7 +18,7 @@ export function listCategories(queryParams:object){
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function listCascadeCategories(queryParams:object) {
|
||||
export function listCascadeCategories(queryParams?:object) {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/categories/cascade',
|
||||
method: 'get',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GoodsPageResult, GoodsQueryParam } from '@/types'
|
||||
import { GoodsDetail, GoodsPageResult, GoodsQueryParam } from '@/types'
|
||||
import request from '@/utils/request'
|
||||
import { AxiosPromise } from 'axios'
|
||||
|
||||
@@ -20,7 +20,7 @@ export function listGoodsPages(queryParams: GoodsQueryParam):AxiosPromise<GoodsP
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
export function getGoodsFormDetail(id: number) {
|
||||
export function getGoodsDetail(id: string):AxiosPromise<GoodsDetail> {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/goods/' + id,
|
||||
method: 'get'
|
||||
|
||||
@@ -6,7 +6,7 @@ import request from '@/utils/request'
|
||||
* @param file
|
||||
*/
|
||||
export function uploadFile(file: File) {
|
||||
let formData = new FormData()
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return request(
|
||||
{
|
||||
|
||||
@@ -98,7 +98,7 @@ export function listRoleMenuIds(roleId: number):AxiosPromise<number[]> {
|
||||
* @param roleId
|
||||
* @param menuIds
|
||||
*/
|
||||
export function updateRoleMenu(roleId: number, menuIds: Array<Number>) {
|
||||
export function updateRoleMenu(roleId: number, menuIds: Array<number>) {
|
||||
return request({
|
||||
url: '/youlai-admin/api/v1/roles/' + roleId + '/menus',
|
||||
method: 'put',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import request from "@/utils/request";
|
||||
import { AxiosPromise } from "axios";
|
||||
import { UserFormData, UserImportFormData, UserInfo, UserPageResult, UserQueryParam } from "@/types";
|
||||
import { UserFormData, UserInfo, UserPageResult, UserQueryParam } from "@/types";
|
||||
|
||||
/**
|
||||
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
||||
@@ -113,6 +113,7 @@ export function exportUser(queryParams: UserQueryParam) {
|
||||
return request({
|
||||
url: '/youlai-admin/api/v1/users/_export',
|
||||
method: 'get',
|
||||
params:queryParams,
|
||||
responseType: "arraybuffer"
|
||||
})
|
||||
}
|
||||
@@ -123,7 +124,7 @@ export function exportUser(queryParams: UserQueryParam) {
|
||||
* @param file
|
||||
*/
|
||||
export function importUser(deptId: number, roleIds: string, file: File) {
|
||||
let formData = new FormData()
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('deptId',deptId.toString())
|
||||
formData.append('roleIds',roleIds)
|
||||
|
||||
9
src/components.d.ts
vendored
Normal file
9
src/components.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// 全局组件类型声明
|
||||
import Pagination from "@/components/Pagination/index.vue";
|
||||
|
||||
declare module "@vue/runtime-core" {
|
||||
export interface GlobalComponents {
|
||||
Pagination: typeof Pagination;
|
||||
}
|
||||
}
|
||||
export {}
|
||||
@@ -1,13 +1,7 @@
|
||||
<template>
|
||||
<div class="icon-body">
|
||||
<el-input
|
||||
v-model="iconName"
|
||||
style="position: relative;"
|
||||
clearable
|
||||
placeholder="请输入图标名称"
|
||||
@clear="filterIcons"
|
||||
@input="filterIcons"
|
||||
>
|
||||
<el-input v-model="iconName" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons"
|
||||
@input="filterIcons">
|
||||
<template #suffix><i class="el-icon-search el-input__icon" /></template>
|
||||
</el-input>
|
||||
<div class="icon-list">
|
||||
@@ -19,11 +13,11 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref} from "vue";
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue';
|
||||
|
||||
let icons = []
|
||||
const icons = [] as string[]
|
||||
const modules = import.meta.glob('../../assets/icons/svg/*.svg');
|
||||
for (const path in modules) {
|
||||
const p = path.split('assets/icons/svg/')[1].split('.svg')[0];
|
||||
@@ -42,7 +36,7 @@ function filterIcons() {
|
||||
}
|
||||
}
|
||||
|
||||
function selectedIcon(name) {
|
||||
function selectedIcon(name: string) {
|
||||
emit('selected', name)
|
||||
document.body.click()
|
||||
}
|
||||
@@ -61,9 +55,11 @@ defineExpose({
|
||||
.icon-body {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
|
||||
.icon-list {
|
||||
height: 200px;
|
||||
overflow-y: scroll;
|
||||
|
||||
div {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
@@ -72,6 +68,7 @@ defineExpose({
|
||||
width: 33%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: -0.15em;
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
<template>
|
||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
||||
<el-pagination
|
||||
:background="background"
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:layout="layout"
|
||||
:page-sizes="pageSizes"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
<div :class="{ 'hidden': hidden }" class="pagination-container">
|
||||
<el-pagination :background="background" v-model:current-page="currentPage" v-model:page-size="pageSize"
|
||||
:layout="layout" :page-sizes="pageSizes" :total="total" @size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {computed} from "vue";
|
||||
import {scrollTo} from '@/utils/scroll-to'
|
||||
<script setup lang="ts">
|
||||
import { computed, PropType } from "vue";
|
||||
import { scrollTo } from '@/utils/scroll-to'
|
||||
|
||||
const props = defineProps({
|
||||
total: {
|
||||
required: true,
|
||||
type: Number,
|
||||
type: Number as PropType<number>,
|
||||
default: 0
|
||||
},
|
||||
page: {
|
||||
@@ -32,7 +25,7 @@ const props = defineProps({
|
||||
default: 20
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
type: Array as PropType<number[]>,
|
||||
default() {
|
||||
return [10, 20, 30, 50]
|
||||
}
|
||||
@@ -55,18 +48,16 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits();
|
||||
const emit = defineEmits(["update:page", "update:limit", "pagination"]);
|
||||
|
||||
const currentPage = computed({
|
||||
get() {
|
||||
return props.page
|
||||
},
|
||||
set(val) {
|
||||
emit('update:page', val)
|
||||
const currentPage = computed<number | undefined>({
|
||||
get: () => props.page,
|
||||
set: (value) => {
|
||||
emit('update:page', value)
|
||||
}
|
||||
})
|
||||
|
||||
const pageSize = computed({
|
||||
const pageSize = computed<number | undefined>({
|
||||
get() {
|
||||
return props.limit
|
||||
},
|
||||
@@ -75,15 +66,16 @@ const pageSize = computed({
|
||||
}
|
||||
})
|
||||
|
||||
function handleSizeChange(val) {
|
||||
emit('pagination', {page: currentPage, limit: val})
|
||||
function handleSizeChange(val: number) {
|
||||
emit('pagination', { page: currentPage, limit: val })
|
||||
if (props.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
}
|
||||
|
||||
function handleCurrentChange(val) {
|
||||
emit('pagination', {page: val, limit: props.pageSizes})
|
||||
function handleCurrentChange(val: number) {
|
||||
currentPage.value = val
|
||||
emit('pagination', { page: val, limit: props.limit })
|
||||
if (props.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
<template>
|
||||
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
|
||||
<div class="rightPanel-background"/>
|
||||
<div ref="rightPanel" :class="{ show: show }" class="rightPanel-container">
|
||||
<div class="rightPanel-background" />
|
||||
<div class="rightPanel">
|
||||
<div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
|
||||
<Close style="width: 1em; height: 1em;vertical-align: middle " v-show="show"/>
|
||||
<Setting style="width:1em; height:1em;vertical-align: middle " v-show="!show"/>
|
||||
<div class="handle-button" :style="{ 'top': buttonTop + 'px', 'background-color': theme }" @click="show = !show">
|
||||
<Close style="width: 1em; height: 1em;vertical-align: middle " v-show="show" />
|
||||
<Setting style="width:1em; height:1em;vertical-align: middle " v-show="!show" />
|
||||
</div>
|
||||
<div class="rightPanel-items">
|
||||
<slot/>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, onBeforeUnmount, onMounted, ref, watch} from "vue";
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
||||
|
||||
import {addClass, removeClass} from '@/utils/index'
|
||||
import { addClass, removeClass } from '@/utils/index'
|
||||
|
||||
import useStore from "@/store";
|
||||
|
||||
// 图标依赖
|
||||
import {Close, Setting} from '@element-plus/icons-vue'
|
||||
import {ElColorPicker} from "element-plus";
|
||||
import { Close, Setting } from '@element-plus/icons-vue'
|
||||
import { ElColorPicker } from "element-plus";
|
||||
|
||||
const {setting} =useStore()
|
||||
const { setting } = useStore()
|
||||
|
||||
const props = defineProps({
|
||||
const theme = computed(() => setting.theme)
|
||||
const show = ref(false)
|
||||
|
||||
defineProps({
|
||||
buttonTop: {
|
||||
default: 250,
|
||||
type: Number
|
||||
}
|
||||
})
|
||||
|
||||
const theme = computed(() =>setting.theme)
|
||||
|
||||
const show = ref(false)
|
||||
|
||||
watch(show, (value) => {
|
||||
if (value) {
|
||||
addEventClick()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" @click="toggle"/>
|
||||
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" @click="toggle" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useFullscreen} from '@vueuse/core'
|
||||
<script setup lang="ts">
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
|
||||
const {isFullscreen, enter, toggle} = useFullscreen();
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
</script>
|
||||
@@ -5,12 +5,8 @@
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="item of sizeOptions"
|
||||
:key="item.value"
|
||||
:disabled="(size || 'default') == item.value"
|
||||
:command="item.value"
|
||||
>
|
||||
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="(size || 'default') == item.value"
|
||||
:command="item.value">
|
||||
{{ item.label }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -20,8 +16,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
import useStore from "@/store";
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, nextTick, watch} from "vue";
|
||||
import {computed, watch} from "vue";
|
||||
import useStore from "@/store";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {localStorage} from "@/utils/storage";
|
||||
|
||||
// 参考连接:https://juejin.cn/post/7024025899813044232#heading-1
|
||||
|
||||
@@ -1,44 +1,27 @@
|
||||
<template>
|
||||
<div class="el-tree-select">
|
||||
<el-select
|
||||
style="width: 100%"
|
||||
v-model="modelValue"
|
||||
ref="treeSelect"
|
||||
:filterable="true"
|
||||
:clearable="true"
|
||||
@clear="clearHandle"
|
||||
:filter-method="selectFilterData"
|
||||
:placeholder="placeholder"
|
||||
>
|
||||
<el-select style="width: 100%" v-model="modelValue" ref="treeSelect" :filterable="true" :clearable="true"
|
||||
@clear="clearHandle" :filter-method="selectFilterData" :placeholder="placeholder">
|
||||
<el-option :value="modelValue" :label="valueTitle">
|
||||
<el-tree
|
||||
id="tree-option"
|
||||
ref="selectTree"
|
||||
:accordion="accordion"
|
||||
:data="options"
|
||||
:props="state.props"
|
||||
:node-key="state.props.value"
|
||||
:expand-on-click-node="false"
|
||||
:default-expanded-keys="defaultExpandedKey"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="handleNodeClick"
|
||||
></el-tree>
|
||||
<el-tree id="tree-option" ref="selectTree" :accordion="accordion" :data="options" :props="state.props"
|
||||
:node-key="state.props.value" :expand-on-click-node="false" :default-expanded-keys="defaultExpandedKey"
|
||||
:filter-node-method="filterNode" @node-click="handleNodeClick"></el-tree>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance,
|
||||
nextTick,
|
||||
onMounted,
|
||||
computed,
|
||||
watch,
|
||||
watch
|
||||
} from "vue";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
|
||||
const state = defineProps({
|
||||
// 配置项
|
||||
@@ -67,7 +50,9 @@ const state = defineProps({
|
||||
// 数据源
|
||||
options: {
|
||||
type: Array,
|
||||
default: [],
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
// 提示文字
|
||||
placeholder: {
|
||||
@@ -87,9 +72,9 @@ const modelValue = computed({
|
||||
},
|
||||
});
|
||||
const valueTitle = ref("");
|
||||
const defaultExpandedKey = ref([]);
|
||||
const defaultExpandedKey = ref([] as any[]);
|
||||
|
||||
function handleNodeClick(node) {
|
||||
function handleNodeClick(node: any) {
|
||||
valueTitle.value = node[state.props.label];
|
||||
modelValue.value = node[state.props.value];
|
||||
defaultExpandedKey.value = [];
|
||||
@@ -97,11 +82,11 @@ function handleNodeClick(node) {
|
||||
selectFilterData("");
|
||||
}
|
||||
|
||||
function selectFilterData(val) {
|
||||
function selectFilterData(val: any) {
|
||||
proxy.$refs.selectTree.filter(val);
|
||||
}
|
||||
|
||||
function filterNode(value, data) {
|
||||
function filterNode(value: any, data: any) {
|
||||
if (!value) return true;
|
||||
return data[state.props["label"]].indexOf(value) !== -1;
|
||||
}
|
||||
|
||||
@@ -28,18 +28,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
import { computed } from "vue";
|
||||
import { Plus, Close } from "@element-plus/icons-vue";
|
||||
import {
|
||||
ElMessage,
|
||||
ElUpload,
|
||||
UploadFile,
|
||||
UploadRawFile,
|
||||
UploadRequestOptions,
|
||||
} from "element-plus";
|
||||
import { uploadFile, deleteFile } from "@/api/system/file";
|
||||
|
||||
const uploadRef = ref(ElUpload);
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const props = defineProps({
|
||||
@@ -89,10 +87,9 @@ function handleRemove(fileUrl?: string) {
|
||||
}
|
||||
/**
|
||||
* 在 before-upload 钩子中限制用户上传文件的格式和大小
|
||||
*
|
||||
*/
|
||||
function handleBeforeUpload(file: UploadRawFile) {
|
||||
const isJPG = file.type === "image/jpeg";
|
||||
// const isJPG = file.type === "image/jpeg";
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
|
||||
if (!isLt2M) {
|
||||
|
||||
@@ -1,28 +1,19 @@
|
||||
<template>
|
||||
<div style="border: 1px solid #ccc">
|
||||
<!-- 工具栏 -->
|
||||
<Toolbar
|
||||
:editorId="editorId"
|
||||
:defaultConfig="toolbarConfig"
|
||||
style="border-bottom: 1px solid #ccc"
|
||||
/>
|
||||
<Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" style="border-bottom: 1px solid #ccc" :mode="mode" />
|
||||
<!-- 编辑器 -->
|
||||
<Editor
|
||||
:editorId="editorId"
|
||||
:defaultConfig="editorConfig"
|
||||
:defaultHtml="defaultHtml"
|
||||
@onChange="handleChange"
|
||||
style="height: 500px; overflow-y: hidden;"
|
||||
/>
|
||||
<Editor :defaultConfig="editorConfig" v-model="defaultHtml" @onChange="handleChange"
|
||||
style="height: 500px; overflow-y: hidden;" :mode="mode" @onCreated="handleCreated" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, onBeforeUnmount, reactive, toRefs} from 'vue'
|
||||
import {Editor, Toolbar, getEditor, removeEditor} from '@wangeditor/editor-for-vue'
|
||||
import { onBeforeUnmount, shallowRef, reactive, toRefs} from 'vue'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
|
||||
// API 引用
|
||||
import {uploadFile} from "@/api/system/file";
|
||||
import { uploadFile } from "@/api/system/file";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
@@ -33,16 +24,18 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
// 编辑器实例,必须用 shallowRef
|
||||
const editorRef = shallowRef()
|
||||
|
||||
const state = reactive({
|
||||
editorId: `w-e-${Math.random().toString().slice(-5)}`, //【注意】编辑器 id ,要全局唯一
|
||||
toolbarConfig: {},
|
||||
editorConfig: {
|
||||
placeholder: '请输入内容...',
|
||||
MENU_CONF: {
|
||||
uploadImage: {
|
||||
// 自定义图片上传
|
||||
// @link https://www.wangeditor.com/v5/guide/menu-config.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%9F%E8%83%BD
|
||||
async customUpload(file:any, insertFn:any) {
|
||||
async customUpload(file: any, insertFn: any) {
|
||||
console.log("上传图片")
|
||||
uploadFile(file).then(response => {
|
||||
const url = response.data
|
||||
insertFn(url)
|
||||
@@ -51,23 +44,28 @@ const state = reactive({
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultHtml: props.modelValue
|
||||
defaultHtml: props.modelValue,
|
||||
mode: 'default'
|
||||
})
|
||||
|
||||
const {editorId, toolbarConfig, editorConfig,defaultHtml} = toRefs(state)
|
||||
const { toolbarConfig, editorConfig, defaultHtml, mode } = toRefs(state)
|
||||
|
||||
function handleChange(editor:any) {
|
||||
const handleCreated = (editor: any) => {
|
||||
editorRef.value = editor // 记录 editor 实例,重要!
|
||||
}
|
||||
|
||||
function handleChange(editor: any) {
|
||||
emit('update:modelValue', editor.getHtml())
|
||||
}
|
||||
|
||||
// 组件销毁时,也及时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
const editor = getEditor(state.editorId)
|
||||
const editor = editorRef.value
|
||||
if (editor == null) return
|
||||
editor.destroy()
|
||||
removeEditor(state.editorId)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style src="@wangeditor/editor/dist/css/style.css"></style>
|
||||
<style src="@wangeditor/editor/dist/css/style.css">
|
||||
</style>
|
||||
@@ -65,7 +65,6 @@ import Hamburger from "@/components/Hamburger/index.vue";
|
||||
import Screenfull from "@/components/Screenfull/index.vue";
|
||||
import SizeSelect from "@/components/SizeSelect/index.vue";
|
||||
import LangSelect from "@/components/LangSelect/index.vue";
|
||||
import SvgIcon from "@/components/SvgIcon/index.vue";
|
||||
|
||||
// 图标依赖
|
||||
import { CaretBottom } from "@element-plus/icons-vue";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
|
||||
<div class="sidebar-logo-container" :class="{ 'collapse': isCollapse }">
|
||||
<transition name="sidebarLogoFade">
|
||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo">
|
||||
@@ -14,17 +14,23 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref, reactive, toRefs } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
collapse: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const title=ref("vue3-element-admin")
|
||||
const logo=ref("https://s2.loli.net/2022/04/07/hyquWXELOoYvlP6.png")
|
||||
const state = reactive({
|
||||
isCollapse: props.collapse
|
||||
})
|
||||
|
||||
const { isCollapse } = toRefs(state)
|
||||
|
||||
const title = ref("vue3-element-admin")
|
||||
const logo = ref("https://s2.loli.net/2022/04/07/hyquWXELOoYvlP6.png")
|
||||
|
||||
</script>
|
||||
|
||||
@@ -32,10 +38,12 @@ const logo=ref("https://s2.loli.net/2022/04/07/hyquWXELOoYvlP6.png")
|
||||
.sidebarLogoFade-enter-active {
|
||||
transition: opacity 1.5s;
|
||||
}
|
||||
|
||||
.sidebarLogoFade-enter,
|
||||
.sidebarLogoFade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.sidebar-logo-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import path from 'path-browserify'
|
||||
import { ref} from "vue";
|
||||
import path from 'path-browserify'
|
||||
import {isExternal} from '@/utils/validate'
|
||||
import AppLink from './Link.vue'
|
||||
|
||||
@@ -83,7 +83,7 @@ function hasOneShowingChild(children = [] as any, parent: any) {
|
||||
}
|
||||
|
||||
return false
|
||||
};
|
||||
}
|
||||
|
||||
function resolvePath(routePath: string) {
|
||||
if (isExternal(routePath)) {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {computed, defineComponent} from "vue";
|
||||
import {computed} from "vue";
|
||||
import {useRoute} from 'vue-router'
|
||||
|
||||
import SidebarItem from './SidebarItem.vue'
|
||||
@@ -44,7 +44,7 @@ const activeMenu = computed(() => {
|
||||
const {meta, path} = route
|
||||
// if set path, the sidebar will highlight the path you set
|
||||
if (meta.activeMenu) {
|
||||
return meta.activeMenu
|
||||
return meta.activeMenu as string
|
||||
}
|
||||
return path
|
||||
})
|
||||
|
||||
@@ -15,12 +15,11 @@ import {
|
||||
computed,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
getCurrentInstance,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import { TagView } from "@/types";
|
||||
import useStore from "@/store";
|
||||
|
||||
const emits = defineEmits();
|
||||
|
||||
const tagAndTagSpacing = ref(4);
|
||||
const scrollContainerRef = ref(null);
|
||||
@@ -29,9 +28,6 @@ const { tagsView } = useStore();
|
||||
|
||||
const visitedViews = computed(() => tagsView.visitedViews);
|
||||
|
||||
const emitScroll = () => {
|
||||
(emits as any)("scroll");
|
||||
};
|
||||
|
||||
const { ctx } = getCurrentInstance() as any;
|
||||
const scrollWrapper = computed(() => {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
class="el-icon-close"
|
||||
@click.prevent.stop="closeSelectedTag(tag)"
|
||||
>
|
||||
<close
|
||||
<Close
|
||||
class="el-icon-close"
|
||||
style="width: 1em; height: 1em; vertical-align: middle"
|
||||
/>
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
class="drawer-bg"
|
||||
@click="handleClickOutside"
|
||||
/>
|
||||
<sidebar class="sidebar-container" />
|
||||
<Sidebar class="sidebar-container" />
|
||||
<div :class="{ hasTagsView: needTagsView }" class="main-container">
|
||||
<div :class="{ 'fixed-header': fixedHeader }">
|
||||
<navbar />
|
||||
<tags-view v-if="needTagsView" />
|
||||
</div>
|
||||
<app-main />
|
||||
<right-panel v-if="showSettings">
|
||||
<RightPanel v-if="showSettings">
|
||||
<settings />
|
||||
</right-panel>
|
||||
</RightPanel>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -28,7 +28,7 @@ import RightPanel from "@/components/RightPanel/index.vue";
|
||||
|
||||
import useStore from "@/store";
|
||||
|
||||
const { width, height } = useWindowSize();
|
||||
const { width } = useWindowSize();
|
||||
const WIDTH = 992;
|
||||
|
||||
const { app, setting } = useStore();
|
||||
|
||||
@@ -62,7 +62,7 @@ const usePermissionStore = defineStore({
|
||||
return new Promise((resolve, reject) => {
|
||||
listRoutes().then(response => {
|
||||
const asyncRoutes = response.data
|
||||
let accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
|
||||
const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
|
||||
this.setRoutes(accessedRoutes)
|
||||
resolve(accessedRoutes)
|
||||
}).catch(error => {
|
||||
|
||||
@@ -145,7 +145,7 @@ const useTagsViewStore = defineStore({
|
||||
})
|
||||
})
|
||||
},
|
||||
delAllViews(view: any) {
|
||||
delAllViews() {
|
||||
return new Promise(resolve => {
|
||||
const affixTags = this.visitedViews.filter(tag => tag.meta?.affix)
|
||||
this.visitedViews = affixTags
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
--el-button-text-color: var(--el-color-white) !important;
|
||||
--el-button-bg-color: var(--el-color-primary) !important;
|
||||
--el-button-border-color: var(--el-color-primary) !important;
|
||||
--el-button-hover-bg-color: var(--el-color-primary-light-2) !important;
|
||||
--el-button-hover-border-color: var(--el-color-primary-light-2) !important;
|
||||
--el-button-active-bg-color: var(--el-color-primary-dark) !important;
|
||||
--el-button-active-border-color: var(--el-color-primary-dark) !important;
|
||||
}
|
||||
@@ -34,8 +32,6 @@
|
||||
--el-button-bg-color: var(--el-color-primary-light-9)!important;
|
||||
--el-button-border-color: var(--el-color-primary-light-5)!important;
|
||||
--el-button-hover-text-color: var(--el-color-white)!important;
|
||||
--el-button-hover-bg-color: var(--el-color-primary)!important;
|
||||
--el-button-hover-border-color: var(--el-color-primary)!important;
|
||||
--el-button-active-text-color: var(--el-color-white)!important;
|
||||
--el-button-active-border-color: var(--el-color-primary)!important;
|
||||
}
|
||||
|
||||
4
src/types/api/oms/order.d.ts
vendored
4
src/types/api/oms/order.d.ts
vendored
@@ -38,9 +38,7 @@ export interface OrderItem {
|
||||
/**
|
||||
* 订单分页项类型声明
|
||||
*/
|
||||
export interface OrderPageResult extends PageResult<Order[]> {
|
||||
|
||||
}
|
||||
export type OrderPageResult = PageResult<Order[]>
|
||||
|
||||
/**
|
||||
* 订单表单类型声明
|
||||
|
||||
6
src/types/api/pms/brand.d.ts
vendored
6
src/types/api/pms/brand.d.ts
vendored
@@ -4,7 +4,7 @@ import { PageQueryParam, PageResult } from "../base"
|
||||
* 品牌查询参数类型声明
|
||||
*/
|
||||
export interface BrandQueryParam extends PageQueryParam {
|
||||
name: String | undefined
|
||||
name?: string
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,7 @@ export interface BrandItem {
|
||||
/**
|
||||
* 品牌分页项类型声明
|
||||
*/
|
||||
export interface BrandPageResult extends PageResult<BrandItem[]> {
|
||||
|
||||
}
|
||||
export type BrandPageResult = PageResult<BrandItem[]>
|
||||
|
||||
/**
|
||||
* 品牌表单类型声明
|
||||
|
||||
35
src/types/api/pms/goods.d.ts
vendored
35
src/types/api/pms/goods.d.ts
vendored
@@ -1,12 +1,11 @@
|
||||
import { PageQueryParam, PageResult } from "../base"
|
||||
|
||||
|
||||
/**
|
||||
* 商品查询参数类型声明
|
||||
*/
|
||||
export interface GoodsQueryParam extends PageQueryParam {
|
||||
name: stirng | undefined,
|
||||
categoryId: number | undefined
|
||||
name?: stirng,
|
||||
categoryId?: number
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,25 +48,25 @@ export interface SkuItem {
|
||||
/**
|
||||
* 商品分页项类型声明
|
||||
*/
|
||||
export interface GoodsPageResult extends PageResult<GoodsItem[]> {
|
||||
|
||||
}
|
||||
export type GoodsPageResult = PageResult<GoodsItem[]>
|
||||
|
||||
/**
|
||||
* 商品表单数据类型声明
|
||||
*/
|
||||
export interface GoodsFormData {
|
||||
id: number|undefined,
|
||||
deptId: number,
|
||||
username: string,
|
||||
nickname: string,
|
||||
password: string,
|
||||
mobile: string,
|
||||
email: string,
|
||||
gender: number,
|
||||
status: number,
|
||||
remark: string,
|
||||
roleIds: number[]
|
||||
export interface GoodsDetail {
|
||||
id: string,
|
||||
name: string,
|
||||
categoryId: string,
|
||||
brandId: string,
|
||||
originPrice: number,
|
||||
price: number,
|
||||
picUrl: string,
|
||||
album: string[],
|
||||
description: string,
|
||||
detail: string,
|
||||
attrList: any[],
|
||||
specList: any[],
|
||||
skuList: any[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
8
src/types/api/sms/advert.d.ts
vendored
8
src/types/api/sms/advert.d.ts
vendored
@@ -4,7 +4,7 @@ import { PageQueryParam, PageResult } from "../base"
|
||||
* 广告查询参数类型声明
|
||||
*/
|
||||
export interface AdvertQueryParam extends PageQueryParam {
|
||||
title: String | undefined
|
||||
title?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,15 +20,13 @@ export interface AdvertItem {
|
||||
/**
|
||||
* 广告分页项类型声明
|
||||
*/
|
||||
export interface AdvertPageResult extends PageResult<AdvertItem[]> {
|
||||
|
||||
}
|
||||
export type AdvertPageResult = PageResult<AdvertItem[]>
|
||||
|
||||
/**
|
||||
* 广告表单类型声明
|
||||
*/
|
||||
export interface AdvertFormData {
|
||||
id: number | undefined;
|
||||
id?: number;
|
||||
title: string;
|
||||
picUrl: string;
|
||||
beginTime: string;
|
||||
|
||||
4
src/types/api/system/client.d.ts
vendored
4
src/types/api/system/client.d.ts
vendored
@@ -31,9 +31,7 @@ export interface ClientItem {
|
||||
/**
|
||||
* 客户端分页项类型声明
|
||||
*/
|
||||
export interface ClientPageResult extends PageResult<ClientItem[]> {
|
||||
|
||||
}
|
||||
export type ClientPageResult = PageResult<ClientItem[]>
|
||||
|
||||
/**
|
||||
* 客户端表单类型声明
|
||||
|
||||
13
src/types/api/system/dict.d.ts
vendored
13
src/types/api/system/dict.d.ts
vendored
@@ -25,9 +25,7 @@ export interface Dict {
|
||||
/**
|
||||
* 字典分页项类型声明
|
||||
*/
|
||||
export interface DictPageResult extends PageResult<Dict[]> {
|
||||
|
||||
}
|
||||
export type DictPageResult = PageResult<Dict[]>
|
||||
|
||||
/**
|
||||
* 字典表单类型声明
|
||||
@@ -71,16 +69,15 @@ export interface DictItem {
|
||||
/**
|
||||
* 字典分页项类型声明
|
||||
*/
|
||||
export interface DictItemPageResult extends PageResult<DictItem[]> {
|
||||
|
||||
}
|
||||
export type DictItemPageResult = PageResult<DictItem[]>
|
||||
|
||||
/**
|
||||
* 字典表单类型声明
|
||||
*/
|
||||
export interface DictItemFormData {
|
||||
id: number | undefined;
|
||||
dictCode:string,
|
||||
id?: number;
|
||||
dictCode?:string,
|
||||
dictName?:string;
|
||||
name: string;
|
||||
code: string;
|
||||
value: string;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
/**
|
||||
* 菜单查询参数类型声明
|
||||
*/
|
||||
export interface MenuQueryParam {
|
||||
name: String | undefined
|
||||
export interface MenuQueryParam {
|
||||
name?: string
|
||||
}
|
||||
|
||||
/**
|
||||
4
src/types/api/system/perm.d.ts
vendored
4
src/types/api/system/perm.d.ts
vendored
@@ -23,9 +23,7 @@ export interface PermItem {
|
||||
/**
|
||||
* 权限分页项类型声明
|
||||
*/
|
||||
export interface PermPageResult extends PageResult<PermItem[]> {
|
||||
|
||||
}
|
||||
export type PermPageResult = PageResult<PermItem[]>
|
||||
|
||||
/**
|
||||
* 权限表单类型声明
|
||||
|
||||
6
src/types/api/system/role.d.ts
vendored
6
src/types/api/system/role.d.ts
vendored
@@ -4,7 +4,7 @@ import { PageQueryParam, PageResult } from "../base"
|
||||
* 角色查询参数类型声明
|
||||
*/
|
||||
export interface RoleQueryParam extends PageQueryParam {
|
||||
name: String | undefined
|
||||
name?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,9 +25,7 @@ export interface RoleItem {
|
||||
/**
|
||||
* 角色分页项类型声明
|
||||
*/
|
||||
export interface RolePageResult extends PageResult<RoleItem[]> {
|
||||
|
||||
}
|
||||
export type RolePageResult = PageResult<RoleItem[]>
|
||||
|
||||
/**
|
||||
* 角色表单类型声明
|
||||
|
||||
13
src/types/api/system/user.d.ts
vendored
13
src/types/api/system/user.d.ts
vendored
@@ -14,9 +14,9 @@ export interface UserInfo {
|
||||
* 用户查询参数类型声明
|
||||
*/
|
||||
export interface UserQueryParam extends PageQueryParam {
|
||||
keywords: String | undefined,
|
||||
status: number | undefined,
|
||||
deptId: number | undefined
|
||||
keywords: string,
|
||||
status: number,
|
||||
deptId: number
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,9 +39,7 @@ export interface UserItem {
|
||||
/**
|
||||
* 用户分页项类型声明
|
||||
*/
|
||||
export interface UserPageResult extends PageResult<UserItem[]> {
|
||||
|
||||
}
|
||||
export type UserPageResult = PageResult<UserItem[]>
|
||||
|
||||
/**
|
||||
* 用户表单类型声明
|
||||
@@ -60,11 +58,10 @@ export interface UserFormData {
|
||||
roleIds: number[]
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户导入表单类型声明
|
||||
*/
|
||||
export interface UserImportFormData {
|
||||
export interface UserImportFormData {
|
||||
deptId: number,
|
||||
roleIds: number[]
|
||||
}
|
||||
6
src/types/api/ums/member.d.ts
vendored
6
src/types/api/ums/member.d.ts
vendored
@@ -4,7 +4,7 @@ import { PageQueryParam, PageResult } from "../base"
|
||||
* 会员查询参数类型声明
|
||||
*/
|
||||
export interface MemberQueryParam extends PageQueryParam {
|
||||
nickName: String | undefined
|
||||
nickName?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,9 +46,7 @@ export interface AddressItem {
|
||||
/**
|
||||
* 会员分页项类型声明
|
||||
*/
|
||||
export interface MemberPageResult extends PageResult<MemberItem[]> {
|
||||
|
||||
}
|
||||
export type MemberPageResult = PageResult<MemberItem[]>
|
||||
|
||||
/**
|
||||
* 会员表单类型声明
|
||||
|
||||
@@ -31,17 +31,17 @@ export function removeClass(ele: HTMLElement, cls: string) {
|
||||
|
||||
export function mix(color1: string, color2: string, weight: number) {
|
||||
weight = Math.max(Math.min(Number(weight), 1), 0);
|
||||
let r1 = parseInt(color1.substring(1, 3), 16);
|
||||
let g1 = parseInt(color1.substring(3, 5), 16);
|
||||
let b1 = parseInt(color1.substring(5, 7), 16);
|
||||
let r2 = parseInt(color2.substring(1, 3), 16);
|
||||
let g2 = parseInt(color2.substring(3, 5), 16);
|
||||
let b2 = parseInt(color2.substring(5, 7), 16);
|
||||
let r = Math.round(r1 * (1 - weight) + r2 * weight);
|
||||
let g = Math.round(g1 * (1 - weight) + g2 * weight);
|
||||
let b = Math.round(b1 * (1 - weight) + b2 * weight);
|
||||
const r1 = parseInt(color1.substring(1, 3), 16);
|
||||
const g1 = parseInt(color1.substring(3, 5), 16);
|
||||
const b1 = parseInt(color1.substring(5, 7), 16);
|
||||
const r2 = parseInt(color2.substring(1, 3), 16);
|
||||
const g2 = parseInt(color2.substring(3, 5), 16);
|
||||
const b2 = parseInt(color2.substring(5, 7), 16);
|
||||
const r = Math.round(r1 * (1 - weight) + r2 * weight);
|
||||
const g = Math.round(g1 * (1 - weight) + g2 * weight);
|
||||
const b = Math.round(b1 * (1 - weight) + b2 * weight);
|
||||
const rStr = ("0" + (r || 0).toString(16)).slice(-2);
|
||||
const gStr = ("0" + (g || 0).toString(16)).slice(-2);
|
||||
const bStr = ("0" + (b || 0).toString(16)).slice(-2);
|
||||
return "#" + rStr + gStr + bStr;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,10 +52,6 @@ service.interceptors.response.use(
|
||||
localStorage.clear(); // 清除浏览器全部缓存
|
||||
window.location.href = '/'; // 跳转登录页
|
||||
ElMessageBox.alert('当前页面已失效,请重新登录', '提示', {})
|
||||
.then(() => {
|
||||
})
|
||||
.catch(() => {
|
||||
});
|
||||
} else {
|
||||
ElMessage({
|
||||
message: msg || '系统出错',
|
||||
|
||||
@@ -34,7 +34,7 @@ const position = () => {
|
||||
* @param {number} duration
|
||||
* @param {Function} callback
|
||||
*/
|
||||
export const scrollTo = (to: number, duration: number, callback?: Function) => {
|
||||
export const scrollTo = (to: number, duration: number, callback?: any) => {
|
||||
const start = position()
|
||||
const change = to - start
|
||||
const increment = 20
|
||||
|
||||
@@ -8,7 +8,7 @@ export const localStorage = {
|
||||
},
|
||||
// 获取永久缓存
|
||||
get(key: string) {
|
||||
let json: any = window.localStorage.getItem(key);
|
||||
const json: any = window.localStorage.getItem(key);
|
||||
return JSON.parse(json);
|
||||
},
|
||||
// 移除永久缓存
|
||||
@@ -31,7 +31,7 @@ export const sessionStorage = {
|
||||
},
|
||||
// 获取临时缓存
|
||||
get(key: string) {
|
||||
let json: any = window.sessionStorage.getItem(key);
|
||||
const json: any = window.sessionStorage.getItem(key);
|
||||
return JSON.parse(json);
|
||||
},
|
||||
// 移除临时缓存
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
import {nextTick, onActivated, onBeforeUnmount, onDeactivated, onMounted} from "vue";
|
||||
import {init, EChartsOption} from 'echarts'
|
||||
import resize from "@/utils/resize";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</template>
|
||||
<el-tabs v-model="teamActiveName">
|
||||
<el-tab-pane label="开发者「无回」" name="developer">
|
||||
<div class="developer" ref="dev_wapper">
|
||||
<div class="developer" ref="dev_wrapper">
|
||||
<ul class="developer__container">
|
||||
<li class="developer__item" v-for="(item, index) in developers" :key="index">
|
||||
<div class="developer__inner">
|
||||
@@ -21,9 +21,10 @@
|
||||
<div class="developer__position">
|
||||
<el-tag
|
||||
v-for="(position, i) in item.positions"
|
||||
:type="colors[i % colors.length]"
|
||||
:type="(colors[i % colors.length] as any)"
|
||||
:class="i !== 0 ? 'f-ml' : ''"
|
||||
size="small"
|
||||
:key="i"
|
||||
>{{ position }}</el-tag>
|
||||
</div>
|
||||
<div class="developer__homepage">
|
||||
@@ -41,8 +42,8 @@
|
||||
<div class="group">
|
||||
<el-image
|
||||
class="group-img"
|
||||
src="https://cdn.youlai.tech/youlaiqun.png"
|
||||
:preview-src-list="['https://cdn.youlai.tech/youlaiqun.png']"
|
||||
src="https://www.youlai.tech/files/blog/youlaiqun.png"
|
||||
:preview-src-list="['https://www.youlai.tech/files/blog/youlaiqun.png']"
|
||||
/>
|
||||
<div class="group-tip">群二维码过期可添加开发者微信由其拉入群,备注「有来」即可。</div>
|
||||
</div>
|
||||
@@ -99,10 +100,10 @@ const { teamActiveName, developers, colors, indicatorImgUrl } = toRefs(state);
|
||||
|
||||
let bScroll = reactive({})
|
||||
|
||||
const dev_wapper = ref<HTMLElement | any>(null)
|
||||
const dev_wrapper = ref<HTMLElement | any>(null)
|
||||
|
||||
onMounted(() => {
|
||||
bScroll = new BScroll(dev_wapper.value, {
|
||||
bScroll = new BScroll(dev_wrapper.value, {
|
||||
mouseWheel: true,//开启鼠标滚轮
|
||||
disableMouse: false,//启用鼠标拖动
|
||||
scrollX: true, //X轴滚动启用
|
||||
|
||||
@@ -86,68 +86,32 @@
|
||||
<!-- Echarts 图表 -->
|
||||
<el-row :gutter="40" style="margin-top: 20px">
|
||||
<el-col :sm="24" :lg="8" class="card-panel-col">
|
||||
<BarChart
|
||||
id="barChart"
|
||||
height="400px"
|
||||
width="100%"
|
||||
class="chart-container"
|
||||
/>
|
||||
<BarChart id="barChart" height="400px" width="100%" class="chart-container" />
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :lg="8" class="card-panel-col">
|
||||
<PieChart
|
||||
id="pieChart"
|
||||
height="400px"
|
||||
width="100%"
|
||||
class="chart-container"
|
||||
/>
|
||||
<PieChart id="pieChart" height="400px" width="100%" class="chart-container" />
|
||||
<!--订单漏斗图-->
|
||||
<!--<FunnelChart id="funnelChart" height="400px" width="100%" class="chart-container"/>-->
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :lg="8" class="card-panel-col">
|
||||
<RadarChart
|
||||
id="radarChart"
|
||||
height="400px"
|
||||
width="100%"
|
||||
class="chart-container"
|
||||
/>
|
||||
<RadarChart id="radarChart" height="400px" width="100%" class="chart-container" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Vue引用
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
onMounted,
|
||||
reactive,
|
||||
toRefs,
|
||||
watchEffect,
|
||||
} from "vue";
|
||||
|
||||
// 组件引用
|
||||
import GithubCorner from "@/components/GithubCorner/index.vue";
|
||||
import SvgIcon from "@/components/SvgIcon/index.vue";
|
||||
import BarChart from "./components/Chart/BarChart.vue";
|
||||
import PieChart from "./components/Chart/PieChart.vue";
|
||||
import RadarChart from "./components/Chart/RadarChart.vue";
|
||||
import FunnelChart from "./components/Chart/FunnelChart.vue";
|
||||
|
||||
import Project from "./components/Project/index.vue";
|
||||
import Team from "./components/Team/index.vue";
|
||||
|
||||
import BScroll from "better-scroll";
|
||||
|
||||
import useStore from "@/store";
|
||||
|
||||
const { user } = useStore();
|
||||
|
||||
const roles = computed(() => user.roles);
|
||||
const avatar = computed(() => user.avatar);
|
||||
const nickname = computed(() => user.nickname);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -171,8 +135,7 @@ const nickname = computed(() => user.nickname);
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
.user-name {
|
||||
}
|
||||
.user-name {}
|
||||
|
||||
.box-center {
|
||||
padding-top: 10px;
|
||||
|
||||
@@ -142,7 +142,6 @@ const state = reactive({
|
||||
},
|
||||
loading: false,
|
||||
passwordType: "password",
|
||||
redirect: "",
|
||||
captchaBase64: "",
|
||||
// 大写提示禁用
|
||||
capslockTooltipDisabled: true,
|
||||
@@ -164,7 +163,6 @@ const {
|
||||
loginRules,
|
||||
loading,
|
||||
passwordType,
|
||||
redirect,
|
||||
captchaBase64,
|
||||
capslockTooltipDisabled,
|
||||
showCopyright,
|
||||
|
||||
@@ -118,10 +118,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, toRefs } from "vue";
|
||||
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { ElForm } from "element-plus";
|
||||
import { Dialog, Order, OrderQueryParam } from "@/types";
|
||||
import { listOrderPages, getOrderDetail } from "@/api/oms/order";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
import { Search, Refresh } from "@element-plus/icons-vue";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
|
||||
@@ -196,14 +196,10 @@ const state = reactive({
|
||||
|
||||
const {
|
||||
loading,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
orderList,
|
||||
total,
|
||||
dialog,
|
||||
dateRange,
|
||||
orderDetail,
|
||||
} = toRefs(state);
|
||||
|
||||
function handleQuery() {
|
||||
@@ -227,9 +223,6 @@ function viewDetail(row: any) {
|
||||
});
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
state.dialog.visible = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
handleQuery();
|
||||
|
||||
@@ -3,16 +3,8 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
click="handleDelete"
|
||||
:disabled="multiple"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" :icon="Delete" click="handleDelete" :disabled="multiple">删除</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="name">
|
||||
@@ -20,20 +12,13 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button :icon="Refresh" @click="resetForm">重置</el-button>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="brandList"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
>
|
||||
<el-table v-loading="loading" :data="brandList" @selection-change="handleSelectionChange" border>
|
||||
<el-table-column type="selection" min-width="5%" />
|
||||
<el-table-column prop="name" label="品牌名称" min-width="10" />
|
||||
<el-table-column prop="logoUrl" label="LOGO" min-width="10">
|
||||
@@ -41,10 +26,7 @@
|
||||
<el-popover placement="right" :width="400" trigger="hover">
|
||||
<img :src="scope.row.logoUrl" width="400" height="400" />
|
||||
<template #reference>
|
||||
<img
|
||||
:src="scope.row.logoUrl"
|
||||
style="max-height: 60px; max-width: 60px"
|
||||
/>
|
||||
<img :src="scope.row.logoUrl" style="max-height: 60px; max-width: 60px" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
@@ -54,46 +36,19 @@
|
||||
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
@click="handleUpdate(scope.row)"
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button @click="handleUpdate(scope.row)" type="primary" :icon="Edit" circle plain />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页工具条 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
|
||||
<!-- 表单弹窗 -->
|
||||
<el-dialog
|
||||
:title="dialog.title"
|
||||
v-model="dialog.visible"
|
||||
top="5vh"
|
||||
width="600px"
|
||||
>
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" top="5vh" width="600px">
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||
<el-form-item label="品牌名称" prop="name">
|
||||
<el-input v-model="formData.name" auto-complete="off" />
|
||||
</el-form-item>
|
||||
@@ -118,7 +73,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, toRefs, unref } from "vue";
|
||||
import { onMounted, reactive, ref, toRefs } from "vue";
|
||||
import { ElForm, ElTable, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
import { BrandFormData, BrandItem, BrandQueryParam, Dialog } from "@/types";
|
||||
@@ -156,14 +111,13 @@ const state = reactive({
|
||||
required: true,
|
||||
message: "请输入品牌名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
loading,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
brandList,
|
||||
@@ -211,17 +165,20 @@ function handleUpdate(row: any) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单提交
|
||||
*/
|
||||
function submitForm() {
|
||||
dataFormRef.value.validate((isValid: boolean) => {
|
||||
if (isValid) {
|
||||
if (state.formData.id) {
|
||||
updateBrand(state.formData.id, state.formData).then((response) => {
|
||||
updateBrand(state.formData.id, state.formData).then(() => {
|
||||
ElMessage.success("修改成功");
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addBrand(state.formData).then((response) => {
|
||||
addBrand(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
cancel();
|
||||
handleQuery();
|
||||
@@ -232,18 +189,16 @@ function submitForm() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置表单
|
||||
* 取消
|
||||
*/
|
||||
function resetForm() {
|
||||
state.formData.id = undefined;
|
||||
function cancel() {
|
||||
state.dialog.visible = false;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
state.dialog.visible = false;
|
||||
resetForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
function handleDelete(row: any) {
|
||||
const ids = [row.id || state.ids].join(",");
|
||||
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
|
||||
|
||||
@@ -7,43 +7,21 @@
|
||||
<el-tag v-else type="info"><i class="el-icon-info"></i> 请选择商品分类</el-tag>
|
||||
</el-col>
|
||||
<el-col :span="12" style="text-align: right">
|
||||
<el-button type="primary" :icon="Check" @click="submitForm">提交</el-button>
|
||||
<el-button type="primary" :icon="Check" @click="submitForm">提交</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row style="margin-top: 10px">
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="formData"
|
||||
:disabled="category?.childrenLen>0"
|
||||
label-width="100"
|
||||
>
|
||||
<el-form-item
|
||||
v-for="(item, index) in formData.attributes"
|
||||
:label="attributeTypeName + (index+1)"
|
||||
:prop="'attributes.' + index + '.name'"
|
||||
:rules="rules.attribute.name"
|
||||
>
|
||||
<el-input v-model="item.name" style="width: 300px"/>
|
||||
<el-form ref="form" :model="formData" :disabled="category?.childrenLen > 0" label-width="100">
|
||||
<el-form-item v-for="(item, index) in formData.attributes" :key="index" :label="attributeTypeName + (index + 1)"
|
||||
:prop="'attributes.' + index + '.name'" :rules="rules.attribute.name">
|
||||
<el-input v-model="item.name" style="width: 300px" />
|
||||
|
||||
<el-button
|
||||
v-if="index===0"
|
||||
type="success"
|
||||
:icon="Plus"
|
||||
circle
|
||||
plain
|
||||
@click.prevent="handleAdd()"
|
||||
style="margin-left: 15px"
|
||||
/>
|
||||
<el-button v-if="index === 0" type="success" :icon="Plus" circle plain @click.prevent="handleAdd()"
|
||||
style="margin-left: 15px" />
|
||||
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
plain
|
||||
circle
|
||||
@click.prevent="handleDelete(index)"
|
||||
style="margin-left: 15px"
|
||||
/>
|
||||
<el-button type="danger" :icon="Delete" plain circle @click.prevent="handleDelete(index)"
|
||||
style="margin-left: 15px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
@@ -52,11 +30,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {listAttributes, saveAttributeBatch} from "@/api/pms/attribute";
|
||||
import {computed, reactive, toRefs, watch} from "vue";
|
||||
import {Plus, Check, Delete} from '@element-plus/icons-vue'
|
||||
import {ElMessage} from "element-plus";
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue';
|
||||
|
||||
|
||||
import { computed, reactive, toRefs, watch } from "vue";
|
||||
import { listAttributes, saveAttributeBatch } from "@/api/pms/attribute";
|
||||
import { Plus, Check, Delete } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
attributeType: {
|
||||
@@ -65,10 +44,12 @@ const props = defineProps({
|
||||
},
|
||||
category: {
|
||||
type: Object,
|
||||
default: {
|
||||
id: undefined,
|
||||
name: '',
|
||||
childrenLen: 0
|
||||
default: () => {
|
||||
return {
|
||||
id: undefined,
|
||||
name: '',
|
||||
childrenLen: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -95,20 +76,20 @@ const state = reactive({
|
||||
rules: {
|
||||
attribute: {
|
||||
name: [
|
||||
{required: true, validator: attributeNameValidator, trigger: 'blur'}
|
||||
{ required: true, validator: attributeNameValidator, trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const {formData, rules} = toRefs(state)
|
||||
const { formData, rules } = toRefs(state)
|
||||
|
||||
watch(() => props.category.id as any, (newVal, oldVal) => {
|
||||
watch(() => props.category.id as any, () => {
|
||||
const categoryId = props.category.id
|
||||
if (categoryId) {
|
||||
listAttributes({categoryId: categoryId,type:props.attributeType}).then(response => {
|
||||
listAttributes({ categoryId: categoryId, type: props.attributeType }).then(response => {
|
||||
|
||||
const {data} = response
|
||||
const { data } = response
|
||||
if (data && data.length > 0) {
|
||||
state.formData.attributes = response.data
|
||||
} else {
|
||||
@@ -156,8 +137,7 @@ function submitForm() {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.component-container{
|
||||
.component-container {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,83 +1,47 @@
|
||||
<!-- 商品分类层级最多为三层,level字段标识 -->
|
||||
<template>
|
||||
<div class="component-container">
|
||||
|
||||
<el-tree
|
||||
v-loading="loading"
|
||||
ref="categoryTreeRef"
|
||||
:data="categoryOptions"
|
||||
:props="{ label: 'name', children: 'children',disabled:'' }"
|
||||
node-key="id"
|
||||
:expand-on-click-node="false"
|
||||
default-expand-all
|
||||
:accordion="true"
|
||||
@node-click="handleNodeClick"
|
||||
>
|
||||
<el-tree v-loading="loading" ref="categoryTreeRef" :data="categoryOptions"
|
||||
:props="{ label: 'name', children: 'children', disabled: '' }" node-key="id" :expand-on-click-node="false"
|
||||
default-expand-all :accordion="true" @node-click="handleNodeClick">
|
||||
<template #default="scope">
|
||||
<div class="custom-tree-node">
|
||||
<span>
|
||||
<el-image
|
||||
v-show="scope.data.level == 3 "
|
||||
:src="scope.data.iconUrl"
|
||||
style="width: 20px; height:20px; vertical-align: middle;margin-top: -5px"
|
||||
>
|
||||
<el-image v-show="scope.data.level == 3" :src="scope.data.iconUrl"
|
||||
style="width: 20px; height:20px; vertical-align: middle;margin-top: -5px">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<Picture style="width: 20px; height:20px;"/>
|
||||
<Picture style="width: 20px; height:20px;" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
{{ scope.data.name }}
|
||||
</span>
|
||||
<span>
|
||||
<el-button
|
||||
v-show="scope.data.level != 3 "
|
||||
type="success"
|
||||
:icon="Plus"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleAdd(scope.data)"/>
|
||||
<el-button
|
||||
v-show="scope.data.id !== 0"
|
||||
type="warning"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleUpdate(scope.data)"/>
|
||||
<el-button
|
||||
v-show="scope.data.id && (!scope.data.children || scope.data.children.length <= 0)"
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleDelete(scope.data)"/>
|
||||
</span>
|
||||
<el-button v-show="scope.data.level != 3" type="success" :icon="Plus" circle plain
|
||||
@click.stop="handleAdd(scope.data)" />
|
||||
<el-button v-show="scope.data.id !== 0" type="warning" :icon="Edit" circle plain
|
||||
@click.stop="handleUpdate(scope.data)" />
|
||||
<el-button v-show="scope.data.id && (!scope.data.children || scope.data.children.length <= 0)" type="danger"
|
||||
:icon="Delete" circle plain @click.stop="handleDelete(scope.data)" />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
|
||||
<el-dialog
|
||||
:title="dialog.title"
|
||||
v-model="dialog.visible"
|
||||
width="750px"
|
||||
>
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="750px">
|
||||
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||
<el-form-item label="上级分类" prop="parentId">
|
||||
<el-input v-model="parent.name" readonly/>
|
||||
<el-input v-model="parent.name" readonly />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="分类名称" prop="name">
|
||||
<el-input v-model="formData.name"/>
|
||||
<el-input v-model="formData.name" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="分类图标" prop="iconUrl">
|
||||
<single-upload v-model="formData.iconUrl"/>
|
||||
<single-upload v-model="formData.iconUrl" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="显示状态" prop="visible">
|
||||
@@ -103,11 +67,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {listCategories, addCategory, updateCategory, deleteCategories} from '@/api/pms/category'
|
||||
import {Search, Plus, Edit, Refresh, Delete} from '@element-plus/icons-vue'
|
||||
import { listCategories, addCategory, updateCategory, deleteCategories } from '@/api/pms/category'
|
||||
import { Plus, Edit, Delete } from '@element-plus/icons-vue'
|
||||
import SingleUpload from '@/components/Upload/SingleUpload.vue'
|
||||
import {getCurrentInstance, onMounted, reactive, ref, toRefs, unref} from "vue";
|
||||
import {ElForm, ElMessage, ElMessageBox, ElTree} from "element-plus";
|
||||
import { onMounted, reactive, ref, toRefs, unref, defineEmits } from "vue";
|
||||
import { ElForm, ElMessage, ElMessageBox, ElTree } from "element-plus";
|
||||
|
||||
const emit = defineEmits(['categoryClick'])
|
||||
|
||||
@@ -145,7 +109,7 @@ const state = reactive({
|
||||
current: {} as any
|
||||
})
|
||||
|
||||
const {loading, categoryOptions, formData, rules, dialog, parent} = toRefs(state)
|
||||
const { loading, categoryOptions, formData, rules, dialog, parent } = toRefs(state)
|
||||
|
||||
function handleQuery() {
|
||||
state.loading = true
|
||||
@@ -159,7 +123,6 @@ function handleQuery() {
|
||||
}]
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function handleNodeClick(row: any) {
|
||||
@@ -175,9 +138,7 @@ function handleNodeClick(row: any) {
|
||||
emit('categoryClick', row)
|
||||
}
|
||||
|
||||
|
||||
function handleAdd(row: any) {
|
||||
resetForm()
|
||||
state.dialog = {
|
||||
title: '新增商品分类',
|
||||
visible: true
|
||||
@@ -192,7 +153,6 @@ function handleAdd(row: any) {
|
||||
}
|
||||
|
||||
function handleUpdate(row: any) {
|
||||
resetForm()
|
||||
handleNodeClick(row)
|
||||
state.dialog = {
|
||||
title: '修改商品分类',
|
||||
@@ -202,24 +162,23 @@ function handleUpdate(row: any) {
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
const form = unref(dataFormRef)
|
||||
form.validate((valid: any) => {
|
||||
dataFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
if (state.formData.id) {
|
||||
updateCategory(state.formData.id, state.formData).then(response => {
|
||||
updateCategory(state.formData.id, state.formData).then(() => {
|
||||
ElMessage.success('修改成功')
|
||||
state.dialog.visible = false
|
||||
cancel()
|
||||
handleQuery()
|
||||
})
|
||||
} else {
|
||||
const parentCategory= state.parent as any
|
||||
console.log('parent',parentCategory)
|
||||
const parentCategory = state.parent as any
|
||||
console.log('parent', parentCategory)
|
||||
state.formData.parentId = parentCategory.id
|
||||
state.formData.level = parentCategory.level+1
|
||||
state.formData.level = parentCategory.level + 1
|
||||
|
||||
addCategory(state.formData).then(() => {
|
||||
ElMessage.success('新增成功')
|
||||
state.dialog.visible = false
|
||||
cancel()
|
||||
handleQuery()
|
||||
})
|
||||
}
|
||||
@@ -241,20 +200,9 @@ function handleDelete(row: any) {
|
||||
})
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
state.formData = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
parentId: 0,
|
||||
level: undefined,
|
||||
iconUrl: undefined,
|
||||
visible: 1,
|
||||
sort: 100
|
||||
}
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
resetForm()
|
||||
state.dialog.visible = false;
|
||||
dataFormRef.value.resetFields();
|
||||
state.dialog.visible = false
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<svg-icon icon-class="menu"/>
|
||||
商品分类
|
||||
</template>
|
||||
<category ref="categoryRef" @categoryClick="handleCategoryClick"/>
|
||||
<Category ref="categoryRef" @categoryClick="handleCategoryClick"/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
{{category.name}} 规格属性
|
||||
</template>
|
||||
<!-- 商品规格 -->
|
||||
<attribute ref="specificationRef" :attributeType="1" :category="category"/>
|
||||
<Attribute ref="specificationRef" :attributeType="1" :category="category"/>
|
||||
<!-- 商品属性 -->
|
||||
<attribute ref="attributeRef" :attributeType="2" :category="category"/>
|
||||
<Attribute ref="attributeRef" :attributeType="2" :category="category"/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -4,35 +4,15 @@
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<span>商品属性</span>
|
||||
<el-button
|
||||
style="float: right"
|
||||
type="success"
|
||||
:icon="Plus"
|
||||
size="small"
|
||||
@click="handleAdd"
|
||||
>
|
||||
<el-button style="float: right" type="success" :icon="Plus" size="small" @click="handleAdd">
|
||||
添加属性
|
||||
</el-button>
|
||||
</template>
|
||||
<el-form
|
||||
ref="dataForm"
|
||||
:model="modelValue"
|
||||
:rules="rules"
|
||||
size="small"
|
||||
:inline="true"
|
||||
>
|
||||
<el-table
|
||||
:data="modelValue.attrList"
|
||||
size="small"
|
||||
highlight-current-row
|
||||
border
|
||||
>
|
||||
<el-form ref="dataFormRef" :model="goodsInfo" :rules="rules" size="small" :inline="true">
|
||||
<el-table :data="goodsInfo.attrList" size="small" highlight-current-row border>
|
||||
<el-table-column property="name" label="属性名称">
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="'attrList[' + scope.$index + '].name'"
|
||||
:rules="rules.name"
|
||||
>
|
||||
<el-form-item :prop="'attrList[' + scope.$index + '].name'" :rules="rules.name">
|
||||
<el-input v-model="scope.row.name" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -40,10 +20,7 @@
|
||||
|
||||
<el-table-column property="value" label="属性值">
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="'attrList[' + scope.$index + '].value'"
|
||||
:rules="rules.value"
|
||||
>
|
||||
<el-form-item :prop="'attrList[' + scope.$index + '].value'" :rules="rules.value">
|
||||
<el-input v-model="scope.row.value" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -52,15 +29,8 @@
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-form-item>
|
||||
<el-button
|
||||
v-if="scope.$index > 0"
|
||||
type="danger"
|
||||
:icon="Minus"
|
||||
size="small"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleRemove(scope.$index)"
|
||||
/>
|
||||
<el-button v-if="scope.$index > 0" type="danger" :icon="Minus" size="small" circle plain
|
||||
@click.stop="handleRemove(scope.$index)" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -70,60 +40,60 @@
|
||||
</div>
|
||||
<div class="component-container__footer">
|
||||
<el-button @click="handlePrev">上一步,填写商品信息</el-button>
|
||||
<el-button type="primary" @click="handleNext"
|
||||
>下一步,设置商品库存</el-button
|
||||
>
|
||||
<el-button type="primary" @click="handleNext">下一步,设置商品库存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, toRefs, watch } from "vue";
|
||||
import { listAttributes } from "@/api/pms/attribute";
|
||||
import { computed, nextTick, reactive, ref, toRefs, unref, watch } from "vue";
|
||||
import { ElForm } from "element-plus";
|
||||
import { Plus, Minus } from "@element-plus/icons-vue";
|
||||
|
||||
const emit = defineEmits(["prev", "next"]);
|
||||
const dataForm = ref(ElForm);
|
||||
const emit = defineEmits(["prev", "next", "update:modelValue"]);
|
||||
const dataFormRef = ref(ElForm);
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
default: () => { }
|
||||
}
|
||||
});
|
||||
|
||||
const categoryId = computed(() => props.modelValue.categoryId);
|
||||
const goodsInfo: any = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
categoryId,
|
||||
(newVal) => {
|
||||
// 商品编辑不加载分类下的属性
|
||||
const spuId = props.modelValue.id;
|
||||
if (spuId) {
|
||||
return false;
|
||||
}
|
||||
watch(() => goodsInfo.value.categoryId, (newVal) => {
|
||||
// 商品编辑不加载分类下的属性
|
||||
const goodsId = goodsInfo.value.id;
|
||||
if (goodsId) {
|
||||
return false;
|
||||
}
|
||||
// 商品新增加载默认分类下的属性
|
||||
if (newVal) {
|
||||
// type=2 商品分类下的属性
|
||||
listAttributes({ categoryId: newVal, type: 2 }).then((response) => {
|
||||
const attrList = response.data;
|
||||
if (attrList && attrList.length > 0) {
|
||||
goodsInfo.value.attrList = attrList;
|
||||
} else {
|
||||
goodsInfo.value.attrList = [{}];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
goodsInfo.value.attrList = [{}];
|
||||
}
|
||||
|
||||
// 商品新增加载默认分类下的属性
|
||||
if (newVal) {
|
||||
// type=2 商品分类下的属性
|
||||
listAttributes({ categoryId: newVal, type: 2 }).then((response) => {
|
||||
const attrList = response.data;
|
||||
if (attrList && attrList.length > 0) {
|
||||
props.modelValue.attrList = attrList;
|
||||
} else {
|
||||
props.modelValue.attrList = [{}];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
props.modelValue.attrList = [{}];
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
deep: true
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
rules: {
|
||||
@@ -135,11 +105,11 @@ const state = reactive({
|
||||
const { rules } = toRefs(state);
|
||||
|
||||
function handleAdd() {
|
||||
props.modelValue.attrList.push({});
|
||||
goodsInfo.value.attrList.push({});
|
||||
}
|
||||
|
||||
function handleRemove(index: number) {
|
||||
props.modelValue.attrList.splice(index, 1);
|
||||
goodsInfo.value.attrList.splice(index, 1);
|
||||
}
|
||||
|
||||
function handlePrev() {
|
||||
@@ -147,8 +117,7 @@ function handlePrev() {
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
const form = unref(dataForm);
|
||||
form.validate((valid: any) => {
|
||||
dataFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
emit("next");
|
||||
}
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
<template>
|
||||
<div class="component-container">
|
||||
<div class="component-container__main">
|
||||
<el-cascader-panel
|
||||
ref="categoryRef"
|
||||
:options="categoryOptions"
|
||||
v-model="modelValue.categoryId"
|
||||
:props="{emitPath:false}"
|
||||
@change="handleCategoryChange"
|
||||
|
||||
/>
|
||||
|
||||
<el-cascader-panel ref="categoryRef" :options="categoryOptions" v-model="goodsInfo.categoryId"
|
||||
:props="{ emitPath: false }" @change="handleCategoryChange" />
|
||||
<div style="margin-top: 20px">
|
||||
<el-link type="info" :underline="false" v-show="pathLabels.length>0">您选择的商品分类:</el-link>
|
||||
<el-link type="danger" :underline="false" v-for="(item,index) in pathLabels" style="margin-left: 5px">
|
||||
<el-link type="info" :underline="false" v-show="pathLabels.length > 0">您选择的商品分类:</el-link>
|
||||
<el-link type="danger" :underline="false" v-for="(item, index) in pathLabels" :key="index"
|
||||
style="margin-left: 5px">
|
||||
{{ item }}
|
||||
<CaretRight v-show="index<pathLabels.length-1" style="width: 1em; height:1em;margin-left: 5px"/>
|
||||
<CaretRight v-show="index < pathLabels.length - 1" style="width: 1em; height:1em;margin-left: 5px" />
|
||||
</el-link>
|
||||
</div>
|
||||
|
||||
@@ -26,18 +20,27 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted,nextTick, reactive, ref, toRefs} from "vue";
|
||||
import {ElCascaderPanel, ElMessage} from "element-plus";
|
||||
import {CaretRight} from '@element-plus/icons-vue';
|
||||
import { onMounted, nextTick, reactive, ref, toRefs } from "vue";
|
||||
import { ElCascaderPanel, ElMessage } from "element-plus";
|
||||
import { CaretRight } from '@element-plus/icons-vue';
|
||||
|
||||
// API 引用
|
||||
import {listCascadeCategories} from "@/api/pms/category";
|
||||
import { listCascadeCategories } from "@/api/pms/category";
|
||||
import { computed } from "@vue/reactivity";
|
||||
import { GoodsDetail } from "@/types";
|
||||
|
||||
const emit = defineEmits(['next'])
|
||||
const emit = defineEmits(['next', "update:modelValue"])
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default:{ }
|
||||
default: () => { }
|
||||
}
|
||||
})
|
||||
|
||||
const goodsInfo: any = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -46,12 +49,12 @@ const state = reactive({
|
||||
pathLabels: []
|
||||
})
|
||||
|
||||
const {categoryOptions, pathLabels} = toRefs(state)
|
||||
const { categoryOptions, pathLabels } = toRefs(state)
|
||||
|
||||
function loadData() {
|
||||
listCascadeCategories({}).then(response => {
|
||||
listCascadeCategories().then(response => {
|
||||
state.categoryOptions = response.data
|
||||
if (props.modelValue.id) {
|
||||
if (goodsInfo.value.id) {
|
||||
nextTick(() => {
|
||||
handleCategoryChange()
|
||||
})
|
||||
@@ -63,15 +66,15 @@ const categoryRef = ref(ElCascaderPanel)
|
||||
function handleCategoryChange() {
|
||||
const checkNode = categoryRef.value.getCheckedNodes()[0]
|
||||
state.pathLabels = checkNode.pathLabels // 商品分类选择层级提示
|
||||
props.modelValue.categoryId = checkNode.value
|
||||
goodsInfo.value.categoryId = checkNode.value
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
if (!props.modelValue.categoryId) {
|
||||
if (!goodsInfo.value.categoryId) {
|
||||
ElMessage.warning('请选择商品分类')
|
||||
return false
|
||||
}
|
||||
emit('next' )
|
||||
emit('next')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -81,7 +84,6 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.component-container {
|
||||
&__main {
|
||||
margin: 20px auto
|
||||
|
||||
@@ -1,74 +1,41 @@
|
||||
<template>
|
||||
<div class="component-container">
|
||||
<div class="component-container__main">
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:rules="rules"
|
||||
:model="modelValue"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form ref="dataFormRef" :rules="rules" :model="goodsInfo" label-width="120px">
|
||||
<el-form-item label="商品品牌" prop="brandId">
|
||||
<el-select
|
||||
v-model="modelValue.brandId"
|
||||
style="width: 400px"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in brandOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
<el-select v-model="goodsInfo.brandId" style="width: 400px" clearable>
|
||||
<el-option v-for="item in brandOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品名称" prop="name">
|
||||
<el-input style="width: 400px" v-model="modelValue.name" />
|
||||
<el-input style="width: 400px" v-model="goodsInfo.name" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="原价" prop="originPrice">
|
||||
<el-input style="width: 400px" v-model="modelValue.originPrice" />
|
||||
<el-input style="width: 400px" v-model="goodsInfo.originPrice" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="现价" prop="price">
|
||||
<el-input style="width: 400px" v-model="modelValue.price" />
|
||||
<el-input style="width: 400px" v-model="goodsInfo.price" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品简介">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||
v-model="modelValue.description"
|
||||
/>
|
||||
<el-input type="textarea" :autosize="{ minRows: 3, maxRows: 6 }" v-model="goodsInfo.description" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品相册">
|
||||
<el-card
|
||||
v-for="(item, index) in pictures"
|
||||
:key="index"
|
||||
<el-card v-for="(item, index) in pictures" :key="index"
|
||||
style="width: 170px; display: inline-block; margin-left: 10px;text-align:center"
|
||||
:body-style="{ padding: '10px' }"
|
||||
>
|
||||
:body-style="{ padding: '10px' }">
|
||||
<single-upload v-model="item.url" :show-close="true" />
|
||||
|
||||
<div v-if="item.url">
|
||||
<el-button
|
||||
type="text"
|
||||
class="button"
|
||||
v-if="item.main == true"
|
||||
style="color: #ff4d51"
|
||||
>商品主图</el-button
|
||||
>
|
||||
<el-button
|
||||
type="text"
|
||||
class="button"
|
||||
v-else
|
||||
@click="changeMainPicture(index)"
|
||||
>设为主图</el-button
|
||||
>
|
||||
<el-button type="text" class="button" v-if="item.main == true" style="color: #ff4d51">商品主图</el-button>
|
||||
<el-button type="text" class="button" v-else @click="changeMainPicture(index)">设为主图</el-button>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div v-else>
|
||||
<!-- 占位 -->
|
||||
<el-button type="text" />
|
||||
</div>
|
||||
@@ -76,21 +43,19 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品详情" prop="detail">
|
||||
<editor v-model="modelValue.detail" style="height: 600px" />
|
||||
<editor v-model="goodsInfo.detail" style="height: 600px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="component-container__footer">
|
||||
<el-button @click="handlePrev">上一步,选择商品分类</el-button>
|
||||
<el-button type="primary" @click="handleNext"
|
||||
>下一步,设置商品属性</el-button
|
||||
>
|
||||
<el-button type="primary" @click="handleNext">下一步,设置商品属性</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, toRefs } from "vue";
|
||||
import { computed, onMounted, reactive, ref, toRefs } from "vue";
|
||||
import { ElForm } from "element-plus";
|
||||
|
||||
// API 依赖
|
||||
@@ -100,16 +65,23 @@ import { listBrands } from "@/api/pms/brand";
|
||||
import Editor from "@/components/WangEditor/index.vue";
|
||||
import SingleUpload from "@/components/Upload/SingleUpload.vue";
|
||||
|
||||
const emit = defineEmits(["prev", "next"]);
|
||||
const emit = defineEmits(["prev", "next", "update:modelValue"]);
|
||||
const dataFormRef = ref(ElForm);
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
default: () => { }
|
||||
}
|
||||
});
|
||||
|
||||
const goodsInfo: any = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
brandOptions: [] as Array<any>,
|
||||
// 商品图册
|
||||
@@ -131,17 +103,16 @@ const state = reactive({
|
||||
const { brandOptions, pictures, rules } = toRefs(state);
|
||||
|
||||
function loadData() {
|
||||
listBrands().then(({data}) => {
|
||||
listBrands().then(({ data }) => {
|
||||
state.brandOptions = data;
|
||||
});
|
||||
const goodsInfo = props.modelValue;
|
||||
const goodsId = goodsInfo.id;
|
||||
const goodsId = goodsInfo.value.id;
|
||||
if (goodsId) {
|
||||
const mainPicUrl = goodsInfo.picUrl;
|
||||
const mainPicUrl = goodsInfo.value.picUrl;
|
||||
if (mainPicUrl) {
|
||||
state.pictures.filter((item) => item.main)[0].url = mainPicUrl;
|
||||
}
|
||||
const subPicUrls = goodsInfo.subPicUrls;
|
||||
const subPicUrls = goodsInfo.value.subPicUrls;
|
||||
if (subPicUrls && subPicUrls.length > 0) {
|
||||
for (let i = 1; i <= subPicUrls.length; i++) {
|
||||
state.pictures[i].url = subPicUrls[i - 1];
|
||||
@@ -150,16 +121,6 @@ function loadData() {
|
||||
}
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
state.pictures = [
|
||||
{ url: undefined, main: true }, // main 代表主图,可以切换
|
||||
{ url: undefined, main: false },
|
||||
{ url: undefined, main: false },
|
||||
{ url: undefined, main: false },
|
||||
{ url: undefined, main: false },
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换主图
|
||||
*/
|
||||
@@ -185,13 +146,13 @@ function handleNext() {
|
||||
.filter((item) => item.main == true && item.url)
|
||||
.map((item) => item.url);
|
||||
if (mainPicUrl && mainPicUrl.length > 0) {
|
||||
props.modelValue.picUrl = mainPicUrl[0];
|
||||
goodsInfo.picUrl = mainPicUrl[0];
|
||||
}
|
||||
const subPicUrl = state.pictures
|
||||
.filter((item) => item.main == false && item.url)
|
||||
.map((item) => item.url);
|
||||
if (subPicUrl && subPicUrl.length > 0) {
|
||||
props.modelValue.subPicUrls = subPicUrl;
|
||||
goodsInfo.subPicUrls = subPicUrl;
|
||||
}
|
||||
emit("next");
|
||||
}
|
||||
|
||||
@@ -4,29 +4,13 @@
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<span>商品规格</span>
|
||||
<el-button
|
||||
:icon="Plus"
|
||||
type="success"
|
||||
@click="handleSpecAdd"
|
||||
size="small"
|
||||
style="float: right"
|
||||
>
|
||||
<el-button :icon="Plus" type="success" @click="handleSpecAdd" size="small" style="float: right">
|
||||
添加规格项
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<el-form
|
||||
ref="specFormRef"
|
||||
:model="specForm"
|
||||
:inline="true"
|
||||
size="small"
|
||||
>
|
||||
<el-table
|
||||
ref="specTableRef"
|
||||
:data="specForm.specList"
|
||||
row-key="id"
|
||||
size="small"
|
||||
>
|
||||
<el-form ref="specFormRef" :model="specForm" :inline="true" size="small">
|
||||
<el-table ref="specTableRef" :data="specForm.specList" row-key="id" size="small">
|
||||
<el-table-column align="center" width="50">
|
||||
<template>
|
||||
<svg-icon class="drag-handler" icon-class="drag" />
|
||||
@@ -34,66 +18,31 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="规格名" width="200">
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="'specList[' + scope.$index + '].name'"
|
||||
:rules="rules.spec.name"
|
||||
>
|
||||
<el-input
|
||||
type="text"
|
||||
v-model="scope.row.name"
|
||||
size="small"
|
||||
@input="handleSpecChange()"
|
||||
/>
|
||||
<el-form-item :prop="'specList[' + scope.$index + '].name'" :rules="rules.spec.name">
|
||||
<el-input type="text" v-model="scope.row.name" size="small" @input="handleSpecChange()" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column>
|
||||
<template #header>
|
||||
规格值
|
||||
<el-link
|
||||
type="danger"
|
||||
style="font-size: 12px"
|
||||
:underline="false"
|
||||
>(默认第一条规格包含图片)</el-link
|
||||
>
|
||||
<el-link type="danger" style="font-size: 12px" :underline="false">(默认第一条规格包含图片)</el-link>
|
||||
</template>
|
||||
|
||||
<template #default="scope">
|
||||
<div
|
||||
v-for="item in scope.row.values"
|
||||
:key="item.id"
|
||||
style="margin-right: 15px; display: inline-block"
|
||||
>
|
||||
<el-tag
|
||||
size="small"
|
||||
closable
|
||||
:type="colors[scope.$index % colors.length]"
|
||||
@close="handleSpecValueRemove(scope.$index, item.id)"
|
||||
>
|
||||
<div v-for="item in scope.row.values" :key="item.id" style="margin-right: 15px; display: inline-block">
|
||||
<el-tag size="small" closable :type="(colors[scope.$index % colors.length] as any)"
|
||||
@close="handleSpecValueRemove(scope.$index, item.id)">
|
||||
{{ item.value }}
|
||||
</el-tag>
|
||||
<single-upload
|
||||
v-model="item.picUrl"
|
||||
v-if="scope.$index == 0"
|
||||
style="margin-top: 5px"
|
||||
/>
|
||||
<single-upload v-model="item.picUrl" v-if="scope.$index == 0" style="margin-top: 5px" />
|
||||
</div>
|
||||
|
||||
<el-input
|
||||
v-if="tagInputs.length > 0 && tagInputs[scope.$index].visible"
|
||||
v-model="tagInputs[scope.$index].value"
|
||||
@keyup.enter="handleSpecValueInput(scope.$index)"
|
||||
@blur="handleSpecValueInput(scope.$index)"
|
||||
style="width: 80px; vertical-align: top"
|
||||
size="small"
|
||||
/>
|
||||
<el-button
|
||||
v-else
|
||||
@click="handleSpecValueAdd(scope.$index)"
|
||||
:icon="Plus"
|
||||
style="vertical-align: top"
|
||||
size="small"
|
||||
>
|
||||
<el-input v-if="tagInputs.length > 0 && tagInputs[scope.$index].visible"
|
||||
v-model="tagInputs[scope.$index].value" @keyup.enter="handleSpecValueInput(scope.$index)"
|
||||
@blur="handleSpecValueInput(scope.$index)" style="width: 80px; vertical-align: top" size="small" />
|
||||
<el-button v-else @click="handleSpecValueAdd(scope.$index)" :icon="Plus" style="vertical-align: top"
|
||||
size="small">
|
||||
添加规格值
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -101,14 +50,8 @@
|
||||
|
||||
<el-table-column width="60" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Minus"
|
||||
size="small"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleSpecRemove(scope.$index)"
|
||||
/>
|
||||
<el-button type="danger" :icon="Minus" size="small" circle plain
|
||||
@click.stop="handleSpecRemove(scope.$index)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -120,39 +63,23 @@
|
||||
<span>商品库存</span>
|
||||
</template>
|
||||
<el-form ref="skuFormRef" :model="skuForm" size="small" :inline="true">
|
||||
<el-table
|
||||
:data="skuForm.skuList"
|
||||
:span-method="objectSpanMethod"
|
||||
highlight-current-row
|
||||
size="small"
|
||||
border
|
||||
>
|
||||
<el-table-column
|
||||
v-for="(title, index) in specTitles"
|
||||
:key="index"
|
||||
align="center"
|
||||
:prop="'specValue' + (index + 1)"
|
||||
:label="title"
|
||||
>
|
||||
<el-table :data="skuForm.skuList" :span-method="(objectSpanMethod as any)" highlight-current-row size="small"
|
||||
border>
|
||||
<el-table-column v-for="(title, index) in specTitles" :key="index" align="center"
|
||||
:prop="'specValue' + (index + 1)" :label="title">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="商品编码" align="center">
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="'skuList[' + scope.$index + '].skuSn'"
|
||||
:rules="rules.sku.skuSn"
|
||||
>
|
||||
<el-input v-model="scope.row.skuSn"/>
|
||||
<el-form-item :prop="'skuList[' + scope.$index + '].skuSn'" :rules="rules.sku.skuSn">
|
||||
<el-input v-model="scope.row.skuSn" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="价格" align="center">
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="'skuList[' + scope.$index + '].price'"
|
||||
:rules="rules.sku.price"
|
||||
>
|
||||
<el-form-item :prop="'skuList[' + scope.$index + '].price'" :rules="rules.sku.price">
|
||||
<el-input v-model="scope.row.price" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -160,10 +87,7 @@
|
||||
|
||||
<el-table-column label="库存" align="center">
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="'skuList[' + scope.$index + '].stockNum'"
|
||||
:rules="rules.sku.stockNum"
|
||||
>
|
||||
<el-form-item :prop="'skuList[' + scope.$index + '].stockNum'" :rules="rules.sku.stockNum">
|
||||
<el-input v-model="scope.row.stockNum" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -179,17 +103,15 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
computed,
|
||||
getCurrentInstance,
|
||||
nextTick,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRefs,
|
||||
unref,
|
||||
watch,
|
||||
watch
|
||||
} from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Plus, Minus } from "@element-plus/icons-vue";
|
||||
@@ -204,32 +126,41 @@ import SvgIcon from "@/components/SvgIcon/index.vue";
|
||||
import SingleUpload from "@/components/Upload/SingleUpload.vue";
|
||||
// import Sortable from 'sortablejs'
|
||||
|
||||
const categoryId = computed(() => props.modelValue.categoryId);
|
||||
const emit = defineEmits(["prev", "next"]);
|
||||
|
||||
const proxy = getCurrentInstance();
|
||||
const emit = defineEmits(["prev", "next", 'update:modelValue']);
|
||||
|
||||
/* const proxy = getCurrentInstance(); */
|
||||
const router = useRouter();
|
||||
|
||||
const specTableRef = ref(ElTable);
|
||||
/* const specTableRef = ref(ElTable); */
|
||||
const specFormRef = ref(ElForm);
|
||||
const skuFormRef = ref(ElForm);
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const goodsInfo: any = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
specForm: {
|
||||
specList: [],
|
||||
specList: [] as any[],
|
||||
},
|
||||
skuForm: {
|
||||
skuList: [],
|
||||
skuList: [] as any[],
|
||||
},
|
||||
// 规格项表格标题
|
||||
specTitles: [],
|
||||
specTitles: [] as any[],
|
||||
rules: {
|
||||
spec: {
|
||||
name: [{ required: true, message: "请输入规格名称", trigger: "blur" }],
|
||||
@@ -245,56 +176,51 @@ const state = reactive({
|
||||
},
|
||||
colors: ["", "success", "warning", "danger"],
|
||||
tagInputs: [{ value: undefined, visible: false }], // 规格值标签临时值和显隐控制
|
||||
loading: undefined,
|
||||
});
|
||||
|
||||
const { specForm, skuForm, specTitles, rules, colors, tagInputs, loading } =
|
||||
const { specForm, skuForm, specTitles, rules, colors, tagInputs } =
|
||||
toRefs(state);
|
||||
|
||||
watch(
|
||||
categoryId,
|
||||
(value) => {
|
||||
|
||||
// 商品编辑不加载分类下的规格
|
||||
const spuId = props.modelValue.id;
|
||||
if (spuId) {
|
||||
return false;
|
||||
}
|
||||
if (value) {
|
||||
// type=1 商品分类下的规格
|
||||
listAttributes({ categoryId: value, type: 1 }).then((response) => {
|
||||
const specList = response.data;
|
||||
if (specList && specList.length > 0) {
|
||||
specList.forEach((item) => {
|
||||
state.specForm.specList.push({
|
||||
name: item.name,
|
||||
values: [],
|
||||
});
|
||||
watch(() => goodsInfo.value.categoryId, (newVal) => {
|
||||
// 商品编辑不加载分类下的规格
|
||||
const goodsId = goodsInfo.value.id;
|
||||
if (goodsId) {
|
||||
return false;
|
||||
}
|
||||
if (newVal) {
|
||||
// type=1 商品分类下的规格
|
||||
listAttributes({ categoryId: newVal, type: 1 }).then((response) => {
|
||||
const specList = response.data;
|
||||
if (specList && specList.length > 0) {
|
||||
specList.forEach((item: any) => {
|
||||
state.specForm.specList.push({
|
||||
name: item.name,
|
||||
values: [],
|
||||
});
|
||||
loadData();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
loadData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
})
|
||||
|
||||
|
||||
|
||||
watch(state.specForm.specList,(value)=>{
|
||||
watch(state.specForm.specList, () => {
|
||||
generateSkuList()
|
||||
})
|
||||
|
||||
function loadData() {
|
||||
props.modelValue.specList.forEach((specItem) => {
|
||||
goodsInfo.value.specList.forEach((specItem: any) => {
|
||||
const specIndex = state.specForm.specList.findIndex(
|
||||
(item) => item.name == specItem.name
|
||||
(item: any) => item.name == specItem.name
|
||||
);
|
||||
if (specIndex > -1) {
|
||||
state.specForm.specList[specIndex].values.push({
|
||||
(state.specForm.specList[specIndex] as any).values.push({
|
||||
id: specItem.id,
|
||||
value: specItem.value,
|
||||
picUrl: specItem.picUrl,
|
||||
@@ -315,7 +241,7 @@ function loadData() {
|
||||
}
|
||||
|
||||
// SKU规格ID拼接字符串处理
|
||||
props.modelValue.skuList.forEach((sku) => {
|
||||
goodsInfo.value.skuList.forEach((sku: any) => {
|
||||
sku.specIdArr = sku.specIds.split("_");
|
||||
});
|
||||
|
||||
@@ -335,7 +261,7 @@ function loadData() {
|
||||
*/
|
||||
function handleSpecChange() {
|
||||
const specList = JSON.parse(JSON.stringify(state.specForm.specList));
|
||||
state.specTitles = specList.map((item) => item.name);
|
||||
state.specTitles = specList.map((item: any) => item.name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,23 +306,23 @@ function handleSpecReorder() {
|
||||
*/
|
||||
function generateSkuList() {
|
||||
// 如果规格为空,生成SKU列表为空
|
||||
if(state.specForm.specList.length==0){
|
||||
state.skuForm.skuList = [];
|
||||
if (state.specForm.specList.length == 0) {
|
||||
state.skuForm.skuList = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const specList = JSON.parse(
|
||||
JSON.stringify(
|
||||
state.specForm.specList.filter((item) => item.values&&item.values.length > 0)
|
||||
state.specForm.specList.filter((item) => item.values && item.values.length > 0)
|
||||
)
|
||||
); // 深拷贝,取有属性的规格项,否则笛卡尔积运算得到的SKU列表值为空
|
||||
|
||||
|
||||
const skuList = specList.reduce(
|
||||
(acc, curr) => {
|
||||
let result = [];
|
||||
acc.forEach((item) => {
|
||||
(acc: any, curr: any) => {
|
||||
let result = [] as any[];
|
||||
acc.forEach((item: any) => {
|
||||
// curr => { 'id':1,'name':'颜色','values':[{id:1,value:'白色'},{id:2,value:'黑色'},{id:3,value:'蓝色'}] }
|
||||
curr.values.forEach((v) => {
|
||||
curr.values.forEach((v: any) => {
|
||||
// v=>{id:1,value:'白色'}
|
||||
let temp = Object.assign({}, item);
|
||||
temp.specValues += v.value + "_"; // 规格值拼接
|
||||
@@ -409,17 +335,17 @@ function generateSkuList() {
|
||||
[{ specValues: "", specIds: "" }]
|
||||
);
|
||||
|
||||
skuList.forEach((item) => {
|
||||
skuList.forEach((item: any) => {
|
||||
item.specIds = item.specIds.substring(0, item.specIds.length - 1);
|
||||
item.name = item.specValues
|
||||
.substring(0, item.specValues.length - 1)
|
||||
.replaceAll("_", " ");
|
||||
const specIdArr = item.specIds.split("|");
|
||||
const skus = props.modelValue.skuList.filter(
|
||||
(sku) =>
|
||||
const skus = goodsInfo.value.skuList.filter(
|
||||
(sku: any) =>
|
||||
sku.specIdArr.length === specIdArr.length &&
|
||||
sku.specIdArr.every((a) => specIdArr.some((b) => a === b)) &&
|
||||
specIdArr.every((x) => sku.specIdArr.some((y) => x === y))
|
||||
sku.specIdArr.every((a: any) => specIdArr.some((b: any) => a === b)) &&
|
||||
specIdArr.every((x: any) => sku.specIdArr.some((y: any) => x === y))
|
||||
); // 数据库的SKU列表
|
||||
|
||||
if (skus && skus.length > 0) {
|
||||
@@ -432,12 +358,12 @@ function generateSkuList() {
|
||||
const specValueArr = item.specValues
|
||||
.substring(0, item.specValues.length - 1)
|
||||
.split("_"); // ['黑','6+128G','官方标配']
|
||||
specValueArr.forEach((v, i) => {
|
||||
specValueArr.forEach((v: any, i: any) => {
|
||||
const key = "specValue" + (i + 1);
|
||||
item[key] = v;
|
||||
if (i == 0 && state.specForm.specList.length > 0) {
|
||||
const valueIndex = state.specForm.specList[0].values.findIndex(
|
||||
(specValue) => specValue.value == v
|
||||
(specValue: any) => specValue.value == v
|
||||
);
|
||||
if (valueIndex > -1) {
|
||||
item.picUrl = state.specForm.specList[0].values[valueIndex].picUrl;
|
||||
@@ -456,7 +382,7 @@ function handleSpecAdd() {
|
||||
ElMessage.warning("最多支持3组规格");
|
||||
return;
|
||||
}
|
||||
state.specForm.specList.push({values:[]});
|
||||
state.specForm.specList.push({ values: [] });
|
||||
state.tagInputs.push({ value: undefined, visible: false });
|
||||
handleSpecReorder();
|
||||
}
|
||||
@@ -465,7 +391,7 @@ function handleSpecAdd() {
|
||||
* 删除规格
|
||||
* @param index
|
||||
*/
|
||||
function handleSpecRemove(index) {
|
||||
function handleSpecRemove(index: any) {
|
||||
state.specForm.specList.splice(index, 1);
|
||||
state.tagInputs.splice(index, 1);
|
||||
generateSkuList();
|
||||
@@ -478,7 +404,7 @@ function handleSpecRemove(index) {
|
||||
*
|
||||
* @param specIndex
|
||||
*/
|
||||
function handleSpecValueAdd(specIndex) {
|
||||
function handleSpecValueAdd(specIndex: any) {
|
||||
state.tagInputs[specIndex].visible = true;
|
||||
}
|
||||
|
||||
@@ -488,10 +414,10 @@ function handleSpecValueAdd(specIndex) {
|
||||
* @param rowIndex
|
||||
* @param specValueId
|
||||
*/
|
||||
function handleSpecValueRemove(rowIndex, specValueId) {
|
||||
function handleSpecValueRemove(rowIndex: any, specValueId: any) {
|
||||
const specList = JSON.parse(JSON.stringify(state.specForm.specList));
|
||||
const removeIndex = specList[rowIndex].values
|
||||
.map((item) => item.id)
|
||||
.map((item: any) => item.id)
|
||||
.indexOf(specValueId);
|
||||
specList[rowIndex].values.splice(removeIndex, 1);
|
||||
state.specForm.specList = specList;
|
||||
@@ -503,13 +429,13 @@ function handleSpecValueRemove(rowIndex, specValueId) {
|
||||
/**
|
||||
* 规格值输入
|
||||
*/
|
||||
function handleSpecValueInput(rowIndex) {
|
||||
function handleSpecValueInput(rowIndex: any) {
|
||||
const currSpecValue = state.tagInputs[rowIndex].value;
|
||||
const specValues = state.specForm.specList[rowIndex].values;
|
||||
if (
|
||||
specValues &&
|
||||
specValues.length > 0 &&
|
||||
specValues.map((item) => item.value).includes(currSpecValue)
|
||||
specValues.map((item: any) => item.value).includes(currSpecValue)
|
||||
) {
|
||||
ElMessage.warning("规格值重复,请重新输入");
|
||||
return false;
|
||||
@@ -518,12 +444,11 @@ function handleSpecValueInput(rowIndex) {
|
||||
if (specValues && specValues.length > 0) {
|
||||
// 临时规格值ID tid_1_1
|
||||
let maxSpecValueIndex = specValues
|
||||
.filter((item) => item.id.includes("tid_"))
|
||||
.map((item) => item.id.split("_")[2])
|
||||
.reduce((acc, curr) => {
|
||||
.filter((item: any) => item.id.includes("tid_"))
|
||||
.map((item: any) => item.id.split("_")[2])
|
||||
.reduce((acc: any, curr: any) => {
|
||||
return acc > curr ? acc : curr;
|
||||
}, 0);
|
||||
console.log("maxSpecValueIndex", maxSpecValueIndex);
|
||||
state.specForm.specList[rowIndex].values[specValues.length] = {
|
||||
value: currSpecValue,
|
||||
id: "tid_" + (rowIndex + 1) + "_" + ++maxSpecValueIndex,
|
||||
@@ -545,7 +470,7 @@ function handleSpecValueInput(rowIndex) {
|
||||
* @param cellObj 单元格对象
|
||||
*/
|
||||
|
||||
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
|
||||
const objectSpanMethod = ({ rowIndex, columnIndex }: any) => {
|
||||
let mergeRows = [1, 1, 1]; // 分别对应规格1、规格2、规格3列合并的行数
|
||||
const specLen = state.specForm.specList.filter(
|
||||
(item) => item.values && item.values.length > 0
|
||||
@@ -589,20 +514,18 @@ function submitForm() {
|
||||
ElMessage.warning("未添加商品库存");
|
||||
return false;
|
||||
}
|
||||
specFormRef.value.validate((specValid) => {
|
||||
specFormRef.value.validate((specValid: any) => {
|
||||
if (specValid) {
|
||||
skuFormRef.value.validate((skuValid) => {
|
||||
skuFormRef.value.validate((skuValid: any) => {
|
||||
if (skuValid) {
|
||||
// openFullScreen()
|
||||
|
||||
// 重组商品的规格和SKU列表
|
||||
let submitsData = Object.assign({}, props.modelValue);
|
||||
let submitsData = Object.assign({}, goodsInfo.value);
|
||||
delete submitsData.specList;
|
||||
delete submitsData.skuList;
|
||||
|
||||
let specList = [];
|
||||
let specList = [] as any[];
|
||||
state.specForm.specList.forEach((item) => {
|
||||
item.values.forEach((value) => {
|
||||
item.values.forEach((value: any) => {
|
||||
value.name = item.name;
|
||||
});
|
||||
specList = specList.concat(item.values);
|
||||
@@ -613,43 +536,35 @@ function submitForm() {
|
||||
submitsData.originPrice *= 100;
|
||||
|
||||
let skuList = JSON.parse(JSON.stringify(state.skuForm.skuList));
|
||||
skuList.map((item) => {
|
||||
skuList.map((item: any) => {
|
||||
item.price *= 100;
|
||||
return item;
|
||||
});
|
||||
submitsData.skuList = skuList;
|
||||
console.log("提交数据", submitsData);
|
||||
const goodsId = props.modelValue.id;
|
||||
const goodsId = goodsInfo.value.id;
|
||||
if (goodsId) {
|
||||
// 编辑商品提交
|
||||
updateGoods(goodsId, submitsData).then(
|
||||
(res) => {
|
||||
() => {
|
||||
router.push({ path: "/pms/goods" });
|
||||
ElNotification({
|
||||
title: "提示",
|
||||
message: "编辑商品成功",
|
||||
type: "success",
|
||||
});
|
||||
//closeFullScreen()
|
||||
},
|
||||
(err) => {
|
||||
//closeFullScreen()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// 新增商品提交
|
||||
addGoods(submitsData).then(
|
||||
(response) => {
|
||||
() => {
|
||||
router.push({ path: "/pms/goods" });
|
||||
ElNotification({
|
||||
title: "提示",
|
||||
message: "新增商品成功",
|
||||
type: "success",
|
||||
});
|
||||
// closeFullScreen()
|
||||
},
|
||||
(err) => {
|
||||
// closeFullScreen()
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -659,8 +574,8 @@ function submitForm() {
|
||||
});
|
||||
}
|
||||
|
||||
function openFullScreen() {
|
||||
state.loading = proxy.$loading({
|
||||
/* function openFullScreen() {
|
||||
state.loading = (proxy as any).$loading({
|
||||
lock: true,
|
||||
text: "商品信息提交中,请等待...",
|
||||
spinner: "el-icon-loading",
|
||||
@@ -670,18 +585,14 @@ function openFullScreen() {
|
||||
|
||||
function closeFullScreen() {
|
||||
if (state.loading) {
|
||||
state.loading.close();
|
||||
(state.loading as any).close();
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
function handlePrev() {
|
||||
emit("prev");
|
||||
}
|
||||
|
||||
function handNext() {
|
||||
emit("next");
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
@@ -704,7 +615,7 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.el-form--inline .el-form-item{
|
||||
.el-form--inline .el-form-item {
|
||||
margin-top: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,108 +1,77 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-steps :active="active" process-status="finish" finish-status="success" simple>
|
||||
<el-step title="选择商品分类"/>
|
||||
<el-step title="填写商品信息"/>
|
||||
<el-step title="设置商品属性"/>
|
||||
<el-step title="设置商品库存"/>
|
||||
<el-step title="选择商品分类" />
|
||||
<el-step title="填写商品信息" />
|
||||
<el-step title="设置商品属性" />
|
||||
<el-step title="设置商品库存" />
|
||||
</el-steps>
|
||||
|
||||
<goods-category
|
||||
v-show="active==0"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next"
|
||||
/>
|
||||
<GoodsCategory v-show="active == 0" v-model="goodsInfo" v-if="loaded == true" @prev="prev" @next="next" />
|
||||
<GoodsInfo v-show="active == 1" v-model="goodsInfo" v-if="loaded == true" @prev="prev" @next="next" />
|
||||
<GoodsAttribute v-show="active == 2" v-model="goodsInfo" v-if="loaded == true" @prev="prev" @next="next" />
|
||||
<GoodsStock v-show="active == 3" v-model="goodsInfo" v-if="loaded == true" @prev="prev" @next="next" />
|
||||
|
||||
<goods-info
|
||||
v-show="active==1"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next"
|
||||
/>
|
||||
<goods-attribute
|
||||
v-show="active==2"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next"
|
||||
/>
|
||||
|
||||
<goods-stock
|
||||
v-show="active==3"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, toRefs } from "vue";
|
||||
|
||||
import GoodsCategory from "./components/GoodsCategory.vue";
|
||||
import GoodsInfo from "./components/GoodsInfo.vue";
|
||||
import GoodsAttribute from "./components/GoodsAttribute.vue";
|
||||
import GoodsStock from "./components/GoodsStock.vue";
|
||||
|
||||
import {getGoodsFormDetail} from "@/api/pms/goods";
|
||||
import { getGoodsDetail } from "@/api/pms/goods";
|
||||
import { useRoute } from "vue-router";
|
||||
import { GoodsDetail } from "@/types";
|
||||
|
||||
export default {
|
||||
name: "goods-detail",
|
||||
components: {GoodsStock, GoodsCategory, GoodsInfo, GoodsAttribute},
|
||||
props: ['goodsId'],
|
||||
data() {
|
||||
return {
|
||||
loaded: false,
|
||||
active: 0,
|
||||
goods: {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
categoryId: undefined,
|
||||
brandId: undefined,
|
||||
originPrice: undefined,
|
||||
price: undefined,
|
||||
picUrl: undefined,
|
||||
album: undefined,
|
||||
description: undefined,
|
||||
detail: undefined,
|
||||
attrList: [],
|
||||
specList: [],
|
||||
skuList: []
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
const goodsId = this.$route.query.goodsId
|
||||
console.log('goodsId',goodsId)
|
||||
if (goodsId) {
|
||||
getGoodsFormDetail(goodsId).then(response => {
|
||||
this.goods = response.data
|
||||
this.goods.originPrice = this.goods.originPrice / 100
|
||||
this.goods.price = this.goods.price / 100
|
||||
this.loaded = true
|
||||
})
|
||||
} else {
|
||||
this.loaded = true
|
||||
}
|
||||
},
|
||||
prev() {
|
||||
if (this.active-- <= 0) {
|
||||
this.active = 0;
|
||||
}
|
||||
},
|
||||
next() {
|
||||
if (this.active++ >= 3) {
|
||||
this.active = 0;
|
||||
}
|
||||
}
|
||||
const route = useRoute();
|
||||
const props = defineProps({
|
||||
goodsId: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
}
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
loaded: false,
|
||||
active: 0,
|
||||
goodsInfo: {} as GoodsDetail
|
||||
});
|
||||
|
||||
const { loaded, active, goodsInfo } = toRefs(state)
|
||||
|
||||
function loadData() {
|
||||
const goodsId = route.query.goodsId as string
|
||||
|
||||
if (goodsId) {
|
||||
getGoodsDetail(goodsId).then((response) => {
|
||||
state.goodsInfo = response.data
|
||||
state.goodsInfo.originPrice = state.goodsInfo.originPrice / 100
|
||||
state.goodsInfo.price = state.goodsInfo.price / 100
|
||||
state.loaded = true
|
||||
})
|
||||
} else {
|
||||
state.loaded = true
|
||||
}
|
||||
}
|
||||
|
||||
function prev() {
|
||||
if (state.active-- <= 0) {
|
||||
state.active = 0;
|
||||
}
|
||||
}
|
||||
function next() {
|
||||
if (state.active++ >= 3) {
|
||||
state.active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<el-cascader
|
||||
v-model="queryParams.categoryId"
|
||||
placeholder="商品分类"
|
||||
:props="{ emitPath: false, expandTrigger: 'hover' }"
|
||||
:props="{ emitPath: false }"
|
||||
:options="categoryOptions"
|
||||
clearable
|
||||
style="width: 300px"
|
||||
@@ -177,8 +177,6 @@ const state = reactive({
|
||||
|
||||
const {
|
||||
loading,
|
||||
ids,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
goodsList,
|
||||
|
||||
@@ -3,40 +3,20 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="广告标题"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<el-input v-model="queryParams.title" placeholder="广告标题" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="advertList"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
>
|
||||
<el-table v-loading="loading" :data="advertList" @selection-change="handleSelectionChange" border>
|
||||
<el-table-column type="selection" min-width="5" align="center" />
|
||||
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||
<el-table-column prop="title" min-width="100" label="广告标题" />
|
||||
@@ -45,10 +25,7 @@
|
||||
<el-popover placement="right" :width="400" trigger="hover">
|
||||
<img :src="scope.row.picUrl" width="400" height="400" />
|
||||
<template #reference>
|
||||
<img
|
||||
:src="scope.row.picUrl"
|
||||
style="max-height: 60px; max-width: 60px"
|
||||
/>
|
||||
<img :src="scope.row.picUrl" style="max-height: 60px; max-width: 60px" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
@@ -64,57 +41,27 @@
|
||||
<el-table-column prop="sort" label="排序" width="80" />
|
||||
<el-table-column label="操作" align="center" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleUpdate(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页工具条 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
|
||||
<!-- 表单弹窗 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="700px">
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||
<el-form-item label="广告标题" prop="title">
|
||||
<el-input v-model="formData.title" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="有效期" prop="beginTime">
|
||||
<el-date-picker
|
||||
v-model="formData.beginTime"
|
||||
placeholder="开始时间"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<el-date-picker v-model="formData.beginTime" placeholder="开始时间" value-format="YYYY-MM-DD" />
|
||||
~
|
||||
<el-date-picker
|
||||
v-model="formData.endTime"
|
||||
placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<el-date-picker v-model="formData.endTime" placeholder="结束时间" value-format="YYYY-MM-DD" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="广告图片" prop="picUrl">
|
||||
@@ -152,7 +99,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, toRefs, unref } from "vue";
|
||||
import { onMounted, reactive, ref, toRefs } from "vue";
|
||||
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
import SingleUpload from "@/components/Upload/SingleUpload.vue";
|
||||
@@ -194,7 +141,6 @@ const state = reactive({
|
||||
|
||||
const {
|
||||
loading,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
advertList,
|
||||
@@ -206,7 +152,7 @@ const {
|
||||
|
||||
function handleQuery() {
|
||||
state.loading = true;
|
||||
listAdvertPages(state.queryParams).then(({data}) => {
|
||||
listAdvertPages(state.queryParams).then(({ data }) => {
|
||||
state.advertList = data.list;
|
||||
state.total = data.total;
|
||||
state.loading = false;
|
||||
@@ -225,7 +171,6 @@ function handleSelectionChange(selection: any) {
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
resetForm();
|
||||
state.dialog = {
|
||||
title: "添加广告",
|
||||
visible: true,
|
||||
@@ -248,13 +193,13 @@ function submitForm() {
|
||||
if (valid) {
|
||||
const avertId = state.formData.id;
|
||||
if (avertId) {
|
||||
updateAdvert(avertId, state.formData).then((response) => {
|
||||
updateAdvert(avertId, state.formData).then(() => {
|
||||
ElMessage.success("修改成功");
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addAdvert(state.formData).then((response) => {
|
||||
addAdvert(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
cancel();
|
||||
handleQuery();
|
||||
@@ -264,16 +209,9 @@ function submitForm() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置表单
|
||||
*/
|
||||
function resetForm() {
|
||||
function cancel() {
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
resetForm();
|
||||
state.dialog.visible = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,43 +3,23 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="clientId">
|
||||
<el-input
|
||||
v-model="queryParams.clientId"
|
||||
placeholder="输入客户端ID"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<el-input v-model="queryParams.clientId" placeholder="输入客户端ID" clearable style="width: 240px"
|
||||
@keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="clientList"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table v-loading="loading" :data="clientList" border @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" type="index" width="55" align="center" />
|
||||
<el-table-column label="客户端ID" prop="clientId" width="200" />
|
||||
@@ -47,69 +27,33 @@
|
||||
<el-table-column label="域" width="100" prop="scope" />
|
||||
<el-table-column label="自动放行" prop="autoapprove" width="100" />
|
||||
<el-table-column label="授权方式" prop="authorizedGrantTypes" />
|
||||
<el-table-column
|
||||
label="认证令牌时效(单位:秒)"
|
||||
width="200"
|
||||
prop="accessTokenValidity"
|
||||
/>
|
||||
<el-table-column
|
||||
label="刷新令牌时效(单位:秒)"
|
||||
width="200"
|
||||
prop="refreshTokenValidity"
|
||||
/>
|
||||
<el-table-column label="认证令牌时效(单位:秒)" width="200" prop="accessTokenValidity" />
|
||||
<el-table-column label="刷新令牌时效(单位:秒)" width="200" prop="refreshTokenValidity" />
|
||||
<el-table-column label="操作" align="center" width="120">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleUpdate(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页工具条 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
|
||||
<!-- 表单弹窗 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="700px">
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户端ID" prop="clientId">
|
||||
<el-input
|
||||
v-model="formData.clientId"
|
||||
placeholder="请输入客户端ID"
|
||||
/>
|
||||
<el-input v-model="formData.clientId" placeholder="请输入客户端ID" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户端密钥" prop="clientSecret">
|
||||
<el-input
|
||||
v-model="formData.clientSecret"
|
||||
placeholder="请输入客户端密钥"
|
||||
/>
|
||||
<el-input v-model="formData.clientSecret" placeholder="请输入客户端密钥" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -132,11 +76,9 @@
|
||||
|
||||
<el-form-item label="授权方式" prop="authorizedGrantTypes">
|
||||
<el-checkbox-group v-model="checkedAuthorizedGrantTypes">
|
||||
<el-checkbox
|
||||
v-for="item in authorizedGrantTypesOptions"
|
||||
:key="item.value"
|
||||
:label="item.value"
|
||||
>{{ item.label }}
|
||||
<el-checkbox v-for="item in authorizedGrantTypesOptions" :key="item.value" :label="item.value">{{
|
||||
item.label
|
||||
}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
@@ -144,19 +86,13 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="认证令牌时效" prop="accessTokenValidity">
|
||||
<el-input
|
||||
v-model="formData.accessTokenValidity"
|
||||
placeholder="请输入认证令牌时效"
|
||||
/>
|
||||
<el-input v-model="formData.accessTokenValidity" placeholder="请输入认证令牌时效" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="刷新令牌时效" prop="refreshTokenValidity">
|
||||
<el-input
|
||||
v-model="formData.refreshTokenValidity"
|
||||
placeholder="请输入刷新令牌时效"
|
||||
/>
|
||||
<el-input v-model="formData.refreshTokenValidity" placeholder="请输入刷新令牌时效" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -164,29 +100,19 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="回调地址" prop="webServerRedirectUri">
|
||||
<el-input
|
||||
v-model="formData.webServerRedirectUri"
|
||||
placeholder="请输入回调地址"
|
||||
/>
|
||||
<el-input v-model="formData.webServerRedirectUri" placeholder="请输入回调地址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="权限" prop="authorities">
|
||||
<el-input
|
||||
v-model="formData.authorities"
|
||||
placeholder="请输入权限"
|
||||
/>
|
||||
<el-input v-model="formData.authorities" placeholder="请输入权限" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="扩展信息" prop="additionalInformation">
|
||||
<el-input
|
||||
v-model="formData.additionalInformation"
|
||||
type="textarea"
|
||||
placeholder="JSON格式"
|
||||
/>
|
||||
<el-input v-model="formData.additionalInformation" type="textarea" placeholder="JSON格式" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -250,7 +176,6 @@ const state = reactive({
|
||||
const {
|
||||
loading,
|
||||
ids,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
clientList,
|
||||
@@ -318,7 +243,7 @@ function submitForm() {
|
||||
state.checkedAuthorizedGrantTypes.join(",");
|
||||
if (state.dialog.type == "edit") {
|
||||
updateClient(state.formData.clientId, state.formData).then(
|
||||
(response) => {
|
||||
() => {
|
||||
ElMessage.success("修改成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
@@ -326,7 +251,7 @@ function submitForm() {
|
||||
}
|
||||
);
|
||||
} else {
|
||||
addClient(state.formData).then((response) => {
|
||||
addClient(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
cancel();
|
||||
handleQuery();
|
||||
|
||||
@@ -179,7 +179,6 @@ const state = reactive({
|
||||
ids: [] as number[],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
disabled: false,
|
||||
loading: true,
|
||||
// 表格树数据
|
||||
deptList: [] as DeptItem[],
|
||||
@@ -205,9 +204,7 @@ const state = reactive({
|
||||
});
|
||||
|
||||
const {
|
||||
ids,
|
||||
single,
|
||||
disabled,
|
||||
loading,
|
||||
deptList,
|
||||
deptOptions,
|
||||
@@ -257,14 +254,6 @@ async function loadDeptOptions() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单重置
|
||||
**/
|
||||
function resetForm() {
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加部门
|
||||
*/
|
||||
@@ -300,15 +289,15 @@ function submitForm() {
|
||||
dataForm.validate((valid: any) => {
|
||||
if (valid) {
|
||||
if (state.formData.id) {
|
||||
updateDept(state.formData.id, state.formData).then((res: any) => {
|
||||
updateDept(state.formData.id, state.formData).then(() => {
|
||||
ElMessage.success("修改成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addDept(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
}
|
||||
@@ -345,7 +334,8 @@ function handleDelete(row: any) {
|
||||
* 取消/关闭弹窗
|
||||
**/
|
||||
function cancel() {
|
||||
resetForm();
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
state.dialog.visible = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,43 +3,23 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="state.queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
:disabled="state.multiple"
|
||||
@click="handleDelete"
|
||||
>删除
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" :icon="Delete" :disabled="state.multiple" @click="handleDelete">删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="name">
|
||||
<el-input
|
||||
v-model="state.queryParams.name"
|
||||
placeholder="字典名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<el-input v-model="state.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="resetForm">重置</el-button>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery()">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery()">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
highlight-current-row
|
||||
:data="dictList"
|
||||
v-loading="loading"
|
||||
@row-click="handleRowClick"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
>
|
||||
<el-table highlight-current-row :data="dictList" v-loading="loading" @row-click="handleRowClick"
|
||||
@selection-change="handleSelectionChange" border>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="字典名称" prop="name" width="120" />
|
||||
<el-table-column label="字典编码" prop="code" />
|
||||
@@ -52,45 +32,18 @@
|
||||
|
||||
<el-table-column label="操作" align="center" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleUpdate(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
|
||||
<!-- 弹窗表单 -->
|
||||
<el-dialog
|
||||
:title="dialog.title"
|
||||
v-model="dialog.visible"
|
||||
width="500px"
|
||||
@close="cancel"
|
||||
>
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" @close="cancel">
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="80px">
|
||||
<el-form-item label="字典名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入字典名称" />
|
||||
</el-form-item>
|
||||
@@ -104,12 +57,8 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
placeholder="请输入内容"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||
/>
|
||||
<el-input v-model="formData.remark" type="textarea" placeholder="请输入内容"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -123,7 +72,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, toRefs } from "vue";
|
||||
import { onMounted, reactive, ref, toRefs, defineEmits } from "vue";
|
||||
import {
|
||||
listDictPages,
|
||||
getDictFormDetail,
|
||||
@@ -134,7 +83,6 @@ import {
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Dialog, Dict, DictFormData, DictQueryParam } from "@/types";
|
||||
import { status } from "nprogress";
|
||||
|
||||
const queryFormRef = ref(ElForm);
|
||||
const dataFormRef = ref(ElForm);
|
||||
@@ -155,7 +103,7 @@ const state = reactive({
|
||||
} as DictQueryParam,
|
||||
dictList: [] as Dict[],
|
||||
total: 0,
|
||||
dialog: {visible:false} as Dialog,
|
||||
dialog: { visible: false } as Dialog,
|
||||
formData: {
|
||||
status: 1,
|
||||
} as DictFormData,
|
||||
@@ -168,14 +116,11 @@ const state = reactive({
|
||||
const {
|
||||
total,
|
||||
dialog,
|
||||
ids,
|
||||
loading,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
dictList,
|
||||
formData,
|
||||
rules,
|
||||
queryParams
|
||||
} = toRefs(state);
|
||||
|
||||
function handleQuery() {
|
||||
@@ -221,15 +166,15 @@ function submitForm() {
|
||||
dataFormRef.value.validate((isValid: boolean) => {
|
||||
if (isValid) {
|
||||
if (state.formData.id) {
|
||||
updateDict(state.formData.id, state.formData).then((response) => {
|
||||
updateDict(state.formData.id, state.formData).then(() => {
|
||||
ElMessage.success("修改成功");
|
||||
state.dialog.visible = false;
|
||||
cancel()
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addDict(state.formData).then((response) => {
|
||||
addDict(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
state.dialog.visible = false;
|
||||
cancel()
|
||||
handleQuery();
|
||||
});
|
||||
}
|
||||
@@ -237,12 +182,9 @@ function submitForm() {
|
||||
});
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
function cancel() {
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
state.dialog.visible = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,39 +3,20 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="数据项名称"
|
||||
clearable
|
||||
/>
|
||||
<el-input v-model="queryParams.name" placeholder="数据项名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
:data="dictItemList"
|
||||
v-loading="loading"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table :data="dictItemList" v-loading="loading" border @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" min-width="5%" />
|
||||
<el-table-column label="数据项名称" prop="name" />
|
||||
<el-table-column label="数据项值" prop="value" />
|
||||
@@ -47,76 +28,37 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleUpdate(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="state.total > 0"
|
||||
:total="state.total"
|
||||
v-model:page="state.queryParams.pageNum"
|
||||
v-model:limit="state.queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
|
||||
<!-- 表单弹窗 -->
|
||||
<el-dialog
|
||||
:title="dialog.title"
|
||||
v-model="dialog.visible"
|
||||
width="500px"
|
||||
@close="cancel"
|
||||
>
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" @close="cancel">
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||
<el-form-item label="字典名称">
|
||||
<el-input v-model="props.dictName" :disabled="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="字典项名称" prop="name">
|
||||
<el-input
|
||||
v-model="state.formData.name"
|
||||
placeholder="请输入字典项名称"
|
||||
/>
|
||||
<el-input v-model="formData.name" placeholder="请输入字典项名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="字典项值" prop="value">
|
||||
<el-input
|
||||
v-model="state.formData.value"
|
||||
placeholder="请输入字典项值"
|
||||
/>
|
||||
<el-input v-model="formData.value" placeholder="请输入字典项值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number
|
||||
v-model="state.formData.sort"
|
||||
style="width: 80px"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
/>
|
||||
<el-input-number v-model="formData.sort" style="width: 80px" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="state.formData.status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio :label="1">正常</el-radio>
|
||||
<el-radio :label="0">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="state.formData.remark" type="textarea"></el-input>
|
||||
<el-input v-model="formData.remark" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -130,7 +72,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, toRefs, unref, watch } from "vue";
|
||||
import { onMounted, reactive, ref, toRefs, watch } from "vue";
|
||||
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -147,15 +89,18 @@ import {
|
||||
} from "@/api/system/dict";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
dictCode: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: () => {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
dictName: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: () => {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -179,32 +124,33 @@ const state = reactive({
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
total: 0,
|
||||
queryParams: { pageNum: 1, pageSize: 10 } as DictItemQueryParam,
|
||||
dictItemList: [] as DictItem[],
|
||||
total: 0,
|
||||
dialog: { visible: false } as Dialog,
|
||||
formData: {
|
||||
dictCode: props.dictCode,
|
||||
dictName: props.dictName,
|
||||
status: 1,
|
||||
sort: 1,
|
||||
} as DictItemFormData,
|
||||
rules: {
|
||||
name: [{ required: true, message: "请输入字典项名称", trigger: "blur" }],
|
||||
value: [{ required: true, message: "请输入字典项值", trigger: "blur" }],
|
||||
value: [{ required: true, message: "请输入字典项值", trigger: "blur" }]
|
||||
},
|
||||
localDictCode: props.dictCode,
|
||||
localDictName: props.dictName
|
||||
});
|
||||
|
||||
const {
|
||||
loading,
|
||||
ids,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
dictItemList,
|
||||
total,
|
||||
dialog,
|
||||
formData,
|
||||
rules,
|
||||
total
|
||||
} = toRefs(state);
|
||||
|
||||
function handleQuery() {
|
||||
@@ -260,15 +206,15 @@ function submitForm() {
|
||||
dataFormRef.value.validate((isValid: boolean) => {
|
||||
if (isValid) {
|
||||
if (state.formData.id) {
|
||||
updateDictItem(state.formData.id, state.formData).then((response) => {
|
||||
updateDictItem(state.formData.id, state.formData).then(() => {
|
||||
ElMessage.success("修改成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addDictItem(state.formData).then((response) => {
|
||||
addDictItem(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
}
|
||||
@@ -276,13 +222,10 @@ function submitForm() {
|
||||
});
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
state.dialog.visible = false;
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
function handleDelete(row: any) {
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<template #header>
|
||||
<svg-icon color="#333" icon-class="dict"/>
|
||||
<span style="margin:0 5px;">字典数据项</span>
|
||||
<el-tag type="success" v-if=" state.dictCode" size="small">{{ state.dictName }}</el-tag>
|
||||
<el-tag type="success" v-if="dictCode" size="small">{{dictName }}</el-tag>
|
||||
<el-tag type="warning" v-else size="small">未选择字典</el-tag>
|
||||
</template>
|
||||
<!-- 字典项组件 -->
|
||||
<dict-item :dictName="state.dictName" :dictCode='state.dictCode'/>
|
||||
<dict-item :dictName="dictName" :dictCode='dictCode'/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -3,43 +3,25 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="菜单名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<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 type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="menuList"
|
||||
highlight-current-row
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
@row-click="handleRowClick"
|
||||
row-key="id"
|
||||
border
|
||||
>
|
||||
<el-table v-loading="loading" :data="menuList" highlight-current-row
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" @row-click="handleRowClick" row-key="id"
|
||||
border>
|
||||
<el-table-column label="菜单名称">
|
||||
<template #default="scope">
|
||||
<svg-icon
|
||||
color="#333"
|
||||
:icon-class="scope.row.icon ? scope.row.icon : 'build'"
|
||||
/>
|
||||
<svg-icon color="#333" :icon-class="scope.row.icon ? scope.row.icon : 'build'" />
|
||||
{{ scope.row.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -53,45 +35,18 @@
|
||||
|
||||
<el-table-column label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="success"
|
||||
:icon="Plus"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleAdd(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleUpdate(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button type="success" :icon="Plus" circle plain @click.stop="handleAdd(scope.row)" />
|
||||
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 弹窗表单 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="750px">
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||
<el-form-item label="父级菜单" prop="parentId">
|
||||
<tree-select
|
||||
v-model="formData.parentId"
|
||||
:options="menuOptions"
|
||||
placeholder="选择上级菜单"
|
||||
/>
|
||||
<tree-select v-model="formData.parentId" :options="menuOptions" placeholder="选择上级菜单" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="菜单名称" prop="name">
|
||||
@@ -110,51 +65,24 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="!isExternalPath" label="页面路径" prop="component">
|
||||
<el-input
|
||||
v-model="formData.component"
|
||||
placeholder="system/user/index"
|
||||
style="width: 95%"
|
||||
>
|
||||
<template v-if="formData.parentId != 0" #prepend
|
||||
>src/views/</template
|
||||
>
|
||||
<el-input v-model="formData.component" placeholder="system/user/index" style="width: 95%">
|
||||
<template v-if="formData.parentId != 0" #prepend>src/views/</template>
|
||||
<template v-if="formData.parentId != 0" #append>.vue</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
content="请输入组件路径,如果是父组件填写 Layout 即可"
|
||||
placement="right"
|
||||
>
|
||||
<i
|
||||
class="el-icon-info"
|
||||
style="margin-left: 10px; color: darkseagreen"
|
||||
></i>
|
||||
<el-tooltip effect="dark" content="请输入组件路径,如果是父组件填写 Layout 即可" placement="right">
|
||||
<i class="el-icon-info" style="margin-left: 10px; color: darkseagreen"></i>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="图标" prop="icon">
|
||||
<el-popover
|
||||
placement="bottom-start"
|
||||
:width="570"
|
||||
trigger="click"
|
||||
v-model:visible="iconSelectVisible"
|
||||
>
|
||||
<el-popover placement="bottom-start" :width="570" trigger="click" visible="iconSelectVisible">
|
||||
<icon-select ref="iconSelectRef" @selected="selected" />
|
||||
<template #reference>
|
||||
<el-input
|
||||
v-model="formData.icon"
|
||||
placeholder="点击选择图标"
|
||||
readonly
|
||||
@click="iconSelectVisible = true"
|
||||
>
|
||||
<el-input v-model="formData.icon" placeholder="点击选择图标" readonly @click="iconSelectVisible = true">
|
||||
<template #prefix>
|
||||
<svg-icon
|
||||
:icon-class="formData.icon ? formData.icon : 'color'"
|
||||
class="el-input__icon"
|
||||
style="margin: auto"
|
||||
color="#999"
|
||||
/>
|
||||
<svg-icon :icon-class="formData.icon ? formData.icon : 'color'" class="el-input__icon"
|
||||
style="margin: auto" color="#999" />
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
@@ -169,20 +97,11 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number
|
||||
v-model="formData.sort"
|
||||
style="width: 100px"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
/>
|
||||
<el-input-number v-model="formData.sort" style="width: 100px" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="跳转路径">
|
||||
<el-input
|
||||
v-model="formData.redirect"
|
||||
placeholder="请输入跳转路径"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-input v-model="formData.redirect" placeholder="请输入跳转路径" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -197,7 +116,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, unref, onMounted, toRefs } from "vue";
|
||||
import { reactive, ref, onMounted, toRefs, defineEmits } from "vue";
|
||||
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
|
||||
@@ -240,8 +159,7 @@ const state = reactive({
|
||||
multiple: true,
|
||||
queryParams: {} as MenuQueryParam,
|
||||
menuList: [] as MenuItem[],
|
||||
total: 0,
|
||||
dialog: {visible:false} as Dialog,
|
||||
dialog: { visible: false } as Dialog,
|
||||
formData: {
|
||||
parentId: 0,
|
||||
visible: 1,
|
||||
@@ -256,16 +174,13 @@ const state = reactive({
|
||||
menuOptions: [] as Option[],
|
||||
currentRow: undefined,
|
||||
isExternalPath: false,
|
||||
iconSelectVisible: false,
|
||||
iconSelectVisible: false
|
||||
});
|
||||
|
||||
const {
|
||||
loading,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
menuList,
|
||||
total,
|
||||
dialog,
|
||||
formData,
|
||||
rules,
|
||||
@@ -307,15 +222,7 @@ function resetQuery() {
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
function handleSelectionChange(selection: any) {
|
||||
state.ids = selection.map((item: any) => item.id);
|
||||
state.single = selection.length !== 1;
|
||||
state.multiple = !selection.length;
|
||||
}
|
||||
|
||||
function handleRowClick(row: any) {
|
||||
|
||||
console.log('handleRowClick',row)
|
||||
state.currentRow = JSON.parse(JSON.stringify(row));
|
||||
emit("menuClick", row);
|
||||
}
|
||||
@@ -367,15 +274,15 @@ function submitForm() {
|
||||
dataFormRef.value.validate((isValid: boolean) => {
|
||||
if (isValid) {
|
||||
if (state.formData.id) {
|
||||
updateMenu(state.formData.id, state.formData).then((response) => {
|
||||
updateMenu(state.formData.id, state.formData).then(() => {
|
||||
ElMessage.success("修改成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addMenu(state.formData).then((response) => {
|
||||
addMenu(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
}
|
||||
@@ -399,29 +306,18 @@ function handleDelete(row: any) {
|
||||
.catch(() => ElMessage.info("已取消删除"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置表单
|
||||
*/
|
||||
function resetForm() {
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消关闭弹窗
|
||||
*/
|
||||
function cancel() {
|
||||
state.formData.id = undefined;
|
||||
dataFormRef.value.resetFields();
|
||||
state.dialog.visible = false;
|
||||
resetForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示图标选择下拉
|
||||
* 选择图标后事件
|
||||
*/
|
||||
function showIconSelect() {
|
||||
state.iconSelectVisible = true;
|
||||
}
|
||||
|
||||
function selected(name: string) {
|
||||
state.formData.icon = name;
|
||||
state.iconSelectVisible = false;
|
||||
|
||||
@@ -3,44 +3,20 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="success"
|
||||
:icon="Plus"
|
||||
:disabled="!menuId"
|
||||
@click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="success" :icon="Plus" :disabled="!menuId" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="权限名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<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 type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
:data="permList"
|
||||
v-loading="loading"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
>
|
||||
<el-table :data="permList" v-loading="loading" @selection-change="handleSelectionChange" border>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column label="权限名称" prop="name" width="150" />
|
||||
<el-table-column label="URL权限" align="center">
|
||||
@@ -51,41 +27,19 @@
|
||||
<el-table-column label="按钮权限" prop="btnPerm" width="200" />
|
||||
<el-table-column label="操作" align="center" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click="handleUpdate(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button type="primary" :icon="Edit" circle plain @click="handleUpdate(scope.row)" />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页工具条 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page="queryParams.pageNum"
|
||||
:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" :v-model:page="queryParams.pageNum" :v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
|
||||
<!-- 表单弹窗 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="700px">
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-form-item label="权限名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入权限名称" />
|
||||
</el-form-item>
|
||||
@@ -93,37 +47,21 @@
|
||||
<el-form-item label="URL权限标识" prop="urlPerm">
|
||||
<el-input placeholder="/api/v1/users" v-model="urlPerm.requestPath">
|
||||
<template #prepend>
|
||||
<el-select
|
||||
v-model="urlPerm.serviceName"
|
||||
style="width: 130px"
|
||||
placeholder="所属服务"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in microServiceOptions"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
<el-select v-model="urlPerm.serviceName" style="width: 130px" placeholder="所属服务" clearable>
|
||||
<el-option v-for="item in microServiceOptions" :key="item.value" :value="item.value"
|
||||
:label="item.label" />
|
||||
</el-select>
|
||||
|
||||
<el-select
|
||||
v-model="urlPerm.requestMethod"
|
||||
style="width: 120px; margin-left: 20px"
|
||||
placeholder="请求方式"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in requestMethodOptions"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
<el-select v-model="urlPerm.requestMethod" style="width: 120px; margin-left: 20px" placeholder="请求方式"
|
||||
clearable>
|
||||
<el-option v-for="item in requestMethodOptions" :key="item.value" :value="item.value"
|
||||
:label="item.label" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-link v-show="urlPerm.requestMethod">
|
||||
{{ urlPerm.requestMethod }}:/{{ urlPerm.serviceName
|
||||
{{ urlPerm.requestMethod }}:/{{
|
||||
urlPerm.serviceName
|
||||
}}{{ urlPerm.requestPath }}
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
@@ -143,22 +81,25 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
listPermPages,
|
||||
getPermFormDetail,
|
||||
addPerm,
|
||||
updatePerm,
|
||||
deletePerms,
|
||||
} from "@/api/system/perm";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
|
||||
import {
|
||||
onMounted,
|
||||
watch,
|
||||
reactive,
|
||||
ref,
|
||||
getCurrentInstance,
|
||||
toRefs,
|
||||
toRefs
|
||||
} from "vue";
|
||||
|
||||
import {
|
||||
listPermPages,
|
||||
getPermFormDetail,
|
||||
addPerm,
|
||||
updatePerm,
|
||||
deletePerms
|
||||
} from "@/api/system/perm";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
|
||||
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -176,7 +117,9 @@ const dataFormRef = ref(ElForm);
|
||||
const props = defineProps({
|
||||
menuId: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: () => {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -216,14 +159,12 @@ const state = reactive({
|
||||
urlPerm: {
|
||||
requestMethod: "",
|
||||
serviceName: "",
|
||||
requestPath: "",
|
||||
requestPath: ""
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
loading,
|
||||
ids,
|
||||
single,
|
||||
multiple,
|
||||
permList,
|
||||
total,
|
||||
@@ -280,7 +221,7 @@ function handleAdd() {
|
||||
loadDictOptions();
|
||||
state.dialog = {
|
||||
title: "添加权限",
|
||||
visible: true,
|
||||
visible: true
|
||||
};
|
||||
}
|
||||
|
||||
@@ -337,13 +278,13 @@ function submitForm() {
|
||||
|
||||
state.formData.menuId = props.menuId;
|
||||
if (state.formData.id) {
|
||||
updatePerm(state.formData.id, state.formData).then((response) => {
|
||||
updatePerm(state.formData.id, state.formData).then(() => {
|
||||
ElMessage.success("修改成功");
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addPerm(state.formData).then((response) => {
|
||||
addPerm(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
cancel();
|
||||
handleQuery();
|
||||
|
||||
@@ -4,44 +4,26 @@
|
||||
<el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="16">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
:icon="Switch"
|
||||
@click="toggleExpandAll"
|
||||
>展开/折叠</el-button
|
||||
>
|
||||
<el-button type="success" plain :icon="Switch" @click="toggleExpandAll">展开/折叠</el-button>
|
||||
</el-col>
|
||||
<el-col :span="8" style="text-align: right">
|
||||
<el-button type="primary" :icon="Check" @click="handleSubmit"
|
||||
>提交</el-button
|
||||
>
|
||||
<el-button type="primary" :icon="Check" @click="handleSubmit">提交</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-tree
|
||||
ref="menuRef"
|
||||
v-if="refreshTree"
|
||||
:default-expanded-keys="expandedKeys"
|
||||
:default-expand-all="isExpandAll"
|
||||
:data="menuOptions"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
empty-text="加载菜单中..."
|
||||
:check-strictly="checkStrictly"
|
||||
highlight-current
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
<el-tree ref="menuRef" v-if="refreshTree" :default-expanded-keys="expandedKeys" :default-expand-all="isExpandAll"
|
||||
:data="menuOptions" show-checkbox node-key="id" empty-text="加载菜单中..." :check-strictly="checkStrictly"
|
||||
highlight-current @node-click="handleNodeClick" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, reactive, ref, toRefs, watch } from "vue";
|
||||
import { listSelectMenus } from "@/api/system/menu";
|
||||
import { listRoleMenuIds, updateRoleMenu } from "@/api/system/role";
|
||||
import { nextTick, onMounted, reactive, ref, toRefs, watch } from "vue";
|
||||
import { ElTree, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { ElTree, ElMessage } from "element-plus";
|
||||
import { Switch, Check } from "@element-plus/icons-vue";
|
||||
import { Option } from "@/types";
|
||||
|
||||
@@ -49,7 +31,9 @@ const emit = defineEmits(["menuClick"]);
|
||||
const props = defineProps({
|
||||
role: {
|
||||
type: Object,
|
||||
default: {},
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -57,7 +41,7 @@ const menuRef = ref(ElTree); // 属性名必须和元素的ref属性值一致
|
||||
|
||||
watch(
|
||||
() => props.role.id as any,
|
||||
(newVal, oldVal) => {
|
||||
() => {
|
||||
const roleId = props.role.id;
|
||||
if (roleId) {
|
||||
state.checkStrictly = true;
|
||||
|
||||
@@ -3,69 +3,54 @@
|
||||
<div v-if="permissionOptions.length > 0">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-checkbox
|
||||
:indeterminate="isIndeterminate"
|
||||
v-model="checkAll"
|
||||
@change="handleCheckAllChange"
|
||||
>全选
|
||||
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选
|
||||
</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :span="12" style="text-align: right">
|
||||
<el-button type="primary" :icon="Check" @click="handleSubmit"
|
||||
>提交</el-button
|
||||
>
|
||||
<el-button type="primary" :icon="Check" @click="handleSubmit">提交</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col
|
||||
:span="8"
|
||||
v-for="item in permissionOptions"
|
||||
style="margin-top: 20px"
|
||||
:key="item.id"
|
||||
>
|
||||
<el-checkbox
|
||||
border
|
||||
v-model="item.checked"
|
||||
:label="item.id"
|
||||
:key="item.id"
|
||||
@change="handleCheckedPermChange"
|
||||
>
|
||||
<el-col :span="8" v-for="item in permissionOptions" style="margin-top: 20px" :key="item.id">
|
||||
<el-checkbox border v-model="item.checked" :label="item.id" :key="item.id" @change="handleCheckedPermChange">
|
||||
{{ item.name }}
|
||||
</el-checkbox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div style="text-align: center" v-else>
|
||||
<el-empty
|
||||
:description="
|
||||
!role
|
||||
? '请选择角色'
|
||||
: !menu
|
||||
<el-empty :description="
|
||||
!role
|
||||
? '请选择角色'
|
||||
: !menu
|
||||
? '请选择菜单'
|
||||
: '暂无数据,您可在【菜单管理】配置权限数据'
|
||||
"
|
||||
></el-empty>
|
||||
"></el-empty>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, toRefs, watch } from "vue";
|
||||
import { listPerms } from "@/api/system/perm";
|
||||
import { listRolePerms, saveRolePerms } from "@/api/system/role";
|
||||
import { onMounted, reactive, toRefs, watch } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { Check } from "@element-plus/icons-vue";
|
||||
import { PermQueryParam, MenuItem } from "@/types";
|
||||
import { PermQueryParam } from "@/types";
|
||||
|
||||
const props = defineProps({
|
||||
role: {
|
||||
type: Object,
|
||||
default: {},
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
menu: {
|
||||
type: Object,
|
||||
default: {},
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -86,10 +71,9 @@ const state = reactive({
|
||||
checkedPerms: [],
|
||||
});
|
||||
|
||||
const { permissionOptions, isIndeterminate, checkAll, checkedPerms } =
|
||||
toRefs(state);
|
||||
const { permissionOptions, isIndeterminate, checkAll } = toRefs(state);
|
||||
|
||||
function handleCheckAllChange(checked: Boolean) {
|
||||
function handleCheckAllChange(checked: boolean) {
|
||||
state.isIndeterminate = false;
|
||||
if (checked) {
|
||||
state.permissionOptions.map((item) => (item.checked = true));
|
||||
@@ -99,7 +83,7 @@ function handleCheckAllChange(checked: Boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleCheckedPermChange(value: any) {
|
||||
function handleCheckedPermChange() {
|
||||
const checkedCount = state.permissionOptions.filter(
|
||||
(item) => item.checked
|
||||
).length;
|
||||
@@ -116,7 +100,7 @@ function loadData() {
|
||||
state.loading = true;
|
||||
|
||||
const params = { menuId: props.menu.id } as PermQueryParam;
|
||||
listPerms(params).then(({data}) => {
|
||||
listPerms(params).then(({ data }) => {
|
||||
state.permissionOptions = data;
|
||||
listRolePerms(props.role.id, props.menu.id).then((response) => {
|
||||
const checkedPermIds = response.data;
|
||||
@@ -150,6 +134,7 @@ function resetData() {
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -3,90 +3,41 @@
|
||||
<!-- 搜索表单 -->
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="角色名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<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 type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
ref="dataTableRef"
|
||||
v-loading="loading"
|
||||
:data="roleList"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-click="handleRowClick"
|
||||
highlight-current-row
|
||||
border
|
||||
>
|
||||
<el-table ref="dataTableRef" v-loading="loading" :data="roleList" @selection-change="handleSelectionChange"
|
||||
@row-click="handleRowClick" highlight-current-row border>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="角色名称" prop="name" />
|
||||
<el-table-column label="角色编码" prop="code" />
|
||||
<el-table-column label="操作" align="center" width="120">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleUpdate(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleDelete(scope.row)"
|
||||
/>
|
||||
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
|
||||
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页工具条 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
|
||||
<!-- 表单弹窗 -->
|
||||
<el-dialog
|
||||
:title="dialog.title"
|
||||
v-model="dialog.visible"
|
||||
@close="cancel"
|
||||
width="450px"
|
||||
>
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" @close="cancel" width="450px">
|
||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||
<el-form-item label="角色名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入角色名称" />
|
||||
</el-form-item>
|
||||
@@ -96,12 +47,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number
|
||||
v-model="formData.sort"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
style="width: 100px"
|
||||
/>
|
||||
<el-input-number v-model="formData.sort" controls-position="right" :min="0" style="width: 100px" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态">
|
||||
@@ -123,6 +69,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, toRefs, defineEmits } from "vue";
|
||||
import {
|
||||
listRolePages,
|
||||
updateRole,
|
||||
@@ -130,7 +77,6 @@ import {
|
||||
addRole,
|
||||
deleteRoles,
|
||||
} from "@/api/system/role";
|
||||
import { onMounted, reactive, ref, toRefs, unref } from "vue";
|
||||
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
import { RoleFormData, RoleItem, RoleQueryParam } from "@/types";
|
||||
@@ -166,7 +112,6 @@ const state = reactive({
|
||||
|
||||
const {
|
||||
loading,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
roleList,
|
||||
@@ -224,16 +169,16 @@ function submitForm() {
|
||||
if (valid) {
|
||||
if (state.formData.id) {
|
||||
updateRole(state.formData.id as any, state.formData).then(
|
||||
(response) => {
|
||||
() => {
|
||||
ElMessage.success("修改成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
addRole(state.formData).then((response) => {
|
||||
addRole(state.formData).then(() => {
|
||||
ElMessage.success("新增成功");
|
||||
state.dialog.visible = false;
|
||||
cancel();
|
||||
handleQuery();
|
||||
});
|
||||
}
|
||||
@@ -244,14 +189,9 @@ function submitForm() {
|
||||
/**
|
||||
* 重置表单
|
||||
*/
|
||||
function resetForm() {
|
||||
dataFormRef.value.resetFields();
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
resetForm();
|
||||
state.dialog.visible = false;
|
||||
dataFormRef.value.resetFields();
|
||||
}
|
||||
|
||||
function handleDelete(row: any) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<svg-icon color="#333" icon-class="role" />
|
||||
角色列表
|
||||
</template>
|
||||
<role ref="role" @roleClick="handleRoleClick" />
|
||||
<Role ref="role" @roleClick="handleRoleClick" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</el-tag>
|
||||
<el-tag type="warning" v-else size="small">请选择角色</el-tag>
|
||||
</template>
|
||||
<menus ref="menu" @menuClick="handleMenuClick" :role="role" />
|
||||
<Menus ref="menu" @menuClick="handleMenuClick" :role="role" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ import { listSelectDepartments } from "@/api/system/dept";
|
||||
import { listRoles } from "@/api/system/role";
|
||||
|
||||
// 组件依赖
|
||||
import { ElMessage, ElMessageBox, ElTree, ElForm, UploadRequestOptions } from "element-plus";
|
||||
import { ElMessage, ElMessageBox, ElTree, ElForm, UploadFile } from "element-plus";
|
||||
import {
|
||||
Search,
|
||||
Plus,
|
||||
@@ -234,7 +234,6 @@ import {
|
||||
Dialog,
|
||||
UserImportFormData
|
||||
} from "@/types";
|
||||
import { assertFile } from "@babel/types";
|
||||
|
||||
// DOM元素的引用声明定义 ,变量名和DOM的ref属性值一致
|
||||
const deptTreeRef = ref(ElTree); // 部门树
|
||||
@@ -312,7 +311,6 @@ const state = reactive({
|
||||
|
||||
const {
|
||||
loading,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
userList,
|
||||
@@ -444,7 +442,7 @@ function resetPassword(row: { [key: string]: any }) {
|
||||
ElMessage.success("修改成功,新密码是:" + value);
|
||||
});
|
||||
})
|
||||
.catch(() => { });
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,7 +487,7 @@ function submitForm() {
|
||||
handleQuery();
|
||||
});
|
||||
} else {
|
||||
addUser(state.formData).then((response: any) => {
|
||||
addUser(state.formData).then(() => {
|
||||
ElMessage.success("新增用户成功");
|
||||
cancel()
|
||||
handleQuery();
|
||||
@@ -576,8 +574,7 @@ async function showImportDialog() {
|
||||
}
|
||||
|
||||
|
||||
function handleExcelChange(file: any, fileList: File[]) {
|
||||
const fileName = file.name;
|
||||
function handleExcelChange(file: UploadFile) {
|
||||
if (!/\.(xlsx|xls|XLSX|XLS)$/.test(file.name)) {
|
||||
ElMessage.warning('上传Excel只能为xlsx、xls格式');
|
||||
state.excelFile = undefined
|
||||
|
||||
@@ -2,54 +2,35 @@
|
||||
<div class="app-container">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<el-input
|
||||
v-model="queryParams.nickName"
|
||||
placeholder="会员昵称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<el-input v-model="queryParams.nickName" placeholder="会员昵称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="memberList"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table v-loading="loading" :data="memberList" border @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" align="center" />
|
||||
<el-table-column type="expand" width="120" label="会员地址">
|
||||
<template #default="scope">
|
||||
<el-table :data="scope.row.addressList" size="small" border>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column type="index" label="序号" width="100" align="center" />
|
||||
<el-table-column align="center" label="收货人" prop="name" />
|
||||
<el-table-column align="center" label="联系方式" prop="mobile" />
|
||||
<el-table-column align="center" label="收货地址">
|
||||
<template #default="scope">
|
||||
{{
|
||||
scope.row.province +
|
||||
scope.row.city +
|
||||
scope.row.area +
|
||||
scope.row.address
|
||||
scope.row.city +
|
||||
scope.row.area +
|
||||
scope.row.address
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="邮编" prop="zipCode" />
|
||||
<el-table-column align="center" label="是否默认">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.defaulted == 1" type="success"
|
||||
>是</el-tag
|
||||
>
|
||||
<el-tag v-if="scope.row.defaulted == 1" type="success">是</el-tag>
|
||||
<el-tag v-if="scope.row.defaulted == 0" type="info">否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -71,10 +52,7 @@
|
||||
<el-popover placement="right" :width="400" trigger="hover">
|
||||
<img :src="scope.row.avatarUrl" width="400" height="400" />
|
||||
<template #reference>
|
||||
<img
|
||||
:src="scope.row.avatarUrl"
|
||||
style="max-height: 60px; max-width: 60px"
|
||||
/>
|
||||
<img :src="scope.row.avatarUrl" style="max-height: 60px; max-width: 60px" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
@@ -98,23 +76,18 @@
|
||||
</el-table>
|
||||
|
||||
<!-- 分页工具条 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRefs } from "vue";
|
||||
import { ElTable, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
|
||||
import { ElTable } from "element-plus";
|
||||
import { Search, Refresh } from "@element-plus/icons-vue";
|
||||
|
||||
import { listMemeberPages } from "@/api/ums/member";
|
||||
import { MemberQueryParam,MemberItem } from "@/types";
|
||||
import { MemberQueryParam, MemberItem } from "@/types";
|
||||
|
||||
const state = reactive({
|
||||
// 遮罩层
|
||||
@@ -128,17 +101,17 @@ const state = reactive({
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 10
|
||||
} as MemberQueryParam,
|
||||
memberList: [] as MemberItem[]
|
||||
});
|
||||
|
||||
const { loading, ids, single, multiple, queryParams, memberList, total } =
|
||||
const { loading, queryParams, memberList, total } =
|
||||
toRefs(state);
|
||||
|
||||
function handleQuery() {
|
||||
state.loading = true;
|
||||
listMemeberPages(state.queryParams).then(({data}) => {
|
||||
listMemeberPages(state.queryParams).then(({ data }) => {
|
||||
state.memberList = data.list;
|
||||
state.total = data.total;
|
||||
state.loading = false;
|
||||
@@ -149,7 +122,7 @@ function resetQuery() {
|
||||
state.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
nickName: undefined,
|
||||
nickName: ''
|
||||
};
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user