index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. <template>
  2. <div class="tenant">
  3. <byTable
  4. :source="sourceList.data"
  5. :pagination="sourceList.pagination"
  6. :config="config"
  7. :loading="loading"
  8. highlight-current-row
  9. :selectConfig="selectConfig"
  10. :table-events="{
  11. select: select,
  12. }"
  13. :action-list="[
  14. {
  15. text: '添加栏目菜单',
  16. action: () => openModal('add'),
  17. },
  18. ]"
  19. @get-list="getList">
  20. <template #listType="{ item }">
  21. {{ getCellColumn(item) }}
  22. </template>
  23. </byTable>
  24. <el-dialog z-index="1100" :title="modalType == 'add' ? '添加栏目菜单' : '编辑栏目菜单'" v-if="dialogVisible" v-model="dialogVisible" width="80%" v-loading="loading">
  25. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="byform">
  26. <template #subColumn>
  27. <el-row style="width: 100%;margin-bottom: 10px" v-for="(row, index) in formData.data.columnMenuSubList" ref="sort">
  28. <el-col :span="7" >
  29. <el-form-item
  30. :prop="'columnMenuSubList.' + index + '.name'"
  31. :rules="rules.subName"
  32. prop="name"
  33. style="margin: 8px 0 8px 0">
  34. <el-input v-model="row.name" placeholder="请输入子栏目" :controls="false" />
  35. </el-form-item>
  36. </el-col>
  37. <el-col :span="6" >
  38. <el-form-item
  39. :prop="'columnMenuSubList.' + index + '.status'"
  40. :rules="rules.subStatus" style="margin-left: 8px;transform: translateY(8px)"
  41. prop="status">
  42. <el-select clearable v-model="row.status" placeholder="请选择状态" >
  43. <el-option v-for="item in enableStatus" :key="item.value" :label="item.label" :value="item.value" />
  44. </el-select>
  45. </el-form-item>
  46. </el-col>
  47. <el-col :span="6" >
  48. <el-form-item
  49. :prop="'columnMenuSubList.' + index + '.sort'"
  50. :rules="rules.subSort" style="margin-left: 8px;transform: translateY(8px)"
  51. prop="sort">
  52. <el-input-number v-model="row.sort" placeholder="请输入排序" :precision="0" :max="999" :min="0" />
  53. </el-form-item>
  54. </el-col>
  55. <el-col :span="5" >
  56. <el-icon style="margin-left: 8px; color: red; cursor: pointer; transform: translateY(10px)" @click="clickDelete(index)"><Delete /></el-icon>
  57. </el-col>
  58. </el-row>
  59. <el-row style="width: 100%">
  60. <el-row>
  61. <el-button type="primary" @click="clickAddSubColumn()">添加</el-button>
  62. </el-row>
  63. </el-row>
  64. </template>
  65. <template #detailsContent>
  66. <div style="width: 100%" v-if="dialogVisible">
  67. <TinymceEditor
  68. :value="formData.data.content"
  69. @updateValue="updateHandover"
  70. ref="contentEditor"
  71. />
  72. </div>
  73. </template>
  74. </byForm>
  75. <template #footer>
  76. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  77. <el-button type="primary" v-no-double-click="submitForm" size="large" :loading="submitLoading">确 定</el-button>
  78. </template>
  79. </el-dialog>
  80. </div>
  81. </template>
  82. <script setup>
  83. import { ElMessage, ElMessageBox } from "element-plus";
  84. import byTable from "@/components/byTable/index";
  85. import byForm from "@/components/byForm/index";
  86. import {computed, nextTick, reactive, ref} from "vue";
  87. import TinymceEditor from "@/components/Editor/TinymceEditor.vue";
  88. import {getDictOneByXmhjc, getFileList,getFileStr} from "@/api/XMHJC/common";
  89. import {
  90. addColumnMenu, checkDeleteColumnMenuSub, deleteColumnMenu,
  91. editColumnMenu, findColumnArticleList,
  92. findColumnMenuList,
  93. getColumnMenu
  94. } from "@/api/XMHJC/column";
  95. import {isNullOrUndefined} from "@tinymce/tinymce-vue/lib/es2015/main/ts/Utils";
  96. const loading = ref(false);
  97. const submitLoading = ref(false);
  98. const sourceList = ref({
  99. data: [],
  100. pagination: {
  101. total: 0,
  102. pageNum: 1,
  103. pageSize: 10,
  104. },
  105. });
  106. let dialogVisible = ref(false);
  107. let modalType = ref("add");
  108. let rules = ref({
  109. name: [{ required: true, message: "请输入企业文化标题", trigger: "blur" }],
  110. status: [{ required: true, message: "请选择启用状态", trigger: "change" }],
  111. subStatus: [{ required: true, message: "请选择启用状态", trigger: "change" }],
  112. type: [{ required: true, message: "请选择跳转类型", trigger: "change" }],
  113. listType: [{ required: true, message: "请选择列表类型", trigger: "change" }],
  114. isRelated: [{ required: true, message: "请选择是否开启", trigger: "change" }],
  115. url: [{ required: true, message: "请输入第三方链接", trigger: "blur" }],
  116. sort: [{ required: true, message: "请输入排序", trigger: "blur" }],
  117. subName: [{ required: true, message: "请输入子栏目", trigger: "blur" }],
  118. subSort: [{ required: true, message: "请输入排序", trigger: "blur" }],
  119. });
  120. const { proxy } = getCurrentInstance();
  121. const columnType = ref([]);
  122. const columListType = ref([]);
  123. const enableStatus = ref([]);
  124. const selectConfig = [];
  125. const config = computed(() => {
  126. return [
  127. {
  128. attrs: {
  129. label: "栏目名称",
  130. prop: "name",
  131. },
  132. },
  133. {
  134. attrs: {
  135. label: "栏目类型",
  136. prop: "type",
  137. },
  138. render(type) {
  139. return proxy.dictValueLabel(type, columnType.value);
  140. },
  141. },
  142. {
  143. attrs: {
  144. label: "列表类型",
  145. prop: "listType",
  146. slot: 'listType',
  147. },
  148. },
  149. {
  150. attrs: {
  151. label: "状态",
  152. prop: "status",
  153. width: '80'
  154. },
  155. render(type) {
  156. return proxy.dictValueLabel(type, enableStatus.value);
  157. },
  158. },
  159. {
  160. attrs: {
  161. label: "排序",
  162. prop: "sort",
  163. width: '80'
  164. },
  165. },
  166. {
  167. attrs: {
  168. label: "操作",
  169. width: "120",
  170. align: "right",
  171. },
  172. renderHTML(row) {
  173. return [
  174. {
  175. attrs: {
  176. label: "修改",
  177. type: "primary",
  178. text: true,
  179. },
  180. el: "button",
  181. click() {
  182. getDtl(row);
  183. },
  184. },
  185. {
  186. attrs: {
  187. label: "删除",
  188. type: "danger",
  189. text: true,
  190. },
  191. el: "button",
  192. click() {
  193. ElMessageBox.confirm("此操作将永久删除该数据, 是否继续?", "提示", {
  194. confirmButtonText: "确定",
  195. cancelButtonText: "取消",
  196. type: "warning",
  197. }).then(() => {
  198. deleteColumnMenu({
  199. id: row.id,
  200. })
  201. .then((res) => {
  202. ElMessage({
  203. message: "删除成功",
  204. type: "success",
  205. });
  206. getList();
  207. });
  208. });
  209. },
  210. },
  211. ];
  212. },
  213. },
  214. ];
  215. });
  216. let formData = reactive({
  217. data: {
  218. columnMenuSubList:[],
  219. },
  220. });
  221. const formOption = reactive({
  222. inline: true,
  223. labelWidth: 100,
  224. itemWidth: 100,
  225. rules: [],
  226. });
  227. const byform = ref(null);
  228. const formConfig = computed(() => {
  229. return [
  230. {
  231. type: "input",
  232. prop: "name",
  233. label: "栏目名称",
  234. required: true,
  235. },
  236. {
  237. type: "select",
  238. prop: "type",
  239. label: "栏目类型",
  240. clearable: true,
  241. data: columnType.value,
  242. required: true,
  243. },
  244. {
  245. type: "select",
  246. prop: "isRelated",
  247. label: "是否开启相关文章",
  248. data: enableStatus.value,
  249. required: true,
  250. clearable: true,
  251. isShow: formData.data.type == "1"
  252. },
  253. {
  254. type: "slot",
  255. slotName: "subColumn",
  256. prop: "subColumn",
  257. label: "子栏目",
  258. isShow: formData.data.type == "1"
  259. },
  260. {
  261. type: "select",
  262. prop: "listType",
  263. label: "列表类型",
  264. data: columListType.value,
  265. required: true,
  266. clearable: true,
  267. isShow: formData.data.type == "1"
  268. },
  269. {
  270. type: "slot",
  271. slotName: "detailsContent",
  272. prop: "detailsContent",
  273. label: "详情内容",
  274. isShow: formData.data.type == "2"
  275. },
  276. {
  277. type: "input",
  278. prop: "url",
  279. label: "第三方链接",
  280. required: true,
  281. isShow: formData.data.type == "3"
  282. },
  283. {
  284. label: "启用状态",
  285. prop: "status",
  286. type: "select",
  287. clearable: true,
  288. data: enableStatus.value,
  289. required: true,
  290. },
  291. {
  292. type: "input",
  293. prop: "sort",
  294. label: "排序",
  295. itemType: "number",
  296. precision: 0,
  297. max: 999,
  298. required: true,
  299. },
  300. ];
  301. });
  302. const getDictlist = async () => {
  303. const res = await getDictOneByXmhjc(["column_type","enable_status","column_list_type"]);
  304. columnType.value = res["column_type"].map((x) => ({
  305. label: x.dictValue,
  306. value: x.dictKey,
  307. }));
  308. enableStatus.value = res["enable_status"].map((x) => ({
  309. label: x.dictValue,
  310. value: x.dictKey,
  311. }));
  312. columListType.value = res["column_list_type"].map((x) => ({
  313. label: x.dictValue,
  314. value: x.dictKey,
  315. }));
  316. };
  317. const getList = async (req) => {
  318. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  319. loading.value = true;
  320. const res = await findColumnMenuList(sourceList.value.pagination);
  321. sourceList.value.data = res.data.rows;
  322. sourceList.value.pagination.total = res.data.total;
  323. setTimeout(() => {
  324. loading.value = false;
  325. }, 200);
  326. };
  327. const openModal = () => {
  328. dialogVisible.value = true;
  329. modalType.value = "add";
  330. formData.data = {
  331. content:'',
  332. columnMenuSubList:[],
  333. };
  334. };
  335. const selection = ref({
  336. data: [],
  337. });
  338. const select = (_selection, row) => {
  339. selection.value.data = _selection;
  340. };
  341. const submitForm = () => {
  342. byform.value.handleSubmit(() => {
  343. if(formData.data.type == '1'){
  344. if (!(formData.data.columnMenuSubList && formData.data.columnMenuSubList.length > 0)) {
  345. // formData.data.columnMenuSubList = [];
  346. ElMessage({message: "请填写子栏目",type: "error",});
  347. return
  348. }
  349. }
  350. if (formData.data.type == '2' &&
  351. !formData.data.content) {
  352. ElMessage({message: "请填写详情内容",type: "error",});
  353. return
  354. }
  355. submitLoading.value = true;
  356. if (modalType.value === 'add'){
  357. addColumnMenu(formData.data).then(response => {
  358. ElMessage({
  359. message: "添加成功",
  360. type: "success",
  361. });
  362. dialogVisible.value = false;
  363. submitLoading.value = false;
  364. getList();
  365. }).catch(()=>{
  366. submitLoading.value = false;
  367. });
  368. }else {
  369. editColumnMenu(formData.data).then(response => {
  370. ElMessage({
  371. message: "编辑成功",
  372. type: "success",
  373. });
  374. dialogVisible.value = false;
  375. submitLoading.value = false;
  376. getList();
  377. }).catch(()=>{
  378. submitLoading.value = false;
  379. });
  380. }
  381. });
  382. };
  383. const getDtl = async (row) => {
  384. modalType.value = "edit";
  385. const response = await getColumnMenu({ id: row.id })
  386. formData.data = response.data;
  387. dialogVisible.value = true;
  388. };
  389. const updateHandover = (val) => {
  390. formData.data.content = val;
  391. };
  392. const clickAddSubColumn = () => {
  393. if (formData.data.columnMenuSubList && formData.data.columnMenuSubList.length > 0) {
  394. const sort = formData.data.columnMenuSubList[formData.data.columnMenuSubList.length-1].sort
  395. formData.data.columnMenuSubList.push({
  396. name: "",
  397. sort: sort+10,
  398. });
  399. } else {
  400. formData.data.columnMenuSubList = [
  401. {
  402. name: "",
  403. sort: 10,
  404. },
  405. ];
  406. }
  407. };
  408. const getCellColumn = (row) =>{
  409. if (row.type != '1'){
  410. return "——"
  411. }else {
  412. const label = columListType.value.filter( (x) => {
  413. if (x.value == row.listType){
  414. return true
  415. }
  416. return false
  417. })
  418. return label.length > 0 ? label[0].label:'';
  419. }
  420. }
  421. const clickDelete = async (index) => {
  422. console.log(isNullOrUndefined(formData.data.columnMenuSubList[index].id))
  423. if (isNullOrUndefined(formData.data.columnMenuSubList[index].id)){
  424. formData.data.columnMenuSubList.splice(index, 1);
  425. }else {
  426. //验证是否能删除该子栏目
  427. const res = await checkDeleteColumnMenuSub({id : formData.data.columnMenuSubList[index].id });
  428. if (res.data){
  429. formData.data.columnMenuSubList.splice(index, 1);
  430. return
  431. }else {
  432. ElMessage({message: "该栏目存在文章,删除失败!如不想显示请禁用",type: "error",});
  433. return
  434. }
  435. }
  436. };
  437. const getArticleList = async () => {
  438. const res = await findColumnArticleList({
  439. pageNum: 1,
  440. pageSize: 99999,
  441. status: 1,
  442. });
  443. articleList.value = res.data.rows.map((x) => ({
  444. label: x.title,
  445. value: x.id,
  446. }));
  447. };
  448. getDictlist()
  449. getList()
  450. </script>
  451. <style lang="scss" scoped>
  452. .tenant {
  453. padding: 20px;
  454. .delete-btn{
  455. margin-top: 10px;
  456. margin-left: 25px;
  457. }
  458. }
  459. .avatar-uploader .avatar {
  460. width: 110px;
  461. height: 110px;
  462. display: block;
  463. background-color: black;
  464. }
  465. .avatar-uploader .el-upload {
  466. border: 1px dashed var(--el-border-color);
  467. border-radius: 6px;
  468. cursor: pointer;
  469. position: relative;
  470. overflow: hidden;
  471. transition: var(--el-transition-duration-fast);
  472. }
  473. .avatar-uploader .el-upload:hover {
  474. border-color: var(--el-color-primary);
  475. }
  476. .el-icon.avatar-uploader-icon {
  477. font-size: 28px;
  478. color: #8c939d;
  479. width: 110px;
  480. height: 110px;
  481. text-align: center;
  482. border: 1px dashed var(--el-border-color);
  483. }
  484. </style>