index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. <template>
  2. <div class="carousel">
  3. <!-- <Banner /> -->
  4. <div class="content">
  5. <byTable
  6. :source="sourceList.data"
  7. :pagination="sourceList.pagination"
  8. :config="config"
  9. :loading="loading"
  10. highlight-current-row
  11. :action-list="[
  12. {
  13. text: '添加轮播图',
  14. action: () => openModal('add'),
  15. },
  16. ]"
  17. @get-list="getList">
  18. <template #slotName="{ item }">
  19. {{ item.createTime }}
  20. </template>
  21. </byTable>
  22. </div>
  23. <el-dialog :title="modalType == 'add' ? '新增' : '编辑'" v-model="dialogVisible" width="800" v-loading="loading">
  24. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="byform">
  25. <template #carouselUrl>
  26. <el-row style="width: 100%">
  27. <el-col :span="6">
  28. <el-form-item prop="carouselUrl">
  29. <el-upload
  30. class="uploader-icon"
  31. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  32. :data="carouselUrlOne"
  33. :show-file-list="false"
  34. accept=".gif, .jpeg, .jpg, .png"
  35. :on-success="carouselUrlSuccess"
  36. :before-upload="uploadCarouselUrl">
  37. <el-image
  38. v-if="formData.data.carouselUrlList && formData.data.carouselUrlList.length > 0"
  39. :src="formData.data.carouselUrlList[0].fileUrl"
  40. fit="scale-down"
  41. class="avatar" />
  42. <el-icon v-else class="uploader-icon"><Plus /></el-icon>
  43. </el-upload>
  44. <el-button
  45. class="delete-btn"
  46. type="danger"
  47. v-if="formData.data.carouselUrlList && formData.data.carouselUrlList.length > 0"
  48. @click="formData.data.carouselUrlList = []">
  49. 删除
  50. </el-button>
  51. </el-form-item>
  52. </el-col>
  53. </el-row>
  54. </template>
  55. <template #menuId>
  56. <el-form-item prop="menuId">
  57. <el-select
  58. v-model="formData.data.columnId"
  59. :rule="rules.columnId"
  60. placeholder="请选择菜单"
  61. no-data-text="无数据,请到栏目菜单添加"
  62. @change="(val) => getArticleListSelect(val)"
  63. >
  64. <el-option
  65. v-for="item in columnListData"
  66. :label="item.name"
  67. :value="item.id"
  68. >
  69. </el-option>
  70. </el-select>
  71. </el-form-item>
  72. </template>
  73. </byForm>
  74. <template #footer>
  75. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  76. <el-button type="primary" v-no-double-click="submitForm" size="large" :loading="submitLoading">确 定</el-button>
  77. </template>
  78. </el-dialog>
  79. </div>
  80. </template>
  81. <script setup>
  82. /* eslint-disable vue/no-unused-components */
  83. import { ElMessage, ElMessageBox } from "element-plus";
  84. import byTable from "@/components/byTable/index.vue";
  85. import byForm from "@/components/byForm/index.vue";
  86. import { computed, ref } from "vue";
  87. import {getDictOneByXmhjc, getFileList, getFileStr} from "@/api/XMHJC/common";
  88. import {findColumnArticleList, findMenuListByOpen} from "@/api/XMHJC/column";
  89. const loading = ref(false);
  90. const submitLoading = ref(false);
  91. const enableStatus = ref([]);
  92. const carouselModules = ref([]);
  93. const articleList = ref([]);
  94. const columnListData = ref([]);
  95. const targetType = ref([]);
  96. const sourceList = ref({
  97. data: [],
  98. pagination: {
  99. total: 3,
  100. pageNum: 1,
  101. pageSize: 10,
  102. },
  103. });
  104. let dialogVisible = ref(false);
  105. let modalType = ref("add");
  106. let rules = ref({
  107. modules: [{ required: true, message: "请选择所属模块" }],
  108. title: [{ required: true, message: "请输入标题" }],
  109. status: [{ required: true, message: "请选择启用状态", trigger: "change" }],
  110. sort: [{ required: true, message: "请输入排序", trigger: "blur" }],
  111. carouselUrl: [{ required: true, message: "请上传轮播图", trigger: "blur" }],
  112. });
  113. const { proxy } = getCurrentInstance();
  114. const config = computed(() => {
  115. return [
  116. {
  117. attrs: {
  118. label: "所属模块",
  119. prop: "modules",
  120. },
  121. render(type) {
  122. return proxy.dictValueLabel(type, carouselModules.value);
  123. },
  124. },
  125. {
  126. attrs: {
  127. label: "标题",
  128. prop: "title",
  129. },
  130. },
  131. {
  132. attrs: {
  133. label: "副标题",
  134. prop: "subTitle",
  135. },
  136. },
  137. {
  138. attrs: {
  139. label: "排序",
  140. prop: "sort",
  141. align: "center",
  142. },
  143. },
  144. {
  145. attrs: {
  146. label: "状态",
  147. prop: "status",
  148. },
  149. render(type) {
  150. return proxy.dictValueLabel(type, enableStatus.value);
  151. },
  152. },
  153. {
  154. attrs: {
  155. label: "操作",
  156. width: "200",
  157. align: "right",
  158. },
  159. // 渲染 el-button,一般用在最后一列。
  160. renderHTML(row) {
  161. return [
  162. {
  163. attrs: {
  164. label: row.status == 1 ? "禁用" : "启用",
  165. type: "primary",
  166. text: true,
  167. },
  168. el: "button",
  169. click() {
  170. changeStatus(row);
  171. },
  172. },
  173. {
  174. attrs: {
  175. label: "编辑",
  176. type: "primary",
  177. text: true,
  178. },
  179. el: "button",
  180. click() {
  181. getDetail(row);
  182. },
  183. },
  184. {
  185. attrs: {
  186. label: "删除",
  187. type: "danger",
  188. text: true,
  189. },
  190. el: "button",
  191. click() {
  192. del(row);
  193. },
  194. },
  195. ];
  196. },
  197. },
  198. ];
  199. });
  200. let formData = reactive({
  201. data: {},
  202. treeData: [],
  203. carouselUrlList:[],
  204. });
  205. const formOption = reactive({
  206. inline: true,
  207. labelWidth: 100,
  208. itemWidth: 100,
  209. rules: [],
  210. });
  211. const byform = ref(null);
  212. const formConfig = computed(() => {
  213. return [
  214. {
  215. label: "所属模块",
  216. prop: "modules",
  217. type: "select",
  218. data: carouselModules.value,
  219. required: true,
  220. },
  221. {
  222. type: "input",
  223. prop: "title",
  224. label: "标题",
  225. itemWidth: 100,
  226. maxlength: 10,
  227. itemType: "text",
  228. },
  229. {
  230. type: "input",
  231. prop: "subTitle",
  232. label: "副标题",
  233. maxlength: 30,
  234. },
  235. {
  236. type: "slot",
  237. slotName: "carouselUrl",
  238. prop: "carouselUrl",
  239. label: "轮播图",
  240. },
  241. {
  242. label: "跳转方式",
  243. prop: "targetType",
  244. type: "select",
  245. data: targetType.value,
  246. },
  247. {
  248. type: "input",
  249. prop: "url",
  250. label: "外链URL",
  251. maxlength: 100,
  252. isShow: formData.data.targetType == 2,
  253. },
  254. {
  255. type: "slot",
  256. slotName: "menuId",
  257. prop: "menuId",
  258. label: "菜单",
  259. required: true,
  260. },
  261. {
  262. label: "跳转文章",
  263. prop: "articleId",
  264. type: "select",
  265. data: articleList.value,
  266. filterable: true,
  267. isShow: formData.data.targetType == 1,
  268. },
  269. {
  270. label: "启用状态",
  271. prop: "status",
  272. type: "select",
  273. data: enableStatus.value,
  274. required: true,
  275. },
  276. {
  277. type: "input",
  278. itemType: "number",
  279. prop: "sort",
  280. label: "排序",
  281. style: {
  282. width: "50%",
  283. },
  284. },
  285. ];
  286. });
  287. const getList = async (req) => {
  288. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  289. loading.value = true;
  290. proxy.post("/carouselManager/page", sourceList.value.pagination).then((message) => {
  291. console.log(message);
  292. sourceList.value.data = message.rows;
  293. sourceList.value.pagination.total = message.total;
  294. setTimeout(() => {
  295. loading.value = false;
  296. }, 200);
  297. });
  298. };
  299. const openModal = () => {
  300. dialogVisible.value = true;
  301. modalType.value = "add";
  302. formData.data = {};
  303. };
  304. const submitForm = () => {
  305. byform.value.handleSubmit((valid) => {
  306. submitLoading.value = true;
  307. proxy.post("/carouselManager/" + modalType.value, formData.data)
  308. .then((res) => {
  309. ElMessage({
  310. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  311. type: "success",
  312. });
  313. dialogVisible.value = false;
  314. submitLoading.value = false;
  315. getList();
  316. })
  317. .catch((err) => {
  318. submitLoading.value = false;
  319. });
  320. });
  321. };
  322. const changeStatus = (row) => {
  323. modalType.value = "edit";
  324. let status = row.status=='1' ? 0 : 1;
  325. proxy.post("/carouselManager/detail", { id: row.id }).then((res) => {
  326. res.status = status;
  327. formData.data = res;
  328. ElMessageBox.confirm("你是否确认此操作?", "提示", {
  329. confirmButtonText: "确定",
  330. cancelButtonText: "取消",
  331. type: "warning",
  332. }).then(() => {
  333. // 更新状态
  334. proxy.post("/carouselManager/" + modalType.value, formData.data).then((res) => {
  335. ElMessage({
  336. message: "操作成功",
  337. type: "success",
  338. });
  339. getList();
  340. });
  341. });
  342. });
  343. };
  344. //编辑详情
  345. const getDetail = (row) => {
  346. modalType.value = "edit";
  347. proxy.post("/carouselManager/detail", { id: row.id }).then((res) => {
  348. formData.data = res;
  349. getFileList({businessIdList: [res.id], fileType: 1}).then((resFile) => {
  350. formData.data.carouselUrlList = resFile.data[res.id];
  351. formData.data.carouselUrl = resFile.data[res.id];
  352. dialogVisible.value = true;
  353. });
  354. });
  355. };
  356. //删除
  357. const del = (row) => {
  358. modalType.value = "edit";
  359. ElMessageBox.confirm("你是否确认此操作?", "提示", {
  360. confirmButtonText: "确定",
  361. cancelButtonText: "取消",
  362. type: "warning",
  363. }).then(() => {
  364. proxy.post("/carouselManager/delete", { id: row.id }).then((res) => {
  365. ElMessage({
  366. message: "操作成功",
  367. type: "success",
  368. });
  369. getList();
  370. });
  371. });
  372. };
  373. //获取字典
  374. const getDictlist = async () => {
  375. const res = await getDictOneByXmhjc(["enable_status", "carousel_modules", "carousel_target_type"]);
  376. enableStatus.value = res["enable_status"].map((x) => ({
  377. label: x.dictValue,
  378. value: x.dictKey,
  379. }));
  380. carouselModules.value = res["carousel_modules"].map((x) => ({
  381. label: x.dictValue,
  382. value: x.dictKey,
  383. }));
  384. targetType.value = res["carousel_target_type"].map((x) => ({
  385. label: x.dictValue,
  386. value: x.dictKey,
  387. }));
  388. };
  389. //获取文章列表
  390. const getArticleListSelect = async (value) => {
  391. formData.data.articleId = ""
  392. await getArticleList(value)
  393. };
  394. //获取文章列表
  395. const getArticleList = async (value) => {
  396. const res = await findColumnArticleList({
  397. pageNum: 1,
  398. pageSize: 99999,
  399. status: 1,
  400. columnId: value,
  401. });
  402. articleList.value = res.data.rows.map((x) => ({
  403. label: x.title,
  404. value: x.id,
  405. }));
  406. };
  407. //图片上传相关
  408. const carouselUrlOne = ref({});
  409. const uploadCarouselUrl = async (file) => {
  410. const res = await getFileStr({ fileName: file.name });
  411. carouselUrlOne.value = res.data.uploadBody;
  412. file.id = res.data.id;
  413. file.fileName = res.data.fileName;
  414. file.fileUrl = res.data.fileUrl;
  415. return true;
  416. };
  417. const carouselUrlSuccess = (response, uploadFile) => {
  418. formData.data.carouselUrlList = [
  419. {
  420. id: uploadFile.raw.id,
  421. fileName: uploadFile.raw.fileName,
  422. fileUrl: uploadFile.raw.fileUrl,
  423. },
  424. ];
  425. formData.data.carouselUrl = uploadFile.raw.fileUrl;
  426. };
  427. const getMenuList = async () => {
  428. const res = await findMenuListByOpen({})
  429. columnListData.value = res.data
  430. };
  431. getMenuList()
  432. getList();
  433. getDictlist();
  434. </script>
  435. <style lang="scss" scoped>
  436. .tenant {
  437. padding: 20px;
  438. }
  439. .el-icon.uploader-icon {
  440. font-size: 28px;
  441. color: #8c939d;
  442. width: 110px;
  443. height: 110px;
  444. text-align: center;
  445. border: 1px dashed var(--el-border-color);
  446. }
  447. </style>