# Conflicts:
#	src/layout/components/Aside.vue
#	src/views/test.vue
This commit is contained in:
sa_10_0 2024-12-10 19:28:30 +08:00
commit 051fc00253
18 changed files with 1022 additions and 292 deletions

BIN
dist.zip

Binary file not shown.

View File

@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="icon" href="https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FypVcAOGV-Snipaste_2024-10-11_15-03-12.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<title>非遗小程序管理端</title>
</head>
<body>
<div id="app"></div>

172
package-lock.json generated
View File

@ -411,9 +411,9 @@
}
},
"@floating-ui/dom": {
"version": "1.6.11",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.11.tgz",
"integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==",
"version": "1.6.12",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.12.tgz",
"integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==",
"requires": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.8"
@ -786,9 +786,9 @@
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
},
"@types/lodash": {
"version": "4.17.12",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.12.tgz",
"integrity": "sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ=="
"version": "4.17.13",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.13.tgz",
"integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg=="
},
"@types/lodash-es": {
"version": "4.17.12",
@ -1177,6 +1177,15 @@
"resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
},
"copy-anything": {
"version": "2.0.6",
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz",
"integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
"dev": true,
"requires": {
"is-what": "^3.14.1"
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -1258,9 +1267,9 @@
"integrity": "sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A=="
},
"element-plus": {
"version": "2.8.6",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.8.6.tgz",
"integrity": "sha512-fk5jB8V3efM02/4roZ5SWOLArgaYXbxEydZLlXSr+KPAwjNyHBlk2+HO5em8YKo5+RLBoHnn6BaThj6IE4nXoQ==",
"version": "2.9.0",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.0.tgz",
"integrity": "sha512-ccOFXKsauo2dtokAr4OX7gZsb7TuAoVxA2zGRZo5o2yyDDBLBaZxOoFQPoxITSLcHbBfQuNDGK5Iag5hnyKkZA==",
"requires": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.1",
@ -1270,7 +1279,7 @@
"@types/lodash-es": "^4.17.6",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.3",
"dayjs": "^1.11.13",
"escape-html": "^1.0.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
@ -1284,6 +1293,16 @@
"resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
},
"errno": {
"version": "0.1.8",
"resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz",
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
"dev": true,
"optional": true,
"requires": {
"prr": "~1.0.1"
}
},
"esbuild": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz",
@ -1474,6 +1493,13 @@
"unicorn-magic": "^0.1.0"
}
},
"graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true,
"optional": true
},
"hash-sum": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz",
@ -1495,11 +1521,28 @@
"resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-5.0.0.tgz",
"integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"optional": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="
},
"image-size": {
"version": "0.5.5",
"resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz",
"integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==",
"dev": true,
"optional": true
},
"immutable": {
"version": "4.3.7",
"resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.7.tgz",
@ -1537,6 +1580,12 @@
"resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="
},
"is-what": {
"version": "3.14.1",
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz",
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
"dev": true
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
@ -1578,6 +1627,24 @@
"resolved": "https://registry.npmmirror.com/knitwork/-/knitwork-1.1.0.tgz",
"integrity": "sha512-oHnmiBUVHz1V+URE77PNot2lv3QiYU2zQf1JjOVkMt3YDKGbu8NAFr+c4mcNOhdsGrB/VpVbRwPwhiXrPhxQbw=="
},
"less": {
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/less/-/less-4.2.1.tgz",
"integrity": "sha512-CasaJidTIhWmjcqv0Uj5vccMI7pJgfD9lMkKtlnTHAdJdYK/7l8pM9tumLyJ0zhbD4KJLo/YvTj+xznQd5NBhg==",
"dev": true,
"requires": {
"copy-anything": "^2.0.1",
"errno": "^0.1.1",
"graceful-fs": "^4.1.2",
"image-size": "~0.5.0",
"make-dir": "^2.1.0",
"mime": "^1.4.1",
"needle": "^3.1.0",
"parse-node-version": "^1.0.1",
"source-map": "~0.6.0",
"tslib": "^2.3.0"
}
},
"local-pkg": {
"version": "0.5.0",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.5.0.tgz",
@ -1618,6 +1685,26 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"dev": true,
"optional": true,
"requires": {
"pify": "^4.0.1",
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.2",
"resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"optional": true
}
}
},
"memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
@ -1648,6 +1735,13 @@
"picomatch": "^2.3.1"
}
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true,
"optional": true
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
@ -1746,6 +1840,17 @@
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="
},
"needle": {
"version": "3.3.1",
"resolved": "https://registry.npmmirror.com/needle/-/needle-3.3.1.tgz",
"integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==",
"dev": true,
"optional": true,
"requires": {
"iconv-lite": "^0.6.3",
"sax": "^1.2.4"
}
},
"node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
@ -1835,6 +1940,12 @@
"mimic-fn": "^4.0.0"
}
},
"parse-node-version": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz",
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
"dev": true
},
"path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
@ -1877,6 +1988,13 @@
"integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
"dev": true
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true,
"optional": true
},
"pinia": {
"version": "2.2.4",
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.2.4.tgz",
@ -1922,6 +2040,13 @@
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz",
"integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
"dev": true,
"optional": true
},
"querystring": {
"version": "0.2.1",
"resolved": "https://registry.npmmirror.com/querystring/-/querystring-0.2.1.tgz",
@ -1996,6 +2121,13 @@
"queue-microtask": "^1.2.2"
}
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true,
"optional": true
},
"sass": {
"version": "1.80.3",
"resolved": "https://registry.npmmirror.com/sass/-/sass-1.80.3.tgz",
@ -2008,6 +2140,13 @@
"source-map-js": ">=0.6.2 <2.0.0"
}
},
"sax": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.1.tgz",
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
"dev": true,
"optional": true
},
"scule": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
@ -2047,6 +2186,13 @@
"resolved": "https://registry.npmmirror.com/slash/-/slash-5.1.0.tgz",
"integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"optional": true
},
"source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
@ -2098,6 +2244,12 @@
"is-number": "^7.0.0"
}
},
"tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true
},
"typescript": {
"version": "5.4.5",
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.4.5.tgz",

View File

@ -13,7 +13,7 @@
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.7.2",
"element-plus": "^2.7.5",
"element-plus": "^2.9.0",
"mitt": "^3.0.1",
"pinia": "^2.2.4",
"pinia-plugin-persistedstate": "^4.1.2",
@ -26,6 +26,7 @@
"@types/node": "^20.17.6",
"@vitejs/plugin-vue": "^5.0.4",
"@vue/tsconfig": "^0.5.1",
"less": "^4.2.1",
"npm-run-all2": "^6.1.2",
"sass": "^1.77.5",
"typescript": "~5.4.0",

View File

@ -1,10 +1,14 @@
<template>
<RouterView v-if="isRouterActive"></RouterView>
<el-config-provider :locale="zhCn">
<RouterView v-if="isRouterActive"></RouterView>
</el-config-provider>
</template>
<script setup lang="ts">
//
import { provide , nextTick , ref } from 'vue'
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn' //ElemenetPlus
const isRouterActive = ref(true)
provide('reload', () => {
isRouterActive.value = false

View File

@ -5,6 +5,7 @@ import router from '../router'
const myAxios = axios.create({
withCredentials:true,
baseURL: 'http://localhost:9092/api'//测试服务器
// baseURL: 'http://123.249.108.160:8888/api'
});
// 添加请求拦截器
axios.interceptors.request.use(function (config) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

View File

@ -11,8 +11,8 @@
active-text-color="#ffd04b">
<div style="height: 80px; color: white; font-weight: bold;
display: flex; align-items: center; justify-content: center">
<img src="../../assets/logo.png" alt="" style="height: 30px">
<span style="margin-left: 5px" v-show="isShow">匠承非遗管理系统</span>
<img src="https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FypVcAOGV-Snipaste_2024-10-11_15-03-12.png" alt="" style="height: 30px">
<span style="margin-left: 5px" v-show="isShow">泠泷水月阁管理系统</span>
</div>
<el-sub-menu index="1">
@ -106,7 +106,7 @@
</template>
<el-menu-item index="/ClothingGrade">
<el-icon><Menu /></el-icon>
<span slot="title">服装类别管理</span>
<span slot="title">服装等级管理</span>
</el-menu-item>
<el-menu-item index="/CostumeDetails">
<el-icon><Menu /></el-icon>

View File

@ -4,9 +4,13 @@
<div v-for="(item, index) in dayList" :key="index">
<div class="inner" style="font-size: medium;">
{{ index + 1 }}
<el-checkbox v-model="isAvailableArray[index]" v-if="timeList[index].length != 0" label="这天可预约" style="margin-left: 10px;"/>
</div>
<!-- 时间段部分 -->
<div class="time-picker">
<el-button circle @click="addList(index, 0)" v-if="timeList[index].length == 0"><el-icon>
<Plus />
</el-icon></el-button>
<div v-for="(item, row) in timeList[index]" :key="row" class="box">
<span> {{ row + 1 }} 个时间段</span>
<el-time-select v-model="timeList[index][row].startTime"
@ -22,23 +26,24 @@
<el-select v-model="timeList[index][row].minNumValue"
placeholder="最小人数"
style="width: 100px"
@change="minNumFun">
@change="minNumFun(index,row)">
<el-option v-for="item in minOptions[index][row]"
:key="item"
:value="item" />
</el-select>
<el-select v-model="timeList[index][row].maxNunValue"
<el-select v-model="timeList[index][row].maxNumValue"
placeholder="最大人数"
style="width: 100px">
style="width: 100px"
@change="maxNumFun(index,row)"
>
<el-option v-for="item in maxOptions[index][row]"
:key="item"
:value="item" />
</el-select>
<el-button circle @click="addList(index, row)"><el-icon>
<Plus />
</el-icon></el-button>
<el-button circle @click="subList(index, row)" v-if="row + 1 > 1"><el-icon>
<el-button circle @click="subList(index, row)" v-if="row >= 0"><el-icon>
<Minus />
</el-icon></el-button>
</div>
@ -46,12 +51,22 @@
</div>
</div>
</div>
<div class="totalButton">
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetForm">重置</el-button>
</el-form-item>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { onMounted, ref , defineEmits } from 'vue'
import { Plus } from '@element-plus/icons-vue';
import { transfer } from '../../utils/dealStringArray'; //js
import { ElMessage } from 'element-plus';
const dayList = ref([0, 1, 2, 3]) //
const timeList = ref([ //timeList[index][row]访
[
@ -59,7 +74,7 @@ const timeList = ref([ //时间段数组可以直接通过timeList[index][
startTime: '',
endTime: '',
minNumValue: '',
maxNunValue: ''
maxNumValue: ''
}
],
[
@ -67,7 +82,7 @@ const timeList = ref([ //时间段数组可以直接通过timeList[index][
startTime: '',
endTime: '',
minNumValue: '',
maxNunValue: ''
maxNumValue: ''
}
],
[
@ -75,7 +90,7 @@ const timeList = ref([ //时间段数组可以直接通过timeList[index][
startTime: '',
endTime: '',
minNumValue: '',
maxNunValue: ''
maxNumValue: ''
}
],
[
@ -83,10 +98,13 @@ const timeList = ref([ //时间段数组可以直接通过timeList[index][
startTime: '',
endTime: '',
minNumValue: '',
maxNunValue: ''
maxNumValue: ''
}
]
])
const isAvailableArray = ref(
Array.from({length:4},()=>(false))
)
//
const minOptions = ref(
Array.from({length:4},()=>(
@ -103,12 +121,23 @@ const maxOptions = ref(
))
)
const flag = ref(0) //
var arr = new Array(4)
const emit = defineEmits(['time-Info']) //
const initTimeList = () => {
for (var i = 0; i < 4; i ++ ) {
timeList.value[i].splice(0)
}
}
onMounted(()=>{
init()
initTimeList()
for(let i=0; i<4; i++) { //开始时初始化人数的数组
for(let j=0; j<6; j++) {
for(let k=0;k<50;k++) {
minOptions.value[i][j][k] = k+1;
maxOptions.value[i][j][k] = k+1;
minOptions.value[i][j][k] = k+5;
maxOptions.value[i][j][k] = k+6;
}
}
}
@ -119,27 +148,66 @@ const addList = (index: any, row: any) => {
startTime: '',
endTime: '',
minNumValue: '',
maxNunValue: ''
maxNumValue: ''
})
flag.value += 1
}
}
const subList = (index: number, row: number) => {
console.log(index, row);
timeList.value[index].splice(row, 1)
}
const minNumFun = (number : any)=> {
for(let i = 0;i<number;i++) {
if(maxOptions.value[i] < number) {
maxOptions.value.splice(i,1)
console.log(maxOptions.value);
const minNumFun = (index : number,row : number)=> {
if(timeList.value[index][row].maxNumValue < timeList.value[index][row].minNumValue && timeList.value[index][row].maxNumValue != '') {
ElMessage({
type: 'error',
message: '最小人数不大于最大人数'
})
timeList.value[index][row].minNumValue = ''
return;
}
}
//
const onSubmit =()=> {
let tempArr = transfer(timeList.value, arr,isAvailableArray.value)
// console.log(tempArr)
//
emit('time-Info',tempArr)
}
const resetForm=()=>{
for(let i=0;i<4;i++) {
timeList.value[i].splice(0, timeList.value[i].length)
isAvailableArray.value[i] = false
}
}
const init = () => {
for (var i = 0; i < 4; i ++ ) {
arr[i] = new Array(6)
}
for (var i = 0; i < 4; i ++ ) {
for (var j = 0; j < 6; j ++ ) {
arr[i][j] = {
timeSlot: '',
numberRange: '',
isAvailable: ''
}
}
}
}
const maxNumFun =(index: number ,row: number)=>{
if(timeList.value[index][row].maxNumValue < timeList.value[index][row].minNumValue) {
ElMessage({
type: 'error',
message: '最大人数应该大于最小人数'
})
return;
}
}
</script>
<style lang="scss" scoped>
.date-picker {
height: 750px;
}
div {
font-size: 12px;
color: rgb(96, 98, 102);
@ -151,9 +219,12 @@ div {
.box {
width: 380px;
height: 50pxpx;
border: 1px solid red;
}
.numRange {
margin-left: 26px;
}
.totalButton {
display: flex;
justify-content: space-evenly;
}
</style>

View File

@ -0,0 +1,219 @@
<template>
<el-calendar class="calbox">
<template #date-cell="{ data }">
<div @click="dateForm(data)">
<p :class="data.isSelected ? 'is-selected' : ''">
{{ data.day.split('-').slice(1).join('-') }}
{{ data.isSelected ? '✔️' : '' }}
</p>
</div>
</template>
</el-calendar>
<el-drawer v-model="drawer" :title="'当前选择的日期是:' + periodObj.specificDate" :with-header="true" @open="drawerOpen" @closed="drawerClean">
<div style="margin-bottom: 20px;">选择当天时间段和人数</div>
<div class="timebox" v-for="(item,index) in periodObj.timePeriodAddRequestList">
<span>选择时间段</span>
<el-time-picker
v-model="timePickArr[index]"
format='HH:mm'
is-range="true"
range-separator="到"
start-placeholder="开始"
end-placeholder="结束"
value-format="HH:mm"
:style="{ width: '236px' }"
@change="saveTime(index)"
/>
<div>
<span>最小人数:</span>
<el-select v-model="periodObj.timePeriodAddRequestList[index].minNumber" style="width: 100px" @change="minNum(index)">
<el-option v-for="item in minArr" :label="item" :value="item" />
</el-select>
<span>最大人数:</span>
<el-select v-model="periodObj.timePeriodAddRequestList[index].maxNumber" style="width: 100px" @change="maxNum(index)">
<el-option v-for="item in maxArr" :label="item" :value="item" />
</el-select>
<el-button circle @click="addList(index)"><el-icon>
<Plus />
</el-icon></el-button>
<el-button circle @click="subList(index)" v-if="index > 0"><el-icon>
<Minus />
</el-icon></el-button>
</div>
</div>
<el-checkbox v-model="isBook" label="这天可预约" style="margin-left: 10px;"/>
<el-button type="success" round @click="saveInfo">保存</el-button>
<el-button type="danger" round @click="closeForm">取消</el-button>
<el-button type="primary" round @click="resetForm">重置</el-button>
</el-drawer>
<el-button type="success" round @click="emittValue" style="margin-left: 100px;">保存</el-button>
</template>
<script setup lang="ts">
import { ref , onMounted , defineEmits} from 'vue'
import { ElMessage } from 'element-plus';
const Selectdate = ref('')
const drawer = ref(false)
const periodObj : any = ref(
{
specificDate: '',
isAvailable: 0,
timePeriodAddRequestList: [
{
timeSlot: '',
minNumber: 0,
maxNumber: 0
}
]
}
)
const periodMap = new Map() //map
const timePickMap = new Map() //
const count = ref(0) //
const timePickArr : any = ref([])
const minArr : any = ref([])
const maxArr : any = ref([])
const isTrue = ref(false) //
const isBook = ref(true)
const appointmentDateAddRequestList :any = ref([]) //
const emit = defineEmits(['calendar-Info'])
onMounted(()=>{
for(let i = 0;i <=50 ; i++) { //
minArr.value[i] = 5+i
maxArr.value[i] = 6+i
}
})
const dateForm =(object : any)=>{ //
Selectdate.value = object.day
periodObj.value.specificDate = object.day
drawer.value = true
}
const closeForm =()=>{ //
drawer.value = false
}
const addList =(index: number)=>{ //
count.value += 1
if(count.value <= 15 && judgeNull(periodObj.value.timePeriodAddRequestList)) {
periodObj.value.timePeriodAddRequestList.push(
{
timeSlot: '',
minNumber: 0,
maxNumber: 0
}
)
timePickArr.value.push([])
} else {
ElMessage({
type:'warning',
message:'请填写完前一段日期后再添加,我知道测试想要干什么!'
})
}
// console.log(index,'--->',periodObj.value);
}
const subList =(index: number)=>{
if(index != 0) {
periodObj.value.timePeriodAddRequestList.splice(index,1)
}
}
const saveTime =(index : number)=>{ //periodObj
try{
periodObj.value.timePeriodAddRequestList[index].timeSlot = timePickArr.value[index][0]+'-'+timePickArr.value[index][1]
} catch {
periodObj.value.timePeriodAddRequestList[index].timeSlot = ''
}
}
const saveInfo =()=>{ //
//
if(!judgeNull(periodObj.value.timePeriodAddRequestList)) {
ElMessage({
type:'warning',
message:'请填写完整时间段和人数!'
})
return;
}
isBook ? periodObj.value.isAvailable = 1 : periodObj.value.isAvailable = 0
periodMap.set(periodObj.value.specificDate,periodObj.value)
timePickMap.set(periodObj.value.specificDate,timePickArr.value)
drawer.value = false
console.log('periodObj--->',periodObj.value);
}
const drawerClean =()=>{ //
periodObj.value = {
specificDate: Selectdate.value,
isAvailable: 0,
timePeriodAddRequestList: [
{
timeSlot: '',
minNumber: 0,
maxNumber: 0
}
]
}
timePickArr.value = []
count.value = 0;
}
const drawerOpen =()=>{ //
isTrue.value = periodMap.has(periodObj.value.specificDate) //
if(isTrue.value) {
periodObj.value = periodMap.get(periodObj.value.specificDate)
timePickArr.value= timePickMap.get(periodObj.value.specificDate)
}
}
const resetForm =()=>{ //
drawerClean() //
if(isTrue.value) { //map
periodMap.delete(periodObj.value.specificDate)
timePickMap.delete(periodObj.value.specificDate)
}
}
const emittValue =()=>{ //
appointmentDateAddRequestList.value.splice(0,appointmentDateAddRequestList.value.length) //
periodMap.forEach(mapFun)
emit('calendar-Info',appointmentDateAddRequestList.value)
}
const mapFun =(value:any ,key:any ,map:any)=>{ //map
if(periodMap.has(key)) {
appointmentDateAddRequestList.value.push(value)
}
console.log(appointmentDateAddRequestList.value);
}
const judgeNull =(List : any)=>{ //
console.log('List--->',List);
if (List.some((item:any) => item.timeSlot==='' || item.minNumber === 0 || item.maxNumber === 0)) {
return false;
}
return true;
}
const minNum =(index : number)=>{ //
if(periodObj.value.timePeriodAddRequestList[index].minNumber > periodObj.value.timePeriodAddRequestList[index].maxNumber && periodObj.value.timePeriodAddRequestList[index].maxNumber != 0) {
ElMessage({
type: 'warning',
message: '最小人数不能大于最大人数'
})
periodObj.value.timePeriodAddRequestList[index].minNumber = 0
return;
}
}
const maxNum =(index : number)=>{
if(periodObj.value.timePeriodAddRequestList[index].maxNumber < periodObj.value.timePeriodAddRequestList[index].minNumber) {
ElMessage({
type: 'warning',
message: '最大人数不能小于最小人数'
})
periodObj.value.timePeriodAddRequestList[index].maxNumber = 0
return;
}
}
</script>
<style scoped>
.calbox {
width: 550px;
height: 280px;
font-size: 12px;
--el-calendar-cell-width: 30px;
}
.timebox {
margin-bottom: 20px;
}
</style>

View File

@ -0,0 +1,92 @@
import { ElMessage } from 'element-plus';
const isNotValid = (val) => {
const timeRegex = /^([0-1]?[0-9]|2[0-3]):([0-5]?[0-9])-(?:[0-1]?[0-9]|2[0-3]):([0-5]?[0-9])$/;
const rangeRegex = /^\(\d+,\d+\)$/
return timeRegex.test(val.timeSlot) && rangeRegex.test(val.numberRange)
}
const isValidPlus = (val) => {
const timeRegex = /^([0-1]?[0-9]|2[0-3]):([0-5]?[0-9])-(?:[0-1]?[0-9]|2[0-3]):([0-5]?[0-9])$/;
const rangeRegex = /^\(\d+,\d+\)$/
if(val.timeSlot === '' && val.numberRange === '') return false
if(timeRegex.test(val.timeSlot) && rangeRegex.test(val.numberRange)) return false
return true
}
export const transfer = (val, arr, isAvailableArr) => {
console.log('这是val:', val)
for (var i = 0; i < val.length; i ++ ) {
for (var j = 0; j < val[i].length; j ++ ) {
arr[i][j].timeSlot = val[i][j].startTime + "-" + val[i][j].endTime
arr[i][j].numberRange = "(" + val[i][j].minNumValue + "," + val[i][j].maxNumValue + ")"
}
}
console.log('这是arr:', arr)
for (var i = 0; i < 4; i ++ ) {
for (var j = 0; j < 6; j ++ ) {
if(isValidPlus(arr[i][j])) {
ElMessage({
type: 'error',
message: '请检查表单数据是否完整填写'
})
return ;
}
}
}
let newArr = new Array(4)
for (var i = 0; i < 4; i ++ ) {
newArr[i] = {
timeSlot:'',
numberRange: '',
isAvailable: false
}
}
let timeSlotArr = []
let numberRangeArr = []
let cnt = 0
let k = 0
for (var i = 0; i < val.length; i ++ ) {
for (var j = 0; j < val[i].length; j ++ ) {
if(isNotValid(arr[i][j])) {
timeSlotArr.push(arr[i][j].timeSlot)
numberRangeArr.push(arr[i][j].numberRange)
}
}
if(val[i].length == 0){
newArr[i].timeSlot = "00:00-00:00"
newArr[i].numberRange = "(0,0)"
newArr[i].isAvailable = 0
k ++
cnt ++
}else{
newArr[i].timeSlot = timeSlotArr.join(';')
newArr[i].numberRange = numberRangeArr.join(';')
newArr[i].isAvailable = isAvailableArr[i] ? 1 : 0
if(!isAvailableArr[i]) k ++
}
if(cnt == 4) {
ElMessage({
type: 'error',
message: '至少得有一个预约时间段'
})
return ;
}
if(k == 4) {
ElMessage({
type: 'error',
message: '至少有一天可以预约'
})
return ;
}
timeSlotArr = []
numberRangeArr = []
}
ElMessage({
type: 'success',
message: '时间段保存成功'
})
// console.log(newArr)
return newArr
}

View File

@ -49,8 +49,6 @@
<el-table-column prop="price" label="商品价格" width="180"></el-table-column>
<el-table-column prop="type" label="商品类型"></el-table-column>
<el-table-column prop="inventory" label="商品数量"></el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column prop="updateTime" label="更新时间"></el-table-column>
<el-table-column label="商品状态">
<template #default="scope">
<div>
@ -370,7 +368,7 @@ const delBatch = async ()=>{
ElMessage.error('删除失败')
}
}
const load =()=>{}
const handleSelectionChange =()=>{}
</script>
<style scoped>

View File

@ -230,7 +230,7 @@ const getCouponsList = async ()=> {
}
}
const handleChange = async (file: any, flag: number) => {
fileSimple.value = filen
fileSimple.value = file
let formData = new FormData() // FormData
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw formData
const res = await myAxios({ //

View File

@ -37,7 +37,7 @@
</template>
<script setup lang="ts">
import {ref, reactive} from 'vue'
import {ref, reactive, onMounted} from 'vue'
import { ElMessage } from 'element-plus'
import {useRouter} from 'vue-router'
import myAxios from '@/api/myAxios';
@ -49,17 +49,29 @@
const router = useRouter()
const store = userStore()
const Login = async ()=>{
if(username.value === '' || password.value === '') {
ElMessage.error('检查账号或密码是否成功填写')
return;
}
const res: any = await myAxios.post("/user/login",{
userAccount: username.value,
userPassword: password.value
})
console.log(res.data.code)
console.log(res.data)
if(res.data.code === 1 && res ?.data) {
//pinia
await store.getLoginUser(res.data.data)
//
await router.replace('/PersonalCenter')
} else {
ElMessage({
type: 'warning',
message: res.data.message
})
return; //
}
}
</script>

View File

@ -4,7 +4,7 @@
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-form ref="resetFormData" :model="form" label-width="auto" style="width: 750px;" size="large">
<div class="totalPicture">
<div class="boxPicture1">
<div>
<el-form-item label="添加课程展示图片">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
@ -42,21 +42,17 @@
</div>
</div>
<el-form-item label="课程简介" prop="intro">
<el-input v-model="form.intro" type="textarea" style="width: 600px;" />
</el-form-item>
<!-- 使用弹窗 -->
<el-form-item label="产品类别" prop="type">
<el-select v-model="selectValue" disabled style="width: 110px;" />
<el-input v-model="form.intro" type="textarea" style="width: 500px;" />
</el-form-item>
<el-form-item label="商品标签" prop="label">
<el-input v-model="form.label" type="textarea" placeholder="使用英文;分隔符分开" style="width: 600px;" />
<el-input v-model="form.label" type="textarea" placeholder="使用英文;分隔符分开" style="width: 500px;" />
</el-form-item>
<el-form-item label="商品详细描述" prop="introDetail">
<el-input v-model="form.introDetail" type="textarea" placeholder="产品尺寸,服务等" style="width: 600px;" />
<el-input v-model="form.introDetail" type="textarea" placeholder="产品尺寸,服务等" style="width: 500px;" />
</el-form-item>
<div class="totalButton">
<el-form-item>
<el-button type="primary" @click="onSubmit">上架</el-button>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetForm">重置</el-button>
@ -65,88 +61,66 @@
</el-form>
</div>
<div class="timeTable">
<appointTime></appointTime>
<!-- <appointTime @time-Info="getInfo"></appointTime> -->
<calendarUtil @calendar-info="getInfo"></calendarUtil>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, inject } from 'vue';
import { ref, onMounted, inject, toRaw } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ElMessage, type UploadFile, type UploadProps, genFileId, type UploadRawFile } from 'element-plus';
import myAxios from "@/api/myAxios";
import appointTime from '@/layout/components/appointTime.vue';
import calendarUtil from '@/layout/components/calendarUtil.vue';
const fileSimple = ref() //
const uploadedFiles = ref<UploadFile[]>([]);//
const uploadedDescription = ref<UploadFile[]>([]);//
const resetFormData = ref()
const selectValue = '服务类'
const dialogVisible = ref(false)
const count = ref(1)
const form = ref({
name: '',
price: '', //
intro: '',//
type: '',//
label: '',//
introDetail: '',//
goodImg: '', //url
detailImg: '', //url
timePeriod: '',
people: 0,
date: []
appointmentDateAddRequestList: [] //
})
//
const reload: any = inject("reload")
const uploadProductImg: any = ref() //ref
const uploadProductDetail: any = ref() //ref
// const startTime = ref('')
// const endTime = ref('')
// const timeList = ref(
// {
// days: [0,1,2,3], //0
// slot: Array.from({ length:8 },()=>({
// startTime: '',
// endTime: ''
// }))
// }
// )
const timeList = ref([
{
slot: Array.from({ length: 8 }, () => ({
startTime: '',
endTime: ''
}))
}
])
//
const arr = ref([
{
timeSlot: '',
isAvailable: 1,
numberRange: ''
}
]);
const myDate = new Date();
onMounted(() => {
console.log(myDate.getHours()); //
// console.log(myDate.getHours()); //
})
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
}
//
const onSubmit = async () => {
const onSubmit = async () => {
const values = Object.values(form.value);
// 使some()
if (values.some(value => value === null || value === undefined || value === '')) {
if (values.some(value => value === null || value === undefined || value === '') || form.value.appointmentDateAddRequestList.length == 0) {
ElMessage({
type: 'warning',
message: '请检查表单数据是否完整填写'
})
return; //
}
const res = await myAxios.post('/goods/add', { ...form.value })
console.log(form.value);
const res = await myAxios.post('/goods/add/service', {
name: form.value.name,
price: form.value.price,
goodImg: form.value.goodImg,
intro: form.value.intro,
introDetail: form.value.introDetail,
detailImg: form.value.detailImg,
label: form.value.label,
appointmentDateAddRequestList: toRaw(form.value.appointmentDateAddRequestList)
})
console.log(res.data);
if (res.data.code === 1) {
ElMessage({
type: 'success',
@ -196,23 +170,10 @@ const Exceed_ProductDetail: UploadProps['onExceed'] = (files) => { //覆盖商
file.uid = genFileId()
uploadProductDetail.value!.handleStart(file)
}
const showDatePop = () => {
dialogVisible.value = true
}
const handleClose = () => {
dialogVisible.value = false;
}
const addList = (index: number, row: number) => {
console.log(index, row);
// if (count.value <= 6) {
// timeList.value[row+1] = {
// startTime: '',
// endTime: ''
// }
// }
}
const subList = (index: number, row: number) => {
// arr.value[index].splice(index, 1)
const getInfo =(info:any)=>{
console.log('info-->',info);
// timeInfo.value = info
form.value.appointmentDateAddRequestList = info
}
</script>
@ -222,8 +183,7 @@ const subList = (index: number, row: number) => {
}
.fromBox {
border: 1px solid red;
width: 750px;
width: 700px;
height: 750px;
}
@ -240,7 +200,9 @@ const subList = (index: number, row: number) => {
justify-content: space-evenly;
/* 盒子里面水平分隔开 */
}
.midBox {
display: flex;
}
.date-picker {
flex: 0.3;
/* 日期选择区域占据左边 */
@ -265,4 +227,5 @@ const subList = (index: number, row: number) => {
margin-bottom: 10px;
border: 1px solid orange;
}
</style>

View File

@ -1,11 +1,358 @@
<template>
<div>123</div>
<!-- 修改前请注释以前的 -->
<!-- 搜索 -->
<div>
<el-input style="width: 200px; height: 30px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入课程名称"
v-model="productName"></el-input>
<el-form-item label="商品状态" style="width: 200px;margin-right: 10px;display: inline-block">
<el-select v-model="state" placeholder="请选择" @change="(event: any) => searchByState(event)">
<el-option label="已上架" value="1" />
<el-option label="已下架" value="0" />
</el-select>
</el-form-item>
<el-button class="ml-5" type="primary" @click="onSearch(productName)" style="height: 25px;">搜索</el-button>
<el-button type="warning" @click="reset" style="height:25px">重置</el-button>
</div>
<div style="margin: 15px 0">
<el-popconfirm class="ml-5" confirm-button-text='确定' cancel-button-text='取消' icon="InfoFilled" icon-color="red"
title="您确定批量删除这些数据吗?" @confirm="delBatch" width=180>
<template #reference>
<el-button style="height: 25px" class="ml-5" type="danger">批量删除 <el-icon style="margin-left: 5px;">
<Remove />
</el-icon></el-button>
</template>
</el-popconfirm>
</div>
<!-- 数据展示 -->
<el-table :data="tableData" border stripe header-cell-class-name="headerBg"
:cell-style="{ 'text-align': 'center', 'font-size': '16px' }" @selection-change="handleSelectionChange"
:header-cell-style="{ 'text-align': 'center' }">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="课程编号" width="80">
<template #default="{ $index }">
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column prop="goodImg" label="课程图片">
<template #default="scope">
<div>
<img :src="scope.row.goodImg" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
<el-table-column prop="name" label="课程名称"></el-table-column>
<el-table-column prop="price" label="单次价格" width="100"></el-table-column>
<el-table-column label="展开时间段" type="expand" width="80">
<template #default="{ $index,row }">
<!-- 放后端传来的预约时间 -->
<el-table :data="appointmentDateArr[$index]" :header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }">
<el-table-column label="是否可预约" prop="isAvailable" />
<el-table-column label="日期" prop="specificDate" />
<el-table-column label="操作">
<el-button size="small" @click="">
详情
</el-button>
<el-button size="small" @click="openDrawer">
编辑
</el-button>
<el-button class="ml-5" type="danger">删除</el-button>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="商品状态" width="80">
<template #default="scope">
<div>
<span style="margin-left: 10px" v-if="scope.row.isShelves == 1">上架</span>
<span style="margin-left: 10px" v-if="scope.row.isShelves == 0">下架</span>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="250px">
<template #default="scope">
<el-button size="small" @click="ReviseOrView(scope.$index, scope.row , 0)">
详情
</el-button>
<el-button size="small" @click="ReviseOrView(scope.$index, scope.row, 1)">
编辑
</el-button>
<el-button size="small" @click="handleOff(scope.$index, scope.row)">
<div v-if="scope.row.isShelves == 1">下架 </div>
<div v-if="scope.row.isShelves == 0">上架 </div>
</el-button>
<el-popconfirm class="ml-5" confirm-button-text='确定' cancel-button-text='取消' icon="InfoFilled" icon-color="red"
title="是否确认删除" @confirm="deleteProduct(scope.row.id)" width=180>
<template #reference>
<el-button class="ml-5" type="danger">删除</el-button>
</template>
</el-popconfirm>
<el-popconfirm confirm-button-text='确定' cancel-button-text='取消' icon="el-icon-info" icon-color="red"
title="您确定删除吗?">
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!-- 分页器 -->
<div style="padding: 10px 0">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="searchParams.current" :page-size="searchParams.pageSize" :page-sizes="[5, 10, 15, 20]"
:small="null" :disabled="null" :background="null" layout="total, sizes, prev, pager, next, jumper"
:total="total" />
</div>
<!-- 编辑/详情表单 -->
<el-dialog v-model="DialogVisible" :title="title">
<el-form label-width="100px" :disabled="disabled">
<el-form-item label="商品编号">
<el-input v-model="editForm.id" disabled></el-input>
</el-form-item>
<el-form-item label="商品图片">
<div v-if="editForm.goodImg">
<img :src="editForm.goodImg" alt="商品图标" class="thumbnail" style="width: 100px; height: 100px;" />
</div>
<el-upload ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 0)" :on-exceed="Exceed_ProductImg"
limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="商品名称">
<el-input v-model="editForm.name"></el-input>
</el-form-item>
<el-form-item label="商品价格">
<el-input v-model="editForm.price"></el-input>
</el-form-item>
<el-form-item label="商品数量">
<el-input v-model="editForm.inventory"></el-input>
</el-form-item>
<el-form-item label="商品状态">
<el-select v-model="editForm.isShelves">
<el-option label="上架" value="上架" />
<el-option label="下架" value="下架" />
</el-select>
</el-form-item>
<el-form-item label="是否为限定类产品" prop="festivalOrder">
<el-select v-model="editForm.festivalOrder" @change="(event: any) => loadForm(event, 0)">
<el-option label="是" value="1" />
<el-option label="否" value="0" />
</el-select>
</el-form-item>
<el-form-item label="商品标签">
<el-input v-model="editForm.label"></el-input>
</el-form-item>
<el-form-item label="商品图文">
<div v-if="editForm.detailImg">
<img :src="editForm.detailImg" alt="商品图标" class="thumbnail" style="width: 100px; height: 100px;" />
</div>
<el-upload ref="uploadProductDetail" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 1)" :on-exceed="Exceed_ProductDetail"
limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="商品描述">
<el-input type="textarea" v-model="editForm.introDetail"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="DialogVisible = false" :disabled="disabled">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
</span>
</template>
</el-dialog>
<!-- 时间段抽屉 -->
<el-drawer
v-model="drawer"
title="I am the title"
direction="ltr"
>
<span>Hi, there!</span>
</el-drawer>
</template>
<script setup lang="ts">
import { ElMessage , type UploadProps , genFileId ,type UploadRawFile } from 'element-plus';
import { ref, onMounted, inject } from 'vue';
import myAxios from "@/api/myAxios";
const total = ref(0); //
const idList = ref([]);
const searchParams: any = ref({ //
current: 1, //
pageSize: 5, //
sortField: "id", //ID
sortOrder: "descend" //
})
const tableData : any= ref([]);
const appointmentDateArr : any = ref([])
const disabled = ref(true)
const title = ref('') //
const productName = ref('');
const DialogVisible = ref(false);
const state = ref(''); //select
const editForm : any = ref({});
const reload : any = inject("reload") //
const fileSimple = ref()
const uploadProductImg : any = ref() //ref
const uploadProductDetail : any = ref() //ref
const drawer = ref(false)
onMounted(() => { //
getProductList()
})
const getProductList = async () => {
try {
const res = await myAxios.post('/goods/service/list/page', { ...searchParams.value });
// console.log('res--->',res.data)
if (res.data.code === 1) {
tableData.value = res.data.data.records;
total.value = parseInt(res.data.data.total) //
appointmentDateArr.value.splice(0,total.value)
console.log(tableData.value);
tableData.value.forEach((val : any) => {
appointmentDateArr.value.push(val.appointmentDateVOList)
})
console.log('时间--->',appointmentDateArr.value);
} else {
ElMessage({
message: '获取数据失败',
});
return;
}
} catch (error) {
ElMessage({
message: '发生错误',
});
}
}
const saveEdit = async () => { //
}
const searchByState = (event : any) => { ///
searchParams.value.isShelves = event
searchParams.value.current = 1
getProductList()
}
//
const deleteProduct = async (index: number) => {
console.log(typeof index)
const res = await myAxios.post('/goods/delete', { id: index })
console.log(res)
if (res.data.code === 1) {
ElMessage({
type: 'success',
message: '删除成功',
})
getProductList()
}
}
//--->
//
const ReviseOrView = (index: number, row: any , flag : number) => {
//flag disabled
flag ? (title.value = "编辑商品" , disabled.value = false) : (title.value = "商品详情" , disabled.value = true)
DialogVisible.value = true;
editForm.value = row;
};
//()
const handleOff = async (index: number, row: any) => {
row.isShelves ? row.isShelves = 0 : row.isShelves = 1 //
editForm.value = row;
const res = await myAxios.post('/goods/update',{...editForm.value})
if(res.data.code === 1) {
ElMessage({
type:'success',
message:'更新成功'
})
}
}
//
const handleSizeChange = (newSize: any) => {
searchParams.value.pageSize = newSize //
getProductList()
}
//
const handleCurrentChange = (Current: any) => {
searchParams.value.current = Current
getProductList()
}
//
const reset = () => {
reload()
};
// --
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
}
const Exceed_ProductImg: UploadProps['onExceed'] = (files , flag) => { //
uploadProductImg.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductImg.value!.handleStart(file)
}
const Exceed_ProductDetail: UploadProps['onExceed'] = (files) => { //
uploadProductDetail.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductDetail.value!.handleStart(file)
}
// //
const loadForm = (value: any, flag: number) => {
flag ? editForm.value.type = value : editForm.value.festivalOrder = value // flag=1 "" flag=0
}
//
const handleChange = async (file: any, flag: number) => {
fileSimple.value = file
let formData = new FormData() // FormData
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw formData
const res = await myAxios({ //
url: '/file/upload/server/not_login',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
file: formData.get("file") // formDatafile
}
})
if (res.data.code === 1) {
// flag0 flag1
flag ? editForm.value.detailImg = res.data.data : editForm.value.goodImg = res.data.data
}
}
const onSearch = (data : String)=>{ //
searchParams.value.name = data
searchParams.value.current = 1
getProductList()
}
//
const delBatch = async ()=>{
console.log(idList.value);
const res = await myAxios.post('/goods/delBatch',{
idList: idList.value
})
console.log(res.data);
if(res.data.code === 1) {
ElMessage({
type: 'success',
message: '批量删除成功'
})
getProductList()
} else {
ElMessage.error('删除失败')
}
}
const handleSelectionChange =()=>{}
const openDrawer =()=>{
drawer.value = true
}
</script>
<style scoped>
.headerBg {
background-color: #eee !important;
}
</style>

View File

@ -1,182 +1,47 @@
<!--<template>-->
<!-- <div class="demo-date-picker">-->
<!-- <div class="block">-->
<!-- <span class="demonstration">选择日期</span>-->
<!-- <el-date-picker-->
<!-- v-model="valueData"-->
<!-- type="daterange"-->
<!-- range-separator="到"-->
<!-- start-placeholder="起始日期"-->
<!-- end-placeholder="截至日期"-->
<!-- :size="size"-->
<!-- />-->
<!-- </div>-->
<!-- </div>-->
<!-- <div style="margin-bottom: 10px">-->
<!-- <el-button @click="addTimePickers">添加时间段</el-button>-->
<!-- </div>-->
<!-- <div v-for="(timeData, index) in timeDataList" :key="index">-->
<!-- <el-time-picker v-model="timeData.value1" placeholder="设置时间段" />-->
<!-- //////////////////-->
<!-- <el-time-picker-->
<!-- v-model="timeData.value2"-->
<!-- is-range-->
<!-- range-separator="到"-->
<!-- start-placeholder="起始时间"-->
<!-- end-placeholder="截至时间"-->
<!-- />-->
<!-- <el-button @click="deleteTimePicker(index)">删除时间段</el-button>-->
<!-- </div>-->
<!--</template>-->
<!--<script lang="ts" setup>-->
<!--import { ref } from 'vue';-->
<!--import { ElButton, ElDatePicker, ElTimePicker } from 'element-plus';-->
<!--const size = ref<'default' | 'large' | 'small'>('default');-->
<!--const valueData = ref('');-->
<!--const timeDataList = ref<{ value1: string; value2: [Date, Date] }[]>([]);-->
<!--const addTimePickers = () => {-->
<!-- timeDataList.value.push({-->
<!-- value1: '',-->
<!-- value2: [new Date(), new Date()]-->
<!-- });-->
<!--};-->
<!--const deleteTimePicker = (index: number) => {-->
<!-- timeDataList.value.splice(index, 1);-->
<!--};-->
<!--</script>-->
<!--<style scoped>-->
<!--.demo-date-picker {-->
<!-- display: flex;-->
<!-- width: 100%;-->
<!-- padding: 0;-->
<!-- flex-wrap: wrap;-->
<!--}-->
<!--.demo-date-picker .block {-->
<!-- padding: 30px 0;-->
<!-- text-align: center;-->
<!-- border-right: solid 1px var(&#45;&#45;el-border-color);-->
<!-- flex: 1;-->
<!--}-->
<!--.demo-date-picker .block:last-child {-->
<!-- border-right: none;-->
<!--}-->
<!--.demo-date-picker .demonstration {-->
<!-- display: block;-->
<!-- color: var(&#45;&#45;el-text-color-secondary);-->
<!-- font-size: 14px;-->
<!-- margin-bottom: 20px;-->
<!--}-->
<!--.example-basic .el-date-editor {-->
<!-- margin: 8px;-->
<!--}-->
<!--.is-selected {-->
<!-- color: #1989fa;-->
<!-- position: relative;-->
<!--}-->
<!--.is-selected::after {-->
<!-- content: '✔️';-->
<!-- position: absolute;-->
<!-- right: 5px;-->
<!-- top: 5px;-->
<!--}-->
<!--.disabled {-->
<!-- color: #ccc;-->
<!-- cursor: not-allowed;-->
<!--}-->
<!--</style>-->
<template>
<el-calendar :disabled-date="disabledDate">
<template #date-cell="{ data }">
<p
:class="[
selectedDates.includes(data.day) ? 'is-selected' : '',
isFutureDate(data.day) ? '' : 'disabled'
]"
@click="handleDateClick(data.day)"
class="calendar-date-cell"
>
{{ data.day.split('-').slice(1).join('-') }}
<span v-if="selectedDates.includes(data.day)"></span>
</p>
</template>
</el-calendar>
<div class="demo-range">
<el-time-picker
v-model="value1"
is-range
range-separator="To"
start-placeholder="Start time"
end-placeholder="End time"
@change="abc"
/>
<el-time-picker
v-model="value2"
is-range
arrow-control
range-separator="To"
start-placeholder="Start time"
end-placeholder="End time"
/>
</div>
</template>
<script setup>
import { ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue'
const selectedDates = ref([]); //
//
const disabledDate = (date) => {
const today = new Date();
const dateString = date.toISOString().split('T')[0]; // YYYY-MM-DD
const todayString = today.toISOString().split('T')[0];
return dateString < todayString; //
};
//
const isFutureDate = (date) => {
const today = new Date().toISOString().split('T')[0]; // : YYYY-MM-DD
return date >= today; //
};
//
const handleDateClick = (date) => {
if (isFutureDate(date)) {
//
if (selectedDates.value.includes(date)) {
selectedDates.value = selectedDates.value.filter(d => d !== date);
} else {
//
selectedDates.value.push(date);
}
}
};
const value1 = ref<[Date, Date]>([
new Date(2016, 9, 10, 8, 40),
new Date(2016, 9, 10, 9, 40),
])
const value2 = ref<[Date, Date]>([
new Date(2016, 9, 10, 8, 40),
new Date(2016, 9, 10, 9, 40),
])
const abc=()=>{
console.log(value1.value);
}
</script>
<style scoped>
.calendar-date-cell {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
<style>
.demo-range .el-date-editor {
margin: 8px;
}
.is-selected {
color: black;
border-radius: 50%;
.demo-range .el-range-separator {
box-sizing: content-box;
}
.disabled {
color: #dcdfe6;
pointer-events: none;
}
.custom-calendar /deep/ .el-calendar-table .el-calendar-day{
height: 50px;
}
</style>
</style>

View File

@ -7,6 +7,11 @@
{
"path": "./tsconfig.app.json"
}
]
],
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true
}
}